r215147 - [modules] Don't defer performing updates if we have incomplete redecl chains.

Richard Smith richard-llvm at metafoo.co.uk
Thu Aug 7 13:58:41 PDT 2014


Author: rsmith
Date: Thu Aug  7 15:58:41 2014
New Revision: 215147

URL: http://llvm.org/viewvc/llvm-project?rev=215147&view=rev
Log:
[modules] Don't defer performing updates if we have incomplete redecl chains.
Instead, perform them carefully immediately.

Modified:
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=215147&r1=215146&r2=215147&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Aug  7 15:58:41 2014
@@ -8125,10 +8125,7 @@ void ASTReader::finishPendingActions() {
     }
 
     // Perform any pending declaration updates.
-    //
-    // Don't do this if we have known-incomplete redecl chains: it relies on
-    // being able to walk redeclaration chains.
-    while (PendingDeclChains.empty() && !PendingUpdateRecords.empty()) {
+    while (!PendingUpdateRecords.empty()) {
       auto Update = PendingUpdateRecords.pop_back_val();
       ReadingKindTracker ReadingKind(Read_Decl, *this);
       loadDeclUpdateRecords(Update.first, Update.second);

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=215147&r1=215146&r2=215147&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Aug  7 15:58:41 2014
@@ -3208,9 +3208,11 @@ public:
   DeclT *operator*() { return Current; }
 
   MergedRedeclIterator &operator++() {
-    if (Current->isFirstDecl())
+    if (Current->isFirstDecl()) {
       Canonical = Current;
-    Current = Current->getPreviousDecl();
+      Current = Current->getMostRecentDecl();
+    } else
+      Current = Current->getPreviousDecl();
 
     // If we started in the merged portion, we'll reach our start position
     // eventually. Otherwise, we'll never reach it, but the second declaration
@@ -3234,11 +3236,34 @@ llvm::iterator_range<MergedRedeclIterato
       MergedRedeclIterator<DeclT>());
 }
 
+template<typename DeclT, typename Fn>
+static void forAllLaterRedecls(DeclT *D, Fn F) {
+  F(D);
+
+  // Check whether we've already merged D into its redeclaration chain.
+  // MostRecent may or may not be nullptr if D has not been merged. If
+  // not, walk the merged redecl chain and see if it's there.
+  auto *MostRecent = D->getMostRecentDecl();
+  bool Found = false;
+  for (auto *Redecl = MostRecent; Redecl && !Found;
+       Redecl = Redecl->getPreviousDecl())
+    Found = (Redecl == D);
+
+  // If this declaration is merged, apply the functor to all later decls.
+  if (Found) {
+    for (auto *Redecl = MostRecent; Redecl != D;
+         Redecl = Redecl->getPreviousDecl())
+      F(Redecl);
+  }
+}
+
 void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
                                const RecordData &Record) {
   while (Idx < Record.size()) {
     switch ((DeclUpdateKind)Record[Idx++]) {
     case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+      // FIXME: If we also have an update record for instantiating the
+      // definition of D, we need that to happen before we get here.
       Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
       assert(MD && "couldn't read decl from update record");
       // FIXME: We should call addHiddenDecl instead, to add the member
@@ -3285,12 +3310,9 @@ void ASTDeclReader::UpdateDecl(Decl *D,
         // Maintain AST consistency: any later redeclarations of this function
         // are inline if this one is. (We might have merged another declaration
         // into this one.)
-        for (auto *D = FD->getMostRecentDecl(); /**/;
-             D = D->getPreviousDecl()) {
-          D->setImplicitlyInline();
-          if (D == FD)
-            break;
-        }
+        forAllLaterRedecls(FD, [](FunctionDecl *FD) {
+          FD->setImplicitlyInline();
+        });
       }
       FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
       if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
@@ -3379,9 +3401,13 @@ void ASTDeclReader::UpdateDecl(Decl *D,
     }
 
     case UPD_CXX_DEDUCED_RETURN_TYPE: {
-      FunctionDecl *FD = cast<FunctionDecl>(D);
-      Reader.Context.adjustDeducedFunctionResultType(
-          FD, Reader.readType(ModuleFile, Record, Idx));
+      // FIXME: Also do this when merging redecls.
+      QualType DeducedResultType = Reader.readType(ModuleFile, Record, Idx);
+      for (auto *Redecl : merged_redecls(D)) {
+        // FIXME: If the return type is already deduced, check that it matches.
+        FunctionDecl *FD = cast<FunctionDecl>(Redecl);
+        Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType);
+      }
       break;
     }
 
@@ -3389,17 +3415,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
       // FIXME: This doesn't send the right notifications if there are
       // ASTMutationListeners other than an ASTWriter.
 
-      // FIXME: We can't both pull in declarations (and thus create new pending
-      // redeclaration chains) *and* walk redeclaration chains in this function.
-      // We should defer the updates that require walking redecl chains.
-
       // Maintain AST consistency: any later redeclarations are used too.
-      for (auto *Redecl = D->getMostRecentDecl(); /**/;
-           Redecl = Redecl->getPreviousDecl()) {
-        Redecl->Used = true;
-        if (Redecl == D)
-          break;
-      }
+      forAllLaterRedecls(D, [](Decl *D) { D->Used = true; });
       break;
     }
 





More information about the cfe-commits mailing list