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 @@ -8665,6 +8665,14 @@ 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 (!PointeeType->isAtomicType() && !PointeeType->isVoidType() && !PointeeType->isStandardLayoutType()) + return InvalidKernelParam; + return PtrKernelParam; } @@ -8689,9 +8697,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 +8706,16 @@ 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 (!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,29 @@ kernel void foo(int); //expected-note{{previous declaration is here}} kernel void foo(float); //expected-error{{conflicting types for 'foo'}} + +struct POD { + int a; + int b; +}; + +kernel void pod_v(POD in) {} +kernel void pod_p(__global POD*__private 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*__private 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*__private in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}