From fd051a0a2ed4f53faac695be9efd2a2aabd4e7c3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Mar 2015 01:44:51 +0000 Subject: [PATCH] [modules] Avoid accidentally completing the redeclaration chain when updating all the existing declarations of a record-like entity with a pointer to its definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@231901 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTReader.h | 6 +++++ lib/Serialization/ASTReader.cpp | 34 ++++++++++++++----------- lib/Serialization/ASTReaderDecl.cpp | 4 +++ 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 1037160ab2..951a21016f 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1159,6 +1159,12 @@ private: void LoadedDecl(unsigned Index, Decl *D); Decl *ReadDeclRecord(serialization::DeclID ID); void markIncompleteDeclChain(Decl *Canon); + + /// \brief Returns the most recent declaration of a declaration (which must be + /// of a redeclarable kind) that is either local or has already been loaded + /// merged into its redecl chain. + Decl *getMostRecentExistingDecl(Decl *D); + RecordLocation DeclCursorForID(serialization::DeclID ID, unsigned &RawLocation); void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 7e3a779b07..da5a0e68e9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -8369,10 +8369,12 @@ void ASTReader::finishPendingActions() { // Make sure that the TagType points at the definition. const_cast(TagT)->decl = TD; } - + if (auto RD = dyn_cast(D)) { - for (auto R : RD->redecls()) { - assert((R == D) == R->isThisDeclarationADefinition() && + for (auto *R = getMostRecentExistingDecl(RD); R; + R = R->getPreviousDecl()) { + assert((R == D) == + cast(R)->isThisDeclarationADefinition() && "declaration thinks it's the definition but it isn't"); cast(R)->DefinitionData = RD->DefinitionData; } @@ -8380,34 +8382,36 @@ void ASTReader::finishPendingActions() { continue; } - + if (auto ID = dyn_cast(D)) { // Make sure that the ObjCInterfaceType points at the definition. const_cast(cast(ID->TypeForDecl)) ->Decl = ID; - - for (auto R : ID->redecls()) - R->Data = ID->Data; - + + for (auto *R = getMostRecentExistingDecl(ID); R; R = R->getPreviousDecl()) + cast(R)->Data = ID->Data; + continue; } - + if (auto PD = dyn_cast(D)) { - for (auto R : PD->redecls()) - R->Data = PD->Data; - + for (auto *R = getMostRecentExistingDecl(PD); R; R = R->getPreviousDecl()) + cast(R)->Data = PD->Data; + continue; } - + auto RTD = cast(D)->getCanonicalDecl(); - for (auto R : RTD->redecls()) - R->Common = RTD->Common; + for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl()) + cast(R)->Common = RTD->Common; } PendingDefinitions.clear(); // Load the bodies of any functions or methods we've encountered. We do // this now (delayed) so that we can be sure that the declaration chains // have been fully wired up. + // FIXME: There seems to be no point in delaying this, it does not depend + // on the redecl chains having been wired up. for (PendingBodiesMap::iterator PB = PendingBodies.begin(), PBEnd = PendingBodies.end(); PB != PBEnd; ++PB) { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 0789ba5e3e..565f33ecba 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2799,6 +2799,10 @@ Decl *ASTDeclReader::getMostRecentDecl(Decl *D) { llvm_unreachable("unknown decl kind"); } +Decl *ASTReader::getMostRecentExistingDecl(Decl *D) { + return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl()); +} + template void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable *D, -- 2.40.0