Attaching a fix to https://llvm.org/bugs/show_bug.cgi?id=26237
Please review. Many thanks! --Vassil
From da6b27875042ee23afaf898f189e410f177311ad Mon Sep 17 00:00:00 2001 From: Vassil Vassilev <v.g.vassi...@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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits