]> granicus.if.org Git - clang/commitdiff
Serialize the AST reader's mapping from canonical declarations to the
authorDouglas Gregor <dgregor@apple.com>
Thu, 22 Dec 2011 21:40:42 +0000 (21:40 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 22 Dec 2011 21:40:42 +0000 (21:40 +0000)
set of (previously-canonical) declaration IDs to the module file, so
that future AST reader instances that load the module know which
declarations are merged. This is important in the fairly tricky case
where a declaration of an entity, e.g.,

  @class X;

occurs before the import of a module that also declares that
entity. We merge the declarations, and record the fact that the
declaration of X loaded from the module was merged into the (now
canonical) declaration of X that we parsed.

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

include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
test/Modules/Inputs/redecl-merge-bottom.h
test/Modules/Inputs/redecl-merge-left.h
test/Modules/redecl-merge.m

index a4b6b8f45e7e92727f7c15d04ab07651401b5903..073ad80d7491e399c944727df1dc8c233992a472 100644 (file)
@@ -452,7 +452,10 @@ namespace clang {
       
       /// \brief Record code for an array of all of the (sub)modules that were
       /// imported by the AST file.
-      IMPORTED_MODULES = 51
+      IMPORTED_MODULES = 51,
+      
+      /// \brief Record code for the set of merged declarations in an AST file.
+      MERGED_DECLARATIONS = 52
     };
 
     /// \brief Record types used within a source manager block.
index 166ac668210463d7e074b81c116e5672b92b8d6b..1595a0ef61f0bd032b43da5e9675ed25845cb7fb 100644 (file)
@@ -690,6 +690,26 @@ private:
   /// that canonical declaration.
   MergedDeclsMap MergedDecls;
   
+  typedef llvm::DenseMap<serialization::GlobalDeclID, 
+                         llvm::SmallVector<serialization::DeclID, 2> >
+    StoredMergedDeclsMap;
+  
+  /// \brief A mapping from canonical declaration IDs to the set of additional
+  /// declaration IDs that have been merged with that canonical declaration.
+  ///
+  /// This is the deserialized representation of the entries in MergedDecls.
+  /// When we query entries in MergedDecls, they will be augmented with entries
+  /// from StoredMergedDecls.
+  StoredMergedDeclsMap StoredMergedDecls;
+  
+  /// \brief Combine the stored merged declarations for the given canonical
+  /// declaration into the set of merged declarations.
+  ///
+  /// \returns An iterator into MergedDecls that corresponds to the position of
+  /// the given canonical declaration.
+  MergedDeclsMap::iterator
+  combineStoredMergedDecls(Decl *Canon, serialization::GlobalDeclID CanonID);
+  
   /// \brief We delay loading the chain of objc categories after recursive
   /// loading of declarations is finished.
   std::vector<std::pair<ObjCInterfaceDecl *, serialization::DeclID> >
index 8791d83d93698089cd0f9c28e49c89baed3b3c39..ef2f1ada6f2b615ab54aa03a40ca418d6fa87935 100644 (file)
@@ -415,7 +415,8 @@ private:
   void WriteDeclContextVisibleUpdate(const DeclContext *DC);
   void WriteFPPragmaOptions(const FPOptions &Opts);
   void WriteOpenCLExtensions(Sema &SemaRef);
-
+  void WriteMergedDecls();
+                        
   unsigned DeclParmVarAbbrev;
   unsigned DeclContextLexicalAbbrev;
   unsigned DeclContextVisibleLookupAbbrev;
index 2ac1908ee2fd38a6f7c9b33fe1eb2aed0eb97cb6..440474b587a98ca613b8cdaafc5bdfe8bae92c55 100644 (file)
@@ -2407,6 +2407,16 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
       F.RedeclarationsInfo = (const LocalRedeclarationsInfo *)BlobStart;
       break;
     }
+        
+    case MERGED_DECLARATIONS: {
+      for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
+        GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
+        SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
+        for (unsigned N = Record[Idx++]; N > 0; --N)
+          Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
+      }
+      break;
+    }
     }
   }
   Error("premature end of bitstream in AST file");
index 2c8e6ea46634fc8db5f4e08c7e835525f2186f52..cb816632bdd9373edf7b003994617cebcccc1dbf 100644 (file)
@@ -676,9 +676,14 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
         }
         
         // If this declaration was the canonical declaration, make a note of 
-        // that.
-        if (IDCanon == ID)
-          Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID());
+        // that. We accept the linear algorithm here because the number of 
+        // unique canonical declarations of an entity should always be tiny.
+        if (IDCanon == ID) {
+          SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
+          if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
+                == Merged.end())
+            Merged.push_back(Redecl.getFirstID());
+        }
       }
     }
   }
@@ -1725,6 +1730,29 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
   }
 }
 
+ASTReader::MergedDeclsMap::iterator
+ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) {
+  // If we don't have any stored merged declarations, just look in the
+  // merged declarations set.
+  StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID);
+  if (StoredPos == StoredMergedDecls.end())
+    return MergedDecls.find(Canon);
+
+  // Append the stored merged declarations to the merged declarations set.
+  MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
+  if (Pos == MergedDecls.end())
+    Pos = MergedDecls.insert(std::make_pair(Canon, 
+                                            SmallVector<DeclID, 2>())).first;
+  Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
+  StoredMergedDecls.erase(StoredPos);
+  
+  // Sort and uniquify the set of merged declarations.
+  llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
+  Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
+                    Pos->second.end());
+  return Pos;
+}
+
 void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
   Decl *previous = GetDecl(ID);
   ASTDeclReader::attachPreviousDecl(D, previous);
@@ -2186,7 +2214,7 @@ static Decl *getMostRecentDecl(Decl *D) {
 void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
   Decl *D = GetDecl(ID);  
   Decl *CanonDecl = D->getCanonicalDecl();
-    
+  
   // Determine the set of declaration IDs we'll be searching for.
   llvm::SmallVector<DeclID, 1> SearchDecls;
   GlobalDeclID CanonID = 0;
@@ -2194,7 +2222,7 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
     SearchDecls.push_back(ID); // Always first.
     CanonID = ID;
   }
-  MergedDeclsMap::iterator MergedPos = MergedDecls.find(CanonDecl);
+  MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID);
   if (MergedPos != MergedDecls.end())
     SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());  
   
index 97c31b07a37b72361dd46ab6b9cf70c6c0a8f84a..feeb27f338929e01d7eb4f1ff7a9e5ae97cb2bea 100644 (file)
@@ -2903,6 +2903,25 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
   Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
 }
 
+void ASTWriter::WriteMergedDecls() {
+  if (!Chain || Chain->MergedDecls.empty())
+    return;
+  
+  RecordData Record;
+  for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(),
+                                        IEnd = Chain->MergedDecls.end();
+       I != IEnd; ++I) {
+    DeclID CanonID = I->first->isFromASTFile()? Chain->DeclToID[I->first]
+                                              : getDeclID(I->first);
+    assert(CanonID && "Merged declaration not known?");
+    
+    Record.push_back(CanonID);
+    Record.push_back(I->second.size());
+    Record.append(I->second.begin(), I->second.end());
+  }
+  Stream.EmitRecord(MERGED_DECLARATIONS, Record);
+}
+
 //===----------------------------------------------------------------------===//
 // General Serialization Routines
 //===----------------------------------------------------------------------===//
@@ -3401,7 +3420,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   WriteDeclUpdatesBlocks();
   WriteDeclReplacementsBlock();
   WriteChainedObjCCategories();
-
+  WriteMergedDecls();
+  
   if (!LocalRedeclarations.empty()) {
     // Sort the local redeclarations info by the first declaration ID,
     // since the reader will be perforing binary searches on this information.
index ce4368d08a01d76965973c890a6ef09a823bc814..50c191c8b60728a76975bc58eb43153d830276fd 100644 (file)
@@ -8,6 +8,8 @@ __import_module__ redecl_merge_right;
 
 @class A;
 
+void refers_to_C4(C4*);
+
 #ifdef __cplusplus
 template<typename T> class Vector;
 
index 7f355e8f9d686f8e346f5319e5f9c516df9685fb..c4789ad0c03b919dea93f36d047c4d7a4f53b4e4 100644 (file)
@@ -22,6 +22,8 @@ void accept_a_C2(C2*);
 void accept_a_C3(C3*);
 @class C3;
 
+@class C4;
+
 @class Explicit;
 
 int *explicit_func(void);
index 930e8df6b87fe13078a413b159293c775d4fb8df..ea04037707edc5f005bb436ce63f1d58186df258 100644 (file)
@@ -58,13 +58,18 @@ void test_C3(C3 *c3) {
 C4 *global_C4;
 __import_module__ redecl_merge_left_left;
 
-void test_C4(C4 *c4) {
+void test_C4a(C4 *c4) {
   global_C4 = c4 = get_a_C4();
   accept_a_C4(c4);
 }
 
 __import_module__ redecl_merge_bottom;
 
+void test_C4b() {
+  if (&refers_to_C4) {
+  }
+}
+
 @implementation B
 + (B*)create_a_B { return 0; }
 @end