[cfe-commits] r50149 - in /cfe/trunk: Driver/ASTConsumers.cpp Driver/SerializationTest.cpp Driver/clang.cpp include/clang/AST/TranslationUnit.h lib/AST/TranslationUnit.cpp

Ted Kremenek kremenek at apple.com
Wed Apr 23 09:25:40 PDT 2008


Author: kremenek
Date: Wed Apr 23 11:25:39 2008
New Revision: 50149

URL: http://llvm.org/viewvc/llvm-project?rev=50149&view=rev
Log:
TranslationUnit now owns IdentifierTable, TargetInfo, and Selectors objects
when it is constructed via deserialization.  This is done by recording a flag
indicating that this is the case, and it deletes these objects by getting
the references stored in the ASTContext object.  This fixes some memory
leaks that occurs when we deserialize translation units from bitcode files.

The rationale between having TranslationUnit sometimes own these objects and
sometimes not is that a TranslationUnit object can be constructed from
state generated by the parser (Preprocessor; semantic analyzer, etc.), and thus
in these cases won't own the IdentifierTable or Selectors, etc.  During
deserialization, there is no Preprocessor, so somebody needs to own these
objects in order for them to be properly reclaimed.

Modified:
    cfe/trunk/Driver/ASTConsumers.cpp
    cfe/trunk/Driver/SerializationTest.cpp
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/include/clang/AST/TranslationUnit.h
    cfe/trunk/lib/AST/TranslationUnit.cpp

Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=50149&r1=50148&r2=50149&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Wed Apr 23 11:25:39 2008
@@ -826,20 +826,24 @@
 class ASTSerializer : public ASTConsumer {
 protected:
   Diagnostic &Diags;
-  TranslationUnit TU;
+  const LangOptions& lang;
+  TranslationUnit* TU;
+
 public:
   ASTSerializer(Diagnostic& diags, const LangOptions& LO)
-    : Diags(diags), TU(LO) {}
+    : Diags(diags), lang(LO), TU(0) {}
+    
+  virtual ~ASTSerializer() { delete TU; }
   
   virtual void Initialize(ASTContext &Context) {
-    TU.setContext(&Context);
+    if (!TU) TU = new TranslationUnit(Context, lang);
   }
   
   virtual void HandleTopLevelDecl(Decl *D) {
     if (Diags.hasErrorOccurred())
       return;
     
-    TU.AddTopLevelDecl(D);
+    if (TU) TU->AddTopLevelDecl(D);
   }
 };
     
@@ -851,7 +855,7 @@
   : ASTSerializer(diags,LO), FName(F) {}    
   
   ~SingleFileSerializer() {
-    EmitASTBitcodeFile(TU,FName);
+    EmitASTBitcodeFile(TU, FName);
   }
 };
 
@@ -863,7 +867,11 @@
   : ASTSerializer(diags,LO), EmitDir(dir) {}
   
   ~BuildSerializer() {
-    SourceManager& SourceMgr = TU.getASTContext()->getSourceManager();
+
+    if (!TU)
+      return;
+    
+    SourceManager& SourceMgr = TU->getContext().getSourceManager();
     unsigned ID = SourceMgr.getMainFileID();
     assert (ID && "MainFileID not set!");
     const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
@@ -887,7 +895,7 @@
             
     sprintf(&buf[0], "%s-%llX.ast", FE->getName(), (uint64_t) FE->getInode());
     FName.appendComponent(&buf[0]);    
-    EmitASTBitcodeFile(TU,FName);
+    EmitASTBitcodeFile(TU, FName);
     
     // Now emit the sources.
     

Modified: cfe/trunk/Driver/SerializationTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/SerializationTest.cpp?rev=50149&r1=50148&r2=50149&view=diff

==============================================================================
--- cfe/trunk/Driver/SerializationTest.cpp (original)
+++ cfe/trunk/Driver/SerializationTest.cpp Wed Apr 23 11:25:39 2008
@@ -33,21 +33,22 @@
 namespace {
   
 class SerializationTest : public ASTConsumer {
-  TranslationUnit TU;
+  llvm::OwningPtr<TranslationUnit> TU;
   Diagnostic &Diags;
   FileManager &FMgr;  
+  const LangOptions& lopts;
 public:  
   SerializationTest(Diagnostic &d, FileManager& fmgr, const LangOptions& LOpts)
-                    : TU(LOpts), Diags(d), FMgr(fmgr) {}
+                    : Diags(d), FMgr(fmgr), lopts(LOpts) {}
   
   ~SerializationTest();
 
   virtual void Initialize(ASTContext& context) {
-    TU.setContext(&context);
+    if (!TU) TU.reset(new TranslationUnit(context, lopts));
   }  
 
   virtual void HandleTopLevelDecl(Decl *D) {
-    TU.AddTopLevelDecl(D);
+    TU->AddTopLevelDecl(D);
   }
   
 private:
@@ -73,12 +74,12 @@
     assert (DeclPP && "Could not open file for printing out decls.");
     llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
     
-    for (TranslationUnit::iterator I=TU.begin(), E=TU.end(); I!=E; ++I)
+    for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)
       FilePrinter->HandleTopLevelDecl(*I);
   }
   
   // Serialize the translation unit.
-  return EmitASTBitcodeFile(TU,Filename);
+  return EmitASTBitcodeFile(*TU,Filename);
 }
 
 bool SerializationTest::Deserialize(llvm::sys::Path& Filename,

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=50149&r1=50148&r2=50149&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Wed Apr 23 11:25:39 2008
@@ -1274,7 +1274,7 @@
     exit (1);
   }
   
-  llvm::OwningPtr<TranslationUnit> TU(ReadASTBitcodeFile(Filename,FileMgr));
+  llvm::OwningPtr<TranslationUnit> TU(ReadASTBitcodeFile(Filename, FileMgr));
   
   if (!TU) {
     fprintf(stderr, "error: file '%s' could not be deserialized\n", 
@@ -1294,7 +1294,7 @@
     exit (1);
   }
   
-  Consumer->Initialize(*TU->getContext());
+  Consumer->Initialize(TU->getContext());
   
   // FIXME: We need to inform Consumer about completed TagDecls as well.
   for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)

Modified: cfe/trunk/include/clang/AST/TranslationUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TranslationUnit.h?rev=50149&r1=50148&r2=50149&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TranslationUnit.h (original)
+++ cfe/trunk/include/clang/AST/TranslationUnit.h Wed Apr 23 11:25:39 2008
@@ -34,19 +34,17 @@
   LangOptions LangOpts;
   ASTContext* Context;
   std::vector<Decl*> TopLevelDecls;
+  bool OwnsMetaData;
 
   // The default ctor is only invoked during deserialization.
-  explicit TranslationUnit() : Context(NULL) {}
+  explicit TranslationUnit() : Context(NULL), OwnsMetaData(true) {}
   
 public:
-  explicit TranslationUnit(const LangOptions& lopt)
-    : LangOpts(lopt), Context(NULL) {}
+  explicit TranslationUnit(ASTContext& Ctx, const LangOptions& lopt)
+    : LangOpts(lopt), Context(&Ctx), OwnsMetaData(false) {}
 
   ~TranslationUnit();
 
-  void setContext(ASTContext* context) { Context = context; }
-  ASTContext* getContext() const { return Context; }
-  
   const LangOptions& getLangOpts() const { return LangOpts; }
   const std::string& getSourceFile() const;
   
@@ -58,9 +56,12 @@
   
   // Accessors
   const LangOptions& getLangOptions() const { return LangOpts; }
-  ASTContext*        getASTContext() { return Context; }
+
+  ASTContext&        getContext() { return *Context; }
+  const ASTContext&  getContext() const { return *Context; }
   
   /// AddTopLevelDecl - Add a top-level declaration to the translation unit.
+  ///  Ownership of the Decl is transfered to the TranslationUnit object.
   void AddTopLevelDecl(Decl* d) {
     TopLevelDecls.push_back(d);
   }
@@ -77,6 +78,9 @@
 /// EmitASTBitcodeFile - Emit a translation unit to a bitcode file.
 bool EmitASTBitcodeFile(const TranslationUnit& TU, 
                         const llvm::sys::Path& Filename);
+  
+bool EmitASTBitcodeFile(const TranslationUnit* TU, 
+                        const llvm::sys::Path& Filename);
                      
 /// ReadASTBitcodeFile - Reconsitute a translation unit from a bitcode file.
 TranslationUnit* ReadASTBitcodeFile(const llvm::sys::Path& Filename,

Modified: cfe/trunk/lib/AST/TranslationUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TranslationUnit.cpp?rev=50149&r1=50148&r2=50149&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TranslationUnit.cpp (original)
+++ cfe/trunk/lib/AST/TranslationUnit.cpp Wed Apr 23 11:25:39 2008
@@ -33,11 +33,28 @@
 TranslationUnit::~TranslationUnit() {
   for (iterator I=begin(), E=end(); I!=E; ++I) 
     (*I)->Destroy(*Context);
+  
+  if (OwnsMetaData && Context) {
+    // The ASTContext object has the sole references to the IdentifierTable
+    // Selectors, and the Target information.  Go and delete them, since
+    // the TranslationUnit effectively owns them.
+    
+    delete &(Context->Idents);
+    delete &(Context->Selectors);
+    delete &(Context->Target);
+    delete Context;
+  }  
 }
 
+bool clang::EmitASTBitcodeFile(const TranslationUnit* TU,                                
+                               const llvm::sys::Path& Filename) {
+
+  return TU ? EmitASTBitcodeFile(*TU, Filename) : false;
+}
+  
 bool clang::EmitASTBitcodeFile(const TranslationUnit& TU, 
                                const llvm::sys::Path& Filename) {  
-
+  
   // Reserve 256K for bitstream buffer.
   std::vector<unsigned char> Buffer;
   Buffer.reserve(256*1024);
@@ -194,7 +211,7 @@
   { // Read the TargetInfo.
     llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
     char* triple = Dezr.ReadCStr(NULL,0,true);
-    Dezr.RegisterPtr(PtrID,TargetInfo::CreateTargetInfo(std::string(triple)));
+    Dezr.RegisterPtr(PtrID, TargetInfo::CreateTargetInfo(std::string(triple)));
     delete [] triple;
   }
   





More information about the cfe-commits mailing list