#pragma OPENCL EXTENSION __cl_clang_variadic_functions : disable
void bar(int a, ...); // error - variadic prototype is not allowed
+``__cl_clang_non_portable_kernel_param_types``
+---------------------------------------------
+
+With this extension it is possible to enable the use of some restricted types
+in kernel parameters specified in `C++ for OpenCL v1.0 s2.4
+<https://www.khronos.org/opencl/assets/CXX_for_OpenCL.html#kernel_function>`_.
+The restrictions can be relaxed using regular OpenCL extension pragma mechanism
+detailed in `the OpenCL Extension Specification, section 1.2
+<https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#extensions-overview>`_.
+
+This is not a conformant behavior and it can only be used when the
+kernel arguments are not accessed on the host side or the data layout/size
+between the host and device is known to be compatible.
+
+**Example of Use**:
+
+.. code-block:: c++
+
+ // Plain Old Data type.
+ struct Pod {
+ int a;
+ int b;
+ };
+
+ // Not POD type because of the constructor.
+ // Standard layout type because there is only one access control.
+ struct OnlySL {
+ int a;
+ int b;
+ NotPod() : a(0), b(0) {}
+ };
+
+ // Not standard layout type because of two different access controls.
+ struct NotSL {
+ int a;
+ private:
+ int b;
+ }
+
+ kernel void kernel_main(
+ Pod a,
+ #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+ OnlySL b,
+ global NotSL *c,
+ #pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : disable
+ global OnlySL *d,
+ );
+
Legacy 1.x atomics with generic address space
---------------------------------------------
OPENCL_EXTENSION(cl_clang_storage_class_specifiers, true, 100)
OPENCL_EXTENSION(__cl_clang_function_pointers, true, 100)
OPENCL_EXTENSION(__cl_clang_variadic_functions, true, 100)
+OPENCL_EXTENSION(__cl_clang_non_portable_kernel_param_types, true, 100)
// AMD OpenCL extensions
OPENCL_EXTENSION(cl_amd_media_ops, true, 100)
Opts["cl_clang_storage_class_specifiers"] = true;
Opts["__cl_clang_variadic_functions"] = true;
Opts["__cl_clang_function_pointers"] = true;
+ Opts["__cl_clang_non_portable_kernel_param_types"] = true;
bool IsAMDGCN = isAMDGCN(getTriple());
Opts["cl_clang_storage_class_specifiers"] = true;
Opts["__cl_clang_function_pointers"] = true;
Opts["__cl_clang_variadic_functions"] = true;
+ Opts["__cl_clang_non_portable_kernel_param_types"] = true;
Opts["cl_khr_fp64"] = true;
Opts["cl_khr_byte_addressable_store"] = true;
}
static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
+ if (PT->isDependentType())
+ return InvalidKernelParam;
+
if (PT->isPointerType() || PT->isReferenceType()) {
QualType PointeeType = PT->getPointeeType();
if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
// 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())
+ if (S.getLangOpts().OpenCLCPlusPlus &&
+ !S.getOpenCLOptions().isAvailableOption(
+ "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
+ !PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+ !PointeeType->isStandardLayoutType())
return InvalidKernelParam;
return PtrKernelParam;
// 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))
+ if (S.getLangOpts().OpenCLCPlusPlus &&
+ !S.getOpenCLOptions().isAvailableOption(
+ "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
+ !PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
return InvalidKernelParam;
if (PT->isRecordType())
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+#ifndef __cl_clang_non_portable_kernel_param_types
+#error "Missing __cl_clang_non_portable_kernel_param_types define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+
#ifndef cl_khr_fp16
#error "Missing cl_khr_fp16 define"
#endif
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+#ifndef __cl_clang_non_portable_kernel_param_types
+#error "Missing __cl_clang_non_portable_kernel_param_types define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+
#ifdef cl_khr_fp16
#error "Incorrect cl_khr_fp16 define"
#endif
#endif
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+#ifndef __cl_clang_non_portable_kernel_param_types
+#error "Missing __cl_clang_non_portable_kernel_param_types define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+
#ifdef cl_khr_fp16
#error "Incorrect cl_khr_fp16 define"
#endif
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_param_types : enable
+#endif
struct C {
kernel void m(); //expected-error{{kernel functions cannot be class members}}
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);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
kernel void k_atomic_p(__global atomic_int *in);
kernel void k_atomic_r(__global atomic_int &in);
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_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
kernel void standard_p(__global StandardLayout *in) {}
kernel void standard_p_p(__global StandardLayout *__global *in) {}
kernel void standard_r(__global StandardLayout &in) {}
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}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif