This patch continues parser-level implementation of designators:

1. It introduces new parser level abstractions for designators
   that are used to communicate between parser and sema.
2. This fixes a FIXME where "identifier ':'" was considered to be
   a designator even if it wasn't the first in a designator list.
3. In the "identifier ':'" case, it actually builds the designator
   representation.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58205 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index f4073af..5f2dc6d 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Parse/Designator.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/SmallString.h"
@@ -54,7 +55,32 @@
 /// initializer (because it is an expression).  We need to consider this case
 /// when parsing array designators.
 ///
-Parser::ExprResult Parser::ParseInitializerWithPotentialDesignator() {
+Parser::ExprResult Parser::
+ParseInitializerWithPotentialDesignator(InitListDesignations &Designations,
+                                        unsigned InitNum) {
+  
+  // If this is the old-style GNU extension:
+  //   designation ::= identifier ':'
+  // Handle it as a field designator.  Otherwise, this must be the start of a
+  // normal expression.
+  if (Tok.is(tok::identifier)) {
+    if (NextToken().is(tok::colon)) {
+      Diag(Tok, diag::ext_gnu_old_style_field_designator);
+
+      Designation &D = Designations.CreateDesignation(InitNum);
+      D.AddDesignator(Designator::getField(Tok.getIdentifierInfo()));
+      ConsumeToken(); // Eat the identifier.
+      
+      assert(Tok.is(tok::colon) && "NextToken() not working properly!");
+      ConsumeToken();
+      return ParseInitializer();
+    }
+    
+    // Otherwise, parse the assignment-expression.
+    return ParseAssignmentExpression();
+  }
+  
+  
   // Parse each designator in the designator list until we find an initializer.
   while (1) {
     switch (Tok.getKind()) {
@@ -138,25 +164,6 @@
       MatchRHSPunctuation(tok::r_square, StartLoc);
       break;
     }
-    case tok::identifier: {
-      // Due to the GNU "designation: identifier ':'" extension, we don't know
-      // whether something starting with an identifier is an
-      // assignment-expression or if it is an old-style structure field
-      // designator.
-      // TODO: Check that this is the first designator.
-      
-      // If this is the gross GNU extension, handle it now.
-      if (NextToken().is(tok::colon)) {
-        Diag(Tok, diag::ext_gnu_old_style_field_designator);
-        ConsumeToken(); // The identifier.
-        assert(Tok.is(tok::colon) && "NextToken() not working properly!");
-        ConsumeToken();
-        return ParseInitializer();
-      }
-      
-      // Otherwise, parse the assignment-expression.
-      return ParseAssignmentExpression();
-    }
     }
   }
 }
@@ -174,6 +181,8 @@
 ///         initializer-list ',' designation[opt] initializer
 ///
 Parser::ExprResult Parser::ParseInitializer() {
+  // TODO: Split this up into ParseInitializer + ParseBraceInitializer, make
+  // ParseInitializer inline so that the non-brace case is short-cut.
   if (Tok.isNot(tok::l_brace))
     return ParseAssignmentExpression();
 
@@ -186,7 +195,15 @@
     // Match the '}'.
     return Actions.ActOnInitList(LBraceLoc, 0, 0, ConsumeBrace());
   }
+  
+  /// InitExprs - This is the actual list of expressions contained in the
+  /// initializer.
   llvm::SmallVector<ExprTy*, 8> InitExprs;
+  
+  /// ExprDesignators - For each initializer, keep track of the designator that
+  /// was specified for it, if any.
+  InitListDesignations InitExprDesignations(Actions);
+
   bool InitExprsOk = true;
   
   while (1) {
@@ -198,7 +215,8 @@
     if (!MayBeDesignationStart(Tok.getKind()))
       SubElt = ParseInitializer();
     else
-      SubElt = ParseInitializerWithPotentialDesignator();
+      SubElt = ParseInitializerWithPotentialDesignator(InitExprDesignations,
+                                                       InitExprs.size());
 
     // If we couldn't parse the subelement, bail out.
     if (!SubElt.isInvalid) {
@@ -220,7 +238,7 @@
     // If we don't have a comma continued list, we're done.
     if (Tok.isNot(tok::comma)) break;
     
-    // FIXME: save comma locations.
+    // TODO: save comma locations if some client cares.
     ConsumeToken();
     
     // Handle trailing comma.
@@ -230,7 +248,7 @@
     return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(), 
                                  ConsumeBrace());
   
-  // Delete any parsed subexpressions.
+  // On error, delete any parsed subexpressions.
   for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
     Actions.DeleteExpr(InitExprs[i]);