From c0a1b97a96bfde9c4ede716c9d150548cca291b3 Mon Sep 17 00:00:00 2001 From: Dan DaCosta Date: Wed, 27 May 2026 21:11:01 +0000 Subject: [PATCH] Support anonymous struct embedding via -fms-extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When -fms-extensions is passed, tagged struct/union members without a declarator name are treated as anonymous embedding (Plan 9 C extension). This allows code using the GCC extension where 'struct tag;' inside another struct inlines the tagged struct's fields. The implementation lets the tagged anonymous member fall through to the existing anonymous member handling (the $anon naming + set_anonymous pass), rather than skipping it with 'continue'. Only this one behavior is implemented — no other MSVC or Plan 9 extensions. The internal config field is named allow_anonymous_struct_embedding to be explicit about scope. --- src/ansi-c/c_typecheck_type.cpp | 6 ++++++ src/goto-cc/gcc_mode.cpp | 4 ++++ src/util/config.cpp | 1 + src/util/config.h | 1 + 4 files changed, 12 insertions(+) diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp index 2362e3966f6..82473e35bd0 100644 --- a/src/ansi-c/c_typecheck_type.cpp +++ b/src/ansi-c/c_typecheck_type.cpp @@ -1008,6 +1008,12 @@ void c_typecheck_baset::typecheck_compound_body( { // ok, anonymous union } + else if(config.ansi_c.allow_anonymous_struct_embedding) + { + // With -fms-extensions, tagged struct/union members without + // a declarator name are treated as anonymous embedding + // (Plan 9 C extension) + } else { continue; diff --git a/src/goto-cc/gcc_mode.cpp b/src/goto-cc/gcc_mode.cpp index d48c4234abb..3ac41dd2ab1 100644 --- a/src/goto-cc/gcc_mode.cpp +++ b/src/goto-cc/gcc_mode.cpp @@ -579,6 +579,10 @@ int gcc_modet::doit() config.ansi_c.wchar_t_is_unsigned=true; } + // -fms-extensions: only anonymous struct embedding is implemented. + if(cmdline.isset("fms-extensions")) + config.ansi_c.allow_anonymous_struct_embedding=true; + // -fsingle-precision-constant makes floating-point constants "float" // instead of double if(cmdline.isset("-fsingle-precision-constant")) diff --git a/src/util/config.cpp b/src/util/config.cpp index da70a3b9888..e765d72ad38 100644 --- a/src/util/config.cpp +++ b/src/util/config.cpp @@ -867,6 +867,7 @@ bool configt::set(const cmdlinet &cmdline) cpp.cpp_standard=cppt::default_cpp_standard(); ansi_c.single_precision_constant=false; + ansi_c.allow_anonymous_struct_embedding=false; ansi_c.for_has_scope=true; // C99 or later ansi_c.ts_18661_3_Floatn_types=false; ansi_c.__float128_is_keyword = false; diff --git a/src/util/config.h b/src/util/config.h index e1cdc3eb99c..17c96d36868 100644 --- a/src/util/config.h +++ b/src/util/config.h @@ -168,6 +168,7 @@ class configt bool bf16_type; // __bf16 (Clang >= 15, GCC >= 13) bool fp16_type; // __fp16 (GCC >= 4.5 on ARM, Clang >= 6) bool single_precision_constant; + bool allow_anonymous_struct_embedding; // -fms-extensions (partial) enum class c_standardt { C89,