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
