]> granicus.if.org Git - clang/commitdiff
Write visible update blocks. No regressions in normal PCH functionality, but no tests...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 24 Aug 2010 00:50:09 +0000 (00:50 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 24 Aug 2010 00:50:09 +0000 (00:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111881 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 75216bf8be4eebe0f63057f947a8ce173f1b71c8..6bdba097c9b56a7a7c812d428f0486d3a6c4f939 100644 (file)
@@ -265,10 +265,12 @@ private:
   void WriteIdentifierTable(Preprocessor &PP);
   void WriteAttributeRecord(const AttrVec &Attrs);
   void WriteDeclUpdateBlock();
+  void WriteDeclContextVisibleUpdate(const DeclContext *DC);
 
   unsigned ParmVarDeclAbbrev;
   unsigned DeclContextLexicalAbbrev;
   unsigned DeclContextVisibleLookupAbbrev;
+  unsigned UpdateVisibleAbbrev;
   void WriteDeclsBlockAbbrevs();
   void WriteDecl(ASTContext &Context, Decl *D);
 
index f47ad3c4d74d65c8cdb6beb398130c91db86e573..dc9f4d409af9b131f387d3984ac72db9716c7e81 100644 (file)
@@ -2013,7 +2013,7 @@ public:
 /// visible from the given DeclContext.
 ///
 /// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
-/// bistream, or 0 if no block was written.
+/// bitstream, or 0 if no block was written.
 uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
                                                  DeclContext *DC) {
   if (DC->getPrimaryContext() != DC)
@@ -2080,6 +2080,64 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
   return Offset;
 }
 
+/// \brief Write an UPDATE_VISIBLE block for the given context.
+///
+/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing
+/// DeclContext in a dependent AST file. As such, they only exist for the TU
+/// (in C++) and for namespaces.
+void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
+  assert((DC->isTranslationUnit() || DC->isNamespace()) &&
+         "Only TU and namespaces should have visible decl updates.");
+
+  // Make the context build its lookup table, but don't make it load external
+  // decls.
+  DC->lookup(DeclarationName());
+
+  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+  if (!Map || Map->empty())
+    return;
+
+  OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+  ASTDeclContextNameLookupTrait Trait(*this);
+
+  // Create the hash table.
+  llvm::SmallVector<NamedDecl *, 16> Decls;
+  for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+       D != DEnd; ++D) {
+    DeclarationName Name = D->first;
+    DeclContext::lookup_result Result = D->second.getLookupResult();
+    // Need to filter these results to only include decls that are not from
+    // an existing PCH.
+    Decls.clear();
+    for (; Result.first != Result.second; ++Result.first) {
+      if ((*Result.first)->getPCHLevel() == 0)
+        Decls.push_back(*Result.first);
+    }
+    if (!Decls.empty()) {
+      Result.first = Decls.data();
+      Result.second = Result.first + Decls.size();
+      Generator.insert(Name, Result, Trait);
+    }
+  }
+
+  // Create the on-disk hash table in a buffer.
+  llvm::SmallString<4096> LookupTable;
+  uint32_t BucketOffset;
+  {
+    llvm::raw_svector_ostream Out(LookupTable);
+    // Make sure that no bucket is at offset 0
+    clang::io::Emit32(Out, 0);
+    BucketOffset = Generator.Emit(Out, Trait);
+  }
+
+  // Write the lookup table
+  RecordData Record;
+  Record.push_back(UPDATE_VISIBLE);
+  Record.push_back(getDeclID(cast<Decl>(DC)));
+  Record.push_back(BucketOffset);
+  Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str());
+}
+
 //===----------------------------------------------------------------------===//
 // General Serialization Routines
 //===----------------------------------------------------------------------===//
@@ -2406,6 +2464,16 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
                           reinterpret_cast<const char*>(NewGlobalDecls.data()),
                           NewGlobalDecls.size() * sizeof(DeclID));
+  // And in C++, a visible updates block for the TU.
+  if (Context.getLangOptions().CPlusPlus) {
+    Abv = new llvm::BitCodeAbbrev();
+    Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
+    Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+    Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32));
+    Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+    UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv);
+    WriteDeclContextVisibleUpdate(TU);
+  }
 
   // Build a record containing all of the new tentative definitions in this
   // file, in TentativeDefinitions order.
@@ -2572,6 +2640,13 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   if (!SemaDeclRefs.empty())
     Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
 
+  // Write the updates to C++ namespaces.
+  for (llvm::SmallPtrSet<const NamespaceDecl *, 16>::iterator
+           I = UpdatedNamespaces.begin(),
+           E = UpdatedNamespaces.end();
+         I != E; ++I)
+    WriteDeclContextVisibleUpdate(*I);
+
   Record.clear();
   Record.push_back(NumStatements);
   Record.push_back(NumMacros);