[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