Push DeclGroup much farther throughout the compiler.  Now the various
productions (except the already broken ObjC cases like @class X,Y;) in 
the parser that can produce more than one Decl return a DeclGroup instead
of a Decl, etc.

This allows elimination of the Decl::NextDeclarator field, and exposes
various clients that should look at all decls in a group, but which were
only looking at one (such as the dumper, printer, etc).  These have been
fixed.

Still TODO:

1) there are some FIXME's in the code about potentially using
DeclGroup for better location info.
2) ParseObjCAtDirectives should return a DeclGroup due to @class etc.
3) I'm not sure what is going on with StmtIterator.cpp, or if it can
   be radically simplified now.
4) I put a truly horrible hack in ParseTemplate.cpp.

I plan to bring up #3/4 on the mailing list, but don't plan to tackle
#1/2 in the short term.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68002 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 049228f..f31aef6 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -144,7 +144,7 @@
 /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
 /// popped.
 Action::DeclPtrTy
-MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup) {
+MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) {
   IdentifierInfo *II = D.getIdentifier();
   
   // If there is no identifier associated with this declarator, bail out.
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index e139cf9..45eaa74 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -27,8 +27,7 @@
   assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && 
          "Current token not a '{' or ':'!");
 
-  DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0,
-                                                   DeclPtrTy());
+  DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);
 
   // Consume the tokens and store them for later parsing.
 
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 5a8b2b8..1f8522f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -228,27 +228,36 @@
 /// [C++0x] static_assert-declaration
 ///         others... [FIXME]
 ///
-Parser::DeclPtrTy Parser::ParseDeclaration(unsigned Context) {
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context) {
+  DeclPtrTy SingleDecl;
   switch (Tok.getKind()) {
   case tok::kw_export:
   case tok::kw_template:
-    return ParseTemplateDeclarationOrSpecialization(Context);
+    SingleDecl = ParseTemplateDeclarationOrSpecialization(Context);
+    break;
   case tok::kw_namespace:
-    return ParseNamespace(Context);
+    SingleDecl = ParseNamespace(Context);
+    break;
   case tok::kw_using:
-    return ParseUsingDirectiveOrDeclaration(Context);
+    SingleDecl = ParseUsingDirectiveOrDeclaration(Context);
+    break;
   case tok::kw_static_assert:
-    return ParseStaticAssertDeclaration();
+    SingleDecl = ParseStaticAssertDeclaration();
+    break;
   default:
     return ParseSimpleDeclaration(Context);
   }
+  
+  // This routine returns a DeclGroup, if the thing we parsed only contains a
+  // single decl, convert it now.
+  return Actions.ConvertDeclToDeclGroup(SingleDecl);
 }
 
 ///       simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
 ///         declaration-specifiers init-declarator-list[opt] ';'
 ///[C90/C++]init-declarator-list ';'                             [TODO]
 /// [OMP]   threadprivate-directive                              [TODO]
-Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
   ParseDeclarationSpecifiers(DS);
@@ -257,7 +266,8 @@
   // declaration-specifiers init-declarator-list[opt] ';'
   if (Tok.is(tok::semi)) {
     ConsumeToken();
-    return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
   
   Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
@@ -291,12 +301,11 @@
 /// According to the standard grammar, =default and =delete are function
 /// definitions, but that definitely doesn't fit with the parser here.
 ///
-Parser::DeclPtrTy Parser::
+Parser::DeclGroupPtrTy Parser::
 ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
-  
-  // Declarators may be grouped together ("int X, *Y, Z();").  Provide info so
-  // that they can be chained properly if the actions want this.
-  Parser::DeclPtrTy LastDeclInGroup;
+  // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
+  // that we parse together here.
+  llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
   
   // At this point, we know that it is not a function definition.  Parse the
   // rest of the init-declarator-list.
@@ -307,7 +316,7 @@
       OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
       if (AsmLabel.isInvalid()) {
         SkipUntil(tok::semi);
-        return DeclPtrTy();
+        return DeclGroupPtrTy();
       }
 
       D.setAsmLabel(AsmLabel.release());
@@ -322,21 +331,22 @@
     }
 
     // Inform the current actions module that we just parsed this declarator.
-    LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup);
+    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(LastDeclInGroup, DelLoc);
+        Actions.SetDeclDeleted(ThisDecl, DelLoc);
       } else {
         OwningExprResult Init(ParseInitializer());
         if (Init.isInvalid()) {
           SkipUntil(tok::semi);
-          return DeclPtrTy();
+          return DeclGroupPtrTy();
         }
-        Actions.AddInitializerToDecl(LastDeclInGroup, move(Init));
+        Actions.AddInitializerToDecl(ThisDecl, move(Init));
       }
     } else if (Tok.is(tok::l_paren)) {
       // Parse C++ direct initializer: '(' expression-list ')'
@@ -355,12 +365,12 @@
       if (!InvalidExpr) {
         assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
                "Unexpected number of commas!");
-        Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
+        Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
                                               move_arg(Exprs),
                                               &CommaLocs[0], RParenLoc);
       }
     } else {
-      Actions.ActOnUninitializedDecl(LastDeclInGroup);
+      Actions.ActOnUninitializedDecl(ThisDecl);
     }
     
     // If we don't have a comma, it is either the end of the list (a ';') or an
@@ -395,23 +405,26 @@
     // for(is key; in keys) is error.
     if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) {
       Diag(Tok, diag::err_parse_error);
-      return DeclPtrTy();
+      return DeclGroupPtrTy();
     }
-    return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+    
+    return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+                                           DeclsInGroup.size());
   }
   
   // If this is an ObjC2 for-each loop, this is a successful declarator
   // parse.  The syntax for these looks like:
   // 'for' '(' declaration 'in' expr ')' statement
   if (D.getContext() == Declarator::ForContext && isTokIdentifier_in())
-    return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+    return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+                                           DeclsInGroup.size());
 
   Diag(Tok, diag::err_parse_error);
   // Skip to end of block or statement
   SkipUntil(tok::r_brace, true, true);
   if (Tok.is(tok::semi))
     ConsumeToken();
-  return DeclPtrTy();
+  return DeclGroupPtrTy();
 }
 
 /// ParseSpecifierQualifierList
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index c50a033..37a460c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -663,14 +663,17 @@
 ///       constant-initializer:
 ///         '=' constant-expression
 ///
-Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
+void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
   // static_assert-declaration
-  if (Tok.is(tok::kw_static_assert))
-    return ParseStaticAssertDeclaration();
+  if (Tok.is(tok::kw_static_assert)) {
+    ParseStaticAssertDeclaration();
+    return;
+  }
       
-  if (Tok.is(tok::kw_template))
-    return ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext,
-                                                    AS);
+  if (Tok.is(tok::kw_template)) {
+    ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, AS);
+    return;
+  }
 
   // Handle:  member-declaration ::= '__extension__' member-declaration
   if (Tok.is(tok::kw___extension__)) {
@@ -692,14 +695,15 @@
     // class-specifier or an enum-specifier or in a friend declaration.
     // FIXME: Friend declarations.
     switch (DS.getTypeSpecType()) {
-      case DeclSpec::TST_struct:
-      case DeclSpec::TST_union:
-      case DeclSpec::TST_class:
-      case DeclSpec::TST_enum:
-        return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
-      default:
-        Diag(DSStart, diag::err_no_declarators);
-        return DeclPtrTy();
+    case DeclSpec::TST_struct:
+    case DeclSpec::TST_union:
+    case DeclSpec::TST_class:
+    case DeclSpec::TST_enum:
+      Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+      return;
+    default:
+      Diag(DSStart, diag::err_no_declarators);
+      return;
     }
   }
 
@@ -714,7 +718,7 @@
       SkipUntil(tok::r_brace, true);
       if (Tok.is(tok::semi))
         ConsumeToken();
-      return DeclPtrTy();
+      return;
     }
 
     // function-definition:
@@ -724,7 +728,7 @@
         Diag(Tok, diag::err_func_def_no_params);
         ConsumeBrace();
         SkipUntil(tok::r_brace, true);
-        return DeclPtrTy();
+        return;
       }
 
       if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -734,10 +738,11 @@
         // assumes the declarator represents a function, not a typedef.
         ConsumeBrace();
         SkipUntil(tok::r_brace, true);
-        return DeclPtrTy();
+        return;
       }
 
-      return ParseCXXInlineMethodDef(AS, DeclaratorInfo);
+      ParseCXXInlineMethodDef(AS, DeclaratorInfo);
+      return;
     }
   }
 
@@ -745,7 +750,7 @@
   //   member-declarator
   //   member-declarator-list ',' member-declarator
 
-  DeclPtrTy LastDeclInGroup;
+  llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
   OwningExprResult BitfieldSize(Actions);
   OwningExprResult Init(Actions);
 
@@ -784,14 +789,14 @@
     }
 
     // NOTE: If Sema is the Action module and declarator is an instance field,
-    // this call will *not* return the created decl; LastDeclInGroup will be
-    // returned instead.
+    // this call will *not* return the created decl; It will return null.
     // See Sema::ActOnCXXMemberDeclarator for details.
-    LastDeclInGroup = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
-                                                       DeclaratorInfo,
-                                                       BitfieldSize.release(),
-                                                       Init.release(),
-                                                       LastDeclInGroup);
+    DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
+                                                          DeclaratorInfo,
+                                                          BitfieldSize.release(),
+                                                          Init.release());
+    if (ThisDecl)
+      DeclsInGroup.push_back(ThisDecl);
 
     if (DeclaratorInfo.isFunctionDeclarator() &&
         DeclaratorInfo.getDeclSpec().getStorageClassSpec() 
@@ -807,7 +812,7 @@
             // Push this method onto the stack of late-parsed method
             // declarations.
             getCurTopClassStack().MethodDecls.push_back(
-                                   LateParsedMethodDeclaration(LastDeclInGroup));
+                                   LateParsedMethodDeclaration(ThisDecl));
             LateMethod = &getCurTopClassStack().MethodDecls.back();
 
             // Add all of the parameters prior to this one (they don't
@@ -853,8 +858,9 @@
 
   if (Tok.is(tok::semi)) {
     ConsumeToken();
-    // Reverse the chain list.
-    return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+    Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+                                    DeclsInGroup.size());
+    return;
   }
 
   Diag(Tok, diag::err_expected_semi_decl_list);
@@ -862,7 +868,7 @@
   SkipUntil(tok::r_brace, true, true);
   if (Tok.is(tok::semi))
     ConsumeToken();
-  return DeclPtrTy();
+  return;
 }
 
 /// ParseCXXMemberSpecification - Parse the class definition.
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 8ff1944..05c919c 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -215,7 +215,7 @@
                                         tok::ObjCKeywordKind contextKey) {
   llvm::SmallVector<DeclPtrTy, 32> allMethods;
   llvm::SmallVector<DeclPtrTy, 16> allProperties;
-  llvm::SmallVector<DeclPtrTy, 8> allTUVariables;
+  llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
   
   SourceLocation AtEndLoc;
@@ -253,8 +253,7 @@
       
       // FIXME: as the name implies, this rule allows function definitions.
       // We could pass a flag or check for functions during semantic analysis.
-      DeclPtrTy VFDecl = ParseDeclarationOrFunctionDefinition();
-      allTUVariables.push_back(VFDecl);
+      allTUVariables.push_back(ParseDeclarationOrFunctionDefinition());
       continue;
     }
     
@@ -359,13 +358,9 @@
   // Insert collected methods declarations into the @interface object.
   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
   Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
-                     allMethods.empty() ? 0 : &allMethods[0],
-                     allMethods.size(), 
-                     allProperties.empty() ? 0 : &allProperties[0],
-                     allProperties.size(),
-                     allTUVariables.empty() ? 0 :
-                     &allTUVariables[0],
-                     allTUVariables.size());
+                     &allMethods[0], allMethods.size(), 
+                     &allProperties[0], allProperties.size(),
+                     &allTUVariables[0], allTUVariables.size());
 }
 
 ///   Parse property attribute declarations.
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index b996c74..b1a32de 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -101,7 +101,7 @@
   default: {
     if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
       SourceLocation DeclStart = Tok.getLocation();
-      DeclPtrTy Decl = ParseDeclaration(Declarator::BlockContext);
+      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext);
       // FIXME: Pass in the right location for the end of the declstmt.
       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclStart);
     }
@@ -444,7 +444,7 @@
       if (isDeclarationStatement()) {
         // FIXME: Save the __extension__ on the decl as a node somehow.
         SourceLocation DeclStart = Tok.getLocation();
-        DeclPtrTy Res = ParseDeclaration(Declarator::BlockContext);
+        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext);
         // FIXME: Pass in the right location for the end of the declstmt.
         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart);
       } else {
@@ -912,10 +912,9 @@
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
 
     SourceLocation DeclStart = Tok.getLocation();
-    DeclPtrTy aBlockVarDecl = ParseSimpleDeclaration(Declarator::ForContext);
+    DeclGroupPtrTy VarDecls = ParseSimpleDeclaration(Declarator::ForContext);
     // FIXME: Pass in the right location for the end of the declstmt.
-    FirstPart = Actions.ActOnDeclStmt(aBlockVarDecl, DeclStart,
-                                          DeclStart);
+    FirstPart = Actions.ActOnDeclStmt(VarDecls, DeclStart, DeclStart);
     if ((ForEach = isTokIdentifier_in())) {
       ConsumeToken(); // consume 'in'
       SecondPart = ParseExpression();
@@ -929,12 +928,10 @@
 
     if (Tok.is(tok::semi)) {
       ConsumeToken();
-    }
-    else if ((ForEach = isTokIdentifier_in())) {
+    } else if ((ForEach = isTokIdentifier_in())) {
       ConsumeToken(); // consume 'in'
       SecondPart = ParseExpression();
-    }
-    else {
+    } else {
       if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
       SkipUntil(tok::semi);
     }
@@ -995,11 +992,11 @@
     return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
                               move(SecondPart), move(ThirdPart),
                               RParenLoc, move(Body));
-  else
-    return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
-                                              move(FirstPart),
-                                              move(SecondPart),
-                                              RParenLoc, move(Body));
+  
+  return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
+                                            move(FirstPart),
+                                            move(SecondPart),
+                                            RParenLoc, move(Body));
 }
 
 /// ParseGotoStatement
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 29b8a14..b962cbf 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -94,7 +94,12 @@
   } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
 
   // Parse the actual template declaration.
-  return ParseDeclarationOrFunctionDefinition(&ParamLists, AS);
+
+  // FIXME: This accepts template<typename x> int y;
+  // FIXME: Converting DeclGroupPtr to DeclPtr like this is an insanely gruesome
+  // hack, will bring up on cfe-dev.
+  DeclGroupPtrTy DG = ParseDeclarationOrFunctionDefinition(&ParamLists, AS);
+  return DeclPtrTy::make(DG.get());
 }
 
 /// ParseTemplateParameters - Parses a template-parameter-list enclosed in
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 00a3349..56f922d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -324,8 +324,8 @@
 
 /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
 /// action tells us to.  This returns true if the EOF was encountered.
-bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) {
-  Result = DeclPtrTy();
+bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+  Result = DeclGroupPtrTy();
   if (Tok.is(tok::eof)) {
     Actions.ActOnEndOfTranslationUnit();
     return true;
@@ -342,7 +342,7 @@
 void Parser::ParseTranslationUnit() {
   Initialize();
 
-  DeclPtrTy Res;
+  DeclGroupPtrTy Res;
   while (!ParseTopLevelDecl(Res))
     /*parse them all*/;
   
@@ -368,20 +368,21 @@
 /// [GNU] asm-definition:
 ///         simple-asm-expr ';'
 ///
-Parser::DeclPtrTy Parser::ParseExternalDeclaration() {
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
+  DeclPtrTy SingleDecl;
   switch (Tok.getKind()) {
   case tok::semi:
     Diag(Tok, diag::ext_top_level_semi);
     ConsumeToken();
     // TODO: Invoke action for top-level semicolon.
-    return DeclPtrTy();
+    return DeclGroupPtrTy();
   case tok::r_brace:
     Diag(Tok, diag::err_expected_external_declaration);
     ConsumeBrace();
-    return DeclPtrTy();
+    return DeclGroupPtrTy();
   case tok::eof:
     Diag(Tok, diag::err_expected_external_declaration);
-    return DeclPtrTy();
+    return DeclGroupPtrTy();
   case tok::kw___extension__: {
     // __extension__ silences extension warnings in the subexpression.
     ExtensionRAIIObject O(Diags);  // Use RAII to do this.
@@ -394,20 +395,26 @@
     ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
                      "top-level asm block");
 
-    if (!Result.isInvalid())
-      return Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
-    return DeclPtrTy();
+    if (Result.isInvalid())
+      return DeclGroupPtrTy();
+    SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
+    break;
   }
   case tok::at:
-    // @ is not a legal token unless objc is enabled, no need to check.
-    return ParseObjCAtDirectives();
+    // @ is not a legal token unless objc is enabled, no need to check for ObjC.
+    /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like
+    /// @class foo, bar;
+    SingleDecl = ParseObjCAtDirectives();
+    break;
   case tok::minus:
   case tok::plus:
-    if (getLang().ObjC1)
-      return ParseObjCMethodDefinition();
-    Diag(Tok, diag::err_expected_external_declaration);
-    ConsumeToken();
-    return DeclPtrTy();
+    if (!getLang().ObjC1) {
+      Diag(Tok, diag::err_expected_external_declaration);
+      ConsumeToken();
+      return DeclGroupPtrTy();
+    }
+    SingleDecl = ParseObjCMethodDefinition();
+    break;
   case tok::kw_using:
   case tok::kw_namespace:
   case tok::kw_typedef:
@@ -420,6 +427,10 @@
     // We can't tell whether this is a function-definition or declaration yet.
     return ParseDeclarationOrFunctionDefinition();
   }
+  
+  // This routine returns a DeclGroup, if the thing we parsed only contains a
+  // single decl, convert it now.
+  return Actions.ConvertDeclToDeclGroup(SingleDecl);
 }
 
 /// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
@@ -438,7 +449,7 @@
 /// [!C99]  init-declarator-list ';'                   [TODO: warn in c99 mode]
 /// [OMP]   threadprivate-directive                              [TODO]
 ///
-Parser::DeclPtrTy
+Parser::DeclGroupPtrTy
 Parser::ParseDeclarationOrFunctionDefinition(
                                   TemplateParameterLists *TemplateParams,
                                   AccessSpecifier AS) {
@@ -450,7 +461,8 @@
   // declaration-specifiers init-declarator-list[opt] ';'
   if (Tok.is(tok::semi)) {
     ConsumeToken();
-    return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
   // ObjC2 allows prefix attributes on class interfaces and protocols.
@@ -462,14 +474,18 @@
         !Tok.isObjCAtKeyword(tok::objc_protocol)) {
       Diag(Tok, diag::err_objc_unexpected_attr);
       SkipUntil(tok::semi); // FIXME: better skip?
-      return DeclPtrTy();
+      return DeclGroupPtrTy();
     }
     const char *PrevSpec = 0;
     if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec))
       Diag(AtLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
+    
+    DeclPtrTy TheDecl;
     if (Tok.isObjCAtKeyword(tok::objc_protocol))
-      return ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
-    return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+      TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
+    else
+      TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
   // If the declspec consisted only of 'extern' and we have a string
@@ -477,8 +493,10 @@
   // 'extern "C"'.
   if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
       DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
-      DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier)
-    return ParseLinkage(Declarator::FileContext);
+      DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+    DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
+  }
 
   // Parse the first declarator.
   Declarator DeclaratorInfo(DS, Declarator::FileContext);
@@ -489,7 +507,7 @@
     SkipUntil(tok::r_brace, true, true);
     if (Tok.is(tok::semi))
       ConsumeToken();
-    return DeclPtrTy();
+    return DeclGroupPtrTy();
   }
 
   // If the declarator is the start of a function definition, handle it.
@@ -500,8 +518,12 @@
       Tok.is(tok::kw___attribute) ||  // int X() __attr__ -> not a function def
       (getLang().CPlusPlus &&
        Tok.is(tok::l_paren)) ) {      // int X(0) -> not a function def [C++]
-    // FALL THROUGH.
-  } else if (DeclaratorInfo.isFunctionDeclarator() &&
+    // Parse the init-declarator-list for a normal declaration.
+    return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+  }
+  
+  
+  if (DeclaratorInfo.isFunctionDeclarator() &&
              (Tok.is(tok::l_brace) ||             // int X() {}
               (!getLang().CPlusPlus &&
                isDeclarationSpecifier()) ||   // int X(f) int f; {}
@@ -519,20 +541,18 @@
       } else {
         SkipUntil(tok::semi);
       }
-      return DeclPtrTy();
+      return DeclGroupPtrTy();
     }
-    return ParseFunctionDefinition(DeclaratorInfo);
-  } else {
-    if (DeclaratorInfo.isFunctionDeclarator())
-      Diag(Tok, diag::err_expected_fn_body);
-    else
-      Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
-    SkipUntil(tok::semi);
-    return DeclPtrTy();
+    DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo);
+    return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
-
-  // Parse the init-declarator-list for a normal declaration.
-  return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+  
+  if (DeclaratorInfo.isFunctionDeclarator())
+    Diag(Tok, diag::err_expected_fn_body);
+  else
+    Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
+  SkipUntil(tok::semi);
+  return DeclGroupPtrTy();
 }
 
 /// ParseFunctionDefinition - We parsed and verified that the specified