[clang] 6fb5541 - [clang][Driver] Don't let -save-temps overwrite the input file (#235413)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 21:02:40 PDT 2026
Author: Bill Wendling
Date: 2026-10-26T04:02:35Z
New Revision: 6fb55419d135ecbf7f664c6c8d0cc103533bffdf
URL: https://github.com/llvm/llvm-project/commit/6fb55419d135ecbf7f664c6c8d0cc103533bffdf
DIFF: https://github.com/llvm/llvm-project/commit/6fb55419d135ecbf7f664c6c8d0cc103533bffdf.diff
LOG: [clang][Driver] Don't let -save-temps overwrite the input file (#235413)
With -save-temps, an intermediate file named after the input can be the
input itself, e.g. the preprocessed output of a .s file on Darwin. The
driver catches this, but only checked for it when the output's name was
the input's file name. It missed two cases, and overwrote the input with
the preprocessed output:
- With -save-temps=obj, the output is in the output's directory, so
"clang -c -save-temps=obj sub/t.s -o sub/t.o" wrote "sub/t.s".
- On a case-insensitive file system, such as macOS's default, the
preprocessed output "t.s" of an input "t.S" is the same file.
Check whether the output is the same file as the input whenever temps
are saved.
Fixes #7002.
Added:
clang/test/Driver/save-temps-input-overwrite-case-insensitive.c
clang/test/Driver/save-temps-input-overwrite.c
Modified:
clang/lib/Driver/Driver.cpp
Removed:
################################################################################
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 955443bc142ed..e43bd6b1049b8 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -5856,15 +5856,14 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
NamedOutput = C.getArgs().MakeArgString(TempPath.c_str());
}
- // If we're saving temps and the temp file conflicts with the input file,
- // then avoid overwriting input file.
- if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) {
+ // If we're saving temps and the temp file is the input file, then avoid
+ // overwriting the input file. Compare the files, not their names: the output
+ // can name the input by another path (e.g. "sub/t.s" from -save-temps=obj),
+ // or with
diff erent case on a case-insensitive file system ("t.s" for an
+ // input "t.S").
+ if (!AtTopLevel && isSaveTempsEnabled()) {
bool SameFile = false;
- SmallString<256> Result;
- llvm::sys::fs::current_path(Result);
- llvm::sys::path::append(Result, BaseName);
- llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile);
- // Must share the same path to conflict.
+ llvm::sys::fs::equivalent(BaseInput, NamedOutput, SameFile);
if (SameFile) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
diff --git a/clang/test/Driver/save-temps-input-overwrite-case-insensitive.c b/clang/test/Driver/save-temps-input-overwrite-case-insensitive.c
new file mode 100644
index 0000000000000..751ed2cd81c58
--- /dev/null
+++ b/clang/test/Driver/save-temps-input-overwrite-case-insensitive.c
@@ -0,0 +1,11 @@
+// Check that -save-temps doesn't overwrite a .S input with its preprocessed
+// output, whose name ends in .s, on a case-insensitive file system.
+
+// REQUIRES: case-insensitive-filesystem
+
+// RUN: rm -rf %t && mkdir -p %t && touch %t/t.S
+// RUN: cd %t && %clang --target=x86_64-linux-gnu -c -save-temps t.S -### 2>&1 \
+// RUN: | FileCheck %s
+// CHECK: "-E"
+// CHECK-NOT: "-o" "t.s"
+// CHECK-SAME: "-o" "{{[^"]*}}t-{{[^"]*}}.s"
diff --git a/clang/test/Driver/save-temps-input-overwrite.c b/clang/test/Driver/save-temps-input-overwrite.c
new file mode 100644
index 0000000000000..2a8da5fc0c87c
--- /dev/null
+++ b/clang/test/Driver/save-temps-input-overwrite.c
@@ -0,0 +1,23 @@
+// Check that -save-temps doesn't name an intermediate file after the input
+// file, which would overwrite it. On Darwin, a .s file is preprocessed, and
+// the preprocessed output's name ends in .s.
+
+// RUN: rm -rf %t && mkdir -p %t/sub %t/obj && cd %t
+// RUN: touch t.s sub/t.s
+
+// The output would be the input in the current directory.
+// RUN: %clang --target=x86_64-apple-darwin -c -save-temps t.s -### 2>&1 | FileCheck %s --check-prefix=CWD
+// CWD: "-E"
+// CWD-NOT: "-o" "t.s"
+// CWD-SAME: "-o" "{{[^"]*}}t-{{[^"]*}}.s"
+
+// With -save-temps=obj, the output would be the input in the output directory.
+// RUN: %clang --target=x86_64-apple-darwin -c -save-temps=obj sub/t.s -o sub/t.o -### 2>&1 | FileCheck %s --check-prefix=OBJ
+// OBJ: "-E"
+// OBJ-NOT: "-o" "sub{{/|\\\\}}t.s"
+// OBJ-SAME: "-o" "{{[^"]*}}t-{{[^"]*}}.s"
+
+// An output with the input's name in another directory is a
diff erent file.
+// RUN: cd obj && %clang --target=x86_64-apple-darwin -c -save-temps ../t.s -o t.o -### 2>&1 | FileCheck %s --check-prefix=OTHER-DIR
+// OTHER-DIR: "-E"
+// OTHER-DIR-SAME: "-o" "t.s"
More information about the cfe-commits
mailing list