summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-04-19 07:53:29 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-04-19 07:53:29 +0000
commit936b411bc8ac6b7da4e21c75023da4cd468ae653 (patch)
tree930ebc978eb6ad7ed8f7a7e0d74263fee3925f6f /clang/lib
parent6f8fd8e98f3a8bdb1569921773ac7abce019a886 (diff)
downloadbcm5719-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')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp42
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp2
2 files changed, 44 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;
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index c74b02877c9..11934c4df68 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1692,6 +1692,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TParams =
MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());
+ handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
SS, Name, NameLoc, attrs.getList(), AS,
OpenPOWER on IntegriCloud