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

Reply via email to