[clang] 94ca490 - [clang][SYCL] Handle cdecl variadic functions for SYCL device (#194922)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 4 01:49:44 PDT 2026
Author: Mariya Podchishchaeva
Date: 2026-05-04T10:49:38+02:00
New Revision: 94ca49099ef77751a33e4babe41b2ae03ff228e1
URL: https://github.com/llvm/llvm-project/commit/94ca49099ef77751a33e4babe41b2ae03ff228e1
DIFF: https://github.com/llvm/llvm-project/commit/94ca49099ef77751a33e4babe41b2ae03ff228e1.diff
LOG: [clang][SYCL] Handle cdecl variadic functions for SYCL device (#194922)
SYCL doesn't allow variadic functions to be called from device code.
Since SYCL device compilation mostly uses targets that don't natively
support variadic fucntions, we now issue an error even if the variadic
function is never called from the device if it has cdecl calling
convention attribute. We also now don't issue an error if a variadic
function is called from the device code. This patch defers the error
caused by cdecl attribute to the actual call point and adds diagnosing
of variadic function calls on device side using deferred diagnostics.
Added:
clang/test/SemaSYCL/sycl-cconv.cpp
clang/test/SemaSYCL/variadic-func-call.cpp
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaDeclAttr.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1302c4296885b..8c4c6f6bce8d7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9752,7 +9752,8 @@ def warn_kern_is_inline : Warning<
"ignored 'inline' attribute on kernel function %0">,
InGroup<CudaCompat>;
def err_variadic_device_fn : Error<
- "CUDA device code does not support variadic functions">;
+ "%enum_select<OffloadLang>{%CUDA{CUDA}|%SYCL{SYCL}}0 device code does not "
+ "support variadic functions">;
def err_va_arg_in_device : Error<
"CUDA device code does not support va_arg">;
def err_alias_not_supported_on_nvptx : Error<"CUDA older than 10.0 does not support .alias">;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index eb957df6f1e97..9f950f185f8f0 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -76,6 +76,7 @@
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
+#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
@@ -4466,6 +4467,11 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
}
}
+ if (FD && FD->isVariadic() && getLangOpts().SYCLIsDevice &&
+ !isUnevaluatedContext())
+ SYCL().DiagIfDeviceCode(Loc, diag::err_variadic_device_fn)
+ << diag::OffloadLang::SYCL;
+
if (FD)
diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 76073ed80175f..28e51848609bb 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5823,14 +5823,12 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
A = HostTI->checkCallingConvention(CC);
if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
A = DeviceTI->checkCallingConvention(CC);
- } else if (LangOpts.SYCLIsDevice && TI.getTriple().isAMDGPU() &&
- CC == CC_X86VectorCall) {
- // Assuming SYCL Device AMDGPU CC_X86VectorCall functions are always to be
- // emitted on the host. The MSVC STL has CC-based specializations so we
- // cannot change the CC to be the default as that will cause a clash with
- // another specialization.
- A = TI.checkCallingConvention(CC);
- if (Aux && A != TargetInfo::CCCR_OK)
+ } else if (LangOpts.SYCLIsDevice) {
+ // In SYCL we may meet unsupported calling conventions in host code,
+ // especially inside of included headers. Now we don't know if they will be
+ // emitted, so we just defer any diagnostics. Check for the host triple if
+ // we have one, since everything is still emitted for the host.
+ if (Aux)
A = Aux->checkCallingConvention(CC);
} else {
A = TI.checkCallingConvention(CC);
diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp
new file mode 100644
index 0000000000000..b4b5e35ed0614
--- /dev/null
+++ b/clang/test/SemaSYCL/sycl-cconv.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify %s
+
+// Check that there is no error/warning emitted for cdecl functions compiled for
+// SYCL device. Make sure variadic calls from within device code are diagnosed.
+
+__inline __cdecl int printf(char const* const _Format, ...) { return 0; }
+
+// FIXME: that should be diagnosed.
+[[clang::sycl_external]] int foo(int, ...) { return 0; }
+
+__inline __cdecl int moo() { return 0; }
+
+void bar() {
+ printf("hello\n");
+}
+
+template<typename KN, typename...Args>
+void sycl_kernel_launch(Args ...args) {}
+
+template<typename KN, typename K>
+[[clang::sycl_kernel_entry_point(KN)]]
+__cdecl void sycl_entry_point(K k) {
+ k(); // expected-note {{called by}}
+}
+
+int main() {
+ //expected-error at +1 {{SYCL device code does not support variadic functions}}
+ sycl_entry_point<class kn>([]() { printf("world\n");
+ moo();
+ //expected-error at +1 {{SYCL device code does not support variadic functions}}
+ foo(1,2); });
+ bar();
+ return 0;
+}
diff --git a/clang/test/SemaSYCL/variadic-func-call.cpp b/clang/test/SemaSYCL/variadic-func-call.cpp
new file mode 100644
index 0000000000000..a9ce19dad226d
--- /dev/null
+++ b/clang/test/SemaSYCL/variadic-func-call.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify %s
+
+template<typename KN, typename...Args>
+void sycl_kernel_launch(Args ...args) {}
+
+template<typename KN, typename K>
+[[clang::sycl_kernel_entry_point(KN)]]
+void sycl_entry_point(K k) {
+ k(); // expected-note 2{{called by}}
+}
+
+void variadic(int, ...) {}
+namespace NS {
+void variadic(int, ...) {}
+}
+
+struct S {
+ S(int, ...) {}
+ void operator()(int, ...) {}
+};
+
+void foo() {
+ auto x = [](int, ...) {};
+ x(5, 10); //expected-error{{SYCL device code does not support variadic functions}}
+}
+
+void overloaded(int, int) {}
+void overloaded(int, ...) {}
+
+int main() {
+ sycl_entry_point<class FK>([]() {
+ 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}}
+ 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}}
+ s2(5); //expected-error{{SYCL device code does not support variadic functions}}
+ foo(); //expected-note{{called by 'operator()'}}
+ overloaded(5, 6); //expected-no-error
+ overloaded(5, s); //expected-error{{SYCL device code does not support variadic functions}}
+ overloaded(5); //expected-error{{SYCL device code does not support variadic functions}}
+ });
+}
More information about the cfe-commits
mailing list