[cfe-commits] r154381 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTentative.cpp test/Parser/cxx0x-attributes.cpp test/Parser/objcxx11-attributes.mm

Richard Smith richard-llvm at metafoo.co.uk
Mon Apr 9 20:25:07 PDT 2012


Author: rsmith
Date: Mon Apr  9 22:25:07 2012
New Revision: 154381

URL: http://llvm.org/viewvc/llvm-project?rev=154381&view=rev
Log:
Parsing of C++11 attributes:
 * Alternative tokens (such as 'compl') are treated as identifiers in
   attribute names.
 * An attribute-list can start with a comma.
 * An ellipsis may not be used with either of our currently-supported
   C++11 attributes.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/test/Parser/cxx0x-attributes.cpp
    cfe/trunk/test/Parser/objcxx11-attributes.mm

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Apr  9 22:25:07 2012
@@ -464,10 +464,10 @@
 def warn_cxx98_compat_attribute : Warning<
   "attributes are incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
-def err_cxx0x_attribute_forbids_arguments : Error<
-  "C++11 attribute '%0' cannot have an argument list">;
-def err_cxx0x_attribute_requires_arguments : Error<
-  "C++11 attribute '%0' must have an argument list">;
+def err_cxx11_attribute_forbids_arguments : Error<
+  "attribute '%0' cannot have an argument list">;
+def err_cxx11_attribute_forbids_ellipsis : Error<
+  "attribute '%0' cannot be used as an attribute pack">;
 def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
 def err_l_square_l_square_not_attribute : Error<
   "C++11 only allows consecutive left square brackets when "

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Apr  9 22:25:07 2012
@@ -1907,7 +1907,7 @@
     if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) {
       ParsedAttributesWithRange attrs(AttrFactory);
       SourceLocation endLoc;
-      ParseCXX0XAttributes(attrs, &endLoc);
+      ParseCXX11Attributes(attrs, &endLoc);
       D.takeAttributes(attrs, endLoc);
     }
   }
@@ -1915,7 +1915,7 @@
                                  SourceLocation *endLoc = 0) {
     if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) {
       ParsedAttributesWithRange attrsWithRange(AttrFactory);
-      ParseCXX0XAttributes(attrsWithRange, endLoc);
+      ParseCXX11Attributes(attrsWithRange, endLoc);
       attrs.takeAllFrom(attrsWithRange);
     }
   }
@@ -1924,13 +1924,14 @@
                                  bool OuterMightBeMessageSend = false) {
     if (getLangOpts().CPlusPlus0x &&
         isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
-      ParseCXX0XAttributes(attrs, endLoc);
+      ParseCXX11Attributes(attrs, endLoc);
   }
 
-  void ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
+  void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
                                     SourceLocation *EndLoc = 0);
-  void ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+  void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
                             SourceLocation *EndLoc = 0);
+  IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc);
 
   void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
                                      SourceLocation *endLoc = 0) {

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Apr  9 22:25:07 2012
@@ -3486,11 +3486,11 @@
 ///
 void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
                                        bool VendorAttributesAllowed,
-                                       bool CXX0XAttributesAllowed) {
-  if (getLangOpts().CPlusPlus0x && CXX0XAttributesAllowed &&
+                                       bool CXX11AttributesAllowed) {
+  if (getLangOpts().CPlusPlus0x && CXX11AttributesAllowed &&
       isCXX11AttributeSpecifier()) {
     ParsedAttributesWithRange attrs(AttrFactory);
-    ParseCXX0XAttributes(attrs);
+    ParseCXX11Attributes(attrs);
     DS.takeAttributesFrom(attrs);
   }
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Apr  9 22:25:07 2012
@@ -2736,7 +2736,49 @@
   Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
 }
 
-/// ParseCXX0XAttributeSpecifier - Parse a C++11 attribute-specifier. Currently
+/// \brief Try to parse an 'identifier' which appears within an attribute-token.
+///
+/// \return the parsed identifier on success, and 0 if the next token is not an
+/// attribute-token.
+///
+/// C++11 [dcl.attr.grammar]p3:
+///   If a keyword or an alternative token that satisfies the syntactic
+///   requirements of an identifier is contained in an attribute-token,
+///   it is considered an identifier.
+IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
+  switch (Tok.getKind()) {
+  default:
+    // Identifiers and keywords have identifier info attached.
+    if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
+      Loc = ConsumeToken();
+      return II;
+    }
+    return 0;
+
+  case tok::ampamp:       // 'and'
+  case tok::pipe:         // 'bitor'
+  case tok::pipepipe:     // 'or'
+  case tok::caret:        // 'xor'
+  case tok::tilde:        // 'compl'
+  case tok::amp:          // 'bitand'
+  case tok::ampequal:     // 'and_eq'
+  case tok::pipeequal:    // 'or_eq'
+  case tok::caretequal:   // 'xor_eq'
+  case tok::exclaim:      // 'not'
+  case tok::exclaimequal: // 'not_eq'
+    // Alternative tokens do not have identifier info, but their spelling
+    // starts with an alphabetical character.
+    llvm::SmallString<8> SpellingBuf;
+    StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf);
+    if (std::isalpha(Spelling[0])) {
+      Loc = ConsumeToken();
+      return &PP.getIdentifierTable().get(Spelling.data());
+    }
+    return 0;
+  }
+}
+
+/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently
 /// only parses standard attributes.
 ///
 /// [C++11] attribute-specifier:
@@ -2746,6 +2788,8 @@
 /// [C++11] attribute-list:
 ///         attribute[opt]
 ///         attribute-list ',' attribute[opt]
+///         attribute '...'
+///         attribute-list ',' attribute '...'
 ///
 /// [C++11] attribute:
 ///         attribute-token attribute-argument-clause[opt]
@@ -2772,7 +2816,7 @@
 ///         '[' balanced-token-seq ']'
 ///         '{' balanced-token-seq '}'
 ///         any token but '(', ')', '[', ']', '{', or '}'
-void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
+void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
                                           SourceLocation *endLoc) {
   if (Tok.is(tok::kw_alignas)) {
     Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);
@@ -2788,40 +2832,34 @@
   ConsumeBracket();
   ConsumeBracket();
 
-  if (Tok.is(tok::comma)) {
-    Diag(Tok.getLocation(), diag::err_expected_ident);
-    ConsumeToken();
-  }
-
-  // C++11 [dcl.attr.grammar]p3: If a keyword or an alternative token that
-  // satisfies the syntactic requirements of an identifier is contained in an
-  // attribute-token, it is considered an identifier.
-  // FIXME: Support alternative tokens here.
-  while (Tok.getIdentifierInfo() || Tok.is(tok::comma)) {
+  while (Tok.isNot(tok::r_square)) {
     // attribute not present
     if (Tok.is(tok::comma)) {
       ConsumeToken();
       continue;
     }
 
-    IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
-    SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
+    SourceLocation ScopeLoc, AttrLoc;
+    IdentifierInfo *ScopeName = 0, *AttrName = 0;
+
+    AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
+    if (!AttrName)
+      // Break out to the "expected ']'" diagnostic.
+      break;
 
     // scoped attribute
     if (Tok.is(tok::coloncolon)) {
       ConsumeToken();
 
-      if (!Tok.getIdentifierInfo()) {
+      ScopeName = AttrName;
+      ScopeLoc = AttrLoc;
+
+      AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
+      if (!AttrName) {
         Diag(Tok.getLocation(), diag::err_expected_ident);
         SkipUntil(tok::r_square, tok::comma, true, true);
         continue;
       }
-
-      ScopeName = AttrName;
-      ScopeLoc = AttrLoc;
-
-      AttrName = Tok.getIdentifierInfo();
-      AttrLoc = ConsumeToken();
     }
 
     bool AttrParsed = false;
@@ -2833,7 +2871,7 @@
       case AttributeList::AT_carries_dependency:
       case AttributeList::AT_noreturn: {
         if (Tok.is(tok::l_paren)) {
-          Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
+          Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
             << AttrName->getName();
           break;
         }
@@ -2856,8 +2894,12 @@
       SkipUntil(tok::r_paren, false);
     }
 
-    if (Tok.is(tok::ellipsis))
+    if (Tok.is(tok::ellipsis)) {
+      if (AttrParsed)
+        Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
+          << AttrName->getName();
       ConsumeToken();
+    }
   }
 
   if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
@@ -2868,18 +2910,18 @@
     SkipUntil(tok::r_square, false);
 }
 
-/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier-seq.
+/// ParseCXX11Attributes - Parse a C++0x attribute-specifier-seq.
 ///
 /// attribute-specifier-seq:
 ///       attribute-specifier-seq[opt] attribute-specifier
-void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
                                   SourceLocation *endLoc) {
   SourceLocation StartLoc = Tok.getLocation(), Loc;
   if (!endLoc)
     endLoc = &Loc;
 
   do {
-    ParseCXX0XAttributeSpecifier(attrs, endLoc);
+    ParseCXX11AttributeSpecifier(attrs, endLoc);
   } while (isCXX11AttributeSpecifier());
 
   attrs.Range = SourceRange(StartLoc, *endLoc);

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Mon Apr  9 22:25:07 2012
@@ -485,18 +485,17 @@
     //   If a keyword or an alternative token that satisfies the syntactic
     //   requirements of an identifier is contained in an attribute-token,
     //   it is considered an identifier.
-    if (!Tok.getIdentifierInfo()) {
+    SourceLocation Loc;
+    if (!TryParseCXX11AttributeIdentifier(Loc)) {
       IsAttribute = false;
       break;
     }
-    ConsumeToken();
     if (Tok.is(tok::coloncolon)) {
       ConsumeToken();
-      if (!Tok.getIdentifierInfo()) {
+      if (!TryParseCXX11AttributeIdentifier(Loc)) {
         IsAttribute = false;
         break;
       }
-      ConsumeToken();
     }
 
     // Parse the attribute-argument-clause, if present.

Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Mon Apr  9 22:25:07 2012
@@ -11,6 +11,9 @@
 alignas(8) int aligned_attr;
 [[test::valid(for 42 [very] **** '+' symbols went on a trip; the end.)]]
   int garbage_attr;
+[[,,,static, class, namespace,, inline, constexpr, mutable,, bi\
+tand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr;
+[[u8"invalid!"]] int invalid_string_attr; // expected-error {{expected ']'}}
 void fn_attr () [[]];
 void noexcept_fn_attr () noexcept [[]];
 struct MemberFnOrder {
@@ -21,7 +24,7 @@
 template <typename T> [[]] void template_attr ();
 [[]] [[]] int [[]] [[]] multi_attr [[]] [[]];
 
-int comma_attr [[,]]; // expected-error {{expected identifier}}
+int comma_attr [[,]];
 int scope_attr [[foo::]]; // expected-error {{expected identifier}}
 int (paren_attr) [[]]; // expected-error {{an attribute list cannot appear here}}
 unsigned [[]] int attr_in_decl_spec; // expected-error {{expected unqualified-id}}
@@ -70,3 +73,7 @@
 
   [[]] return;
 }
+
+template<typename...Ts> void variadic() {
+  void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot be used as an attribute pack}}
+}

Modified: cfe/trunk/test/Parser/objcxx11-attributes.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-attributes.mm?rev=154381&r1=154380&r2=154381&view=diff
==============================================================================
--- cfe/trunk/test/Parser/objcxx11-attributes.mm (original)
+++ cfe/trunk/test/Parser/objcxx11-attributes.mm Mon Apr  9 22:25:07 2012
@@ -33,6 +33,7 @@
   [[]];
   [[int(), noreturn]];
   [[class, test(foo 'x' bar),,,]];
+  [[bitand, noreturn]];
 }
 
 template<typename...Ts> void f(Ts ...x) {





More information about the cfe-commits mailing list