Author: Haohai Wen Date: 2026-10-21T10:46:37+08:00 New Revision: 837f998d417a92ba9b56998e532454715749479f
URL: https://github.com/llvm/llvm-project/commit/837f998d417a92ba9b56998e532454715749479f DIFF: https://github.com/llvm/llvm-project/commit/837f998d417a92ba9b56998e532454715749479f.diff LOG: [clang-cl] Don't count linker inputs against /Fo and /Fa (#232611) The /Fo and /Fa checks reject a file name when there is more than one input. But the input list also holds object files, libraries, and linker options such as -Xlinker, which go straight to the linker and never get an output named by /Fo or /Fa. So clang-cl /c foo.c /Fofoo.obj -Xlinker -bar failed with "cannot specify '/Fofoo.obj' when compiling multiple source files". MSVC's cl.exe also accepts .obj and .lib inputs next to /Fo<file>. Count only the inputs that get compiled. Fixes #216085. Added: Modified: clang/lib/Driver/Driver.cpp clang/test/Driver/cl-outputs.c Removed: ################################################################################ diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 1c612c7d1547b..75471cfb63dd0 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3387,27 +3387,25 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, const InputList &Inputs, ActionList &Actions) const { - // Diagnose misuse of /Fo. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) { - StringRef V = A->getValue(); - if (Inputs.size() > 1 && !V.empty() && - !llvm::sys::path::is_separator(V.back())) { - // Check whether /Fo tries to name an output file for multiple inputs. - Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) - << A->getSpelling() << V; - Args.eraseArg(options::OPT__SLASH_Fo); - } - } - - // Diagnose misuse of /Fa. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) { - StringRef V = A->getValue(); - if (Inputs.size() > 1 && !V.empty() && - !llvm::sys::path::is_separator(V.back())) { - // Check whether /Fa tries to name an asm file for multiple inputs. - Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) - << A->getSpelling() << V; - Args.eraseArg(options::OPT__SLASH_Fa); + // Diagnose misuse of /Fo and /Fa. + if (Arg *FoArg = Args.getLastArg(options::OPT__SLASH_Fo), + *FaArg = Args.getLastArg(options::OPT__SLASH_Fa); + FoArg || FaArg) { + // Linker inputs do not produce the outputs named by /Fo and /Fa. + unsigned NumCompiledInputs = llvm::count_if( + Inputs, [](const InputTy &I) { return I.first != types::TY_Object; }); + + for (Arg *A : {FoArg, FaArg}) { + if (!A) + continue; + StringRef V = A->getValue(); + if (NumCompiledInputs > 1 && !V.empty() && + !llvm::sys::path::is_separator(V.back())) { + // Check whether /Fo or /Fa names an output file for multiple inputs. + Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) + << A->getSpelling() << V; + Args.eraseArg(A->getOption().getID()); + } } } diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index c59adc8acb3b6..b480f62897214 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -37,6 +37,11 @@ // CHECK-MULTIPLESOURCEOK2: "-o" "cl-outputs.obj" // CHECK-MULTIPLESOURCEOK2: "-o" "cl-outputs.obj" +// RUN: %clang_cl /c /Foa.obj -Xlinker -foo -### -- %s foo.obj foo.lib 2>&1 | FileCheck -check-prefix=FoLINKERINPUT %s +// RUN: %clang_cl /Foa.obj -Xlinker -foo -### -- %s foo.lib 2>&1 | FileCheck -check-prefix=FoLINKERINPUT %s +// FoLINKERINPUT-NOT: error: cannot specify '/Foa.obj' when compiling multiple source files +// FoLINKERINPUT: "-o" "a.obj" + // RUN: %clang_cl /c /oa -### -- %s 2>&1 | FileCheck -check-prefix=oNAME1 %s // oNAME1: "-o" "a.obj" @@ -243,6 +248,9 @@ // RUN: %clang_cl /Fa -### -- %s %s 2>&1 | FileCheck -check-prefix=FaMULTIPLESOURCEOK %s // FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm" // FaMULTIPLESOURCEOK: "-o" "cl-outputs.asm" +// RUN: %clang_cl /Faa.asm -Xlinker -foo -### -- %s foo.obj 2>&1 | FileCheck -check-prefix=FaLINKERINPUT %s +// FaLINKERINPUT-NOT: error: cannot specify '/Faa.asm' when compiling multiple source files +// FaLINKERINPUT: "-o" "a.asm" // Copy of the same tests above, but with /FAcsu // RUN: %clang_cl /FAcsu -### -- %s 2>&1 | FileCheck -check-prefix=FA_CSU %s _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
