https://github.com/schittir updated https://github.com/llvm/llvm-project/pull/216393
>From 0feaeafbb0cdc1e36195c1dd40804969dada3d83 Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Fri, 14 Aug 2026 11:10:01 -0700 Subject: [PATCH 1/3] [clang][SYCL] Diagnose variadic sycl_external functions at their declaration SYCL device code does not support variadic functions. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaSYCL.cpp | 5 +++++ .../spirv-host-adaptation-valist.cpp | 9 +++++---- clang/test/SemaSYCL/sycl-cconv.cpp | 2 +- clang/test/SemaSYCL/sycl-external-attr.cpp | 16 ++++++++++++++++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b314c17ad27bd..3816eafaf7e3c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13545,6 +13545,8 @@ 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 err_sycl_external_invalid_variadic_function : Error< + "%0 cannot be applied to a variadic function">; def warn_sycl_external_missing_on_first_decl : Warning< "%0 attribute does not appear on the first declaration">, InGroup<NonPortableSYCL>; diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index b942f19761f40..0f2f5753d4136 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -293,6 +293,11 @@ void SemaSYCL::CheckSYCLExternalFunctionDecl(FunctionDecl *FD) { diag::err_sycl_external_invalid_deleted_function) << SEAttr; } + if (FD->isVariadic()) { + Diag(SEAttr->getLocation(), + diag::err_sycl_external_invalid_variadic_function) + << SEAttr; + } } void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) { diff --git a/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp b/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp index d926e30376b18..799eaf257af71 100644 --- a/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp +++ b/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp @@ -5,9 +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, ...) { +/// No variadic functions in SYCL device code, so 'ap' comes from the caller. +[[clang::sycl_external]] int f(__builtin_va_list *ap) { __builtin_va_list ap1, ap2; - __builtin_va_start(ap1, n); + __builtin_va_copy(ap1, *ap); int v = __builtin_va_arg(ap1, int); __builtin_va_copy(ap2, ap1); __builtin_va_end(ap1); @@ -15,10 +16,10 @@ return v; } -// LINUX: define {{.*}} i32 @_Z1fiz(i32 noundef %n, ...) {{.*}} { +// LINUX: define {{.*}} i32 @_Z1fPA1_13__va_list_tag( // LINUX: %ap1 = alloca [1 x %struct.__va_list_tag], align 8 // LINUX: %ap2 = alloca [1 x %struct.__va_list_tag], align 8 -// WINDOWS: define {{.*}} i32 @_Z1fiz(i32 noundef %n, ...) {{.*}} { +// WINDOWS: define {{.*}} i32 @_Z1fPPc( // WINDOWS: %ap1 = alloca ptr addrspace(4), align 8 // WINDOWS: %ap2 = alloca ptr addrspace(4), align 8 diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp index 664a4dbf37c49..1d3ba97b624bf 100644 --- a/clang/test/SemaSYCL/sycl-cconv.cpp +++ b/clang/test/SemaSYCL/sycl-cconv.cpp @@ -8,7 +8,7 @@ // no-aux-error@+1 {{variadic function cannot use spir_function calling convention}} __inline __cdecl int printf(char const* const _Format, ...) { return 0; } -// FIXME: that should be diagnosed. +// expected-error@+1 {{'clang::sycl_external' cannot be applied to a variadic function}} [[clang::sycl_external]] int foo(int, ...) { return 0; } // no-aux-warning@+1 {{'__cdecl' calling convention is not supported for this target}} diff --git a/clang/test/SemaSYCL/sycl-external-attr.cpp b/clang/test/SemaSYCL/sycl-external-attr.cpp index ebda94e7d5030..22f4276d5a547 100644 --- a/clang/test/SemaSYCL/sycl-external-attr.cpp +++ b/clang/test/SemaSYCL/sycl-external-attr.cpp @@ -113,6 +113,22 @@ 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-error@+1{{'clang::sycl_external' cannot be applied to a variadic function}} +[[clang::sycl_external]] void var(int, ...) {} + +// expected-error@+1{{'clang::sycl_external' cannot be applied to a variadic function}} +[[clang::sycl_external]] void vardecl(int, ...); + +// expected-error@+2{{'clang::sycl_external' cannot be applied to a variadic function}} +class E { + [[clang::sycl_external]] void mvar(int, ...) {} +}; + +template<typename... Ts> +[[clang::sycl_external]] void pack(Ts...) {} +template void pack(int); + struct NonCopyable { ~NonCopyable() = delete; [[clang::sycl_external]] NonCopyable(const NonCopyable&) = default; >From fbed1e75c687dd652c64b95cc81b9a353ae9078f Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Thu, 20 Aug 2026 20:43:20 -0700 Subject: [PATCH 2/3] Replace the error with a warning --- clang/include/clang/Basic/AttrDocs.td | 6 ++++++ .../include/clang/Basic/DiagnosticSemaKinds.td | 6 ++++-- clang/include/clang/Sema/SemaSYCL.h | 5 +++++ clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaSYCL.cpp | 17 ++++++++++++----- clang/test/SemaSYCL/sycl-cconv.cpp | 2 +- clang/test/SemaSYCL/sycl-external-attr.cpp | 15 ++++++++++++--- clang/test/SemaSYCL/variadic-func-call.cpp | 4 ++++ 8 files changed, 45 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 847e44688ed95..c10ea02b71d33 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -645,6 +645,10 @@ following requirements: The attribute shall be present on the first declaration of a function and may optionally be present on subsequent declarations. +The attribute is ignored, with a warning, when applied to a variadic function. +A variadic function cannot be called from device code, so there is no reason to +emit device code for one. + 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. @@ -661,6 +665,8 @@ The following examples demonstrate the use of this attribute: [[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 3816eafaf7e3c..38ca60c1d94a1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13545,8 +13545,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 err_sycl_external_invalid_variadic_function : Error< - "%0 cannot be applied to a variadic 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 4980aa44c3012..7d3b5653964f0 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -62,6 +62,11 @@ class SemaSYCL : public SemaBase { ParsedType ParsedTy); void handleKernelAttr(Decl *D, const ParsedAttr &AL); + + /// Adds a SYCLExternalAttr to 'D', or warns that the attribute is ignored if + /// 'D' is a variadic function. + void handleExternalAttr(Decl *D, const ParsedAttr &AL); + void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL); /// Issues a deferred diagnostic if use of the declaration designated diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0645f99492433..06461220658d3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7846,7 +7846,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, S.SYCL().handleKernelAttr(D, AL); break; case ParsedAttr::AT_SYCLExternal: - handleSimpleAttribute<SYCLExternalAttr>(S, D, AL); + S.SYCL().handleExternalAttr(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 0f2f5753d4136..a96cb060cee4c 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -213,6 +213,18 @@ void SemaSYCL::handleKernelAttr(Decl *D, const ParsedAttr &AL) { handleSimpleAttribute<SYCLKernelAttr>(*this, D, AL); } +void SemaSYCL::handleExternalAttr(Decl *D, const ParsedAttr &AL) { + // Device code can neither call a variadic function nor take its address, so + // there is no reason to emit device code for one. Since SYCL 2020 prohibits + // only the call, 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::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) { ParsedType PT = AL.getTypeArg(); TypeSourceInfo *TSI = nullptr; @@ -293,11 +305,6 @@ void SemaSYCL::CheckSYCLExternalFunctionDecl(FunctionDecl *FD) { diag::err_sycl_external_invalid_deleted_function) << SEAttr; } - if (FD->isVariadic()) { - Diag(SEAttr->getLocation(), - diag::err_sycl_external_invalid_variadic_function) - << SEAttr; - } } void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) { diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp index 1d3ba97b624bf..dee3cee8b95c1 100644 --- a/clang/test/SemaSYCL/sycl-cconv.cpp +++ b/clang/test/SemaSYCL/sycl-cconv.cpp @@ -8,7 +8,7 @@ // no-aux-error@+1 {{variadic function cannot use spir_function calling convention}} __inline __cdecl int printf(char const* const _Format, ...) { return 0; } -// expected-error@+1 {{'clang::sycl_external' cannot be applied to a variadic function}} +// 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; } // no-aux-warning@+1 {{'__cdecl' calling convention is not supported for this target}} diff --git a/clang/test/SemaSYCL/sycl-external-attr.cpp b/clang/test/SemaSYCL/sycl-external-attr.cpp index 22f4276d5a547..a02ae48c6fd9a 100644 --- a/clang/test/SemaSYCL/sycl-external-attr.cpp +++ b/clang/test/SemaSYCL/sycl-external-attr.cpp @@ -114,13 +114,18 @@ class D { [[clang::sycl_external]] void del() = delete; // SYCL device code does not support variadic functions. -// expected-error@+1{{'clang::sycl_external' cannot be applied to a variadic function}} +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} [[clang::sycl_external]] void var(int, ...) {} -// expected-error@+1{{'clang::sycl_external' cannot be applied to a variadic function}} +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} [[clang::sycl_external]] void vardecl(int, ...); -// expected-error@+2{{'clang::sycl_external' cannot be applied to a variadic function}} +// 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, ...) {} }; @@ -129,6 +134,10 @@ 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, ...) {} + 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 a9ce19dad226d..a8e5143a7880d 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}} >From 519113cc345eed13dd22b0f2ca67bbdbbb6f17b5 Mon Sep 17 00:00:00 2001 From: Sindhu Chittireddy <[email protected]> Date: Fri, 21 Aug 2026 13:25:14 -0700 Subject: [PATCH 3/3] Keep the warning but stick to the original (non-handler) design. --- clang/include/clang/Sema/SemaSYCL.h | 5 ----- clang/lib/Sema/SemaDecl.cpp | 4 +++- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaSYCL.cpp | 22 +++++++++---------- .../spirv-host-adaptation-valist.cpp | 14 +++++++----- .../sycl-external-attr-variadic.cpp | 21 ++++++++++++++++++ 6 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 clang/test/CodeGenSYCL/sycl-external-attr-variadic.cpp diff --git a/clang/include/clang/Sema/SemaSYCL.h b/clang/include/clang/Sema/SemaSYCL.h index 7d3b5653964f0..4980aa44c3012 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -62,11 +62,6 @@ class SemaSYCL : public SemaBase { ParsedType ParsedTy); void handleKernelAttr(Decl *D, const ParsedAttr &AL); - - /// Adds a SYCLExternalAttr to 'D', or warns that the attribute is ignored if - /// 'D' is a variadic function. - void handleExternalAttr(Decl *D, const ParsedAttr &AL); - void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL); /// Issues a deferred diagnostic if use of the declaration designated diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 032737c7a191d..17fecd2805886 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4243,8 +4243,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, // used on the first declaration of that function in the translation unit. // Redeclarations of the function in the same translation unit may // optionally use SYCL_EXTERNAL, but this is not required. + // The attribute is ignored and dropped for a variadic function, so 'Old' + // won't have it; 'New' still does since the drop happens after this check. const SYCLExternalAttr *SEA = New->getAttr<SYCLExternalAttr>(); - if (SEA && !Old->hasAttr<SYCLExternalAttr>()) { + if (SEA && !New->isVariadic() && !Old->hasAttr<SYCLExternalAttr>()) { Diag(SEA->getLocation(), diag::warn_sycl_external_missing_on_first_decl) << SEA; Diag(Old->getLocation(), diag::note_previous_declaration); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 06461220658d3..0645f99492433 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7846,7 +7846,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, S.SYCL().handleKernelAttr(D, AL); break; case ParsedAttr::AT_SYCLExternal: - S.SYCL().handleExternalAttr(D, AL); + handleSimpleAttribute<SYCLExternalAttr>(S, 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 a96cb060cee4c..29453e57e8f0f 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -213,18 +213,6 @@ void SemaSYCL::handleKernelAttr(Decl *D, const ParsedAttr &AL) { handleSimpleAttribute<SYCLKernelAttr>(*this, D, AL); } -void SemaSYCL::handleExternalAttr(Decl *D, const ParsedAttr &AL) { - // Device code can neither call a variadic function nor take its address, so - // there is no reason to emit device code for one. Since SYCL 2020 prohibits - // only the call, 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::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) { ParsedType PT = AL.getTypeArg(); TypeSourceInfo *TSI = nullptr; @@ -293,6 +281,16 @@ static bool CheckSYCLKernelName(Sema &S, SourceLocation Loc, void SemaSYCL::CheckSYCLExternalFunctionDecl(FunctionDecl *FD) { const auto *SEAttr = FD->getAttr<SYCLExternalAttr>(); assert(SEAttr && "Missing sycl_external attribute"); + // 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 (FD->isVariadic()) { + Diag(SEAttr->getLocation(), + diag::warn_sycl_external_ignored_variadic_function) + << SEAttr; + FD->dropAttr<SYCLExternalAttr>(); + return; + } if (!FD->isInvalidDecl() && !FD->isTemplated()) { if (!FD->isExternallyVisible()) if (!FD->isFunctionTemplateSpecialization() || diff --git a/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp b/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp index 799eaf257af71..359da08ba86d5 100644 --- a/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp +++ b/clang/test/CodeGenSPIRV/spirv-host-adaptation-valist.cpp @@ -5,10 +5,11 @@ // 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 -/// No variadic functions in SYCL device code, so 'ap' comes from the caller. -[[clang::sycl_external]] int f(__builtin_va_list *ap) { +/// The sycl_external attribute is ignored for a variadic function, so 'f' is +/// emitted because 'g' references it. +int f(int n, ...) { __builtin_va_list ap1, ap2; - __builtin_va_copy(ap1, *ap); + __builtin_va_start(ap1, n); int v = __builtin_va_arg(ap1, int); __builtin_va_copy(ap2, ap1); __builtin_va_end(ap1); @@ -16,10 +17,13 @@ return v; } -// LINUX: define {{.*}} i32 @_Z1fPA1_13__va_list_tag( +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 -// WINDOWS: define {{.*}} i32 @_Z1fPPc( +// WINDOWS: define {{.*}} i32 @_Z1fiz(i32 noundef %n, ...) {{.*}} { // WINDOWS: %ap1 = alloca ptr addrspace(4), align 8 // WINDOWS: %ap2 = alloca ptr addrspace(4), 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 0000000000000..f2c8ecdbc679b --- /dev/null +++ b/clang/test/CodeGenSYCL/sycl-external-attr-variadic.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown \ +// RUN: -disable-llvm-passes -emit-llvm -verify %s -o - | FileCheck %s + +// 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(int n, ...) { return n; } +// CHECK-NOT: @_Z8variadiciz + +int reachedFromVariadicOnly() { return 1; } +// CHECK-NOT: @_Z23reachedFromVariadicOnlyv + +// expected-warning@+1{{'clang::sycl_external' attribute ignored; a variadic function cannot be called from device code}} +[[clang::sycl_external]] int variadicCaller(int n, ...) { + return reachedFromVariadicOnly(); +} +// CHECK-NOT: @_Z14variadicCalleriz + +// CHECK: define dso_local spir_func noundef i32 @_Z11nonVariadici +[[clang::sycl_external]] int nonVariadic(int n) { return n; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
