diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1527,6 +1527,11 @@ return false; } +static const char BugReporMsg[] = + "\n********************\n\n" + "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" + "Preprocessed source(s) and associated run script(s) are located at:"; + // 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. @@ -1582,6 +1587,29 @@ // Suppress tool output. C.initCompilationForDiagnostics(); + // If lld failed, rerun it again with --reproduce. + if (IsLLD) { + const char *TmpName = CreateTempFile(C, "linker-crash", "tar"); + Command NewLLDInvocation = Cmd; + llvm::opt::ArgStringList ArgList = NewLLDInvocation.getArguments(); + StringRef ReproduceOption = + C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() + ? "/reproduce:" + : "--reproduce="; + ArgList.push_back(Saver.save(Twine(ReproduceOption) + TmpName).data()); + NewLLDInvocation.replaceArguments(std::move(ArgList)); + + // Redirect stdout/stderr to /dev/null. + NewLLDInvocation.Execute({None, {""}, {""}}, nullptr, nullptr); + Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg; + Diag(clang::diag::note_drv_command_failed_diag_msg) << TmpName; + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "\n\n********************"; + if (Report) + Report->TemporaryFiles.push_back(TmpName); + return; + } + // Construct the list of inputs. InputList Inputs; BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs); @@ -1659,22 +1687,6 @@ return; } - // If lld failed, rerun it again with --reproduce. - if (IsLLD) { - const char *TmpName = CreateTempFile(C, "linker-crash", "tar"); - Command NewLLDInvocation = Cmd; - llvm::opt::ArgStringList ArgList = NewLLDInvocation.getArguments(); - StringRef ReproduceOption = - C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() - ? "/reproduce:" - : "--reproduce="; - ArgList.push_back(Saver.save(Twine(ReproduceOption) + TmpName).data()); - NewLLDInvocation.replaceArguments(std::move(ArgList)); - - // Redirect stdout/stderr to /dev/null. - NewLLDInvocation.Execute({None, {""}, {""}}, nullptr, nullptr); - } - const ArgStringList &TempFiles = C.getTempFiles(); if (TempFiles.empty()) { Diag(clang::diag::note_drv_command_failed_diag_msg) @@ -1682,10 +1694,7 @@ return; } - Diag(clang::diag::note_drv_command_failed_diag_msg) - << "\n********************\n\n" - "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" - "Preprocessed source(s) and associated run script(s) are located at:"; + Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg; SmallString<128> VFS; SmallString<128> ReproCrashFilename; diff --git a/clang/test/Driver/lld-repro.c b/clang/test/Driver/lld-repro.c --- a/clang/test/Driver/lld-repro.c +++ b/clang/test/Driver/lld-repro.c @@ -1,22 +1,28 @@ // REQUIRES: lld // UNSUPPORTED: ps4, ps5 -// RUN: not %clang %s -nostartfiles -nostdlib -fuse-ld=lld -gen-reproducer=error -fcrash-diagnostics-dir=%t -fcrash-diagnostics=all 2>&1 \ +// RUN: echo "-nostartfiles -nostdlib -fuse-ld=lld -gen-reproducer=error -fcrash-diagnostics-dir=%t" \ +// RUN: | sed -e 's/\\/\\\\/g' > %t.rsp + +// RUN: not %clang %s @%t.rsp -fcrash-diagnostics=all 2>&1 \ +// RUN: | FileCheck %s + +// Test that the reproducer can still be created even when the input source cannot be preprocessed +// again, like when reading from stdin. +// RUN: not %clang -x c - @%t.rsp -fcrash-diagnostics=all 2>&1 < %s \ // RUN: | FileCheck %s // check that we still get lld's output // CHECK: error: undefined symbol: {{_?}}a // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK-NEXT: note: diagnostic msg: {{.*}}lld-repro-{{.*}}.c // CHECK-NEXT: note: diagnostic msg: {{.*}}linker-crash-{{.*}}.tar -// CHECK-NEXT: note: diagnostic msg: {{.*}}lld-repro-{{.*}}.sh // CHECK-NEXT: note: diagnostic msg: // CHECK: ******************** -// RUN: not %clang %s -nostartfiles -nostdlib -fuse-ld=lld -gen-reproducer=error -fcrash-diagnostics-dir=%t -fcrash-diagnostics=compiler 2>&1 \ +// RUN: not %clang %s @%t.rsp -fcrash-diagnostics=compiler 2>&1 \ // RUN: | FileCheck %s --check-prefix=NO-LINKER -// RUN: not %clang %s -nostartfiles -nostdlib -fuse-ld=lld -gen-reproducer=error -fcrash-diagnostics-dir=%t 2>&1 \ +// RUN: not %clang %s @%t.rsp 2>&1 \ // RUN: | FileCheck %s --check-prefix=NO-LINKER // NO-LINKER-NOT: Preprocessed source(s) and associated run script(s) are located at: