From: Michael Han Date: Tue, 6 Nov 2012 19:34:54 +0000 (+0000) Subject: Teach Clang parser to reject C++11 attributes that appertain to declaration specifiers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f64231e9f47234826fbcdc3b4fe0370ef6c9961d;p=clang Teach Clang parser to reject C++11 attributes that appertain to declaration specifiers. We don't support any C++11 attributes that appertain to declaration specifiers so reject the attributes in parser until we support them; this also conforms to what g++ 4.8 is doing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167481 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 3b8d5c8b9b..0968d9c276 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1865,6 +1865,11 @@ private: } void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs); + // Forbid C++11 attributes that appear on certain syntactic + // locations which standard permits but we don't supported yet, + // for example, attributes appertain to decl specifiers. + void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs); + void MaybeParseGNUAttributes(Declarator &D, LateParsedAttrList *LateAttrs = 0) { if (Tok.is(tok::kw___attribute)) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d45f038f31..f73907a7c4 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1142,6 +1142,18 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { << attrs.Range; } +void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { + AttributeList *AttrList = attrs.getList(); + while (AttrList) { + if (AttrList->isCXX0XAttribute()) { + Diag(AttrList->getLoc(), diag::warn_attribute_no_decl) + << AttrList->getName(); + AttrList->setInvalid(); + } + AttrList = AttrList->getNext(); + } +} + /// 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 @@ -2148,8 +2160,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DoneWithDeclSpec: if (!AttrsLastTime) ProhibitAttributes(attrs); - else + else { + // Reject C++11 attributes that appertain to decl specifiers as + // we don't support any C++11 attributes that appertain to decl + // specifiers. This also conforms to what g++ 4.8 is doing. + ProhibitCXX11Attributes(attrs); + DS.takeAttributesFrom(attrs); + } // If this is not a declaration specifier token, we're done reading decl // specifiers. First verify that DeclSpec's are consistent. diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp index 0b518bb085..02cc973018 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -34,7 +34,7 @@ void f() { void g() throw (struct Ex {}) { // expected-error {{'Ex' can not be defined in a type specifier}} } -int alignas(struct Aa {}) x; // expected-error {{'Aa' can not be defined in a type specifier}} +alignas(struct Aa {}) int x; // expected-error {{'Aa' can not be defined in a type specifier}} int a = sizeof(struct So {}); // expected-error {{'So' can not be defined in a type specifier}} int b = alignof(struct Ao {}); // expected-error {{'Ao' can not be defined in a type specifier}} diff --git a/test/CXX/expr/expr.const/p5-0x.cpp b/test/CXX/expr/expr.const/p5-0x.cpp index 60fabe37e2..bdb2b23ec7 100644 --- a/test/CXX/expr/expr.const/p5-0x.cpp +++ b/test/CXX/expr/expr.const/p5-0x.cpp @@ -61,10 +61,10 @@ enum NotFixed { // [dcl.align]p2: When the alignment-specifier is of the form // alignas(assignment-expression), the assignment-expression shall be an // integral constant expression -int alignas(ok) alignas1; -int alignas(incomplete) alignas2; // expected-error {{incomplete}} -int alignas(expl) alignas3; // expected-error {{explicit conversion}} -int alignas(ambig) alignas4; // expected-error {{ambiguous conversion}} +alignas(ok) int alignas1; +alignas(incomplete) int alignas2; // expected-error {{incomplete}} +alignas(expl) int alignas3; // expected-error {{explicit conversion}} +alignas(ambig) int alignas4; // expected-error {{ambiguous conversion}} // [dcl.array]p1: If the constant-expression is present, it shall be an integral // constant expression diff --git a/test/Parser/cxx0x-attributes.cpp b/test/Parser/cxx0x-attributes.cpp index 5790e10044..58e42bffcf 100644 --- a/test/Parser/cxx0x-attributes.cpp +++ b/test/Parser/cxx0x-attributes.cpp @@ -223,3 +223,10 @@ namespace arguments { void f(const char*, ...) [[gnu::format(printf, 1, 2)]]; // expected-warning {{unknown attribute 'format' ignored}} void g() [[unknown::foo(currently arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}} } + +// forbid attributes on decl specifiers +unsigned [[gnu::used]] static int [[gnu::unused]] v1; // expected-warning {{attribute 'unused' ignored, because it is not attached to a declaration}} \ + expected-error {{an attribute list cannot appear here}} +typedef [[gnu::used]] unsigned long [[gnu::unused]] v2; // expected-warning {{attribute 'unused' ignored, because it is not attached to a declaration}} \ + expected-error {{an attribute list cannot appear here}} +int [[carries_dependency]] foo(int [[carries_dependency]] x); // expected-warning 2{{attribute 'carries_dependency' ignored, because it is not attached to a declaration}} diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 249195564a..d497d45c3e 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -20,7 +20,7 @@ class Variadic2 {}; template // expected-warning {{variadic templates are incompatible with C++98}} class Variadic3 {}; -int alignas(8) with_alignas; // expected-warning {{'alignas' is incompatible with C++98}} +alignas(8) int with_alignas; // expected-warning {{'alignas' is incompatible with C++98}} int with_attribute [[ ]]; // expected-warning {{attributes are incompatible with C++98}} void Literals() {