[clang] [clang] Stub out gcc_struct attribute (PR #71148)

Dan Klishch via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 28 18:45:01 PST 2023


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

>From 1033441efd9e790bdb027824ffa1986cd09c06f2 Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Fri, 3 Nov 2023 21:18:06 -0400
Subject: [PATCH 1/7] [clang] Stub out gcc_struct attribute

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

When C++ ABI is not "Microsoft" (i. e. 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 TargetInfo, since it now non-trivially depends on other
supplied flags. Also this, 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.
---
 clang/include/clang/Basic/Attr.td             |  7 +++++
 clang/include/clang/Basic/LangOptions.def     |  1 -
 clang/include/clang/Basic/LangOptions.h       |  2 ++
 clang/include/clang/Basic/TargetInfo.h        |  4 +++
 clang/include/clang/Driver/Options.td         |  4 +--
 clang/lib/AST/Decl.cpp                        |  7 ++++-
 clang/lib/CodeGen/CGRecordLayoutBuilder.cpp   |  5 +---
 clang/lib/Driver/ToolChains/Clang.cpp         | 10 ++++---
 clang/lib/Frontend/CompilerInvocation.cpp     | 12 +++++++++
 clang/lib/Sema/SemaDecl.cpp                   |  4 +--
 clang/lib/Sema/SemaDeclCXX.cpp                | 27 ++++++++++++-------
 clang/test/Driver/ms-bitfields.c              | 11 +++++---
 clang/test/Layout/itanium-union-bitfield.cpp  |  2 +-
 ...a-attribute-supported-attributes-list.test |  1 +
 14 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 1800f584c7e1088..0d7e44d783bcc39 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3671,6 +3671,13 @@ def MSStruct : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def GCCStruct : InheritableAttr {
+  let Spellings = [GCC<"gcc_struct">];
+  let Subjects = SubjectList<[Record]>;
+  let Documentation = [Undocumented];
+  let SimpleHandler = 1;
+}
+
 def DLLExport : InheritableAttr, TargetSpecificAttr<TargetHasDLLImportExport> {
   let Spellings = [Declspec<"dllexport">, GCC<"dllexport">];
   let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>;
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index c3d5399905a3fda..5b0869a792d8785 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -149,7 +149,6 @@ LANGOPT(AssumeNothrowExceptionDtor , 1, 0, "Assume exception object's destructor
 LANGOPT(TraditionalCPP    , 1, 0, "traditional CPP emulation")
 LANGOPT(RTTI              , 1, 1, "run-time type information")
 LANGOPT(RTTIData          , 1, 1, "emit run-time type information data")
-LANGOPT(MSBitfields       , 1, 0, "Microsoft-compatible structure layout")
 LANGOPT(MSVolatile        , 1, 0, "Microsoft-compatible volatile loads and stores")
 LANGOPT(Freestanding, 1, 0, "freestanding implementation")
 LANGOPT(NoBuiltin         , 1, 0, "disable builtin functions")
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 2d167dd2bdf1287..162929b90730b0e 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -507,6 +507,8 @@ class LangOptions : public LangOptionsBase {
   // implementation on real-world examples.
   std::string OpenACCMacroOverride;
 
+  std::optional<bool> MSBitfields;
+
   LangOptions();
 
   /// Set language defaults for the given input language and
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 41f3c2e403cbef6..fc9555cf29cec7b 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1738,6 +1738,10 @@ class TargetInfo : public TransferrableTargetInfo,
   /// Whether to support HIP image/texture API's.
   virtual bool hasHIPImageSupport() const { return true; }
 
+  virtual bool defaultsToMsStruct() const {
+    return getCXXABI().isMicrosoft() || getTriple().isWindowsGNUEnvironment();
+  }
+
 protected:
   /// Copy type and layout related info.
   void copyAuxTarget(const TargetInfo *Aux);
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 9689f12fd01417b..ffad856e1fd8781 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4426,8 +4426,7 @@ def : Joined<["-"], "mmacosx-version-min=">,
   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)">;
@@ -4435,6 +4434,7 @@ def mno_outline : Flag<["-"], "mno-outline">, Group<f_clang_Group>,
   Visibility<[ClangOption, CC1Option]>,
     HelpText<"Disable function outlining (AArch64 only)">;
 def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">;
 def mskip_rax_setup : Flag<["-"], "mskip-rax-setup">, Group<m_Group>,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index c5c2edf1bfe3aba..25201995925322e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5031,7 +5031,12 @@ 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;
+  return C.getLangOpts().MSBitfields.value_or(
+      C.getTargetInfo().defaultsToMsStruct());
 }
 
 void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) {
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index cbfa79e10bfefcc..296151c32c91c12 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -104,10 +104,7 @@ struct CGRecordLowering {
   /// fields of the same formal type.  We want to emit a layout with
   /// these discrete storage units instead of combining them into a
   /// continuous run.
-  bool isDiscreteBitFieldABI() {
-    return Context.getTargetInfo().getCXXABI().isMicrosoft() ||
-           D->isMsStruct(Context);
-  }
+  bool isDiscreteBitFieldABI() { return D->isMsStruct(Context); }
 
   /// Helper function to check if we are targeting AAPCS.
   bool isAAPCS() const {
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2d73f42772a29dc..4851a4915ece91e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5666,9 +5666,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("-mms-bitfields");
+    else
+      CmdArgs.push_back("-mno-ms-bitfields");
   }
 
   if (Triple.isWindowsGNUEnvironment()) {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 5a8e4cf9843de2b..b4f48863653bcd7 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3635,6 +3635,13 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
     GenerateArg(Consumer, OPT_fcxx_abi_EQ,
                 TargetCXXABI::getSpelling(*Opts.CXXABI));
 
+  if (Opts.MSBitfields.has_value()) {
+    if (Opts.MSBitfields.value())
+      GenerateArg(Consumer, OPT_mms_bitfields);
+    else
+      GenerateArg(Consumer, OPT_mno_ms_bitfields);
+  }
+
   if (Opts.RelativeCXXABIVTables)
     GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);
   else
@@ -4177,6 +4184,11 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
                    options::OPT_fno_experimental_relative_cxx_abi_vtables,
                    TargetCXXABI::usesRelativeVTables(T));
 
+  if (Args.hasArg(options::OPT_mms_bitfields) ||
+      Args.hasArg(options::OPT_mno_ms_bitfields))
+    Opts.MSBitfields = Args.hasFlag(options::OPT_mms_bitfields,
+                                    options::OPT_mno_ms_bitfields, false);
+
   // RTTI is on by default.
   bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);
   Opts.OmitVTableRTTI =
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 77ff4e1df8e9c90..74e3514a3149293 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18246,9 +18246,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 7385eac48d8c895..8b2f4f13e4c09cc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7255,20 +7255,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
+  // alignements 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().MSBitfields.has_value() &&
+      Record->isMsStruct(Context) !=
+          Context.getTargetInfo().defaultsToMsStruct() &&
       (Record->isPolymorphic() || Record->getNumBases())) {
     Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
   }
diff --git a/clang/test/Driver/ms-bitfields.c b/clang/test/Driver/ms-bitfields.c
index 031ed41e2aad678..4cd3f1380e41acf 100644
--- a/clang/test/Driver/ms-bitfields.c
+++ b/clang/test/Driver/ms-bitfields.c
@@ -1,8 +1,13 @@
-// 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 -### -target x86_64-linux-gnu %s 2>&1 | FileCheck %s -check-prefix=DEFAULT-MSBITFIELDS
+// RUN: %clang -### -target x86_64-windows-gnu %s 2>&1 | FileCheck %s -check-prefix=DEFAULT-MSBITFIELDS
+// RUN: %clang -### -target x86_64-windows-msvc %s 2>&1 | FileCheck %s -check-prefix=DEFAULT-MSBITFIELDS
+// RUN: %clang -### -mms-bitfields %s 2>&1 | FileCheck %s -check-prefix=MSBITFIELDS
+// RUN: %clang -### -mno-ms-bitfields %s 2>&1 | FileCheck %s -check-prefix=NO-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
 
 // MSBITFIELDS: -mms-bitfields
-// NO-MSBITFIELDS-NOT: -mms-bitfields
+// NO-MSBITFIELDS: -mno-ms-bitfields
+// DEFAULT-MSBITFIELDS-NOT: -mms-bitfields
+// DEFAULT-MSBITFIELDS-NOT: -mno-ms-bitfields
 
diff --git a/clang/test/Layout/itanium-union-bitfield.cpp b/clang/test/Layout/itanium-union-bitfield.cpp
index febfc46dfee54c1..3e22fe9a3faabd3 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 -mno-ms-bitfields -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 dd91f4f88ad685b..b7073cd1adde118 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -77,6 +77,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)

>From 3bb5235c74aa149df8b95e58190d1fc3b939b6e0 Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Mon, 13 Nov 2023 19:08:03 -0500
Subject: [PATCH 2/7] documentation and diagnostic

---
 clang/docs/ReleaseNotes.rst                   |  5 ++++
 clang/include/clang/Basic/Attr.td             |  4 ++--
 clang/include/clang/Basic/AttrDocs.td         | 23 +++++++++++++++++++
 .../include/clang/Basic/DiagnosticASTKinds.td |  3 +++
 clang/lib/AST/RecordLayoutBuilder.cpp         |  7 ++++++
 5 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e4beeee0a2cb5e0..dcda86566a1c3ce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -340,6 +340,11 @@ Attribute Changes in Clang
   All parameters of a function are considered to be lifetime bound if the function
   returns a type annotated with ``[[clang::coro_lifetimebound]]`` and ``[[clang::coro_return_type]]``.
 
+- On targets with C++ ABI other than Microsoft, Clang now supports
+  ``[[gnu:gcc_struct]]`` with the behavior similar to one existing in GCC. In
+  particular, it locally cancels the effect of ``-mms-bitfields`` switch (either
+  if it is provided explicitly or if the behavior is default on a target).
+
 Improvements to Clang's diagnostics
 -----------------------------------
 - Clang constexpr evaluator now prints template arguments when displaying
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 0d7e44d783bcc39..26028e72a033ad3 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3667,14 +3667,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 = [Undocumented];
+  let Documentation = [GCCStructDocs];
   let SimpleHandler = 1;
 }
 
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b7f366c29b77b48..4c829aaf3f3bff3 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7659,3 +7659,26 @@ Both coroutines and coroutine wrappers are part of this analysis.
 .. _`CRT`: https://clang.llvm.org/docs/AttributeReference.html#coro-return-type
 }];
 }
+
+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``.
+  }];
+}
+
+def GCCStructDocs : Documentation {
+  let Category = DocCatDecl;
+  let Content = [{
+See ms_struct_.
+  }];
+}
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index c81d17ed641084a..9d61a3285c3d5f1 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -998,6 +998,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<
+  "sorry, Itanium-compatible layout is unimplemented for the current C++ ABI">;
+
 // -Wpadded-bitfield
 def warn_padded_struct_bitfield : Warning<
   "padding %select{struct|interface|class}0 %1 with %2 "
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index a51c8b938f411c0..8ea46f680b19e70 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2795,6 +2795,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

>From 87deadc18823054b4e8cf38ff9feabb8d4d7b38c Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Tue, 14 Nov 2023 11:45:00 -0500
Subject: [PATCH 3/7] fixup

---
 clang/docs/ReleaseNotes.rst                     | 9 +++++----
 clang/include/clang/Basic/DiagnosticASTKinds.td | 2 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index dcda86566a1c3ce..a61150a57855cc6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -340,10 +340,11 @@ Attribute Changes in Clang
   All parameters of a function are considered to be lifetime bound if the function
   returns a type annotated with ``[[clang::coro_lifetimebound]]`` and ``[[clang::coro_return_type]]``.
 
-- On targets with C++ ABI other than Microsoft, Clang now supports
-  ``[[gnu:gcc_struct]]`` with the behavior similar to one existing in GCC. In
-  particular, it locally cancels the effect of ``-mms-bitfields`` switch (either
-  if it is provided explicitly or if the behavior is default on a target).
+- 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
 -----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 9d61a3285c3d5f1..0346b7fed8163ef 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -999,7 +999,7 @@ def warn_npot_ms_struct : Warning<
   DefaultError, InGroup<IncompatibleMSStruct>;
 
 def err_itanium_layout_unimplemented : Error<
-  "sorry, Itanium-compatible layout is unimplemented for the current C++ ABI">;
+  "Itanium-compatible layout for the Microsoft C++ ABI is not yet supported">;
 
 // -Wpadded-bitfield
 def warn_padded_struct_bitfield : Warning<

>From b7d7efab31ccb0d3595cd1ea221be77647da156d Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Tue, 14 Nov 2023 15:24:47 -0500
Subject: [PATCH 4/7] fixup

---
 clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8b2f4f13e4c09cc..c0e76594364134e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7259,7 +7259,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
   // 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
-  // alignements of fundamental types and layout of bit fields.
+  // 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

>From 354896c5a2e03442f12f9f6c311a1b6a047b095e Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Wed, 15 Nov 2023 13:52:47 -0500
Subject: [PATCH 5/7] fixup

---
 clang/include/clang/Basic/Attr.td     | 2 +-
 clang/include/clang/Basic/AttrDocs.td | 7 -------
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 26028e72a033ad3..571889c08c84d07 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3674,7 +3674,7 @@ def MSStruct : InheritableAttr {
 def GCCStruct : InheritableAttr {
   let Spellings = [GCC<"gcc_struct">];
   let Subjects = SubjectList<[Record]>;
-  let Documentation = [GCCStructDocs];
+  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 4c829aaf3f3bff3..c5322ef223bc605 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7675,10 +7675,3 @@ Note that the default behavior can be controlled by ``-mms-bitfields`` and
 ``-mno-ms-bitfields`` switches and via ``#pragma ms_struct``.
   }];
 }
-
-def GCCStructDocs : Documentation {
-  let Category = DocCatDecl;
-  let Content = [{
-See ms_struct_.
-  }];
-}

>From fc6a51224e47d0db633c63e3b9720a9e981705f6 Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Tue, 28 Nov 2023 21:37:28 -0500
Subject: [PATCH 6/7] change cc1 option to
 -fms-layout-compatibility={default,microsoft,itanium}

---
 clang/include/clang/Basic/LangOptions.def    |  2 ++
 clang/include/clang/Basic/LangOptions.h      | 11 +++++++--
 clang/include/clang/Driver/Options.td        | 10 ++++++--
 clang/lib/AST/Decl.cpp                       |  6 +++--
 clang/lib/Driver/ToolChains/Clang.cpp        |  4 ++--
 clang/lib/Frontend/CompilerInvocation.cpp    | 12 ----------
 clang/lib/Sema/SemaDeclCXX.cpp               |  2 +-
 clang/test/CodeGen/mingw-long-double.c       |  2 +-
 clang/test/CodeGen/mms-bitfields.c           |  2 +-
 clang/test/Driver/ms-bitfields.c             | 24 +++++++++++---------
 clang/test/Layout/itanium-union-bitfield.cpp |  2 +-
 clang/test/Sema/mms-bitfields.c              |  2 +-
 clang/test/SemaCXX/ms_struct.cpp             |  2 +-
 clang/test/SemaCXX/ms_wide_bitfield.cpp      |  2 +-
 14 files changed, 45 insertions(+), 38 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 5b0869a792d8785..24ef16b8950c51a 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -149,6 +149,8 @@ LANGOPT(AssumeNothrowExceptionDtor , 1, 0, "Assume exception object's destructor
 LANGOPT(TraditionalCPP    , 1, 0, "traditional CPP emulation")
 LANGOPT(RTTI              , 1, 1, "run-time type information")
 LANGOPT(RTTIData          , 1, 1, "emit run-time type information data")
+ENUM_LANGOPT(LayoutCompatibility, LayoutCompatibilityKind, 2,
+             LayoutCompatibilityKind::Default, "Microsoft-compatible structure layout")
 LANGOPT(MSVolatile        , 1, 0, "Microsoft-compatible volatile loads and stores")
 LANGOPT(Freestanding, 1, 0, "freestanding implementation")
 LANGOPT(NoBuiltin         , 1, 0, "disable builtin functions")
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 162929b90730b0e..bc7abc6de2a6b77 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -391,6 +391,15 @@ class LangOptions : public LangOptionsBase {
     IncompleteOnly = 3,
   };
 
+  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,
+  };
+
 public:
   /// The used language standard.
   LangStandard::Kind LangStd;
@@ -507,8 +516,6 @@ class LangOptions : public LangOptionsBase {
   // implementation on real-world examples.
   std::string OpenACCMacroOverride;
 
-  std::optional<bool> MSBitfields;
-
   LangOptions();
 
   /// Set language defaults for the given input language and
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index ffad856e1fd8781..3b29790d246e67d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4425,7 +4425,7 @@ def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
 def : Joined<["-"], "mmacosx-version-min=">,
   Group<m_Group>, Alias<mmacos_version_min_EQ>;
 def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>,
-  Visibility<[ClangOption, CC1Option]>,
+  Visibility<[ClangOption]>,
   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]>,
@@ -4434,8 +4434,14 @@ def mno_outline : Flag<["-"], "mno-outline">, Group<f_clang_Group>,
   Visibility<[ClangOption, CC1Option]>,
     HelpText<"Disable function outlining (AArch64 only)">;
 def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
-  Visibility<[ClangOption, CC1Option]>,
+  Visibility<[ClangOption]>,
   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 25201995925322e..0fff0a4f53cc8c9 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5035,8 +5035,10 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const {
     return true;
   if (hasAttr<GCCStructAttr>())
     return false;
-  return C.getLangOpts().MSBitfields.value_or(
-      C.getTargetInfo().defaultsToMsStruct());
+  auto LayoutCompatibility = C.getLangOpts().getLayoutCompatibility();
+  if (LayoutCompatibility == LangOptions::LayoutCompatibilityKind::Default)
+    return C.getTargetInfo().defaultsToMsStruct();
+  return LayoutCompatibility == LangOptions::LayoutCompatibilityKind::Microsoft;
 }
 
 void RecordDecl::reorderDecls(const SmallVectorImpl<Decl *> &Decls) {
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 4851a4915ece91e..c0e37e2a13a1d63 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5670,9 +5670,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       Args.hasArg(options::OPT_mno_ms_bitfields)) {
     if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
                      false))
-      CmdArgs.push_back("-mms-bitfields");
+      CmdArgs.push_back("-fms-layout-compatibility=microsoft");
     else
-      CmdArgs.push_back("-mno-ms-bitfields");
+      CmdArgs.push_back("-fms-layout-compatibility=itanium");
   }
 
   if (Triple.isWindowsGNUEnvironment()) {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b4f48863653bcd7..5a8e4cf9843de2b 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3635,13 +3635,6 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
     GenerateArg(Consumer, OPT_fcxx_abi_EQ,
                 TargetCXXABI::getSpelling(*Opts.CXXABI));
 
-  if (Opts.MSBitfields.has_value()) {
-    if (Opts.MSBitfields.value())
-      GenerateArg(Consumer, OPT_mms_bitfields);
-    else
-      GenerateArg(Consumer, OPT_mno_ms_bitfields);
-  }
-
   if (Opts.RelativeCXXABIVTables)
     GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);
   else
@@ -4184,11 +4177,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
                    options::OPT_fno_experimental_relative_cxx_abi_vtables,
                    TargetCXXABI::usesRelativeVTables(T));
 
-  if (Args.hasArg(options::OPT_mms_bitfields) ||
-      Args.hasArg(options::OPT_mno_ms_bitfields))
-    Opts.MSBitfields = Args.hasFlag(options::OPT_mms_bitfields,
-                                    options::OPT_mno_ms_bitfields, false);
-
   // RTTI is on by default.
   bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);
   Opts.OmitVTableRTTI =
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c0e76594364134e..d7349809a43bf35 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7273,7 +7273,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
   // 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 (!Context.getLangOpts().MSBitfields.has_value() &&
+  if (Context.getLangOpts().getLayoutCompatibility() == LangOptions::LayoutCompatibilityKind::Default &&
       Record->isMsStruct(Context) !=
           Context.getTargetInfo().defaultsToMsStruct() &&
       (Record->isPolymorphic() || Record->getNumBases())) {
diff --git a/clang/test/CodeGen/mingw-long-double.c b/clang/test/CodeGen/mingw-long-double.c
index a50f8f0b3b63341..2bd212a69566664 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 49c5c1c3e7d40d8..43d189a793f7e52 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 4cd3f1380e41acf..07d1c38c3ef3bed 100644
--- a/clang/test/Driver/ms-bitfields.c
+++ b/clang/test/Driver/ms-bitfields.c
@@ -1,13 +1,15 @@
-// RUN: %clang -### -target x86_64-linux-gnu %s 2>&1 | FileCheck %s -check-prefix=DEFAULT-MSBITFIELDS
-// RUN: %clang -### -target x86_64-windows-gnu %s 2>&1 | FileCheck %s -check-prefix=DEFAULT-MSBITFIELDS
-// RUN: %clang -### -target x86_64-windows-msvc %s 2>&1 | FileCheck %s -check-prefix=DEFAULT-MSBITFIELDS
-// RUN: %clang -### -mms-bitfields %s 2>&1 | FileCheck %s -check-prefix=MSBITFIELDS
-// RUN: %clang -### -mno-ms-bitfields %s 2>&1 | FileCheck %s -check-prefix=NO-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: -mno-ms-bitfields
-// DEFAULT-MSBITFIELDS-NOT: -mms-bitfields
-// DEFAULT-MSBITFIELDS-NOT: -mno-ms-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 3e22fe9a3faabd3..34f501f4b569a7b 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 -mno-ms-bitfields -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/Sema/mms-bitfields.c b/clang/test/Sema/mms-bitfields.c
index cee5b0669d252fd..d0a67a4a3d793e1 100644
--- a/clang/test/Sema/mms-bitfields.c
+++ b/clang/test/Sema/mms-bitfields.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -mms-bitfields -fsyntax-only -verify -triple x86_64-apple-darwin9 %s
+// RUN: %clang_cc1 -fms-layout-compatibility=microsoft -fsyntax-only -verify -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.cpp b/clang/test/SemaCXX/ms_struct.cpp
index 995e424d1f87640..29d29e4fd6fdc82 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 0dcc787928b0a31..76af5bdaf90930e 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 -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only -mms-bitfields -verify %s 2>&1
+// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -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)}}

>From f2ca9e72ae662b6ea756dec4d1e9070d0f53a2e5 Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch at gmail.com>
Date: Tue, 28 Nov 2023 21:44:39 -0500
Subject: [PATCH 7/7] fixup style

---
 clang/include/clang/Basic/LangOptions.h | 3 ++-
 clang/lib/Sema/SemaDeclCXX.cpp          | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index bc7abc6de2a6b77..9da86d00e4a961e 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -396,7 +396,8 @@ class LangOptions : public LangOptionsBase {
     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.
+    /// Use Microsoft C++ ABI rules for bit-field layout and fundamental types
+    /// alignment.
     Microsoft = 2,
   };
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index d7349809a43bf35..f553964b1c0a4f5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7273,7 +7273,8 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
   // 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 (Context.getLangOpts().getLayoutCompatibility() == LangOptions::LayoutCompatibilityKind::Default &&
+  if (Context.getLangOpts().getLayoutCompatibility() ==
+          LangOptions::LayoutCompatibilityKind::Default &&
       Record->isMsStruct(Context) !=
           Context.getTargetInfo().defaultsToMsStruct() &&
       (Record->isPolymorphic() || Record->getNumBases())) {



More information about the cfe-commits mailing list