From: Justin Bogner Date: Thu, 9 Jul 2015 06:58:31 +0000 (+0000) Subject: Driver: Include the driver arguments in crash reports X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e76c48bf2ab5a6934fa2996cb7d735a93d602eb4;p=clang Driver: Include the driver arguments in crash reports Similarly to r231989, the driver arguments can be quite helpful in diagnosing a crash. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241786 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 8fc2e8d3a5..186244bacf 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -106,6 +106,9 @@ public: const char *getExecutable() const { return Executable; } const llvm::opt::ArgStringList &getArguments() const { return Arguments; } + + /// Print a command argument, and optionally quote it. + static void printArg(llvm::raw_ostream &OS, const char *Arg, bool Quote); }; /// Like Command, but with a fallback which is executed in case diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1914a33c0c..4edca26166 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -398,6 +398,19 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { return C; } +static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) { + llvm::opt::ArgStringList ASL; + for (const auto *A : Args) + A->render(Args, ASL); + + for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) { + if (I != ASL.begin()) + OS << ' '; + Command::printArg(OS, *I, true); + } + OS << '\n'; +} + // 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. @@ -546,7 +559,9 @@ void Driver::generateCompilationDiagnostics(Compilation &C, << "Error generating run script: " + Script + " " + EC.message(); } else { ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" - << "# Original command: "; + << "# Driver args: "; + printArgList(ScriptOS, C.getInputArgs()); + ScriptOS << "# Original command: "; Cmd.Print(ScriptOS, "\n", /*Quote=*/true); Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index ac18e1eb56..42bba56f5d 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -71,7 +71,7 @@ static int skipArgs(const char *Flag, bool HaveCrashVFS) { return 0; } -static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) { +void Command::printArg(raw_ostream &OS, const char *Arg, bool Quote) { const bool Escape = std::strpbrk(Arg, "\"\\$"); if (!Quote && !Escape) { @@ -146,7 +146,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo) const { // Always quote the exe. OS << ' '; - PrintArg(OS, Executable, /*Quote=*/true); + printArg(OS, Executable, /*Quote=*/true); llvm::ArrayRef Args = Arguments; llvm::SmallVector ArgsRespFile; @@ -175,20 +175,20 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, // Replace the input file name with the crashinfo's file name. OS << ' '; StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename); - PrintArg(OS, ShortName.str().c_str(), Quote); + printArg(OS, ShortName.str().c_str(), Quote); continue; } } OS << ' '; - PrintArg(OS, Arg, Quote); + printArg(OS, Arg, Quote); } if (CrashInfo && HaveCrashVFS) { OS << ' '; - PrintArg(OS, "-ivfsoverlay", Quote); + printArg(OS, "-ivfsoverlay", Quote); OS << ' '; - PrintArg(OS, CrashInfo->VFSPath.str().c_str(), Quote); + printArg(OS, CrashInfo->VFSPath.str().c_str(), Quote); } if (ResponseFile != nullptr) { diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m index 66ebaa750d..0e1d81a1f3 100644 --- a/test/Driver/crash-report-modules.m +++ b/test/Driver/crash-report-modules.m @@ -26,6 +26,8 @@ const int x = MODULE_MACRO; // CHECKSRC: const int x = 10; // CHECKSH: # Crash reproducer +// CHECKSH-NEXT: # Driver args: "-fsyntax-only" +// CHECKSH-SAME: "-D" "FOO=BAR" // CHECKSH-NEXT: # Original command: {{.*$}} // CHECKSH-NEXT: "-cc1" // CHECKSH: "-isysroot" "/tmp/" diff --git a/test/Driver/crash-report.c b/test/Driver/crash-report.c index 5caad79f19..2ff5b44f5e 100644 --- a/test/Driver/crash-report.c +++ b/test/Driver/crash-report.c @@ -5,7 +5,7 @@ // RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \ // RUN: -Xclang -internal-isystem -Xclang /tmp/ \ // RUN: -Xclang -internal-externc-isystem -Xclang /tmp/ \ -// RUN: -DFOO=BAR 2>&1 | FileCheck %s +// RUN: -DFOO=BAR -DBAR="BAZ QUX" 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 // REQUIRES: crash-recovery @@ -19,10 +19,14 @@ FOO // CHECKSRC: FOO // CHECKSH: # Crash reproducer +// CHECKSH-NEXT: # Driver args: "-fsyntax-only" +// CHECKSH-SAME: "-D" "FOO=BAR" +// CHECKSH-SAME: "-D" "BAR=BAZ QUX" // CHECKSH-NEXT: # Original command: {{.*$}} // CHECKSH-NEXT: "-cc1" // CHECKSH: "-main-file-name" "crash-report.c" // CHECKSH: "-D" "FOO=BAR" +// CHECKSH: "-D" "BAR=BAZ QUX" // CHECKSH-NOT: "-F/tmp/" // CHECKSH-NOT: "-I" "/tmp/" // CHECKSH-NOT: "-idirafter" "/tmp/"