https://github.com/rthomas-activision updated https://github.com/llvm/llvm-project/pull/189977
>From 1e698a3919320b8e5594b02383bc6ff65e06f497 Mon Sep 17 00:00:00 2001 From: Romain Thomas <[email protected]> Date: Wed, 1 Apr 2026 10:19:43 +0200 Subject: [PATCH 1/5] [clang][Driver] Ensure intermediate bitcode files are written according to `/Fo` With the following compilation process: ``` $ mkdir -p src/ tmp/ $ cat << 'EOF' > src/main.c int main() { return 0; } EOF $ clang-cl /c /Fo:tmp/ /clang:-fembed-bitcode src/main.c ``` the object file `main.obj` is generated in the `tmp/` directory but the intermediate `main.bc` is placed in the current working directory. Ensure that intermediate `.bc` files are written to the same directory specified by `/Fo`. --- clang/lib/Driver/Driver.cpp | 6 ++++++ clang/test/Driver/cl-outputs.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 0686a89d42faf..7d11d61cb84da 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -6629,6 +6629,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, ->getValue(); NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object); + } else if ((JA.getType() == types::TY_LLVM_BC || + JA.getType() == types::TY_LLVM_IR) && + IsCLMode() && C.getArgs().hasArg(options::OPT__SLASH_Fo)) { + StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue(); + NamedOutput = + MakeCLOutputFilename(C.getArgs(), Val, BaseName, JA.getType()); } else { const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode()); diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index a8509e795c295..fc5fb49d2a514 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -310,3 +310,6 @@ // RUN: %clang_cl -target x86_64-windows -fdebug-compilation-dir=. /Z7 /Fofoo/a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH2 %s // RELATIVE_OBJPATH2: "-object-file-name=foo\\a.obj" + +// RUN: %clang_cl /c /Fodir/ /clang:-fembed-bitcode -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC %s +// FoNAMEBC: "-o" "dir/cl-outputs.bc" >From 6943feeb8f7af540ab5fd2082372635e1ebf8eb9 Mon Sep 17 00:00:00 2001 From: Romain Thomas <[email protected]> Date: Thu, 2 Apr 2026 18:38:46 +0200 Subject: [PATCH 2/5] updates tests to include `-emit-llvm` --- clang/test/Driver/cl-outputs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index fc5fb49d2a514..e2ce16ee840e1 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -313,3 +313,9 @@ // RUN: %clang_cl /c /Fodir/ /clang:-fembed-bitcode -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC %s // FoNAMEBC: "-o" "dir/cl-outputs.bc" + +// RUN: %clang_cl /c /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC2 %s +// FoNAMEBC2: "-o" "cl-outputs.bc" + +// RUN: %clang_cl /c /Fodir/ /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC3 %s +// FoNAMEBC3: "-o" "dir/cl-outputs.bc" >From e37dfff4fbd4a8a1884b8ad95eb9bf0d397a0ae3 Mon Sep 17 00:00:00 2001 From: Romain Thomas <[email protected]> Date: Fri, 3 Apr 2026 15:39:36 +0200 Subject: [PATCH 3/5] add support for the `-o` option with the appropriated tests --- clang/lib/Driver/Driver.cpp | 9 +++++++-- clang/test/Driver/cl-outputs.c | 15 +++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 7d11d61cb84da..f77c7fde8b0a7 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -6631,8 +6631,13 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object); } else if ((JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LLVM_IR) && - IsCLMode() && C.getArgs().hasArg(options::OPT__SLASH_Fo)) { - StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue(); + IsCLMode() && + C.getArgs().hasArg(options::OPT__SLASH_Fo, + options::OPT__SLASH_o)) { + StringRef Val = + C.getArgs() + .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o) + ->getValue(); NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, JA.getType()); } else { diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index e2ce16ee840e1..c59adc8acb3b6 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -313,9 +313,16 @@ // RUN: %clang_cl /c /Fodir/ /clang:-fembed-bitcode -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC %s // FoNAMEBC: "-o" "dir/cl-outputs.bc" +// FoNAMEBC: "-o" "dir/cl-outputs.obj" -// RUN: %clang_cl /c /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC2 %s -// FoNAMEBC2: "-o" "cl-outputs.bc" +// RUN: %clang_cl /c /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=EMITLLVM %s +// EMITLLVM: "-o" "cl-outputs.bc" -// RUN: %clang_cl /c /Fodir/ /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEBC3 %s -// FoNAMEBC3: "-o" "dir/cl-outputs.bc" +// RUN: %clang_cl /c /Fodir/ /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=EMITLLVM_Fo %s +// EMITLLVM_Fo: "-o" "dir/cl-outputs.bc" + +// RUN: %clang_cl /c /odir/ /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=EMITLLVM_o %s +// EMITLLVM_o: "-o" "dir/cl-outputs.bc" + +// RUN: %clang_cl /c /omain.bc /clang:-emit-llvm -### -- %s 2>&1 | FileCheck -check-prefix=EMITLLVM_oNAME %s +// EMITLLVM_oNAME: "-o" "main.bc" >From 04f8e0684e2328a335571d5f655318b8acf77442 Mon Sep 17 00:00:00 2001 From: Romain Thomas <[email protected]> Date: Tue, 7 Apr 2026 10:04:34 +0200 Subject: [PATCH 4/5] address latest feedback --- clang/lib/Driver/Driver.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index f77c7fde8b0a7..d84df6ce2969c 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -6574,15 +6574,25 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, // Determine what the derived output name should be. const char *NamedOutput; - if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) && + if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC || + JA.getType() == types::TY_LLVM_BC || + JA.getType() == types::TY_LLVM_IR) && C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) { // The /Fo or /o flag decides the object filename. StringRef Val = C.getArgs() .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o) ->getValue(); + types::ID OutputFileTy = types::TY_Object; + if (JA.getType() == types::TY_LLVM_BC || + JA.getType() == types::TY_LLVM_IR) { + // As discussed in PR #189977, this prevents intermediate files from + // receiving an incorrect object extension and unintentionally overwriting + // the final object file. + OutputFileTy = JA.getType(); + } NamedOutput = - MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object); + MakeCLOutputFilename(C.getArgs(), Val, BaseName, OutputFileTy); } else if (JA.getType() == types::TY_Image && C.getArgs().hasArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)) { @@ -6629,17 +6639,6 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, ->getValue(); NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object); - } else if ((JA.getType() == types::TY_LLVM_BC || - JA.getType() == types::TY_LLVM_IR) && - IsCLMode() && - C.getArgs().hasArg(options::OPT__SLASH_Fo, - options::OPT__SLASH_o)) { - StringRef Val = - C.getArgs() - .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o) - ->getValue(); - NamedOutput = - MakeCLOutputFilename(C.getArgs(), Val, BaseName, JA.getType()); } else { const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode()); >From 2e078aea35dc06dff443ca75e0af92aed54c333d Mon Sep 17 00:00:00 2001 From: Romain Thomas <[email protected]> Date: Wed, 8 Apr 2026 09:20:53 +0200 Subject: [PATCH 5/5] forward `JA.getType()` unconditionally --- clang/lib/Driver/Driver.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index d84df6ce2969c..cc55129506a2b 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -6583,16 +6583,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, C.getArgs() .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o) ->getValue(); - types::ID OutputFileTy = types::TY_Object; - if (JA.getType() == types::TY_LLVM_BC || - JA.getType() == types::TY_LLVM_IR) { - // As discussed in PR #189977, this prevents intermediate files from - // receiving an incorrect object extension and unintentionally overwriting - // the final object file. - OutputFileTy = JA.getType(); - } NamedOutput = - MakeCLOutputFilename(C.getArgs(), Val, BaseName, OutputFileTy); + MakeCLOutputFilename(C.getArgs(), Val, BaseName, JA.getType()); } else if (JA.getType() == types::TY_Image && C.getArgs().hasArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
