r235272 - [MS ABI] Correctly associate align attrs before the class-key
David Majnemer
david.majnemer at gmail.com
Sun Apr 19 00:53:29 PDT 2015
Author: majnemer
Date: Sun Apr 19 02:53:29 2015
New Revision: 235272
URL: http://llvm.org/viewvc/llvm-project?rev=235272&view=rev
Log:
[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.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/test/Parser/MicrosoftExtensions.c
cfe/trunk/test/Parser/MicrosoftExtensions.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=235272&r1=235271&r2=235272&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Apr 19 02:53:29 2015
@@ -1979,6 +1979,9 @@ private:
void DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
SourceLocation CorrectLocation);
+ void handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS, Sema::TagUseKind TUK);
+
void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
if (!attrs.Range.isValid()) return;
DiagnoseProhibitedAttributes(attrs);
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=235272&r1=235271&r2=235272&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sun Apr 19 02:53:29 2015
@@ -1360,6 +1360,46 @@ void Parser::ProhibitCXX11Attributes(Par
}
}
+// 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(SourceLo
return;
}
+ handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+
bool Owned = false;
bool IsDependent = false;
const char *PrevSpec = nullptr;
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=235272&r1=235271&r2=235272&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Apr 19 02:53:29 2015
@@ -1692,6 +1692,8 @@ void Parser::ParseClassSpecifier(tok::To
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,
Modified: cfe/trunk/test/Parser/MicrosoftExtensions.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.c?rev=235272&r1=235271&r2=235272&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.c (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.c Sun Apr 19 02:53:29 2015
@@ -93,3 +93,10 @@ typedef void(*ignored_quals_dummy3)(), _
typedef void(*ignored_quals_dummy4)(), __thiscall ignored_quals4; // expected-warning {{qualifiers after comma in declarator list are ignored}}
typedef void(*ignored_quals_dummy5)(), __cdecl ignored_quals5; // expected-warning {{qualifiers after comma in declarator list are ignored}}
typedef void(*ignored_quals_dummy6)(), __vectorcall ignored_quals6; // expected-warning {{qualifiers after comma in declarator list are ignored}}
+
+__declspec(align(16)) struct align_before_key1 {};
+__declspec(align(16)) struct align_before_key2 {} align_before_key2_var;
+__declspec(align(16)) struct align_before_key3 {} *align_before_key3_var;
+_Static_assert(__alignof(struct align_before_key1) == 16, "");
+_Static_assert(__alignof(struct align_before_key2) == 16, "");
+_Static_assert(__alignof(struct align_before_key3) == 16, "");
Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=235272&r1=235271&r2=235272&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Sun Apr 19 02:53:29 2015
@@ -391,3 +391,12 @@ constexpr A<int> h() {
}
static_assert(h().g() == false, "");
}
+
+namespace {
+__declspec(align(16)) struct align_before_key1 {};
+__declspec(align(16)) struct align_before_key2 {} align_before_key2_var;
+__declspec(align(16)) struct align_before_key3 {} *align_before_key3_var;
+static_assert(__alignof(struct align_before_key1) == 16, "");
+static_assert(__alignof(struct align_before_key2) == 16, "");
+static_assert(__alignof(struct align_before_key3) == 16, "");
+}
More information about the cfe-commits
mailing list