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
