r175649 - Process and handle attributes on conditions and for loop variables. Process and
Richard Smith
richard-llvm at metafoo.co.uk
Wed Feb 20 11:22:52 PST 2013
Author: rsmith
Date: Wed Feb 20 13:22:51 2013
New Revision: 175649
URL: http://llvm.org/viewvc/llvm-project?rev=175649&view=rev
Log:
Process and handle attributes on conditions and for loop variables. Process and
diagnose attributes on alias declarations, using directives, and attribute
declarations.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/Parser/cxx0x-attributes.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 20 13:22:51 2013
@@ -1908,6 +1908,8 @@ def warn_attribute_not_on_decl : Warning
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
def err_base_specifier_attribute : Error<
"%0 attribute cannot be applied to a base specifier">;
+def err_attribute_declaration : Error<
+ "%0 attribute cannot be used in an attribute declaration">;
// Availability attribute
def warn_availability_unknown_platform : Warning<
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Feb 20 13:22:51 2013
@@ -1800,7 +1800,8 @@ public:
Declarator::TheContext Context
= Declarator::TypeNameContext,
AccessSpecifier AS = AS_none,
- Decl **OwnedType = 0);
+ Decl **OwnedType = 0,
+ ParsedAttributes *Attrs = 0);
private:
void ParseBlockId(SourceLocation CaretLoc);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 20 13:22:51 2013
@@ -1447,6 +1447,9 @@ public:
SourceLocation AsmLoc,
SourceLocation RParenLoc);
+ /// \brief Handle a C++11 attribute-declaration.
+ void ActOnAttributeDeclaration(AttributeList *AttrList);
+
/// \brief The parser has processed a module import declaration.
///
/// \param AtLoc The location of the '@' symbol, if any.
@@ -3429,6 +3432,7 @@ public:
MultiTemplateParamsArg TemplateParams,
SourceLocation UsingLoc,
UnqualifiedId &Name,
+ AttributeList *AttrList,
TypeResult Type);
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Feb 20 13:22:51 2013
@@ -38,13 +38,16 @@ using namespace clang;
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;
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Feb 20 13:22:51 2013
@@ -451,24 +451,21 @@ Decl *Parser::ParseUsingDeclaration(unsi
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 @@ Decl *Parser::ParseUsingDeclaration(unsi
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 @@ Decl *Parser::ParseUsingDeclaration(unsi
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 @@ Decl *Parser::ParseUsingDeclaration(unsi
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);
}
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Feb 20 13:22:51 2013
@@ -1383,6 +1383,7 @@ bool Parser::ParseCXXCondition(ExprResul
// type-specifier-seq
DeclSpec DS(AttrFactory);
+ DS.takeAttributesFrom(attrs);
ParseSpecifierQualifierList(DS);
// declarator
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Wed Feb 20 13:22:51 2013
@@ -1385,9 +1385,6 @@ StmtResult Parser::ParseForStatement(Sou
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);
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Feb 20 13:22:51 2013
@@ -566,7 +566,6 @@ bool Parser::ParseTopLevelDecl(DeclGroup
/// 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 @@ bool Parser::ParseTopLevelDecl(DeclGroup
/// [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 @@ Parser::ParseExternalDeclaration(ParsedA
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();
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb 20 13:22:51 2013
@@ -6456,7 +6456,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
}
- // FIXME: We ignore attributes for now.
+ if (UDir)
+ ProcessDeclAttributeList(S, UDir, AttrList);
+
return UDir;
}
@@ -7172,6 +7174,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope
MultiTemplateParamsArg TemplateParamLists,
SourceLocation UsingLoc,
UnqualifiedId &Name,
+ AttributeList *AttrList,
TypeResult Type) {
// Skip up to the relevant declaration scope.
while (S->getFlags() & Scope::TemplateParamScope)
@@ -7218,6 +7221,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope
if (Invalid)
NewTD->setInvalidDecl();
+ ProcessDeclAttributeList(S, NewTD, AttrList);
+
CheckTypedefForVariablyModifiedType(S, NewTD);
Invalid |= NewTD->isInvalidDecl();
@@ -10080,6 +10085,25 @@ Decl *Sema::ActOnFinishLinkageSpecificat
return LinkageSpec;
}
+/// \brief Perform semantic checks on a C++11 attribute-declaration.
+void Sema::ActOnAttributeDeclaration(AttributeList *AttrList) {
+ // FIXME: Build an AST node for an attribute declaration and return it.
+
+ // Since we do not support any attributes which can be used in an attribute
+ // declaration, just diagnose standard and unknown attributes appropriately.
+ for (/**/; AttrList; AttrList = AttrList->getNext()) {
+ if (AttrList->getKind() == AttributeList::IgnoredAttribute ||
+ AttrList->isInvalid())
+ continue;
+
+ Diag(AttrList->getLoc(),
+ AttrList->getKind() == AttributeList::UnknownAttribute
+ ? diag::warn_unknown_attribute_ignored
+ : diag::err_attribute_declaration)
+ << AttrList->getName();
+ }
+}
+
/// \brief Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Feb 20 13:22:51 2013
@@ -3497,7 +3497,11 @@ TypeResult Sema::ActOnTypeName(Scope *S,
// Make sure there are no unused decl attributes on the declarator.
// We don't want to do this for ObjC parameters because we're going
// to apply them to the actual parameter declaration.
- if (D.getContext() != Declarator::ObjCParameterContext)
+ // Likewise, we don't want to do this for alias declarations, because
+ // we are actually going to build a declaration from this eventually.
+ if (D.getContext() != Declarator::ObjCParameterContext &&
+ D.getContext() != Declarator::AliasDeclContext &&
+ D.getContext() != Declarator::AliasTemplateContext)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=175649&r1=175648&r2=175649&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Wed Feb 20 13:22:51 2013
@@ -41,6 +41,8 @@ const [[]] int between_attr_2 = 0; // ex
int after_attr [[]];
int * [[]] ptr_attr;
int & [[]] ref_attr = after_attr;
+int & [[unknown]] ref_attr_2 = after_attr; // expected-warning {{unknown attribute 'unknown' ignored}}
+int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attribute cannot be applied to types}}
int && [[]] rref_attr = 0;
int array_attr [1] [[]];
alignas(8) int aligned_attr;
@@ -112,13 +114,18 @@ extern "C++" [[]] { } // expected-error
[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
[[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
-[[]] using namespace ns;
+[[unknown]] using namespace ns; // expected-warning {{unknown attribute 'unknown' ignored}}
+[[noreturn]] using namespace ns; // expected-error {{'noreturn' attribute only applies to functions and methods}}
[[]] using T = int; // expected-error {{an attribute list cannot appear here}}
using T [[]] = int; // ok
template<typename T> using U [[]] = T;
using ns::i [[]]; // expected-error {{an attribute list cannot appear here}}
using [[]] ns::i; // expected-error {{an attribute list cannot appear here}}
+using T [[unknown]] = int; // expected-warning {{unknown attribute 'unknown' ignored}}
+using T [[noreturn]] = int; // expected-error {{'noreturn' attribute only applies to functions and methods}}
+using V = int; // expected-note {{previous}}
+using V [[gnu::vector_size(16)]] = int; // expected-error {{redefinition with different types}}
auto trailing() -> [[]] const int; // expected-error {{an attribute list cannot appear here}}
auto trailing() -> const [[]] int; // expected-error {{an attribute list cannot appear here}}
@@ -220,10 +227,10 @@ void bar () {
// Condition tests
void baz () {
- if ([[]] bool b = true) {
- switch ([[]] int n { 42 }) {
+ if ([[unknown]] bool b = true) { // expected-warning {{unknown attribute 'unknown' ignored}}
+ switch ([[unknown]] int n { 42 }) { // expected-warning {{unknown attribute 'unknown' ignored}}
default:
- for ([[]] int n = 0; [[]] char b = n < 5; ++b) {
+ for ([[unknown]] int n = 0; [[unknown]] char b = n < 5; ++b) { // expected-warning 2{{unknown attribute 'unknown' ignored}}
}
}
}
@@ -240,7 +247,7 @@ void baz () {
do {
} while ([[]] false); // expected-error {{an attribute list cannot appear here}}
- for ([[]] int n : { 1, 2, 3 }) {
+ for ([[unknown]] int n : { 1, 2, 3 }) { // expected-warning {{unknown attribute 'unknown' ignored}}
}
}
@@ -251,7 +258,7 @@ enum class [[]] EvenMoreSecrets {};
namespace arguments {
void f[[gnu::format(printf, 1, 2)]](const char*, ...);
- void g() [[unknown::foo(currently arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}}
+ void g() [[unknown::foo(arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}}
}
// Forbid attributes on decl specifiers.
@@ -265,3 +272,6 @@ int [[carries_dependency]] foo(int [[car
int *[[gnu::unused]] v3; // expected-warning {{attribute 'unused' ignored}}
int v4[2][[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}
int v5()[[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}
+
+[[attribute_declaration]]; // expected-warning {{unknown attribute 'attribute_declaration' ignored}}
+[[noreturn]]; // expected-error {{'noreturn' attribute cannot be used in an attribute declaration}}
More information about the cfe-commits
mailing list