https://github.com/jdenny-ornl updated 
https://github.com/llvm/llvm-project/pull/149003

>From 670d2ab7ad2df476e89326dc1845106453ec7579 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.o...@gmail.com>
Date: Tue, 15 Jul 2025 21:10:03 -0400
Subject: [PATCH 1/5] [LinkerWrapper] Fix -fsave-optimization-record default
 file

As discussed in PR #145603, the following command fails to produce a
YAML remarks file for offload LTO passes and thus for kernel-info:

```
clang -O2 -g -fopenmp --offload-arch=native test.c -foffload-lto \
  -Rpass=kernel-info -fsave-optimization-record
```

The problem is that, in clang-linker-wrapper's clang call, clang names
the file based on clang's main output file (from `-o`).  That is a
temporary file, so the YAML file becomes a temporary file, which the
user never sees.

This patch:
- Extends clang with a hidden `-foutput-file-base=BASE` option that
  overrides the main output file as the base for other output files.
- Makes clang honor that option only for the default YAML remarks
  file, but future patches could use it for other output files too.
- Extends clang-linker-wrapper to specify that option to clang.
---
 clang/include/clang/Driver/Options.td         |  6 ++++
 .../include/clang/Frontend/FrontendOptions.h  |  3 ++
 clang/lib/Driver/ToolChains/CommonArgs.cpp    |  8 +++--
 clang/test/Driver/linker-wrapper.c            | 32 +++++++++----------
 clang/test/Driver/opt-record.c                | 11 +++++++
 .../ClangLinkerWrapper.cpp                    | 11 ++++---
 6 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index d0b54a446309b..d96e1437f0f40 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5880,6 +5880,12 @@ def o : JoinedOrSeparate<["-"], "o">,
   Visibility<[ClangOption, CC1Option, CC1AsOption, FC1Option, FlangOption]>,
   HelpText<"Write output to <file>">, MetaVarName<"<file>">,
   MarshallingInfoString<FrontendOpts<"OutputFile">>;
+def foutput_file_base : Joined<["-"], "foutput-file-base=">,
+  Flags<[NoXarchOption, HelpHidden]>,
+  Visibility<[ClangOption]>,
+  HelpText<"Name extra output files after <base> not the main output file">,
+  MetaVarName<"<base>">,
+  MarshallingInfoString<FrontendOpts<"OutputFileBase">>;
 def object_file_name_EQ : Joined<["-"], "object-file-name=">,
   Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption, DXCOption]>,
   HelpText<"Set the output <file> for debug infos">, MetaVarName<"<file>">,
diff --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index c919a53ae089e..a03165e05962c 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -439,6 +439,9 @@ class FrontendOptions {
   /// The output file, if any.
   std::string OutputFile;
 
+  /// The base, if any, to use instead of OutputFile for extra output files.
+  std::string OutputFileBase;
+
   /// If given, the new suffix for fix-it rewritten files.
   std::string FixItSuffix;
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 097d186ad8ea4..513425a855511 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -294,8 +294,9 @@ static void renderRemarksOptions(const ArgList &Args, 
ArgStringList &CmdArgs,
     Format = A->getValue();
 
   SmallString<128> F;
-  const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
-  if (A)
+  if (const Arg *A = 
Args.getLastArg(options::OPT_foptimization_record_file_EQ))
+    F = A->getValue();
+  else if (const Arg *A = Args.getLastArg(options::OPT_foutput_file_base))
     F = A->getValue();
   else if (Output.isFilename())
     F = Output.getFilename();
@@ -1320,6 +1321,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
   if (Args.hasArg(options::OPT_ftime_report))
     CmdArgs.push_back(
         Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes"));
+
+  // clang-linker-wrapper adds this without checking if it is needed.
+  Args.ClaimAllArgs(options::OPT_foutput_file_base);
 }
 
 void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
diff --git a/clang/test/Driver/linker-wrapper.c 
b/clang/test/Driver/linker-wrapper.c
index 80b1a5745a123..d97328b6600a8 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -22,7 +22,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=NVPTX-LINK
 
-// NVPTX-LINK: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda 
-march=sm_70 {{.*}}.o {{.*}}.o
+// NVPTX-LINK: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.nvptx64.sm_70.img --target=nvptx64-nvidia-cuda 
-march=sm_70 {{.*}}.o {{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   
--image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \
@@ -40,7 +40,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=AMDGPU-LINK
 
-// AMDGPU-LINK: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMDGPU-LINK: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   
--image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030 \
@@ -57,7 +57,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: not clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu 
--dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=SPIRV-LINK
 
-// SPIRV-LINK: clang{{.*}} -o {{.*}}.img --target=spirv64-unknown-unknown 
{{.*}}.o --sycl-link -Xlinker -triple=spirv64-unknown-unknown -Xlinker -arch=
+// SPIRV-LINK: clang{{.*}} -o {{.*}}.img -foutput-file-base=a.out.spirv64..img 
--target=spirv64-unknown-unknown {{.*}}.o --sycl-link -Xlinker 
-triple=spirv64-unknown-unknown -Xlinker -arch=
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
@@ -68,7 +68,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld --whole-archive %t.a 
--no-whole-archive \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CPU-LINK
 
-// CPU-LINK: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu 
-Wl,--no-undefined {{.*}}.o {{.*}}.o -Wl,-Bsymbolic -shared -Wl,--whole-archive 
{{.*}}.a -Wl,--no-whole-archive
+// CPU-LINK: clang{{.*}} -o {{.*}}.img -foutput-file-base=a.out.x86_64..img 
--target=x86_64-unknown-linux-gnu -Wl,--no-undefined {{.*}}.o {{.*}}.o 
-Wl,-Bsymbolic -shared -Wl,--whole-archive {{.*}}.a -Wl,--no-whole-archive
 
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu 
-mllvm -openmp-opt-disable \
@@ -100,8 +100,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \
 // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=CUDA
 
-// CUDA: clang{{.*}} -o [[IMG_SM70:.+]] --target=nvptx64-nvidia-cuda 
-march=sm_70
-// CUDA: clang{{.*}} -o [[IMG_SM52:.+]] --target=nvptx64-nvidia-cuda 
-march=sm_52
+// CUDA: clang{{.*}} -o [[IMG_SM70:.+]] 
-foutput-file-base=a.out.nvptx64.sm_70.img --target=nvptx64-nvidia-cuda 
-march=sm_70
+// CUDA: clang{{.*}} -o [[IMG_SM52:.+]] 
-foutput-file-base=a.out.nvptx64.sm_52.img --target=nvptx64-nvidia-cuda 
-march=sm_52
 // CUDA: fatbinary{{.*}}-64 --create {{.*}}.fatbin 
--image=profile=sm_70,file=[[IMG_SM70]] --image=profile=sm_52,file=[[IMG_SM52]]
 // CUDA: usr/bin/ld{{.*}} {{.*}}.openmp.image.{{.*}}.o 
{{.*}}.cuda.image.{{.*}}.o
 
@@ -127,8 +127,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --compress --compression-level=6 \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=HIP
 
-// HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a
-// HIP: clang{{.*}} -o [[IMG_GFX908:.+]] --target=amdgcn-amd-amdhsa 
-mcpu=gfx908
+// HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] 
-foutput-file-base=a.out.amdgcn.gfx90a.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a
+// HIP: clang{{.*}} -o [[IMG_GFX908:.+]] 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908
 // HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -compress 
-compression-level=6 
-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx90a,hip-amdgcn-amd-amdhsa--gfx908
 -input={{/dev/null|NUL}} -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] 
-output={{.*}}.hipfb
 
 // RUN: clang-offload-packager -o %t.out \
@@ -157,7 +157,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run 
--clang-backend \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=CLANG-BACKEND
 
-// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o
+// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   
--image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
@@ -180,8 +180,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t-on.o %t-off.o %t.a -o a.out 2>&1 | 
FileCheck %s --check-prefix=AMD-TARGET-ID
 
-// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a:xnack+ -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
-// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a:xnack- -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a:xnack+.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a:xnack+ -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a:xnack-.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a:xnack- -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
 
 // RUN: clang-offload-packager -o %t-lib.out \
 // RUN:   
--image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=generic
@@ -196,8 +196,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t1.o %t2.o %t.a -o a.out 2>&1 | FileCheck 
%s --check-prefix=ARCH-ALL
 
-// ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a 
-flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
-// ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 
-flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// ARCH-ALL: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// ARCH-ALL: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
@@ -207,7 +207,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK
 
-// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img 
--target=x86_64-unknown-linux-gnu
+// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.x86_64..img --target=x86_64-unknown-linux-gnu
 // RELOCATABLE-LINK: /usr/bin/ld.lld{{.*}}-r
 // RELOCATABLE-LINK: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading
 
@@ -219,7 +219,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-HIP
 
-// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa
+// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a.img --target=amdgcn-amd-amdhsa
 // RELOCATABLE-LINK-HIP: clang-offload-bundler{{.*}} -type=o 
-bundle-align=4096 
-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx90a 
-input={{/dev/null|NUL}} -input={{.*}} -output={{.*}}
 // RELOCATABLE-LINK-HIP: /usr/bin/ld.lld{{.*}}-r
 // RELOCATABLE-LINK-HIP: llvm-objcopy{{.*}}a.out --remove-section 
.llvm.offloading
@@ -233,7 +233,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=RELOCATABLE-LINK-CUDA
 
-// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img 
--target=nvptx64-nvidia-cuda
+// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.nvptx64.sm_89.img --target=nvptx64-nvidia-cuda
 // RELOCATABLE-LINK-CUDA: fatbinary{{.*}} -64 --create {{.*}}.fatbin 
--image=profile=sm_89,file={{.*}}.img
 // RELOCATABLE-LINK-CUDA: /usr/bin/ld.lld{{.*}}-r
 // RELOCATABLE-LINK-CUDA: llvm-objcopy{{.*}}a.out --remove-section 
.llvm.offloading
diff --git a/clang/test/Driver/opt-record.c b/clang/test/Driver/opt-record.c
index 220f5db7fbca2..afbc2a012abb1 100644
--- a/clang/test/Driver/opt-record.c
+++ b/clang/test/Driver/opt-record.c
@@ -78,3 +78,14 @@
 // CHECK-PASS-RPASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100"
 
 // CHECK-PASS-AUTO:   "-plugin-opt=opt-remarks-hotness-threshold=auto"
+
+// Check -foutput-file-base effect on -foptimization-record-file.
+// RUN: %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld -flto 
-fsave-optimization-record -foutput-file-base=/dir/file.ext %s 2>&1 | FileCheck 
%s -check-prefix=CHECK-BASE
+// RUN: %clang --target=x86_64-linux -### -o FOO -fuse-ld=lld -B%S/Inputs/lld 
-flto -fsave-optimization-record -foutput-file-base=/dir/file.ext %s 2>&1 | 
FileCheck %s -check-prefix=CHECK-BASE
+// RUN: %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld -flto 
-fsave-optimization-record -foptimization-record-file=user-file.ext 
-foutput-file-base=/dir/file.ext %s 2>&1 | FileCheck %s 
-check-prefix=CHECK-IGNORE-BASE
+
+// CHECK-BASE:      
"-plugin-opt=opt-remarks-filename=/dir/file.ext.opt.ld.yaml"
+// CHECK-BASE-SAME: "-plugin-opt=opt-remarks-format=yaml"
+
+// CHECK-IGNORE-BASE:      
"-plugin-opt=opt-remarks-filename=user-file.ext.opt.ld.yaml"
+// CHECK-IGNORE-BASE-SAME: "-plugin-opt=opt-remarks-format=yaml"
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp 
b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 9d34b62da20f5..8a459efc843b4 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/TargetID.h"
 #include "clang/Basic/Version.h"
+#include "clang/Driver/Options.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
@@ -474,10 +475,10 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, 
const ArgList &Args,
   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
   // Create a new file to write the linked device image to. Assume that the
   // input filename already has the device and architecture.
-  auto TempFileOrErr =
-      createOutputFile(sys::path::filename(ExecutableName) + "." +
-                           Triple.getArchName() + "." + Arch,
-                       "img");
+  std::string OutputFileBase =
+      "." + Triple.getArchName().str() + "." + Arch.str();
+  auto TempFileOrErr = createOutputFile(
+      sys::path::filename(ExecutableName) + OutputFileBase, "img");
   if (!TempFileOrErr)
     return TempFileOrErr.takeError();
 
@@ -486,6 +487,8 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, 
const ArgList &Args,
       "--no-default-config",
       "-o",
       *TempFileOrErr,
+      Args.MakeArgString("-foutput-file-base=" + ExecutableName +
+                         OutputFileBase + ".img"),
       Args.MakeArgString("--target=" + Triple.getTriple()),
   };
 

>From ed6071d5dd69ea0d01aef0d74c8c2fea1cd02829 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.o...@gmail.com>
Date: Wed, 16 Jul 2025 15:59:33 -0400
Subject: [PATCH 2/5] Drop unused OutputFileBase variable

---
 clang/include/clang/Driver/Options.td          | 3 +--
 clang/include/clang/Frontend/FrontendOptions.h | 3 ---
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 6e20466e35966..58ec37e327940 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5899,8 +5899,7 @@ def foutput_file_base : Joined<["-"], 
"foutput-file-base=">,
   Flags<[NoXarchOption, HelpHidden]>,
   Visibility<[ClangOption]>,
   HelpText<"Name extra output files after <base> not the main output file">,
-  MetaVarName<"<base>">,
-  MarshallingInfoString<FrontendOpts<"OutputFileBase">>;
+  MetaVarName<"<base>">;
 def object_file_name_EQ : Joined<["-"], "object-file-name=">,
   Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption, DXCOption]>,
   HelpText<"Set the output <file> for debug infos">, MetaVarName<"<file>">,
diff --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index a03165e05962c..c919a53ae089e 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -439,9 +439,6 @@ class FrontendOptions {
   /// The output file, if any.
   std::string OutputFile;
 
-  /// The base, if any, to use instead of OutputFile for extra output files.
-  std::string OutputFileBase;
-
   /// If given, the new suffix for fix-it rewritten files.
   std::string FixItSuffix;
 

>From a04b47058378274a046d835efe9a4f49ff579d58 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.o...@gmail.com>
Date: Wed, 16 Jul 2025 15:59:41 -0400
Subject: [PATCH 3/5] Extend to benefit -gsplit-dwarf as well

---
 clang/lib/Driver/ToolChains/CommonArgs.cpp | 10 ++++-
 clang/test/Driver/opt-record.c             | 47 +++++++++++++++++-----
 2 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 79b00259367d3..80a3bf185dd92 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1068,9 +1068,15 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
     }
   }
 
-  if (Args.hasArg(options::OPT_gsplit_dwarf))
+  if (Args.hasArg(options::OPT_gsplit_dwarf)) {
+    StringRef F;
+    if (const Arg *A = Args.getLastArg(options::OPT_foutput_file_base))
+      F = A->getValue();
+    else
+      F = Output.getFilename();
     CmdArgs.push_back(Args.MakeArgString(
-        Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo"));
+        Twine(PluginOptPrefix) + "dwo_dir=" + F + "_dwo"));
+  }
 
   if (IsThinLTO && !IsOSAIX)
     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto"));
diff --git a/clang/test/Driver/opt-record.c b/clang/test/Driver/opt-record.c
index afbc2a012abb1..c648bf80fabeb 100644
--- a/clang/test/Driver/opt-record.c
+++ b/clang/test/Driver/opt-record.c
@@ -79,13 +79,40 @@
 
 // CHECK-PASS-AUTO:   "-plugin-opt=opt-remarks-hotness-threshold=auto"
 
-// Check -foutput-file-base effect on -foptimization-record-file.
-// RUN: %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld -flto 
-fsave-optimization-record -foutput-file-base=/dir/file.ext %s 2>&1 | FileCheck 
%s -check-prefix=CHECK-BASE
-// RUN: %clang --target=x86_64-linux -### -o FOO -fuse-ld=lld -B%S/Inputs/lld 
-flto -fsave-optimization-record -foutput-file-base=/dir/file.ext %s 2>&1 | 
FileCheck %s -check-prefix=CHECK-BASE
-// RUN: %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld -flto 
-fsave-optimization-record -foptimization-record-file=user-file.ext 
-foutput-file-base=/dir/file.ext %s 2>&1 | FileCheck %s 
-check-prefix=CHECK-IGNORE-BASE
-
-// CHECK-BASE:      
"-plugin-opt=opt-remarks-filename=/dir/file.ext.opt.ld.yaml"
-// CHECK-BASE-SAME: "-plugin-opt=opt-remarks-format=yaml"
-
-// CHECK-IGNORE-BASE:      
"-plugin-opt=opt-remarks-filename=user-file.ext.opt.ld.yaml"
-// CHECK-IGNORE-BASE-SAME: "-plugin-opt=opt-remarks-format=yaml"
+// Check -foutput-file-base effect on -foptimization-record-file and
+// -gsplit-dwarf.
+//
+// DEFINE: %{RUN-BASE} = \
+// DEFINE:   %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld \
+// DEFINE:       -flto -fsave-optimization-record -gsplit-dwarf %s
+//
+// RUN: %{RUN-BASE} 2>&1 | FileCheck %s -check-prefix=CHECK-BASE-NONE
+//
+// RUN: %{RUN-BASE} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-BASE-O
+//
+// RUN: %{RUN-BASE} -foutput-file-base=/dir/file.ext 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=CHECK-BASE
+//
+// RUN: %{RUN-BASE} -o FOO -foutput-file-base=/dir/file.ext 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=CHECK-BASE
+//
+// There is currently no option to ignore -foutput-file-base in the case of
+// -gsplit-dwarf.
+// RUN: %{RUN-BASE} -foutput-file-base=/dir/file.ext \
+// RUN:     -foptimization-record-file=user-file.ext 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=CHECK-BASE-IGNORE
+//
+//        CHECK-BASE-NONE: "-plugin-opt=dwo_dir=a.out_dwo"
+//   CHECK-BASE-NONE-SAME: "-plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml"
+//   CHECK-BASE-NONE-SAME: "-plugin-opt=opt-remarks-format=yaml"
+//
+//           CHECK-BASE-O: "-plugin-opt=dwo_dir=FOO_dwo"
+//      CHECK-BASE-O-SAME: "-plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml"
+//      CHECK-BASE-O-SAME: "-plugin-opt=opt-remarks-format=yaml"
+//
+//             CHECK-BASE: "-plugin-opt=dwo_dir=/dir/file.ext_dwo"
+//        CHECK-BASE-SAME: 
"-plugin-opt=opt-remarks-filename=/dir/file.ext.opt.ld.yaml"
+//        CHECK-BASE-SAME: "-plugin-opt=opt-remarks-format=yaml"
+//
+//      CHECK-BASE-IGNORE: 
"-plugin-opt=opt-remarks-filename=user-file.ext.opt.ld.yaml"
+// CHECK-BASE-IGNORE-SAME: "-plugin-opt=opt-remarks-format=yaml"

>From 25381a23798a7a8745219542810c20e4e37376a2 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.o...@gmail.com>
Date: Wed, 16 Jul 2025 17:23:51 -0400
Subject: [PATCH 4/5] Apply clang-format

---
 clang/lib/Driver/ToolChains/CommonArgs.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 80a3bf185dd92..e76b3bfee901d 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1074,8 +1074,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
       F = A->getValue();
     else
       F = Output.getFilename();
-    CmdArgs.push_back(Args.MakeArgString(
-        Twine(PluginOptPrefix) + "dwo_dir=" + F + "_dwo"));
+    CmdArgs.push_back(
+        Args.MakeArgString(Twine(PluginOptPrefix) + "dwo_dir=" + F + "_dwo"));
   }
 
   if (IsThinLTO && !IsOSAIX)

>From 81db69d90cf1372feb4da55127fd21ff9cb2c684 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.o...@gmail.com>
Date: Thu, 17 Jul 2025 21:37:05 -0400
Subject: [PATCH 5/5] Drop -foutput-file-base, use -dumpdir

---
 clang/include/clang/Driver/Options.td         |  5 --
 clang/lib/Driver/ToolChains/CommonArgs.cpp    | 27 ++++++-----
 clang/test/Driver/linker-wrapper-libs.c       | 32 ++++++-------
 clang/test/Driver/linker-wrapper.c            | 32 ++++++-------
 clang/test/Driver/lto-dwo.c                   | 20 +++++++-
 clang/test/Driver/opt-record.c                | 46 +++++--------------
 .../ClangLinkerWrapper.cpp                    |  9 ++--
 7 files changed, 82 insertions(+), 89 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 58ec37e327940..a8c1b5dd8ab3b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5895,11 +5895,6 @@ def o : JoinedOrSeparate<["-"], "o">,
   Visibility<[ClangOption, CC1Option, CC1AsOption, FC1Option, FlangOption]>,
   HelpText<"Write output to <file>">, MetaVarName<"<file>">,
   MarshallingInfoString<FrontendOpts<"OutputFile">>;
-def foutput_file_base : Joined<["-"], "foutput-file-base=">,
-  Flags<[NoXarchOption, HelpHidden]>,
-  Visibility<[ClangOption]>,
-  HelpText<"Name extra output files after <base> not the main output file">,
-  MetaVarName<"<base>">;
 def object_file_name_EQ : Joined<["-"], "object-file-name=">,
   Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption, DXCOption]>,
   HelpText<"Set the output <file> for debug infos">, MetaVarName<"<file>">,
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index e76b3bfee901d..4e5d2fbd34e2e 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -294,18 +294,22 @@ static void renderRemarksOptions(const ArgList &Args, 
ArgStringList &CmdArgs,
     Format = A->getValue();
 
   SmallString<128> F;
-  if (const Arg *A = 
Args.getLastArg(options::OPT_foptimization_record_file_EQ))
+  if (const Arg *A =
+          Args.getLastArg(options::OPT_foptimization_record_file_EQ)) {
     F = A->getValue();
-  else if (const Arg *A = Args.getLastArg(options::OPT_foutput_file_base))
+    F += ".";
+  } else if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) {
     F = A->getValue();
-  else if (Output.isFilename())
+  } else if (Output.isFilename()) {
     F = Output.getFilename();
+    F += ".";
+  }
 
   assert(!F.empty() && "Cannot determine remarks output name.");
   // Append "opt.ld.<format>" to the end of the file name.
   CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
-                                       "opt-remarks-filename=" + F +
-                                       ".opt.ld." + Format));
+                                       "opt-remarks-filename=" + F + "opt.ld." 
+
+                                       Format));
 
   if (const Arg *A =
           Args.getLastArg(options::OPT_foptimization_record_passes_EQ))
@@ -1069,13 +1073,15 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
   }
 
   if (Args.hasArg(options::OPT_gsplit_dwarf)) {
-    StringRef F;
-    if (const Arg *A = Args.getLastArg(options::OPT_foutput_file_base))
+    SmallString<128> F;
+    if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) {
       F = A->getValue();
-    else
+    } else {
       F = Output.getFilename();
+      F += "_";
+    }
     CmdArgs.push_back(
-        Args.MakeArgString(Twine(PluginOptPrefix) + "dwo_dir=" + F + "_dwo"));
+        Args.MakeArgString(Twine(PluginOptPrefix) + "dwo_dir=" + F + "dwo"));
   }
 
   if (IsThinLTO && !IsOSAIX)
@@ -1338,9 +1344,6 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
     for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ))
       CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A));
   }
-
-  // clang-linker-wrapper adds this without checking if it is needed.
-  Args.ClaimAllArgs(options::OPT_foutput_file_base);
 }
 
 void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
diff --git a/clang/test/Driver/linker-wrapper-libs.c 
b/clang/test/Driver/linker-wrapper-libs.c
index cb5c7c137a0ba..1404fe3fc7a3e 100644
--- a/clang/test/Driver/linker-wrapper-libs.c
+++ b/clang/test/Driver/linker-wrapper-libs.c
@@ -48,8 +48,8 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-RESOLVES
 
-// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda 
-march=sm_70 {{.*}}.o {{.*}}.o
-// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx1030 {{.*}}.o {{.*}}.o
+// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
+// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
 
 //
 // Check that we extract a static library that defines a global visibile to the
@@ -72,8 +72,8 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL
 
-// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda 
-march=sm_70 {{.*}}.o {{.*}}.o
-// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx1030 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
 
 //
 // Check that we do not extract a global symbol if the source file was not
@@ -95,8 +95,8 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-NONE
 
-// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
-// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
 
 //
 // Check that we do not extract an external weak symbol.
@@ -116,9 +116,9 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-WEAK
 
-// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda 
-march=sm_70
+// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70
 // LIBRARY-WEAK-NOT: {{.*}}.o {{.*}}.o
-// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx1030
+// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030
 
 //
 // Check that we do not extract an unneeded hidden symbol.
@@ -138,9 +138,9 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-HIDDEN
 
-// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda 
-march=sm_70
+// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70
 // LIBRARY-HIDDEN-NOT: {{.*}}.o {{.*}}.o
-// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx1030
+// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030
 
 //
 // Check that we do not extract a static library that defines a global visibile
@@ -161,9 +161,9 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.o %t.a %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-DEFINED
 
-// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
 // LIBRARY-GLOBAL-DEFINED-NOT: {{.*}}gfx1030{{.*}}.o
-// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
 
 //
 // Check that we can use --[no-]whole-archive to control extraction.
@@ -185,7 +185,7 @@ int bar() { return weak; }
 // RUN:   --linker-path=/usr/bin/ld %t.o --whole-archive %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-WHOLE-ARCHIVE
 
-// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
-// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx1030 {{.*}}.o {{.*}}.o
-// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img 
--target=nvptx64-nvidia-cuda -march=sm_52 {{.*}}.o
-// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a {{.*}}.o
+// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
+// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
+// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=nvptx64-nvidia-cuda -march=sm_52 {{.*}}.o
+// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx90a {{.*}}.o
diff --git a/clang/test/Driver/linker-wrapper.c 
b/clang/test/Driver/linker-wrapper.c
index d97328b6600a8..e73fa5ca3dbf9 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -22,7 +22,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=NVPTX-LINK
 
-// NVPTX-LINK: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.nvptx64.sm_70.img --target=nvptx64-nvidia-cuda 
-march=sm_70 {{.*}}.o {{.*}}.o
+// NVPTX-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.nvptx64.sm_70.img. 
--target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   
--image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \
@@ -40,7 +40,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=AMDGPU-LINK
 
-// AMDGPU-LINK: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMDGPU-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx908.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o 
{{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   
--image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030 \
@@ -57,7 +57,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: not clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu 
--dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=SPIRV-LINK
 
-// SPIRV-LINK: clang{{.*}} -o {{.*}}.img -foutput-file-base=a.out.spirv64..img 
--target=spirv64-unknown-unknown {{.*}}.o --sycl-link -Xlinker 
-triple=spirv64-unknown-unknown -Xlinker -arch=
+// SPIRV-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.spirv64..img. 
--target=spirv64-unknown-unknown {{.*}}.o --sycl-link -Xlinker 
-triple=spirv64-unknown-unknown -Xlinker -arch=
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
@@ -68,7 +68,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld --whole-archive %t.a 
--no-whole-archive \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CPU-LINK
 
-// CPU-LINK: clang{{.*}} -o {{.*}}.img -foutput-file-base=a.out.x86_64..img 
--target=x86_64-unknown-linux-gnu -Wl,--no-undefined {{.*}}.o {{.*}}.o 
-Wl,-Bsymbolic -shared -Wl,--whole-archive {{.*}}.a -Wl,--no-whole-archive
+// CPU-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.x86_64..img. 
--target=x86_64-unknown-linux-gnu -Wl,--no-undefined {{.*}}.o {{.*}}.o 
-Wl,-Bsymbolic -shared -Wl,--whole-archive {{.*}}.a -Wl,--no-whole-archive
 
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu 
-mllvm -openmp-opt-disable \
@@ -100,8 +100,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \
 // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=CUDA
 
-// CUDA: clang{{.*}} -o [[IMG_SM70:.+]] 
-foutput-file-base=a.out.nvptx64.sm_70.img --target=nvptx64-nvidia-cuda 
-march=sm_70
-// CUDA: clang{{.*}} -o [[IMG_SM52:.+]] 
-foutput-file-base=a.out.nvptx64.sm_52.img --target=nvptx64-nvidia-cuda 
-march=sm_52
+// CUDA: clang{{.*}} -o [[IMG_SM70:.+]] -dumpdir a.out.nvptx64.sm_70.img. 
--target=nvptx64-nvidia-cuda -march=sm_70
+// CUDA: clang{{.*}} -o [[IMG_SM52:.+]] -dumpdir a.out.nvptx64.sm_52.img. 
--target=nvptx64-nvidia-cuda -march=sm_52
 // CUDA: fatbinary{{.*}}-64 --create {{.*}}.fatbin 
--image=profile=sm_70,file=[[IMG_SM70]] --image=profile=sm_52,file=[[IMG_SM52]]
 // CUDA: usr/bin/ld{{.*}} {{.*}}.openmp.image.{{.*}}.o 
{{.*}}.cuda.image.{{.*}}.o
 
@@ -127,8 +127,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --compress --compression-level=6 \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=HIP
 
-// HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] 
-foutput-file-base=a.out.amdgcn.gfx90a.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a
-// HIP: clang{{.*}} -o [[IMG_GFX908:.+]] 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908
+// HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] -dumpdir a.out.amdgcn.gfx90a.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx90a
+// HIP: clang{{.*}} -o [[IMG_GFX908:.+]] -dumpdir a.out.amdgcn.gfx908.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx908
 // HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -compress 
-compression-level=6 
-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx90a,hip-amdgcn-amd-amdhsa--gfx908
 -input={{/dev/null|NUL}} -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] 
-output={{.*}}.hipfb
 
 // RUN: clang-offload-packager -o %t.out \
@@ -157,7 +157,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run 
--clang-backend \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=CLANG-BACKEND
 
-// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o
+// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx908.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   
--image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
@@ -180,8 +180,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t-on.o %t-off.o %t.a -o a.out 2>&1 | 
FileCheck %s --check-prefix=AMD-TARGET-ID
 
-// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a:xnack+.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a:xnack+ -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
-// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a:xnack-.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a:xnack- -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img -dumpdir 
a.out.amdgcn.gfx90a:xnack+.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ 
-flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img -dumpdir 
a.out.amdgcn.gfx90a:xnack-.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- 
-flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
 
 // RUN: clang-offload-packager -o %t-lib.out \
 // RUN:   
--image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=generic
@@ -196,8 +196,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
 // RUN:   --linker-path=/usr/bin/ld %t1.o %t2.o %t.a -o a.out 2>&1 | FileCheck 
%s --check-prefix=ARCH-ALL
 
-// ARCH-ALL: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx90a -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
-// ARCH-ALL: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx908.img --target=amdgcn-amd-amdhsa 
-mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// ARCH-ALL: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx90a -flto -Wl,--no-undefined {{.*}}.o 
{{.*}}.o
+// ARCH-ALL: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx908.img. 
--target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o 
{{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
@@ -207,7 +207,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK
 
-// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.x86_64..img --target=x86_64-unknown-linux-gnu
+// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.x86_64..img. 
--target=x86_64-unknown-linux-gnu
 // RELOCATABLE-LINK: /usr/bin/ld.lld{{.*}}-r
 // RELOCATABLE-LINK: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading
 
@@ -219,7 +219,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-HIP
 
-// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.amdgcn.gfx90a.img --target=amdgcn-amd-amdhsa
+// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img -dumpdir 
a.out.amdgcn.gfx90a.img. --target=amdgcn-amd-amdhsa
 // RELOCATABLE-LINK-HIP: clang-offload-bundler{{.*}} -type=o 
-bundle-align=4096 
-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx90a 
-input={{/dev/null|NUL}} -input={{.*}} -output={{.*}}
 // RELOCATABLE-LINK-HIP: /usr/bin/ld.lld{{.*}}-r
 // RELOCATABLE-LINK-HIP: llvm-objcopy{{.*}}a.out --remove-section 
.llvm.offloading
@@ -233,7 +233,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s 
--check-prefix=RELOCATABLE-LINK-CUDA
 
-// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img 
-foutput-file-base=a.out.nvptx64.sm_89.img --target=nvptx64-nvidia-cuda
+// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img -dumpdir 
a.out.nvptx64.sm_89.img. --target=nvptx64-nvidia-cuda
 // RELOCATABLE-LINK-CUDA: fatbinary{{.*}} -64 --create {{.*}}.fatbin 
--image=profile=sm_89,file={{.*}}.img
 // RELOCATABLE-LINK-CUDA: /usr/bin/ld.lld{{.*}}-r
 // RELOCATABLE-LINK-CUDA: llvm-objcopy{{.*}}a.out --remove-section 
.llvm.offloading
diff --git a/clang/test/Driver/lto-dwo.c b/clang/test/Driver/lto-dwo.c
index 206d4cba7f2a9..50727656b3289 100644
--- a/clang/test/Driver/lto-dwo.c
+++ b/clang/test/Driver/lto-dwo.c
@@ -1,9 +1,25 @@
 // Confirm that -gsplit-dwarf=DIR is passed to linker
 
-// RUN: %clang --target=x86_64-unknown-linux -### %s -flto=thin -gsplit-dwarf 
-o a.out 2> %t
+// DEFINE: %{RUN-ELF} = %clang --target=x86_64-unknown-linux -### %s \
+// DEFINE:              -flto=thin -gsplit-dwarf
+
+// RUN: %{RUN-ELF} -o a.out 2> %t
 // RUN: FileCheck -check-prefix=CHECK-LINK-ELF-DWO-DIR-DEFAULT < %t %s
 // RUN: %clang_cl --target=x86_64-unknown-windows-msvc -### -fuse-ld=lld -flto 
-gsplit-dwarf -o a.out -- %s 2> %t
 // RUN: FileCheck -check-prefix=CHECK-LINK-COFF-DWO-DIR-DEFAULT < %t %s
 //
-// CHECK-LINK-ELF-DWO-DIR-DEFAULT:  "-plugin-opt=dwo_dir=a.out_dwo"
+// CHECK-LINK-ELF-DWO-DIR-DEFAULT:  "-plugin-opt=dwo_dir=a.out-dwo"
 // CHECK-LINK-COFF-DWO-DIR-DEFAULT: "/dwodir:a.out_dwo"
+
+// Check -dumpdir effect on -gsplit-dwarf.
+//
+// DEFINE: %{RUN-DUMPDIR} = %{RUN-ELF} -dumpdir /dir/file.ext
+//
+// RUN: %{RUN-ELF} 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O
+// RUN: %{RUN-ELF} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-O
+// RUN: %{RUN-DUMPDIR} 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR
+// RUN: %{RUN-DUMPDIR} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR
+//
+//    CHECK-NO-O: "-plugin-opt=dwo_dir=a-dwo"
+//       CHECK-O: "-plugin-opt=dwo_dir=FOO-dwo"
+// CHECK-DUMPDIR: "-plugin-opt=dwo_dir=/dir/file.extdwo"
diff --git a/clang/test/Driver/opt-record.c b/clang/test/Driver/opt-record.c
index c648bf80fabeb..86d00d5612647 100644
--- a/clang/test/Driver/opt-record.c
+++ b/clang/test/Driver/opt-record.c
@@ -58,12 +58,12 @@
 // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-format=yaml"
 // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-hotness-threshold=100"
 
-// CHECK-PASS-A:      "-plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml"
+// CHECK-PASS-A:      "-plugin-opt=opt-remarks-filename=a-opt.ld.yaml"
 // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-passes=inline"
 // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-format=yaml"
 // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100"
 
-// CHECK-PASS:      "-plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml"
+// CHECK-PASS:      "-plugin-opt=opt-remarks-filename=FOO-opt.ld.yaml"
 // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-passes=inline"
 // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-format=yaml"
 // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100"
@@ -79,40 +79,16 @@
 
 // CHECK-PASS-AUTO:   "-plugin-opt=opt-remarks-hotness-threshold=auto"
 
-// Check -foutput-file-base effect on -foptimization-record-file and
-// -gsplit-dwarf.
+// Check -dumpdir effect on -foptimization-record-file.
 //
-// DEFINE: %{RUN-BASE} = \
+// DEFINE: %{RUN-DUMPDIR} = \
 // DEFINE:   %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld \
-// DEFINE:       -flto -fsave-optimization-record -gsplit-dwarf %s
+// DEFINE:       -flto -fsave-optimization-record -dumpdir /dir/file.ext %s
 //
-// RUN: %{RUN-BASE} 2>&1 | FileCheck %s -check-prefix=CHECK-BASE-NONE
+// RUN: %{RUN-DUMPDIR} 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR
+// RUN: %{RUN-DUMPDIR} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR
+// RUN: %{RUN-DUMPDIR} -foptimization-record-file=user-file.ext 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=CHECK-DUMPDIR-IGNORE
 //
-// RUN: %{RUN-BASE} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-BASE-O
-//
-// RUN: %{RUN-BASE} -foutput-file-base=/dir/file.ext 2>&1 | \
-// RUN:   FileCheck %s -check-prefix=CHECK-BASE
-//
-// RUN: %{RUN-BASE} -o FOO -foutput-file-base=/dir/file.ext 2>&1 | \
-// RUN:   FileCheck %s -check-prefix=CHECK-BASE
-//
-// There is currently no option to ignore -foutput-file-base in the case of
-// -gsplit-dwarf.
-// RUN: %{RUN-BASE} -foutput-file-base=/dir/file.ext \
-// RUN:     -foptimization-record-file=user-file.ext 2>&1 | \
-// RUN:   FileCheck %s -check-prefix=CHECK-BASE-IGNORE
-//
-//        CHECK-BASE-NONE: "-plugin-opt=dwo_dir=a.out_dwo"
-//   CHECK-BASE-NONE-SAME: "-plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml"
-//   CHECK-BASE-NONE-SAME: "-plugin-opt=opt-remarks-format=yaml"
-//
-//           CHECK-BASE-O: "-plugin-opt=dwo_dir=FOO_dwo"
-//      CHECK-BASE-O-SAME: "-plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml"
-//      CHECK-BASE-O-SAME: "-plugin-opt=opt-remarks-format=yaml"
-//
-//             CHECK-BASE: "-plugin-opt=dwo_dir=/dir/file.ext_dwo"
-//        CHECK-BASE-SAME: 
"-plugin-opt=opt-remarks-filename=/dir/file.ext.opt.ld.yaml"
-//        CHECK-BASE-SAME: "-plugin-opt=opt-remarks-format=yaml"
-//
-//      CHECK-BASE-IGNORE: 
"-plugin-opt=opt-remarks-filename=user-file.ext.opt.ld.yaml"
-// CHECK-BASE-IGNORE-SAME: "-plugin-opt=opt-remarks-format=yaml"
+//        CHECK-DUMPDIR: 
"-plugin-opt=opt-remarks-filename=/dir/file.extopt.ld.yaml"
+// CHECK-DUMPDIR-IGNORE: 
"-plugin-opt=opt-remarks-filename=user-file.ext.opt.ld.yaml"
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp 
b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 8a459efc843b4..1d91f5f255f18 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -16,7 +16,6 @@
 
 #include "clang/Basic/TargetID.h"
 #include "clang/Basic/Version.h"
-#include "clang/Driver/Options.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
@@ -487,8 +486,12 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, 
const ArgList &Args,
       "--no-default-config",
       "-o",
       *TempFileOrErr,
-      Args.MakeArgString("-foutput-file-base=" + ExecutableName +
-                         OutputFileBase + ".img"),
+      // Without -dumpdir, Clang will place auxiliary output files in the
+      // temporary directory of TempFileOrErr, where they will not easily be
+      // found by the user and might eventually be automatically removed.  Tell
+      // Clang to instead place them alongside the final executable.
+      "-dumpdir",
+      Args.MakeArgString(ExecutableName + OutputFileBase + ".img."),
       Args.MakeArgString("--target=" + Triple.getTriple()),
   };
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to