Process and handle attributes on conditions and for loop variables. Process and
diagnose attributes on alias declarations, using directives, and attribute
declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175649 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cb013e7..8bfdffc 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -38,13 +38,16 @@
TypeResult Parser::ParseTypeName(SourceRange *Range,
Declarator::TheContext Context,
AccessSpecifier AS,
- Decl **OwnedType) {
+ Decl **OwnedType,
+ ParsedAttributes *Attrs) {
DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
if (DSC == DSC_normal)
DSC = DSC_type_specifier;
// Parse the common declaration-specifiers piece.
DeclSpec DS(AttrFactory);
+ if (Attrs)
+ DS.addAttributes(Attrs->getList());
ParseSpecifierQualifierList(DS, AS, DSC);
if (OwnedType)
*OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 4d428ce..22f5863 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -451,24 +451,21 @@
Decl **OwnedType) {
CXXScopeSpec SS;
SourceLocation TypenameLoc;
- bool IsTypeName;
- ParsedAttributesWithRange attrs(AttrFactory);
+ bool IsTypeName = false;
+ ParsedAttributesWithRange Attrs(AttrFactory);
// FIXME: Simply skip the attributes and diagnose, don't bother parsing them.
- MaybeParseCXX11Attributes(attrs);
- ProhibitAttributes(attrs);
- attrs.clear();
- attrs.Range = SourceRange();
+ MaybeParseCXX11Attributes(Attrs);
+ ProhibitAttributes(Attrs);
+ Attrs.clear();
+ Attrs.Range = SourceRange();
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
- TypenameLoc = Tok.getLocation();
- ConsumeToken();
+ TypenameLoc = ConsumeToken();
IsTypeName = true;
}
- else
- IsTypeName = false;
// Parse nested-name-specifier.
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
@@ -495,14 +492,13 @@
return 0;
}
- MaybeParseCXX11Attributes(attrs);
+ MaybeParseCXX11Attributes(Attrs);
// Maybe this is an alias-declaration.
bool IsAliasDecl = Tok.is(tok::equal);
TypeResult TypeAlias;
if (IsAliasDecl) {
- // TODO: Attribute support. C++0x attributes may appear before the equals.
- // Where can GNU attributes appear?
+ // TODO: Can GNU attributes appear here?
ConsumeToken();
Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
@@ -547,20 +543,21 @@
TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
Declarator::AliasTemplateContext :
- Declarator::AliasDeclContext, AS, OwnedType);
+ Declarator::AliasDeclContext, AS, OwnedType,
+ &Attrs);
} else {
// C++11 attributes are not allowed on a using-declaration, but GNU ones
// are.
- ProhibitAttributes(attrs);
+ ProhibitAttributes(Attrs);
// Parse (optional) attributes (most likely GNU strong-using extension).
- MaybeParseGNUAttributes(attrs);
+ MaybeParseGNUAttributes(Attrs);
}
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- !attrs.empty() ? "attributes list" :
+ !Attrs.empty() ? "attributes list" :
IsAliasDecl ? "alias declaration" : "using declaration",
tok::semi);
@@ -592,13 +589,13 @@
MultiTemplateParamsArg TemplateParamsArg(
TemplateParams ? TemplateParams->data() : 0,
TemplateParams ? TemplateParams->size() : 0);
- // FIXME: Propagate attributes.
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
- UsingLoc, Name, TypeAlias);
+ UsingLoc, Name, Attrs.getList(),
+ TypeAlias);
}
return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
- Name, attrs.getList(),
+ Name, Attrs.getList(),
IsTypeName, TypenameLoc);
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 613b0be..0a1111e 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1383,6 +1383,7 @@
// type-specifier-seq
DeclSpec DS(AttrFactory);
+ DS.takeAttributesFrom(attrs);
ParseSpecifierQualifierList(DS);
// declarator
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 4c8bd6f..a77c034 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -1385,9 +1385,6 @@
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
-
// In C++0x, "for (T NS:a" might not be a typo for ::
bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 1a667da..2d8d5b1 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -566,7 +566,6 @@
/// external-declaration: [C99 6.9], declaration: [C++ dcl.dcl]
/// function-definition
/// declaration
-/// [C++0x] empty-declaration
/// [GNU] asm-definition
/// [GNU] __extension__ external-declaration
/// [OBJC] objc-class-definition
@@ -578,8 +577,10 @@
/// [C++] linkage-specification
/// [GNU] asm-definition:
/// simple-asm-expr ';'
+/// [C++11] empty-declaration
+/// [C++11] attribute-declaration
///
-/// [C++0x] empty-declaration:
+/// [C++11] empty-declaration:
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
@@ -624,6 +625,13 @@
HandlePragmaOpenCLExtension();
return DeclGroupPtrTy();
case tok::semi:
+ // Either a C++11 empty-declaration or attribute-declaration.
+ if (attrs.Range.isValid()) {
+ // FIXME: Add an AST representation for this.
+ Actions.ActOnAttributeDeclaration(attrs.getList());
+ return DeclGroupPtrTy();
+ }
+
ConsumeExtraSemi(OutsideFunction);
// TODO: Invoke action for top-level semicolon.
return DeclGroupPtrTy();