https://github.com/aeubanks updated 
https://github.com/llvm/llvm-project/pull/198838

>From d1c339ba464bcc1aadf0a5972acf3091d41ca556 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <[email protected]>
Date: Wed, 20 May 2026 16:33:53 +0000
Subject: [PATCH 1/3] [clang] Add -fcrash-diagnostics-tar for tarball of crash
 reproducer files

Makes it easier to move around crash diagnostics.
---
 clang/include/clang/Options/Options.td        |  4 ++
 clang/lib/Driver/Driver.cpp                   | 64 +++++++++++++++++++
 clang/test/Driver/Inputs/empty.h              |  1 +
 clang/test/Driver/Inputs/module.modulemap     |  3 +
 clang/test/Driver/crash-diagnostics-modules.c | 17 +++++
 clang/test/Driver/crash-diagnostics-tar.c     | 17 +++++
 6 files changed, 106 insertions(+)
 create mode 100644 clang/test/Driver/Inputs/empty.h
 create mode 100644 clang/test/Driver/Inputs/module.modulemap
 create mode 100644 clang/test/Driver/crash-diagnostics-modules.c
 create mode 100644 clang/test/Driver/crash-diagnostics-tar.c

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 753e3ac1b74a5..8ee8bb544535e 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2177,6 +2177,10 @@ def fcrash_diagnostics_dir : Joined<["-"], 
"fcrash-diagnostics-dir=">,
   Group<f_clang_Group>, Flags<[NoArgumentUnused]>,
   Visibility<[ClangOption, CLOption, DXCOption]>,
   HelpText<"Put crash-report files in <dir>">, MetaVarName<"<dir>">;
+def fcrash_diagnostics_tar : Joined<["-"], "fcrash-diagnostics-tar=">,
+  Group<f_clang_Group>, Flags<[NoArgumentUnused]>,
+  Visibility<[ClangOption, CLOption, DXCOption]>,
+  HelpText<"Put crash-report tarball at <path>">, MetaVarName<"<path>">;
 def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
 defm cxx_exceptions: BoolFOption<"cxx-exceptions",
   LangOpts<"CXXExceptions">, DefaultFalse,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 4a968a4ce5cc0..42226193c3b15 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -98,12 +98,14 @@
 #include "llvm/Support/IOSandbox.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/MD5.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/StringSaver.h"
+#include "llvm/Support/TarWriter.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
@@ -2271,9 +2273,71 @@ void Driver::generateCompilationDiagnostics(
                << "\n";
     if (Report)
       Report->TemporaryFiles.push_back(std::string(Script));
+    TempFiles.push_back(std::string(Script));
+    ScriptOS.close();
     Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
   }
 
+  if (Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_tar)) {
+    StringRef CrashDiagnosticsTar = A->getValue();
+    Expected<std::unique_ptr<llvm::TarWriter>> TarOrErr =
+        llvm::TarWriter::create(CrashDiagnosticsTar,
+                                llvm::sys::path::stem(CrashDiagnosticsTar));
+    if (!TarOrErr) {
+      Diag(clang::diag::note_drv_command_failed_diag_msg)
+          << (std::string("Error creating reproducer tarball: ") +
+              llvm::toString(TarOrErr.takeError()));
+    } else {
+      std::unique_ptr<llvm::TarWriter> &Tar = *TarOrErr;
+      for (const std::string &TempFile : TempFiles) {
+        if (llvm::sys::fs::is_directory(TempFile)) {
+          std::error_code EC;
+          for (llvm::sys::fs::recursive_directory_iterator I(TempFile, EC), E;
+               I != E && !EC; I.increment(EC)) {
+            if (llvm::sys::fs::is_regular_file(I->path())) {
+              auto BufferOrErr = llvm::MemoryBuffer::getFile(I->path());
+              if (BufferOrErr) {
+                // Construct path of file relative to TempFile.
+                llvm::SmallString<128> PathInTar =
+                    llvm::sys::path::filename(TempFile);
+                StringRef SubPath = I->path();
+                if (SubPath.consume_front(TempFile)) {
+                  if (!SubPath.empty() &&
+                      llvm::sys::path::is_separator(SubPath.front())) {
+                    SubPath = SubPath.drop_front();
+                  }
+                  llvm::sys::path::append(PathInTar, SubPath);
+                  Tar->append(PathInTar, (*BufferOrErr)->getBuffer());
+                }
+              } else {
+                Diag(clang::diag::note_drv_command_failed_diag_msg)
+                    << (std::string("Error reading file for tarball: ") +
+                        I->path());
+              }
+            }
+          }
+          if (EC) {
+            Diag(clang::diag::note_drv_command_failed_diag_msg)
+                << (std::string("Error iterating directory for tarball: ") +
+                    TempFile + " " + EC.message());
+          }
+        } else {
+          auto BufferOrErr = llvm::MemoryBuffer::getFile(TempFile);
+          if (BufferOrErr) {
+            Tar->append(llvm::sys::path::filename(TempFile),
+                        (*BufferOrErr)->getBuffer());
+          } else {
+            Diag(clang::diag::note_drv_command_failed_diag_msg)
+                << (std::string("Error reading file for tarball: ") + 
TempFile);
+          }
+        }
+      }
+      Diag(clang::diag::note_drv_command_failed_diag_msg)
+          << (std::string("Crash reproducer tarball created at: ") +
+              CrashDiagnosticsTar);
+    }
+  }
+
   // On darwin, provide information about the .crash diagnostic report.
   if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) {
     SmallString<128> CrashDiagDir;
diff --git a/clang/test/Driver/Inputs/empty.h b/clang/test/Driver/Inputs/empty.h
new file mode 100644
index 0000000000000..655474edc7b65
--- /dev/null
+++ b/clang/test/Driver/Inputs/empty.h
@@ -0,0 +1 @@
+// Empty header
diff --git a/clang/test/Driver/Inputs/module.modulemap 
b/clang/test/Driver/Inputs/module.modulemap
new file mode 100644
index 0000000000000..b6edda7ff5dda
--- /dev/null
+++ b/clang/test/Driver/Inputs/module.modulemap
@@ -0,0 +1,3 @@
+module Empty {
+  header "empty.h"
+}
diff --git a/clang/test/Driver/crash-diagnostics-modules.c 
b/clang/test/Driver/crash-diagnostics-modules.c
new file mode 100644
index 0000000000000..49414f7fe2bfc
--- /dev/null
+++ b/clang/test/Driver/crash-diagnostics-modules.c
@@ -0,0 +1,17 @@
+// UNSUPPORTED: system-windows
+// RUN: export LSAN_OPTIONS=detect_leaks=0
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=%t.tar -fmodules 
-fmodules-cache-path=%t/cache -I %S/Inputs -c %s -o /dev/null 2>&1 | FileCheck 
%s
+// RUN: tar -tf %t.tar | FileCheck %s --check-prefix=TAR
+
+#include "empty.h"
+
+#pragma clang __debug parser_crash
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK: Crash reproducer tarball created at:
+
+// TAR-DAG: {{.*}}.c
+// TAR-DAG: {{.*}}.sh
+// TAR-DAG: {{.*}}.cache/{{.*}}module.modulemap
diff --git a/clang/test/Driver/crash-diagnostics-tar.c 
b/clang/test/Driver/crash-diagnostics-tar.c
new file mode 100644
index 0000000000000..4159afb75b885
--- /dev/null
+++ b/clang/test/Driver/crash-diagnostics-tar.c
@@ -0,0 +1,17 @@
+// UNSUPPORTED: system-windows
+// RUN: export LSAN_OPTIONS=detect_leaks=0
+// RUN: rm -rf %t.tar
+// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=%t.tar -c %s -o 
/dev/null 2>&1 | FileCheck %s
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: tar -xf %t.tar -C %t
+// RUN: FileCheck %s --check-prefix=SH < %t/*/crash-diagnostics-tar-*.sh
+// RUN: FileCheck %s --check-prefix=C < %t/*/crash-diagnostics-tar-*.c
+
+#pragma clang __debug parser_crash
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK: Crash reproducer tarball created at:
+
+// SH: # Crash reproducer for
+// C: # 1 "

>From de2f684b6187a70259c89d90997dec3260ab83ec Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <[email protected]>
Date: Fri, 22 May 2026 00:00:20 +0000
Subject: [PATCH 2/3] make tests work on windows

---
 clang/test/Driver/crash-diagnostics-modules.c |  9 ++++-----
 clang/test/Driver/crash-diagnostics-tar.c     | 15 +++++++--------
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/clang/test/Driver/crash-diagnostics-modules.c 
b/clang/test/Driver/crash-diagnostics-modules.c
index 49414f7fe2bfc..41d04384affa9 100644
--- a/clang/test/Driver/crash-diagnostics-modules.c
+++ b/clang/test/Driver/crash-diagnostics-modules.c
@@ -1,9 +1,8 @@
-// UNSUPPORTED: system-windows
 // RUN: export LSAN_OPTIONS=detect_leaks=0
-// RUN: rm -rf %t
-// RUN: mkdir %t
-// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=%t.tar -fmodules 
-fmodules-cache-path=%t/cache -I %S/Inputs -c %s -o /dev/null 2>&1 | FileCheck 
%s
-// RUN: tar -tf %t.tar | FileCheck %s --check-prefix=TAR
+// RUN: rm -rf %t && mkdir %t
+// RUN: cd %t
+// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=repro.tar -fmodules 
-fmodules-cache-path=cache -I %S/Inputs -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: tar -tf repro.tar | FileCheck %s --check-prefix=TAR
 
 #include "empty.h"
 
diff --git a/clang/test/Driver/crash-diagnostics-tar.c 
b/clang/test/Driver/crash-diagnostics-tar.c
index 4159afb75b885..ddc95ae5b00df 100644
--- a/clang/test/Driver/crash-diagnostics-tar.c
+++ b/clang/test/Driver/crash-diagnostics-tar.c
@@ -1,12 +1,11 @@
-// UNSUPPORTED: system-windows
 // RUN: export LSAN_OPTIONS=detect_leaks=0
-// RUN: rm -rf %t.tar
-// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=%t.tar -c %s -o 
/dev/null 2>&1 | FileCheck %s
-// RUN: rm -rf %t
-// RUN: mkdir %t
-// RUN: tar -xf %t.tar -C %t
-// RUN: FileCheck %s --check-prefix=SH < %t/*/crash-diagnostics-tar-*.sh
-// RUN: FileCheck %s --check-prefix=C < %t/*/crash-diagnostics-tar-*.c
+// RUN: rm -rf %t && mkdir %t
+// RUN: cd %t
+// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=repro.tar -c %s -o 
/dev/null 2>&1 | FileCheck %s
+// RUN: mkdir extract
+// RUN: tar -xf repro.tar -C extract
+// RUN: FileCheck %s --check-prefix=SH < extract/*/crash-diagnostics-tar-*.sh
+// RUN: FileCheck %s --check-prefix=C < extract/*/crash-diagnostics-tar-*.c
 
 #pragma clang __debug parser_crash
 

>From 9fc24501342f103d9ffd6f530804cc2082543960 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <[email protected]>
Date: Fri, 22 May 2026 22:55:25 +0000
Subject: [PATCH 3/3] Print path to tar instead when -fcrash-diagnostic-tar

---
 clang/lib/Driver/Driver.cpp                   | 21 ++++++++++---------
 clang/test/Driver/crash-diagnostics-dir-3.c   |  2 +-
 clang/test/Driver/crash-diagnostics-dir.c     |  2 +-
 clang/test/Driver/crash-diagnostics-modules.c |  4 ++--
 clang/test/Driver/crash-diagnostics-tar.c     | 15 ++++++++++---
 5 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 42226193c3b15..5aba0067fda46 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2011,10 +2011,9 @@ bool Driver::getCrashDiagnosticFile(StringRef 
ReproCrashFilename,
   return false;
 }
 
-static const char BugReporMsg[] =
+static const char BugReportMsg[] =
     "\n********************\n\n"
-    "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"
-    "Preprocessed source(s) and associated run script(s) are located at:";
+    "PLEASE ATTACH THE FOLLOWING CRASH REPRODUCER FILES TO THE BUG REPORT:";
 
 // When clang crashes, produce diagnostic information including the fully
 // preprocessed source file(s).  Request that the developer attach the
@@ -2025,6 +2024,8 @@ void Driver::generateCompilationDiagnostics(
   if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))
     return;
 
+  bool HasCrashTar = C.getArgs().hasArg(options::OPT_fcrash_diagnostics_tar);
+
   unsigned Level = 1;
   if (Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_EQ)) {
     Level = llvm::StringSwitch<unsigned>(A->getValue())
@@ -2085,7 +2086,7 @@ void Driver::generateCompilationDiagnostics(
 
     // Redirect stdout/stderr to /dev/null.
     NewLLDInvocation.Execute({std::nullopt, {""}, {""}}, nullptr, nullptr);
-    Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;
+    Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReportMsg;
     Diag(clang::diag::note_drv_command_failed_diag_msg) << TmpName;
     Diag(clang::diag::note_drv_command_failed_diag_msg)
         << "\n\n********************";
@@ -2226,12 +2227,13 @@ void Driver::generateCompilationDiagnostics(
     TempFiles.push_back(std::string(Path.begin(), Path.end()));
   }
 
-  Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;
+  Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReportMsg;
 
   SmallString<128> VFS;
   SmallString<128> ReproCrashFilename;
   for (std::string &TempFile : TempFiles) {
-    Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
+    if (!HasCrashTar)
+      Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
     if (Report)
       Report->TemporaryFiles.push_back(TempFile);
     if (ReproCrashFilename.empty()) {
@@ -2275,7 +2277,8 @@ void Driver::generateCompilationDiagnostics(
       Report->TemporaryFiles.push_back(std::string(Script));
     TempFiles.push_back(std::string(Script));
     ScriptOS.close();
-    Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
+    if (!HasCrashTar)
+      Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
   }
 
   if (Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_tar)) {
@@ -2332,9 +2335,7 @@ void Driver::generateCompilationDiagnostics(
           }
         }
       }
-      Diag(clang::diag::note_drv_command_failed_diag_msg)
-          << (std::string("Crash reproducer tarball created at: ") +
-              CrashDiagnosticsTar);
+      Diag(clang::diag::note_drv_command_failed_diag_msg) << 
CrashDiagnosticsTar;
     }
   }
 
diff --git a/clang/test/Driver/crash-diagnostics-dir-3.c 
b/clang/test/Driver/crash-diagnostics-dir-3.c
index 63a5efc853a4c..753b60ee2e2a0 100644
--- a/clang/test/Driver/crash-diagnostics-dir-3.c
+++ b/clang/test/Driver/crash-diagnostics-dir-3.c
@@ -2,5 +2,5 @@
 // RUN: rm -rf %t
 // RUN: not %crash_opt env CLANG_CRASH_DIAGNOSTICS_DIR=%t %clang -c %s -o - 
2>&1 | FileCheck %s
 #pragma clang __debug parser_crash
-// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK: PLEASE ATTACH THE FOLLOWING CRASH REPRODUCER FILES TO THE BUG REPORT:
 // CHECK: diagnostic msg: 
{{.*}}{{/|\\}}crash-diagnostics-dir-3.c.tmp{{(/|\\).*}}.c
diff --git a/clang/test/Driver/crash-diagnostics-dir.c 
b/clang/test/Driver/crash-diagnostics-dir.c
index 9a8299bffe005..8350ef70f9fef 100644
--- a/clang/test/Driver/crash-diagnostics-dir.c
+++ b/clang/test/Driver/crash-diagnostics-dir.c
@@ -2,5 +2,5 @@
 // RUN: rm -rf %t
 // RUN: not %crash_opt %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | 
FileCheck %s
 #pragma clang __debug parser_crash
-// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK: PLEASE ATTACH THE FOLLOWING CRASH REPRODUCER FILES TO THE BUG REPORT:
 // CHECK: diagnostic msg: 
{{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c
diff --git a/clang/test/Driver/crash-diagnostics-modules.c 
b/clang/test/Driver/crash-diagnostics-modules.c
index 41d04384affa9..cb9299b8e73cc 100644
--- a/clang/test/Driver/crash-diagnostics-modules.c
+++ b/clang/test/Driver/crash-diagnostics-modules.c
@@ -8,8 +8,8 @@
 
 #pragma clang __debug parser_crash
 
-// CHECK: Preprocessed source(s) and associated run script(s) are located at:
-// CHECK: Crash reproducer tarball created at:
+// CHECK: PLEASE ATTACH THE FOLLOWING CRASH REPRODUCER FILES TO THE BUG REPORT:
+// CHECK: repro.tar
 
 // TAR-DAG: {{.*}}.c
 // TAR-DAG: {{.*}}.sh
diff --git a/clang/test/Driver/crash-diagnostics-tar.c 
b/clang/test/Driver/crash-diagnostics-tar.c
index ddc95ae5b00df..a8dd28498aa30 100644
--- a/clang/test/Driver/crash-diagnostics-tar.c
+++ b/clang/test/Driver/crash-diagnostics-tar.c
@@ -1,16 +1,25 @@
 // RUN: export LSAN_OPTIONS=detect_leaks=0
 // RUN: rm -rf %t && mkdir %t
 // RUN: cd %t
-// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=repro.tar -c %s -o 
/dev/null 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -fcrash-diagnostics-tar=repro.tar -c %s -o 
/dev/null 2>&1 | FileCheck %s --check-prefix=TAR
 // RUN: mkdir extract
 // RUN: tar -xf repro.tar -C extract
 // RUN: FileCheck %s --check-prefix=SH < extract/*/crash-diagnostics-tar-*.sh
 // RUN: FileCheck %s --check-prefix=C < extract/*/crash-diagnostics-tar-*.c
 
+// RUN: not %crash_opt %clang -c %s -o /dev/null 2>&1 | FileCheck %s 
--check-prefix=NOTAR
+
 #pragma clang __debug parser_crash
 
-// CHECK: Preprocessed source(s) and associated run script(s) are located at:
-// CHECK: Crash reproducer tarball created at:
+// TAR: PLEASE ATTACH THE FOLLOWING CRASH REPRODUCER FILES TO THE BUG REPORT:
+// TAR: repro.tar
+// TAR-NOT: .c
+// TAR-NOT: .sh
+
+// NOTAR: PLEASE ATTACH THE FOLLOWING CRASH REPRODUCER FILES TO THE BUG REPORT:
+// NOTAR: .c
+// NOTAR: .sh
+// NOTAR-NOT: .tar
 
 // SH: # Crash reproducer for
 // C: # 1 "

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

Reply via email to