diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-03-22 16:08:04 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-03-22 16:08:04 +0000 |
commit | 643586fe4fcd42b0978efd3566832ab4dce50367 (patch) | |
tree | 4de2bfcbba7f4c7eff9fc2b3af726f917a4e2219 /lib/Serialization | |
parent | 86029ea254a3a54834940787e58adc55d93c695f (diff) |
[PCH] When we are replacing a decl in a chained PCH that is also a DeclContext,
make sure to fully load its external lexical and visible declarations before
re-writing it.
rdar://10914192
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153254 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization')
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 45 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 37 |
2 files changed, 69 insertions, 13 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4c6c9dc524..9436bfb50b 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4972,6 +4972,51 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, return const_cast<DeclContext*>(DC)->lookup(Name); } +namespace { + /// \brief ModuleFile visitor used to complete the visible decls map of a + /// declaration context. + class DeclContextVisibleDeclMapVisitor { + ASTReader &Reader; + DeclContext *DC; + + public: + DeclContextVisibleDeclMapVisitor(ASTReader &Reader, DeclContext *DC) + : Reader(Reader), DC(DC) { } + + static bool visit(ModuleFile &M, void *UserData) { + return static_cast<DeclContextVisibleDeclMapVisitor*>(UserData)->visit(M); + } + + bool visit(ModuleFile &M) { + // Check whether we have any visible declaration information for + // this context in this module. + ModuleFile::DeclContextInfosMap::iterator + Info = M.DeclContextInfos.find(DC); + if (Info == M.DeclContextInfos.end() || + !Info->second.NameLookupTableData) + return false; + + // Look for this name within this module. + ASTDeclContextNameLookupTable *LookupTable = + (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData; + for (ASTDeclContextNameLookupTable::key_iterator + I = LookupTable->key_begin(), + E = LookupTable->key_end(); I != E; ++I) { + DC->lookup(*I); // Force loading of the visible decls for the decl name. + } + + return false; + } + }; +} + +void ASTReader::completeVisibleDeclsMap(DeclContext *DC) { + if (!DC->hasExternalVisibleStorage()) + return; + DeclContextVisibleDeclMapVisitor Visitor(*this, DC); + ModuleMgr.visit(&DeclContextVisibleDeclMapVisitor::visit, &Visitor); +} + /// \brief Under non-PCH compilation the consumer receives the objc methods /// before receiving the implementation, and codegen depends on this. /// We simulate this by deserializing and passing to consumer the methods of the diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index d7cc850a80..7a4ef63bb3 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTWriter.h" +#include "clang/Serialization/ASTReader.h" #include "ASTCommon.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/DeclCXX.h" @@ -1640,6 +1641,20 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { RecordData Record; ASTDeclWriter W(*this, Context, Record); + // Determine the ID for this declaration. + serialization::DeclID ID; + if (D->isFromASTFile()) + ID = getDeclID(D); + else { + serialization::DeclID &IDR = DeclIDs[D]; + if (IDR == 0) + IDR = NextDeclID++; + + ID= IDR; + } + + bool isReplacingADecl = ID < FirstDeclID; + // If this declaration is also a DeclContext, write blocks for the // declarations that lexically stored inside its context and those // declarations that are visible from its context. These blocks @@ -1649,23 +1664,19 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { uint64_t VisibleOffset = 0; DeclContext *DC = dyn_cast<DeclContext>(D); if (DC) { + if (isReplacingADecl) { + // It is replacing a decl from a chained PCH; make sure that the + // DeclContext is fully loaded. + if (DC->hasExternalLexicalStorage()) + DC->LoadLexicalDeclsFromExternalStorage(); + if (DC->hasExternalVisibleStorage()) + Chain->completeVisibleDeclsMap(DC); + } LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); } - - // Determine the ID for this declaration. - serialization::DeclID ID; - if (D->isFromASTFile()) - ID = getDeclID(D); - else { - serialization::DeclID &IDR = DeclIDs[D]; - if (IDR == 0) - IDR = NextDeclID++; - - ID= IDR; - } - if (ID < FirstDeclID) { + if (isReplacingADecl) { // We're replacing a decl in a previous file. ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(), D->getLocation())); |