From 5b3d931d4c530c3de66347fae1529752774afda3 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 22 Jul 2014 12:44:22 +0000 Subject: [PATCH] Disallowing GNU-style attributes in new expressions, since they are prohibited by GCC as well. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213650 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Parser.h | 17 ++++++++++++-- lib/Parse/ParseDecl.cpp | 45 +++++++++++++++++++++--------------- lib/Parse/ParseStmtAsm.cpp | 2 +- test/SemaCXX/attr-gnu.cpp | 13 +++++++++++ 4 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 test/SemaCXX/attr-gnu.cpp diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index c58c41a44c..5b5f8eb967 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -2207,8 +2207,21 @@ private: void ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser); - void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, - bool CXX11AttributesAllowed = true, + enum AttrRequirements { + AR_NoAttributesParsed = 0, ///< No attributes are diagnosed. + AR_GNUAttributesParsedAndRejected = 1 << 0, ///< Diagnose GNU attributes. + AR_GNUAttributesParsed = 1 << 1, + AR_CXX11AttributesParsed = 1 << 2, + AR_DeclspecAttributesParsed = 1 << 3, + AR_AllAttributesParsed = AR_GNUAttributesParsed | + AR_CXX11AttributesParsed | + AR_DeclspecAttributesParsed, + AR_VendorAttributesParsed = AR_GNUAttributesParsed | + AR_DeclspecAttributesParsed + }; + + void ParseTypeQualifierListOpt(DeclSpec &DS, + unsigned AttrReqs = AR_AllAttributesParsed, bool AtomicAllowed = true, bool IdentifierRequired = false); void ParseDirectDeclarator(Declarator &D); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 62d43768bf..1bbc894337 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4373,20 +4373,18 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { /// type-qualifier-list: [C99 6.7.5] /// type-qualifier /// [vendor] attributes -/// [ only if VendorAttributesAllowed=true ] +/// [ only if AttrReqs & AR_VendorAttributesParsed ] /// type-qualifier-list type-qualifier /// [vendor] type-qualifier-list attributes -/// [ only if VendorAttributesAllowed=true ] +/// [ only if AttrReqs & AR_VendorAttributesParsed ] /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq -/// [ only if CXX11AttributesAllowed=true ] -/// Note: vendor can be GNU, MS, etc. -/// -void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, - bool VendorAttributesAllowed, - bool CXX11AttributesAllowed, +/// [ only if AttReqs & AR_CXX11AttributesParsed ] +/// Note: vendor can be GNU, MS, etc and can be explicitly controlled via +/// AttrRequirements bitmask values. +void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed, bool IdentifierRequired) { - if (getLangOpts().CPlusPlus11 && CXX11AttributesAllowed && + if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); ParseCXX11Attributes(attrs); @@ -4439,7 +4437,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___uptr: // GNU libc headers in C mode use '__uptr' as an identifer which conflicts // with the MS modifier keyword. - if (VendorAttributesAllowed && !getLangOpts().CPlusPlus && + if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus && IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) { if (TryKeywordIdentFallback(false)) continue; @@ -4453,19 +4451,26 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___fastcall: case tok::kw___thiscall: case tok::kw___unaligned: - if (VendorAttributesAllowed) { + if (AttrReqs & AR_DeclspecAttributesParsed) { ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; } goto DoneWithTypeQuals; case tok::kw___pascal: - if (VendorAttributesAllowed) { + if (AttrReqs & AR_VendorAttributesParsed) { ParseBorlandTypeAttributes(DS.getAttributes()); continue; } goto DoneWithTypeQuals; case tok::kw___attribute: - if (VendorAttributesAllowed) { + if (AttrReqs & AR_GNUAttributesParsedAndRejected) + // When GNU attributes are expressly forbidden, diagnose their usage. + Diag(Tok, diag::err_attributes_not_allowed); + + // Parse the attributes even if they are rejected to ensure that error + // recovery is graceful. + if (AttrReqs & AR_GNUAttributesParsed || + AttrReqs & AR_GNUAttributesParsedAndRejected) { ParseGNUAttributes(DS.getAttributes()); continue; // do *not* consume the next token! } @@ -4601,8 +4606,13 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Is a pointer. DeclSpec DS(AttrFactory); - // FIXME: GNU attributes are not allowed here in a new-type-id. - ParseTypeQualifierListOpt(DS, true, true, true, !D.mayOmitIdentifier()); + // GNU attributes are not allowed here in a new-type-id, but Declspec and + // C++11 attributes are allowed. + unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed | + ((D.getContext() != Declarator::CXXNewContext) + ? AR_GNUAttributesParsed + : AR_GNUAttributesParsedAndRejected); + ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier()); D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. @@ -5149,8 +5159,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // with the virt-specifier-seq and pure-specifier in the same way. // Parse cv-qualifier-seq[opt]. - ParseTypeQualifierListOpt(DS, /*VendorAttributesAllowed*/ false, - /*CXX11AttributesAllowed*/ false, + ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, /*AtomicAllowed*/ false); if (!DS.getSourceRange().getEnd().isInvalid()) { EndLoc = DS.getSourceRange().getEnd(); @@ -5546,7 +5555,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // If there is a type-qualifier-list, read it now. // Type qualifiers in an array subscript are a C99 feature. DeclSpec DS(AttrFactory); - ParseTypeQualifierListOpt(DS, false /*no attributes*/); + ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed); // If we haven't already read 'static', check to see if there is one after the // type-qualifier-list. diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp index f7e8307883..58d69965de 100644 --- a/lib/Parse/ParseStmtAsm.cpp +++ b/lib/Parse/ParseStmtAsm.cpp @@ -590,7 +590,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } DeclSpec DS(AttrFactory); SourceLocation Loc = Tok.getLocation(); - ParseTypeQualifierListOpt(DS, true, false); + ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed); // GNU asms accept, but warn, about type-qualifiers other than volatile. if (DS.getTypeQualifiers() & DeclSpec::TQ_const) diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp new file mode 100644 index 0000000000..3d23ed945e --- /dev/null +++ b/test/SemaCXX/attr-gnu.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -fms-compatibility -verify %s + +void f() { + // GNU-style attributes are prohibited in this position. + auto P = new int * __attribute__((vector_size(8))); // expected-error {{an attribute list cannot appear here}} \ + // expected-error {{invalid vector element type 'int *'}} + + // Ensure that MS type attribute keywords are still supported in this + // position. + auto P2 = new int * __sptr; // Ok +} + +void g(int a[static [[]] 5]); // expected-error {{static array size is a C99 feature, not permitted in C++}} -- 2.40.0