[OpenCL] Fix diagnostics with templates in kernel args.
authorAnastasia Stulova <anastasia.stulova@arm.com>
Thu, 10 Nov 2022 15:20:34 +0000 (15:20 +0000)
committerAnastasia Stulova <anastasia.stulova@arm.com>
Thu, 10 Nov 2022 18:55:12 +0000 (18:55 +0000)
Improve checking for the standard layout type when diagnosing
the kernel argument with templated types. The check doesn't work
correctly for references or pointers due to the lazy template
instantiation.

Current fix only improves cases where nested types in the templates
do not depend on the template parameters.

Differential Revision: https://reviews.llvm.org/D134445

clang/lib/Sema/SemaDecl.cpp
clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

index 3bec6b0..bac87c0 100644 (file)
@@ -9234,10 +9234,23 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
     // reference if an implementation supports them in kernel parameters.
     if (S.getLangOpts().OpenCLCPlusPlus &&
         !S.getOpenCLOptions().isAvailableOption(
-            "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
-        !PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
-        !PointeeType->isStandardLayoutType())
+            "__cl_clang_non_portable_kernel_param_types", S.getLangOpts())) {
+     auto CXXRec = PointeeType.getCanonicalType()->getAsCXXRecordDecl();
+     bool IsStandardLayoutType = true;
+     if (CXXRec) {
+       // If template type is not ODR-used its definition is only available
+       // in the template definition not its instantiation.
+       // FIXME: This logic doesn't work for types that depend on template
+       // parameter (PR58590).
+       if (!CXXRec->hasDefinition())
+         CXXRec = CXXRec->getTemplateInstantiationPattern();
+       if (!CXXRec || !CXXRec->hasDefinition() || !CXXRec->isStandardLayout())
+         IsStandardLayoutType = false;
+     }
+     if (!PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+        !IsStandardLayoutType)
       return InvalidKernelParam;
+    }
 
     return PtrKernelParam;
   }
index 9bd1473..8795fd7 100644 (file)
@@ -93,3 +93,24 @@ 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
+
+// Nested types and templates
+struct Outer {
+  struct Inner{
+    int i;
+  };
+};
+template<class T>
+struct OuterTempl {
+  struct Inner{
+    int i;
+  };
+};
+// FIXME: (PR58590) Use of template parameter dependent types doesn't
+// work yet due to lazy instantiation of reference types.
+//template<class T>
+//struct Templ {
+//T i;
+//};
+
+extern kernel void nested(constant Outer::Inner& r1, constant OuterTempl<int>::Inner& r2/*, constant Templ<int>& r3*/);