diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8648,7 +8648,7 @@ } static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { - if (PT->isPointerType()) { + if (PT->isPointerType() || PT->isReferenceType()) { QualType PointeeType = PT->getPointeeType(); if (PointeeType.getAddressSpace() == LangAS::opencl_generic || PointeeType.getAddressSpace() == LangAS::opencl_private || @@ -8665,6 +8665,15 @@ return PtrPtrKernelParam; } + + // C++ for OpenCL v1.0 s2.4: + // Moreover the types used in parameters of the kernel functions must be: + // Standard layout types for pointer parameters. The same applies to + // reference if an implementation supports them in kernel parameters. + if (S.getLangOpts().OpenCLCPlusPlus && !PointeeType->isAtomicType() && + !PointeeType->isVoidType() && !PointeeType->isStandardLayoutType()) + return InvalidKernelParam; + return PtrKernelParam; } @@ -8689,9 +8698,6 @@ PT->isHalfType()) return InvalidKernelParam; - if (PT->isRecordType()) - return RecordKernelParam; - // Look into an array argument to check if it has a forbidden type. if (PT->isArrayType()) { const Type *UnderlyingTy = PT->getPointeeOrArrayElementType(); @@ -8701,6 +8707,17 @@ return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0)); } + // C++ for OpenCL v1.0 s2.4: + // Moreover the types used in parameters of the kernel functions must be: + // Trivial and standard-layout types C++17 [basic.types] (plain old data + // types) for parameters passed by value; + if (S.getLangOpts().OpenCLCPlusPlus && !PT->isOpenCLSpecificType() && + !PT.isPODType(S.Context)) + return InvalidKernelParam; + + if (PT->isRecordType()) + return RecordKernelParam; + return ValidKernelParam; } diff --git a/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp b/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp --- a/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp +++ b/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp @@ -5,6 +5,7 @@ }; template +//expected-error@+1{{'T' cannot be used as the type of a kernel parameter}} kernel void templ(T par) { //expected-error{{kernel functions cannot be used in a template declaration, instantiation or specialization}} } @@ -15,3 +16,58 @@ kernel void foo(int); //expected-note{{previous declaration is here}} kernel void foo(float); //expected-error{{conflicting types for 'foo'}} + +kernel void int_v(int in); +kernel void int_p(__global int *in); +kernel void int_r(__global int &in); +kernel void int_p_p(__global int *__global *in); +kernel void int_p_r(__global int *__global &in); +kernel void int_p_p_r(__global int *__global *__global &in); + +// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}} +kernel void k_atomic_v(atomic_int in); +kernel void k_atomic_p(__global atomic_int *in); +kernel void k_atomic_r(__global atomic_int &in); + +kernel void k_pipe(read_only pipe int in, write_only pipe int out); +kernel void k_sampler(sampler_t in); +kernel void k_void(__global void *in); + +typedef int int4 __attribute__((ext_vector_type(4))); + +kernel void int4_v(int4 in); +kernel void int4_p(__global int4 *in); +kernel void int4_p_p(__global int4 *__global *in); +kernel void int4_r(__global int4 &in); + +struct POD { + int a; + int b; +}; + +kernel void pod_v(POD in) {} +kernel void pod_p(__global POD *in) {} +kernel void pod_p_p(__global POD *__global *in) {} +kernel void pod_r(__global POD &in) {} + +struct StandardLayout { + int a; + int b; + StandardLayout(int a, int b) : a(a), b(b) {} +}; + +kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}} +kernel void standard_p(__global StandardLayout *in) {} +kernel void standard_p_p(__global StandardLayout *__global *in) {} +kernel void standard_r(__global StandardLayout &in) {} + +struct Trivial { + int a; +private: + int b; +}; + +kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}} +kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}} +kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}} +kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}