From: Chandler Carruth Date: Thu, 26 Mar 2015 09:08:15 +0000 (+0000) Subject: [Modules] Preserve source order for the map of late parsed templates. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2baeab1242a4c166c56eb5f08f5eaddfeffad2b9;p=clang [Modules] Preserve source order for the map of late parsed templates. Clang was inserting these into a dense map. While it never iterated the dense map during normal compilation, it did when emitting a module. Fix this by using a standard MapVector to preserve the order in which we encounter the late parsed templates. I suspect this still isn't ideal, as we don't seem to remove things from this map even when we mark the templates as no longer late parsed. But I don't know enough about this particular extension to craft a nice, subtle test case covering this. I've managed to get the stress test to at least do some late parsing and demonstrate the core problem here. This patch fixes the test and provides deterministic behavior which is a strict improvement over the prior state. I've cleaned up some of the code here as well to be explicit about inserting when that is what is actually going on. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@233264 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 1083784fb7..430cef7846 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -182,7 +182,7 @@ public: /// external source should take care not to introduce the same map entries /// repeatedly. virtual void ReadLateParsedTemplates( - llvm::DenseMap &LPTMap) {} + llvm::MapVector &LPTMap) {} /// \copydoc Sema::CorrectTypo /// \note LookupKind must correspond to a valid Sema::LookupNameKind diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 7a57abc010..5f71789103 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -331,8 +331,8 @@ public: /// external source should take care not to introduce the same map entries /// repeatedly. void ReadLateParsedTemplates( - llvm::DenseMap &LPTMap) override; + llvm::MapVector &LPTMap) + override; /// \copydoc ExternalSemaSource::CorrectTypo /// \note Returns the first nonempty correction. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index dde928ff91..21fe2e493c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -455,8 +455,8 @@ public: SmallVector, 2> DelayedDefaultedMemberExceptionSpecs; - typedef llvm::DenseMap - LateParsedTemplateMapT; + typedef llvm::MapVector + LateParsedTemplateMapT; LateParsedTemplateMapT LateParsedTemplateMap; /// \brief Callback to the parser to parse templated functions when needed. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 1471910db4..f8366f7621 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1832,8 +1832,8 @@ public: SourceLocation> > &Pending) override; void ReadLateParsedTemplates( - llvm::DenseMap &LPTMap) override; + llvm::MapVector &LPTMap) + override; /// \brief Load a selector from disk, registering its ID if it exists. void LoadSelector(Selector Sel); diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp index bd7e785780..51a12746fd 100644 --- a/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/lib/Sema/MultiplexExternalSemaSource.cpp @@ -276,7 +276,7 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations( } void MultiplexExternalSemaSource::ReadLateParsedTemplates( - llvm::DenseMap &LPTMap) { + llvm::MapVector &LPTMap) { for (size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadLateParsedTemplates(LPTMap); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index fad15bbc4f..805709dab8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -8305,7 +8305,7 @@ void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD, // Take tokens to avoid allocations LPT->Toks.swap(Toks); LPT->D = FnD; - LateParsedTemplateMap[FD] = LPT; + LateParsedTemplateMap.insert(std::make_pair(FD, LPT)); FD->setLateTemplateParsed(true); } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 2273979883..4d5141bf92 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -7453,7 +7453,7 @@ void ASTReader::ReadPendingInstantiations( } void ASTReader::ReadLateParsedTemplates( - llvm::DenseMap &LPTMap) { + llvm::MapVector &LPTMap) { for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N; /* In loop */) { FunctionDecl *FD = cast(GetDecl(LateParsedTemplates[Idx++])); @@ -7469,7 +7469,7 @@ void ASTReader::ReadLateParsedTemplates( for (unsigned T = 0; T < TokN; ++T) LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx)); - LPTMap[FD] = LT; + LPTMap.insert(std::make_pair(FD, LT)); } LateParsedTemplates.clear(); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 7227a97e7b..679419c9c5 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4089,11 +4089,10 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { return; RecordData Record; - for (Sema::LateParsedTemplateMapT::iterator It = LPTMap.begin(), - ItEnd = LPTMap.end(); - It != ItEnd; ++It) { - LateParsedTemplate *LPT = It->second; - AddDeclRef(It->first, Record); + for (auto LPTMapEntry : LPTMap) { + const FunctionDecl *FD = LPTMapEntry.first; + LateParsedTemplate *LPT = LPTMapEntry.second; + AddDeclRef(FD, Record); AddDeclRef(LPT->D, Record); Record.push_back(LPT->Toks.size()); diff --git a/test/Modules/stress1.cpp b/test/Modules/stress1.cpp index e03e538a3c..df690aa7e6 100644 --- a/test/Modules/stress1.cpp +++ b/test/Modules/stress1.cpp @@ -17,13 +17,22 @@ // // RUN: diff %t/m00.pcm %t/m00_check.pcm // -// RUN: %clang_cc1 -fmodules -x c++ -std=c++11 \ +// RUN: %clang_cc1 -fmodules -x c++ -std=c++11 -fdelayed-template-parsing \ // RUN: -I Inputs/stress1 \ // RUN: -fno-implicit-modules -fno-modules-implicit-maps \ // RUN: -fmodule-map-file-home-is-cwd \ // RUN: -emit-module -fmodule-name=m01 -o %t/m01.pcm \ // RUN: Inputs/stress1/module.modulemap // +// RUN: %clang_cc1 -fmodules -x c++ -std=c++11 -fdelayed-template-parsing \ +// RUN: -I Inputs/stress1 \ +// RUN: -fno-implicit-modules -fno-modules-implicit-maps \ +// RUN: -fmodule-map-file-home-is-cwd \ +// RUN: -emit-module -fmodule-name=m01 -o %t/m01_check.pcm \ +// RUN: Inputs/stress1/module.modulemap +// +// RUN: diff %t/m01.pcm %t/m01_check.pcm +// // RUN: %clang_cc1 -fmodules -x c++ -std=c++11 \ // RUN: -I Inputs/stress1 \ // RUN: -fno-implicit-modules -fno-modules-implicit-maps \