diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-04-19 07:53:29 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-04-19 07:53:29 +0000 |
commit | 936b411bc8ac6b7da4e21c75023da4cd468ae653 (patch) | |
tree | 930ebc978eb6ad7ed8f7a7e0d74263fee3925f6f /clang/lib/Parse/ParseDecl.cpp | |
parent | 6f8fd8e98f3a8bdb1569921773ac7abce019a886 (diff) | |
download | bcm5719-llvm-936b411bc8ac6b7da4e21c75023da4cd468ae653.tar.gz bcm5719-llvm-936b411bc8ac6b7da4e21c75023da4cd468ae653.zip |
[MS ABI] Correctly associate align attrs before the class-key
__declspec(align(...)) is unlike all other attributes in that it is not
applied to a variable if it appears before the class-key. If the
tag in question isn't part of a variable declaration, it is not ignored.
Instead, the alignment attribute is applied to the tag.
This fixes PR18024.
llvm-svn: 235272
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8f4afdf9034..c64421793c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1360,6 +1360,46 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { } } +// As an exception to the rule, __declspec(align(...)) before the +// class-key affects the type instead of the variable. +void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs, + DeclSpec &DS, + Sema::TagUseKind TUK) { + if (TUK == Sema::TUK_Reference) + return; + + ParsedAttributes &PA = DS.getAttributes(); + AttributeList *AL = PA.getList(); + AttributeList *Prev = nullptr; + while (AL) { + AttributeList *Next = AL->getNext(); + + // We only consider attributes using the appropriate '__declspec' spelling, + // this behavior doesn't extend to any other spellings. + if (AL->getKind() == AttributeList::AT_Aligned && + AL->isDeclspecAttribute()) { + // Stitch the attribute into the tag's attribute list. + AL->setNext(nullptr); + Attrs.add(AL); + + // Remove the attribute from the variable's attribute list. + if (Prev) { + // Set the last variable attribute's next attribute to be the attribute + // after the current one. + Prev->setNext(Next); + } else { + // Removing the head of the list requires us to reset the head to the + // next attribute. + PA.set(Next); + } + } else { + Prev = AL; + } + + AL = Next; + } +} + /// ParseDeclaration - Parse a full 'declaration', which consists of /// declaration-specifiers, some number of declarators, and a semicolon. /// 'Context' should be a Declarator::TheContext value. This returns the @@ -3851,6 +3891,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } + handleDeclspecAlignBeforeClassKey(attrs, DS, TUK); + bool Owned = false; bool IsDependent = false; const char *PrevSpec = nullptr; |