https://github.com/riyaz86a updated 
https://github.com/llvm/llvm-project/pull/176551

>From 9c01511289217c605e37ca08ee4ccc554d8a9270 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Sat, 17 Jan 2026 04:16:28 -0500
Subject: [PATCH 01/15] [Frontend][Sema] Add CC1-only -fms-anonymous-structs to
 enable Microsoft anonymous struct/union feature

Add a CC1-only option `-fms-anonymous-structs` to enable Microsoft anonymous
struct/union feature without enabling full Microsoft extensions.

Motivation:
  - On AIX, some Microsoft extensions (e.g _ptr32) conflict with system headers.
  - Certain code bases rely on Microsoft anonymous structs/unions behavior.

This new option allows selectively enabling the anonymous struct/union features 
in
the front-end without triggering other Microsoft extensions features.

CC1 option can be passed via clang "-Xclang -fms-anonymous-structs".

Implementation:
  - Introduced CC1-only option `-fms-anonymous-structs`.
  - The option updates LangOpts::MSAnonymousStructs and Updated Sema to use 
this flag.
  - Added frontend, driver, and Sema tests.
---
 clang/include/clang/Basic/LangOptions.def     |  1 +
 clang/include/clang/Options/Options.td        |  6 ++
 clang/lib/Driver/ToolChains/Clang.cpp         |  4 +-
 clang/lib/Sema/SemaDecl.cpp                   |  2 +-
 clang/test/Driver/cl-options.c                |  3 +
 clang/test/Driver/unknown-arg.c               |  2 +
 clang/test/Frontend/ms-anon-structs-args.c    | 15 ++++
 clang/test/Sema/MicrosoftAnonymousStructs.c   | 81 +++++++++++++++++++
 .../Frontend/CompilerInvocationTest.cpp       | 20 +++++
 9 files changed, 132 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Frontend/ms-anon-structs-args.c
 create mode 100644 clang/test/Sema/MicrosoftAnonymousStructs.c

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 36fec24638363..4420cd942cac0 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -47,6 +47,7 @@ LANGOPT(MSVCCompat        , 1, 0, NotCompatible, "Microsoft 
Visual C++ full comp
 LANGOPT(Kernel            , 1, 0, NotCompatible, "Kernel mode")
 LANGOPT(MicrosoftExt      , 1, 0, NotCompatible, "Microsoft C++ extensions")
 LANGOPT(ZOSExt            , 1, 0, NotCompatible, "z/OS extensions")
+LANGOPT(MSAnonymousStructs, 1, 0, NotCompatible, "Microsoft anonymous struct 
and union extension")
 LANGOPT(AsmBlocks         , 1, 0, NotCompatible, "Microsoft inline asm blocks")
 LANGOPT(Borland           , 1, 0, NotCompatible, "Borland extensions")
 LANGOPT(CPlusPlus         , 1, 0, NotCompatible, "C++")
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 188739e72434a..5cdca7132e779 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3327,6 +3327,12 @@ def fms_extensions : Flag<["-"], "fms-extensions">, 
Group<f_Group>,
   Visibility<[ClangOption, CC1Option, CLOption]>,
   HelpText<"Accept some non-standard constructs supported by the Microsoft 
compiler">,
   MarshallingInfoFlag<LangOpts<"MicrosoftExt">>, 
ImpliedByAnyOf<[fms_compatibility.KeyPath]>;
+def fms_anonymous_structs
+    : Flag<["-"], "fms-anonymous-structs">,
+      Visibility<[CC1Option]>,
+      MarshallingInfoFlag<LangOpts<"MSAnonymousStructs">>,
+      ImpliedByAnyOf<[fms_extensions.KeyPath]>,
+      HelpText<"Enable Microsoft anonymous struct/union extension.">;
 defm asm_blocks : BoolFOption<"asm-blocks",
   LangOpts<"AsmBlocks">, Default<fms_extensions.KeyPath>,
   PosFlag<SetTrue, [], [ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 41ee88fd5501a..b0fd41e0a026e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7156,8 +7156,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 
   // -fms-extensions=0 is default.
   if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
-                   IsWindowsMSVC || IsUEFI))
+                   IsWindowsMSVC || IsUEFI)) {
     CmdArgs.push_back("-fms-extensions");
+    CmdArgs.push_back("-fms-anonymous-structs");
+  }
 
   // -fms-compatibility=0 is default.
   bool IsMSVCCompat = Args.hasFlag(
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ae779d6830d9b..4f030c6ec649f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5342,7 +5342,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, 
AccessSpecifier AS,
         DS.getTypeSpecType() == DeclSpec::TST_typename) {
       RecordDecl *Record = Tag ? dyn_cast<RecordDecl>(Tag)
                                : DS.getRepAsType().get()->getAsRecordDecl();
-      if (Record && getLangOpts().MicrosoftExt) {
+      if (Record && getLangOpts().MSAnonymousStructs) {
         Diag(DS.getBeginLoc(), diag::ext_ms_anonymous_record)
             << Record->isUnion() << DS.getSourceRange();
         return BuildMicrosoftCAnonymousStruct(S, DS, Record);
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index 611d0d2927c43..f4ee39d3fc7d9 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -350,6 +350,9 @@
 // WJoined: "-cc1"
 // WJoined: "-Wunused-pragmas"
 
+// RUN: %clang_cl -c -fms-extensions -### -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-MS-ANON-STRUCT %s
+// CHECK-MS-ANON-STRUCT: "-fms-extensions" "-fms-anonymous-structs"
+
 // We recognize -f[no-]strict-aliasing.
 // RUN: %clang_cl -c -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULTSTRICT %s
 // DEFAULTSTRICT: "-relaxed-aliasing"
diff --git a/clang/test/Driver/unknown-arg.c b/clang/test/Driver/unknown-arg.c
index 26032a407f413..b209b1bff0c9f 100644
--- a/clang/test/Driver/unknown-arg.c
+++ b/clang/test/Driver/unknown-arg.c
@@ -25,6 +25,7 @@
 
 // This needs to exit non-0, for configure scripts.
 // RUN: not %clang /GR-
+// RUN: not %clang %s -fms-anonymous-structs -### 2>&1 | FileCheck %s 
--check-prefix=CL-MS-ERROR
 
 // CHECK: error: unknown argument: '-cake-is-lie'
 // CHECK: error: unknown argument: '-%0'
@@ -70,3 +71,4 @@
 //      O-WARN: warning: joined argument treated as '-o ffload-arch=sm_70'; 
did you mean '--offload-arch=sm_70'?
 // O-WARN-NEXT: warning: joined argument treated as '-o ffload-device-only'; 
did you mean '--offload-device-only'?
 // O-WARN-NEXT: warning: joined argument treated as '-o utput'; did you mean 
'--output'?
+// CL-MS-ERROR: error: unknown argument '-fms-anonymous-structs'; did you mean 
'-Xclang -fms-anonymous-structs'?
diff --git a/clang/test/Frontend/ms-anon-structs-args.c 
b/clang/test/Frontend/ms-anon-structs-args.c
new file mode 100644
index 0000000000000..ddd3cea598959
--- /dev/null
+++ b/clang/test/Frontend/ms-anon-structs-args.c
@@ -0,0 +1,15 @@
+// Test that -fms-anonymous-structs is a CC1-only option and properly rejected 
by driver
+
+// RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
+// RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
+// CC1-OK-NOT: error: unknown argument
+
+// Test that multiple occurrences are handled
+// RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-anonymous-structs 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
+// RUN:     FileCheck --check-prefix=MULTI-OK %s --allow-empty
+// MULTI-OK-NOT: error: unknown argument
+
+// Test with other MS-related options
+// RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-extensions 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
+// RUN:     FileCheck --check-prefix=WITH-MS-EXT %s --allow-empty
+// WITH-MS-EXT-NOT: error: unknown argument
diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
new file mode 100644
index 0000000000000..163c2f726cb67
--- /dev/null
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-anonymous-structs
+// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-anonymous-structs
+
+typedef struct notnested {
+  long bad1;
+  long bad2;
+} NOTNESTED;
+
+
+typedef struct nested1 {
+  long a;
+  struct notnested var1;
+  NOTNESTED var2;
+} NESTED1;
+
+struct nested2 {
+  long b;
+  NESTED1;  // expected-warning {{anonymous structs are a Microsoft extension}}
+};
+
+struct nested2 PR20573 = { .a = 3 };
+
+struct nested3 {
+  long d;
+  struct nested4 { // expected-warning {{anonymous structs are a Microsoft 
extension}}
+    long e;
+  };
+  union nested5 { // expected-warning {{anonymous unions are a Microsoft 
extension}}
+    long f;
+  };
+};
+
+typedef union nested6 {
+  long f;
+} NESTED6;
+
+struct test {
+  int c;
+  struct nested2;   // expected-warning {{anonymous structs are a Microsoft 
extension}}
+  NESTED6;   // expected-warning {{anonymous unions are a Microsoft extension}}
+};
+
+void foo(void)
+{
+  struct test var;
+  var.a;
+  var.b;
+  var.c;
+  var.bad1;   // expected-error {{no member named 'bad1' in 'struct test'}}
+  var.bad2;   // expected-error {{no member named 'bad2' in 'struct test'}}
+}
+
+// Enumeration types with a fixed underlying type.
+const int seventeen = 17;
+typedef int Int;
+
+void pointer_to_integral_type_conv(char* ptr) {
+  char ch = (char)ptr;
+  short sh = (short)ptr;
+  ch = (char)ptr;
+  sh = (short)ptr;
+
+  // This is valid ISO C.
+  _Bool b = (_Bool)ptr;
+}
+
+typedef struct {
+  UNKNOWN u; // expected-error {{unknown type name 'UNKNOWN'}}
+} AA;
+
+typedef struct {
+  AA; // expected-warning {{anonymous structs are a Microsoft extension}}
+} BB;
+
+struct anon_fault {
+  struct undefined; // expected-warning {{anonymous structs are a Microsoft 
extension}}
+                    // expected-error@-1 {{field has incomplete type 'struct 
undefined'}}
+                    // expected-note@-2 {{forward declaration of 'struct 
undefined'}}
+};
+
+const int anon_falt_size = sizeof(struct anon_fault);
diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp 
b/clang/unittests/Frontend/CompilerInvocationTest.cpp
index 64d0f4c38f11c..cf758c4ae2c50 100644
--- a/clang/unittests/Frontend/CompilerInvocationTest.cpp
+++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -190,6 +190,26 @@ TEST_F(CommandLineTest, 
BoolOptionDefaultTrueSingleFlagPresent) {
   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
 }
 
+TEST_F(CommandLineTest, MSAnonymousStructsFlagPresent) {
+  const char *Args[] = {"-cc1", "-fms-anonymous-structs"};
+
+  ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
+
+  EXPECT_TRUE(Invocation.getLangOpts().MSAnonymousStructs);
+
+  Invocation.generateCC1CommandLine(GeneratedArgs, *this);
+
+  ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fms-anonymous-structs")));
+}
+
+TEST_F(CommandLineTest, MSAnonymousStructsEnabledByMSExtensions) {
+  const char *Args[] = {"clang", "-fms-extensions"};
+
+  ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
+
+  EXPECT_TRUE(Invocation.getLangOpts().MSAnonymousStructs);
+}
+
 TEST_F(CommandLineTest, CC1FlagPresentWhenDoingRoundTrip) {
   const char *Args[] = {"-cc1", "-round-trip-args"};
 

>From d503955da34dc705678fc1cae8c4a8400c990c6a Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Wed, 21 Jan 2026 12:17:55 -0500
Subject: [PATCH 02/15] [Frontend][Sema] Address review comments

---
 clang/lib/Driver/ToolChains/Clang.cpp         |  1 -
 clang/test/Driver/unknown-arg.c               |  2 --
 clang/test/Sema/MicrosoftAnonymousStructs.c   |  1 +
 .../Frontend/CompilerInvocationTest.cpp       | 20 -------------------
 4 files changed, 1 insertion(+), 23 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index b0fd41e0a026e..de4dc62497433 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7158,7 +7158,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                    IsWindowsMSVC || IsUEFI)) {
     CmdArgs.push_back("-fms-extensions");
-    CmdArgs.push_back("-fms-anonymous-structs");
   }
 
   // -fms-compatibility=0 is default.
diff --git a/clang/test/Driver/unknown-arg.c b/clang/test/Driver/unknown-arg.c
index b209b1bff0c9f..26032a407f413 100644
--- a/clang/test/Driver/unknown-arg.c
+++ b/clang/test/Driver/unknown-arg.c
@@ -25,7 +25,6 @@
 
 // This needs to exit non-0, for configure scripts.
 // RUN: not %clang /GR-
-// RUN: not %clang %s -fms-anonymous-structs -### 2>&1 | FileCheck %s 
--check-prefix=CL-MS-ERROR
 
 // CHECK: error: unknown argument: '-cake-is-lie'
 // CHECK: error: unknown argument: '-%0'
@@ -71,4 +70,3 @@
 //      O-WARN: warning: joined argument treated as '-o ffload-arch=sm_70'; 
did you mean '--offload-arch=sm_70'?
 // O-WARN-NEXT: warning: joined argument treated as '-o ffload-device-only'; 
did you mean '--offload-device-only'?
 // O-WARN-NEXT: warning: joined argument treated as '-o utput'; did you mean 
'--output'?
-// CL-MS-ERROR: error: unknown argument '-fms-anonymous-structs'; did you mean 
'-Xclang -fms-anonymous-structs'?
diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index 163c2f726cb67..3f81962515d4d 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-anonymous-structs
 // RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-anonymous-structs
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-extensions
 
 typedef struct notnested {
   long bad1;
diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp 
b/clang/unittests/Frontend/CompilerInvocationTest.cpp
index cf758c4ae2c50..64d0f4c38f11c 100644
--- a/clang/unittests/Frontend/CompilerInvocationTest.cpp
+++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -190,26 +190,6 @@ TEST_F(CommandLineTest, 
BoolOptionDefaultTrueSingleFlagPresent) {
   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
 }
 
-TEST_F(CommandLineTest, MSAnonymousStructsFlagPresent) {
-  const char *Args[] = {"-cc1", "-fms-anonymous-structs"};
-
-  ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
-
-  EXPECT_TRUE(Invocation.getLangOpts().MSAnonymousStructs);
-
-  Invocation.generateCC1CommandLine(GeneratedArgs, *this);
-
-  ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fms-anonymous-structs")));
-}
-
-TEST_F(CommandLineTest, MSAnonymousStructsEnabledByMSExtensions) {
-  const char *Args[] = {"clang", "-fms-extensions"};
-
-  ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
-
-  EXPECT_TRUE(Invocation.getLangOpts().MSAnonymousStructs);
-}
-
 TEST_F(CommandLineTest, CC1FlagPresentWhenDoingRoundTrip) {
   const char *Args[] = {"-cc1", "-round-trip-args"};
 

>From 4ea10266307d37d7782b336db3c043ec8b5ff175 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Wed, 21 Jan 2026 14:15:13 -0500
Subject: [PATCH 03/15] [Frontend][Sema] Address review comments.

---
 clang/include/clang/Options/Options.td      |  2 +-
 clang/lib/Driver/ToolChains/Clang.cpp       |  3 +-
 clang/test/Driver/cl-options.c              |  3 --
 clang/test/Frontend/ms-anon-structs-args.c  |  7 ++-
 clang/test/Sema/MicrosoftAnonymousStructs.c | 53 ++++++++++++++-------
 5 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 5cdca7132e779..1b959826daade 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3331,7 +3331,7 @@ def fms_anonymous_structs
     : Flag<["-"], "fms-anonymous-structs">,
       Visibility<[CC1Option]>,
       MarshallingInfoFlag<LangOpts<"MSAnonymousStructs">>,
-      ImpliedByAnyOf<[fms_extensions.KeyPath]>,
+      ImpliedByAnyOf<[fms_extensions.KeyPath, fms_compatibility.KeyPath]>,
       HelpText<"Enable Microsoft anonymous struct/union extension.">;
 defm asm_blocks : BoolFOption<"asm-blocks",
   LangOpts<"AsmBlocks">, Default<fms_extensions.KeyPath>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index de4dc62497433..41ee88fd5501a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7156,9 +7156,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 
   // -fms-extensions=0 is default.
   if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
-                   IsWindowsMSVC || IsUEFI)) {
+                   IsWindowsMSVC || IsUEFI))
     CmdArgs.push_back("-fms-extensions");
-  }
 
   // -fms-compatibility=0 is default.
   bool IsMSVCCompat = Args.hasFlag(
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index f4ee39d3fc7d9..611d0d2927c43 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -350,9 +350,6 @@
 // WJoined: "-cc1"
 // WJoined: "-Wunused-pragmas"
 
-// RUN: %clang_cl -c -fms-extensions -### -- %s 2>&1 | FileCheck 
-check-prefix=CHECK-MS-ANON-STRUCT %s
-// CHECK-MS-ANON-STRUCT: "-fms-extensions" "-fms-anonymous-structs"
-
 // We recognize -f[no-]strict-aliasing.
 // RUN: %clang_cl -c -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULTSTRICT %s
 // DEFAULTSTRICT: "-relaxed-aliasing"
diff --git a/clang/test/Frontend/ms-anon-structs-args.c 
b/clang/test/Frontend/ms-anon-structs-args.c
index ddd3cea598959..e2f6edeef20c1 100644
--- a/clang/test/Frontend/ms-anon-structs-args.c
+++ b/clang/test/Frontend/ms-anon-structs-args.c
@@ -1,4 +1,4 @@
-// Test that -fms-anonymous-structs is a CC1-only option and properly rejected 
by driver
+// Test that -fms-anonymous-structs is a CC1-only option and is accepted by 
CC1 without error.
 
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
 // RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
@@ -13,3 +13,8 @@
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-extensions 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
 // RUN:     FileCheck --check-prefix=WITH-MS-EXT %s --allow-empty
 // WITH-MS-EXT-NOT: error: unknown argument
+
+// Test rejection of the unsupported negative form.
+// RUN: not %clang_cc1 -triple powerpc-ibm-aix -fno-ms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
+// RUN:     FileCheck %s
+// CHECK: error: unknown argument: '-fno-ms-anonymous-structs'
diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index 3f81962515d4d..cf47322f59df7 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -1,6 +1,13 @@
-// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-anonymous-structs
-// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-anonymous-structs
-// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value 
-Wno-pointer-to-int-cast -Wmicrosoft -verify -fms-extensions
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-anonymous-structs
+// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value \
+// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-anonymous-structs
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-extensions
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-compatibility
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis
 
 typedef struct notnested {
   long bad1;
@@ -16,17 +23,20 @@ typedef struct nested1 {
 
 struct nested2 {
   long b;
-  NESTED1;  // expected-warning {{anonymous structs are a Microsoft extension}}
+  NESTED1;  // ms-anonymous-warning {{anonymous structs are a Microsoft 
extension}}
+            // ms-anonymous-dis-warning@-1 {{declaration does not declare 
anything}}
 };
 
-struct nested2 PR20573 = { .a = 3 };
+struct nested2 PR20573 = { .a = 3 };  // ms-anonymous-dis-error {{field 
designator 'a' does not refer to any field in type 'struct nested2'}}
 
 struct nested3 {
   long d;
-  struct nested4 { // expected-warning {{anonymous structs are a Microsoft 
extension}}
+  struct nested4 { // ms-anonymous-warning {{anonymous structs are a Microsoft 
extension}}
+                   // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
     long e;
   };
-  union nested5 { // expected-warning {{anonymous unions are a Microsoft 
extension}}
+  union nested5 { // ms-anonymous-warning {{anonymous unions are a Microsoft 
extension}}
+                  // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
     long f;
   };
 };
@@ -37,18 +47,22 @@ typedef union nested6 {
 
 struct test {
   int c;
-  struct nested2;   // expected-warning {{anonymous structs are a Microsoft 
extension}}
-  NESTED6;   // expected-warning {{anonymous unions are a Microsoft extension}}
+  struct nested2;   // ms-anonymous-warning {{anonymous structs are a 
Microsoft extension}}
+                    // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
+  NESTED6;   // ms-anonymous-warning {{anonymous unions are a Microsoft 
extension}}
+            // ms-anonymous-dis-warning@-1 {{declaration does not declare 
anything}}
 };
 
 void foo(void)
 {
   struct test var;
-  var.a;
-  var.b;
+  var.a;      // ms-anonymous-dis-error {{no member named 'a' in 'struct 
test'}}
+  var.b;      // ms-anonymous-dis-error {{no member named 'b' in 'struct 
test'}}
   var.c;
-  var.bad1;   // expected-error {{no member named 'bad1' in 'struct test'}}
-  var.bad2;   // expected-error {{no member named 'bad2' in 'struct test'}}
+  var.bad1;   // ms-anonymous-error {{no member named 'bad1' in 'struct test'}}
+              // ms-anonymous-dis-error@-1 {{no member named 'bad1' in 'struct 
test'}}
+  var.bad2;   // ms-anonymous-error {{no member named 'bad2' in 'struct test'}}
+              // ms-anonymous-dis-error@-1 {{no member named 'bad2' in 'struct 
test'}}
 }
 
 // Enumeration types with a fixed underlying type.
@@ -66,17 +80,20 @@ void pointer_to_integral_type_conv(char* ptr) {
 }
 
 typedef struct {
-  UNKNOWN u; // expected-error {{unknown type name 'UNKNOWN'}}
+  UNKNOWN u; // ms-anonymous-error {{unknown type name 'UNKNOWN'}}
+             // ms-anonymous-dis-error@-1 {{unknown type name 'UNKNOWN'}}
 } AA;
 
 typedef struct {
-  AA; // expected-warning {{anonymous structs are a Microsoft extension}}
+  AA; // ms-anonymous-warning {{anonymous structs are a Microsoft extension}}
+      // ms-anonymous-dis-warning@-1 {{declaration does not declare anything}}
 } BB;
 
 struct anon_fault {
-  struct undefined; // expected-warning {{anonymous structs are a Microsoft 
extension}}
-                    // expected-error@-1 {{field has incomplete type 'struct 
undefined'}}
-                    // expected-note@-2 {{forward declaration of 'struct 
undefined'}}
+  struct undefined; // ms-anonymous-warning {{anonymous structs are a 
Microsoft extension}}
+                    // ms-anonymous-error@-1 {{field has incomplete type 
'struct undefined'}}
+                    // ms-anonymous-note@-2 {{forward declaration of 'struct 
undefined'}}
+                    // ms-anonymous-dis-warning@-3 {{declaration does not 
declare anything}}
 };
 
 const int anon_falt_size = sizeof(struct anon_fault);

>From e3fb3bd01360b5ab3ba4babdc9295256f34b3918 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Thu, 22 Jan 2026 02:43:18 -0500
Subject: [PATCH 04/15] [Frontend][Sema] Address review comments.

---
 clang/test/Sema/MicrosoftAnonymousStructs.c | 76 ++++-----------------
 1 file changed, 15 insertions(+), 61 deletions(-)

diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index cf47322f59df7..d0b32ce53a3ff 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -11,89 +11,43 @@
 
 typedef struct notnested {
   long bad1;
-  long bad2;
 } NOTNESTED;
 
-
 typedef struct nested1 {
   long a;
-  struct notnested var1;
   NOTNESTED var2;
 } NESTED1;
 
 struct nested2 {
   long b;
-  NESTED1;  // ms-anonymous-warning {{anonymous structs are a Microsoft 
extension}}
-            // ms-anonymous-dis-warning@-1 {{declaration does not declare 
anything}}
-};
-
-struct nested2 PR20573 = { .a = 3 };  // ms-anonymous-dis-error {{field 
designator 'a' does not refer to any field in type 'struct nested2'}}
-
-struct nested3 {
-  long d;
-  struct nested4 { // ms-anonymous-warning {{anonymous structs are a Microsoft 
extension}}
+  NESTED1;         // ms-anonymous-warning {{anonymous structs are a Microsoft 
extension}}
                    // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
-    long e;
-  };
-  union nested5 { // ms-anonymous-warning {{anonymous unions are a Microsoft 
extension}}
-                  // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
-    long f;
-  };
 };
 
-typedef union nested6 {
+typedef union nested3 {
   long f;
-} NESTED6;
+} NESTED3;
 
 struct test {
   int c;
   struct nested2;   // ms-anonymous-warning {{anonymous structs are a 
Microsoft extension}}
                     // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
-  NESTED6;   // ms-anonymous-warning {{anonymous unions are a Microsoft 
extension}}
-            // ms-anonymous-dis-warning@-1 {{declaration does not declare 
anything}}
+  NESTED3;          // ms-anonymous-warning {{anonymous unions are a Microsoft 
extension}}
+                    // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
+};
+
+struct nested4 {
+  long d;
+  struct nested5 { // ms-anonymous-warning {{anonymous structs are a Microsoft 
extension}}
+                   // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
+    long e;
+  };
 };
 
 void foo(void)
 {
   struct test var;
-  var.a;      // ms-anonymous-dis-error {{no member named 'a' in 'struct 
test'}}
-  var.b;      // ms-anonymous-dis-error {{no member named 'b' in 'struct 
test'}}
   var.c;
-  var.bad1;   // ms-anonymous-error {{no member named 'bad1' in 'struct test'}}
-              // ms-anonymous-dis-error@-1 {{no member named 'bad1' in 'struct 
test'}}
-  var.bad2;   // ms-anonymous-error {{no member named 'bad2' in 'struct test'}}
-              // ms-anonymous-dis-error@-1 {{no member named 'bad2' in 'struct 
test'}}
-}
-
-// Enumeration types with a fixed underlying type.
-const int seventeen = 17;
-typedef int Int;
-
-void pointer_to_integral_type_conv(char* ptr) {
-  char ch = (char)ptr;
-  short sh = (short)ptr;
-  ch = (char)ptr;
-  sh = (short)ptr;
-
-  // This is valid ISO C.
-  _Bool b = (_Bool)ptr;
+  var.b;          // ms-anonymous-dis-error {{no member named 'b' in 'struct 
test'}}
+  var.f;          // ms-anonymous-dis-error {{no member named 'f' in 'struct 
test'}}
 }
-
-typedef struct {
-  UNKNOWN u; // ms-anonymous-error {{unknown type name 'UNKNOWN'}}
-             // ms-anonymous-dis-error@-1 {{unknown type name 'UNKNOWN'}}
-} AA;
-
-typedef struct {
-  AA; // ms-anonymous-warning {{anonymous structs are a Microsoft extension}}
-      // ms-anonymous-dis-warning@-1 {{declaration does not declare anything}}
-} BB;
-
-struct anon_fault {
-  struct undefined; // ms-anonymous-warning {{anonymous structs are a 
Microsoft extension}}
-                    // ms-anonymous-error@-1 {{field has incomplete type 
'struct undefined'}}
-                    // ms-anonymous-note@-2 {{forward declaration of 'struct 
undefined'}}
-                    // ms-anonymous-dis-warning@-3 {{declaration does not 
declare anything}}
-};
-
-const int anon_falt_size = sizeof(struct anon_fault);

>From 368d435724608fee9655faa660c803111b2054f9 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Fri, 23 Jan 2026 01:03:05 -0500
Subject: [PATCH 05/15] [Frontend][Sema] Address review comments.

---
 clang/test/Sema/MicrosoftAnonymousStructs.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index d0b32ce53a3ff..f9b6fa20c5bd1 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -9,13 +9,12 @@
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis
 
-typedef struct notnested {
-  long bad1;
-} NOTNESTED;
+struct union_mem {
+  long g;
+};
 
 typedef struct nested1 {
   long a;
-  NOTNESTED var2;
 } NESTED1;
 
 struct nested2 {
@@ -26,6 +25,8 @@ struct nested2 {
 
 typedef union nested3 {
   long f;
+  struct union_mem; // ms-anonymous-warning {{anonymous structs are a 
Microsoft extension}}
+                    // ms-anonymous-dis-warning@-1 {{declaration does not 
declare anything}}
 } NESTED3;
 
 struct test {
@@ -48,6 +49,8 @@ void foo(void)
 {
   struct test var;
   var.c;
+  var.a;          // ms-anonymous-dis-error {{no member named 'a' in 'struct 
test'}}
   var.b;          // ms-anonymous-dis-error {{no member named 'b' in 'struct 
test'}}
   var.f;          // ms-anonymous-dis-error {{no member named 'f' in 'struct 
test'}}
+  var.g;          // ms-anonymous-dis-error {{no member named 'g' in 'struct 
test'}}
 }

>From 6bda77381fa52674a13dee70e6640818119112d8 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Fri, 23 Jan 2026 11:12:55 -0500
Subject: [PATCH 06/15] [Clang] Add release notes for -fms-anonymous-structs
 CC1 option

---
 clang/docs/ReleaseNotes.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5fd607d98faa3..b8b2b83b58981 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -109,6 +109,7 @@ Non-comprehensive list of changes in this release
 
 New Compiler Flags
 ------------------
+- New CC1 option ``-fms-anonymous-structs`` added to enable only Microsoft's 
anonymous struct/union extension without enabling other ``-fms-extensions`` 
features [GH177607].
 
 Deprecated Compiler Flags
 -------------------------

>From c3c5543e6905d598332561357a4eafd90776c004 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Sat, 24 Jan 2026 11:43:37 -0500
Subject: [PATCH 07/15] [Frontend][Sema] Address review comments.

---
 clang/include/clang/Options/Options.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 1b959826daade..5cdca7132e779 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3331,7 +3331,7 @@ def fms_anonymous_structs
     : Flag<["-"], "fms-anonymous-structs">,
       Visibility<[CC1Option]>,
       MarshallingInfoFlag<LangOpts<"MSAnonymousStructs">>,
-      ImpliedByAnyOf<[fms_extensions.KeyPath, fms_compatibility.KeyPath]>,
+      ImpliedByAnyOf<[fms_extensions.KeyPath]>,
       HelpText<"Enable Microsoft anonymous struct/union extension.">;
 defm asm_blocks : BoolFOption<"asm-blocks",
   LangOpts<"AsmBlocks">, Default<fms_extensions.KeyPath>,

>From 4a3ba57b8edf9858a0e86ae5020f560672b4b685 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Sat, 24 Jan 2026 11:55:38 -0500
Subject: [PATCH 08/15] Frontend][Sema] Address review comments

---
 clang/test/Frontend/ms-anon-structs-args.c  |  6 ++----
 clang/test/Sema/MicrosoftAnonymousStructs.c | 10 +++++-----
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/clang/test/Frontend/ms-anon-structs-args.c 
b/clang/test/Frontend/ms-anon-structs-args.c
index e2f6edeef20c1..48c0d31b6c159 100644
--- a/clang/test/Frontend/ms-anon-structs-args.c
+++ b/clang/test/Frontend/ms-anon-structs-args.c
@@ -6,13 +6,11 @@
 
 // Test that multiple occurrences are handled
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-anonymous-structs 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
-// RUN:     FileCheck --check-prefix=MULTI-OK %s --allow-empty
-// MULTI-OK-NOT: error: unknown argument
+// RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
 
 // Test with other MS-related options
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-extensions 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
-// RUN:     FileCheck --check-prefix=WITH-MS-EXT %s --allow-empty
-// WITH-MS-EXT-NOT: error: unknown argument
+// RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
 
 // Test rejection of the unsupported negative form.
 // RUN: not %clang_cc1 -triple powerpc-ibm-aix -fno-ms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index f9b6fa20c5bd1..31fba67d4a324 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -1,13 +1,13 @@
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
-// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-anonymous-structs
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-anonymous-structs
 // RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value \
-// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-anonymous-structs
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-anonymous-structs
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
-// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-extensions
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-extensions
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
-// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-compatibility
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-compatibility
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
-// RUN: -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis
 
 struct union_mem {
   long g;

>From 0ca900d07e2ad7ad787aef569dd8cbbaf165d1f5 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Sun, 25 Jan 2026 11:01:03 -0500
Subject: [PATCH 09/15] [Frontend][Sema] Add -fno-ms-anonymous-structs option
 to disable anonymous structs

This patch adds support for the -fno-ms-anonymous-structs flag to explicitly 
disable
Microsoft's anonymous struct/union extension, even when -fms-anonymous-structs 
or
-fms-extensions or -fms-compatibility is enabled.

Update tests to verify both positive and negative flags work correctly and
Added tests to ensure explicit disable overrides implicit enablement.
---
 clang/include/clang/Options/Options.td      | 16 ++++++++++------
 clang/test/Frontend/ms-anon-structs-args.c  | 14 ++++++++++----
 clang/test/Sema/MicrosoftAnonymousStructs.c | 19 +++++++++++++++++++
 3 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 5cdca7132e779..dd7a0139484be 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3327,12 +3327,16 @@ def fms_extensions : Flag<["-"], "fms-extensions">, 
Group<f_Group>,
   Visibility<[ClangOption, CC1Option, CLOption]>,
   HelpText<"Accept some non-standard constructs supported by the Microsoft 
compiler">,
   MarshallingInfoFlag<LangOpts<"MicrosoftExt">>, 
ImpliedByAnyOf<[fms_compatibility.KeyPath]>;
-def fms_anonymous_structs
-    : Flag<["-"], "fms-anonymous-structs">,
-      Visibility<[CC1Option]>,
-      MarshallingInfoFlag<LangOpts<"MSAnonymousStructs">>,
-      ImpliedByAnyOf<[fms_extensions.KeyPath]>,
-      HelpText<"Enable Microsoft anonymous struct/union extension.">;
+defm fms_anonymous_structs
+    : BoolFOption<"ms-anonymous-structs",
+      LangOpts<"MSAnonymousStructs">,
+      DefaultFalse,
+      PosFlag<SetTrue, [], [CC1Option],
+              "Enable Microsoft anonymous struct/union extension.",
+              [fms_extensions.KeyPath]>,
+      NegFlag<SetFalse, [], [CC1Option],
+              "Disable Microsoft anonymous struct/union extension.">,
+      BothFlags<[], [CC1Option], " Microsoft anonymous struct/union 
extension">>;
 defm asm_blocks : BoolFOption<"asm-blocks",
   LangOpts<"AsmBlocks">, Default<fms_extensions.KeyPath>,
   PosFlag<SetTrue, [], [ClangOption, CC1Option]>,
diff --git a/clang/test/Frontend/ms-anon-structs-args.c 
b/clang/test/Frontend/ms-anon-structs-args.c
index 48c0d31b6c159..38546353655a0 100644
--- a/clang/test/Frontend/ms-anon-structs-args.c
+++ b/clang/test/Frontend/ms-anon-structs-args.c
@@ -12,7 +12,13 @@
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-extensions 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
 // RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
 
-// Test rejection of the unsupported negative form.
-// RUN: not %clang_cc1 -triple powerpc-ibm-aix -fno-ms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
-// RUN:     FileCheck %s
-// CHECK: error: unknown argument: '-fno-ms-anonymous-structs'
+// Test that -fno-ms-anonymous-structs is accepted by CC1 without error.
+// RUN: %clang_cc1 -triple powerpc-ibm-aix -fno-ms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
+// RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
+
+// Test toggling between enable and disable (last one wins)
+// RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-anonymous-structs 
-fno-ms-anonymous-structs %s -fsyntax-only 2>&1 | \
+// RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
+
+// RUN: %clang_cc1 -triple powerpc-ibm-aix -fno-ms-anonymous-structs 
-fms-anonymous-structs %s -fsyntax-only 2>&1 | \
+// RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index 31fba67d4a324..d5296878dbee6 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -8,6 +8,25 @@
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-compatibility
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis
+// Test that explicit -fno-ms-anonymous-structs does not enable the feature
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
+// RUN:   -fno-ms-anonymous-structs
+// Test that explicit -fno-ms-anonymous-structs overrides 
-fms-anonymous-structs
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
+// RUN:   -fms-anonymous-structs -fno-ms-anonymous-structs
+// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value \
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
+// RUN:   -fms-anonymous-structs -fno-ms-anonymous-structs
+// Test that explicit -fno-ms-anonymous-structs overrides -fms-extensions
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
+// RUN:   -fms-extensions -fno-ms-anonymous-structs
+// Test that explicit -fno-ms-anonymous-structs overrides -fms-compatibility
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
+// RUN:   -fms-compatibility -fno-ms-anonymous-structs
 
 struct union_mem {
   long g;

>From a8ff6b3e20c3ea7c74607183cc613b55da4d2580 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Sun, 25 Jan 2026 23:26:39 -0500
Subject: [PATCH 10/15] [Frontend][Sema] Address review comments.

---
 clang/test/Frontend/ms-anon-structs-args.c  |  2 +-
 clang/test/Sema/MicrosoftAnonymousStructs.c | 17 +++++++++++------
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/clang/test/Frontend/ms-anon-structs-args.c 
b/clang/test/Frontend/ms-anon-structs-args.c
index 38546353655a0..571c50d9f3126 100644
--- a/clang/test/Frontend/ms-anon-structs-args.c
+++ b/clang/test/Frontend/ms-anon-structs-args.c
@@ -16,7 +16,7 @@
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fno-ms-anonymous-structs %s 
-fsyntax-only 2>&1 | \
 // RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
 
-// Test toggling between enable and disable (last one wins)
+// Test both orderings of using both the negative and positive forms.
 // RUN: %clang_cc1 -triple powerpc-ibm-aix -fms-anonymous-structs 
-fno-ms-anonymous-structs %s -fsyntax-only 2>&1 | \
 // RUN:     FileCheck --check-prefix=CC1-OK %s --allow-empty
 
diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index d5296878dbee6..f76eedb183636 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -8,22 +8,27 @@
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous 
-fms-compatibility
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis
-// Test that explicit -fno-ms-anonymous-structs does not enable the feature
+// Test that explicit -fno-ms-anonymous-structs does not enable the feature.
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
 // RUN:   -fno-ms-anonymous-structs
-// Test that explicit -fno-ms-anonymous-structs overrides 
-fms-anonymous-structs
+// Test that explicit -fno-ms-anonymous-structs does not enable the feature.
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
-// RUN:   -fms-anonymous-structs -fno-ms-anonymous-structs
-// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -fsyntax-only -Wno-unused-value \
+// RUN:   -fno-ms-anonymous-structs
+// Test that explicit -fno-ms-anonymous-structs overrides -earlier 
fms-anonymous-structs.
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
 // RUN:   -fms-anonymous-structs -fno-ms-anonymous-structs
-// Test that explicit -fno-ms-anonymous-structs overrides -fms-extensions
+// Test that explicit -fms-anonymous-structs overrides earlier 
-fno-ms-anonymous-structs.
+// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
+// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous \
+// RUN:   -fno-ms-anonymous-structs -fms-anonymous-structs
+// Test that explicit -fno-ms-anonymous-structs overrides earlier 
-fms-extensions.
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
 // RUN:   -fms-extensions -fno-ms-anonymous-structs
-// Test that explicit -fno-ms-anonymous-structs overrides -fms-compatibility
+// Test that explicit -fno-ms-anonymous-structs overrides earlier 
-fms-compatibility.
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
 // RUN:   -fms-compatibility -fno-ms-anonymous-structs

>From 6ed5207feffa0e5465dbb7712075e7f8d759af69 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Mon, 26 Jan 2026 05:43:40 -0500
Subject: [PATCH 11/15] [Frontend][Sema] Address review comments.

---
 clang/test/Sema/MicrosoftAnonymousStructs.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/clang/test/Sema/MicrosoftAnonymousStructs.c 
b/clang/test/Sema/MicrosoftAnonymousStructs.c
index f76eedb183636..f656411daea3d 100644
--- a/clang/test/Sema/MicrosoftAnonymousStructs.c
+++ b/clang/test/Sema/MicrosoftAnonymousStructs.c
@@ -12,11 +12,7 @@
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
 // RUN:   -fno-ms-anonymous-structs
-// Test that explicit -fno-ms-anonymous-structs does not enable the feature.
-// RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
-// RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
-// RUN:   -fno-ms-anonymous-structs
-// Test that explicit -fno-ms-anonymous-structs overrides -earlier 
fms-anonymous-structs.
+// Test that explicit -fno-ms-anonymous-structs overrides earlier 
-fms-anonymous-structs.
 // RUN: %clang_cc1 -triple i686-windows %s -fsyntax-only -Wno-unused-value \
 // RUN:   -Wno-pointer-to-int-cast -Wmicrosoft -verify=ms-anonymous-dis \
 // RUN:   -fms-anonymous-structs -fno-ms-anonymous-structs

>From 4c27d8d775ab5a5543881e5208e40d1a37a7cae5 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Tue, 27 Jan 2026 12:05:13 -0500
Subject: [PATCH 12/15] [Driver][Frontend] Add -f[no-]ms-anonymous-structs flag
 to control Microsoft anonymous struct/union extension

Add a Clang driver option -fms-anonymous-structs and -fno-ms-anonymous-structs
to enable or disable Microsoft anonymous struct/union support independently of 
-fms-extensions.

Motivation:
  - On some platforms (e.g. AIX), enabling -fms-extensions can conflict
    with system headers (such as usage of __ptr32).
  - Some codebases rely specifically on Microsoft anonymous struct/union
    behavior without requiring other Microsoft extensions.

This change allows users to selectively enable the anonymous struct/union
extension at the driver level without enabling full Microsoft compatibility
mode.

Behavior:
  - -fms-anonymous-structs enables the feature explicitly.
  - The feature is still enabled implicitly when -fms-extensions or
    -fms-compatibility is in effect.
  - Explicit enable/disable options follow last-option-wins semantics.
  - When multiple flags affect this feature, the last flag on the command 
determines
    the behavior.
    For example:
    -fms-extensions -fno-ms-anonymous-structs, disable the feature.
    -fno-ms-anonymous-structs -fms-anonymous-structs, enables the feature (last 
option wins).

Implementation:
  - Added driver-level options -fms-anonymous-structs and
    -fno-ms-anonymous-structs.
  - Forwarded the option from the driver to CC1.
  - Added driver and frontend tests to verify option interactions.
---
 clang/docs/ReleaseNotes.rst              |  2 +-
 clang/include/clang/Options/Options.td   | 18 +++++------
 clang/lib/Driver/ToolChains/Clang.cpp    | 35 ++++++++++++++++++++++
 clang/test/Driver/ms-anonymous-structs.c | 38 ++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/Driver/ms-anonymous-structs.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b8b2b83b58981..06fbb49ce6b32 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -109,7 +109,7 @@ Non-comprehensive list of changes in this release
 
 New Compiler Flags
 ------------------
-- New CC1 option ``-fms-anonymous-structs`` added to enable only Microsoft's 
anonymous struct/union extension without enabling other ``-fms-extensions`` 
features [GH177607].
+- New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added 
to enable or disable Microsoft's anonymous struct/union extension without 
enabling other ``-fms-extensions`` features [GH177607].
 
 Deprecated Compiler Flags
 -------------------------
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index dd7a0139484be..11df591f35e7f 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3327,16 +3327,14 @@ def fms_extensions : Flag<["-"], "fms-extensions">, 
Group<f_Group>,
   Visibility<[ClangOption, CC1Option, CLOption]>,
   HelpText<"Accept some non-standard constructs supported by the Microsoft 
compiler">,
   MarshallingInfoFlag<LangOpts<"MicrosoftExt">>, 
ImpliedByAnyOf<[fms_compatibility.KeyPath]>;
-defm fms_anonymous_structs
-    : BoolFOption<"ms-anonymous-structs",
-      LangOpts<"MSAnonymousStructs">,
-      DefaultFalse,
-      PosFlag<SetTrue, [], [CC1Option],
-              "Enable Microsoft anonymous struct/union extension.",
-              [fms_extensions.KeyPath]>,
-      NegFlag<SetFalse, [], [CC1Option],
-              "Disable Microsoft anonymous struct/union extension.">,
-      BothFlags<[], [CC1Option], " Microsoft anonymous struct/union 
extension">>;
+defm ms_anonymous_structs
+    : BoolFOption<
+          "ms-anonymous-structs", LangOpts<"MSAnonymousStructs">, DefaultFalse,
+          PosFlag<SetTrue, [], [ClangOption, CC1Option],
+                  "Enable Microsoft anonymous struct/union extension.",
+                  [fms_extensions.KeyPath]>,
+          NegFlag<SetFalse, [], [ClangOption, CC1Option],
+                  "Disable Microsoft anonymous struct/union extension.">>;
 defm asm_blocks : BoolFOption<"asm-blocks",
   LangOpts<"AsmBlocks">, Default<fms_extensions.KeyPath>,
   PosFlag<SetTrue, [], [ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 41ee88fd5501a..4d513c7500af0 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7171,6 +7171,41 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
       CmdArgs.push_back("-fms-define-stdc");
   }
 
+  // -fms-anonymous-struct=0 default.
+  bool EnableMSAnon = false;
+  bool SeenRelevantOption = false;
+  for (const Arg *A : Args) {
+    switch (A->getOption().getID()) {
+    case options::OPT_fms_anonymous_structs:
+      A->claim();
+      EnableMSAnon = true;
+      SeenRelevantOption = true;
+      break;
+    case options::OPT_fno_ms_anonymous_structs:
+      A->claim();
+      EnableMSAnon = false;
+      SeenRelevantOption = true;
+      break;
+    case options::OPT_fms_extensions:
+    case options::OPT_fms_compatibility:
+      EnableMSAnon = true;
+      SeenRelevantOption = true;
+      break;
+    case options::OPT_fno_ms_extensions:
+    case options::OPT_fno_ms_compatibility:
+      EnableMSAnon = false;
+      SeenRelevantOption = true;
+      break;
+    default:
+      break;
+    }
+  }
+
+  if (SeenRelevantOption) {
+    CmdArgs.push_back(EnableMSAnon ? "-fms-anonymous-structs"
+                                   : "-fno-ms-anonymous-structs");
+  }
+
   if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() &&
       Args.hasArg(options::OPT_fms_runtime_lib_EQ))
     ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs);
diff --git a/clang/test/Driver/ms-anonymous-structs.c 
b/clang/test/Driver/ms-anonymous-structs.c
new file mode 100644
index 0000000000000..79723590ee6d4
--- /dev/null
+++ b/clang/test/Driver/ms-anonymous-structs.c
@@ -0,0 +1,38 @@
+// RUN: %clang -### -target powerpc-ibm-aix -fms-anonymous-structs %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=MS-STRUCT-ENABLE
+// MS-STRUCT-ENABLE: "-fms-anonymous-structs"
+
+// RUN: %clang -### -target powerpc-ibm-aix -fno-ms-anonymous-structs %s 2>&1 
| \
+// RUN:   FileCheck %s --check-prefix=MS-STRUCT-DISABLE
+// MS-STRUCT-DISABLE: "-fno-ms-anonymous-structs"
+
+// RUN: %clang -### -target powerpc-ibm-aix -fms-extensions %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=IMPLICIT-ENABLE
+// IMPLICIT-ENABLE: "-fms-anonymous-structs"
+
+// RUN: %clang -### -target powerpc-ibm-aix -fms-compatibility %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=IMPLICIT-ENABLE
+
+// RUN: %clang -### -target powerpc-ibm-aix -fno-ms-anonymous-structs 
-fms-anonymous-structs %s 2>&1 |\
+// RUN:   FileCheck %s --check-prefix=LAST-ENABLE
+// LAST-ENABLE: "-fms-anonymous-structs"
+// LAST-ENABLE-NOT: "-fno-ms-anonymous-structs"
+
+// RUN: %clang -### -target powerpc-ibm-aix -fno-ms-anonymous-structs 
-fms-extensions %s 2>&1 |\
+// RUN:   FileCheck %s --check-prefix=LAST-ENABLE
+
+// RUN: %clang -### -target powerpc-ibm-aix -fms-anonymous-structs 
-fno-ms-anonymous-structs %s 2>&1 |\
+// RUN:   FileCheck %s --check-prefix=LAST-DISABLE
+// LAST-DISABLE: "-fno-ms-anonymous-structs"
+// LAST-DISABLE-NOT: "-fms-anonymous-structs"
+
+// RUN: %clang -### -target powerpc-ibm-aix -fms-extensions 
-fno-ms-anonymous-structs %s 2>&1 |\
+// RUN:   FileCheck %s --check-prefix=LAST-DISABLE
+
+// RUN: %clang -### -target powerpc-ibm-aix -fms-compatibility 
-fno-ms-anonymous-structs %s 2>&1 |\
+// RUN:   FileCheck %s --check-prefix=LAST-DISABLE
+
+// RUN: %clang -### -target powerpc-ibm-aix %s 2>&1 | FileCheck %s 
--check-prefix=NO-MS-STRUCT
+// NO-MS-STRUCT-NOT: "-fms-anonymous-structs"
+// NO-MS-STRUCT-NOT: "-fno-ms-anonymous-structs"
+

>From 534698753bec7a6285673914f64805c3bd1d0d79 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Wed, 28 Jan 2026 12:03:09 -0500
Subject: [PATCH 13/15] Address review comments and update
 LanguageExtensions.rst.

---
 clang/docs/LanguageExtensions.rst     | 43 +++++++++++++++++++++++++++
 clang/docs/ReleaseNotes.rst           |  4 ++-
 clang/lib/Driver/ToolChains/Clang.cpp |  2 +-
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index a734e5083f360..ec0e124ea7e69 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2424,6 +2424,49 @@ Clang provides support for Microsoft extensions to 
support enumerations with no
 
   typedef enum empty { } A;
 
+Microsoft Anonymous Structs and Unions
+--------------------------------------
+
+Clang provides support for a Microsoft extension that allows named struct or 
union types to be declared
+as anonymous member inside another struct or union, making their fields 
directly accessible from the
+enclosing type.
+
+
+For example, consider the following code:
+
+.. code-block:: c
+
+    struct Inner {
+        int x;
+        int y;
+    };
+
+    struct Outer {
+        struct Inner;  /* Microsoft extension: named anonymous struct member */
+    };
+
+    void f(struct Outer *o) {
+        o->x = 1;      /* accesses Inner::x directly */
+        o->y = 1;      /* accesses Inner::y directly */
+    }
+
+Without this extension, such declarations generate a warning that the 
declaration does not
+declare anything and their members cannot be accessed directly.
+
+This extension can be controlled independently of other Microsoft extensions:
+
+* ``-fms-anonymous-structs``
+    Enable named anonymous struct/union support
+
+* ``-fno-ms-anonymous-structs``
+    Disable anonymous struct/union support
+
+This extension is also **implicitly enabled** when either of the following 
options is used:
+
+* ``-fms-extensions``
+* ``-fms-compatibility``
+
+When multiple controlling options are specified, the last option on command 
line take precedence.
 
 Interoperability with C++11 lambdas
 -----------------------------------
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 06fbb49ce6b32..bfc504e6cbcb7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -109,7 +109,9 @@ Non-comprehensive list of changes in this release
 
 New Compiler Flags
 ------------------
-- New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added 
to enable or disable Microsoft's anonymous struct/union extension without 
enabling other ``-fms-extensions`` features [GH177607].
+- New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
+  to enable or disable Microsoft's anonymous struct/union extension without
+  enabling other ``-fms-extensions`` features (#GH177607).
 
 Deprecated Compiler Flags
 -------------------------
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 4d513c7500af0..3b1ac8a6e6dd4 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7171,7 +7171,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
       CmdArgs.push_back("-fms-define-stdc");
   }
 
-  // -fms-anonymous-struct=0 default.
+  // -fms-anonymous-structs is disabled by default.
   bool EnableMSAnon = false;
   bool SeenRelevantOption = false;
   for (const Arg *A : Args) {

>From 8b52cd75f55a47771a86e64a95557270e64852f9 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Thu, 29 Jan 2026 08:54:18 -0500
Subject: [PATCH 14/15] [Driver][Frontend] Address review comments.

---
 clang/docs/LanguageExtensions.rst     | 17 +++---
 clang/lib/Driver/ToolChains/Clang.cpp | 79 ++++++++++++++++-----------
 2 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index ec0e124ea7e69..0d59ec9e98c9d 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2427,10 +2427,9 @@ Clang provides support for Microsoft extensions to 
support enumerations with no
 Microsoft Anonymous Structs and Unions
 --------------------------------------
 
-Clang provides support for a Microsoft extension that allows named struct or 
union types to be declared
-as anonymous member inside another struct or union, making their fields 
directly accessible from the
-enclosing type.
-
+Clang provides support for a Microsoft extension that allows use of named 
struct or union types to
+declare anonymous members inside another struct or union, making their fields 
directly accessible
+from the enclosing type.
 
 For example, consider the following code:
 
@@ -2446,12 +2445,13 @@ For example, consider the following code:
     };
 
     void f(struct Outer *o) {
-        o->x = 1;      /* accesses Inner::x directly */
-        o->y = 1;      /* accesses Inner::y directly */
+        o->x = 1;      /* accesses x member of anonymous member of type Inner 
directly */
+        o->y = 1;      /* accesses x member of anonymous member of type Inner 
directly */
     }
 
 Without this extension, such declarations generate a warning that the 
declaration does not
-declare anything and their members cannot be accessed directly.
+declare anything, the associated member names are not available for access, 
and the layout
+of types containing such declarations are affected accordingly.
 
 This extension can be controlled independently of other Microsoft extensions:
 
@@ -2466,7 +2466,8 @@ This extension is also **implicitly enabled** when either 
of the following optio
 * ``-fms-extensions``
 * ``-fms-compatibility``
 
-When multiple controlling options are specified, the last option on command 
line take precedence.
+When multiple controlling options are specified, the last option on the 
command line takes
+precedence.
 
 Interoperability with C++11 lambdas
 -----------------------------------
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 3b1ac8a6e6dd4..19237fcd6085a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7172,39 +7172,56 @@ void Clang::ConstructJob(Compilation &C, const 
JobAction &JA,
   }
 
   // -fms-anonymous-structs is disabled by default.
-  bool EnableMSAnon = false;
-  bool SeenRelevantOption = false;
-  for (const Arg *A : Args) {
-    switch (A->getOption().getID()) {
-    case options::OPT_fms_anonymous_structs:
-      A->claim();
-      EnableMSAnon = true;
-      SeenRelevantOption = true;
-      break;
-    case options::OPT_fno_ms_anonymous_structs:
-      A->claim();
-      EnableMSAnon = false;
-      SeenRelevantOption = true;
-      break;
-    case options::OPT_fms_extensions:
-    case options::OPT_fms_compatibility:
-      EnableMSAnon = true;
-      SeenRelevantOption = true;
-      break;
-    case options::OPT_fno_ms_extensions:
-    case options::OPT_fno_ms_compatibility:
-      EnableMSAnon = false;
-      SeenRelevantOption = true;
-      break;
-    default:
-      break;
+  // Determine whether to enable Microsoft named anonymous struct/union 
support.
+  // This implements "last flag wins" semantics for -fms-anonymous-structs,
+  // where the feature can be:
+  // - Explicitly enabled via -fms-anonymous-structs.
+  // - Explicitly disabled via fno-ms-anonymous-structs
+  // - Implicitly enabled via -fms-extensions or -fms-compatibility
+  // - Implicitly disabled via -fno-ms-extensions or -fno-ms-compatibility
+  //
+  // When multiple relevent options are present, the last option on the 
command line
+  // takes precedence. This allows users to selectively override implicit 
enablement.
+  // Examples:
+  //   -fms-extensions -fno-ms-anonymous-structs -> disabled (explicit 
override)
+  //   -fno-ms-anonymous-structs -fms-extensions -> enabled (last flag wins)
+  auto ShouldEnableMSAnonymousStructs =
+      [&](const ArgList &Args) -> std::optional<bool> {
+    std::optional<bool> EnableAnonymousStructs;
+
+    // Iterate through all arguments in order to implement "last flag wins".
+    for (const Arg *A : Args) {
+      switch (A->getOption().getID()) {
+      case options::OPT_fms_anonymous_structs:
+        A->claim();
+        EnableAnonymousStructs = true;
+        break;
+      case options::OPT_fno_ms_anonymous_structs:
+        A->claim();
+        EnableAnonymousStructs = false;
+        break;
+      // -fms-extensions and -fms-compatibility implicitly enables feature.
+      case options::OPT_fms_extensions:
+      case options::OPT_fms_compatibility:
+        EnableAnonymousStructs = true;
+        break;
+      // -fno-ms-extensions and -fno-ms-compatibility implicitly disable
+      // this feature.
+      case options::OPT_fno_ms_extensions:
+      case options::OPT_fno_ms_compatibility:
+        EnableAnonymousStructs = false;
+        break;
+      default:
+        break;
+      }
     }
-  }
+    return EnableAnonymousStructs;
+  };
 
-  if (SeenRelevantOption) {
-    CmdArgs.push_back(EnableMSAnon ? "-fms-anonymous-structs"
-                                   : "-fno-ms-anonymous-structs");
-  }
+  // Only pass a flag to CC1 if a relevant option was seen
+  if (auto MSAnon = ShouldEnableMSAnonymousStructs(Args))
+    CmdArgs.push_back(*MSAnon ? "-fms-anonymous-structs"
+                              : "-fno-ms-anonymous-structs");
 
   if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() &&
       Args.hasArg(options::OPT_fms_runtime_lib_EQ))

>From 3c8f696394b67193ced8e3ba897d0ccf651d68a2 Mon Sep 17 00:00:00 2001
From: Riyaz Ahmad <[email protected]>
Date: Thu, 29 Jan 2026 09:21:32 -0500
Subject: [PATCH 15/15] Address clang-format issue.

---
 clang/lib/Driver/ToolChains/Clang.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 19237fcd6085a..a6cd72048522d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7180,9 +7180,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   // - Implicitly enabled via -fms-extensions or -fms-compatibility
   // - Implicitly disabled via -fno-ms-extensions or -fno-ms-compatibility
   //
-  // When multiple relevent options are present, the last option on the 
command line
-  // takes precedence. This allows users to selectively override implicit 
enablement.
-  // Examples:
+  // When multiple relevent options are present, the last option on the command
+  // line takes precedence. This allows users to selectively override implicit
+  // enablement. Examples:
   //   -fms-extensions -fno-ms-anonymous-structs -> disabled (explicit 
override)
   //   -fno-ms-anonymous-structs -fms-extensions -> enabled (last flag wins)
   auto ShouldEnableMSAnonymousStructs =

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to