Disambiguation of '[[':
 * In C++11, '[[' is ill-formed unless it starts an attribute-specifier. Reject
   array sizes and array indexes which begin with a lambda-expression. Recover by
   parsing the lambda as a lambda.
 * In Objective-C++11, either '[' could be the start of a message-send.
   Fully disambiguate this case: it turns out that the grammars of message-sends,
   lambdas and attributes do not actually overlap. Accept any occurrence of '[['
   where either '[' starts a message send, but reject a lambda in an array index
   just like in C++11 mode.

Implement a couple of changes to the attribute wording which occurred after our
attributes implementation landed:
 * In a function-declaration, the attributes go after the exception specification,
   not after the right paren.
 * A reference type can have attributes applied.
 * An 'identifier' in an attribute can also be a keyword. Support for alternative
   tokens (iso646 keywords) in attributes to follow.

And some bug fixes:
 * Parse attributes after declarator-ids, even if they are not simple identifiers.
 * Do not accept attributes after a parenthesized declarator.
 * Accept attributes after an array size in a new-type-id.
 * Partially disamiguate 'delete' followed by a lambda. More work is required
   here for the case where the lambda-introducer is '[]'.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154369 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 9321c13..10ed3b1 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -2736,38 +2736,38 @@
   Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
 }
 
-/// ParseCXX0XAttributeSpecifier - Parse a C++0x attribute-specifier. Currently
+/// ParseCXX0XAttributeSpecifier - Parse a C++11 attribute-specifier. Currently
 /// only parses standard attributes.
 ///
-/// [C++0x] attribute-specifier:
+/// [C++11] attribute-specifier:
 ///         '[' '[' attribute-list ']' ']'
 ///         alignment-specifier
 ///
-/// [C++0x] attribute-list:
+/// [C++11] attribute-list:
 ///         attribute[opt]
 ///         attribute-list ',' attribute[opt]
 ///
-/// [C++0x] attribute:
+/// [C++11] attribute:
 ///         attribute-token attribute-argument-clause[opt]
 ///
-/// [C++0x] attribute-token:
+/// [C++11] attribute-token:
 ///         identifier
 ///         attribute-scoped-token
 ///
-/// [C++0x] attribute-scoped-token:
+/// [C++11] attribute-scoped-token:
 ///         attribute-namespace '::' identifier
 ///
-/// [C++0x] attribute-namespace:
+/// [C++11] attribute-namespace:
 ///         identifier
 ///
-/// [C++0x] attribute-argument-clause:
+/// [C++11] attribute-argument-clause:
 ///         '(' balanced-token-seq ')'
 ///
-/// [C++0x] balanced-token-seq:
+/// [C++11] balanced-token-seq:
 ///         balanced-token
 ///         balanced-token-seq balanced-token
 ///
-/// [C++0x] balanced-token:
+/// [C++11] balanced-token:
 ///         '(' balanced-token-seq ')'
 ///         '[' balanced-token-seq ']'
 ///         '{' balanced-token-seq '}'
@@ -2781,7 +2781,7 @@
   }
 
   assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
-      && "Not a C++0x attribute list");
+      && "Not a C++11 attribute list");
 
   Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute);
 
@@ -2793,7 +2793,11 @@
     ConsumeToken();
   }
 
-  while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
+  // 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)) {
     // attribute not present
     if (Tok.is(tok::comma)) {
       ConsumeToken();
@@ -2807,7 +2811,7 @@
     if (Tok.is(tok::coloncolon)) {
       ConsumeToken();
 
-      if (!Tok.is(tok::identifier)) {
+      if (!Tok.getIdentifierInfo()) {
         Diag(Tok.getLocation(), diag::err_expected_ident);
         SkipUntil(tok::r_square, tok::comma, true, true);
         continue;
@@ -2824,8 +2828,7 @@
     // No scoped names are supported; ideally we could put all non-standard
     // attributes into namespaces.
     if (!ScopeName) {
-      switch(AttributeList::getKind(AttrName))
-      {
+      switch (AttributeList::getKind(AttrName)) {
       // No arguments
       case AttributeList::AT_carries_dependency:
       case AttributeList::AT_noreturn: {
@@ -2852,6 +2855,9 @@
       // SkipUntil maintains the balancedness of tokens.
       SkipUntil(tok::r_paren, false);
     }
+
+    if (Tok.is(tok::ellipsis))
+      ConsumeToken();
   }
 
   if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
@@ -2874,7 +2880,7 @@
 
   do {
     ParseCXX0XAttributeSpecifier(attrs, endLoc);
-  } while (isCXX0XAttributeSpecifier());
+  } while (isCXX11AttributeSpecifier());
 
   attrs.Range = SourceRange(StartLoc, *endLoc);
 }
@@ -2892,6 +2898,7 @@
   assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
 
   while (Tok.is(tok::l_square)) {
+    // FIXME: If this is actually a C++11 attribute, parse it as one.
     ConsumeBracket();
     SkipUntil(tok::r_square, true, true);
     if (endLoc) *endLoc = Tok.getLocation();