[clang] [Driver][SYCL] Treat C files as C++ when compiled with -fsycl (PR #200318)
Srividya Sundaram via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 2 18:03:04 PDT 2026
https://github.com/srividya-sundaram updated https://github.com/llvm/llvm-project/pull/200318
>From 928d8589b0b4188aaa9a8fb8bfb5aaa7a9194f5e Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Tue, 26 May 2026 10:06:00 -0700
Subject: [PATCH 1/5] [Driver][SYCL] Verify that a .c file compiled with -fsycl
is treated as C++ with a warning
---
.../clang/Basic/DiagnosticDriverKinds.td | 5 ++++
clang/lib/Driver/Driver.cpp | 26 +++++++++++++++++--
clang/test/Driver/sycl-c-warn.c | 7 +++++
3 files changed, 36 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Driver/sycl-c-warn.c
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 020014dabacfd..9a90b03c45b25 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -533,6 +533,11 @@ def warn_drv_overriding_complex_range : Warning<
def warn_drv_treating_input_as_cxx : Warning<
"treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
InGroup<Deprecated>;
+def warn_drv_fsycl_with_c_type : Warning<
+ "treating '%0' input as '%1' when -fsycl is used">,
+ InGroup<InvalidCommandLineArgument>;
+def err_drv_fsycl_with_c_type : Error<
+ "'%0' must not be used in conjunction with '-fsycl', which expects C++ source">;
def warn_drv_pch_not_first_include : Warning<
"precompiled header '%0' was ignored because '%1' is not first '-include'">;
def warn_drv_pch_ignoring_gch_file : Warning<
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ed3ddd130d6c7..bd30512ce9265 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3070,12 +3070,13 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
// actually use it, so we warn about unused -x arguments.
types::ID InputType = types::TY_Nothing;
Arg *InputTypeArg = nullptr;
+ bool IsSYCL = Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false);
// The last /TC or /TP option sets the input type to C or C++ globally.
if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,
options::OPT__SLASH_TP)) {
InputTypeArg = TCTP;
- InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)
+ InputType = TCTP->getOption().matches(options::OPT__SLASH_TC) && !IsSYCL
? types::TY_C
: types::TY_CXX;
@@ -3142,6 +3143,21 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (const char *Ext = strrchr(Value, '.'))
Ty = TC.LookupTypeForExtension(Ext + 1);
+ // For SYCL, convert C-type sources to C++-type sources.
+ if (IsSYCL) {
+ types::ID OldTy = Ty;
+ switch (Ty) {
+ case types::TY_C: Ty = types::TY_CXX; break;
+ case types::TY_CHeader: Ty = types::TY_CXXHeader; break;
+ case types::TY_PP_C: Ty = types::TY_PP_CXX; break;
+ case types::TY_PP_CHeader: Ty = types::TY_PP_CXXHeader; break;
+ default: break;
+ }
+ if (OldTy != Ty)
+ Diag(clang::diag::warn_drv_fsycl_with_c_type)
+ << getTypeName(OldTy) << getTypeName(Ty);
+ }
+
if (Ty == types::TY_INVALID) {
if (IsCLMode() && (Args.hasArgNoClaim(options::OPT_E) || CCGenDiagnostics))
Ty = types::TY_CXX;
@@ -3219,7 +3235,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (DiagnoseInputExistence(Value, types::TY_C,
/*TypoCorrect=*/false)) {
Arg *InputArg = makeInputArg(Args, Opts, A->getValue());
- Inputs.push_back(std::make_pair(types::TY_C, InputArg));
+ Inputs.push_back(
+ std::make_pair(IsSYCL ? types::TY_CXX : types::TY_C, InputArg));
}
A->claim();
} else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
@@ -3248,6 +3265,11 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
InputType = types::TY_Object;
}
+ // Emit an error if C compilation is forced in -fsycl mode.
+ if (IsSYCL && (InputType == types::TY_C || InputType == types::TY_PP_C ||
+ InputType == types::TY_CHeader))
+ Diag(clang::diag::err_drv_fsycl_with_c_type) << A->getAsString(Args);
+
// If the user has put -fmodule-header{,=} then we treat C++ headers as
// header unit inputs. So we 'promote' -xc++-header appropriately.
if (InputType == types::TY_CXXHeader && hasHeaderMode())
diff --git a/clang/test/Driver/sycl-c-warn.c b/clang/test/Driver/sycl-c-warn.c
new file mode 100644
index 0000000000000..4f3474add0f1c
--- /dev/null
+++ b/clang/test/Driver/sycl-c-warn.c
@@ -0,0 +1,7 @@
+// Verify that a .c file compiled with -fsycl is treated as C++ with a warning.
+// RUN: %clang -### -fsycl %s 2>&1 | FileCheck -check-prefix WARN %s
+// WARN: warning: treating 'c' input as 'c++' when -fsycl is used
+
+// Verify that explicitly forcing -x c with -fsycl is an error.
+// RUN: %clang -### -fsycl -x c %s 2>&1 | FileCheck -check-prefix ERR %s
+// ERR: error: '-x c' must not be used in conjunction with '-fsycl', which expects C++ source
>From bb2c790e47038d113f01bf867a480b0d74ebe8e0 Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Thu, 28 May 2026 20:01:57 -0700
Subject: [PATCH 2/5] Update test.
---
clang/test/Driver/sycl-c-warn.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/Driver/sycl-c-warn.c b/clang/test/Driver/sycl-c-warn.c
index 4f3474add0f1c..df21103898639 100644
--- a/clang/test/Driver/sycl-c-warn.c
+++ b/clang/test/Driver/sycl-c-warn.c
@@ -1,7 +1,7 @@
// Verify that a .c file compiled with -fsycl is treated as C++ with a warning.
// RUN: %clang -### -fsycl %s 2>&1 | FileCheck -check-prefix WARN %s
-// WARN: warning: treating 'c' input as 'c++' when -fsycl is used
+// WARN: warning: treating 'c' input as 'c++' when -fsycl is used [-Winvalid-command-line-argument]
// Verify that explicitly forcing -x c with -fsycl is an error.
-// RUN: %clang -### -fsycl -x c %s 2>&1 | FileCheck -check-prefix ERR %s
+// RUN: not %clang -### -fsycl -x c %s 2>&1 | FileCheck -check-prefix ERR %s
// ERR: error: '-x c' must not be used in conjunction with '-fsycl', which expects C++ source
>From cc232aa8017621757ebabdf7dc1f1fb93b27ec19 Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Thu, 28 May 2026 20:08:28 -0700
Subject: [PATCH 3/5] clang format
---
clang/lib/Driver/Driver.cpp | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index bd30512ce9265..1439ba718b718 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3147,11 +3147,20 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (IsSYCL) {
types::ID OldTy = Ty;
switch (Ty) {
- case types::TY_C: Ty = types::TY_CXX; break;
- case types::TY_CHeader: Ty = types::TY_CXXHeader; break;
- case types::TY_PP_C: Ty = types::TY_PP_CXX; break;
- case types::TY_PP_CHeader: Ty = types::TY_PP_CXXHeader; break;
- default: break;
+ case types::TY_C:
+ Ty = types::TY_CXX;
+ break;
+ case types::TY_CHeader:
+ Ty = types::TY_CXXHeader;
+ break;
+ case types::TY_PP_C:
+ Ty = types::TY_PP_CXX;
+ break;
+ case types::TY_PP_CHeader:
+ Ty = types::TY_PP_CXXHeader;
+ break;
+ default:
+ break;
}
if (OldTy != Ty)
Diag(clang::diag::warn_drv_fsycl_with_c_type)
>From 59ffd02a26b9abfa05999e8cda57c9e4ea48f5d5 Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Fri, 29 May 2026 08:38:55 -0700
Subject: [PATCH 4/5] [Driver][SYCL] Reuse existing C-to-C++ input promotion
for -fsycl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Instead of adding SYCL-specific diagnostics and a duplicate type-promotion
switch, extend the existing CCCIsCXX() path in BuildInputs to also trigger
when -fsycl is active. This reuses types::lookupCXXTypeForCType() for the
C→C++ type promotion and warn_drv_treating_input_as_cxx for the warning.
The -x c error case is similarly replaced with the generic
err_drv_argument_not_allowed_with diagnostic.
---
.../clang/Basic/DiagnosticDriverKinds.td | 5 ----
clang/lib/Driver/Driver.cpp | 30 +++----------------
clang/test/Driver/sycl-c-warn.c | 4 +--
3 files changed, 6 insertions(+), 33 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 9a90b03c45b25..020014dabacfd 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -533,11 +533,6 @@ def warn_drv_overriding_complex_range : Warning<
def warn_drv_treating_input_as_cxx : Warning<
"treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
InGroup<Deprecated>;
-def warn_drv_fsycl_with_c_type : Warning<
- "treating '%0' input as '%1' when -fsycl is used">,
- InGroup<InvalidCommandLineArgument>;
-def err_drv_fsycl_with_c_type : Error<
- "'%0' must not be used in conjunction with '-fsycl', which expects C++ source">;
def warn_drv_pch_not_first_include : Warning<
"precompiled header '%0' was ignored because '%1' is not first '-include'">;
def warn_drv_pch_ignoring_gch_file : Warning<
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 1439ba718b718..4b62963270b96 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3143,30 +3143,6 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (const char *Ext = strrchr(Value, '.'))
Ty = TC.LookupTypeForExtension(Ext + 1);
- // For SYCL, convert C-type sources to C++-type sources.
- if (IsSYCL) {
- types::ID OldTy = Ty;
- switch (Ty) {
- case types::TY_C:
- Ty = types::TY_CXX;
- break;
- case types::TY_CHeader:
- Ty = types::TY_CXXHeader;
- break;
- case types::TY_PP_C:
- Ty = types::TY_PP_CXX;
- break;
- case types::TY_PP_CHeader:
- Ty = types::TY_PP_CXXHeader;
- break;
- default:
- break;
- }
- if (OldTy != Ty)
- Diag(clang::diag::warn_drv_fsycl_with_c_type)
- << getTypeName(OldTy) << getTypeName(Ty);
- }
-
if (Ty == types::TY_INVALID) {
if (IsCLMode() && (Args.hasArgNoClaim(options::OPT_E) || CCGenDiagnostics))
Ty = types::TY_CXX;
@@ -3180,7 +3156,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
// If the driver is invoked as C++ compiler (like clang++ or c++) it
// should autodetect some input files as C++ for g++ compatibility.
- if (CCCIsCXX()) {
+ // -fsycl also requires C++ sources, so apply the same promotion.
+ if (CCCIsCXX() || IsSYCL) {
types::ID OldTy = Ty;
Ty = types::lookupCXXTypeForCType(Ty);
@@ -3277,7 +3254,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
// Emit an error if C compilation is forced in -fsycl mode.
if (IsSYCL && (InputType == types::TY_C || InputType == types::TY_PP_C ||
InputType == types::TY_CHeader))
- Diag(clang::diag::err_drv_fsycl_with_c_type) << A->getAsString(Args);
+ Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-fsycl";
// If the user has put -fmodule-header{,=} then we treat C++ headers as
// header unit inputs. So we 'promote' -xc++-header appropriately.
diff --git a/clang/test/Driver/sycl-c-warn.c b/clang/test/Driver/sycl-c-warn.c
index df21103898639..9de4067daaa53 100644
--- a/clang/test/Driver/sycl-c-warn.c
+++ b/clang/test/Driver/sycl-c-warn.c
@@ -1,7 +1,7 @@
// Verify that a .c file compiled with -fsycl is treated as C++ with a warning.
// RUN: %clang -### -fsycl %s 2>&1 | FileCheck -check-prefix WARN %s
-// WARN: warning: treating 'c' input as 'c++' when -fsycl is used [-Winvalid-command-line-argument]
+// WARN: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
// Verify that explicitly forcing -x c with -fsycl is an error.
// RUN: not %clang -### -fsycl -x c %s 2>&1 | FileCheck -check-prefix ERR %s
-// ERR: error: '-x c' must not be used in conjunction with '-fsycl', which expects C++ source
+// ERR: error: invalid argument '-x c' not allowed with '-fsycl'
>From 68263e2be3d902d56e7864b312ca34c1a23e5b32 Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Tue, 2 Jun 2026 18:02:29 -0700
Subject: [PATCH 5/5] [Driver][SYCL] Error on C inputs when compiling with
-fsycl
-fsycl requires C++ source files. Rather than silently promoting C
inputs to C++ (which could mask issues like -std=c17 or other
C-specific flags being ignored), emit an error when a C-type file is
detected, whether via file extension or explicit -x c. The check is
placed before the CCCIsCXX() promotion block since -fsycl implies C++
mode and would otherwise promote TY_C to TY_CXX before the check fires.
Reuses the existing err_drv_argument_not_allowed_with diagnostic to
avoid adding SYCL-specific diagnostics.
---
clang/lib/Driver/Driver.cpp | 9 +++++++--
clang/test/Driver/sycl-c-warn.c | 12 ++++++------
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 4b62963270b96..c7c88f2891c91 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3154,10 +3154,15 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
Ty = types::TY_Object;
}
+ // -fsycl requires C++ source; error if a C file is detected.
+ if (IsSYCL && (Ty == types::TY_C || Ty == types::TY_PP_C ||
+ Ty == types::TY_CHeader || Ty == types::TY_PP_CHeader))
+ Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << Value << "-fsycl";
+
// If the driver is invoked as C++ compiler (like clang++ or c++) it
// should autodetect some input files as C++ for g++ compatibility.
- // -fsycl also requires C++ sources, so apply the same promotion.
- if (CCCIsCXX() || IsSYCL) {
+ if (CCCIsCXX()) {
types::ID OldTy = Ty;
Ty = types::lookupCXXTypeForCType(Ty);
diff --git a/clang/test/Driver/sycl-c-warn.c b/clang/test/Driver/sycl-c-warn.c
index 9de4067daaa53..28358ac0fe88d 100644
--- a/clang/test/Driver/sycl-c-warn.c
+++ b/clang/test/Driver/sycl-c-warn.c
@@ -1,7 +1,7 @@
-// Verify that a .c file compiled with -fsycl is treated as C++ with a warning.
-// RUN: %clang -### -fsycl %s 2>&1 | FileCheck -check-prefix WARN %s
-// WARN: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+// Verify that a .c file compiled with -fsycl is an error.
+// RUN: not %clang -### -fsycl %s 2>&1 | FileCheck -check-prefix ERR %s
+// ERR: error: invalid argument '{{.*}}sycl-c-warn.c' not allowed with '-fsycl'
-// Verify that explicitly forcing -x c with -fsycl is an error.
-// RUN: not %clang -### -fsycl -x c %s 2>&1 | FileCheck -check-prefix ERR %s
-// ERR: error: invalid argument '-x c' not allowed with '-fsycl'
+// Verify that explicitly forcing -x c with -fsycl is also an error.
+// RUN: not %clang -### -fsycl -x c %s 2>&1 | FileCheck -check-prefix ERR_XC %s
+// ERR_XC: error: invalid argument '-x c' not allowed with '-fsycl'
More information about the cfe-commits
mailing list