Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -8849,10 +8849,19 @@ // 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 (!CXXRec->hasDefinition()) + CXXRec = CXXRec->getTemplateInstantiationPattern(); + if (!CXXRec || !CXXRec->hasDefinition() || !CXXRec->isStandardLayout()) + IsStandardLayoutType = false; + } + if (!PointeeType->isAtomicType() && !PointeeType->isVoidType() && + !IsStandardLayoutType) return InvalidKernelParam; + } return PtrKernelParam; } Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp =================================================================== --- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp +++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp @@ -93,3 +93,24 @@ #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 +struct OuterTempl { +struct Inner{ +int i; +}; +}; + +// FIXME: Use of templates doesn't work due to lazy instantiation of reference types. +//template +//struct Templ { +//T i; +//}; + +extern kernel void nested(constant Outer::Inner& r1, constant OuterTempl::Inner& r2/*, constant Templ& r3*/);