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

Reply via email to