]> granicus.if.org Git - clang/commitdiff
[OpenCL] Disallow blocks capture other blocks (v2.0, s6.12.5)
authorAnastasia Stulova <anastasia.stulova@arm.com>
Thu, 16 Feb 2017 11:13:30 +0000 (11:13 +0000)
committerAnastasia Stulova <anastasia.stulova@arm.com>
Thu, 16 Feb 2017 11:13:30 +0000 (11:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@295307 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/SemaOpenCL/invalid-block.cl

index 6049d488de823ac9edb4c425e017d243ba12be7b..615050603d30b4eb8f36d7c766d9b6aa674796a8 100644 (file)
@@ -8299,6 +8299,8 @@ def err_opencl_invalid_block_declaration : Error<
   "invalid block variable declaration - must be %select{const qualified|initialized}0">;
 def err_opencl_extern_block_declaration : Error<
   "invalid block variable declaration - using 'extern' storage class is disallowed">;
+def err_opencl_block_ref_block : Error<
+  "cannot refer to a block inside block">;
 
 // OpenCL v2.0 s6.13.9 - Address space qualifier functions. 
 def err_opencl_builtin_to_addr_arg_num : Error<
index 39116f9c1ea626bb0c636f59ac564d9421689c3d..ce4c22bb7f9d7d6713c7d361f2e97aa963c00d73 100644 (file)
@@ -13565,6 +13565,13 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
     }
     return false;
   }
+  // OpenCL v2.0 s6.12.5: Blocks cannot reference/capture other blocks
+  if (S.getLangOpts().OpenCL && IsBlock &&
+      Var->getType()->isBlockPointerType()) {
+    if (Diagnose)
+      S.Diag(Loc, diag::err_opencl_block_ref_block);
+    return false;
+  }
 
   return true;
 }
index 598784c95a0665d83dcc93ddf0afe04d06dcea09..89bf03264e13d89ad895dbaa6743a58deaebae2b 100644 (file)
@@ -66,3 +66,18 @@ void f6(bl2_t *bl_ptr) { // expected-error{{pointer to type '__generic bl2_t' (a
   *bl;      // expected-error {{invalid argument type 'bl2_t' (aka 'int (__generic ^const)(int)') to unary expression}}
   &bl;      // expected-error {{invalid argument type 'bl2_t' (aka 'int (__generic ^const)(int)') to unary expression}}
 }
+// A block can't reference another block
+kernel void f7() {
+  bl2_t bl1 = ^(int i) {
+    return 1;
+  };
+  void (^bl2)(void) = ^{
+    int i = bl1(1); // expected-error {{cannot refer to a block inside block}}
+  };
+  void (^bl3)(void) = ^{
+  };
+  void (^bl4)(void) = ^{
+    bl3(); // expected-error {{cannot refer to a block inside block}}
+  };
+  return;
+}