Disallowing GNU-style attributes in new expressions, since they are prohibited by GCC as well.

llvm-svn: 213650
This commit is contained in:
Aaron Ballman 2014-07-22 12:44:22 +00:00
parent f2b96e3009
commit 08b065909f
4 changed files with 56 additions and 21 deletions

View File

@ -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);

View File

@ -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.

View File

@ -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)

View File

@ -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++}}