[OpenCL] Diagnose variadic arguments
OpenCL disallows using variadic arguments (s6.9.e and s6.12.5 OpenCL v2.0) apart from some exceptions: - printf - enqueue_kernel This change adds error diagnostic for variadic functions but accepts printf and any compiler internal function (which should cover __enqueue_kernel_XXX cases). It also unifies diagnostic with block prototype and adds missing uncaught cases for blocks. llvm-svn: 285395
This commit is contained in:
parent
c3ccf5d77b
commit
7c30533362
|
@ -8080,8 +8080,6 @@ def err_atomic_init_constant : Error<
|
||||||
" in the declaration statement in the program scope">;
|
" in the declaration statement in the program scope">;
|
||||||
def err_opencl_implicit_vector_conversion : Error<
|
def err_opencl_implicit_vector_conversion : Error<
|
||||||
"implicit conversions between vector types (%0 and %1) are not permitted">;
|
"implicit conversions between vector types (%0 and %1) are not permitted">;
|
||||||
def err_opencl_block_proto_variadic : Error<
|
|
||||||
"invalid block prototype, variadic arguments are not allowed in OpenCL">;
|
|
||||||
def err_opencl_invalid_type_array : Error<
|
def err_opencl_invalid_type_array : Error<
|
||||||
"array of %0 type is invalid in OpenCL">;
|
"array of %0 type is invalid in OpenCL">;
|
||||||
def err_opencl_ternary_with_block : Error<
|
def err_opencl_ternary_with_block : Error<
|
||||||
|
@ -8093,6 +8091,8 @@ def err_opencl_type_can_only_be_used_as_function_parameter : Error <
|
||||||
def warn_opencl_attr_deprecated_ignored : Warning <
|
def warn_opencl_attr_deprecated_ignored : Warning <
|
||||||
"%0 attribute is deprecated and ignored in OpenCL version %1">,
|
"%0 attribute is deprecated and ignored in OpenCL version %1">,
|
||||||
InGroup<IgnoredAttributes>;
|
InGroup<IgnoredAttributes>;
|
||||||
|
def err_opencl_variadic_function : Error<
|
||||||
|
"invalid prototype, variadic arguments are not allowed in OpenCL">;
|
||||||
|
|
||||||
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
|
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
|
||||||
def err_opencl_builtin_pipe_first_arg : Error<
|
def err_opencl_builtin_pipe_first_arg : Error<
|
||||||
|
|
|
@ -15459,9 +15459,11 @@ half16 __ovld __cnfn shuffle2(half8 x, half8 y, ushort16 mask);
|
||||||
half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
|
half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
|
||||||
#endif //cl_khr_fp16
|
#endif //cl_khr_fp16
|
||||||
|
|
||||||
|
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
|
||||||
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
|
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
|
||||||
|
|
||||||
int printf(__constant const char* st, ...);
|
int printf(__constant const char* st, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions
|
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions
|
||||||
|
|
||||||
|
|
|
@ -6888,17 +6888,6 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
||||||
NewVD->setInvalidDecl();
|
NewVD->setInvalidDecl();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// OpenCL v2.0 s6.12.5 - Blocks with variadic arguments are not supported.
|
|
||||||
// TODO: this check is not enough as it doesn't diagnose the typedef
|
|
||||||
const BlockPointerType *BlkTy = T->getAs<BlockPointerType>();
|
|
||||||
const FunctionProtoType *FTy =
|
|
||||||
BlkTy->getPointeeType()->getAs<FunctionProtoType>();
|
|
||||||
if (FTy && FTy->isVariadic()) {
|
|
||||||
Diag(NewVD->getLocation(), diag::err_opencl_block_proto_variadic)
|
|
||||||
<< T << NewVD->getSourceRange();
|
|
||||||
NewVD->setInvalidDecl();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// OpenCL v1.2 s6.5 - All program scope variables must be declared in the
|
// OpenCL v1.2 s6.5 - All program scope variables must be declared in the
|
||||||
// __constant address space.
|
// __constant address space.
|
||||||
|
|
|
@ -4043,13 +4043,26 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LangOpts.OpenCL) {
|
||||||
// OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
|
// OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
|
||||||
// function.
|
// function.
|
||||||
if (LangOpts.OpenCL && (T->isBlockPointerType() || T->isImageType() ||
|
if (T->isBlockPointerType() || T->isImageType() || T->isSamplerT() ||
|
||||||
T->isSamplerT() || T->isPipeType())) {
|
T->isPipeType()) {
|
||||||
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
|
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
|
||||||
<< T << 1 /*hint off*/;
|
<< T << 1 /*hint off*/;
|
||||||
D.setInvalidType(true);
|
D.setInvalidType(true);
|
||||||
|
}
|
||||||
|
// OpenCL doesn't support variadic functions and blocks
|
||||||
|
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
|
||||||
|
// We also allow here any toolchain reserved identifiers.
|
||||||
|
if (FTI.isVariadic &&
|
||||||
|
!(D.getIdentifier() &&
|
||||||
|
((D.getIdentifier()->getName() == "printf" &&
|
||||||
|
LangOpts.OpenCLVersion >= 120) ||
|
||||||
|
D.getIdentifier()->getName().startswith("__")))) {
|
||||||
|
S.Diag(D.getIdentifierLoc(), diag::err_opencl_variadic_function);
|
||||||
|
D.setInvalidType(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods cannot return interface types. All ObjC objects are
|
// Methods cannot return interface types. All ObjC objects are
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
|
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2
|
||||||
|
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
|
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
|
||||||
|
|
||||||
|
// Variadic functions
|
||||||
|
void vararg_f(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
|
||||||
|
void __vararg_f(int, ...);
|
||||||
|
typedef void (*vararg_fptr_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
|
||||||
|
int printf(__constant const char *st, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
|
||||||
|
|
||||||
|
//Function pointer
|
||||||
void foo(void*);
|
void foo(void*);
|
||||||
|
|
||||||
void bar()
|
void bar()
|
|
@ -31,23 +31,30 @@ void f4() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A block with variadic argument is not allowed.
|
// A block with variadic argument is not allowed.
|
||||||
int (^bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
|
int (^bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}} expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
typedef int (^bl1_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
|
||||||
|
|
||||||
// A block can't be used to declare an array
|
// A block can't be used to declare an array
|
||||||
typedef int (^bl1_t)(int);
|
typedef int (^bl2_t)(int);
|
||||||
void f5(int i) {
|
void f5(int i) {
|
||||||
bl1_t bl1 = ^(int i) {return 1;};
|
bl2_t bl1 = ^(int i) {
|
||||||
bl1_t bl2 = ^(int i) {return 2;};
|
return 1;
|
||||||
bl1_t arr[] = {bl1, bl2}; // expected-error {{array of 'bl1_t' (aka 'int (^const)(int)') type is invalid in OpenCL}}
|
};
|
||||||
|
bl2_t bl2 = ^(int i) {
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
bl2_t arr[] = {bl1, bl2}; // expected-error {{array of 'bl2_t' (aka 'int (^const)(int)') type is invalid in OpenCL}}
|
||||||
int tmp = i ? bl1(i) // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
|
int tmp = i ? bl1(i) // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
|
||||||
: bl2(i); // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
|
: bl2(i); // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
|
||||||
}
|
}
|
||||||
// A block pointer type and all pointer operations are disallowed
|
// A block pointer type and all pointer operations are disallowed
|
||||||
void f6(bl1_t * bl_ptr) { // expected-error{{pointer to type '__generic bl1_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
|
void f6(bl2_t *bl_ptr) { // expected-error{{pointer to type '__generic bl2_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
|
||||||
bl1_t bl = ^(int i) {return 1;};
|
bl2_t bl = ^(int i) {
|
||||||
bl1_t *p; // expected-error {{pointer to type '__generic bl1_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
|
return 1;
|
||||||
*bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
|
};
|
||||||
&bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
|
bl2_t *p; // expected-error {{pointer to type '__generic bl2_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
|
||||||
|
*bl; // expected-error {{invalid argument type 'bl2_t' (aka 'int (^const)(int)') to unary expression}}
|
||||||
|
&bl; // expected-error {{invalid argument type 'bl2_t' (aka 'int (^const)(int)') to unary expression}}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue