https://github.com/mstorsjo updated 
https://github.com/llvm/llvm-project/pull/71148

From 3ed428a75517c49e6eab560fecd746b88ac94df9 Mon Sep 17 00:00:00 2001
From: Dan Klishch <[email protected]>
Date: Fri, 3 Nov 2023 21:18:06 -0400
Subject: [PATCH 1/4] [clang] Implement gcc_struct attribute on Itanium targets

This commit implements gcc_struct attribute with the behavior similar to
one in GCC. Current behavior is as follows:

When ItaniumRecordLayoutBuilder is used, [[gcc_struct]] will locally
cancel the effect of -mms-bitfields on a record. If -mms-bitfields is
not supplied and is not a default behavior on a target, [[gcc_struct]]
will be a no-op. This should provide enough compatibility with GCC.

If C++ ABI is "Microsoft", [[gcc_struct]] will currently always produce
a diagnostic, since support for it is not yet implemented in
MicrosoftRecordLayoutBuilder. Note, however, that all the infrastructure
is ready for the future implementation.

In particular, check for default value of -mms-bitfields is moved from
a driver to ASTContext, since it now non-trivially depends on other
supplied flags. This also, unfortunately, makes it impossible to use
usual argument parsing for -m{no-,}ms-bitfields.

The patch doesn't introduce any backwards-incompatible changes, except
for situations when cc1 is called directly with -mms-bitfields option.

Work towards #24757
---
 clang/docs/ReleaseNotes.rst                   |  6 +++++
 clang/include/clang/AST/ASTContext.h          |  4 +++
 clang/include/clang/Basic/Attr.td             |  9 ++++++-
 clang/include/clang/Basic/AttrDocs.td         | 16 +++++++++++
 .../include/clang/Basic/DiagnosticASTKinds.td |  3 +++
 clang/include/clang/Basic/LangOptions.def     |  4 ++-
 clang/include/clang/Basic/LangOptions.h       | 10 +++++++
 clang/include/clang/Options/Options.td        | 10 ++++---
 clang/lib/AST/Decl.cpp                        |  9 ++++++-
 clang/lib/AST/RecordLayoutBuilder.cpp         | 12 +++++++++
 clang/lib/Driver/ToolChains/Clang.cpp         | 10 ++++---
 clang/lib/Sema/SemaDecl.cpp                   |  4 +--
 clang/lib/Sema/SemaDeclCXX.cpp                | 27 ++++++++++++-------
 clang/test/CodeGen/mingw-long-double.c        |  2 +-
 clang/test/CodeGen/mms-bitfields.c            |  2 +-
 clang/test/Driver/ms-bitfields.c              | 19 ++++++++-----
 clang/test/Layout/itanium-union-bitfield.cpp  |  2 +-
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/mms-bitfields.c               |  5 ++--
 .../SemaCXX/ms_struct-bitfield-padding.cpp    |  2 +-
 clang/test/SemaCXX/ms_struct.cpp              |  2 +-
 clang/test/SemaCXX/ms_wide_bitfield.cpp       |  2 +-
 .../TableGen/ClangDiagnosticsEmitter.cpp      |  1 +
 23 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c80e060f6b7d2..119c22287f672 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -357,6 +357,12 @@ Attribute Changes in Clang
   attribute, but `malloc_span` applies not to functions returning pointers, 
but to functions returning
   span-like structures (i.e. those that contain a pointer field and a size 
integer field or two pointers).
 
+- On targets with Itanium C++ ABI, Clang now supports ``[[gnu:gcc_struct]]``
+  with the behavior similar to one existing in GCC. In particular, whenever
+  ``-mms-bitfields`` command line option is provided (or if 
Microsoft-compatible
+  structure layout is default on the target), ``[[gnu::gcc_struct]]`` requests
+  the compiler to follow Itanium rules for the layout of an annotated 
structure.
+
 Improvements to Clang's diagnostics
 -----------------------------------
 - Diagnostics messages now refer to ``structured binding`` instead of 
``decomposition``,
diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 6e9e737dcae4f..e204b670c08e2 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2791,6 +2791,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   /// runtime, such as those using the Itanium C++ ABI.
   CharUnits getExnObjectAlignment() const;
 
+  /// Return whether unannotated records are treated as if they have
+  /// [[gnu::ms_struct]].
+  bool defaultsToMsStruct() const;
+
   /// Get or compute information about the layout of the specified
   /// record (struct/union/class) \p D, which indicates its size and field
   /// position information.
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 8e5f7ef0bb82d..54746ded155d0 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4387,7 +4387,14 @@ def CFGuard : InheritableAttr, 
TargetSpecificAttr<TargetWindows> {
 def MSStruct : InheritableAttr {
   let Spellings = [GCC<"ms_struct">];
   let Subjects = SubjectList<[Record]>;
-  let Documentation = [Undocumented];
+  let Documentation = [MSStructDocs];
+  let SimpleHandler = 1;
+}
+
+def GCCStruct : InheritableAttr {
+  let Spellings = [GCC<"gcc_struct">];
+  let Subjects = SubjectList<[Record]>;
+  let Documentation = [MSStructDocs]; // Covers this attribute too.
   let SimpleHandler = 1;
 }
 
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index c1b1510f363d4..1517d222f02d8 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9630,3 +9630,19 @@ silence diagnostics with code like:
   __attribute__((nonstring)) char NotAStr[3] = "foo"; // Not diagnosed
   }];
 }
+
+def MSStructDocs : Documentation {
+  let Category = DocCatDecl;
+  let Content = [{
+The ``ms_struct`` and ``gcc_struct`` attributes request the compiler to enter a
+special record layout compatibility mode which mimics the layout of Microsoft 
or
+Itanium C++ ABI respectively. Obviously, if the current C++ ABI matches the
+requested ABI, the attribute does nothing. However, if it does not, annotated
+structure or class is laid out in a special compatibility mode, which slightly
+changes offsets for fields and bit-fields. The intention is to match the layout
+of the requested ABI for structures which only use C features.
+
+Note that the default behavior can be controlled by ``-mms-bitfields`` and
+``-mno-ms-bitfields`` switches and via ``#pragma ms_struct``.
+  }];
+}
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 5c462f9646b3b..e90ee9d376e07 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -1040,6 +1040,9 @@ def warn_npot_ms_struct : Warning<
   "data types with sizes that aren't a power of two">,
   DefaultError, InGroup<IncompatibleMSStruct>;
 
+def err_itanium_layout_unimplemented : Error<
+  "Itanium-compatible layout for the Microsoft C++ ABI is not yet supported">;
+
 // -Wpadded-bitfield
 def warn_padded_struct_bitfield : Warning<
   "padding %select{struct|interface|class}0 %1 with %2 "
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..abb36cf2bc3c0 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -104,7 +104,9 @@ LANGOPT(AssumeNothrowExceptionDtor , 1, 0, NotCompatible, 
"Assume exception obje
 LANGOPT(TraditionalCPP    , 1, 0, NotCompatible, "traditional CPP emulation")
 LANGOPT(RTTI              , 1, 1, NotCompatible, "run-time type information")
 LANGOPT(RTTIData          , 1, 1, NotCompatible, "emit run-time type 
information data")
-LANGOPT(MSBitfields       , 1, 0, NotCompatible, "Microsoft-compatible 
structure layout")
+ENUM_LANGOPT(LayoutCompatibility, LayoutCompatibilityKind, 2,
+             LayoutCompatibilityKind::Default, NotCompatible,
+             "Microsoft-compatible structure layout")
 LANGOPT(MSVolatile        , 1, 0, NotCompatible, "Microsoft-compatible 
volatile loads and stores")
 LANGOPT(Freestanding      , 1, 0, NotCompatible, "freestanding implementation")
 LANGOPT(NoBuiltin         , 1, 0, NotCompatible, "disable builtin functions")
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 3f042f8ddb5a1..a26a481cd4897 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -414,6 +414,16 @@ class LangOptionsBase {
     None,
   };
 
+  enum class LayoutCompatibilityKind {
+    /// Use default layout rules of the target.
+    Default = 0,
+    /// Use Itanium rules for bit-field layout and fundamental types alignment.
+    Itanium = 1,
+    /// Use Microsoft C++ ABI rules for bit-field layout and fundamental types
+    /// alignment.
+    Microsoft = 2,
+  };
+
   // Define simple language options (with no accessors).
 #define LANGOPT(Name, Bits, Default, Compatibility, Description)               
\
   unsigned Name : Bits;
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 786acd6abbd21..0e6b74d1f92fe 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5137,9 +5137,7 @@ def : Joined<["-"], "mmacosx-version-min=">,
   Visibility<[ClangOption, CC1Option, FC1Option, FlangOption]>,
   Group<m_Group>, Alias<mmacos_version_min_EQ>;
 def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>,
-  Visibility<[ClangOption, CC1Option]>,
-  HelpText<"Set the default structure layout to be compatible with the 
Microsoft compiler standard">,
-  MarshallingInfoFlag<LangOpts<"MSBitfields">>;
+  HelpText<"Set the default structure layout to be compatible with the 
Microsoft compiler standard">;
 def moutline : Flag<["-"], "moutline">, Group<f_clang_Group>,
   Visibility<[ClangOption, CC1Option]>,
     HelpText<"Enable function outlining (AArch64 only)">;
@@ -5148,6 +5146,12 @@ def mno_outline : Flag<["-"], "mno-outline">, 
Group<f_clang_Group>,
     HelpText<"Disable function outlining (AArch64 only)">;
 def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
   HelpText<"Do not set the default structure layout to be compatible with the 
Microsoft compiler standard">;
+def fms_layout_compatibility_EQ : Joined<["-"], "fms-layout-compatibility=">,
+  Visibility<[CC1Option]>,
+  HelpText<"Structure layout compatibility with Microsoft C++ ABI">,
+  Values<"default,itanium,microsoft">,
+  NormalizedValues<["Default", "Itanium", "Microsoft"]>, 
NormalizedValuesScope<"LangOptions::LayoutCompatibilityKind">,
+  MarshallingInfoEnum<LangOpts<"LayoutCompatibility">, "Default">;
 def mskip_rax_setup : Flag<["-"], "mskip-rax-setup">, Group<m_Group>,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Skip setting up RAX register when passing variable arguments (x86 
only)">,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index eff2b81d61a50..e23a9aa4929b7 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5237,7 +5237,14 @@ void RecordDecl::completeDefinition() {
 /// This which can be turned on with an attribute, pragma, or the
 /// -mms-bitfields command-line option.
 bool RecordDecl::isMsStruct(const ASTContext &C) const {
-  return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
+  if (hasAttr<MSStructAttr>())
+    return true;
+  if (hasAttr<GCCStructAttr>())
+    return false;
+  auto LayoutCompatibility = C.getLangOpts().getLayoutCompatibility();
+  if (LayoutCompatibility == LangOptions::LayoutCompatibilityKind::Default)
+    return C.defaultsToMsStruct();
+  return LayoutCompatibility == 
LangOptions::LayoutCompatibilityKind::Microsoft;
 }
 
 void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) {
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp 
b/clang/lib/AST/RecordLayoutBuilder.cpp
index ac18d4da22e8c..2a996e318b1c9 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2794,6 +2794,13 @@ void 
MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
     UseExternalLayout = Source->layoutRecordType(
         RD, External.Size, External.Align, External.FieldOffsets,
         External.BaseOffsets, External.VirtualBaseOffsets);
+
+  if (!RD->isMsStruct(Context)) {
+    auto Location = RD->getLocation();
+    if (Location.isValid())
+      Context.getDiagnostics().Report(Location,
+                                      diag::err_itanium_layout_unimplemented);
+  }
 }
 
 void
@@ -3358,6 +3365,11 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
   }
 }
 
+bool ASTContext::defaultsToMsStruct() const {
+  return getTargetInfo().hasMicrosoftRecordLayout() ||
+         getTargetInfo().getTriple().isWindowsGNUEnvironment();
+}
+
 /// getASTRecordLayout - Get or compute information about the layout of the
 /// specified record (struct/union/class), which indicates its size and field
 /// position information.
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..8b9f1a29ff065 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5865,9 +5865,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   if (KernelOrKext && RawTriple.isOSDarwin())
     CmdArgs.push_back("-fforbid-guard-variables");
 
-  if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
-                   Triple.isWindowsGNUEnvironment())) {
-    CmdArgs.push_back("-mms-bitfields");
+  if (Args.hasArg(options::OPT_mms_bitfields) ||
+      Args.hasArg(options::OPT_mno_ms_bitfields)) {
+    if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
+                     false))
+      CmdArgs.push_back("-fms-layout-compatibility=microsoft");
+    else
+      CmdArgs.push_back("-fms-layout-compatibility=itanium");
   }
 
   if (Triple.isOSCygMing()) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index b8ca2a376fde8..830760a1947ca 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18941,9 +18941,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
     // ABI.
     bool CStdConstraintViolation =
         BitfieldIsOverwide && !getLangOpts().CPlusPlus;
-    bool MSBitfieldViolation =
-        Value.ugt(TypeStorageSize) &&
-        (IsMsStruct || Context.getTargetInfo().getCXXABI().isMicrosoft());
+    bool MSBitfieldViolation = Value.ugt(TypeStorageSize) && IsMsStruct;
     if (CStdConstraintViolation || MSBitfieldViolation) {
       unsigned DiagWidth =
           CStdConstraintViolation ? TypeWidth : TypeStorageSize;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index aa36a79142e52..5ee99e07a3866 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7284,20 +7284,27 @@ void Sema::CheckCompletedCXXClass(Scope *S, 
CXXRecordDecl *Record) {
       CheckCompletedMemberFunction(MD);
   }
 
-  // ms_struct is a request to use the same ABI rules as MSVC.  Check
-  // whether this class uses any C++ features that are implemented
-  // completely differently in MSVC, and if so, emit a diagnostic.
-  // That diagnostic defaults to an error, but we allow projects to
-  // map it down to a warning (or ignore it).  It's a fairly common
-  // practice among users of the ms_struct pragma to mass-annotate
-  // headers, sweeping up a bunch of types that the project doesn't
-  // really rely on MSVC-compatible layout for.  We must therefore
-  // support "ms_struct except for C++ stuff" as a secondary ABI.
+  // {ms,gcc}_struct is a request to change ABI rules to either follow
+  // Microsoft or Itanium C++ ABI. However, even if these attributes are
+  // present, we do not layout classes following foreign ABI rules, but
+  // instead enter a special "compatibility mode", which only changes
+  // alignments of fundamental types and layout of bit fields.
+  // Check whether this class uses any C++ features that are implemented
+  // completely differently in the requested ABI, and if so, emit a
+  // diagnostic. That diagnostic defaults to an error, but we allow
+  // projects to map it down to a warning (or ignore it). It's a fairly
+  // common practice among users of the ms_struct pragma to
+  // mass-annotate headers, sweeping up a bunch of types that the
+  // project doesn't really rely on MSVC-compatible layout for. We must
+  // therefore support "ms_struct except for C++ stuff" as a secondary
+  // ABI.
   // Don't emit this diagnostic if the feature was enabled as a
   // language option (as opposed to via a pragma or attribute), as
   // the option -mms-bitfields otherwise essentially makes it impossible
   // to build C++ code, unless this diagnostic is turned off.
-  if (Record->isMsStruct(Context) && !Context.getLangOpts().MSBitfields &&
+  if (Context.getLangOpts().getLayoutCompatibility() ==
+          LangOptions::LayoutCompatibilityKind::Default &&
+      Record->isMsStruct(Context) != Context.defaultsToMsStruct() &&
       (Record->isPolymorphic() || Record->getNumBases())) {
     Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
   }
diff --git a/clang/test/CodeGen/mingw-long-double.c 
b/clang/test/CodeGen/mingw-long-double.c
index b98929701bc62..4050cd159136e 100644
--- a/clang/test/CodeGen/mingw-long-double.c
+++ b/clang/test/CodeGen/mingw-long-double.c
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -o - %s \
 // RUN:    | FileCheck %s --check-prefix=GNU32
-// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -o - %s -mms-bitfields \
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -o - %s 
-fms-layout-compatibility=microsoft \
 // RUN:    | FileCheck %s --check-prefix=GNU32
 // RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -o - %s \
 // RUN:    | FileCheck %s --check-prefix=GNU64
diff --git a/clang/test/CodeGen/mms-bitfields.c 
b/clang/test/CodeGen/mms-bitfields.c
index 2ccce326c7131..8d3b403b7e7be 100644
--- a/clang/test/CodeGen/mms-bitfields.c
+++ b/clang/test/CodeGen/mms-bitfields.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -mms-bitfields -emit-llvm %s -o 
- | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 
-fms-layout-compatibility=microsoft -emit-llvm %s -o - | FileCheck %s
 
 struct s1 {
   int       f32;
diff --git a/clang/test/Driver/ms-bitfields.c b/clang/test/Driver/ms-bitfields.c
index d5a3656b3d110..acd1bdc9c0ac9 100644
--- a/clang/test/Driver/ms-bitfields.c
+++ b/clang/test/Driver/ms-bitfields.c
@@ -1,8 +1,15 @@
-// RUN: %clang -### --target=x86_64-linux-gnu %s 2>&1 | FileCheck %s 
-check-prefix=NO-MSBITFIELDS
-// RUN: %clang -### --target=x86_64-windows-gnu %s 2>&1 | FileCheck %s 
-check-prefix=MSBITFIELDS
-// RUN: %clang -### -mno-ms-bitfields -mms-bitfields %s 2>&1 | FileCheck %s 
-check-prefix=MSBITFIELDS
-// RUN: %clang -### -mms-bitfields -mno-ms-bitfields %s 2>&1 | FileCheck %s 
-check-prefix=NO-MSBITFIELDS
+// RUN: %clang -### --target=x86_64-linux-gnu %s 2>&1 | FileCheck %s 
-check-prefix=DEFAULT-LAYOUT
+// RUN: %clang -### --target=x86_64-windows-gnu %s 2>&1 | FileCheck %s 
-check-prefix=DEFAULT-LAYOUT
+// RUN: %clang -### --target=x86_64-windows-msvc %s 2>&1 | FileCheck %s 
-check-prefix=DEFAULT-LAYOUT
+// RUN: %clang -### -mms-bitfields %s 2>&1 | FileCheck %s 
-check-prefix=MICROSOFT-LAYOUT
+// RUN: %clang -### -mno-ms-bitfields %s 2>&1 | FileCheck %s 
-check-prefix=ITANIUM-LAYOUT
+// RUN: %clang -### -mno-ms-bitfields -mms-bitfields %s 2>&1 | FileCheck %s 
-check-prefix=MICROSOFT-LAYOUT
+// RUN: %clang -### -mms-bitfields -mno-ms-bitfields %s 2>&1 | FileCheck %s 
-check-prefix=ITANIUM-LAYOUT
 
-// MSBITFIELDS: -mms-bitfields
-// NO-MSBITFIELDS-NOT: -mms-bitfields
+// DEFAULT-LAYOUT-NOT: -fms-layout-compatibility=itanium
+// DEFAULT-LAYOUT-NOT: -fms-layout-compatibility=microsoft
+// MICROSOFT-LAYOUT: -fms-layout-compatibility=microsoft
+// MICROSOFT-LAYOUT-NOT: -fms-layout-compatibility=itanium
+// ITANIUM-LAYOUT: -fms-layout-compatibility=itanium
+// ITANIUM-LAYOUT-NOT: -fms-layout-compatibility=microsoft
 
diff --git a/clang/test/Layout/itanium-union-bitfield.cpp 
b/clang/test/Layout/itanium-union-bitfield.cpp
index febfc46dfee54..34f501f4b569a 100644
--- a/clang/test/Layout/itanium-union-bitfield.cpp
+++ b/clang/test/Layout/itanium-union-bitfield.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple 
-fdump-record-layouts %s 2>/dev/null \
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple 
-fms-layout-compatibility=itanium -fdump-record-layouts %s 2>/dev/null \
 // RUN:            | FileCheck %s
 
 // On z/OS, a bit-field has single byte alignment.  Add aligned(4) on z/OS so 
the union has
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test 
b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 747eb17446c87..7eec1ec807e85 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -87,6 +87,7 @@
 // CHECK-NEXT: FlagEnum (SubjectMatchRule_enum)
 // CHECK-NEXT: Flatten (SubjectMatchRule_function)
 // CHECK-NEXT: FunctionReturnThunks (SubjectMatchRule_function)
+// CHECK-NEXT: GCCStruct (SubjectMatchRule_record)
 // CHECK-NEXT: GNUInline (SubjectMatchRule_function)
 // CHECK-NEXT: HIPManaged (SubjectMatchRule_variable)
 // CHECK-NEXT: Hot (SubjectMatchRule_function)
diff --git a/clang/test/Sema/mms-bitfields.c b/clang/test/Sema/mms-bitfields.c
index a976578845229..d7c8b0aa2cb9a 100644
--- a/clang/test/Sema/mms-bitfields.c
+++ b/clang/test/Sema/mms-bitfields.c
@@ -1,6 +1,5 @@
-// RUN: %clang_cc1 -mms-bitfields -fsyntax-only -verify -triple 
x86_64-apple-darwin9 %s
-// RUN: %clang_cc1 -mms-bitfields -fsyntax-only -Wms-bitfield-padding 
-verify=checkms -triple x86_64-apple-darwin9 %s
-
+// RUN: %clang_cc1 -fms-layout-compatibility=microsoft -fsyntax-only -verify 
-triple x86_64-apple-darwin9 %s
+// RUN: %clang_cc1 -fms-layout-compatibility=microsoft -fsyntax-only 
-Wms-bitfield-padding -verify=checkms -triple x86_64-apple-darwin9 %s
 // expected-no-diagnostics
 
 // The -mms-bitfields commandline parameter should behave the same
diff --git a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp 
b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp
index c0f90f798118a..2499d9e392c19 100644
--- a/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp
+++ b/clang/test/SemaCXX/ms_struct-bitfield-padding.cpp
@@ -1,6 +1,6 @@
 
 // RUN: %clang_cc1 -fsyntax-only -Wms-bitfield-padding -verify -triple armv8 
-std=c++23 %s
-// RUN: %clang_cc1 -fsyntax-only -DMS_BITFIELDS -mms-bitfields 
-verify=msbitfields -triple armv8-apple-macos10.15 -std=c++23 %s
+// RUN: %clang_cc1 -fsyntax-only -DMS_BITFIELDS 
-fms-layout-compatibility=microsoft -verify=msbitfields -triple 
armv8-apple-macos10.15 -std=c++23 %s
 
 // msbitfields-no-diagnostics
 
diff --git a/clang/test/SemaCXX/ms_struct.cpp b/clang/test/SemaCXX/ms_struct.cpp
index 409350f2606a9..8ba4631e2d1a3 100644
--- a/clang/test/SemaCXX/ms_struct.cpp
+++ b/clang/test/SemaCXX/ms_struct.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -DTEST_FOR_WARNING 
-Wno-error=incompatible-ms-struct -verify -triple i686-apple-darwin9 -std=c++11 
%s
 // RUN: %clang_cc1 -fsyntax-only -DTEST_FOR_WARNING 
-Wno-error=incompatible-ms-struct -verify -triple armv7-apple-darwin9 
-std=c++11 %s
 // RUN: %clang_cc1 -fsyntax-only -DTEST_FOR_ERROR -verify -triple 
armv7-apple-darwin9 -std=c++11 %s
-// RUN: %clang_cc1 -fsyntax-only -DNO_PRAGMA -mms-bitfields -verify -triple 
armv7-apple-darwin9 -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -DNO_PRAGMA 
-fms-layout-compatibility=microsoft -verify -triple armv7-apple-darwin9 
-std=c++11 %s
 
 #ifndef NO_PRAGMA
 #pragma ms_struct on
diff --git a/clang/test/SemaCXX/ms_wide_bitfield.cpp 
b/clang/test/SemaCXX/ms_wide_bitfield.cpp
index a5b7a433c7c4c..eccfd90f0faf0 100644
--- a/clang/test/SemaCXX/ms_wide_bitfield.cpp
+++ b/clang/test/SemaCXX/ms_wide_bitfield.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fno-rtti -triple i686-pc-win32 -fdump-record-layouts 
-fsyntax-only -mms-bitfields -verify %s 2>&1
+// RUN: %clang_cc1 -fno-rtti -triple i686-pc-win32 -fdump-record-layouts 
-fsyntax-only -fms-layout-compatibility=microsoft -verify %s 2>&1
 
 struct A {
   char a : 9; // expected-error{{width of bit-field 'a' (9 bits) exceeds the 
size of its type (8 bits)}}
diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp 
b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 17078e2bc1505..f4d5023d1cb92 100644
--- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -1357,6 +1357,7 @@ static bool isExemptAtStart(StringRef Text) {
       .Case("Fuchsia", true)
       .Case("GNUstep", true)
       .Case("IBOutletCollection", true)
+      .Case("Itanium", true)
       .Case("Microsoft", true)
       .Case("Neon", true)
       .StartsWith("NSInvocation", true) // NSInvocation, NSInvocation's

From 73e55d509424c66d5f96f0d111fcfeb2e0dec24a Mon Sep 17 00:00:00 2001
From: Dan Klishch <[email protected]>
Date: Mon, 13 Jan 2025 16:05:18 -0500
Subject: [PATCH 2/4] fixup! Add test for gcc_struct

---
 clang/lib/AST/Decl.cpp          |  4 ++--
 clang/test/CodeGen/gcc_struct.c | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/gcc_struct.c

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index e23a9aa4929b7..b962fb13e3e68 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5237,10 +5237,10 @@ void RecordDecl::completeDefinition() {
 /// This which can be turned on with an attribute, pragma, or the
 /// -mms-bitfields command-line option.
 bool RecordDecl::isMsStruct(const ASTContext &C) const {
-  if (hasAttr<MSStructAttr>())
-    return true;
   if (hasAttr<GCCStructAttr>())
     return false;
+  if (hasAttr<MSStructAttr>())
+    return true;
   auto LayoutCompatibility = C.getLangOpts().getLayoutCompatibility();
   if (LayoutCompatibility == LangOptions::LayoutCompatibilityKind::Default)
     return C.defaultsToMsStruct();
diff --git a/clang/test/CodeGen/gcc_struct.c b/clang/test/CodeGen/gcc_struct.c
new file mode 100644
index 0000000000000..ac8b84c016752
--- /dev/null
+++ b/clang/test/CodeGen/gcc_struct.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-linux-gnu %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-linux-gnu 
-fms-layout-compatibility=microsoft %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-windows-gnu %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-windows-gnu 
-fms-layout-compatibility=itanium %s
+
+struct {
+    int a : 24;
+    char b : 8;
+} __attribute__((gcc_struct)) t1;
+static int a1[(sizeof(t1) == 4) - 1];
+
+#pragma ms_struct on
+struct {
+    int a : 24;
+    char b : 8;
+} __attribute__((gcc_struct)) t2;
+static int a2[(sizeof(t2) == 4) - 1];
+#pragma ms_struct off

From 0781c7b50b72720804a2de72f78ee6119a7a8e9b Mon Sep 17 00:00:00 2001
From: Dan Klishch <[email protected]>
Date: Mon, 13 Jan 2025 18:30:12 -0500
Subject: [PATCH 3/4] tests for todo diagnostic & static_assert

---
 clang/test/CodeGen/gcc_struct-msvc-todo-1.c | 6 ++++++
 clang/test/CodeGen/gcc_struct-msvc-todo-2.c | 6 ++++++
 clang/test/CodeGen/gcc_struct.c             | 4 ++--
 3 files changed, 14 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/gcc_struct-msvc-todo-1.c
 create mode 100644 clang/test/CodeGen/gcc_struct-msvc-todo-2.c

diff --git a/clang/test/CodeGen/gcc_struct-msvc-todo-1.c 
b/clang/test/CodeGen/gcc_struct-msvc-todo-1.c
new file mode 100644
index 0000000000000..0bd097f0765cc
--- /dev/null
+++ b/clang/test/CodeGen/gcc_struct-msvc-todo-1.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-windows-msvc -verify %s
+
+// expected-error@+1 {{Itanium-compatible layout for the Microsoft C++ ABI is 
not yet supported}}
+struct {
+    int a;
+} __attribute__((gcc_struct)) t1;
diff --git a/clang/test/CodeGen/gcc_struct-msvc-todo-2.c 
b/clang/test/CodeGen/gcc_struct-msvc-todo-2.c
new file mode 100644
index 0000000000000..048bf43d31c2a
--- /dev/null
+++ b/clang/test/CodeGen/gcc_struct-msvc-todo-2.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-windows-msvc 
-fms-layout-compatibility=itanium -verify %s
+
+// expected-error@+1 {{Itanium-compatible layout for the Microsoft C++ ABI is 
not yet supported}}
+struct {
+    int a;
+} t1;
diff --git a/clang/test/CodeGen/gcc_struct.c b/clang/test/CodeGen/gcc_struct.c
index ac8b84c016752..57ea58de7cfe2 100644
--- a/clang/test/CodeGen/gcc_struct.c
+++ b/clang/test/CodeGen/gcc_struct.c
@@ -7,12 +7,12 @@ struct {
     int a : 24;
     char b : 8;
 } __attribute__((gcc_struct)) t1;
-static int a1[(sizeof(t1) == 4) - 1];
+_Static_assert(sizeof(t1) == 4, "");
 
 #pragma ms_struct on
 struct {
     int a : 24;
     char b : 8;
 } __attribute__((gcc_struct)) t2;
-static int a2[(sizeof(t2) == 4) - 1];
+_Static_assert(sizeof(t2) == 4, "");
 #pragma ms_struct off

From d337956cd1c680efca5e863b42f93ec127208196 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <[email protected]>
Date: Fri, 21 Nov 2025 14:38:22 +0200
Subject: [PATCH 4/4] Try to address
 https://github.com/llvm/llvm-project/pull/71148#discussion_r1929617748

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

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 8b9f1a29ff065..3bbb2b12434b2 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5865,10 +5865,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   if (KernelOrKext && RawTriple.isOSDarwin())
     CmdArgs.push_back("-fforbid-guard-variables");
 
-  if (Args.hasArg(options::OPT_mms_bitfields) ||
-      Args.hasArg(options::OPT_mno_ms_bitfields)) {
-    if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
-                     false))
+  if (Arg *A = Args.getLastArg(options::OPT_mms_bitfields,
+                               options::OPT_mno_ms_bitfields)) {
+    if (A->getOption().matches(options::OPT_mms_bitfields))
       CmdArgs.push_back("-fms-layout-compatibility=microsoft");
     else
       CmdArgs.push_back("-fms-layout-compatibility=itanium");

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

Reply via email to