[clang] 362958a - [C++4OpenCL] Add extra diagnostics for kernel argument types
Anastasia Stulova via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 22 07:29:32 PDT 2021
Author: Anastasia Stulova
Date: 2021-04-22T15:28:04+01:00
New Revision: 362958ac7346ba3539f819e9fe93d2529caad1e8
URL: https://github.com/llvm/llvm-project/commit/362958ac7346ba3539f819e9fe93d2529caad1e8
DIFF: https://github.com/llvm/llvm-project/commit/362958ac7346ba3539f819e9fe93d2529caad1e8.diff
LOG: [C++4OpenCL] Add extra diagnostics for kernel argument types
Add restrictions on type layout (PR48099):
- Types passed by pointer or reference must be standard layout types.
- Types passed by value must be POD types.
Patch by olestrohm (Ole Strohm)!
Differential Revision: https://reviews.llvm.org/D100471
Added:
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d1dc9db5abd7f..8a718249d8549 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8648,7 +8648,7 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) {
}
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 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
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 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
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 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
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
index 2cbfffd5a00e9..977d487928b65 100644
--- a/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ b/clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -5,6 +5,7 @@ struct C {
};
template <typename T>
+//expected-error at +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 bar(int par) { //expected-error{{kernel functions cannot be used in
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 at +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}}
More information about the cfe-commits
mailing list