Migrate DeclStmt over to using a DeclGroup instead of a pointer to a ScopedDecl*.
This also removes the ugly hack needed in CFG.cpp for subclassing DeclStmt to create a DeclStmt with one Decl*.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57275 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/CFG.cpp b/lib/AST/CFG.cpp
index 2eea649..2a79355 100644
--- a/lib/AST/CFG.cpp
+++ b/lib/AST/CFG.cpp
@@ -50,32 +50,6 @@
   return D->getLocation();  
 }
   
-class VISIBILITY_HIDDEN UnaryDeclStmt : public DeclStmt {
-  Stmt* Ex;
-public:
-  UnaryDeclStmt(ScopedDecl* D)
-  : DeclStmt(D, D->getLocation(), GetEndLoc(D)), Ex(0) {
-    if (VarDecl* VD = dyn_cast<VarDecl>(D))
-      Ex = VD->getInit();
-  }
-  
-  virtual ~UnaryDeclStmt() {}
-  virtual void Destroy(ASTContext& Ctx) { assert(false && "Do not call"); }
-  
-  virtual child_iterator child_begin() {
-    return Ex ? &Ex : 0;
-  }  
-  virtual child_iterator child_end() {
-    return Ex ? &Ex + 1 : 0;
-  }  
-  virtual decl_iterator decl_begin() {
-    return TheDecl;
-  }  
-  virtual decl_iterator decl_end() {
-    return TheDecl ? TheDecl->getNextDeclarator() : 0;
-  }
-};
-  
 /// CFGBuilder - This class implements CFG construction from an AST.
 ///   The builder is stateful: an instance of the builder should be used to only
 ///   construct a single CFG.
@@ -395,16 +369,25 @@
           Buf.push_back(*DI);
         
         for (BufTy::reverse_iterator I=Buf.rbegin(), E=Buf.rend(); I!=E; ++I) {
-          // Get the alignment of UnaryDeclStmt, padding out to >=8 bytes.
-          unsigned A = llvm::AlignOf<UnaryDeclStmt>::Alignment < 8
-                       ? 8 : llvm::AlignOf<UnaryDeclStmt>::Alignment;
+          // Get the alignment of the new DeclStmt, padding out to >=8 bytes.
+          unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
+                       ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
           
-          // Allocate the UnaryDeclStmt using the BumpPtrAllocator.  It will
-          // get automatically freed with the CFG.
-          void* Mem = cfg->getAllocator().Allocate(sizeof(UnaryDeclStmt), A);
+          // Allocate the DeclStmt using the BumpPtrAllocator.  It will
+          // get automatically freed with the CFG.  Note that even though
+          // we are using a DeclGroupOwningRef that wraps a singe Decl*,
+          // that Decl* will not get deallocated because the destroy method
+          // of DG is never called.
+          DeclGroupOwningRef DG(*I);
+          ScopedDecl* D = *I;
+          void* Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);
+          
+          DeclStmt* DS = new (Mem) DeclStmt(DG, D->getLocation(),
+                                            GetEndLoc(D));
+          
           // Append the fake DeclStmt to block.
-          Block->appendStmt(new (Mem) UnaryDeclStmt(*I));
-          B = WalkAST_VisitDeclSubExpr(*I);
+          Block->appendStmt(DS);
+          B = WalkAST_VisitDeclSubExpr(D);
         }
         return B;
       }
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index fbb369f..f30e105 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -55,7 +55,7 @@
 }
 
 void DeclStmt::Destroy(ASTContext& C) {
-  TheDecl->Destroy(C);
+  DG.Destroy(C);
   delete this;
 }
 
@@ -188,16 +188,12 @@
 //===----------------------------------------------------------------------===//
 
 // DeclStmt
-Stmt::child_iterator DeclStmt::child_begin() { return TheDecl; }
-Stmt::child_iterator DeclStmt::child_end() { return child_iterator(); }
-
-DeclStmt::decl_iterator& DeclStmt::decl_iterator::operator++() {
-  D = D->getNextDeclarator();
-  return *this;
+Stmt::child_iterator DeclStmt::child_begin() {
+  return StmtIterator(DG.begin(), DG.end());
 }
 
-bool DeclStmt::hasSolitaryDecl() const {
-  return TheDecl->getNextDeclarator() == 0;
+Stmt::child_iterator DeclStmt::child_end() {
+  return StmtIterator(DG.end(), DG.end());
 }
 
 // NullStmt
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index b226bdf..f72800d 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -478,14 +478,14 @@
 void DeclStmt::EmitImpl(Serializer& S) const {
   S.Emit(StartLoc);
   S.Emit(EndLoc);
-  S.EmitOwnedPtr(TheDecl);
+  S.Emit(DG);
 }
     
 DeclStmt* DeclStmt::CreateImpl(Deserializer& D, ASTContext& C) {
   SourceLocation StartLoc = SourceLocation::ReadVal(D);
-  SourceLocation EndLoc = SourceLocation::ReadVal(D);  
-  ScopedDecl* decl = cast<ScopedDecl>(D.ReadOwnedPtr<Decl>(C));  
-  return new DeclStmt(decl, StartLoc, EndLoc);
+  SourceLocation EndLoc = SourceLocation::ReadVal(D); 
+  DeclGroupOwningRef DG;
+  return new DeclStmt(DG.Read(D, C), StartLoc, EndLoc);
 }
 
 void DeclRefExpr::EmitImpl(Serializer& S) const {
diff --git a/lib/AST/StmtViz.cpp b/lib/AST/StmtViz.cpp
index 6790efb..1316d35 100644
--- a/lib/AST/StmtViz.cpp
+++ b/lib/AST/StmtViz.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/StmtGraphTraits.h"
+#include "clang/AST/Decl.h"
 #include "llvm/Support/GraphWriter.h"
 #include <sstream>
 
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 68b36ba..f75758e 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -42,7 +42,28 @@
     return true;
   
   ScopedDecl *SD = cast<ScopedDecl>(static_cast<Decl *>(decl));
-  return new DeclStmt(SD, StartLoc, EndLoc);
+  
+  
+  // This is a temporary hack until we are always passing around
+  // DeclGroupRefs.
+  llvm::SmallVector<Decl*, 10> decls;
+  while (SD) { 
+    ScopedDecl* d = SD;
+    SD = SD->getNextDeclarator();
+    d->setNextDeclarator(0);
+    decls.push_back(d);
+  }
+
+  assert (!decls.empty());
+    
+  if (decls.size() == 1) {
+    DeclGroupOwningRef DG(*decls.begin());                      
+    return new DeclStmt(DG, StartLoc, EndLoc);
+  }
+  else {
+    DeclGroupOwningRef DG(DeclGroup::Create(Context, decls.size(), &decls[0]));                      
+    return new DeclStmt(DG, StartLoc, EndLoc);
+  }
 }
 
 Action::StmtResult