]> granicus.if.org Git - clang/commitdiff
TranslationUnit now owns IdentifierTable, TargetInfo, and Selectors objects
authorTed Kremenek <kremenek@apple.com>
Wed, 23 Apr 2008 16:25:39 +0000 (16:25 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 23 Apr 2008 16:25:39 +0000 (16:25 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50149 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/ASTConsumers.cpp
Driver/SerializationTest.cpp
Driver/clang.cpp
include/clang/AST/TranslationUnit.h
lib/AST/TranslationUnit.cpp

index eaee94e51da8a1470a8d6b38f6625a4f53fe3344..2f04ab78d4fed5567dbd73fe6ed080d28ff5eb96 100644 (file)
@@ -826,20 +826,24 @@ namespace {
 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 @@ public:
   : ASTSerializer(diags,LO), FName(F) {}    
   
   ~SingleFileSerializer() {
-    EmitASTBitcodeFile(TU,FName);
+    EmitASTBitcodeFile(TU, FName);
   }
 };
 
@@ -863,7 +867,11 @@ public:
   : 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 @@ public:
             
     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.
     
index 086d5587e981f2b1ac59d6b31167a2eb728cc1be..6e9309dc28ba9c662aec71b9067f3a950f4efc63 100644 (file)
@@ -33,21 +33,22 @@ using namespace clang;
 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 @@ bool SerializationTest::Serialize(llvm::sys::Path& Filename,
     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,
index 144ab4e65ac8982af7b69c6420cdb97f6355c0cf..f077952ea21ab69f77edeb8f0806b065d4fdc678 100644 (file)
@@ -1274,7 +1274,7 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag,
     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 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag,
     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)
index 0c7d0348da8f8574a9388023b39fe543d19323d1..6aa3a40b87cbab6b39124da8023952ce022afab3 100644 (file)
@@ -34,19 +34,17 @@ class TranslationUnit {
   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 @@ public:
   
   // 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 @@ public:
 /// 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,
index 0198f6f1cf7ef9a1fc6af7538eab9002680f5a9e..5c043efeb31753e7671ffcc4f77cf0f9fdca6732 100644 (file)
@@ -33,11 +33,28 @@ enum { BasicMetadataBlock = 1,
 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 @@ TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr,
   { // 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;
   }