erik.pilkington created this revision.
erik.pilkington added reviewers: rjmccall, rsmith.
Herald added a subscriber: dexonsmith.
Previously, clang would crash here:
template <class T> struct S {
int (^p)() = ^{ return 0; };
};
S<int> x;
The problem was that InstantiateClass() was iterating over all the decls(),
which included the BlockDecl. The template instantiator doesn't know how to
instantiate BlockDecls though, it knows about BlockExprs. This is typically
fine because BlockExprs must be the parent of the BlockDecl. To accommodate
this, delay instantiating the BlockDecl until we're instantiating the
default-member-initializer.
Thanks for taking a look!
Erik
Repository:
rC Clang
https://reviews.llvm.org/D49688
Files:
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/test/SemaCXX/instantiate-blocks.cpp
Index: clang/test/SemaCXX/instantiate-blocks.cpp
===================================================================
--- clang/test/SemaCXX/instantiate-blocks.cpp
+++ clang/test/SemaCXX/instantiate-blocks.cpp
@@ -30,3 +30,12 @@
noret((float)0.0, double(0.0)); // expected-note {{in instantiation of
function template specialization 'noret<float, double>' requested here}}
}
+namespace rdar41200624 {
+template <class T>
+struct S {
+ int (^p)() = ^{ return 0; };
+ T (^t)() = ^{ return T{}; };
+ T s = ^{ return T{}; }();
+};
+S<int> x;
+}
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2083,6 +2083,11 @@
if (Member->getDeclContext() != Pattern)
continue;
+ // BlockDecls can appear in a default-member-initializer. They must be the
+ // child of a BlockExpr, so we only know how to instantiate them from
there.
+ if (isa<BlockDecl>(Member))
+ continue;
+
if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
Index: clang/test/SemaCXX/instantiate-blocks.cpp
===================================================================
--- clang/test/SemaCXX/instantiate-blocks.cpp
+++ clang/test/SemaCXX/instantiate-blocks.cpp
@@ -30,3 +30,12 @@
noret((float)0.0, double(0.0)); // expected-note {{in instantiation of function template specialization 'noret<float, double>' requested here}}
}
+namespace rdar41200624 {
+template <class T>
+struct S {
+ int (^p)() = ^{ return 0; };
+ T (^t)() = ^{ return T{}; };
+ T s = ^{ return T{}; }();
+};
+S<int> x;
+}
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2083,6 +2083,11 @@
if (Member->getDeclContext() != Pattern)
continue;
+ // BlockDecls can appear in a default-member-initializer. They must be the
+ // child of a BlockExpr, so we only know how to instantiate them from there.
+ if (isa<BlockDecl>(Member))
+ continue;
+
if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits