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