From: Richard Smith Date: Wed, 24 Feb 2016 21:59:10 +0000 (+0000) Subject: PR26237: Fix iterator invalidation bug that occurs if serializing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e639f9c8bbde03a63afea2c1b4834c4536b1dbc8;p=clang PR26237: Fix iterator invalidation bug that occurs if serializing 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 --- diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index f2f4a02c87..6ff3f95416 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -192,8 +192,8 @@ namespace clang { return None; } - template - void AddTemplateSpecializations(Decl *D) { + template + 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 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 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); }