]> granicus.if.org Git - clang/commitdiff
Implement C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains to...
authorMichael Han <Michael.Han@autodesk.com>
Wed, 28 Nov 2012 23:17:40 +0000 (23:17 +0000)
committerMichael Han <Michael.Han@autodesk.com>
Wed, 28 Nov 2012 23:17:40 +0000 (23:17 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168826 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/DeclSpec.h
lib/Parse/ParseDeclCXX.cpp
test/Parser/cxx0x-attributes.cpp

index c1cf30e45f0ec545259d4f0f682769559dd3d898..280ac84767343925044c76f306c458f101ea8e5c 100644 (file)
@@ -1897,6 +1897,17 @@ public:
     return false;
   }
 
+  /// \brief Return a source range list of C++11 attributes associated
+  /// with the declarator.
+  void getCXX11AttributeRanges(SmallVector<SourceRange, 4> &Ranges) {
+    AttributeList *AttrList = Attrs.getList();
+    while (AttrList) {
+      if (AttrList->isCXX0XAttribute())
+        Ranges.push_back(AttrList->getRange());
+      AttrList = AttrList->getNext();
+    }
+  }
+
   void setAsmLabel(Expr *E) { AsmLabel = E; }
   Expr *getAsmLabel() const { return AsmLabel; }
 
index 700cf4e4afd480ebc0a262312cb73b2998cdeac3..bf12ee6900209df015835f7571700b1e4da402c7 100644 (file)
@@ -1915,8 +1915,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
   ColonProtectionRAIIObject X(*this);
 
   ParsedAttributesWithRange attrs(AttrFactory);
+  ParsedAttributesWithRange FnAttrs(AttrFactory);
   // Optional C++0x attribute-specifier
   MaybeParseCXX0XAttributes(attrs);
+  // We need to keep these attributes for future diagnostic
+  // before they are taken over by declaration specifier.
+  FnAttrs.addAll(attrs.getList());
+  FnAttrs.Range = attrs.Range;
+
   MaybeParseMicrosoftAttributes(attrs);
 
   if (Tok.is(tok::kw_using)) {
@@ -1955,6 +1961,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
 
   if (Tok.is(tok::semi)) {
     ConsumeToken();
+
+    if (DS.isFriendSpecified())
+      ProhibitAttributes(FnAttrs);
+
     Decl *TheDecl =
       Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams);
     DS.complete(TheDecl);
@@ -2023,12 +2033,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
       }
     }
 
+    // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains 
+    // to a friend declaration, that declaration shall be a definition.
+    if (DeclaratorInfo.isFunctionDeclarator() && 
+        DefinitionKind != FDK_Definition && DS.isFriendSpecified()) {
+      // Diagnose attributes that appear before decl specifier:
+      // [[]] friend int foo();
+      ProhibitAttributes(FnAttrs);
+    }
+
     if (DefinitionKind) {
       if (!DeclaratorInfo.isFunctionDeclarator()) {
         Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);
         ConsumeBrace();
         SkipUntil(tok::r_brace, /*StopAtSemi*/false);
-        
+
         // Consume the optional ';'
         if (Tok.is(tok::semi))
           ConsumeToken();
@@ -2123,6 +2142,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
 
     Decl *ThisDecl = 0;
     if (DS.isFriendSpecified()) {
+      // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains 
+      // to a friend declaration, that declaration shall be a definition.
+      //
+      // Diagnose attributes appear after friend member function declarator:
+      // foo [[]] ();
+      SmallVector<SourceRange, 4> Ranges;
+      DeclaratorInfo.getCXX11AttributeRanges(Ranges);
+      if (!Ranges.empty()) {
+        for (SmallVector<SourceRange, 4>::iterator I = Ranges.begin(), 
+             E = Ranges.end(); I != E; ++I) {
+          Diag((*I).getBegin(), diag::err_attributes_not_allowed) 
+            << *I;
+        }
+      }
+
       // TODO: handle initializers, bitfields, 'delete'
       ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
                                                  TemplateParams);
index 54baaedfd39bc3da835ac954b46aef3dad4cc1a4..90e73004f6204ee5da90032b5dd6a987d98ef777 100644 (file)
@@ -151,10 +151,16 @@ enum struct [[]] E5;
 
 struct S {
   friend int f [[]] (); // expected-FIXME{{an attribute list cannot appear here}}
-  [[]] friend int g(); // expected-FIXME{{an attribute list cannot appear here}}
+  friend int f1 [[noreturn]] (); //expected-error{{an attribute list cannot appear here}}
+  friend int f2 [[]] [[noreturn]] () {}
+  [[]] friend int g(); // expected-error{{an attribute list cannot appear here}}
   [[]] friend int h() {
   }
+  [[]] friend int f3(), f4(), f5(); // expected-error{{an attribute list cannot appear here}}
+  friend int f6 [[noreturn]] (), f7 [[noreturn]] (), f8 [[noreturn]] (); // expected-error3 {{an attribute list cannot appear here}}
   friend class [[]] C; // expected-error{{an attribute list cannot appear here}}
+  [[]] friend class D; // expected-error{{an attribute list cannot appear here}}
+  [[]] friend int; // expected-error{{an attribute list cannot appear here}}
 };
 template<typename T> void tmpl(T) {}
 template void tmpl [[]] (int); // expected-FIXME {{an attribute list cannot appear here}}