Author: schittir Date: 2026-11-03T11:56:28-05:00 New Revision: 352d9bcc7b6689e5993c30df5658dadb60442a7a
URL: https://github.com/llvm/llvm-project/commit/352d9bcc7b6689e5993c30df5658dadb60442a7a DIFF: https://github.com/llvm/llvm-project/commit/352d9bcc7b6689e5993c30df5658dadb60442a7a.diff LOG: [clang][SYCL] Diagnose variadic sycl_external function (#216393) SYCL device code does not support variadic function calls. Added: clang/test/CodeGenSYCL/sycl-external-attr-variadic.cpp clang/test/SemaSYCL/sycl-external-attr-variadic-undefined.cpp Modified: clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/SemaSYCL.h clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaSYCL.cpp clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp clang/test/SemaSYCL/sycl-cconv.cpp clang/test/SemaSYCL/sycl-external-attr.cpp clang/test/SemaSYCL/variadic-func-call.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 687e022c7bd61f..2300c8456ef164 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -624,6 +624,10 @@ following requirements: The attribute shall be present on the first declaration of a function and may optionally be present on subsequent declarations. +SYCL prohibits calls to a variadic function in device functions. Since there is +little reason to emit a function that cannot be called, the attribute is ignored, +with a warning, when applied to a variadic function. + When compiling for a SYCL device target that does not support the generic address space, the function shall not specify a raw pointer or reference type as the return type or as a parameter type. @@ -638,6 +642,8 @@ The following examples demonstrate the use of this attribute: [[clang::sycl_external]] extern void Baz(); // Ok. [[clang::sycl_external]] static void Quux() { /* ... */ } // error: Quux() has internal linkage. + +[[clang::sycl_external]] void Corge(int, ...); // warning: attribute ignored; Corge() is variadic. ``` }]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 671bdd63af6861..a2fc0206c445be 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13624,6 +13624,10 @@ def err_sycl_external_invalid_main : Error< "%0 cannot be applied to the 'main' function">; def err_sycl_external_invalid_deleted_function : Error< "%0 cannot be applied to an explicitly deleted function">; +def warn_sycl_external_ignored_variadic_function : Warning< + "%0 attribute ignored; a variadic function cannot be called from device " + "code">, + InGroup<IgnoredAttributes>; def warn_sycl_external_missing_on_first_decl : Warning< "%0 attribute does not appear on the first declaration">, InGroup<NonPortableSYCL>; diff --git a/clang/include/clang/Sema/SemaSYCL.h b/clang/include/clang/Sema/SemaSYCL.h index 4980aa44c30129..f4e4a5ef3e4adf 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -61,6 +61,7 @@ class SemaSYCL : public SemaBase { SourceLocation RParen, ParsedType ParsedTy); + void handleSYCLExternalAttr(Decl *D, const ParsedAttr &AL); void handleKernelAttr(Decl *D, const ParsedAttr &AL); void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 33b680c4d93d4c..e57f1de9c11007 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7901,7 +7901,7 @@ ProcessDeclAttribute(Sema &S, Decl *D, const ParsedAttr &AL, S.SYCL().handleKernelAttr(D, AL); break; case ParsedAttr::AT_SYCLExternal: - handleSimpleAttribute<SYCLExternalAttr>(S, D, AL); + S.SYCL().handleSYCLExternalAttr(D, AL); break; case ParsedAttr::AT_SYCLKernelEntryPoint: S.SYCL().handleKernelEntryPointAttr(D, AL); diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index e180b3655bd730..56675ee9f2d107 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -278,6 +278,18 @@ static bool CheckSYCLKernelName(Sema &S, SourceLocation Loc, return false; } +void SemaSYCL::handleSYCLExternalAttr(Decl *D, const ParsedAttr &AL) { + // SYCL 2020 section 5.4 prohibits calling a variadic function from device + // code, so the attribute cannot be honored; declaring one is not prohibited, + // so ignore the attribute rather than reject the declaration. + if (cast<FunctionDecl>(D)->isVariadic()) { + Diag(AL.getLoc(), diag::warn_sycl_external_ignored_variadic_function) << AL; + return; + } + + handleSimpleAttribute<SYCLExternalAttr>(*this, D, AL); +} + void SemaSYCL::CheckSYCLExternalFunctionDecl(FunctionDecl *FD) { const auto *SEAttr = FD->getAttr<SYCLExternalAttr>(); assert(SEAttr && "Missing sycl_external attribute"); diff --git a/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp b/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp index d926e30376b188..814671329423e3 100644 --- a/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp +++ b/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp @@ -5,7 +5,10 @@ // RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \ // RUN: -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=WINDOWS %s -[[clang::sycl_external]] int f(int n, ...) { +// SYCL 2020 section 5.4, "Language restrictions for device functions", prohibits +// calls to variadic functions in device code, but doesn't prohibit other ODR-uses. +// Function f() is emitted during device compilation due to the ODR-use in g(). +int f(int n, ...) { __builtin_va_list ap1, ap2; __builtin_va_start(ap1, n); int v = __builtin_va_arg(ap1, int); @@ -15,6 +18,9 @@ return v; } +using FP = int (*)(int, ...); +[[clang::sycl_external]] FP g() { return f; } + // LINUX: define {{.*}} i32 @_Z1fiz(i32 noundef %n, ...) {{.*}} { // LINUX: %ap1 = alloca [1 x %struct.__va_list_tag], align 8 // LINUX: %ap2 = alloca [1 x %struct.__va_list_tag], align 8 diff --git a/clang/test/CodeGenSYCL/sycl-external-attr-variadic.cpp b/clang/test/CodeGenSYCL/sycl-external-attr-variadic.cpp new file mode 100644 index 00000000000000..e45af97492447e --- /dev/null +++ b/clang/test/CodeGenSYCL/sycl-external-attr-variadic.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown \ +// RUN: -disable-llvm-passes -emit-llvm -verify %s -o - | FileCheck %s \ +// RUN: --implicit-check-not=variadic_fn_test1 \ +// RUN: --implicit-check-not=reached_from_variadic_fn_test2 \ +// RUN: --implicit-check-not=variadic_caller_fn_test3 + +// This test checks that the sycl_external attribute is ignored for variadic +// functions; no device code is emitted for such functions. + +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] int variadic_fn_test1(int n, ...) { return n; } + +int reached_from_variadic_fn_test2() { return 1; } + +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] int variadic_caller_fn_test3(int n, ...) { + return reached_from_variadic_fn_test2(); +} + +// Check that non-variadic functions are emitted to ensure the lack of emission +// for the others is due to their being variadic functions. +[[clang::sycl_external]] int non_variadic_fn_test4(int n) { return n; } +// CHECK: define dso_local spir_func noundef i32 @{{.*}}non_variadic_fn_test4 diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp index 1b250676cf4784..c60501d5bd0bed 100644 --- a/clang/test/SemaSYCL/sycl-cconv.cpp +++ b/clang/test/SemaSYCL/sycl-cconv.cpp @@ -6,7 +6,7 @@ __inline __cdecl int printf(char const* const _Format, ...) { return 0; } -// FIXME: that should be diagnosed. +// expected-warning@+1 {{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} [[clang::sycl_external]] int foo(int, ...) { return 0; } __inline __cdecl int moo() { return 0; } diff --git a/clang/test/SemaSYCL/sycl-external-attr-variadic-undefined.cpp b/clang/test/SemaSYCL/sycl-external-attr-variadic-undefined.cpp new file mode 100644 index 00000000000000..8039017ae2b7ec --- /dev/null +++ b/clang/test/SemaSYCL/sycl-external-attr-variadic-undefined.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -fsyntax-only \ +// RUN: -verify %s + +// This test checks the diagnostics issued for an ODR-use of a variadic function +// declared, but not defined, with the ignored sycl_external attribute. + +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] void undefined_variadic_fn_test1(int, ...); + +[[clang::sycl_external]] void use_undefined_variadic_fn_test2() { + // FIXME: Clang does not diagnose an ODR-use of a function that is neither + // defined in this translation unit nor declared sycl_external. + // expected error once it does. + (void)&undefined_variadic_fn_test1; +} diff --git a/clang/test/SemaSYCL/sycl-external-attr.cpp b/clang/test/SemaSYCL/sycl-external-attr.cpp index ebda94e7d50307..922ca9c328846e 100644 --- a/clang/test/SemaSYCL/sycl-external-attr.cpp +++ b/clang/test/SemaSYCL/sycl-external-attr.cpp @@ -113,6 +113,36 @@ class D { // expected-error@+1{{'clang::sycl_external' cannot be applied to an explicitly deleted function}} [[clang::sycl_external]] void del() = delete; +// SYCL device code does not support variadic functions. +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] void var(int, ...) {} + +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] void vardecl(int, ...); + +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] void varredecl(int, ...); +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] void varredecl(int, ...) {} + +// expected-warning@+2{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +class E { + [[clang::sycl_external]] void mvar(int, ...) {} +}; + +template<typename... Ts> +[[clang::sycl_external]] void pack(Ts...) {} +template void pack(int); + +// expected-warning@+2{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +template<typename T> +[[clang::sycl_external]] void tvar(T, ...) {} +template void tvar(int, ...); +using TVarFP = void (*)(char, ...); +[[clang::sycl_external]] TVarFP tvar_implicit_instantiation() { + return &tvar<char>; +} + struct NonCopyable { ~NonCopyable() = delete; [[clang::sycl_external]] NonCopyable(const NonCopyable&) = default; diff --git a/clang/test/SemaSYCL/variadic-func-call.cpp b/clang/test/SemaSYCL/variadic-func-call.cpp index a9ce19dad226d3..a8e5143a7880d8 100644 --- a/clang/test/SemaSYCL/variadic-func-call.cpp +++ b/clang/test/SemaSYCL/variadic-func-call.cpp @@ -15,6 +15,9 @@ namespace NS { void variadic(int, ...) {} } +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] void external_variadic(int, ...) {} + struct S { S(int, ...) {} void operator()(int, ...) {} @@ -33,6 +36,7 @@ int main() { variadic(5); //expected-error{{SYCL device code does not support variadic functions}} variadic(5, 2); //expected-error{{SYCL device code does not support variadic functions}} NS::variadic(5, 3); //expected-error{{SYCL device code does not support variadic functions}} + external_variadic(5, 4); //expected-error{{SYCL device code does not support variadic functions}} S s(5, 4); //expected-error{{SYCL device code does not support variadic functions}} S s2(5); //expected-error{{SYCL device code does not support variadic functions}} s(5, 5); //expected-error{{SYCL device code does not support variadic functions}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
