forked from OSchip/llvm-project
Defer loading any pending update records until we've finished deserializing.
This fixes a bug where an update record causes us to load an entity that refers to an entity we've not finished loading yet, resulting in badness. llvm-svn: 207603
This commit is contained in:
parent
b5b622a03c
commit
d1c4674603
|
@ -3430,6 +3430,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
||||||
llvm::SaveAndRestore<SourceLocation>
|
llvm::SaveAndRestore<SourceLocation>
|
||||||
SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
|
SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
|
||||||
|
|
||||||
|
// Defer any pending actions until we get to the end of reading the AST file.
|
||||||
|
Deserializing AnASTFile(this);
|
||||||
|
|
||||||
// Bump the generation number.
|
// Bump the generation number.
|
||||||
unsigned PreviousGeneration = CurrentGeneration++;
|
unsigned PreviousGeneration = CurrentGeneration++;
|
||||||
|
|
||||||
|
@ -3742,24 +3745,6 @@ void ASTReader::InitializeContext() {
|
||||||
DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
|
DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
|
||||||
Context.getTranslationUnitDecl());
|
Context.getTranslationUnitDecl());
|
||||||
|
|
||||||
// For any declarations we have already loaded, load any update records.
|
|
||||||
{
|
|
||||||
// We're not back to a consistent state until all our pending update
|
|
||||||
// records have been loaded. There can be interdependencies between them.
|
|
||||||
Deserializing SomeUpdateRecords(this);
|
|
||||||
ReadingKindTracker ReadingKind(Read_Decl, *this);
|
|
||||||
|
|
||||||
// Make sure we load the declaration update records for the translation
|
|
||||||
// unit, if there are any.
|
|
||||||
// FIXME: Is this necessary any more?
|
|
||||||
loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID,
|
|
||||||
Context.getTranslationUnitDecl());
|
|
||||||
|
|
||||||
for (auto &Update : PendingUpdateRecords)
|
|
||||||
loadDeclUpdateRecords(Update.first, Update.second);
|
|
||||||
PendingUpdateRecords.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Find a better way to deal with collisions between these
|
// FIXME: Find a better way to deal with collisions between these
|
||||||
// built-in types. Right now, we just ignore the problem.
|
// built-in types. Right now, we just ignore the problem.
|
||||||
|
|
||||||
|
@ -8057,6 +8042,13 @@ void ASTReader::finishPendingActions() {
|
||||||
Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext());
|
Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform any pending declaration updates.
|
||||||
|
while (!PendingUpdateRecords.empty()) {
|
||||||
|
auto Update = PendingUpdateRecords.pop_back_val();
|
||||||
|
ReadingKindTracker ReadingKind(Read_Decl, *this);
|
||||||
|
loadDeclUpdateRecords(Update.first, Update.second);
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger the import of the full definition of each class that had any
|
// Trigger the import of the full definition of each class that had any
|
||||||
// odr-merging problems, so we can produce better diagnostics for them.
|
// odr-merging problems, so we can produce better diagnostics for them.
|
||||||
for (auto &Merge : PendingOdrMergeFailures) {
|
for (auto &Merge : PendingOdrMergeFailures) {
|
||||||
|
|
|
@ -2801,7 +2801,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
||||||
assert(Idx == Record.size());
|
assert(Idx == Record.size());
|
||||||
|
|
||||||
// Load any relevant update records.
|
// Load any relevant update records.
|
||||||
loadDeclUpdateRecords(ID, D);
|
PendingUpdateRecords.push_back(std::make_pair(ID, D));
|
||||||
|
|
||||||
// Load the categories after recursive loading is finished.
|
// Load the categories after recursive loading is finished.
|
||||||
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
|
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
|
||||||
|
|
|
@ -51,3 +51,8 @@ void useExplicitInstantiation() {
|
||||||
ExplicitInstantiation<true, false>().f();
|
ExplicitInstantiation<true, false>().f();
|
||||||
ExplicitInstantiation<true, true>().f();
|
ExplicitInstantiation<true, true>().f();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename> struct DelayUpdates;
|
||||||
|
template<> struct DelayUpdates<int>;
|
||||||
|
template<typename T> struct DelayUpdates<T*>;
|
||||||
|
template<typename T> void testDelayUpdates(DelayUpdates<T> *p = 0) {}
|
||||||
|
|
|
@ -29,3 +29,5 @@ template<typename T> struct Outer {
|
||||||
template<bool, bool> struct ExplicitInstantiation {
|
template<bool, bool> struct ExplicitInstantiation {
|
||||||
void f() {}
|
void f() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename> struct DelayUpdates {};
|
||||||
|
|
|
@ -84,3 +84,5 @@ template<typename T> void MergePatternDecl<T>::f(Type type) {}
|
||||||
// CHECK: define {{.*}}@_ZN21ExplicitInstantiationILb0ELb1EE1fEv(
|
// CHECK: define {{.*}}@_ZN21ExplicitInstantiationILb0ELb1EE1fEv(
|
||||||
template struct ExplicitInstantiation<false, true>;
|
template struct ExplicitInstantiation<false, true>;
|
||||||
template struct ExplicitInstantiation<true, true>;
|
template struct ExplicitInstantiation<true, true>;
|
||||||
|
|
||||||
|
void testDelayUpdatesImpl() { testDelayUpdates<int>(); }
|
||||||
|
|
Loading…
Reference in New Issue