]> granicus.if.org Git - clang/commitdiff
Introduce the local -> global declaration ID mapping into the AST
authorDouglas Gregor <dgregor@apple.com>
Wed, 3 Aug 2011 15:48:04 +0000 (15:48 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 3 Aug 2011 15:48:04 +0000 (15:48 +0000)
reader, to allow AST files to be loaded with their declarations
remapped to different ID numbers. Fix a number of places where we were
either failing to map local declaration IDs into global declaration
IDs or where interpreting the local declaration IDs within the wrong
module.

I've tested this via the usual "random gaps" method. It works well
except for the preamble tests, because our handling of the precompiled
preamble requires declaration and preprocessed entity to be stable
when parsing code and then loading that back into memory. This
property will hold in general, but my randomized testing naturally
breaks this property to get more coverage. In the future, I expect
that the precompiled preamble logic won't need this property.

I am very unhappy with the current handling of the translation unit,
which is a rather egregious hack. We're going to have to do something
very different here for loading multiple AST files, because we don't
want to have to cope with merging two translation units. Likely, we'll
just handle translation units entirely via "update" records, and
predefine a single, fixed declaration ID for the translation
unit. That will come later.

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

include/clang/Serialization/ASTReader.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp

index 09a5c31bad08a4ddb74ffa5237acc44c6be3a908..2851028dc9b358490fe0f1e721eec0f7d1863db8 100644 (file)
@@ -361,6 +361,9 @@ public:
   /// \brief Base declaration ID for declarations local to this module.
   serialization::DeclID BaseDeclID;
 
+  /// \brief Remapping table for declaration IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
+
   /// \brief The number of C++ base specifier sets in this AST file.
   unsigned LocalNumCXXBaseSpecifiers;
   
@@ -628,7 +631,7 @@ private:
   // TU, and when we read those update records, the actual context will not
   // be available yet (unless it's the TU), so have this pending map using the
   // ID as a key. It will be realized when the context is actually loaded.
-  typedef SmallVector<void *, 1> DeclContextVisibleUpdates;
+  typedef SmallVector<std::pair<void *, Module*>, 1> DeclContextVisibleUpdates;
   typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
       DeclContextVisibleUpdatesPending;
 
@@ -1023,8 +1026,8 @@ private:
   QualType readTypeRecord(unsigned Index);
   RecordLocation TypeCursorForIndex(unsigned Index);
   void LoadedDecl(unsigned Index, Decl *D);
-  Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID);
-  RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID);
+  Decl *ReadDeclRecord(serialization::DeclID ID);
+  RecordLocation DeclCursorForID(serialization::DeclID ID);
   RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
   
   void PassInterestingDeclsToConsumer();
index 4205cdb087e8e821d782141e8d01025d20d0b725..95bc60260c521ac1c63403e39a6e573f05983f55 100644 (file)
@@ -2068,21 +2068,31 @@ ASTReader::ReadASTBlock(Module &F) {
       break;
     }
         
-    case DECL_OFFSET:
+    case DECL_OFFSET: {
       if (F.LocalNumDecls != 0) {
         Error("duplicate DECL_OFFSET record in AST file");
         return Failure;
       }
       F.DeclOffsets = (const uint32_t *)BlobStart;
       F.LocalNumDecls = Record[0];
+      unsigned LocalBaseDeclID = Record[1];
       F.BaseDeclID = getTotalNumDecls();
         
-      // Introduce the global -> local mapping for declarations within this 
-      // AST file.
-      GlobalDeclMap.insert(std::make_pair(getTotalNumDecls() + 1, &F));
-      DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);      
+      if (F.LocalNumDecls > 0) {
+        // Introduce the global -> local mapping for declarations within this 
+        // module.
+        GlobalDeclMap.insert(std::make_pair(getTotalNumDecls() + 1, &F));
+        
+        // Introduce the local -> global mapping for declarations within this
+        // module.
+        F.DeclRemap.insert(std::make_pair(LocalBaseDeclID, 
+                                          F.BaseDeclID - LocalBaseDeclID));
+        
+        DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
+      }
       break;
-
+    }
+        
     case TU_UPDATE_LEXICAL: {
       DeclContextInfo Info = {
         &F,
@@ -2096,28 +2106,28 @@ ASTReader::ReadASTBlock(Module &F) {
     }
 
     case UPDATE_VISIBLE: {
-      serialization::DeclID ID = Record[0];
+      unsigned Idx = 0;
+      serialization::DeclID ID = ReadDeclID(F, Record, Idx);
       void *Table = ASTDeclContextNameLookupTable::Create(
-                        (const unsigned char *)BlobStart + Record[1],
+                        (const unsigned char *)BlobStart + Record[Idx++],
                         (const unsigned char *)BlobStart,
                         ASTDeclContextNameLookupTrait(*this, F));
-      if (ID == 1 && Context) { // Is it the TU?
+      // FIXME: Complete hack to check for the TU
+      if (ID == (*(ModuleMgr.end() - 1))->BaseDeclID + 1 && Context) { // Is it the TU?
         DeclContextInfo Info = {
-          &F, Table, /* No lexical inforamtion */ 0, 0
+          &F, Table, /* No lexical information */ 0, 0
         };
         DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info);
       } else
-        PendingVisibleUpdates[ID].push_back(Table);
+        PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
       break;
     }
 
     case REDECLS_UPDATE_LATEST: {
       assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
-      for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
-        DeclID First = Record[i], Latest = Record[i+1];
-        assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
-                Latest > FirstLatestDeclIDs[First]) &&
-               "The new latest is supposed to come after the previous latest");
+      for (unsigned i = 0, e = Record.size(); i < e; /* in loop */) {
+        DeclID First = ReadDeclID(F, Record, i);
+        DeclID Latest = ReadDeclID(F, Record, i);
         FirstLatestDeclIDs[First] = Latest;
       }
       break;
@@ -2282,6 +2292,7 @@ ASTReader::ReadASTBlock(Module &F) {
       
       // Continuous range maps we may be updating in our module.
       ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);
       ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
 
       while(Data < DataEnd) {
@@ -2312,7 +2323,9 @@ ASTReader::ReadASTBlock(Module &F) {
         (void)PreprocessedEntityIDOffset;
         (void)MacroDefinitionIDOffset;
         (void)SelectorIDOffset;
-        (void)DeclIDOffset;
+        DeclRemap.insert(std::make_pair(DeclIDOffset, 
+                                        OM->BaseDeclID - DeclIDOffset));
+        
         (void)CXXBaseSpecifiersIDOffset;
         
         TypeRemap.insert(std::make_pair(TypeIndexOffset, 
@@ -2474,8 +2487,8 @@ ASTReader::ReadASTBlock(Module &F) {
         return Failure;
       }
       for (unsigned I = 0, N = Record.size(); I != N; I += 2)
-        DeclUpdateOffsets[static_cast<DeclID>(Record[I])]
-            .push_back(std::make_pair(&F, Record[I+1]));
+        DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
+          .push_back(std::make_pair(&F, Record[I+1]));
       break;
     }
 
@@ -2485,8 +2498,8 @@ ASTReader::ReadASTBlock(Module &F) {
         return Failure;
       }
       for (unsigned I = 0, N = Record.size(); I != N; I += 2)
-        ReplacedDecls[static_cast<DeclID>(Record[I])] =
-            std::make_pair(&F, Record[I+1]);
+        ReplacedDecls[getGlobalDeclID(F, Record[I])]
+          = std::make_pair(&F, Record[I+1]);
       break;
     }
         
@@ -4090,19 +4103,30 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
 }
 
 TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() {
-  if (!DeclsLoaded[0]) {
-    ReadDeclRecord(0, 1);
+  // FIXME: This routine might not even make sense when we're loading multiple
+  // unrelated AST files, since we'll have to merge the translation units
+  // somehow.
+  unsigned TranslationUnitID = (*(ModuleMgr.end() - 1))->BaseDeclID + 1;
+  if (!DeclsLoaded[TranslationUnitID - 1]) {
+    ReadDeclRecord(TranslationUnitID);
     if (DeserializationListener)
-      DeserializationListener->DeclRead(1, DeclsLoaded[0]);
+      DeserializationListener->DeclRead(TranslationUnitID, 
+                                        DeclsLoaded[TranslationUnitID - 1]);
   }
 
-  return cast<TranslationUnitDecl>(DeclsLoaded[0]);
+  return cast<TranslationUnitDecl>(DeclsLoaded[TranslationUnitID - 1]);
 }
 
 serialization::DeclID 
 ASTReader::getGlobalDeclID(Module &F, unsigned LocalID) const {
-  // FIXME: Perform local -> global remapping for declarations.
-  return LocalID;
+  if (LocalID == 0)
+    return LocalID;
+
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = F.DeclRemap.find(LocalID - 1);
+  assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");
+  
+  return LocalID + I->second;
 }
 
 Decl *ASTReader::GetDecl(DeclID ID) {
@@ -4116,7 +4140,7 @@ Decl *ASTReader::GetDecl(DeclID ID) {
 
   unsigned Index = ID - 1;
   if (!DeclsLoaded[Index]) {
-    ReadDeclRecord(Index, ID);
+    ReadDeclRecord(ID);
     if (DeserializationListener)
       DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
   }
@@ -5465,7 +5489,7 @@ ASTReader::~ASTReader() {
     for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
                                              F = I->second.end();
          J != F; ++J)
-      delete static_cast<ASTDeclContextNameLookupTable*>(*J);
+      delete static_cast<ASTDeclContextNameLookupTable*>(J->first);
   }
 }
 
@@ -5526,9 +5550,12 @@ void Module::dump() {
   llvm::errs() << "  Base source location offset: " << SLocEntryBaseOffset 
                << '\n';
   dumpLocalRemap("Source location offset map", SLocRemap);
-  llvm::errs() << "  Base type ID: " << BaseTypeIndex << '\n'
+  llvm::errs() << "  Base type index: " << BaseTypeIndex << '\n'
                << "  Number of types: " << LocalNumTypes << '\n';
-  dumpLocalRemap("Type ID map", TypeRemap);
+  dumpLocalRemap("Type index map", TypeRemap);
+  llvm::errs() << "  Base decl ID: " << BaseDeclID << '\n'
+               << "  Number of decls: " << LocalNumDecls << '\n';
+  dumpLocalRemap("Decl ID map", DeclRemap);
 }
 
 Module *ModuleManager::lookup(StringRef Name) {
index 546ca4dbe471751f34e22fbd0440f45173a26030..f9a99fc67107e1bf768310f89908a5de77bead67 100644 (file)
@@ -1398,7 +1398,7 @@ static bool isConsumerInterestedIn(Decl *D) {
 
 /// \brief Get the correct cursor and offset for loading a declaration.
 ASTReader::RecordLocation
-ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) {
+ASTReader::DeclCursorForID(DeclID ID) {
   // See if there's an override.
   DeclReplacementMap::iterator It = ReplacedDecls.find(ID);
   if (It != ReplacedDecls.end())
@@ -1407,7 +1407,7 @@ ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) {
   GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID);
   assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
   Module *M = I->second;
-  return RecordLocation(M, M->DeclOffsets[Index - M->BaseDeclID]);
+  return RecordLocation(M, M->DeclOffsets[ID - M->BaseDeclID - 1]);
 }
 
 ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) {
@@ -1438,8 +1438,9 @@ void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
 }
 
 /// \brief Read the declaration at the given offset from the AST file.
-Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
-  RecordLocation Loc = DeclCursorForIndex(Index, ID);
+Decl *ASTReader::ReadDeclRecord(DeclID ID) {
+  unsigned Index = ID - 1;
+  RecordLocation Loc = DeclCursorForID(ID);
   llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
   // Keep track of where we are in the stream, then jump back there
   // after reading this declaration.
@@ -1463,7 +1464,8 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
     assert(false && "Record cannot be de-serialized with ReadDeclRecord");
     break;
   case DECL_TRANSLATION_UNIT:
-    assert(Index == 0 && "Translation unit must be at index 0");
+    assert(Index == Loc.F->BaseDeclID && 
+           "Translation unit must be at first index in file");
     D = Context->getTranslationUnitDecl();
     break;
   case DECL_TYPEDEF:
@@ -1707,12 +1709,12 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
       DeclContextVisibleUpdates &U = I->second;
       DeclContextInfos &Infos = DeclContextOffsets[DC];
       DeclContextInfo Info;
-      Info.F = Loc.F;
       Info.LexicalDecls = 0;
       Info.NumLexicalDecls = 0;
       for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
            UI != UE; ++UI) {
-        Info.NameLookupTableData = *UI;
+        Info.NameLookupTableData = UI->first;
+        Info.F = UI->second;
         Infos.push_back(Info);
       }
       PendingVisibleUpdates.erase(I);
@@ -1759,23 +1761,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, Module &Module,
     switch ((DeclUpdateKind)Record[Idx++]) {
     case UPD_CXX_SET_DEFINITIONDATA: {
       CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
-      CXXRecordDecl *DefinitionDecl = ReadDeclAs<CXXRecordDecl>(Record, Idx);
+      CXXRecordDecl *DefinitionDecl
+        = Reader.ReadDeclAs<CXXRecordDecl>(Module, Record, Idx);
       assert(!RD->DefinitionData && "DefinitionData is already set!");
       InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx);
       break;
     }
 
     case UPD_CXX_ADDED_IMPLICIT_MEMBER:
-        cast<CXXRecordDecl>(D)->addedMember(ReadDecl(Record, Idx));
+      cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(Module, Record, Idx));
       break;
 
     case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
       // It will be added to the template's specializations set when loaded.
-      (void)ReadDecl(Record, Idx);
+      (void)Reader.ReadDecl(Module, Record, Idx);
       break;
 
     case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
-      NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
+      NamespaceDecl *Anon
+        = Reader.ReadDeclAs<NamespaceDecl>(Module, Record, Idx);
       // Guard against these being loaded out of original order. Don't use
       // getNextNamespace(), since it tries to access the context and can't in
       // the middle of deserialization.
index 66c7d5f669adb7b07dec867c7d2985c76d2ba9f5..c3bbecdb0e7f8f9204101429d5e3ab1e8cd0cd77 100644 (file)
@@ -2033,11 +2033,13 @@ void ASTWriter::WriteTypeDeclOffsets() {
   Abbrev = new BitCodeAbbrev();
   Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET));
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
   unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
   Record.clear();
   Record.push_back(DECL_OFFSET);
   Record.push_back(DeclOffsets.size());
+  Record.push_back(FirstDeclID - 1);
   Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets));
 }