Refactor the parsing of declarations so that template declarations can
parse just a single declaration and provide a reasonable diagnostic
when the "only one declarator per template declaration" rule is
violated. This eliminates some ugly, ugly hackery where we used to
require thatn the layout of a DeclGroup of a single element be the
same as the layout of a single declaration.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71596 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index b3c2d8c..9d7d9d4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -233,8 +233,14 @@
                                                 SourceLocation &DeclEnd) {
   DeclPtrTy SingleDecl;
   switch (Tok.getKind()) {
-  case tok::kw_export:
   case tok::kw_template:
+    if (NextToken().isNot(tok::less)) {
+      SingleDecl = ParseExplicitInstantiation(DeclEnd);
+      break;
+    }
+    // Fall through for template declarations and specializations
+
+  case tok::kw_export:
     SingleDecl = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd);
     break;
   case tok::kw_namespace:
@@ -302,15 +308,11 @@
   return DG;
 }
 
-
-/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
-/// parsing 'declaration-specifiers declarator'.  This method is split out this
-/// way to handle the ambiguity between top-level function-definitions and
-/// declarations.
+/// \brief Parse 'declaration' after parsing 'declaration-specifiers
+/// declarator'. This method parses the remainder of the declaration
+/// (including any attributes or initializer, among other things) and
+/// finalizes the declaration.
 ///
-///       init-declarator-list: [C99 6.7]
-///         init-declarator
-///         init-declarator-list ',' init-declarator
 ///       init-declarator: [C99 6.7]
 ///         declarator
 ///         declarator '=' initializer
@@ -327,6 +329,81 @@
 /// According to the standard grammar, =default and =delete are function
 /// definitions, but that definitely doesn't fit with the parser here.
 ///
+Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) {
+  // If a simple-asm-expr is present, parse it.
+  if (Tok.is(tok::kw_asm)) {
+    SourceLocation Loc;
+    OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+    if (AsmLabel.isInvalid()) {
+      SkipUntil(tok::semi, true, true);
+      return DeclPtrTy();
+    }
+    
+    D.setAsmLabel(AsmLabel.release());
+    D.SetRangeEnd(Loc);
+  }
+  
+  // If attributes are present, parse them.
+  if (Tok.is(tok::kw___attribute)) {
+    SourceLocation Loc;
+    AttributeList *AttrList = ParseAttributes(&Loc);
+    D.AddAttributes(AttrList, Loc);
+  }
+  
+  // Inform the current actions module that we just parsed this declarator.
+  DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D);
+  
+  // Parse declarator '=' initializer.
+  if (Tok.is(tok::equal)) {
+    ConsumeToken();
+    if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
+      SourceLocation DelLoc = ConsumeToken();
+      Actions.SetDeclDeleted(ThisDecl, DelLoc);
+    } else {
+      OwningExprResult Init(ParseInitializer());
+      if (Init.isInvalid()) {
+        SkipUntil(tok::semi, true, true);
+        return DeclPtrTy();
+      }
+      Actions.AddInitializerToDecl(ThisDecl, move(Init));
+    }
+  } else if (Tok.is(tok::l_paren)) {
+    // Parse C++ direct initializer: '(' expression-list ')'
+    SourceLocation LParenLoc = ConsumeParen();
+    ExprVector Exprs(Actions);
+    CommaLocsTy CommaLocs;
+
+    if (ParseExpressionList(Exprs, CommaLocs)) {
+      SkipUntil(tok::r_paren);
+    } else {
+      // Match the ')'.
+      SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+      assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
+             "Unexpected number of commas!");
+      Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
+                                            move_arg(Exprs),
+                                            &CommaLocs[0], RParenLoc);
+    }
+  } else {
+    Actions.ActOnUninitializedDecl(ThisDecl);
+  }
+
+  return ThisDecl;
+}
+
+/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
+/// parsing 'declaration-specifiers declarator'.  This method is split out this
+/// way to handle the ambiguity between top-level function-definitions and
+/// declarations.
+///
+///       init-declarator-list: [C99 6.7]
+///         init-declarator
+///         init-declarator-list ',' init-declarator
+///
+/// According to the standard grammar, =default and =delete are function
+/// definitions, but that definitely doesn't fit with the parser here.
+///
 Parser::DeclGroupPtrTy Parser::
 ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
   // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
@@ -336,65 +413,9 @@
   // At this point, we know that it is not a function definition.  Parse the
   // rest of the init-declarator-list.
   while (1) {
-    // If a simple-asm-expr is present, parse it.
-    if (Tok.is(tok::kw_asm)) {
-      SourceLocation Loc;
-      OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
-      if (AsmLabel.isInvalid()) {
-        SkipUntil(tok::semi, true, true);
-        return DeclGroupPtrTy();
-      }
-
-      D.setAsmLabel(AsmLabel.release());
-      D.SetRangeEnd(Loc);
-    }
-    
-    // If attributes are present, parse them.
-    if (Tok.is(tok::kw___attribute)) {
-      SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
-      D.AddAttributes(AttrList, Loc);
-    }
-
-    // Inform the current actions module that we just parsed this declarator.
-    DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D);
-    DeclsInGroup.push_back(ThisDecl);
-
-    // Parse declarator '=' initializer.
-    if (Tok.is(tok::equal)) {
-      ConsumeToken();
-      if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
-        SourceLocation DelLoc = ConsumeToken();
-        Actions.SetDeclDeleted(ThisDecl, DelLoc);
-      } else {
-        OwningExprResult Init(ParseInitializer());
-        if (Init.isInvalid()) {
-          SkipUntil(tok::semi, true, true);
-          return DeclGroupPtrTy();
-        }
-        Actions.AddInitializerToDecl(ThisDecl, move(Init));
-      }
-    } else if (Tok.is(tok::l_paren)) {
-      // Parse C++ direct initializer: '(' expression-list ')'
-      SourceLocation LParenLoc = ConsumeParen();
-      ExprVector Exprs(Actions);
-      CommaLocsTy CommaLocs;
-
-      if (ParseExpressionList(Exprs, CommaLocs)) {
-        SkipUntil(tok::r_paren);
-      } else {
-        // Match the ')'.
-        SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
-        assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
-               "Unexpected number of commas!");
-        Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
-                                              move_arg(Exprs),
-                                              &CommaLocs[0], RParenLoc);
-      }
-    } else {
-      Actions.ActOnUninitializedDecl(ThisDecl);
-    }
+    DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+    if (ThisDecl.get())
+      DeclsInGroup.push_back(ThisDecl);
     
     // If we don't have a comma, it is either the end of the list (a ';') or an
     // error, bail out.