From 810876919a16f5c2f0f18746b8dd9581746db599 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 30 Apr 2014 02:24:17 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207603 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTReader.cpp | 28 ++++++++++------------------ lib/Serialization/ASTReaderDecl.cpp | 2 +- test/Modules/Inputs/templates-left.h | 5 +++++ test/Modules/Inputs/templates-top.h | 2 ++ test/Modules/templates.mm | 2 ++ 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index ccdf3fe10a..31b649f16e 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3430,6 +3430,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, llvm::SaveAndRestore 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. unsigned PreviousGeneration = CurrentGeneration++; @@ -3742,24 +3745,6 @@ void ASTReader::InitializeContext() { DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, 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 // built-in types. Right now, we just ignore the problem. @@ -8057,6 +8042,13 @@ void ASTReader::finishPendingActions() { 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 // odr-merging problems, so we can produce better diagnostics for them. for (auto &Merge : PendingOdrMergeFailures) { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 96253ca301..5f1d65f8eb 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2801,7 +2801,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { assert(Idx == Record.size()); // Load any relevant update records. - loadDeclUpdateRecords(ID, D); + PendingUpdateRecords.push_back(std::make_pair(ID, D)); // Load the categories after recursive loading is finished. if (ObjCInterfaceDecl *Class = dyn_cast(D)) diff --git a/test/Modules/Inputs/templates-left.h b/test/Modules/Inputs/templates-left.h index 076a1f43c2..ae9d8bd894 100644 --- a/test/Modules/Inputs/templates-left.h +++ b/test/Modules/Inputs/templates-left.h @@ -51,3 +51,8 @@ void useExplicitInstantiation() { ExplicitInstantiation().f(); ExplicitInstantiation().f(); } + +template struct DelayUpdates; +template<> struct DelayUpdates; +template struct DelayUpdates; +template void testDelayUpdates(DelayUpdates *p = 0) {} diff --git a/test/Modules/Inputs/templates-top.h b/test/Modules/Inputs/templates-top.h index 144bfcd0ef..168155b5b9 100644 --- a/test/Modules/Inputs/templates-top.h +++ b/test/Modules/Inputs/templates-top.h @@ -29,3 +29,5 @@ template struct Outer { template struct ExplicitInstantiation { void f() {} }; + +template struct DelayUpdates {}; diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm index feeae85cc1..ebd55df7b0 100644 --- a/test/Modules/templates.mm +++ b/test/Modules/templates.mm @@ -84,3 +84,5 @@ template void MergePatternDecl::f(Type type) {} // CHECK: define {{.*}}@_ZN21ExplicitInstantiationILb0ELb1EE1fEv( template struct ExplicitInstantiation; template struct ExplicitInstantiation; + +void testDelayUpdatesImpl() { testDelayUpdates(); } -- 2.40.0