]> granicus.if.org Git - clang/commitdiff
PR26237: Fix iterator invalidation bug that occurs if serializing
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 24 Feb 2016 21:59:10 +0000 (21:59 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 24 Feb 2016 21:59:10 +0000 (21:59 +0000)
specializations of a template manages to trigger deserialization of more
specializations of the same template.

No test case provided: this is hard to reliably test due to standard library
differences.

Patch by Vassil Vassilev!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261781 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTWriterDecl.cpp

index f2f4a02c876b4562b1ad176511802274592d2576..6ff3f9541681b178db7fadd8db648c452a8274dd 100644 (file)
@@ -192,8 +192,8 @@ namespace clang {
       return None;
     }
 
-    template<typename Decl>
-    void AddTemplateSpecializations(Decl *D) {
+    template<typename DeclTy>
+    void AddTemplateSpecializations(DeclTy *D) {
       auto *Common = D->getCommonPtr();
 
       // If we have any lazy specializations, and the external AST source is
@@ -205,8 +205,6 @@ namespace clang {
         assert(!Common->LazySpecializations);
       }
 
-      auto &Specializations = Common->Specializations;
-      auto &&PartialSpecializations = getPartialSpecializations(Common);
       ArrayRef<DeclID> LazySpecializations;
       if (auto *LS = Common->LazySpecializations)
         LazySpecializations = llvm::makeArrayRef(LS + 1, LS[0]);
@@ -215,13 +213,15 @@ namespace clang {
       unsigned I = Record.size();
       Record.push_back(0);
 
-      for (auto &Entry : Specializations) {
-        auto *D = getSpecializationDecl(Entry);
-        assert(D->isCanonicalDecl() && "non-canonical decl in set");
-        AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
-      }
-      for (auto &Entry : PartialSpecializations) {
-        auto *D = getSpecializationDecl(Entry);
+      // AddFirstDeclFromEachModule might trigger deserialization, invalidating
+      // *Specializations iterators.
+      llvm::SmallVector<const Decl*, 16> Specs;
+      for (auto &Entry : Common->Specializations)
+        Specs.push_back(getSpecializationDecl(Entry));
+      for (auto &Entry : getPartialSpecializations(Common))
+        Specs.push_back(getSpecializationDecl(Entry));
+
+      for (auto *D : Specs) {
         assert(D->isCanonicalDecl() && "non-canonical decl in set");
         AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
       }