]> granicus.if.org Git - clang/commitdiff
[Modules] Preserve source order for the map of late parsed templates.
authorChandler Carruth <chandlerc@gmail.com>
Thu, 26 Mar 2015 09:08:15 +0000 (09:08 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Thu, 26 Mar 2015 09:08:15 +0000 (09:08 +0000)
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

include/clang/Sema/ExternalSemaSource.h
include/clang/Sema/MultiplexExternalSemaSource.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTReader.h
lib/Sema/MultiplexExternalSemaSource.cpp
lib/Sema/SemaTemplate.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/Modules/stress1.cpp

index 1083784fb7f005f868597c5461da59bf2be6e380..430cef7846b53d889fd1f8dfb81651dfff5681ed 100644 (file)
@@ -182,7 +182,7 @@ public:
   /// external source should take care not to introduce the same map entries
   /// repeatedly.
   virtual void ReadLateParsedTemplates(
-      llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {}
+      llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {}
 
   /// \copydoc Sema::CorrectTypo
   /// \note LookupKind must correspond to a valid Sema::LookupNameKind
index 7a57abc01066206bd2f8d8d107dc25b192fd77f0..5f717891032e4ad6bc5dc101001faf671e6ff85f 100644 (file)
@@ -331,8 +331,8 @@ public:
   /// external source should take care not to introduce the same map entries
   /// repeatedly.
   void ReadLateParsedTemplates(
-                         llvm::DenseMap<const FunctionDecl *,
-                                        LateParsedTemplate *> &LPTMap) override;
+      llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap)
+      override;
 
   /// \copydoc ExternalSemaSource::CorrectTypo
   /// \note Returns the first nonempty correction.
index dde928ff914e7c461e7d9f332add57b1a689af31..21fe2e493c2942b0c6da92cc11cd2877dd3e0744 100644 (file)
@@ -455,8 +455,8 @@ public:
   SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2>
     DelayedDefaultedMemberExceptionSpecs;
 
-  typedef llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *>
-  LateParsedTemplateMapT;
+  typedef llvm::MapVector<const FunctionDecl *, LateParsedTemplate *>
+      LateParsedTemplateMapT;
   LateParsedTemplateMapT LateParsedTemplateMap;
 
   /// \brief Callback to the parser to parse templated functions when needed.
index 1471910db47e3b7208e56fd970380bd4f67e466d..f8366f7621a580f4fa40782f3d1318ec5cd0ff0e 100644 (file)
@@ -1832,8 +1832,8 @@ public:
                                            SourceLocation> > &Pending) override;
 
   void ReadLateParsedTemplates(
-                         llvm::DenseMap<const FunctionDecl *,
-                                        LateParsedTemplate *> &LPTMap) override;
+      llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap)
+      override;
 
   /// \brief Load a selector from disk, registering its ID if it exists.
   void LoadSelector(Selector Sel);
index bd7e785780bf3709d11c93e9711b2e3810b2264c..51a12746fddaa03ee4d72aa591c9c7fde6ebc376 100644 (file)
@@ -276,7 +276,7 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
 }
 
 void MultiplexExternalSemaSource::ReadLateParsedTemplates(
-    llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+    llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
   for (size_t i = 0; i < Sources.size(); ++i)
     Sources[i]->ReadLateParsedTemplates(LPTMap);
 }
index fad15bbc4f661b7fabd8bf356b1662115460f50a..805709dab804665fa66b9dd7f076e5a44e81d141 100644 (file)
@@ -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);
 }
index 2273979883aa2f167346adee724bbbefc6891d9c..4d5141bf92159a0baaf7f12cd87cb3d98f4d5d80 100644 (file)
@@ -7453,7 +7453,7 @@ void ASTReader::ReadPendingInstantiations(
 }
 
 void ASTReader::ReadLateParsedTemplates(
-    llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+    llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
   for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N;
        /* In loop */) {
     FunctionDecl *FD = cast<FunctionDecl>(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();
index 7227a97e7b92414947c6634be378c672c3ebbcd3..679419c9c5aec319ccd76e987d78cd36ba5547a4 100644 (file)
@@ -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());
 
index e03e538a3ce504baf771b2b0277009cc32e87bf7..df690aa7e657e07c12e2900bb41a3f04e94bca77 100644 (file)
 //
 // 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 \