]> granicus.if.org Git - clang/commitdiff
Reclaim memory from chains of ScopedDecls, and reclaim memory for the initializers...
authorTed Kremenek <kremenek@apple.com>
Tue, 20 May 2008 04:49:55 +0000 (04:49 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 20 May 2008 04:49:55 +0000 (04:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51299 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/AST/Decl.cpp

index 0714b120ad744c90bdd587f87238bb5463bee5d2..6b3eccf30c913244d51b5cfd4bf1cf39b7d53fcb 100644 (file)
@@ -125,6 +125,8 @@ protected:
   
   void EmitOutRec(llvm::Serializer& S) const;
   void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
+  
+  friend void Decl::Destroy(ASTContext& C);
 };
 
 /// NamespaceDecl - Represent a C++ namespace.
@@ -150,6 +152,8 @@ class NamespaceDecl : public ScopedDecl, public DeclContext {
 public:
   static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
                                SourceLocation L, IdentifierInfo *Id);
+  
+  virtual void Destroy(ASTContext& C);
 
   NamespaceDecl *getNextNamespace() {
     return cast_or_null<NamespaceDecl>(getNextDeclarator());
@@ -565,6 +569,8 @@ public:
                                   QualType T, Expr *E,
                                   const llvm::APSInt &V, ScopedDecl *PrevDecl);
   
+  virtual void Destroy(ASTContext& C);
+
   const Expr *getInitExpr() const { return Init; }
   Expr *getInitExpr() { return Init; }
   const llvm::APSInt &getInitVal() const { return Val; }
@@ -703,6 +709,8 @@ public:
                           SourceLocation L, IdentifierInfo *Id,
                           ScopedDecl *PrevDecl);
   
+  virtual void Destroy(ASTContext& C);
+
   /// defineElements - When created, EnumDecl correspond to a forward declared
   /// enum.  This method is used to mark the decl as being defined, with the
   /// specified list of enums.
index c75fb8b674dc1aa944113454559e3cd9ab79083b..02d86a32fccd358b94342c09f07a76f0d025d797 100644 (file)
@@ -226,6 +226,15 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
   return new (Mem) NamespaceDecl(DC, L, Id);
 }
 
+void NamespaceDecl::Destroy(ASTContext& C) {
+  // NamespaceDecl uses "NextDeclarator" to chain namespace declarations
+  // together. They are all top-level Decls.
+  
+  this->~Decl();
+  C.getAllocator().Deallocate((void *)this);
+}
+
+
 VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
                          SourceLocation L,
                          IdentifierInfo *Id, QualType T,
@@ -267,6 +276,11 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
   return new (Mem) EnumConstantDecl(CD, L, Id, T, E, V, PrevDecl);
 }
 
+void EnumConstantDecl::Destroy(ASTContext& C) {
+  if (Init) Init->Destroy(C);
+  Decl::Destroy(C);
+}
+
 TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
                                  SourceLocation L,
                                  IdentifierInfo *Id, QualType T,
@@ -289,6 +303,12 @@ RecordDecl *RecordDecl::Create(ASTContext &C, Kind DK, DeclContext *DC,
   return new (Mem) RecordDecl(DK, DC, L, Id, PrevDecl);
 }
 
+void EnumDecl::Destroy(ASTContext& C) {
+  if (ElementList) ElementList->Destroy(C);
+  Decl::Destroy(C);
+}
+
+
 FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
                                            SourceLocation L,
                                            StringLiteral *Str) {
@@ -370,6 +390,23 @@ void Decl::swapAttrs(Decl *RHS) {
 
 
 void Decl::Destroy(ASTContext& C) {
+
+  if (ScopedDecl* SD = dyn_cast<ScopedDecl>(this)) {    
+
+    // Observe the unrolled recursion.  By setting N->NextDeclarator = 0x0
+    // within the loop, only the Destroy method for the first ScopedDecl
+    // will deallocate all of the ScopedDecls in a chain.
+    
+    ScopedDecl* N = SD->getNextDeclarator();
+    
+    while (N) {
+      ScopedDecl* Tmp = N->getNextDeclarator();
+      N->NextDeclarator = 0x0;
+      N->Destroy(C);
+      N = Tmp;
+    }
+  }  
+  
   this->~Decl();
   C.getAllocator().Deallocate((void *)this);
 }