[clang] bd46a56 - [OpenCL] Reject block arguments

Sven van Haastregt via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 29 06:14:23 PDT 2020


Author: Sven van Haastregt
Date: 2020-06-29T14:13:12+01:00
New Revision: bd46a56474d3b27a4fb520503d5714e23097d495

URL: https://github.com/llvm/llvm-project/commit/bd46a56474d3b27a4fb520503d5714e23097d495
DIFF: https://github.com/llvm/llvm-project/commit/bd46a56474d3b27a4fb520503d5714e23097d495.diff

LOG: [OpenCL] Reject block arguments

OpenCL 2.0 does not allow block arguments, primarily because it is
difficult to support function pointers on the various architectures
that OpenCL targets.  Clang was still accepting them.

Rename and reuse the `err_opencl_half_param` diagnostic.

Fixes PR46324.

Differential Revision: https://reviews.llvm.org/D82313

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaType.cpp
    clang/test/CodeGenOpenCL/blocks.cl
    clang/test/Frontend/opencl.cl
    clang/test/SemaOpenCL/invalid-block.cl

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 70b43f5abc4b..f0921337f312 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -830,8 +830,8 @@ def err_opencl_half_load_store : Error<
 def err_opencl_cast_to_half : Error<"casting to type %0 is not allowed">;
 def err_opencl_half_declaration : Error<
   "declaring variable of type %0 is not allowed">;
-def err_opencl_half_param : Error<
-  "declaring function parameter of type %0 is not allowed; did you forget * ?">;
+def err_opencl_invalid_param : Error<
+  "declaring function parameter of type %0 is not allowed%select{; did you forget * ?|}1">;
 def err_opencl_invalid_return : Error<
   "declaring function return value of type %0 is not allowed %select{; did you forget * ?|}1">;
 def warn_enum_value_overflow : Warning<"overflow in enumeration value">;

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 08d12fc25bf7..52fe292ce113 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5139,8 +5139,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
             // FIXME: This really should be in BuildFunctionType.
             if (S.getLangOpts().OpenCL) {
               if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
-                S.Diag(Param->getLocation(),
-                  diag::err_opencl_half_param) << ParamTy;
+                S.Diag(Param->getLocation(), diag::err_opencl_invalid_param)
+                    << ParamTy << 0;
                 D.setInvalidType();
                 Param->setInvalidDecl();
               }
@@ -5159,6 +5159,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
                 Param->setKNRPromoted(true);
               }
             }
+          } else if (S.getLangOpts().OpenCL && ParamTy->isBlockPointerType()) {
+            // OpenCL 2.0 s6.12.5: A block cannot be a parameter of a function.
+            S.Diag(Param->getLocation(), diag::err_opencl_invalid_param)
+                << ParamTy << 1 /*hint off*/;
+            D.setInvalidType();
           }
 
           if (LangOpts.ObjCAutoRefCount && Param->hasAttr<NSConsumedAttr>()) {

diff  --git a/clang/test/CodeGenOpenCL/blocks.cl b/clang/test/CodeGenOpenCL/blocks.cl
index c3e26855dfe0..f8315515f1d9 100644
--- a/clang/test/CodeGenOpenCL/blocks.cl
+++ b/clang/test/CodeGenOpenCL/blocks.cl
@@ -70,26 +70,6 @@ void foo(){
 
 // COMMON-NOT: define{{.*}}@__foo_block_invoke_kernel
 
-// Test that we support block arguments.
-// COMMON-LABEL: define {{.*}} @blockArgFunc
-int blockArgFunc(int (^ bl)(void)) {
-  return bl();
-}
-
-// COMMON-LABEL: define {{.*}} @get21
-// COMMON: define {{.*}} @__get21_block_invoke
-// COMMON: ret i32 21
-int get21() {
-  return blockArgFunc(^{return 21;});
-}
-
-// COMMON-LABEL: define {{.*}} @get42
-// COMMON: define {{.*}} @__get42_block_invoke
-// COMMON: ret i32 42
-int get42() {
-  return blockArgFunc(^{return 42;});
-}
-
 // COMMON-LABEL: define {{.*}}@call_block
 // call {{.*}}@__call_block_block_invoke
 int call_block() {

diff  --git a/clang/test/Frontend/opencl.cl b/clang/test/Frontend/opencl.cl
index ea7d3d4c8731..e25a4b8fac6a 100644
--- a/clang/test/Frontend/opencl.cl
+++ b/clang/test/Frontend/opencl.cl
@@ -21,7 +21,7 @@ int member;
 #endif
 #endif
 
-void f(void (^g)(void)) {
+typedef int (^bl_t)(void);
 #if defined(__OPENCL_C_VERSION__) || defined(__OPENCL_CPP_VERSION__)
 #if !defined(BLOCKS) && (defined(__OPENCL_CPP_VERSION__)  || __OPENCL_C_VERSION__ != CL_VERSION_2_0)
   // expected-error at -3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0}}
@@ -29,7 +29,6 @@ void f(void (^g)(void)) {
 #else
   // expected-error at -6{{blocks support disabled - compile with -fblocks or pick a deployment target that supports them}}
 #endif
-}
 
 // CHECK-INVALID-OPENCL-VERSION11: warning: OpenCL version 1.1 does not support the option '-cl-strict-aliasing'
 // CHECK-INVALID-OPENCL-VERSION12: warning: OpenCL version 1.2 does not support the option '-cl-strict-aliasing'

diff  --git a/clang/test/SemaOpenCL/invalid-block.cl b/clang/test/SemaOpenCL/invalid-block.cl
index ec74d16cc9b8..0fb2e2692073 100644
--- a/clang/test/SemaOpenCL/invalid-block.cl
+++ b/clang/test/SemaOpenCL/invalid-block.cl
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s
 
 // OpenCL v2.0 s6.12.5
-void f0(int (^const bl)());
+void f0(int (^const bl)()); // expected-error{{declaring function parameter of type 'int (__generic ^const __private)(void)' is not allowed}}
 // All blocks declarations must be const qualified and initialized.
 void f1() {
   int (^bl1)(void) = ^() {
@@ -26,9 +26,18 @@ void f2() {
   };
 }
 
-// A block cannot be the return value of a function.
+// A block cannot be the return value or parameter of a function.
 typedef int (^bl_t)(void);
-bl_t f3(bl_t bl); // expected-error{{declaring function return value of type 'bl_t' (aka 'int (__generic ^const)(void)') is not allowed}}
+bl_t f3a(int);     // expected-error{{declaring function return value of type 'bl_t' (aka 'int (__generic ^const)(void)') is not allowed}}
+bl_t f3b(bl_t bl);
+// expected-error at -1{{declaring function return value of type 'bl_t' (aka 'int (__generic ^const)(void)') is not allowed}}
+// expected-error at -2{{declaring function parameter of type '__private bl_t' (aka 'int (__generic ^const __private)(void)') is not allowed}}
+void f3c() {
+  // Block with a block argument.
+  int (^const bl2)(bl_t block_arg) = ^() { // expected-error{{declaring function parameter of type '__private bl_t' (aka 'int (__generic ^const __private)(void)') is not allowed}}
+    return block_arg(); // expected-error{{implicit declaration of function 'block_arg' is invalid in OpenCL}}
+  };
+}
 
 struct bl_s {
   int (^bl)(void); // expected-error {{the 'int (__generic ^const)(void)' type cannot be used to declare a structure or union field}}


        


More information about the cfe-commits mailing list