https://github.com/isanbard updated 
https://github.com/llvm/llvm-project/pull/235413

>From 1884a3b4ff013c982924620faa8799222ed4c72e Mon Sep 17 00:00:00 2001
From: Bill Wendling <[email protected]>
Date: Sun, 25 Oct 2026 00:29:30 -0700
Subject: [PATCH 1/2] [clang][Driver] Don't let -save-temps overwrite the input
 file

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.

Assisted-by: Claude Opus 5.5
---
 clang/lib/Driver/Driver.cpp                   | 15 +++++------
 ...e-temps-input-overwrite-case-insensitive.c | 11 ++++++++
 .../test/Driver/save-temps-input-overwrite.c  | 26 +++++++++++++++++++
 3 files changed, 44 insertions(+), 8 deletions(-)
 create mode 100644 
clang/test/Driver/save-temps-input-overwrite-case-insensitive.c
 create mode 100644 clang/test/Driver/save-temps-input-overwrite.c

diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 707d6847caf446..1c693e792b9da5 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -5857,15 +5857,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 different 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 00000000000000..751ed2cd81c58f
--- /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 00000000000000..3d0739265ad47e
--- /dev/null
+++ b/clang/test/Driver/save-temps-input-overwrite.c
@@ -0,0 +1,26 @@
+// 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
+// RUN: touch %t/t.s %t/sub/t.s
+
+// The output would be the input in the current directory.
+// RUN: cd %t && %clang --target=x86_64-apple-darwin -c -save-temps t.s -### 
2>&1 \
+// RUN:   | 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: cd %t && %clang --target=x86_64-apple-darwin -c -save-temps=obj 
sub/t.s -o sub/t.o -### 2>&1 \
+// RUN:   | 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 different file.
+// RUN: cd %t/obj && %clang --target=x86_64-apple-darwin -c -save-temps ../t.s 
-o t.o -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=OTHER-DIR
+// OTHER-DIR: "-E"
+// OTHER-DIR-SAME: "-o" "t.s"

>From 01e0b64d9e080a2973a04d54db743cab7a8404ca Mon Sep 17 00:00:00 2001
From: Bill Wendling <[email protected]>
Date: Sun, 25 Oct 2026 19:24:59 -0700
Subject: [PATCH 2/2] Do the `cd` once so we don't have to use the dir prefix

---
 clang/test/Driver/save-temps-input-overwrite.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/clang/test/Driver/save-temps-input-overwrite.c 
b/clang/test/Driver/save-temps-input-overwrite.c
index 3d0739265ad47e..2a8da5fc0c87c7 100644
--- a/clang/test/Driver/save-temps-input-overwrite.c
+++ b/clang/test/Driver/save-temps-input-overwrite.c
@@ -2,25 +2,22 @@
 // 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
-// RUN: touch %t/t.s %t/sub/t.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: cd %t && %clang --target=x86_64-apple-darwin -c -save-temps t.s -### 
2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CWD
+// 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: cd %t && %clang --target=x86_64-apple-darwin -c -save-temps=obj 
sub/t.s -o sub/t.o -### 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=OBJ
+// 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 different file.
-// RUN: cd %t/obj && %clang --target=x86_64-apple-darwin -c -save-temps ../t.s 
-o t.o -### 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=OTHER-DIR
+// 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"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to