[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
This commit is contained in:
Sven van Haastregt 2020-06-29 14:13:12 +01:00
parent b7ca06b745
commit bd46a56474
5 changed files with 22 additions and 29 deletions

View File

@ -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">;

View File

@ -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>()) {

View File

@ -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() {

View File

@ -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@-3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0}}
@ -29,7 +29,6 @@ void f(void (^g)(void)) {
#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'

View File

@ -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@-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}}