https://github.com/srividya-sundaram created https://github.com/llvm/llvm-project/pull/200318
SYCL is a C++-only programming model, but the Clang driver in llvm-project would silently accept .c files when -fsycl was specified and compile them as C. This could lead to confusing errors deep in compilation rather than a clear diagnostic at the driver level. This patch implements the following behavior: - A .c file passed with -fsycl is automatically treated as C++ and a warning is emitted: treating 'c' input as 'c++' when -fsycl is used - Explicitly forcing -x c alongside -fsycl is now an error: '-x c' must not be used in conjunction with '-fsycl', which expects C++ source - The same promotion applies to .h and preprocessed C files (.i), and to the MSVC-style /TC and /Tc flags - The warning uses -Winvalid-command-line-argument, consistent with how llvm-project diagnoses other conflicting driver flag combinations. >From 928d8589b0b4188aaa9a8fb8bfb5aaa7a9194f5e Mon Sep 17 00:00:00 2001 From: srividya sundaram <[email protected]> Date: Tue, 26 May 2026 10:06:00 -0700 Subject: [PATCH 1/2] [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 <[email protected]> Date: Thu, 28 May 2026 20:01:57 -0700 Subject: [PATCH 2/2] 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
