diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -830,8 +830,8 @@ 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 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5139,8 +5139,8 @@ // 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 @@ 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()) { diff --git a/clang/test/CodeGenOpenCL/blocks.cl b/clang/test/CodeGenOpenCL/blocks.cl --- a/clang/test/CodeGenOpenCL/blocks.cl +++ b/clang/test/CodeGenOpenCL/blocks.cl @@ -70,26 +70,6 @@ // 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 --- a/clang/test/Frontend/opencl.cl +++ b/clang/test/Frontend/opencl.cl @@ -21,7 +21,7 @@ #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@-3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0}} @@ -29,7 +29,6 @@ #else // expected-error@-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 --- 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 @@ }; } -// 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@-1{{declaring function return value of type 'bl_t' (aka 'int (__generic ^const)(void)') is not allowed}} +// expected-error@-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}}