diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-03 03:32:14 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-03 03:32:14 +0000 |
commit | 2a9e5c57ef559fd8b19438720eed47e9de615962 (patch) | |
tree | 646bd7d38dac72a734cd663f6fd41010110ae501 /clang/lib/Serialization/ASTReaderDecl.cpp | |
parent | decf03b68f7a41c78cf391234fcaa8bd69e419d5 (diff) | |
download | bcm5719-llvm-2a9e5c57ef559fd8b19438720eed47e9de615962.tar.gz bcm5719-llvm-2a9e5c57ef559fd8b19438720eed47e9de615962.zip |
[modules] Be sure to load the lexical definition of a class template
specialization from an update record exactly once, even if we needed to fake up
the definition.
llvm-svn: 227939
Diffstat (limited to 'clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 754b0a0a535..7f666a46077 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -103,7 +103,7 @@ namespace clang { return Reader.getSubmodule(readSubmoduleID(R, I)); } - void ReadCXXRecordDefinition(CXXRecordDecl *D); + void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, const RecordData &R, unsigned &I); void MergeDefinitionData(CXXRecordDecl *D, @@ -1360,11 +1360,13 @@ void ASTDeclReader::MergeDefinitionData( "merging class definition into non-definition"); auto &DD = *D->DefinitionData.getNotUpdated(); - if (Reader.PendingFakeDefinitionData.count(&DD)) { + auto PFDI = Reader.PendingFakeDefinitionData.find(&DD); + if (PFDI != Reader.PendingFakeDefinitionData.end() && + PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) { // We faked up this definition data because we found a class for which we'd // not yet loaded the definition. Replace it with the real thing now. - Reader.PendingFakeDefinitionData.erase(&DD); assert(!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?"); + PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded; // Don't change which declaration is the definition; that is required // to be invariant once we select it. @@ -1458,7 +1460,7 @@ void ASTDeclReader::MergeDefinitionData( Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition); } -void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { +void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { struct CXXRecordDecl::DefinitionData *DD; ASTContext &C = Reader.getContext(); @@ -1491,6 +1493,11 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) { if (Canon == D) { D->DefinitionData = DD; D->IsCompleteDefinition = true; + + // If this is an update record, we can have redeclarations already. Make a + // note that we need to propagate the DefinitionData pointer onto them. + if (Update) + Reader.PendingDefinitions.insert(D); } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) { // We have already deserialized a definition of this record. This // definition is no longer really a definition. Note that the pre-existing @@ -1556,7 +1563,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { bool WasDefinition = Record[Idx++]; if (WasDefinition) - ReadCXXRecordDefinition(D); + ReadCXXRecordDefinition(D, /*Update*/false); else // Propagate DefinitionData pointer from the canonical declaration. D->DefinitionData = D->getCanonicalDecl()->DefinitionData; @@ -2573,7 +2580,8 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, RD->getCanonicalDecl()->DefinitionData = DD; // Track that we did this horrible thing so that we can fix it later. - Reader.PendingFakeDefinitionData.insert(DD); + Reader.PendingFakeDefinitionData.insert( + std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); } return DD->Definition; @@ -3638,18 +3646,19 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast<CXXRecordDecl>(D); - bool HadRealDefinition = RD->getDefinition() && - !Reader.PendingFakeDefinitionData.count( - RD->DefinitionData.getNotUpdated()); - ReadCXXRecordDefinition(RD); + auto *OldDD = RD->DefinitionData.getNotUpdated(); + bool HadRealDefinition = + OldDD && !Reader.PendingFakeDefinitionData.count(OldDD); + ReadCXXRecordDefinition(RD, /*Update*/true); + // Visible update is handled separately. uint64_t LexicalOffset = Record[Idx++]; if (!HadRealDefinition && LexicalOffset) { RD->setHasExternalLexicalStorage(true); Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor, - std::make_pair(LexicalOffset, 0), - ModuleFile.DeclContextInfos[RD]); - Reader.PendingDefinitions.insert(RD); + std::make_pair(LexicalOffset, 0), + ModuleFile.DeclContextInfos[RD]); + Reader.PendingFakeDefinitionData.erase(OldDD); } auto TSK = (TemplateSpecializationKind)Record[Idx++]; |