[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