https://github.com/ianayl updated https://github.com/llvm/llvm-project/pull/208571
>From bb73b24cf5e0a77209576f8d8253f2793d848050 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 7 Jul 2026 07:26:01 -0700 Subject: [PATCH 1/8] Initial work --- .../clang/Basic/DiagnosticSemaKinds.td | 4 + clang/lib/Sema/SemaSYCL.cpp | 30 +++++ .../sycl-kernel-param-restrictions.cpp | 107 ++++++++++++++++++ 3 files changed, 141 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 86b765fdf1fab..3f393fa574434 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13514,6 +13514,10 @@ def err_sycl_special_type_num_init_method : Error< "method defined">; def err_sycl_device_invalid_target : Error< "%0 is not a supported SYCL device target">; +def warn_sycl_kernel_has_ptr_param : Warning< + "pointers parameters in SYCL kernels must point to device-accessible memory, " + "i.e. the USM">, + InGroup<NonPortableSYCL>, DefaultIgnore; // SYCL external attribute diagnostics def err_sycl_external_invalid_linkage : Error< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index b942f19761f40..0b35172c3deb4 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -750,6 +750,36 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { // invalid use of a reference. IsValid = false; return false; + } + + Ty.dump(); + if (Ty->isAtomicType() || + Ty->isStructureTypeWithFlexibleArrayMember() || + Ty->isVariablyModifiedType()) { + + auto DirectParent = ObjectAccessPath.back(); + auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent); + SemaSYCLRef.Diag(DirectFieldParent->getLocation(), + diag::err_bad_kernel_param_type) + << DirectFieldParent->getType(); + emitObjectAccessPathNotes(); + + IsValid = false; + return false; + } /* + } else if (0 ) { // TODO detect virtual base class + + } // TODO introduce warning to detect pointers + // "sycl portability warning: it is user's responsibility to ensure pointers being used are USM" + */ + // Warn about pointer parameters in SYCL kernels if non-portable SYCL + // warnings are enabled. + if (Ty->isPointerType()) { + auto DirectParent = ObjectAccessPath.back(); + auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent); + SemaSYCLRef.Diag(DirectFieldParent->getLocation(), + diag::warn_sycl_kernel_has_ptr_param); + emitObjectAccessPathNotes(); } return true; } diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index 66aa00da18a04..f93cc17d72d89 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wno-vla-cxx-extension -fsycl-is-host -verify %s // RUN: %clang_cc1 -triple spirv64 -std=c++17 -fsyntax-only -Wno-vla-cxx-extension -fsycl-is-device -verify %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-host -verify=nonportable %s + // A unique kernel name type is required for each declared kernel entry point. template<int, int = 0> struct KN; @@ -213,3 +215,108 @@ void test() { } } // namespace badref7 + + +#include <stdatomic.h> +// Check for atomic parameters and subobjects. +namespace badref8 { +// Kernel entry point template definition. +template<typename KNT, typename T> +[[clang::sycl_kernel_entry_point(KNT)]] +void kernel_single_task(T t) {} + +struct S { + int a; + _Atomic int b; +}; + +class Kernel { + S data{1, 2}; +public: + void operator()() { } +}; + +void test() { + _Atomic int a = 0; + // TODO _Atomic(int) a + S s{1, 2}; + S arr[] = {s, s}; + kernel_single_task<class KN<15>>([=]{ (void)a; }); + kernel_single_task<class KN<16>>([=]{ (void)s; }); + kernel_single_task<class KN<17>>([=]{ (void)arr; }); + kernel_single_task<class KN<18>>(Kernel()); + // kernel_single_task<class KN<17>>([](S s) { (void)s; }); // DOESNT DETECT +} + +} // namespace badref8 + + +// Check for flexible array members -- would not be copyable to device +namespace badref9 { +// Kernel entry point template definition. +template<typename KNT, typename T> +[[clang::sycl_kernel_entry_point(KNT)]] +void kernel_single_task(T t) {} + +struct FAM { + int a; + int[] b; +}; + +class Kernel { + FAM fam; +public: + void operator()() { } +}; + +void test() { + FAM fam; + kernel_single_task<class KN<19>>([=]{ (void)fam; }); // DOESNT DETECT + kernel_single_task<class KN<20>>(Kernel()); +} + +} // namespace badref9 + +// Check for variable member array -- would not be copyable to device +namespace badref10 { +// Kernel entry point template definition. +template<typename KNT, typename T> +[[clang::sycl_kernel_entry_point(KNT)]] +void kernel_single_task(T t) {} + +class Kernel { + int len; +public: + Kernel(int l, int vmt[n]) : len(l) {} + void operator()(int n, int vmt[n]) { (void)vmt; } +}; + +void test() { + int n; + int Vmt[n]; + kernel_single_task<class KN<21>>([=](int n, int vmt[n]) { (void)vmt; }); // DOESNT DETECT + kernel_single_task<class KN<22>>(Kernel()); // DOESNT DETECT + kernel_single_task<class KN<23>>([=]{ (void)Vmt; }); +} + +} // namespace badref10 + +// Check for pointer parameters +namespace nonportable1 { +// Kernel entry point template definition. +template<typename KNT, typename T> +[[clang::sycl_kernel_entry_point(KNT)]] +void kernel_single_task(T t) {} + +class Kernel { +public: + void operator()(int *ptr) { (void)ptr; } +}; + +void test() { + int *ptr; + kernel_single_task<class KN<24>>(Kernel()); // DOESNT DETECT + kernel_single_task<class KN<25>>([=]{ (void)ptr; }); // DOESNT DETECT +} + +} // namespace nonportable1 \ No newline at end of file >From 57abfe8abd081828564881b6398ac5b079c2f00f Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Wed, 8 Jul 2026 08:16:40 -0700 Subject: [PATCH 2/8] Tentative implementation --- .../clang/Basic/DiagnosticSemaKinds.td | 2 + clang/lib/Sema/SemaSYCL.cpp | 20 ++++-- .../sycl-kernel-param-restrictions.cpp | 61 ++++++++++--------- 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3f393fa574434..acef5af0b34f8 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13518,6 +13518,8 @@ def warn_sycl_kernel_has_ptr_param : Warning< "pointers parameters in SYCL kernels must point to device-accessible memory, " "i.e. the USM">, InGroup<NonPortableSYCL>, DefaultIgnore; +def err_sycl_kernel_param_has_vbase : Error< + "%0 inherits virtual base classes and cannot be used as a SYCL kernel parameter">; // SYCL external attribute diagnostics def err_sycl_external_invalid_linkage : Error< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 0b35172c3deb4..88b6aefa187f9 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -766,12 +766,20 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { IsValid = false; return false; - } /* - } else if (0 ) { // TODO detect virtual base class - - } // TODO introduce warning to detect pointers - // "sycl portability warning: it is user's responsibility to ensure pointers being used are USM" - */ + } + if (CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) { + if (RD->getNumVBases() > 0) { + auto DirectParent = ObjectAccessPath.back(); + auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent); + SemaSYCLRef.Diag(DirectFieldParent->getLocation(), + diag::err_sycl_kernel_param_has_vbase) + << DirectFieldParent->getType(); + emitObjectAccessPathNotes(); + + IsValid = false; + return false; + } + } // Warn about pointer parameters in SYCL kernels if non-portable SYCL // warnings are enabled. if (Ty->isPointerType()) { diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index f93cc17d72d89..5cbf6ce472ebc 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -151,33 +151,6 @@ void test(int AS) { } // namespace badref4 -// Test virtual bases. -// FIXME: explicitly diagnose virtual bases within kernel parameters. -namespace badref5 { -// Kernel entry point template definition. -template<typename KNT, typename T> -[[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} //expected-note {{within parameter 't' of type 'badref5::Derived' declared here}} - -class Base { // expected-note {{within field of type 'Base' declared here}}} - int &data; // expected-error {{'int &' cannot be used as the type of a kernel parameter}} -public: - Base(int &a) : data(a) {} -}; - -class Derived : virtual Base { // expected-note {{within base class of type 'Base' declared here}} -public: - Derived(int &a) : Base(a) {} - -}; - -void test() { - int p = 0; - kernel_single_task<class KN<12>>(Derived{p}); - // expected-note-re@-1 {{in instantiation of function template specialization 'badref5::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} -} -} // namespace badref5 - // Check that a struct that hold a reference and captured by reference by lambda // kernel object is diagnosed correctly. namespace badref6 { @@ -316,7 +289,37 @@ class Kernel { void test() { int *ptr; kernel_single_task<class KN<24>>(Kernel()); // DOESNT DETECT - kernel_single_task<class KN<25>>([=]{ (void)ptr; }); // DOESNT DETECT + kernel_single_task<class KN<25>>([=]{ (void)ptr; }); } -} // namespace nonportable1 \ No newline at end of file +} // namespace nonportable1 + +// Test virtual bases. +// FIXME: explicitly diagnose virtual bases within kernel parameters. +namespace badref5 { +// Kernel entry point template definition. +template<typename KNT, typename T> +[[clang::sycl_kernel_entry_point(KNT)]] +void kernel_single_task(T t) {} //expected-note {{within parameter 't' of type 'badref5::Derived' declared here}} + +class Base { // expected-note {{within field of type 'Base' declared here}}} + int &data; // expected-error {{'int &' cannot be used as the type of a kernel parameter}} +public: + Base(int &a) : data(a) {} +}; + +class Derived : virtual Base { // expected-note {{within base class of type 'Base' declared here}} +public: + Derived(int &a) : Base(a) {} + +}; + +void test() { + int p = 0; + kernel_single_task<class KN<12>>(Derived{p}); + // expected-note-re@-1 {{in instantiation of function template specialization 'badref5::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + + Derived d{p}; + kernel_single_task<class KN<30>>([=]{ (void)d; }); +} +} // namespace badref5 >From 34521226c5b70a9ab21eeabe93b2371ae7fc4b66 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Thu, 9 Jul 2026 15:10:19 -0700 Subject: [PATCH 3/8] update handling of object path --- .../clang/Basic/DiagnosticSemaKinds.td | 8 +- clang/lib/Sema/SemaSYCL.cpp | 53 +++--- .../sycl-kernel-param-restrictions.cpp | 164 ++++++++++++------ 3 files changed, 148 insertions(+), 77 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index acef5af0b34f8..bd59d17b08b12 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13514,12 +13514,16 @@ def err_sycl_special_type_num_init_method : Error< "method defined">; def err_sycl_device_invalid_target : Error< "%0 is not a supported SYCL device target">; -def warn_sycl_kernel_has_ptr_param : Warning< - "pointers parameters in SYCL kernels must point to device-accessible memory, " +def warn_sycl_kernel_param_has_ptr: Warning< + "pointer parameters in SYCL kernels must point to device-accessible memory, " "i.e. the USM">, InGroup<NonPortableSYCL>, DefaultIgnore; def err_sycl_kernel_param_has_vbase : Error< "%0 inherits virtual base classes and cannot be used as a SYCL kernel parameter">; +def err_sycl_kernel_param_has_fam : Error< + "%0 contains a flexible array member and cannot be used as a SYCL kernel parameter">; +def err_sycl_kernel_param_has_vmt : Error< + "%0 is a variably modified type and cannot be used as a SYCL kernel parameter">; // SYCL external attribute diagnostics def err_sycl_external_invalid_linkage : Error< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 88b6aefa187f9..3eaaacefe396b 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -674,6 +674,16 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { const FieldDecl *>; SmallVector<ObjectAccess, 4> ObjectAccessPath; + std::pair<QualType, SourceLocation> getObjectAccessDebugInfo(ObjectAccess o) { + if (auto *PVD = dyn_cast<const ParmVarDecl *>(o)) + return std::pair{PVD->getType(), PVD->getLocation()}; + else if (auto *FD = dyn_cast<const FieldDecl *>(o)) + return std::pair{FD->getType(), FD->getLocation()}; + else if (auto *BS = dyn_cast<const CXXBaseSpecifier *>(o)) + return std::pair{BS->getType(), BS->getBaseTypeLoc()}; + llvm_unreachable("Unexpected type in ObjectAccess"); + } + void emitObjectAccessPathNotes() { for (auto Parent : llvm::reverse(ObjectAccessPath)) { if (auto *FD = Parent.dyn_cast<const FieldDecl *>()) { @@ -751,29 +761,34 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { IsValid = false; return false; } - - Ty.dump(); - if (Ty->isAtomicType() || - Ty->isStructureTypeWithFlexibleArrayMember() || - Ty->isVariablyModifiedType()) { - - auto DirectParent = ObjectAccessPath.back(); - auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent); - SemaSYCLRef.Diag(DirectFieldParent->getLocation(), - diag::err_bad_kernel_param_type) - << DirectFieldParent->getType(); + if (Ty->isAtomicType()) { + const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); + SemaSYCLRef.Diag(Loc, diag::err_bad_kernel_param_type) << Type; emitObjectAccessPathNotes(); IsValid = false; return false; } + if (Ty->isVariablyModifiedType()) { + const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); + SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_vmt) << Type; + emitObjectAccessPathNotes(); + + IsValid = false; + return false; + } + if (Ty->isStructureTypeWithFlexibleArrayMember()) { + const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); + SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_fam) << Type; + emitObjectAccessPathNotes(); + + IsValid = false; + return false; + } if (CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) { if (RD->getNumVBases() > 0) { - auto DirectParent = ObjectAccessPath.back(); - auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent); - SemaSYCLRef.Diag(DirectFieldParent->getLocation(), - diag::err_sycl_kernel_param_has_vbase) - << DirectFieldParent->getType(); + const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); + SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_vbase) << Type; emitObjectAccessPathNotes(); IsValid = false; @@ -783,10 +798,8 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { // Warn about pointer parameters in SYCL kernels if non-portable SYCL // warnings are enabled. if (Ty->isPointerType()) { - auto DirectParent = ObjectAccessPath.back(); - auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent); - SemaSYCLRef.Diag(DirectFieldParent->getLocation(), - diag::warn_sycl_kernel_has_ptr_param); + const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); + SemaSYCLRef.Diag(Loc, diag::warn_sycl_kernel_param_has_ptr) << Type; emitObjectAccessPathNotes(); } return true; diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index 5cbf6ce472ebc..a32c3f7c14355 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -1,7 +1,8 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wno-vla-cxx-extension -fsycl-is-host -verify %s -// RUN: %clang_cc1 -triple spirv64 -std=c++17 -fsyntax-only -Wno-vla-cxx-extension -fsycl-is-device -verify %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-host -verify %s +// RUN: %clang_cc1 -triple spirv64 -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-device -verify %s + +// TODO conditionally toggle Wnonportable-sycl -// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-host -verify=nonportable %s // A unique kernel name type is required for each declared kernel entry point. template<int, int = 0> struct KN; @@ -192,123 +193,171 @@ void test() { #include <stdatomic.h> // Check for atomic parameters and subobjects. -namespace badref8 { +namespace atomic1 { // Kernel entry point template definition. template<typename KNT, typename T> [[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} +void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note-re@-1 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note-re@-2 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note-re@-3 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note@-4 {{within parameter 't' of type 'atomic1::Kernel' declared here}} -struct S { +struct Sa { int a; - _Atomic int b; + _Atomic int b; // expected-error {{'_Atomic(int)' cannot be used as the type of a kernel parameter}} + // expected-note@-3 {{within field of type 'Sa' declared here}} + // expected-error@-2 {{'_Atomic(int)' cannot be used as the type of a kernel parameter}} + // expected-note@-5 {{within field of type 'Sa' declared here}} + // expected-error@-4 {{'_Atomic(int)' cannot be used as the type of a kernel parameter}} + // expected-note@-7 {{within field of type 'Sa' declared here}} }; class Kernel { - S data{1, 2}; + Sa data{1, 2}; // expected-note@-1 {{within field of type 'Kernel' declared here}} public: void operator()() { } }; void test() { _Atomic int a = 0; - // TODO _Atomic(int) a - S s{1, 2}; - S arr[] = {s, s}; + _Atomic(int) b = 2; + Sa s{1, 2}; + Sa arr[] = {s, s}; kernel_single_task<class KN<15>>([=]{ (void)a; }); - kernel_single_task<class KN<16>>([=]{ (void)s; }); - kernel_single_task<class KN<17>>([=]{ (void)arr; }); - kernel_single_task<class KN<18>>(Kernel()); - // kernel_single_task<class KN<17>>([](S s) { (void)s; }); // DOESNT DETECT + // expected-error@-1 {{'_Atomic(int)' cannot be used as the type of a kernel parameter}} + // expected-note-re@-2 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-3 {{within capture 'a' of lambda expression here}} + kernel_single_task<class KN<16>>([=]{ (void)b; }); + // expected-error@-1 {{'_Atomic(int)' cannot be used as the type of a kernel parameter}} + // expected-note-re@-2 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-3 {{within capture 'b' of lambda expression here}} + kernel_single_task<class KN<17>>([=]{ (void)s; }); + // expected-note-re@-1 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-2 {{within capture 's' of lambda expression here}} + kernel_single_task<class KN<18>>([=]{ (void)arr; }); + // expected-note-re@-1 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-2 {{within capture 'arr' of lambda expression here}} + kernel_single_task<class KN<19>>(Kernel()); + // expected-note-re@-1 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} } -} // namespace badref8 - +} // namespace atomic1 // Check for flexible array members -- would not be copyable to device -namespace badref9 { +namespace fam1 { // Kernel entry point template definition. template<typename KNT, typename T> [[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} +void kernel_single_task(T t) {} // expected-note {{within parameter 't' of type 'fam1::Kernel' declared here}} struct FAM { int a; - int[] b; + int b[]; }; -class Kernel { - FAM fam; +class Kernel { // expected-note {{within field of type 'Kernel' declared here}} + FAM fam; // expected-error {{'FAM' contains a flexible array member and cannot be used as a SYCL kernel parameter}} public: - void operator()() { } + void operator()() { (void)fam; } }; void test() { FAM fam; - kernel_single_task<class KN<19>>([=]{ (void)fam; }); // DOESNT DETECT - kernel_single_task<class KN<20>>(Kernel()); + //kernel_single_task<class KN<40>>([=]{ (void)fam; }); // Doesn't detect, FAM might not be capturable + //kernel_single_task<class KN<40>>([](FAM f){ (void)f; return 1; }(fam)); // DOESNT DETECT + //kernel_single_task<class KN<20>>([](FAM f){ return f; }(fam)); // not the result I'm looking for + kernel_single_task<class KN<21>>(Kernel()); + // expected-note-re@-1 {{in instantiation of function template specialization 'fam1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} } -} // namespace badref9 +} // namespace fam1 // Check for variable member array -- would not be copyable to device -namespace badref10 { +namespace vmt1 { // Kernel entry point template definition. template<typename KNT, typename T> [[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} - -class Kernel { - int len; -public: - Kernel(int l, int vmt[n]) : len(l) {} - void operator()(int n, int vmt[n]) { (void)vmt; } -}; +void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} void test() { int n; int Vmt[n]; - kernel_single_task<class KN<21>>([=](int n, int vmt[n]) { (void)vmt; }); // DOESNT DETECT - kernel_single_task<class KN<22>>(Kernel()); // DOESNT DETECT + //kernel_single_task<class KN<22>>([](int n, int vmt[n]){ (void)vmt; }(n, Vmt)); // DOESNT DETECT kernel_single_task<class KN<23>>([=]{ (void)Vmt; }); + // expected-error@-1 {{'int[n]' is a variably modified type and cannot be used as a SYCL kernel parameter}} + // expected-note-re@-2 {{in instantiation of function template specialization 'vmt1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-3 {{within capture 'Vmt' of lambda expression here}} + // expected-error@-4 {{variable-sized object may not be initialized}} } -} // namespace badref10 - +} // namespace vmt1 + // Check for pointer parameters namespace nonportable1 { // Kernel entry point template definition. template<typename KNT, typename T> [[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} +void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note-re@-1 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note-re@-2 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // expected-note-re@-3 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} -class Kernel { +struct S { // expected-note {{within field of type 'S' declared here}} + // expected-note@-1 {{within field of type 'S' declared here}} + int *ptr; + // expected-warning@-1 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // expected-warning@-2 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} +}; + +class C { // expected-note {{within field of type 'C' declared here}} +private: + int *ptr; + // expected-warning@-1 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // TODO double-check this warning actually tells me what field is the problem public: - void operator()(int *ptr) { (void)ptr; } + C(int *p) : ptr(p) {} }; void test() { int *ptr; - kernel_single_task<class KN<24>>(Kernel()); // DOESNT DETECT kernel_single_task<class KN<25>>([=]{ (void)ptr; }); + // expected-warning@-1 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // expected-note-re@-2 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-3 {{within capture 'ptr' of lambda expression here}} + + S s{ptr}; + kernel_single_task<class KN<26>>([=]{ (void)s; }); + // expected-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-2 {{within capture 's' of lambda expression here}} + + C c{ptr}; + kernel_single_task<class KN<27>>([=]{ (void)c; }); + // expected-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-2 {{within capture 'c' of lambda expression here}} + + S arr[3] = {{ptr}, {ptr}, {ptr}}; + kernel_single_task<class KN<28>>([=]{ (void)arr; }); + // expected-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-2 {{within capture 'arr' of lambda expression here}} } } // namespace nonportable1 -// Test virtual bases. -// FIXME: explicitly diagnose virtual bases within kernel parameters. -namespace badref5 { +// Check for virtual bases +namespace vbase1 { // Kernel entry point template definition. template<typename KNT, typename T> [[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} //expected-note {{within parameter 't' of type 'badref5::Derived' declared here}} +void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} -class Base { // expected-note {{within field of type 'Base' declared here}}} - int &data; // expected-error {{'int &' cannot be used as the type of a kernel parameter}} +class Base { + int &data; public: Base(int &a) : data(a) {} }; -class Derived : virtual Base { // expected-note {{within base class of type 'Base' declared here}} +class Derived : virtual Base { public: Derived(int &a) : Base(a) {} @@ -316,10 +365,15 @@ class Derived : virtual Base { // expected-note {{within base class of type 'Bas void test() { int p = 0; - kernel_single_task<class KN<12>>(Derived{p}); - // expected-note-re@-1 {{in instantiation of function template specialization 'badref5::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - Derived d{p}; - kernel_single_task<class KN<30>>([=]{ (void)d; }); + kernel_single_task<class KN<29>>([=]{ (void)d; }); + // expected-error@-1 {{'Derived' inherits virtual base classes and cannot be used as a SYCL kernel parameter}} + // expected-note-re@-2 {{in instantiation of function template specialization 'vbase1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // expected-note@-3 {{within capture 'd' of lambda expression here}} + + //kernel_single_task<class KN<30>>([](Derived d){ return d; }(d)); // not sure if this gives me what I actually want + // xpected-error@-1 {{'vbase1::Derived' inherits virtual base classes and cannot be used as a SYCL kernel parameter}} + // xpected-note-re@-2 {{in instantiation of function template specialization 'vbase1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // xpected-note@-3 {{within capture 'd' of lambda expression here}} } -} // namespace badref5 +} // namespace vbase1 >From 8be6ac0148757871460c5ec8759261d41055e0ec Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Fri, 10 Jul 2026 10:08:14 -0700 Subject: [PATCH 4/8] Address issues with test coverage --- clang/lib/Sema/SemaSYCL.cpp | 13 +++++-------- .../SemaSYCL/sycl-kernel-param-restrictions.cpp | 13 +++++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 3eaaacefe396b..a52a412fc174b 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -760,32 +760,28 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { // invalid use of a reference. IsValid = false; return false; - } - if (Ty->isAtomicType()) { + } else if (Ty->isAtomicType()) { const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); SemaSYCLRef.Diag(Loc, diag::err_bad_kernel_param_type) << Type; emitObjectAccessPathNotes(); IsValid = false; return false; - } - if (Ty->isVariablyModifiedType()) { + } else if (Ty->isVariablyModifiedType()) { const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_vmt) << Type; emitObjectAccessPathNotes(); IsValid = false; return false; - } - if (Ty->isStructureTypeWithFlexibleArrayMember()) { + } else if (Ty->isStructureTypeWithFlexibleArrayMember()) { const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_fam) << Type; emitObjectAccessPathNotes(); IsValid = false; return false; - } - if (CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) { + } else if (CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) { if (RD->getNumVBases() > 0) { const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_vbase) << Type; @@ -795,6 +791,7 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { return false; } } + // Warn about pointer parameters in SYCL kernels if non-portable SYCL // warnings are enabled. if (Ty->isPointerType()) { diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index a32c3f7c14355..493c1843dca72 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -264,16 +264,14 @@ class Kernel { // expected-note {{within field of type 'Kernel' declared here}} void test() { FAM fam; - //kernel_single_task<class KN<40>>([=]{ (void)fam; }); // Doesn't detect, FAM might not be capturable - //kernel_single_task<class KN<40>>([](FAM f){ (void)f; return 1; }(fam)); // DOESNT DETECT - //kernel_single_task<class KN<20>>([](FAM f){ return f; }(fam)); // not the result I'm looking for - kernel_single_task<class KN<21>>(Kernel()); + // Flexible array members cannot be captured in a lambda, thus no lambda tests are provided. + kernel_single_task<class KN<21>>(Kernel{}); // expected-note-re@-1 {{in instantiation of function template specialization 'fam1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} } } // namespace fam1 -// Check for variable member array -- would not be copyable to device +// Check for variably modified types -- would not be copyable to device namespace vmt1 { // Kernel entry point template definition. template<typename KNT, typename T> @@ -283,7 +281,10 @@ void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of ty void test() { int n; int Vmt[n]; - //kernel_single_task<class KN<22>>([](int n, int vmt[n]){ (void)vmt; }(n, Vmt)); // DOESNT DETECT + // VLAs as parameters are lowered to a pointer, preventing test cases with VLAs + // as normal lambda parameters. The below test case uses technically invalid + // code, but preserves the VLA in the lambda. + // As a result, suppress "variable-sized object may not be initialized" is needed. kernel_single_task<class KN<23>>([=]{ (void)Vmt; }); // expected-error@-1 {{'int[n]' is a variably modified type and cannot be used as a SYCL kernel parameter}} // expected-note-re@-2 {{in instantiation of function template specialization 'vmt1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} >From dbb30993402cdb6ca9d8a78dd560e9d9d09c77f3 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Fri, 10 Jul 2026 10:37:21 -0700 Subject: [PATCH 5/8] Clean up code --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaSYCL.cpp | 46 ++++++++----------- .../sycl-kernel-param-restrictions.cpp | 8 ++-- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index bd59d17b08b12..eb28a6a4494d2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13515,7 +13515,7 @@ def err_sycl_special_type_num_init_method : Error< def err_sycl_device_invalid_target : Error< "%0 is not a supported SYCL device target">; def warn_sycl_kernel_param_has_ptr: Warning< - "pointer parameters in SYCL kernels must point to device-accessible memory, " + "pointers used in SYCL kernels must point to device-accessible memory, " "i.e. the USM">, InGroup<NonPortableSYCL>, DefaultIgnore; def err_sycl_kernel_param_has_vbase : Error< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index a52a412fc174b..40ff8d35a4305 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -675,13 +675,13 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { SmallVector<ObjectAccess, 4> ObjectAccessPath; std::pair<QualType, SourceLocation> getObjectAccessDebugInfo(ObjectAccess o) { - if (auto *PVD = dyn_cast<const ParmVarDecl *>(o)) - return std::pair{PVD->getType(), PVD->getLocation()}; - else if (auto *FD = dyn_cast<const FieldDecl *>(o)) - return std::pair{FD->getType(), FD->getLocation()}; - else if (auto *BS = dyn_cast<const CXXBaseSpecifier *>(o)) - return std::pair{BS->getType(), BS->getBaseTypeLoc()}; - llvm_unreachable("Unexpected type in ObjectAccess"); + if (auto *PVD = dyn_cast<const ParmVarDecl *>(o)) + return std::pair{PVD->getType(), PVD->getLocation()}; + else if (auto *FD = dyn_cast<const FieldDecl *>(o)) + return std::pair{FD->getType(), FD->getLocation()}; + else if (auto *BS = dyn_cast<const CXXBaseSpecifier *>(o)) + return std::pair{BS->getType(), BS->getBaseTypeLoc()}; + llvm_unreachable("Unexpected type in ObjectAccess"); } void emitObjectAccessPathNotes() { @@ -738,6 +738,12 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { // Returns true if subobjects should be visited and false otherwise. bool checkType(QualType Ty) { + auto emitDiagnostic = [this](clang::diag::kind mesg) { + const auto &[Type, Loc] = + getObjectAccessDebugInfo(ObjectAccessPath.back()); + SemaSYCLRef.Diag(Loc, mesg) << Type; + emitObjectAccessPathNotes(); + }; if (Ty->isReferenceType()) { auto DirectParent = ObjectAccessPath.back(); // Reference cannot be a base, so just assume we came via a FieldDecl. @@ -761,43 +767,29 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { IsValid = false; return false; } else if (Ty->isAtomicType()) { - const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); - SemaSYCLRef.Diag(Loc, diag::err_bad_kernel_param_type) << Type; - emitObjectAccessPathNotes(); - + emitDiagnostic(diag::err_bad_kernel_param_type); IsValid = false; return false; } else if (Ty->isVariablyModifiedType()) { - const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); - SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_vmt) << Type; - emitObjectAccessPathNotes(); - + emitDiagnostic(diag::err_sycl_kernel_param_has_vmt); IsValid = false; return false; } else if (Ty->isStructureTypeWithFlexibleArrayMember()) { - const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); - SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_fam) << Type; - emitObjectAccessPathNotes(); - + emitDiagnostic(diag::err_sycl_kernel_param_has_fam); IsValid = false; return false; } else if (CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) { if (RD->getNumVBases() > 0) { - const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); - SemaSYCLRef.Diag(Loc, diag::err_sycl_kernel_param_has_vbase) << Type; - emitObjectAccessPathNotes(); - + emitDiagnostic(diag::err_sycl_kernel_param_has_vbase); IsValid = false; return false; } } - + // Warn about pointer parameters in SYCL kernels if non-portable SYCL // warnings are enabled. if (Ty->isPointerType()) { - const auto& [Type, Loc] = getObjectAccessDebugInfo(ObjectAccessPath.back()); - SemaSYCLRef.Diag(Loc, diag::warn_sycl_kernel_param_has_ptr) << Type; - emitObjectAccessPathNotes(); + emitDiagnostic(diag::warn_sycl_kernel_param_has_ptr); } return true; } diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index 493c1843dca72..c0b3d910bc7d9 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -307,14 +307,14 @@ void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of ty struct S { // expected-note {{within field of type 'S' declared here}} // expected-note@-1 {{within field of type 'S' declared here}} int *ptr; - // expected-warning@-1 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} - // expected-warning@-2 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // expected-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // expected-warning@-2 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} }; class C { // expected-note {{within field of type 'C' declared here}} private: int *ptr; - // expected-warning@-1 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // expected-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} // TODO double-check this warning actually tells me what field is the problem public: C(int *p) : ptr(p) {} @@ -323,7 +323,7 @@ class C { // expected-note {{within field of type 'C' declared here}} void test() { int *ptr; kernel_single_task<class KN<25>>([=]{ (void)ptr; }); - // expected-warning@-1 {{pointer parameters in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // expected-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} // expected-note-re@-2 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} // expected-note@-3 {{within capture 'ptr' of lambda expression here}} >From b2815bd778bebeb35e45e56d2be949abc204893a Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Fri, 10 Jul 2026 11:33:19 -0700 Subject: [PATCH 6/8] remove VMT checks, split nonportable lit test into separate run --- .../clang/Basic/DiagnosticSemaKinds.td | 2 - clang/lib/Sema/SemaSYCL.cpp | 4 -- .../sycl-kernel-param-restrictions.cpp | 70 ++++++------------- 3 files changed, 23 insertions(+), 53 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index eb28a6a4494d2..784bde5d68f08 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13522,8 +13522,6 @@ def err_sycl_kernel_param_has_vbase : Error< "%0 inherits virtual base classes and cannot be used as a SYCL kernel parameter">; def err_sycl_kernel_param_has_fam : Error< "%0 contains a flexible array member and cannot be used as a SYCL kernel parameter">; -def err_sycl_kernel_param_has_vmt : Error< - "%0 is a variably modified type and cannot be used as a SYCL kernel parameter">; // SYCL external attribute diagnostics def err_sycl_external_invalid_linkage : Error< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 40ff8d35a4305..47e41d81b9a68 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -770,10 +770,6 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> { emitDiagnostic(diag::err_bad_kernel_param_type); IsValid = false; return false; - } else if (Ty->isVariablyModifiedType()) { - emitDiagnostic(diag::err_sycl_kernel_param_has_vmt); - IsValid = false; - return false; } else if (Ty->isStructureTypeWithFlexibleArrayMember()) { emitDiagnostic(diag::err_sycl_kernel_param_has_fam); IsValid = false; diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index c0b3d910bc7d9..120b00e1fc41f 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -1,8 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-host -verify %s -// RUN: %clang_cc1 -triple spirv64 -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-device -verify %s - -// TODO conditionally toggle Wnonportable-sycl - +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wno-vla-cxx-extension -fsycl-is-host -verify=expected %s +// RUN: %clang_cc1 -triple spirv64 -std=c++17 -fsyntax-only -Wno-vla-cxx-extension -fsycl-is-device -verify=expected %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-host -verify=expected,nonportable %s +// RUN: %clang_cc1 -triple spirv64 -std=c++17 -fsyntax-only -Wnonportable-sycl -Wno-vla-cxx-extension -fsycl-is-device -verify=expected,nonportable %s // A unique kernel name type is required for each declared kernel entry point. template<int, int = 0> struct KN; @@ -271,50 +270,27 @@ void test() { } // namespace fam1 -// Check for variably modified types -- would not be copyable to device -namespace vmt1 { -// Kernel entry point template definition. -template<typename KNT, typename T> -[[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} - -void test() { - int n; - int Vmt[n]; - // VLAs as parameters are lowered to a pointer, preventing test cases with VLAs - // as normal lambda parameters. The below test case uses technically invalid - // code, but preserves the VLA in the lambda. - // As a result, suppress "variable-sized object may not be initialized" is needed. - kernel_single_task<class KN<23>>([=]{ (void)Vmt; }); - // expected-error@-1 {{'int[n]' is a variably modified type and cannot be used as a SYCL kernel parameter}} - // expected-note-re@-2 {{in instantiation of function template specialization 'vmt1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - // expected-note@-3 {{within capture 'Vmt' of lambda expression here}} - // expected-error@-4 {{variable-sized object may not be initialized}} -} - -} // namespace vmt1 - // Check for pointer parameters namespace nonportable1 { // Kernel entry point template definition. template<typename KNT, typename T> [[clang::sycl_kernel_entry_point(KNT)]] -void kernel_single_task(T t) {} // expected-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} - // expected-note-re@-1 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} - // expected-note-re@-2 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} - // expected-note-re@-3 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} +void kernel_single_task(T t) {} // nonportable-note-re {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // nonportable-note-re@-1 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // nonportable-note-re@-2 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} + // nonportable-note-re@-3 {{within parameter 't' of type '(lambda at {{.*}})' declared here}} -struct S { // expected-note {{within field of type 'S' declared here}} - // expected-note@-1 {{within field of type 'S' declared here}} +struct S { // nonportable-note {{within field of type 'S' declared here}} + // nonportable-note@-1 {{within field of type 'S' declared here}} int *ptr; - // expected-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} - // expected-warning@-2 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // nonportable-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // nonportable-warning@-2 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} }; -class C { // expected-note {{within field of type 'C' declared here}} +class C { // nonportable-note {{within field of type 'C' declared here}} private: int *ptr; - // expected-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // nonportable-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} // TODO double-check this warning actually tells me what field is the problem public: C(int *p) : ptr(p) {} @@ -323,24 +299,24 @@ class C { // expected-note {{within field of type 'C' declared here}} void test() { int *ptr; kernel_single_task<class KN<25>>([=]{ (void)ptr; }); - // expected-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} - // expected-note-re@-2 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - // expected-note@-3 {{within capture 'ptr' of lambda expression here}} + // nonportable-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} + // nonportable-note-re@-2 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // nonportable-note@-3 {{within capture 'ptr' of lambda expression here}} S s{ptr}; kernel_single_task<class KN<26>>([=]{ (void)s; }); - // expected-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - // expected-note@-2 {{within capture 's' of lambda expression here}} + // nonportable-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // nonportable-note@-2 {{within capture 's' of lambda expression here}} C c{ptr}; kernel_single_task<class KN<27>>([=]{ (void)c; }); - // expected-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - // expected-note@-2 {{within capture 'c' of lambda expression here}} + // nonportable-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // nonportable-note@-2 {{within capture 'c' of lambda expression here}} S arr[3] = {{ptr}, {ptr}, {ptr}}; kernel_single_task<class KN<28>>([=]{ (void)arr; }); - // expected-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - // expected-note@-2 {{within capture 'arr' of lambda expression here}} + // nonportable-note-re@-1 {{in instantiation of function template specialization 'nonportable1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} + // nonportable-note@-2 {{within capture 'arr' of lambda expression here}} } } // namespace nonportable1 >From e868ab9f789f6ff79395eca98bfd783b9e34d39a Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Fri, 10 Jul 2026 11:38:10 -0700 Subject: [PATCH 7/8] Make formatting conform --- clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index 120b00e1fc41f..80235804b2b26 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -237,7 +237,7 @@ void test() { kernel_single_task<class KN<18>>([=]{ (void)arr; }); // expected-note-re@-1 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} // expected-note@-2 {{within capture 'arr' of lambda expression here}} - kernel_single_task<class KN<19>>(Kernel()); + kernel_single_task<class KN<19>>(Kernel{}); // expected-note-re@-1 {{in instantiation of function template specialization 'atomic1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} } >From 0abd5060f208a3bd3188afe5c883937b52ef164f Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 13 Jul 2026 09:50:58 -0700 Subject: [PATCH 8/8] Remove leftover todos --- clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp index 80235804b2b26..52b683c017a7b 100644 --- a/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-param-restrictions.cpp @@ -291,7 +291,6 @@ class C { // nonportable-note {{within field of type 'C' declared here}} private: int *ptr; // nonportable-warning@-1 {{pointers used in SYCL kernels must point to device-accessible memory, i.e. the USM}} - // TODO double-check this warning actually tells me what field is the problem public: C(int *p) : ptr(p) {} }; @@ -347,10 +346,5 @@ void test() { // expected-error@-1 {{'Derived' inherits virtual base classes and cannot be used as a SYCL kernel parameter}} // expected-note-re@-2 {{in instantiation of function template specialization 'vbase1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} // expected-note@-3 {{within capture 'd' of lambda expression here}} - - //kernel_single_task<class KN<30>>([](Derived d){ return d; }(d)); // not sure if this gives me what I actually want - // xpected-error@-1 {{'vbase1::Derived' inherits virtual base classes and cannot be used as a SYCL kernel parameter}} - // xpected-note-re@-2 {{in instantiation of function template specialization 'vbase1::kernel_single_task<KN<{{[0-9]+}}>, {{.*}}>' requested here}} - // xpected-note@-3 {{within capture 'd' of lambda expression here}} } } // namespace vbase1 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
