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/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 70daebf..cafeecb 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -16,7 +16,7 @@
 
 namespace clang {
   class ASTContext;
-  class Decl;
+  class DeclGroupRef;
   class TagDecl;
   class HandleTagDeclDefinition;
   
@@ -25,7 +25,7 @@
 /// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
 class ASTConsumer {
 public:
-  virtual ~ASTConsumer();
+  virtual ~ASTConsumer() {}
   
   /// Initialize - This is called to initialize the consumer, providing the
   /// ASTContext.
@@ -35,7 +35,7 @@
   ///  called by the parser to process every top-level Decl*. Note that D can
   ///  be the head of a chain of Decls (e.g. for `int a, b` the chain will have
   ///  two elements). Use Decl::getNextDeclarator() to walk the chain.
-  virtual void HandleTopLevelDecl(Decl *D) {}
+  virtual void HandleTopLevelDecl(DeclGroupRef D);
   
   /// HandleTranslationUnit - This method is called when the ASTs for entire
   ///  translation unit have been parsed.
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index aaec16e..abdb10d 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -100,16 +100,9 @@
   };
     
 private:
-  /// NextDeclarator - If this decl was part of a multi-declarator declaration,
-  /// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
-  Decl *NextDeclarator;
-  
   /// NextDeclInContext - The next declaration within the same lexical
   /// DeclContext. These pointers form the linked list that is
   /// traversed via DeclContext's decls_begin()/decls_end().
-  /// FIXME: If NextDeclarator is non-NULL, will it always be the same
-  /// as NextDeclInContext? If so, we can use a
-  /// PointerIntPair<Decl*, 1> to make Decl smaller.
   Decl *NextDeclInContext;
 
   friend class DeclContext;
@@ -176,8 +169,7 @@
   friend class CXXClassMemberWrapper;
 
   Decl(Kind DK, DeclContext *DC, SourceLocation L) 
-    : NextDeclarator(0), NextDeclInContext(0), 
-      DeclCtx(DC), 
+    : NextDeclInContext(0), DeclCtx(DC), 
       Loc(L), DeclKind(DK), InvalidDecl(0),
       HasAttrs(false), Implicit(false), 
       IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
@@ -276,13 +268,6 @@
   
   void setLexicalDeclContext(DeclContext *DC);
 
-  /// getNextDeclarator - If this decl was part of a multi-declarator
-  /// declaration, such as "int X, Y, *Z;" this returns the decl for the next
-  /// declarator.  Otherwise it returns null.
-  Decl *getNextDeclarator() { return NextDeclarator; }
-  const Decl *getNextDeclarator() const { return NextDeclarator; }
-  void setNextDeclarator(Decl *N) { NextDeclarator = N; }
-  
   // isDefinedOutsideFunctionOrMethod - This predicate returns true if this
   // scoped decl is defined outside the current function or method.  This is
   // roughly global variables and functions, but also handles enums (which could
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index b1c2575..1a85463 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -34,7 +34,7 @@
   DeclGroup(unsigned numdecls, Decl** decls);
 
 public:
-  static DeclGroup* Create(ASTContext& C, unsigned numdecls, Decl** decls);
+  static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
   void Destroy(ASTContext& C);
 
   unsigned size() const { return NumDecls; }
@@ -57,6 +57,8 @@
 };
     
 class DeclGroupRef {
+  // Note this is not a PointerIntPair because we need the address of the
+  // non-group case to be valid as a Decl** for iteration.
   enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };  
   Decl* D;
 
@@ -71,6 +73,14 @@
   explicit DeclGroupRef(DeclGroup* dg)
     : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
   
+  static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+    if (NumDecls == 0)
+      return DeclGroupRef();
+    if (NumDecls == 1)
+      return DeclGroupRef(Decls[0]);
+    return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
+  }
+  
   typedef Decl** iterator;
   typedef Decl* const * const_iterator;
   
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 84023d6..a58fc81 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -71,6 +71,7 @@
   typedef ActionBase::ExprTy ExprTy;
   typedef ActionBase::StmtTy StmtTy;
   typedef OpaquePtr<0> DeclPtrTy;
+  typedef OpaquePtr<1> DeclGroupPtrTy;
   typedef void TypeTy;  // FIXME: Change TypeTy to use OpaquePtr<1>.
   typedef void AttrTy;
   typedef void BaseTy;
@@ -130,6 +131,13 @@
   // Declaration Tracking Callbacks.
   //===--------------------------------------------------------------------===//
   
+  /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
+  /// needs a decl group, it calls this to convert between the two
+  /// representations.
+  virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
+    return DeclGroupPtrTy();
+  }
+  
   /// getTypeName - Return non-null if the specified identifier is a type name
   /// in the current scope.
   /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
@@ -210,11 +218,7 @@
   /// 'Init' specifies the initializer if any.  This is for things like:
   /// "int X = 4" or "typedef int foo".
   ///
-  /// LastInGroup is non-null for cases where one declspec has multiple
-  /// declarators on it.  For example in 'int A, B', ActOnDeclarator will be
-  /// called with LastInGroup=A when invoked for B.
-  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
-                                    DeclPtrTy LastInGroup) {
+  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
     return DeclPtrTy();
   }
 
@@ -253,10 +257,12 @@
 
   /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
   /// gives the actions implementation a chance to process the group as a whole.
-  virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group) {
-    return Group;
+  virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+                                                 unsigned NumDecls) {
+    return DeclGroupPtrTy();
   }
 
+  
   /// @brief Indicates that all K&R-style parameter declarations have
   /// been parsed prior to a function definition.
   /// @param S  The function prototype scope.
@@ -270,7 +276,7 @@
   virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
     // Default to ActOnDeclarator.
     return ActOnStartOfFunctionDef(FnBodyScope,
-                                   ActOnDeclarator(FnBodyScope, D,DeclPtrTy()));
+                                   ActOnDeclarator(FnBodyScope, D));
   }
 
   /// ActOnStartOfFunctionDef - This is called at the start of a function
@@ -415,7 +421,8 @@
                                              bool isStmtExpr) {
     return StmtEmpty();
   }
-  virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,SourceLocation StartLoc,
+  virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+                                         SourceLocation StartLoc,
                                          SourceLocation EndLoc) {
     return StmtEmpty();
   }
@@ -1041,8 +1048,7 @@
   virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
                                              Declarator &D,
                                              ExprTy *BitfieldWidth,
-                                             ExprTy *Init,
-                                             DeclPtrTy LastInGroup) {
+                                             ExprTy *Init) {
     return DeclPtrTy();
   }
 
@@ -1408,9 +1414,8 @@
                           unsigned allNum = 0,
                           DeclPtrTy *allProperties = 0, 
                           unsigned pNum = 0,
-                          DeclPtrTy *allTUVars = 0,
+                          DeclGroupPtrTy *allTUVars = 0,
                           unsigned tuvNum = 0) {
-    return;
   }
   // ActOnProperty - called to build one property AST
   virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
@@ -1570,8 +1575,7 @@
   /// ActOnDeclarator - If this is a typedef declarator, we modify the
   /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
   /// popped.
-  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
-                                    DeclPtrTy LastInGroup);
+  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D);
   
   /// ActOnPopScope - When a scope is popped, if any typedefs are now 
   /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 66058ca..eb82057 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -120,6 +120,7 @@
   typedef Action::ExprTy ExprTy;
   typedef Action::StmtTy StmtTy;
   typedef Action::DeclPtrTy DeclPtrTy;
+  typedef Action::DeclGroupPtrTy DeclGroupPtrTy;
   typedef Action::TypeTy TypeTy;
   typedef Action::BaseTy BaseTy;
   typedef Action::MemInitTy MemInitTy;
@@ -167,7 +168,7 @@
   
   /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if 
   /// the EOF was encountered.
-  bool ParseTopLevelDecl(DeclPtrTy &Result);
+  bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
   
 private:
   //===--------------------------------------------------------------------===//
@@ -547,8 +548,8 @@
 
   //===--------------------------------------------------------------------===//
   // C99 6.9: External Definitions.
-  DeclPtrTy ParseExternalDeclaration();
-  DeclPtrTy ParseDeclarationOrFunctionDefinition(
+  DeclGroupPtrTy ParseExternalDeclaration();
+  DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
             TemplateParameterLists *TemplateParams = 0,
             AccessSpecifier AS = AS_none);
                                                
@@ -807,9 +808,9 @@
   //===--------------------------------------------------------------------===//
   // C99 6.7: Declarations.
   
-  DeclPtrTy ParseDeclaration(unsigned Context);
-  DeclPtrTy ParseSimpleDeclaration(unsigned Context);
-  DeclPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
+  DeclGroupPtrTy ParseDeclaration(unsigned Context);
+  DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context);
+  DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
   DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
   void ParseDeclarationSpecifiers(DeclSpec &DS, 
                                   TemplateParameterLists *TemplateParams = 0,
@@ -1009,7 +1010,7 @@
                            AccessSpecifier AS = AS_none);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    DeclPtrTy TagDecl);
-  DeclPtrTy ParseCXXClassMemberDeclaration(AccessSpecifier AS);
+  void ParseCXXClassMemberDeclaration(AccessSpecifier AS);
   void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
   MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
 
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index 6c44d1a..f37cbde 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -12,7 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTConsumer.h"
-#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
 using namespace clang;
 
-ASTConsumer::~ASTConsumer() {}
+void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index 36a7c2b..64b0399 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -19,13 +19,12 @@
 #include "llvm/Bitcode/Deserialize.h"
 using namespace clang;
 
-DeclGroup* DeclGroup::Create(ASTContext& C, unsigned numdecls, Decl** decls) {
-  assert (numdecls > 0);
-  unsigned size = sizeof(DeclGroup) + sizeof(Decl*) * numdecls;
-  unsigned alignment = llvm::AlignOf<DeclGroup>::Alignment;  
-  void* mem = C.Allocate(size, alignment);
-  new (mem) DeclGroup(numdecls, decls);
-  return static_cast<DeclGroup*>(mem);
+DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+  assert(NumDecls > 1 && "Invalid DeclGroup");
+  unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
+  void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
+  new (Mem) DeclGroup(NumDecls, Decls);
+  return static_cast<DeclGroup*>(Mem);
 }
 
 /// Emit - Serialize a DeclGroup to Bitcode.
@@ -37,9 +36,9 @@
 /// Read - Deserialize a DeclGroup from Bitcode.
 DeclGroup* DeclGroup::Read(llvm::Deserializer& D, ASTContext& C) {
   unsigned NumDecls = (unsigned) D.ReadInt();
-  unsigned size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
+  unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
   unsigned alignment = llvm::AlignOf<DeclGroup>::Alignment;  
-  DeclGroup* DG = (DeclGroup*) C.Allocate(size, alignment);
+  DeclGroup* DG = (DeclGroup*) C.Allocate(Size, alignment);
   new (DG) DeclGroup();
   DG->NumDecls = NumDecls;
   D.BatchReadOwnedPtrs(NumDecls, &(*DG)[0], C);
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 8e3ef08..acaced2 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -39,7 +39,6 @@
   S.EmitInt(Access);
   S.EmitPtr(cast_or_null<Decl>(getDeclContext()));  // From Decl.
   S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext()));  // From Decl.
-  S.EmitPtr(NextDeclarator);
   if (const DeclContext *DC = dyn_cast<const DeclContext>(this))
     DC->EmitOutRec(S);
   
@@ -144,7 +143,6 @@
     D.ReadPtr(MDC->SemanticDC, SemaDCPtrID);
     D.ReadPtr(MDC->LexicalDC, LexicalDCPtrID);
   }
-  D.ReadPtr(Dcl->NextDeclarator);
   if (DeclContext *DC = dyn_cast<DeclContext>(Dcl))
     DC->ReadOutRec(D, C);
   bool OwnsNext = D.ReadBool();
diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp
index 94829c0..20024f5 100644
--- a/lib/AST/StmtIterator.cpp
+++ b/lib/AST/StmtIterator.cpp
@@ -67,12 +67,11 @@
   if (inDecl()) {
     assert (decl);
     
+    // FIXME: SIMPLIFY AWAY.
     if (ImmediateAdvance)
-      decl = decl->getNextDeclarator();
-    
-    for ( ; decl ; decl = decl->getNextDeclarator())
-      if (HandleDecl(decl))
-        return;
+      decl = 0;
+    else if (HandleDecl(decl))
+      return;
   }
   else {
     assert (inDeclGroup());
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index d41f133..896464e 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -60,16 +60,16 @@
                                                *M, *TD, Diags));
     }
     
-    virtual void HandleTopLevelDecl(Decl *D) {
+    virtual void HandleTopLevelDecl(DeclGroupRef DG) {
       // Make sure to emit all elements of a Decl.
-      for (; D; D = D->getNextDeclarator())
-        Builder->EmitTopLevelDecl(D);
+      for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+        Builder->EmitTopLevelDecl(*I);
     }
 
     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
-    /// (e.g. struct, union, enum, class) is completed. This allows the client to
-    /// hack on the type, which can occur at any point in the file (because these
-    /// can be defined in declspecs).
+    /// to (e.g. struct, union, enum, class) is completed. This allows the
+    /// client hack on the type, which can occur at any point in the file
+    /// (because these can be defined in declspecs).
     virtual void HandleTagDeclDefinition(TagDecl *D) {
       Builder->UpdateCompletedType(D);
     }
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
diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp
index 59a04da..4bcb478 100644
--- a/lib/Sema/ParseAST.cpp
+++ b/lib/Sema/ParseAST.cpp
@@ -44,16 +44,14 @@
   
   Consumer->Initialize(Ctx);
   
-  Parser::DeclPtrTy ADecl;
+  Parser::DeclGroupPtrTy ADecl;
   
   while (!P.ParseTopLevelDecl(ADecl)) {  // Not end of file.
     // If we got a null return and something *was* parsed, ignore it.  This
     // is due to a top-level semicolon, an action override, or a parse error
     // skipping something.
-    if (ADecl) {
-      Decl *D = ADecl.getAs<Decl>();      
-      Consumer->HandleTopLevelDecl(D);
-    }
+    if (ADecl)
+      Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
   };
   
   Consumer->HandleTranslationUnit(Ctx);
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0ebccf3..b7903c1 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -328,29 +328,28 @@
   /// an empty string if not.  This is used for pretty crash reporting. 
   virtual std::string getDeclName(DeclPtrTy D);
   
+  DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr);
+
   virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, 
                               Scope *S, const CXXScopeSpec *SS);
-  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
-                                    DeclPtrTy LastInGroup){
-    return ActOnDeclarator(S, D, LastInGroup, false);
+  virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
+    return ActOnDeclarator(S, D, false);
   }
-  DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup,
-                            bool IsFunctionDefinition);
+  DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition);
   void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
                                         Scope *S);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                                    QualType R, Decl* LastDeclarator,
+                                    QualType R,
                                     Decl* PrevDecl, bool& InvalidDecl,
                                     bool &Redeclaration);
   NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                                     QualType R, Decl* LastDeclarator,
+                                     QualType R, 
                                      NamedDecl* PrevDecl, bool& InvalidDecl,
                                      bool &Redeclaration);
   bool CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
                                 bool &Redeclaration);
   NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                                     QualType R, Decl *LastDeclarator,
-                                     NamedDecl* PrevDecl, 
+                                     QualType R, NamedDecl* PrevDecl, 
                                      bool IsFunctionDefinition,
                                      bool& InvalidDecl, bool &Redeclaration);
   bool CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
@@ -367,8 +366,8 @@
   void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit);
   void ActOnUninitializedDecl(DeclPtrTy dcl);
   virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc);
-  virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group);
-
+  virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+                                                 unsigned NumDecls);
   virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D);
   virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D);
   virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D);
@@ -490,8 +489,7 @@
                                 Stmt* ParentCompoundStmt);
 
   /// Subroutines of ActOnDeclarator().
-  TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
-                                Decl *LastDecl);
+  TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
   bool MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
   bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
@@ -1084,7 +1082,7 @@
   virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
                                              MultiStmtArg Elts,
                                              bool isStmtExpr);
-  virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,
+  virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
                                          SourceLocation StartLoc,
                                          SourceLocation EndLoc);
   virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
@@ -1589,8 +1587,7 @@
   virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
                                              Declarator &D,
                                              ExprTy *BitfieldWidth,
-                                             ExprTy *Init,
-                                             DeclPtrTy LastInGroup);
+                                             ExprTy *Init);
 
   virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD,
                                             Scope *S,
@@ -2076,7 +2073,7 @@
   virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
                       DeclPtrTy *allMethods = 0, unsigned allNum = 0,
                       DeclPtrTy *allProperties = 0, unsigned pNum = 0,
-                      DeclPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+                      DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
   
   virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
                                   FieldDeclarator &FD, ObjCDeclSpec &ODS,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f98da95..be9a0e2 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -39,6 +39,10 @@
   return "";
 }
 
+Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
+  return DeclGroupPtrTy::make(DeclGroupRef(Ptr.getAs<Decl>()));
+}
+
 /// \brief If the identifier refers to a type name within this scope,
 /// return the declaration of that type.
 ///
@@ -1235,10 +1239,7 @@
 }
 
 Sema::DeclPtrTy 
-Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy lastDecl,
-                      bool IsFunctionDefinition) {
-  NamedDecl *LastDeclarator =
-    dyn_cast_or_null<NamedDecl>(lastDecl.getAs<Decl>());
+Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
   DeclarationName Name = GetNameForDeclarator(D);
 
   // All of these full declarators require an identifier.  If it doesn't have
@@ -1356,14 +1357,14 @@
 
   bool Redeclaration = false;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
-    New = ActOnTypedefDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
+    New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl,
                                  InvalidDecl, Redeclaration);
   } else if (R->isFunctionType()) {
-    New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, 
+    New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl, 
                                   IsFunctionDefinition, InvalidDecl,
                                   Redeclaration);
   } else {
-    New = ActOnVariableDeclarator(S, D, DC, R, LastDeclarator, PrevDecl, 
+    New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, 
                                   InvalidDecl, Redeclaration);
   }
 
@@ -1454,8 +1455,7 @@
 
 NamedDecl*
 Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                             QualType R, Decl* LastDeclarator,
-                             Decl* PrevDecl, bool& InvalidDecl, 
+                             QualType R, Decl* PrevDecl, bool& InvalidDecl, 
                              bool &Redeclaration) {
   // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
   if (D.getCXXScopeSpec().isSet()) {
@@ -1475,7 +1475,7 @@
            diag::err_virtual_non_function);
   }
 
-  TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
+  TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
   if (!NewTD) return 0;
 
   // Handle attributes prior to checking for duplicates in MergeVarDecl
@@ -1580,8 +1580,7 @@
 
 NamedDecl*
 Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                              QualType R, Decl* LastDeclarator,
-                              NamedDecl* PrevDecl, bool& InvalidDecl,
+                              QualType R,NamedDecl* PrevDecl, bool& InvalidDecl,
                               bool &Redeclaration) {
   DeclarationName Name = GetNameForDeclarator(D);
 
@@ -1645,7 +1644,6 @@
                           // FIXME: Move to DeclGroup...
                           D.getDeclSpec().getSourceRange().getBegin());
   NewVD->setThreadSpecified(ThreadSpecified);
-  NewVD->setNextDeclarator(LastDeclarator);
 
   // Set the lexical context. If the declarator has a C++ scope specifier, the
   // lexical context will be different from the semantic context.
@@ -1800,8 +1798,8 @@
 
 NamedDecl* 
 Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                              QualType R, Decl *LastDeclarator,
-                              NamedDecl* PrevDecl, bool IsFunctionDefinition,
+                              QualType R, NamedDecl* PrevDecl,
+                              bool IsFunctionDefinition,
                               bool& InvalidDecl, bool &Redeclaration) {
   assert(R.getTypePtr()->isFunctionType());
 
@@ -1937,7 +1935,6 @@
                                  // FIXME: Move to DeclGroup...
                                  D.getDeclSpec().getSourceRange().getBegin());
   }
-  NewFD->setNextDeclarator(LastDeclarator);
 
   // Set the lexical context. If the declarator has a C++
   // scope specifier, the lexical context will be different
@@ -2517,39 +2514,29 @@
   }
 }
 
-/// The declarators are chained together backwards, reverse the list.
-Sema::DeclPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy group) {
-  // Often we have single declarators, handle them quickly.
-  Decl *Group = group.getAs<Decl>();
-  if (Group == 0)
-    return DeclPtrTy();
+Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+                                                   unsigned NumDecls) {
+  llvm::SmallVector<Decl*, 8> Decls;
   
-  Decl *NewGroup = 0;
-  if (Group->getNextDeclarator() == 0) 
-    NewGroup = Group;
-  else { // reverse the list.
-    while (Group) {
-      Decl *Next = Group->getNextDeclarator();
-      Group->setNextDeclarator(NewGroup);
-      NewGroup = Group;
-      Group = Next;
-    }
-  }
+  for (unsigned i = 0; i != NumDecls; ++i)
+    if (Decl *D = Group[i].getAs<Decl>())
+      Decls.push_back(D);
+  
   // Perform semantic analysis that depends on having fully processed both
   // the declarator and initializer.
-  for (Decl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) {
-    VarDecl *IDecl = dyn_cast<VarDecl>(ID);
+  for (unsigned i = 0, e = Decls.size(); i != e; ++i) {
+    VarDecl *IDecl = dyn_cast<VarDecl>(Decls[i]);
     if (!IDecl)
       continue;
     QualType T = IDecl->getType();
-
+    
     // Block scope. C99 6.7p7: If an identifier for an object is declared with
     // no linkage (C99 6.2.2p6), the type for the object shall be complete...
     if (IDecl->isBlockVarDecl() && 
         IDecl->getStorageClass() != VarDecl::Extern) {
       if (!IDecl->isInvalidDecl() &&
           RequireCompleteType(IDecl->getLocation(), T, 
-                                 diag::err_typecheck_decl_incomplete_type))
+                              diag::err_typecheck_decl_incomplete_type))
         IDecl->setInvalidDecl();
     }
     // File scope. C99 6.9.2p2: A declaration of an identifier for and 
@@ -2560,13 +2547,13 @@
     if (IDecl->isTentativeDefinition(Context)) {
       QualType CheckType = T;
       unsigned DiagID = diag::err_typecheck_decl_incomplete_type;
-
+      
       const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(T);
       if (ArrayT) {
         CheckType = ArrayT->getElementType();
         DiagID = diag::err_illegal_decl_array_incomplete_type;
       }
-
+      
       if (IDecl->isInvalidDecl()) {
         // Do nothing with invalid declarations
       } else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) &&
@@ -2578,9 +2565,11 @@
       }
     }
   }
-  return DeclPtrTy::make(NewGroup);
+  return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
+                                                   &Decls[0], NumDecls));
 }
 
+
 /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
 /// to introduce parameters into function prototype scope.
 Sema::DeclPtrTy 
@@ -2722,9 +2711,8 @@
   
   Scope *ParentScope = FnBodyScope->getParent();
 
-  return ActOnStartOfFunctionDef(FnBodyScope,
-                                 ActOnDeclarator(ParentScope, D, DeclPtrTy(), 
-                                                /*IsFunctionDefinition=*/true));
+  DeclPtrTy DP = ActOnDeclarator(ParentScope, D, /*IsFunctionDefinition=*/true);
+  return ActOnStartOfFunctionDef(FnBodyScope, DP);
 }
 
 Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
@@ -3056,8 +3044,7 @@
   }
 }
 
-TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
-                                    Decl *LastDeclarator) {
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
   assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
   assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
   
@@ -3076,7 +3063,6 @@
       TD->setTypedefForAnonDecl(NewTD);
   }
 
-  NewTD->setNextDeclarator(LastDeclarator);
   if (D.getInvalidType())
     NewTD->setInvalidDecl();
   return NewTD;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 258641f..ea2af68 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -473,8 +473,7 @@
 /// declarators on it.
 Sema::DeclPtrTy
 Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
-                               ExprTy *BW, ExprTy *InitExpr,
-                               DeclPtrTy LastInGroup) {
+                               ExprTy *BW, ExprTy *InitExpr) {
   const DeclSpec &DS = D.getDeclSpec();
   DeclarationName Name = GetNameForDeclarator(D);
   Expr *BitWidth = static_cast<Expr*>(BW);
@@ -553,10 +552,10 @@
                          AS);
     assert(Member && "HandleField never returns null");
   } else {
-    Member = ActOnDeclarator(S, D, LastInGroup).getAs<Decl>();
+    Member = ActOnDeclarator(S, D).getAs<Decl>();
     if (!Member) {
       if (BitWidth) DeleteExpr(BitWidth);
-      return LastInGroup;
+      return DeclPtrTy();
     }
 
     // Non-instance-fields can't have a bitfield.
@@ -595,7 +594,7 @@
 
   if (isInstField) {
     FieldCollector->Add(cast<FieldDecl>(Member));
-    return LastInGroup;
+    return DeclPtrTy();
   }
   return DeclPtrTy::make(Member);
 }
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d84a0d1..18e3e4f 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1234,8 +1234,7 @@
 void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
                       DeclPtrTy *allMethods, unsigned allNum,
                       DeclPtrTy *allProperties, unsigned pNum,
-                      DeclPtrTy *allTUVars,
-                      unsigned tuvNum) {
+                      DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
   Decl *ClassDecl = classDecl.getAs<Decl>();
 
   // FIXME: If we don't have a ClassDecl, we have an error. We should consider
@@ -1339,16 +1338,18 @@
       }
     }
   }
-  if (isInterfaceDeclKind)
-    for (unsigned i = 0; i < tuvNum; i++) {
-      if (VarDecl *VDecl = dyn_cast<VarDecl>(allTUVars[i].getAs<Decl>())) {
-        if (VDecl->getStorageClass() != VarDecl::Extern &&
-            VDecl->getStorageClass() != VarDecl::PrivateExtern) {
-          NamedDecl  *ClassNameDecl = dyn_cast<NamedDecl>(ClassDecl);
-          Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass) 
-            << ClassNameDecl->getIdentifier();
+  if (isInterfaceDeclKind) {
+    // Reject invalid vardecls.
+    for (unsigned i = 0; i != tuvNum; i++) {
+      DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+      for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+        if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
+          if (VDecl->getStorageClass() != VarDecl::Extern &&
+              VDecl->getStorageClass() != VarDecl::PrivateExtern)
+            Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass) 
+              << cast<NamedDecl>(ClassDecl)->getIdentifier();
         }
-     }
+    }
   }
 }
 
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index b331911..d258ec3 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -37,31 +37,13 @@
   return Owned(new (Context) NullStmt(SemiLoc));
 }
 
-Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclPtrTy decl,
+Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg,
                                            SourceLocation StartLoc,
                                            SourceLocation EndLoc) {
-  Decl *D = decl.getAs<Decl>();
-  if (D == 0)
-    return StmtError();
-
-  // This is a temporary hack until we are always passing around
-  // DeclGroupRefs.
-  llvm::SmallVector<Decl*, 10> decls;
-  while (D) { 
-    Decl* d = D;
-    D = D->getNextDeclarator();
-    d->setNextDeclarator(0);
-    decls.push_back(d);
-  }
-
-  assert (!decls.empty());
-
-  if (decls.size() == 1) {
-    DeclGroupRef DG(*decls.begin());                      
-    return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
-  }
-
-  DeclGroupRef DG(DeclGroup::Create(Context, decls.size(), &decls[0]));
+  // If we have an invalid decl, just return an error.
+  if (!dg) return StmtError();
+  
+  DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
   return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
 }
 
diff --git a/tools/clang-cc/ASTConsumers.cpp b/tools/clang-cc/ASTConsumers.cpp
index cb09659..3910c77 100644
--- a/tools/clang-cc/ASTConsumers.cpp
+++ b/tools/clang-cc/ASTConsumers.cpp
@@ -539,8 +539,9 @@
   public:
     ASTPrinter(llvm::raw_ostream* o = NULL) : DeclPrinter(o) {}
     
-    virtual void HandleTopLevelDecl(Decl *D) {
-      PrintDecl(D);
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        PrintDecl(*I);
     }
   };
 } // end anonymous namespace
@@ -562,11 +563,15 @@
       SM = &Context.getSourceManager();
     }
 
-    virtual void HandleTopLevelDecl(Decl *D);
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        HandleTopLevelSingleDecl(*I);
+    }
+    void HandleTopLevelSingleDecl(Decl *D);
   };
 } // end anonymous namespace
 
-void ASTDumper::HandleTopLevelDecl(Decl *D) {
+void ASTDumper::HandleTopLevelSingleDecl(Decl *D) {
   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     PrintFunctionDeclStart(FD);
     
@@ -624,12 +629,17 @@
     void Initialize(ASTContext &Context) {
       SM = &Context.getSourceManager();
     }
+
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        HandleTopLevelSingleDecl(*I);
+    }
     
-    virtual void HandleTopLevelDecl(Decl *D);
+    void HandleTopLevelSingleDecl(Decl *D);
   };
 }
 
-void ASTViewer::HandleTopLevelDecl(Decl *D) {
+void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     DeclPrinter().PrintFunctionDeclStart(FD);
     
diff --git a/tools/clang-cc/AnalysisConsumer.cpp b/tools/clang-cc/AnalysisConsumer.cpp
index 366f384..bc38593 100644
--- a/tools/clang-cc/AnalysisConsumer.cpp
+++ b/tools/clang-cc/AnalysisConsumer.cpp
@@ -220,7 +220,12 @@
       Ctx = &Context;
     }
     
-    virtual void HandleTopLevelDecl(Decl *D);
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        HandleTopLevelSingleDecl(*I);
+    }
+    
+    void HandleTopLevelSingleDecl(Decl *D);
     virtual void HandleTranslationUnit(ASTContext &C);
     
     void HandleCode(Decl* D, Stmt* Body, Actions& actions);
@@ -411,7 +416,7 @@
 // AnalysisConsumer implementation.
 //===----------------------------------------------------------------------===//
 
-void AnalysisConsumer::HandleTopLevelDecl(Decl *D) { 
+void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { 
   switch (D->getKind()) {
     case Decl::Function: {
       FunctionDecl* FD = cast<FunctionDecl>(D);
diff --git a/tools/clang-cc/Backend.cpp b/tools/clang-cc/Backend.cpp
index 0faabbe..3b3be31 100644
--- a/tools/clang-cc/Backend.cpp
+++ b/tools/clang-cc/Backend.cpp
@@ -8,11 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "ASTConsumers.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/Frontend/CompileOptions.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Basic/TargetInfo.h"
 #include "llvm/Module.h"
 #include "llvm/ModuleProvider.h"
 #include "llvm/PassManager.h"
@@ -117,13 +118,14 @@
         LLVMIRGeneration.stopTimer();
     }
     
-    virtual void HandleTopLevelDecl(Decl *D) {
-      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
                                      Context->getSourceManager(),
                                      "LLVM IR generation of declaration");
+      
       if (CompileOpts.TimePasses)
         LLVMIRGeneration.startTimer();
-      
+
       Gen->HandleTopLevelDecl(D);
 
       if (CompileOpts.TimePasses)
diff --git a/tools/clang-cc/PrintParserCallbacks.cpp b/tools/clang-cc/PrintParserCallbacks.cpp
index 9dce6d8..dc25f54 100644
--- a/tools/clang-cc/PrintParserCallbacks.cpp
+++ b/tools/clang-cc/PrintParserCallbacks.cpp
@@ -29,8 +29,7 @@
     /// ActOnDeclarator - This callback is invoked when a declarator is parsed
     /// and 'Init' specifies the initializer if any.  This is for things like:
     /// "int X = 4" or "typedef int foo".
-    virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
-                                      DeclPtrTy LastInGroup) {
+    virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
       llvm::cout << __FUNCTION__ << " ";
       if (IdentifierInfo *II = D.getIdentifier()) {
         llvm::cout << "'" << II->getName() << "'";
@@ -40,7 +39,7 @@
       llvm::cout << "\n";
       
       // Pass up to EmptyActions so that the symbol table is maintained right.
-      return MinimalAction::ActOnDeclarator(S, D, LastInGroup);
+      return MinimalAction::ActOnDeclarator(S, D);
     }
     /// ActOnPopScope - This callback is called immediately before the specified
     /// scope is popped and deleted.
@@ -112,17 +111,20 @@
       llvm::cout << __FUNCTION__ << "\n";
     }
 
-    /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
-    /// gives the actions implementation a chance to process the group as a whole.
-    virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group) {
+    /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed,
+    /// this gives the actions implementation a chance to process the group as
+    /// a whole.
+    virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+                                                   unsigned NumDecls) {
       llvm::cout << __FUNCTION__ << "\n";
-      return DeclPtrTy();
+      return DeclGroupPtrTy();
     }
 
     /// ActOnStartOfFunctionDef - This is called at the start of a function
     /// definition, instead of calling ActOnDeclarator.  The Declarator includes
     /// information about formal arguments that are part of this function.
-    virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+    virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope,
+                                              Declarator &D){
       llvm::cout << __FUNCTION__ << "\n";
       return DeclPtrTy();
     }
@@ -256,7 +258,7 @@
       llvm::cout << __FUNCTION__ << "\n";
       return StmtEmpty();
     }
-    virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,
+    virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
                                            SourceLocation StartLoc,
                                            SourceLocation EndLoc) {
       llvm::cout << __FUNCTION__ << "\n";
diff --git a/tools/clang-cc/RewriteBlocks.cpp b/tools/clang-cc/RewriteBlocks.cpp
index 2672d32..f302913 100644
--- a/tools/clang-cc/RewriteBlocks.cpp
+++ b/tools/clang-cc/RewriteBlocks.cpp
@@ -83,7 +83,11 @@
                    const char *NewStr, unsigned NewLength);
 
   // Top Level Driver code.
-  virtual void HandleTopLevelDecl(Decl *D);
+  virtual void HandleTopLevelDecl(DeclGroupRef D) {
+    for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+      HandleTopLevelSingleDecl(*I);
+  }
+  void HandleTopLevelSingleDecl(Decl *D);
   void HandleDeclInMainFile(Decl *D);
   
   // Top level 
@@ -336,7 +340,7 @@
 // Top Level Driver Code
 //===----------------------------------------------------------------------===//
 
-void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
+void RewriteBlocks::HandleTopLevelSingleDecl(Decl *D) {
   // Two cases: either the decl could be in the main file, or it could be in a
   // #included file.  If the former, rewrite it now.  If the later, check to see
   // if we rewrote the #include/#import.
diff --git a/tools/clang-cc/RewriteObjC.cpp b/tools/clang-cc/RewriteObjC.cpp
index e0267ec..5fcecc6 100644
--- a/tools/clang-cc/RewriteObjC.cpp
+++ b/tools/clang-cc/RewriteObjC.cpp
@@ -126,7 +126,11 @@
     virtual void Initialize(ASTContext &context);
 
     // Top Level Driver code.
-    virtual void HandleTopLevelDecl(Decl *D);
+    virtual void HandleTopLevelDecl(DeclGroupRef D) {
+      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+        HandleTopLevelSingleDecl(*I);
+    }
+    void HandleTopLevelSingleDecl(Decl *D);
     void HandleDeclInMainFile(Decl *D);
     RewriteObjC(std::string inFile, std::string outFile,
                 Diagnostic &D, const LangOptions &LOpts);
@@ -550,7 +554,7 @@
 // Top Level Driver Code
 //===----------------------------------------------------------------------===//
 
-void RewriteObjC::HandleTopLevelDecl(Decl *D) {
+void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
   // Two cases: either the decl could be in the main file, or it could be in a
   // #included file.  If the former, rewrite it now.  If the later, check to see
   // if we rewrote the #include/#import.
@@ -583,7 +587,7 @@
     for (DeclContext::decl_iterator DI = LSD->decls_begin(),
                                  DIEnd = LSD->decls_end();
          DI != DIEnd; ++DI)
-      HandleTopLevelDecl(*DI);
+      HandleTopLevelSingleDecl(*DI);
   }
   // If we have a decl in the main file, see if we should rewrite it.
   if (SM->isFromMainFile(Loc))
diff --git a/tools/clang-cc/SerializationTest.cpp b/tools/clang-cc/SerializationTest.cpp
index 74ccb4b..fda8d88 100644
--- a/tools/clang-cc/SerializationTest.cpp
+++ b/tools/clang-cc/SerializationTest.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CFG.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
 #include "clang.h"
 #include "ASTConsumers.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -73,7 +74,7 @@
     TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl();
     for (DeclContext::decl_iterator I = TUD->decls_begin(), E =TUD->decls_end();
          I != E; ++I)
-      FilePrinter->HandleTopLevelDecl(*I);
+      FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
   }
   
   // Serialize the translation unit.
@@ -124,7 +125,7 @@
     TranslationUnitDecl *TUD = NewCtx->getTranslationUnitDecl();
     for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end();
          I != E; ++I)
-      FilePrinter->HandleTopLevelDecl(*I);
+      FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
   }
 
   delete NewCtx;
diff --git a/tools/clang-cc/clang.cpp b/tools/clang-cc/clang.cpp
index c0a2ae7..5b1e6ab 100644
--- a/tools/clang-cc/clang.cpp
+++ b/tools/clang-cc/clang.cpp
@@ -37,6 +37,7 @@
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/LexDiagnostic.h"
@@ -1563,7 +1564,7 @@
   TranslationUnitDecl *TUD = Ctx->getTranslationUnitDecl();
   for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end();
        I != E; ++I)
-    Consumer->HandleTopLevelDecl(*I);
+    Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
 }