From: Eli Friedman Date: Fri, 12 Oct 2012 23:29:20 +0000 (+0000) Subject: Make -mms-bitfields behave consistently. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5f608aedb6c5d32d2f7c51f9354a75b21f1eeaee;p=clang Make -mms-bitfields behave consistently. Patch by Jeremiah Zanin. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165849 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 835961f798..41f4d5cac2 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -3015,6 +3015,11 @@ public: return K >= firstRecord && K <= lastRecord; } + /// isMsStrust - Get whether or not this is an ms_struct which can + /// be turned on with an attribute, pragma, or -mms-bitfields + /// commandline option. + bool isMsStruct(const ASTContext &C) const; + private: /// \brief Deserialize just the fields. void LoadFieldsFromExternalStorage() const; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index fea81cf2c4..442deca11b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2517,7 +2517,7 @@ unsigned FieldDecl::getFieldIndex() const { unsigned Index = 0; const RecordDecl *RD = getParent(); const FieldDecl *LastFD = 0; - bool IsMsStruct = RD->hasAttr(); + bool IsMsStruct = RD->isMsStruct(getASTContext()); for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Index) { @@ -2765,6 +2765,13 @@ void RecordDecl::completeDefinition() { TagDecl::completeDefinition(); } +/// isMsStruct - Get whether or not this record uses ms_struct layout. +/// 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() || C.getLangOpts().MSBitfields == 1; +} + static bool isFieldOrIndirectField(Decl::Kind K) { return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); } diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index fc7586cffd..2bdc1e14e6 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1574,12 +1574,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { } void RecordLayoutBuilder::InitializeLayout(const Decl *D) { - if (const RecordDecl *RD = dyn_cast(D)) + if (const RecordDecl *RD = dyn_cast(D)) { IsUnion = RD->isUnion(); + IsMsStruct = RD->isMsStruct(Context); + } - Packed = D->hasAttr(); - - IsMsStruct = D->hasAttr(); + Packed = D->hasAttr(); // Honor the default struct packing maximum alignment flag. if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) { @@ -2085,7 +2085,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { ZeroLengthBitfield = 0; } - if (Context.getLangOpts().MSBitfields || IsMsStruct) { + if (IsMsStruct) { // If MS bitfield layout is required, figure out what type is being // laid out and align the field to the width of that type. diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index e263a44f2d..402a945e4e 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -824,7 +824,7 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, } } } else { - bool IsMsStruct = record->hasAttr(); + bool IsMsStruct = record->isMsStruct(CGM.getContext()); const FieldDecl *LastFD = 0; for (RecordDecl::field_iterator I = record->field_begin(), E = record->field_end(); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 0a20c08b15..206f74a302 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -379,7 +379,7 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { unsigned FieldNo = 0; unsigned ElementNo = 0; const FieldDecl *LastFD = 0; - bool IsMsStruct = RD->hasAttr(); + bool IsMsStruct = RD->isMsStruct(CGM.getContext()); for (RecordDecl::field_iterator Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { @@ -478,7 +478,7 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, unsigned FieldNo = 0; const FieldDecl *LastFD = 0; - bool IsMsStruct = RD->hasAttr(); + bool IsMsStruct = RD->isMsStruct(CGM.getContext()); uint64_t OffsetBits = CGM.getContext().toBits(Offset); for (RecordDecl::field_iterator Field = RD->field_begin(), diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 2f33ba93c2..26ef3efe73 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -206,7 +206,7 @@ void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { Alignment = Types.getContext().getASTRecordLayout(D).getAlignment(); Packed = D->hasAttr(); - IsMsStruct = D->hasAttr(); + IsMsStruct = D->isMsStruct(Types.getContext()); if (D->isUnion()) { LayoutUnion(D); @@ -1061,7 +1061,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D); RecordDecl::field_iterator it = D->field_begin(); const FieldDecl *LastFD = 0; - bool IsMsStruct = D->hasAttr(); + bool IsMsStruct = D->isMsStruct(getContext()); for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) { const FieldDecl *FD = *it; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 5671a0fd21..0b8dec314a 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -974,8 +974,8 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (TagDecl *TD = dyn_cast(D)) - TD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); + if (RecordDecl *RD = dyn_cast(D)) + RD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } diff --git a/test/Sema/mms-bitfields.c b/test/Sema/mms-bitfields.c new file mode 100644 index 0000000000..9289b9029a --- /dev/null +++ b/test/Sema/mms-bitfields.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -mms-bitfields -fsyntax-only -verify -triple x86_64-apple-darwin9 %s + +// The -mms-bitfields commandline parameter should behave the same +// as the ms_struct attribute. +struct +{ + int a : 1; + short b : 1; +} t; + +// MS pads out bitfields between different types. +static int arr[(sizeof(t) == 8) ? 1 : -1]; diff --git a/test/Sema/pragma-ms_struct.c b/test/Sema/pragma-ms_struct.c index d76ee8bab3..6533320e51 100644 --- a/test/Sema/pragma-ms_struct.c +++ b/test/Sema/pragma-ms_struct.c @@ -31,6 +31,12 @@ struct S { unsigned long bf_2 : 12; } __attribute__((ms_struct)) t2; +enum +{ + A = 0, + B, + C +} __attribute__((ms_struct)) e1; // expected-warning {{'ms_struct' attribute ignored}} // rdar://10513599 #pragma ms_struct on