[cfe-commits] r147181 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Thu Dec 22 13:40:43 PST 2011


Author: dgregor
Date: Thu Dec 22 15:40:42 2011
New Revision: 147181

URL: http://llvm.org/viewvc/llvm-project?rev=147181&view=rev
Log:
Serialize the AST reader's mapping from canonical declarations to the
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.


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

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Dec 22 15:40:42 2011
@@ -452,7 +452,10 @@
       
       /// \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.

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Dec 22 15:40:42 2011
@@ -690,6 +690,26 @@
   /// 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> >

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Thu Dec 22 15:40:42 2011
@@ -415,7 +415,8 @@
   void WriteDeclContextVisibleUpdate(const DeclContext *DC);
   void WriteFPPragmaOptions(const FPOptions &Opts);
   void WriteOpenCLExtensions(Sema &SemaRef);
-
+  void WriteMergedDecls();
+                        
   unsigned DeclParmVarAbbrev;
   unsigned DeclContextLexicalAbbrev;
   unsigned DeclContextVisibleLookupAbbrev;

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Dec 22 15:40:42 2011
@@ -2407,6 +2407,16 @@
       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");

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Dec 22 15:40:42 2011
@@ -676,9 +676,14 @@
         }
         
         // 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 @@
   }
 }
 
+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 @@
 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 @@
     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());  
   

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Dec 22 15:40:42 2011
@@ -2903,6 +2903,25 @@
   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 @@
   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.

Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h Thu Dec 22 15:40:42 2011
@@ -8,6 +8,8 @@
 
 @class A;
 
+void refers_to_C4(C4*);
+
 #ifdef __cplusplus
 template<typename T> class Vector;
 

Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-left.h?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-left.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-left.h Thu Dec 22 15:40:42 2011
@@ -22,6 +22,8 @@
 void accept_a_C3(C3*);
 @class C3;
 
+ at class C4;
+
 @class Explicit;
 
 int *explicit_func(void);

Modified: cfe/trunk/test/Modules/redecl-merge.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/redecl-merge.m?rev=147181&r1=147180&r2=147181&view=diff
==============================================================================
--- cfe/trunk/test/Modules/redecl-merge.m (original)
+++ cfe/trunk/test/Modules/redecl-merge.m Thu Dec 22 15:40:42 2011
@@ -58,13 +58,18 @@
 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





More information about the cfe-commits mailing list