]> granicus.if.org Git - clang/commitdiff
Defer loading any pending update records until we've finished deserializing.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Apr 2014 02:24:17 +0000 (02:24 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Apr 2014 02:24:17 +0000 (02:24 +0000)
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
lib/Serialization/ASTReaderDecl.cpp
test/Modules/Inputs/templates-left.h
test/Modules/Inputs/templates-top.h
test/Modules/templates.mm

index ccdf3fe10ae608b07e26bc512605e4a1b0044f3c..31b649f16e10e99394471c960ee32e80cb1024ee 100644 (file)
@@ -3430,6 +3430,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
   llvm::SaveAndRestore<SourceLocation>
     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) {
index 96253ca301fa67b58ac40a0d3373a2bb8145083a..5f1d65f8eb1641997f4509105bf16a2f5a122155 100644 (file)
@@ -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<ObjCInterfaceDecl>(D))
index 076a1f43c2d30d20d4e6774f169657e3c4e07845..ae9d8bd8942c25ddeed6f8e6c9adb5a465cebcad 100644 (file)
@@ -51,3 +51,8 @@ void useExplicitInstantiation() {
   ExplicitInstantiation<true, false>().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) {}
index 144bfcd0efd8f9c1796ce7b25f743c4ca7ececcf..168155b5b9c1286b0989126f934b65d2dd0b3f0c 100644 (file)
@@ -29,3 +29,5 @@ template<typename T> struct Outer {
 template<bool, bool> struct ExplicitInstantiation {
   void f() {}
 };
+
+template<typename> struct DelayUpdates {};
index feeae85cc12a71545ec63e357534dafd7336dc3f..ebd55df7b0f8e0860b662adf9685e925b09fbfa4 100644 (file)
@@ -84,3 +84,5 @@ template<typename T> void MergePatternDecl<T>::f(Type type) {}
 // CHECK: define {{.*}}@_ZN21ExplicitInstantiationILb0ELb1EE1fEv(
 template struct ExplicitInstantiation<false, true>;
 template struct ExplicitInstantiation<true, true>;
+
+void testDelayUpdatesImpl() { testDelayUpdates<int>(); }