[c++1z] Implement N3994: a range-based for loop can declare a variable with super-terse notation

  for (x : range) { ... }

which is equivalent to

  for (auto &&x : range) { ... }

llvm-svn: 211267
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 059c2b6..536e92c 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1388,6 +1388,25 @@
                              Cond.get(), T.getCloseLocation());
 }
 
+bool Parser::isForRangeIdentifier() {
+  assert(Tok.is(tok::identifier));
+
+  const Token &Next = NextToken();
+  if (Next.is(tok::colon))
+    return true;
+
+  if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) {
+    TentativeParsingAction PA(*this);
+    ConsumeToken();
+    SkipCXX11Attributes();
+    bool Result = Tok.is(tok::colon);
+    PA.Revert();
+    return Result;
+  }
+
+  return false;
+}
+
 /// ParseForStatement
 ///       for-statement: [C99 6.8.5.3]
 ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
@@ -1471,6 +1490,29 @@
     ProhibitAttributes(attrs);
     // no first part, eat the ';'.
     ConsumeToken();
+  } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
+             isForRangeIdentifier()) {
+    ProhibitAttributes(attrs);
+    IdentifierInfo *Name = Tok.getIdentifierInfo();
+    SourceLocation Loc = ConsumeToken();
+    MaybeParseCXX11Attributes(attrs);
+
+    ForRangeInit.ColonLoc = ConsumeToken();
+    if (Tok.is(tok::l_brace))
+      ForRangeInit.RangeExpr = ParseBraceInitializer();
+    else
+      ForRangeInit.RangeExpr = ParseExpression();
+
+    Diag(Loc, getLangOpts().CPlusPlus1z
+                  ? diag::warn_cxx1y_compat_for_range_identifier
+                  : diag::ext_for_range_identifier)
+      << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z)
+              ? FixItHint::CreateInsertion(Loc, "auto &&")
+              : FixItHint());
+
+    FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name,
+                                                   attrs, attrs.Range.getEnd());
+    ForRange = true;
   } else if (isForInitDeclaration()) {  // for (int X = 4;
     // Parse declaration, which eats the ';'.
     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?