[PATCH][modules][PR26237]

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Sat Jan 30 06:49:00 PST 2016


Attaching a fix to https://llvm.org/bugs/show_bug.cgi?id=26237

Please review.

Many thanks!
--Vassil
-------------- next part --------------
From da6b27875042ee23afaf898f189e410f177311ad Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Sat, 30 Jan 2016 14:50:06 +0100
Subject: [PATCH] [modules] Writing out template specializations might trigger
 deserialization.

Rebuilding a redecl chain of template (partial) specialization might be trigger
deserialization. If the container's capacity is exceeded the relocation
invalidates the iterators and at best causes a crash. Force deserialization by
copying the collections before iterating.

Fixes PR26237 (https://llvm.org/bugs/show_bug.cgi?id=26237)

I haven't been successful in reducing a reasonable testcase. It should contain
multimodule setup and at least 8 specializations being deserializaed in a very
specific way.
---
 lib/Serialization/ASTWriterDecl.cpp | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index cc67b17..bcf863c 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -191,8 +191,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
@@ -204,8 +204,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]);
@@ -214,6 +212,19 @@ namespace clang {
       unsigned I = Record.size();
       Record.push_back(0);
 
+      auto &Specializations = Common->Specializations;
+      auto &&PartialSpecializations = getPartialSpecializations(Common);
+
+      // AddFirstDeclFromEachModule might trigger deserialization, invalidating
+      // *Specializations iterators. Force the deserialization in advance.
+      llvm::SmallVector<const Decl*, 16> Specs;
+      for (auto &Entry : Specializations)
+	Specs.push_back(getSpecializationDecl(Entry));
+      for (auto &Entry : PartialSpecializations)
+	Specs.push_back(getSpecializationDecl(Entry));
+      for (auto *D : Specs)
+	D->getMostRecentDecl();
+
       for (auto &Entry : Specializations) {
         auto *D = getSpecializationDecl(Entry);
         assert(D->isCanonicalDecl() && "non-canonical decl in set");
-- 
1.9.1



More information about the cfe-commits mailing list