[cfe-commits] r139974 - in /cfe/trunk: include/clang/Serialization/ASTWriter.h lib/Serialization/ASTWriter.cpp test/Modules/objc-categories.m

Douglas Gregor dgregor at apple.com
Fri Sep 16 17:05:03 PDT 2011


Author: dgregor
Date: Fri Sep 16 19:05:03 2011
New Revision: 139974

URL: http://llvm.org/viewvc/llvm-project?rev=139974&view=rev
Log:
With modules, we can end up loading a new module after we've seen an
arbitrary amount of code. This forces us to stage the AST writer more
strictly, ensuring that we don't assign a declaration ID to a
declaration until after we're certain that no more modules will get
loaded.

Modified:
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Modules/objc-categories.m

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=139974&r1=139973&r2=139974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Fri Sep 16 19:05:03 2011
@@ -97,6 +97,10 @@
   /// \brief A listener object that receives notifications when certain 
   /// entities are serialized.                    
   ASTSerializationListener *SerializationListener;
+                   
+  /// \brief Indicates when the AST writing is actively performing 
+  /// serialization, rather than just queueing updates.
+  bool WritingAST;
                     
   /// \brief Stores a declaration or a type to be written to the AST file.
   class DeclOrType {
@@ -251,11 +255,15 @@
   struct ChainedObjCCategoriesData {
     /// \brief The interface in the imported module.
     const ObjCInterfaceDecl *Interface;
-    /// \brief ID of the interface.
+    /// \brief The local tail category ID that got chained to the imported
+    /// interface.
+    const ObjCCategoryDecl *TailCategory;
+    
+    /// \brief ID corresponding to \c Interface.
     serialization::DeclID InterfaceID;
-    /// \brief ID of the locally tail category ID that got chained to the
-    /// imported interface.
-    serialization::DeclID TailCatID;
+    
+    /// \brief ID corresponding to TailCategoryID.
+    serialization::DeclID TailCategoryID;
   };
   /// \brief ObjC categories that got chained to an interface imported from
   /// another module.
@@ -351,8 +359,10 @@
   void WriteReferencedSelectorsPool(Sema &SemaRef);
   void WriteIdentifierTable(Preprocessor &PP, bool IsModule);
   void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
+  void ResolveDeclUpdatesBlocks();
   void WriteDeclUpdatesBlocks();
   void WriteDeclReplacementsBlock();
+  void ResolveChainedObjCCategories();
   void WriteChainedObjCCategories();
   void WriteDeclContextVisibleUpdate(const DeclContext *DC);
   void WriteFPPragmaOptions(const FPOptions &Opts);

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=139974&r1=139973&r2=139974&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Sep 16 19:05:03 2011
@@ -2719,6 +2719,7 @@
 
 ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
   : Stream(Stream), Context(0), Chain(0), SerializationListener(0), 
+    WritingAST(false),
     FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
     FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
     FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), 
@@ -2740,6 +2741,8 @@
 void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
                          const std::string &OutputFile,
                          bool IsModule, StringRef isysroot) {
+  WritingAST = true;
+  
   // Emit the file header.
   Stream.Emit((unsigned)'C', 8);
   Stream.Emit((unsigned)'P', 8);
@@ -2751,6 +2754,8 @@
   Context = &SemaRef.Context;
   WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, IsModule);
   Context = 0;
+  
+  WritingAST = false;
 }
 
 template<typename Vector>
@@ -2983,10 +2988,15 @@
     ASTWriter::UpdateRecord &Record = DeclUpdates[TU];
     if (Record.empty()) {
       Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE);
-      AddDeclRef(NS, Record);
+      Record.push_back(reinterpret_cast<uint64_t>(NS));
     }
   }
   
+  // Resolve any declaration pointers within the declaration updates block and
+  // chained Objective-C categories block to declaration IDs.
+  ResolveDeclUpdatesBlocks();
+  ResolveChainedObjCCategories();
+  
   // Form the record of special types.
   RecordData SpecialTypes;
   AddTypeRef(Context.getBuiltinVaListType(), SpecialTypes);
@@ -3120,6 +3130,36 @@
   Stream.ExitBlock();
 }
 
+/// \brief Go through the declaration update blocks and resolve declaration
+/// pointers into declaration IDs.
+void ASTWriter::ResolveDeclUpdatesBlocks() {
+  for (DeclUpdateMap::iterator
+       I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
+    const Decl *D = I->first;
+    UpdateRecord &URec = I->second;
+    
+    if (DeclsToRewrite.count(D))
+      continue; // The decl will be written completely
+
+    unsigned Idx = 0, N = URec.size();
+    while (Idx < N) {
+      switch ((DeclUpdateKind)URec[Idx++]) {
+      case UPD_CXX_SET_DEFINITIONDATA:
+      case UPD_CXX_ADDED_IMPLICIT_MEMBER:
+      case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
+      case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
+        URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
+        ++Idx;
+        break;
+          
+      case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
+        ++Idx;
+        break;
+      }
+    }
+  }
+}
+
 void ASTWriter::WriteDeclUpdatesBlocks() {
   if (DeclUpdates.empty())
     return;
@@ -3157,6 +3197,17 @@
   Stream.EmitRecord(DECL_REPLACEMENTS, Record);
 }
 
+void ASTWriter::ResolveChainedObjCCategories() {
+  for (SmallVector<ChainedObjCCategoriesData, 16>::iterator
+       I = LocalChainedObjCCategories.begin(),
+       E = LocalChainedObjCCategories.end(); I != E; ++I) {
+    ChainedObjCCategoriesData &Data = *I;
+    Data.InterfaceID = GetDeclRef(Data.Interface);
+    Data.TailCategoryID = GetDeclRef(Data.TailCategory);
+  }
+
+}
+
 void ASTWriter::WriteChainedObjCCategories() {
   if (LocalChainedObjCCategories.empty())
     return;
@@ -3172,7 +3223,7 @@
 
     Record.push_back(Data.InterfaceID);
     Record.push_back(HeadCatID);
-    Record.push_back(Data.TailCatID);
+    Record.push_back(Data.TailCategoryID);
   }
   Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record);
 }
@@ -3354,6 +3405,8 @@
 }
 
 DeclID ASTWriter::GetDeclRef(const Decl *D) {
+  assert(WritingAST && "Cannot request a declaration ID before AST writing");
+  
   if (D == 0) {
     return 0;
   }
@@ -3874,6 +3927,7 @@
 
 void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
   assert(D->isDefinition());
+  assert(!WritingAST && "Already writing the AST!");
   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
     // We are interested when a PCH decl is modified.
     if (RD->isFromASTFile()) {
@@ -3895,12 +3949,14 @@
         Record.push_back(UPD_CXX_SET_DEFINITIONDATA);
         assert(Redecl->DefinitionData);
         assert(Redecl->DefinitionData->Definition == D);
-        AddDeclRef(D, Record); // the DefinitionDecl
+        Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl
       }
     }
   }
 }
 void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
+  assert(!WritingAST && "Already writing the AST!");
+
   // TU and namespaces are handled elsewhere.
   if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
     return;
@@ -3912,6 +3968,7 @@
 }
 
 void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
+  assert(!WritingAST && "Already writing the AST!");
   assert(D->isImplicit());
   if (!(!D->isFromASTFile() && RD->isFromASTFile()))
     return; // Not a source member added to a class from PCH.
@@ -3922,34 +3979,37 @@
   assert(RD->isDefinition());
   UpdateRecord &Record = DeclUpdates[RD];
   Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER);
-  AddDeclRef(D, Record);
+  Record.push_back(reinterpret_cast<uint64_t>(D));
 }
 
 void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
                                      const ClassTemplateSpecializationDecl *D) {
   // The specializations set is kept in the canonical template.
+  assert(!WritingAST && "Already writing the AST!");
   TD = TD->getCanonicalDecl();
   if (!(!D->isFromASTFile() && TD->isFromASTFile()))
     return; // Not a source specialization added to a template from PCH.
 
   UpdateRecord &Record = DeclUpdates[TD];
   Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
-  AddDeclRef(D, Record);
+  Record.push_back(reinterpret_cast<uint64_t>(D));
 }
 
 void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                                const FunctionDecl *D) {
   // The specializations set is kept in the canonical template.
+  assert(!WritingAST && "Already writing the AST!");
   TD = TD->getCanonicalDecl();
   if (!(!D->isFromASTFile() && TD->isFromASTFile()))
     return; // Not a source specialization added to a template from PCH.
 
   UpdateRecord &Record = DeclUpdates[TD];
   Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
-  AddDeclRef(D, Record);
+  Record.push_back(reinterpret_cast<uint64_t>(D));
 }
 
 void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
+  assert(!WritingAST && "Already writing the AST!");
   if (!D->isFromASTFile())
     return; // Declaration not imported from PCH.
 
@@ -3959,6 +4019,7 @@
 }
 
 void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
+  assert(!WritingAST && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -3972,6 +4033,7 @@
 
 void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                              const ObjCInterfaceDecl *IFD) {
+  assert(!WritingAST && "Already writing the AST!");
   if (!IFD->isFromASTFile())
     return; // Declaration not imported from PCH.
   if (CatD->getNextClassCategory() &&
@@ -3979,7 +4041,7 @@
     return; // We already recorded that the tail of a category chain should be
             // attached to an interface.
 
-  ChainedObjCCategoriesData Data =  { IFD, GetDeclRef(IFD), GetDeclRef(CatD) };
+  ChainedObjCCategoriesData Data =  { IFD, CatD, 0, 0 };
   LocalChainedObjCCategories.push_back(Data);
 }
 

Modified: cfe/trunk/test/Modules/objc-categories.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-categories.m?rev=139974&r1=139973&r2=139974&view=diff
==============================================================================
--- cfe/trunk/test/Modules/objc-categories.m (original)
+++ cfe/trunk/test/Modules/objc-categories.m Fri Sep 16 19:05:03 2011
@@ -54,12 +54,13 @@
 #elif defined(MODULE_BOTTOM)
 
 __import_module__ diamond_left;
-__import_module__ diamond_right;
 
 @interface Foo(Bottom)
 -(void)bottom;
 @end
 
+__import_module__ diamond_right;
+
 @interface LeftFoo(Bottom)
 -(void)bottom;
 @end





More information about the cfe-commits mailing list