From: Richard Smith Date: Thu, 7 Aug 2014 20:58:41 +0000 (+0000) Subject: [modules] Don't defer performing updates if we have incomplete redecl chains. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=916938ce651d3fc6a7567ff0f9f2ef86ff2a0e1c;p=clang [modules] Don't defer performing updates if we have incomplete redecl chains. Instead, perform them carefully immediately. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215147 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4847678d25..4733c6bdeb 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 078e9c86f2..b153043082 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -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> merged_redecls(DeclT *D) { MergedRedeclIterator()); } +template +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, ModuleFile &ModuleFile, // 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(FD)) @@ -3379,9 +3401,13 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, } case UPD_CXX_DEDUCED_RETURN_TYPE: { - FunctionDecl *FD = cast(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(Redecl); + Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType); + } break; } @@ -3389,17 +3415,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, // 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; }