]> granicus.if.org Git - clang/commitdiff
Migrate DeclStmt over to using a DeclGroup instead of a pointer to a ScopedDecl*.
authorTed Kremenek <kremenek@apple.com>
Tue, 7 Oct 2008 23:09:49 +0000 (23:09 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 7 Oct 2008 23:09:49 +0000 (23:09 +0000)
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

include/clang/AST/Stmt.h
lib/AST/CFG.cpp
lib/AST/Stmt.cpp
lib/AST/StmtSerialization.cpp
lib/AST/StmtViz.cpp
lib/Sema/SemaStmt.cpp

index 1111bd31e1aacbb0ddb8748ae8e495876fc54578..f6216eeeef39eca4cd0fa35e20e857c8c89d16a2 100644 (file)
@@ -18,6 +18,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/AST/StmtIterator.h"
+#include "clang/AST/DeclGroup.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/Bitcode/SerializationFwd.h"
@@ -141,33 +142,37 @@ public:
 ///
 class DeclStmt : public Stmt {
 protected:
-  ScopedDecl *TheDecl;
+  DeclGroupOwningRef DG;
   SourceLocation StartLoc, EndLoc;
 public:
-  DeclStmt(ScopedDecl *D, SourceLocation startLoc, SourceLocation endLoc)
-    : Stmt(DeclStmtClass), TheDecl(D), StartLoc(startLoc), EndLoc(endLoc) {}
+  DeclStmt(DeclGroupOwningRef& dg, SourceLocation startLoc, 
+           SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
+                                    StartLoc(startLoc), EndLoc(endLoc) {}
   
   virtual void Destroy(ASTContext& Ctx);
 
   // hasSolitaryDecl - This method returns true if this DeclStmt refers
   // to a single Decl.
-  bool hasSolitaryDecl() const;
+  bool hasSolitaryDecl() const {
+    return DG.hasSolitaryDecl();
+  }
  
   const ScopedDecl* getSolitaryDecl() const {
     assert (hasSolitaryDecl() &&
             "Caller assumes this DeclStmt points to one Decl*");
-    return TheDecl;
+    return llvm::cast<ScopedDecl>(*DG.begin());
   }
   
   ScopedDecl* getSolitaryDecl() {
     assert (hasSolitaryDecl() &&
             "Caller assumes this DeclStmt points to one Decl*");
-    return TheDecl;
+    return llvm::cast<ScopedDecl>(*DG.begin());
   }  
 
   SourceLocation getStartLoc() const { return StartLoc; }
   SourceLocation getEndLoc() const { return EndLoc; }
-  virtual SourceRange getSourceRange() const {
+  
+  SourceRange getSourceRange() const {
     return SourceRange(StartLoc, EndLoc);
   }
   
@@ -180,42 +185,42 @@ public:
   virtual child_iterator child_begin();
   virtual child_iterator child_end();
   
-  // Iterators over the decls.
   class decl_iterator {
-    ScopedDecl* D;
+    DeclGroupRef::iterator I;
   public:
-    decl_iterator(ScopedDecl *d) : D(d) {}    
-    bool operator==(const decl_iterator& I) const { return D == I.D; }
-    bool operator!=(const decl_iterator& I) const { return D != I.D; }
-    ScopedDecl* operator*() const { return D; }
-    decl_iterator& operator++();
+    decl_iterator(DeclGroupRef::iterator i) : I(i) {}
+    decl_iterator& operator++() { ++I; return *this; }
+    bool operator==(const decl_iterator& R) const {
+      return R.I == I;
+    }
+    bool operator!=(const decl_iterator& R) const {
+      return R.I != I;
+    }
+    ScopedDecl* operator*() const {
+      return llvm::cast<ScopedDecl>(*I);
+    }
   };
-  
-  virtual decl_iterator decl_begin() { return TheDecl; }
-  virtual decl_iterator decl_end() { return 0; }
-  
+    
   class const_decl_iterator {
-    decl_iterator Impl;
+    DeclGroupRef::const_iterator I;
   public:
-    const_decl_iterator(const ScopedDecl *d)
-      : Impl(const_cast<ScopedDecl*>(d)) {}
-    
-    bool operator==(const const_decl_iterator& I) const {
-      return Impl == I.Impl;
-    }
-    bool operator!=(const const_decl_iterator& I) const {
-      return Impl != I.Impl;
+    const_decl_iterator(DeclGroupRef::const_iterator i) : I(i) {}
+    const_decl_iterator& operator++() { ++I; return *this; }
+    bool operator==(const const_decl_iterator& R) const {
+      return R.I == I;
     }
-    const ScopedDecl* operator*() const {
-      return *Impl;
+    bool operator!=(const const_decl_iterator& R) const {
+      return R.I != I;
     }
-    const_decl_iterator& operator++() {
-      ++Impl; return *this;
+    ScopedDecl* operator*() const {
+      return llvm::cast<ScopedDecl>(*I);
     }
   };
   
-  const_decl_iterator decl_begin() const { return TheDecl; }
-  const_decl_iterator decl_end() const { return 0; }
+  decl_iterator decl_begin() { return DG.begin(); }
+  decl_iterator decl_end() { return DG.end(); }
+  const_decl_iterator decl_begin() const { return DG.begin(); }
+  const_decl_iterator decl_end() const { return DG.end(); }
   
   // Serialization.  
   virtual void EmitImpl(llvm::Serializer& S) const;
index 2eea6492cd0f58dea6576ff3081363ffa1e2de04..2a79355a6363ddbc71390a6e2be831a26a4805a3 100644 (file)
@@ -50,32 +50,6 @@ static SourceLocation GetEndLoc(ScopedDecl* D) {
   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 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
           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 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));
           
-          // Allocate the UnaryDeclStmt using the BumpPtrAllocator.  It will
-          // get automatically freed with the CFG.
-          void* Mem = cfg->getAllocator().Allocate(sizeof(UnaryDeclStmt), A);
           // 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;
       }
index fbb369f387e2291237a64cea6b3b4b39fa2da678..f30e105b179536778d67a230bc2fcc421eb1ef9f 100644 (file)
@@ -55,7 +55,7 @@ void Stmt::Destroy(ASTContext& C) {
 }
 
 void DeclStmt::Destroy(ASTContext& C) {
-  TheDecl->Destroy(C);
+  DG.Destroy(C);
   delete this;
 }
 
@@ -188,16 +188,12 @@ ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
 //===----------------------------------------------------------------------===//
 
 // 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
index b226bdf8f9ad5d4d6af5040d217b87f4e33050e9..f72800d8ad12b36f2c2bc51cd1fe03b9f2f62d99 100644 (file)
@@ -478,14 +478,14 @@ ContinueStmt* ContinueStmt::CreateImpl(Deserializer& D, ASTContext& C) {
 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 {
index 6790efbd5682ac0e2980a591c417f7df406477f6..1316d3551d91aa45e30a8e7aaf2977e2b2d7f5d5 100644 (file)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/StmtGraphTraits.h"
+#include "clang/AST/Decl.h"
 #include "llvm/Support/GraphWriter.h"
 #include <sstream>
 
index 68b36ba81848942c01d85db3ba717895fd2c82d8..f75758ebb0a78c87982616507f279ea1e7d07dfa 100644 (file)
@@ -42,7 +42,28 @@ Sema::StmtResult Sema::ActOnDeclStmt(DeclTy *decl, SourceLocation StartLoc,
     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