aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Basic/IdentifierTable.cpp2
-rw-r--r--lib/Lex/PPMacroExpansion.cpp4
-rw-r--r--lib/Lex/Pragma.cpp2
-rw-r--r--lib/Lex/Preprocessor.cpp7
-rw-r--r--lib/Sema/IdentifierResolver.cpp165
-rw-r--r--lib/Sema/Sema.cpp12
-rw-r--r--lib/Sema/SemaDecl.cpp5
-rw-r--r--lib/Serialization/ASTReader.cpp135
-rw-r--r--lib/Serialization/ASTWriter.cpp52
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);