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 cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits