Index: clang/CMakeLists.txt =================================================================== --- clang/CMakeLists.txt +++ clang/CMakeLists.txt @@ -512,6 +512,15 @@ "Generate build targets for the Clang unit tests." ${LLVM_INCLUDE_TESTS}) +include(CMakeDependentOption) + +cmake_dependent_option(CLANG_CRASH_SAVE_TEMPS + "In addition to tar reproducer, save all temp files that go in the tar" + ON "${CMAKE_BUILD_TYPE} MATCHES Debug" OFF) +if(CLANG_CRASH_SAVE_TEMPS) + add_definitions(-DCLANG_CRASH_SAVE_TEMPS) +endif() + add_subdirectory(utils/TableGen) add_subdirectory(include) Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -109,6 +109,10 @@ - ``-Wunused-but-set-variable`` now also warns if the variable is only used by unary operators. +- Crash diagnostics are now aggregated into a single tar file instead of + being split across many temp files. Moreover, input files are written into + the output tar file as well. + Non-comprehensive list of changes in this release ------------------------------------------------- - The builtin function __builtin_dump_struct would crash clang when the target Index: clang/include/clang/Driver/Compilation.h =================================================================== --- clang/include/clang/Driver/Compilation.h +++ clang/include/clang/Driver/Compilation.h @@ -309,7 +309,7 @@ /// initCompilationForDiagnostics - Remove stale state and suppress output /// so compilation can be reexecuted to generate additional diagnostic /// information (e.g., preprocessed source(s)). - void initCompilationForDiagnostics(); + void initCompilationForDiagnostics(bool SaveTemps); /// Return true if we're compiling for diagnostics. bool isForDiagnostics() const { return ForDiagnostics; } Index: clang/lib/Driver/Compilation.cpp =================================================================== --- clang/lib/Driver/Compilation.cpp +++ clang/lib/Driver/Compilation.cpp @@ -255,7 +255,7 @@ } } -void Compilation::initCompilationForDiagnostics() { +void Compilation::initCompilationForDiagnostics(bool SaveTemps) { ForDiagnostics = true; // Free actions and jobs. @@ -295,7 +295,7 @@ Redirects = {None, {""}, {""}}; // Temporary files added by diagnostics should be kept. - ForceKeepTempFiles = true; + ForceKeepTempFiles = SaveTemps; } StringRef Compilation::getSysRoot() const { Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -90,8 +90,10 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/TarWriter.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" +#include #include #include #include @@ -1395,12 +1397,46 @@ return false; } +static std::pair, std::string> +openReproTarFile(Driver &D, Compilation &C) { + SmallString<64> TmpName; + if (Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir)) + TmpName = A->getValue(); + else + llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, TmpName); + + if (!D.getVFS().exists(TmpName)) + llvm::sys::fs::create_directories(TmpName); + + llvm::sys::path::append(TmpName, "%%%%%%.tar"); + std::error_code EC = llvm::sys::fs::createUniqueFile(TmpName, TmpName); + if (EC) { + D.Diag(clang::diag::err_unable_to_make_temp) << EC.message(); + return {}; + } + + auto TarWriterOrErr = + llvm::TarWriter::create(TmpName, llvm::sys::path::stem(TmpName)); + if (!TarWriterOrErr) { + D.Diag(clang::diag::err_unable_to_make_temp) << TmpName; + return {}; + } + + return {std::move(*TarWriterOrErr), TmpName.c_str()}; +} + // When clang crashes, produce diagnostic information including the fully // preprocessed source file(s). Request that the developer attach the // diagnostic information to a bug report. void Driver::generateCompilationDiagnostics( Compilation &C, const Command &FailingCommand, StringRef AdditionalInformation, CompilationDiagnosticReport *Report) { +#ifdef CLANG_CRASH_SAVE_TEMPS + constexpr bool SaveReproTemps = true; +#else + constexpr bool SaveReproTemps = false; +#endif + if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) return; @@ -1423,7 +1459,7 @@ DiagnosticErrorTrap Trap(Diags); // Suppress tool output. - C.initCompilationForDiagnostics(); + C.initCompilationForDiagnostics(SaveReproTemps); // Construct the list of inputs. InputList Inputs; @@ -1509,6 +1545,42 @@ return; } + std::unique_ptr TarWriter; + std::string ReproFileName; + std::tie(TarWriter, ReproFileName) = openReproTarFile(*this, C); + if (!TarWriter) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s). - cannot open tar file"; + return; + } + + std::function WriteFileToTar = + [&WriteFileToTar, &TarWriter](StringRef FSPath, std::string TarPath) { + if (llvm::sys::fs::is_directory(FSPath)) { + using llvm::sys::fs::recursive_directory_iterator; + std::error_code EC; + for (recursive_directory_iterator I{FSPath, EC}, E; I != E && !EC; + I.increment(EC)) { + // Skip over the base path of the dir. i.e., if + // WriteFileToTar("a/b/dir", "tmp/"), where dir has "c" and "d" + // "a/b/dir/c" -> "dir/", so this will be put into the tar file at + // "tmp/dir/c" and "tmp/dir/d". + std::string Path = I->path(); + Path = Path.data() + FSPath.size() + 1; + llvm::SmallString<32> Prefix{Path.begin(), Path.end()}; + llvm::sys::path::remove_filename(Prefix); + if (I->type() == llvm::sys::fs::file_type::regular_file) + WriteFileToTar(I->path(), (TarPath + Prefix + "/").str()); + } + } + auto MBOrErr = llvm::MemoryBuffer::getFile(FSPath); + if (!MBOrErr) + return; + + TarPath += llvm::sys::path::filename(FSPath); + TarWriter->append(TarPath, MBOrErr->get()->getBuffer()); + }; + Diag(clang::diag::note_drv_command_failed_diag_msg) << "\n********************\n\n" "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" @@ -1517,9 +1589,9 @@ SmallString<128> VFS; SmallString<128> ReproCrashFilename; for (const char *TempFile : TempFiles) { - Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile; - if (Report) - Report->TemporaryFiles.push_back(TempFile); + if (SaveReproTemps) + Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile; + WriteFileToTar(TempFile, "tmp/"); if (ReproCrashFilename.empty()) { ReproCrashFilename = TempFile; llvm::sys::path::replace_extension(ReproCrashFilename, ".crash"); @@ -1532,39 +1604,50 @@ } } + for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file_EQ, + options::OPT_INPUT)) + WriteFileToTar(A->getValue(), "input/"); + // Assume associated files are based off of the first temporary file. CrashReportInfo CrashInfo(TempFiles[0], VFS); - llvm::SmallString<128> Script(CrashInfo.Filename); - llvm::sys::path::replace_extension(Script, "sh"); - std::error_code EC; - llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew, - llvm::sys::fs::FA_Write, - llvm::sys::fs::OF_Text); - if (EC) { - Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Error generating run script: " << Script << " " << EC.message(); - } else { - ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" - << "# Driver args: "; - printArgList(ScriptOS, C.getInputArgs()); - ScriptOS << "# Original command: "; - Cmd.Print(ScriptOS, "\n", /*Quote=*/true); - Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); - if (!AdditionalInformation.empty()) - ScriptOS << "\n# Additional information: " << AdditionalInformation - << "\n"; - if (Report) - Report->TemporaryFiles.push_back(std::string(Script.str())); - Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; + std::string Storage; + llvm::raw_string_ostream ScriptOS{Storage}; + ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" + << "# Driver args: "; + printArgList(ScriptOS, C.getInputArgs()); + ScriptOS << "# Original command: "; + Cmd.Print(ScriptOS, "\n", /*Quote=*/true); + Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); + if (!AdditionalInformation.empty()) + ScriptOS << "\n# Additional information: " << AdditionalInformation << "\n"; + TarWriter->append("repro.sh", Storage); + + if (SaveReproTemps) { + llvm::SmallString<128> Script(CrashInfo.Filename); + llvm::sys::path::replace_extension(Script, "sh"); + std::error_code EC; + llvm::raw_fd_ostream ScriptFileOS(Script, EC, llvm::sys::fs::CD_CreateNew, + llvm::sys::fs::FA_Write, + llvm::sys::fs::OF_Text); + if (EC) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating run script: " << Script << " " << EC.message(); + } else { + ScriptFileOS << Storage; + Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; + } } + Diag(clang::diag::note_drv_command_failed_diag_msg) << ReproFileName; + if (Report) + Report->TemporaryFiles.push_back(ReproFileName); + // On darwin, provide information about the .crash diagnostic report. if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) { SmallString<128> CrashDiagDir; if (getCrashDiagnosticFile(ReproCrashFilename, CrashDiagDir)) { - Diag(clang::diag::note_drv_command_failed_diag_msg) - << ReproCrashFilename.str(); + WriteFileToTar(ReproCrashFilename.str(), ""); } else { // Suggest a directory for the user to look for .crash files. llvm::sys::path::append(CrashDiagDir, Name); CrashDiagDir += "__.crash"; @@ -1577,9 +1660,6 @@ } } - for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file_EQ)) - Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue(); - Diag(clang::diag::note_drv_command_failed_diag_msg) << "\n\n********************"; } Index: clang/test/CMakeLists.txt =================================================================== --- clang/test/CMakeLists.txt +++ clang/test/CMakeLists.txt @@ -14,6 +14,7 @@ LLVM_ENABLE_PER_TARGET_RUNTIME_DIR LLVM_ENABLE_THREADS LLVM_WITH_Z3 + CLANG_CRASH_SAVE_TEMPS ) configure_lit_site_cfg( Index: clang/test/Driver/crash-diagnostics-dir.c =================================================================== --- clang/test/Driver/crash-diagnostics-dir.c +++ clang/test/Driver/crash-diagnostics-dir.c @@ -2,4 +2,4 @@ // RUN: not %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: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c +// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.tar Index: clang/test/Driver/crash-report-clang-cl.cpp =================================================================== --- clang/test/Driver/crash-report-clang-cl.cpp +++ clang/test/Driver/crash-report-clang-cl.cpp @@ -1,16 +1,23 @@ +// UNSUPPORTED: windows + // RUN: rm -rf %t // RUN: mkdir %t // RUN: not %clang_cl -fsyntax-only /Brepro /source-charset:utf-8 \ // RUN: -fcrash-diagnostics-dir=%t -- %s 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-clang-cl-*.cpp | FileCheck --check-prefix=CHECKSRC %s -// RUN: cat %t/crash-report-clang-cl-*.sh | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-clang-cl-*.cpp" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s +// RN: cat %t/crash-report-clang-cl-*.cpp | FileCheck --check-prefix=CHECKSRC %s +// RN: cat %t/crash-report-clang-cl-*.sh | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery #pragma clang __debug crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK: note: diagnostic msg: {{.*}}.tar // __has_feature(cxx_exceptions) is default-off in the cl-compatible driver. FOO @@ -32,7 +39,6 @@ // CHECKSRC-NEXT: {{^}}int a = 0; // CHECKSRC-NEXT: {{^}}#endif -// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-clang-cl-{{.*}}.cpp // CHECKSH: # Crash reproducer // CHECKSH-NEXT: # Driver args: {{.*}}"-fsyntax-only" // CHECKSH-SAME: /Brepro Index: clang/test/Driver/crash-report-header.h =================================================================== --- clang/test/Driver/crash-report-header.h +++ clang/test/Driver/crash-report-header.h @@ -1,13 +1,15 @@ +// UNSUPPORTED: windows + // RUN: rm -rf %t // RUN: mkdir %t // RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only %s 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-header-*.h | FileCheck --check-prefix=CHECKSRC "%s" -// RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s" +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-header-*.h" | FileCheck --check-prefix=CHECKSRC "%s" +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.h +// CHECK: note: diagnostic msg: {{.*}}.tar FOO // CHECKSRC: FOO // CHECKSH: "-cc1" Index: clang/test/Driver/crash-report-modules.m =================================================================== --- clang/test/Driver/crash-report-modules.m +++ clang/test/Driver/crash-report-modules.m @@ -8,8 +8,12 @@ // RUN: not %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \ // RUN: -fmodules -fmodules-cache-path=%T/crmdir/m/ -DFOO=BAR 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %T/crmdir/crash-report-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %T/crmdir/crash-report-*.sh +// RUN: tar tf %T/crmdir/*.tar | sort | FileCheck %s --check-prefix=CHECKTAR + +// RUN: tar xOf %T/crmdir/*.tar --wildcards "*/tmp/crash-report-modules-*.m" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %T/crmdir/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery // FIXME: This test creates excessively deep directory hierarchies that cause @@ -21,8 +25,15 @@ // CHECK: PLEASE submit a bug report to {{.*}} and include the crash backtrace, preprocessed source, and associated run script. // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK: note: diagnostic msg: {{.*}}.tar + +// CHECKTAR: {{.*}}/repro.sh +// CHECKTAR-NEXT: {{.*}}/tmp/crash-report-modules-{{.*}}.m +// CHECKTAR-NEXT: {{.*}}/tmp/modules/{{.*}}/modules.idx +// CHECKTAR-NEXT: {{.*}}/tmp/modules/{{.*}}/simple-{{.*}}.pcm +// CHECKTAR-NEXT: {{.*}}/tmp/vfs/{{.*}}/module/module.modulemap +// CHECKTAR-NEXT: {{.*}}/tmp/vfs/{{.*}}/module/simple.h +// CHECKTAR-NEXT: {{.*}}/tmp/vfs/vfs.yaml // CHECKSRC: @import simple; // CHECKSRC: const int x = 10; Index: clang/test/Driver/crash-report-save-temps.c =================================================================== --- /dev/null +++ clang/test/Driver/crash-report-save-temps.c @@ -0,0 +1,14 @@ +// REQUIRES: save-crash-temps + +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: env FORCE_CLANG_DIAGNOSTICS_CRASH=1 TMPDIR=%t TEMP=%t TMP=%t \ +// RUN: not %clang -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK-NEXT: note: diagnostic msg: {{.*}}.c +// CHECK-NEXT: note: diagnostic msg: {{.*}}.sh +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar + +// RUN: false Index: clang/test/Driver/crash-report-spaces.c =================================================================== --- clang/test/Driver/crash-report-spaces.c +++ clang/test/Driver/crash-report-spaces.c @@ -1,14 +1,16 @@ +// UNSUPPORTED: windows + // RUN: rm -rf "%t" // RUN: mkdir "%t" // RUN: cp "%s" "%t/crash report spaces.c" // RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s" -// RUN: cat "%t/crash report spaces"-*.c | FileCheck --check-prefix=CHECKSRC "%s" -// RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s" +// RUN: tar xOf %t/*.tar --wildcards "*/crash report spaces-*.c" | FileCheck --check-prefix=CHECKSRC "%s" +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.c +// CHECK: note: diagnostic msg: {{.*}}.tar FOO // CHECKSRC: FOO // CHECKSH: "-cc1" Index: clang/test/Driver/crash-report-with-asserts.c =================================================================== --- clang/test/Driver/crash-report-with-asserts.c +++ clang/test/Driver/crash-report-with-asserts.c @@ -1,3 +1,5 @@ +// UNSUPPORTED: windows + // RUN: rm -rf %t // RUN: mkdir %t @@ -12,14 +14,20 @@ // RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ // RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ // RUN: not %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s -// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-*.c" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s + +// RUN: rm -f %t/*.tar // RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ // RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ // RUN: not %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-with-asserts-*.c | FileCheck --check-prefix=CHECKSRC %s -// RUN: cat %t/crash-report-with-asserts-*.sh | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-*.c" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery, asserts @@ -30,7 +38,7 @@ #endif // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-with-asserts-{{.*}}.c +// CHECK: note: diagnostic msg: {{.*}}.tar FOO // CHECKSRC: FOO // CHECKSH: # Crash reproducer Index: clang/test/Driver/crash-report.cpp =================================================================== --- clang/test/Driver/crash-report.cpp +++ clang/test/Driver/crash-report.cpp @@ -1,3 +1,5 @@ +// UNSUPPORTED: windows + // RUN: rm -rf %t // RUN: mkdir %t @@ -12,20 +14,30 @@ // RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ // RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ // RUN: not %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s -// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-*.cpp" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s + +// RUN: rm -f %t/*.tar // RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ // RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ // RUN: not %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s -// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-*.cpp" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s + +// RUN: rm -f %t/*.tar // RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ // RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ // RUN: not %clang %s @%t.rsp -DFATAL 2>&1 | FileCheck %s -// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s -// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-report-*.cpp" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery @@ -38,7 +50,7 @@ #endif // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.cpp +// CHECK: note: diagnostic msg: {{.*}}.tar // __has_feature(cxx_exceptions) is default-on in the gcc-compatible driver. FOO Index: clang/test/Driver/rewrite-map-in-diagnostics.c =================================================================== --- clang/test/Driver/rewrite-map-in-diagnostics.c +++ clang/test/Driver/rewrite-map-in-diagnostics.c @@ -1,11 +1,19 @@ +// UNSUPPORTED: windows + // RUN: rm -rf "%t" // RUN: mkdir -p "%t" // RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTION=1 \ // RUN: not %clang -fsyntax-only -frewrite-map-file=%p/Inputs/rewrite.map %s 2>&1 \ // RUN: | FileCheck %s +// RUN: tar tf %t/*.tar | sort | FileCheck --check-prefix=CHECKTAR %s #pragma clang __debug parser_crash -// CHECK: note: diagnostic msg: {{.*}}rewrite.map +// CHECK: note: diagnostic msg: {{.*}}.tar + +// CHECKTAR: {{.*}}/input/rewrite-map-in-diagnostics.c +// CHECKTAR-NEXT: {{.*}}/input/rewrite.map +// CHECKTAR-NEXT: {{.*}}/repro.sh +// CHECKTAR-NEXT: {{.*}}/tmp/rewrite-map-in-diagnostics-{{.*}}.c // REQUIRES: crash-recovery Index: clang/test/Index/create-libclang-completion-reproducer.c =================================================================== --- clang/test/Index/create-libclang-completion-reproducer.c +++ clang/test/Index/create-libclang-completion-reproducer.c @@ -10,5 +10,5 @@ // CHECK: REPRODUCER: // CHECK-NEXT: { -// CHECK-NEXT: "files":["{{.*}}.c","{{.*}}.sh"] +// CHECK-NEXT: "files":["{{.*}}.tar"] // CHECK-NEXT: } Index: clang/test/Index/create-libclang-parsing-reproducer.c =================================================================== --- clang/test/Index/create-libclang-parsing-reproducer.c +++ clang/test/Index/create-libclang-parsing-reproducer.c @@ -17,5 +17,5 @@ // CHECK: REPRODUCER: // CHECK-NEXT: { -// CHECK-NEXT: "files":["{{.*}}.c","{{.*}}.sh"] +// CHECK-NEXT: "files":["{{.*}}.tar"] // CHECK-NEXT: } Index: clang/test/Modules/crash-vfs-path-emptydir-entries.m =================================================================== --- clang/test/Modules/crash-vfs-path-emptydir-entries.m +++ clang/test/Modules/crash-vfs-path-emptydir-entries.m @@ -14,18 +14,18 @@ // RUN: not %clang -fsyntax-only %s -I %/t/i -isysroot %/t/sysroot/ \ // RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh -// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ -// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: find %t/crash-vfs-*.cache/vfs | \ -// RUN: grep "usr/include/stdio.h" | count 1 +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-vfs-*.m" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/vfs/vfs.yaml" \ +// RUN: | FileCheck --check-prefix=CHECKYAML %s +// RUN: tar tf %t/*.tar | FileCheck --check-prefix=CHECKTAR %s #include "usr/include/stdio.h" // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar // CHECKSRC: #pragma clang module import cstd.stdio @@ -47,3 +47,5 @@ // CHECKYAML-NEXT: 'name': "pthread_impl.h", // CHECKYAML-NEXT: 'external-contents': "/{{.*}}/i/usr/include/pthread_impl.h" // CHECKYAML-NEXT: }, + +// CHECKTAR: usr/include/stdio.h Index: clang/test/Modules/crash-vfs-path-symlink-component.m =================================================================== --- clang/test/Modules/crash-vfs-path-symlink-component.m +++ clang/test/Modules/crash-vfs-path-symlink-component.m @@ -15,18 +15,18 @@ // RUN: not %clang -fsyntax-only %s -I %/t/i -isysroot %/t/sysroot/ \ // RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh -// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ -// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: find %t/crash-vfs-*.cache/vfs | \ -// RUN: grep "usr/include/stdio.h" | count 1 +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-vfs-*.m" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/vfs/vfs.yaml" \ +// RUN: | FileCheck --check-prefix=CHECKYAML %s +// RUN: tar tf %t/*.tar | FileCheck --check-prefix=CHECKTAR %s #include "usr/x/../stdio.h" // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar // CHECKSRC: #pragma clang module import cstd.stdio @@ -53,6 +53,8 @@ // CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/i/usr/include/module.map" // CHECKYAML-NEXT: }, +// CHECKTAR: usr/include/stdio.h + // Test that by using the previous generated YAML file clang is able to find the // right files inside the overlay and map the virtual request for a path that // previously contained a symlink to work. To make sure of this, wipe out the Index: clang/test/Modules/crash-vfs-path-symlink-topheader.m =================================================================== --- clang/test/Modules/crash-vfs-path-symlink-topheader.m +++ clang/test/Modules/crash-vfs-path-symlink-topheader.m @@ -16,18 +16,18 @@ // RUN: not %clang -fsyntax-only %s -I %/t/i -isysroot %/t/sysroot/ \ // RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh -// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ -// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: find %t/crash-vfs-*.cache/vfs | \ -// RUN: grep "usr/include/pthread_impl.h" | count 1 +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-vfs-*.m" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/vfs/vfs.yaml" \ +// RUN: | FileCheck --check-prefix=CHECKYAML %s +// RUN: tar tf %t/*.tar | FileCheck --check-prefix=CHECKTAR %s #include "usr/include/stdio.h" // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar // CHECKSRC: #pragma clang module import cstd.stdio @@ -49,3 +49,5 @@ // CHECKYAML-NEXT: 'name': "pthread_impl.h", // CHECKYAML-NEXT: 'external-contents': "/{{.*}}/i/usr/include/pthread_impl.h" // CHECKYAML-NEXT: }, + +// CHECKTAR: usr/include/pthread_impl.h Index: clang/test/Modules/crash-vfs-path-traversal.m =================================================================== --- clang/test/Modules/crash-vfs-path-traversal.m +++ clang/test/Modules/crash-vfs-path-traversal.m @@ -13,18 +13,18 @@ // RUN: not %clang -fsyntax-only %s -I %S/Inputs/crash-recovery -isysroot %/t/i/ \ // RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh -// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ -// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: find %t/crash-vfs-*.cache/vfs | \ -// RUN: grep "Inputs/crash-recovery/usr/include/stdio.h" | count 1 +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-vfs-*.m" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/vfs/vfs.yaml" \ +// RUN: | FileCheck --check-prefix=CHECKYAML %s +// RUN: tar tf %t/*.tar | FileCheck --check-prefix=CHECKTAR %s #include "usr/././//////include/../include/./././../include/stdio.h" // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar // CHECKSRC: #pragma clang module import cstd.stdio @@ -50,6 +50,8 @@ // CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/Inputs/crash-recovery/usr/include/module.map" // CHECKYAML-NEXT: }, +// CHECKTAR: Inputs/crash-recovery/usr/include/stdio.h + // Replace the paths in the YAML files with relative ".." traversals // and fed into clang to test whether we're correctly representing them // in the VFS overlay. Index: clang/test/Modules/crash-vfs-relative-overlay.m =================================================================== --- clang/test/Modules/crash-vfs-relative-overlay.m +++ clang/test/Modules/crash-vfs-relative-overlay.m @@ -11,18 +11,18 @@ // RUN: -I %S/Inputs/crash-recovery/usr/include -isysroot %/t/i/ \ // RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh -// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ -// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: find %t/crash-vfs-*.cache/vfs | \ -// RUN: grep "Inputs/crash-recovery/usr/include/stdio.h" | count 1 +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/crash-vfs-*.m" \ +// RUN: | FileCheck --check-prefix=CHECKSRC %s +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" \ +// RUN: | FileCheck --check-prefix=CHECKSH %s +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/vfs/vfs.yaml" \ +// RUN: | FileCheck --check-prefix=CHECKYAML %s +// RUN: tar tf %t/*.tar | FileCheck --check-prefix=CHECKTAR %s #include // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar // CHECKSRC: #pragma clang module import cstd.stdio @@ -49,6 +49,8 @@ // CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/Inputs/crash-recovery/usr/include/module.map" // CHECKYAML-NEXT: }, +// CHECKTAR: Inputs/crash-recovery/usr/include/stdio.h + // Test that reading the YAML file will yield the correct path after // the overlay dir is prefixed to access headers in .cache/vfs directory. Index: clang/test/Modules/crash-vfs-umbrella-frameworks.m =================================================================== --- clang/test/Modules/crash-vfs-umbrella-frameworks.m +++ clang/test/Modules/crash-vfs-umbrella-frameworks.m @@ -14,14 +14,12 @@ // RUN: -F %/t/i/Frameworks -fmodules \ // RUN: -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ -// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: find %t/crash-vfs-*.cache/vfs | \ -// RUN: grep "B.framework/Headers/B.h" | count 1 +// RUN: tar xOf %t/*.tar --wildcards "*/tmp/vfs/vfs.yaml" \ +// RUN: | FileCheck --check-prefix=CHECKYAML %s +// RUN: tar tf %t/*.tar | FileCheck --check-prefix=CHECKTAR %s // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}.m -// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache +// CHECK-NEXT: note: diagnostic msg: {{.*}}.tar // CHECKYAML: 'type': 'directory', // CHECKYAML: 'name': "/[[PATH:.*]]/i/Frameworks/A.framework/Frameworks/B.framework/Headers", @@ -39,6 +37,8 @@ // CHECKYAML-NEXT: 'name': "B.h", // CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/i/Frameworks/B.framework/Headers/B.h" +// CHECKTAR: B.framework/Headers/B.h + @import I; // Run the reproducer script - regular exit code is enough to test it works. The @@ -51,5 +51,6 @@ // RUN: cd %t // RUN: rm -rf i // RUN: rm -rf crash-vfs-umbrella-*.cache/modules/* -// RUN: chmod 755 crash-vfs-*.sh -// RUN: ./crash-vfs-*.sh +// RUN: tar xOf %t/*.tar --wildcards "*/repro.sh" > repro.sh +// RUN: chmod 755 repro.sh +// RUN: ./repro.sh Index: clang/test/lit.cfg.py =================================================================== --- clang/test/lit.cfg.py +++ clang/test/lit.cfg.py @@ -158,6 +158,10 @@ if platform.system() not in ['Darwin', 'Fuchsia']: config.available_features.add('libgcc') +if config.save_crash_temps: + print("\n\n\n\n\nsave_crash_temps is true\n\n\n\n\n") + config.available_features.add('save-crash-temps') + # Case-insensitive file system Index: clang/test/lit.site.cfg.py.in =================================================================== --- clang/test/lit.site.cfg.py.in +++ clang/test/lit.site.cfg.py.in @@ -37,6 +37,7 @@ config.has_plugins = @CLANG_PLUGIN_SUPPORT@ config.clang_vendor_uti = "@CLANG_VENDOR_UTI@" config.llvm_external_lit = path(r"@LLVM_EXTERNAL_LIT@") +config.save_crash_temps = @CLANG_CRASH_SAVE_TEMPS@ import lit.llvm lit.llvm.initialize(lit_config, config)