[clang] Implement gcc_struct attribute on Itanium targets (#71148)

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

---------

Co-authored-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
Dan Klishch 2025-12-12 12:22:40 -05:00 committed by GitHub
parent 44aec0e768
commit 1760effa33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 233 additions and 38 deletions

View File

@ -379,6 +379,12 @@ Attribute Changes in Clang
multilibs for printf features. Requires cooperation with the libc
implementation.
- 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``,

View File

@ -2810,6 +2810,10 @@ public:
/// 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.

View File

@ -4387,8 +4387,13 @@ def CFGuard : InheritableAttr, TargetSpecificAttr<TargetWindows> {
def MSStruct : InheritableAttr {
let Spellings = [GCC<"ms_struct">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
let Documentation = [MSStructDocs];
}
def GCCStruct : InheritableAttr {
let Spellings = [GCC<"gcc_struct">];
let Subjects = SubjectList<[Record]>;
let Documentation = [MSStructDocs]; // Covers this attribute too.
}
def DLLExport : InheritableAttr, TargetSpecificAttr<TargetHasDLLImportExport> {

View File

@ -9682,3 +9682,24 @@ The following aspects are currently supported:
- ``float``: The call has a floating point argument
}];
}
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``.
The primary difference is for bitfields, where the MS variant only packs
adjacent fields into the same allocation unit if they have integral types
of the same size, while the GCC/Itanium variant packs all fields in a bitfield
tightly.
}];
}

View File

@ -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 "

View File

@ -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")

View File

@ -421,6 +421,16 @@ public:
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;

View File

@ -5219,9 +5219,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)">;
@ -5230,6 +5228,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)">,

View File

@ -5244,7 +5244,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<GCCStructAttr>())
return false;
if (hasAttr<MSStructAttr>())
return true;
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) {

View File

@ -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.

View File

@ -5889,9 +5889,12 @@ 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 (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");
}
if (Triple.isOSCygMing()) {

View File

@ -18992,9 +18992,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;

View File

@ -6173,6 +6173,36 @@ static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));
}
static void handleMSStructAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *First = D->getAttr<GCCStructAttr>()) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< AL << First << 0;
S.Diag(First->getLocation(), diag::note_conflicting_attribute);
return;
}
if (const auto *Preexisting = D->getAttr<MSStructAttr>()) {
if (Preexisting->isImplicit())
D->dropAttr<MSStructAttr>();
}
D->addAttr(::new (S.Context) MSStructAttr(S.Context, AL));
}
static void handleGCCStructAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *First = D->getAttr<MSStructAttr>()) {
if (First->isImplicit()) {
D->dropAttr<MSStructAttr>();
} else {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< AL << First << 0;
S.Diag(First->getLocation(), diag::note_conflicting_attribute);
return;
}
}
D->addAttr(::new (S.Context) GCCStructAttr(S.Context, AL));
}
static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SmallVector<StringRef, 4> Tags;
for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
@ -7983,6 +8013,14 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_ModularFormat:
handleModularFormat(S, D, AL);
break;
case ParsedAttr::AT_MSStruct:
handleMSStructAttr(S, D, AL);
break;
case ParsedAttr::AT_GCCStruct:
handleGCCStructAttr(S, D, AL);
break;
}
}

View File

@ -7288,20 +7288,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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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_assert(sizeof(t1) == 4, "");
#pragma ms_struct on
struct {
int a : 24;
char b : 8;
} __attribute__((gcc_struct)) t2;
_Static_assert(sizeof(t2) == 4, "");
#pragma ms_struct off

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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: HLSLVkLocation (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_field, SubjectMatchRule_function)

View File

@ -0,0 +1,37 @@
// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-windows-gnu -verify %s
struct {
int a;
}
// expected-note@+1 {{conflicting attribute is here}}
__attribute__((gcc_struct))
// expected-error@+1 {{'ms_struct' and 'gcc_struct' attributes are not compatible}}
__attribute__((ms_struct))
t1;
struct {
int a;
}
// expected-note@+1 {{conflicting attribute is here}}
__attribute__((ms_struct))
// expected-error@+1 {{'gcc_struct' and 'ms_struct' attributes are not compatible}}
__attribute__((gcc_struct))
t2;
#pragma ms_struct on
struct {
int a;
}
// No diagnostic for an attribute, unambiguously overriding the pragma.
__attribute__((gcc_struct))
t3;
struct {
int a;
}
// expected-note@+1 {{conflicting attribute is here}}
__attribute__((ms_struct))
// expected-error@+1 {{'gcc_struct' and 'ms_struct' attributes are not compatible}}
__attribute__((gcc_struct))
t4;
#pragma ms_struct off

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)}}

View File

@ -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