diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Basic/IdentifierTable.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 165 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 135 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 52 |
9 files changed, 266 insertions, 118 deletions
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 78f8a7cbdb..94ca1789f3 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -37,7 +37,9 @@ IdentifierInfo::IdentifierInfo() { IsCPPOperatorKeyword = false; NeedsHandleIdentifier = false; IsFromAST = false; + ChangedAfterLoad = false; RevertedTokenID = false; + OutOfDate = false; FETokenInfo = 0; Entry = 0; } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 50929158b2..7557f2e0fe 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -51,9 +51,13 @@ void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) { if (MI) { Macros[II] = MI; II->setHasMacroDefinition(true); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); } else if (II->hasMacroDefinition()) { Macros.erase(II); II->setHasMacroDefinition(false); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); } } diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index f6532c2175..cc612fff9f 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -304,6 +304,8 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { // Finally, poison it! II->setIsPoisoned(); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); } } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 31662ad0c1..af0faca43b 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -492,6 +492,13 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { IdentifierInfo &II = *Identifier.getIdentifierInfo(); + // If the information about this identifier is out of date, update it from + // the external source. + if (II.isOutOfDate()) { + ExternalSource->updateOutOfDateIdentifier(II); + Identifier.setKind(II.getTokenID()); + } + // If this identifier was poisoned, and if it was not produced from a macro // expansion, emit an error. if (II.isPoisoned() && CurPPLexer) { diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index a643267085..812f5d64fa 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -15,7 +15,10 @@ #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/Scope.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/Preprocessor.h" using namespace clang; @@ -93,9 +96,11 @@ IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { // IdentifierResolver Implementation //===----------------------------------------------------------------------===// -IdentifierResolver::IdentifierResolver(const LangOptions &langOpt) - : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) { +IdentifierResolver::IdentifierResolver(Preprocessor &PP) + : LangOpt(PP.getLangOptions()), PP(PP), + IdDeclInfos(new IdDeclInfoMap) { } + IdentifierResolver::~IdentifierResolver() { delete IdDeclInfos; } @@ -146,7 +151,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, void IdentifierResolver::AddDecl(NamedDecl *D) { DeclarationName Name = D->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -170,6 +175,9 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) { @@ -195,7 +203,8 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { } if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); // General case: insert the declaration at the appropriate point in the // list, which already has at least two elements. @@ -212,7 +221,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { assert(D && "null param passed"); DeclarationName Name = D->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -233,7 +242,7 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { DeclarationName Name = Old->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -254,6 +263,9 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { /// begin - Returns an iterator for decls with name 'Name'. IdentifierResolver::iterator IdentifierResolver::begin(DeclarationName Name) { + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + readingIdentifier(*II); + void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) return end(); @@ -269,27 +281,142 @@ IdentifierResolver::begin(DeclarationName Name) { return end(); } -void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, - NamedDecl *D) { - II->setIsFromAST(false); - void *Ptr = II->getFETokenInfo<void>(); +namespace { + enum DeclMatchKind { + DMK_Different, + DMK_Replace, + DMK_Ignore + }; +} - if (!Ptr) { - II->setFETokenInfo(D); - return; +/// \brief Compare two declarations to see whether they are different or, +/// if they are the same, whether the new declaration should replace the +/// existing declaration. +static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { + // If the declarations are identical, ignore the new one. + if (Existing == New) + return DMK_Ignore; + + // If the declarations have different kinds, they're obviously different. + if (Existing->getKind() != New->getKind()) + return DMK_Different; + + // If the declarations are redeclarations of each other, keep the newest one. + if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) { + // If the existing declaration is somewhere in the previous declaration + // chain of the new declaration, then prefer the new declaration. + for (Decl::redecl_iterator RD = New->redecls_begin(), + RDEnd = New->redecls_end(); + RD != RDEnd; ++RD) { + if (*RD == Existing) + return DMK_Replace; + + if (RD->isCanonicalDecl()) + break; + } + + return DMK_Ignore; } + + // If the declarations are both Objective-C classes, and one is a forward + // declaration and the other is not, take the full definition. + // FIXME: At some point, we'll actually have to detect collisions better. + // This logic, however, belongs in the AST reader, not here. + if (ObjCInterfaceDecl *ExistingIFace = dyn_cast<ObjCInterfaceDecl>(Existing)) + if (ObjCInterfaceDecl *NewIFace = dyn_cast<ObjCInterfaceDecl>(New)) + if (ExistingIFace->isForwardDecl() != NewIFace->isForwardDecl()) + return ExistingIFace->isForwardDecl()? DMK_Replace : DMK_Ignore; + + return DMK_Different; +} +bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){ + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo<void>(); + + if (!Ptr) { + Name.setFETokenInfo(D); + return true; + } + IdDeclInfo *IDI; - + if (isDeclPtr(Ptr)) { - II->setFETokenInfo(NULL); - IDI = &(*IdDeclInfos)[II]; NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); - IDI->AddDecl(PrevD); - } else - IDI = toIdDeclInfo(Ptr); + + switch (compareDeclarations(PrevD, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + Name.setFETokenInfo(D); + return true; + } + + Name.setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[Name]; + + // If the existing declaration is not visible in translation unit scope, + // then add the new top-level declaration first. + if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + IDI->AddDecl(D); + IDI->AddDecl(PrevD); + } else { + IDI->AddDecl(PrevD); + IDI->AddDecl(D); + } + return true; + } + + IDI = toIdDeclInfo(Ptr); + // See whether this declaration is identical to any existing declarations. + // If not, find the right place to insert it. + for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(), + IEnd = IDI->decls_end(); + I != IEnd; ++I) { + + switch (compareDeclarations(*I, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + *I = D; + return true; + } + + if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + // We've found a declaration that is not visible from the translation + // unit (it's in an inner scope). Insert our declaration here. + IDI->InsertDecl(I, D); + return true; + } + } + + // Add the declaration to the end. IDI->AddDecl(D); + return true; +} + +void IdentifierResolver::readingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); +} + +void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); + + if (II.isFromAST()) + II.setChangedSinceDeserialization(); } //===----------------------------------------------------------------------===// diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 8346cc475f..9b788a7058 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -98,7 +98,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CurContext(0), OriginalLexicalContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0), ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0), - IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), + IdResolver(pp), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), ObjCShouldCallSuperDealloc(false), ObjCShouldCallSuperFinalize(false), @@ -143,11 +143,11 @@ void Sema::Initialize() { // If either of the 128-bit integer types are unavailable to name lookup, // define them now. DeclarationName Int128 = &Context.Idents.get("__int128_t"); - if (IdentifierResolver::begin(Int128) == IdentifierResolver::end()) + if (IdResolver.begin(Int128) == IdResolver.end()) PushOnScopeChains(Context.getInt128Decl(), TUScope); DeclarationName UInt128 = &Context.Idents.get("__uint128_t"); - if (IdentifierResolver::begin(UInt128) == IdentifierResolver::end()) + if (IdResolver.begin(UInt128) == IdResolver.end()) PushOnScopeChains(Context.getUInt128Decl(), TUScope); } @@ -157,18 +157,18 @@ void Sema::Initialize() { // If 'SEL' does not yet refer to any declarations, make it refer to the // predefined 'SEL'. DeclarationName SEL = &Context.Idents.get("SEL"); - if (IdentifierResolver::begin(SEL) == IdentifierResolver::end()) + if (IdResolver.begin(SEL) == IdResolver.end()) PushOnScopeChains(Context.getObjCSelDecl(), TUScope); // If 'id' does not yet refer to any declarations, make it refer to the // predefined 'id'. DeclarationName Id = &Context.Idents.get("id"); - if (IdentifierResolver::begin(Id) == IdentifierResolver::end()) + if (IdResolver.begin(Id) == IdResolver.end()) PushOnScopeChains(Context.getObjCIdDecl(), TUScope); // Create the built-in typedef for 'Class'. DeclarationName Class = &Context.Idents.get("Class"); - if (IdentifierResolver::begin(Class) == IdentifierResolver::end()) + if (IdResolver.begin(Class) == IdResolver.end()) PushOnScopeChains(Context.getObjCClassDecl(), TUScope); } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5f26c3185b..fb00c918ab 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -938,6 +938,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } } +void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { + if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope) + TUScope->AddDecl(D); +} + bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) { return IdResolver.isDeclInScope(D, Ctx, Context, S, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index d47bb3701d..5898ff0961 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -514,6 +514,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); Reader.SetIdentifierInfo(ID, II); II->setIsFromAST(); + II->setOutOfDate(false); return II; } @@ -539,7 +540,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, IdentifierInfo *II = KnownII; if (!II) II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second)); - Reader.SetIdentifierInfo(ID, II); + II->setOutOfDate(false); + II->setIsFromAST(); // Set or check the various bits in the IdentifierInfo structure. // Token IDs are read-only. @@ -564,6 +566,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, DataLen -= 4; } + Reader.SetIdentifierInfo(ID, II); + // Read all of the declarations visible at global scope with this // name. if (DataLen > 0) { @@ -573,7 +577,6 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k, Reader.SetGloballyVisibleDecls(II, DeclIDs); } - II->setIsFromAST(); return II; } @@ -1276,6 +1279,7 @@ void ASTReader::ReadMacroRecord(Module &F, uint64_t Offset) { Error("macro must have a name in AST file"); return; } + SourceLocation Loc = ReadSourceLocation(F, Record[1]); bool isUsed = Record[2]; @@ -1500,6 +1504,46 @@ void ASTReader::LoadMacroDefinition(IdentifierInfo *II) { LoadMacroDefinition(Pos); } +namespace { + /// \brief Visitor class used to look up identifirs in an AST file. + class IdentifierLookupVisitor { + StringRef Name; + IdentifierInfo *Found; + public: + explicit IdentifierLookupVisitor(StringRef Name) : Name(Name), Found() { } + + static bool visit(Module &M, void *UserData) { + IdentifierLookupVisitor *This + = static_cast<IdentifierLookupVisitor *>(UserData); + + ASTIdentifierLookupTable *IdTable + = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; + if (!IdTable) + return false; + + std::pair<const char*, unsigned> Key(This->Name.begin(), + This->Name.size()); + ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key); + if (Pos == IdTable->end()) + return false; + + // Dereferencing the iterator has the effect of building the + // IdentifierInfo node and populating it with the various + // declarations it needs. + This->Found = *Pos; + return true; + } + + // \brief Retrieve the identifier info found within the module + // files. + IdentifierInfo *getIdentifierInfo() const { return Found; } + }; +} + +void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) { + get(II.getName()); +} + const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { std::string Filename = filenameStrRef; MaybeAddSystemRootToFilename(Filename); @@ -2329,43 +2373,6 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(Module &M) { return Success; } -namespace { - /// \brief Visitor class used to look up identifirs in an AST file. - class IdentifierLookupVisitor { - StringRef Name; - IdentifierInfo *Found; - public: - explicit IdentifierLookupVisitor(StringRef Name) : Name(Name), Found() { } - - static bool visit(Module &M, void *UserData) { - IdentifierLookupVisitor *This - = static_cast<IdentifierLookupVisitor *>(UserData); - - ASTIdentifierLookupTable *IdTable - = (ASTIdentifierLookupTable *)M.IdentifierLookupTable; - if (!IdTable) - return false; - - std::pair<const char*, unsigned> Key(This->Name.begin(), - This->Name.size()); - ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key); - if (Pos == IdTable->end()) - return false; - - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - This->Found = *Pos; - return true; - } - - // \brief Retrieve the identifier info found within the module - // files. - IdentifierInfo *getIdentifierInfo() const { return Found; } - }; -} - - ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type) { switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) { @@ -2384,33 +2391,13 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, CheckPredefinesBuffers()) return IgnorePCH; - // Initialization of keywords and pragmas occurs before the - // AST file is read, so there may be some identifiers that were - // loaded into the IdentifierTable before we intercepted the - // creation of identifiers. Iterate through the list of known - // identifiers and determine whether we have to establish - // preprocessor definitions or top-level identifier declaration - // chains for those identifiers. - // - // We copy the IdentifierInfo pointers to a small vector first, - // since de-serializing declarations or macro definitions can add - // new entries into the identifier table, invalidating the - // iterators. - // - // FIXME: We need a lazier way to load this information, e.g., by marking - // the identifier data as 'dirty', so that it will be looked up in the - // AST file(s) if it is uttered in the source. This could save us some - // module load time. - SmallVector<IdentifierInfo *, 128> Identifiers; + // Mark all of the identifiers in the identifier table as being out of date, + // so that various accessors know to check the loaded modules when the + // identifier is used. for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(), IdEnd = PP.getIdentifierTable().end(); Id != IdEnd; ++Id) - Identifiers.push_back(Id->second); - - for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { - IdentifierLookupVisitor Visitor(Identifiers[I]->getName()); - ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); - } + Id->second->setOutOfDate(true); InitializeContext(); @@ -4412,10 +4399,8 @@ void ASTReader::InitializeSema(Sema &S) { // Makes sure any declarations that were deserialized "too early" // still get added to the identifier's declaration chains. for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) { - if (SemaObj->TUScope) - SemaObj->TUScope->AddDecl(PreloadedDecls[I]); - - SemaObj->IdResolver.AddDecl(PreloadedDecls[I]); + SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I], + PreloadedDecls[I]->getDeclName()); } PreloadedDecls.clear(); @@ -4446,7 +4431,10 @@ void ASTReader::InitializeSema(Sema &S) { IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart)); ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor); - return Visitor.getIdentifierInfo(); + IdentifierInfo *II = Visitor.getIdentifierInfo(); + if (II) + II->setOutOfDate(false); + return II; } namespace clang { @@ -4775,13 +4763,10 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II, for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); if (SemaObj) { - if (SemaObj->TUScope) { - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - SemaObj->TUScope->AddDecl(D); - } - SemaObj->IdResolver.AddDeclToIdentifierChain(II, D); + // Introduce this declaration into the translation-unit scope + // and add it to the declaration chain for this identifier, so + // that (unqualified) name lookup will find it. + SemaObj->pushExternalDeclIntoScope(D, II); } else { // Queue this declaration so that it will be added to the // translation unit scope and identifier's declaration chain diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index ba9a82bbb7..3f1a1d8ce8 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1664,8 +1664,9 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // chained PCH, by storing the offset into the original PCH rather than // writing the macro definition a second time. if (MI->isBuiltinMacro() || - (Chain && Name->isFromAST() && MI->isFromAST() && - !MI->hasChangedAfterLoad())) + (Chain && + Name->isFromAST() && !Name->hasChangedSinceDeserialization() && + MI->isFromAST() && !MI->hasChangedAfterLoad())) continue; AddIdentifierRef(Name, Record); @@ -2191,6 +2192,7 @@ namespace { class ASTIdentifierTableTrait { ASTWriter &Writer; Preprocessor &PP; + IdentifierResolver &IdResolver; bool IsModule; /// \brief Determines whether this is an "interesting" identifier @@ -2200,6 +2202,7 @@ class ASTIdentifierTableTrait { if (II->isPoisoned() || II->isExtensionToken() || II->getObjCOrBuiltinID() || + II->hasRevertedTokenIDToIdentifier() || II->getFETokenInfo<void>()) return true; @@ -2223,15 +2226,16 @@ public: typedef IdentID data_type; typedef data_type data_type_ref; - ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, bool IsModule) - : Writer(Writer), PP(PP), IsModule(IsModule) { } + ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, + IdentifierResolver &IdResolver, bool IsModule) + : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule) { } static unsigned ComputeHash(const IdentifierInfo* II) { return llvm::HashString(II->getName()); } std::pair<unsigned,unsigned> - EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { + EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 MacroInfo *Macro = 0; @@ -2239,8 +2243,9 @@ public: DataLen += 2; // 2 bytes for builtin ID, flags if (hasMacroDefinition(II, Macro)) DataLen += 4; - for (IdentifierResolver::iterator D = IdentifierResolver::begin(II), - DEnd = IdentifierResolver::end(); + + for (IdentifierResolver::iterator D = IdResolver.begin(II), + DEnd = IdResolver.end(); D != DEnd; ++D) DataLen += sizeof(DeclID); } @@ -2285,14 +2290,13 @@ public: // Emit the declaration IDs in reverse order, because the // IdentifierResolver provides the declarations as they would be // visible (e.g., the function "stat" would come before the struct - // "stat"), but IdentifierResolver::AddDeclToIdentifierChain() - // adds declarations to the end of the list (so we need to see the - // struct "status" before the function "status"). + // "stat"), but the ASTReader adds declarations to the end of the list + // (so we need to see the struct "status" before the function "status"). // Only emit declarations that aren't from a chained PCH, though. - SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), - IdentifierResolver::end()); + SmallVector<Decl *, 16> Decls(IdResolver.begin(II), + IdResolver.end()); for (SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), - DEnd = Decls.rend(); + DEnd = Decls.rend(); D != DEnd; ++D) clang::io::Emit32(Out, Writer.getDeclID(*D)); } @@ -2304,14 +2308,16 @@ public: /// The identifier table consists of a blob containing string data /// (the actual identifiers themselves) and a separate "offsets" index /// that maps identifier IDs to locations within the blob. -void ASTWriter::WriteIdentifierTable(Preprocessor &PP, bool IsModule) { +void ASTWriter::WriteIdentifierTable(Preprocessor &PP, + IdentifierResolver &IdResolver, + bool IsModule) { using namespace llvm; // Create and write out the blob that contains the identifier // strings. { OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator; - ASTIdentifierTableTrait Trait(*this, PP, IsModule); + ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash @@ -2330,7 +2336,8 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, bool IsModule) { ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); ID != IDEnd; ++ID) { assert(ID->first && "NULL identifier in identifier table"); - if (!Chain || !ID->first->isFromAST()) + if (!Chain || !ID->first->isFromAST() || + ID->first->hasChangedSinceDeserialization()) Generator.insert(const_cast<IdentifierInfo *>(ID->first), ID->second, Trait); } @@ -2339,7 +2346,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP, bool IsModule) { llvm::SmallString<4096> IdentifierTable; uint32_t BucketOffset; { - ASTIdentifierTableTrait Trait(*this, PP, IsModule); + ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule); llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 clang::io::Emit32(Out, 0); @@ -2791,6 +2798,15 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, getIdentifierRef(&Table.get(BuiltinNames[I])); } + // If there are any out-of-date identifiers, bring them up to date. + if (ExternalPreprocessorSource *ExtSource = PP.getExternalSource()) { + for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), + IDEnd = PP.getIdentifierTable().end(); + ID != IDEnd; ++ID) + if (ID->second->isOutOfDate()) + ExtSource->updateOutOfDateIdentifier(*ID->second); + } + // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. @@ -3018,7 +3034,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); WriteSelectors(SemaRef); WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP, IsModule); + WriteIdentifierTable(PP, SemaRef.IdResolver, IsModule); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); |