diff options
Diffstat (limited to 'lib/Driver')
-rw-r--r-- | lib/Driver/Compilation.cpp | 100 | ||||
-rw-r--r-- | lib/Driver/Driver.cpp | 55 |
2 files changed, 102 insertions, 53 deletions
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index c962fca0bf..e804a54383 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -17,6 +17,7 @@ #include "clang/Driver/ToolChain.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Program.h" #include <sys/stat.h> @@ -101,6 +102,105 @@ void Compilation::PrintJob(raw_ostream &OS, const Job &J, } } +static bool skipArg(const char *Flag, bool &SkipNextArg) { + StringRef FlagRef(Flag); + + // Assume we're going to see -Flag <Arg>. + SkipNextArg = true; + + // These flags are all of the form -Flag <Arg> and are treated as two + // arguments. Therefore, we need to skip the flag and the next argument. + bool Res = llvm::StringSwitch<bool>(Flag) + .Cases("-I", "-MF", "-MT", "-MQ", true) + .Cases("-o", "-coverage-file", "-dependency-file", true) + .Cases("-fdebug-compilation-dir", "-fmodule-cache-path", "-idirafter", true) + .Cases("-include", "-include-pch", "-internal-isystem", true) + .Cases("-internal-externc-isystem ", "-iprefix ", "-iwithprefix", true) + .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true) + .Cases("-resource-dir", "-serialize-diagnostic-file", true) + .Case("-dwarf-debug-flags", true) + .Default(false); + + // Match found. + if (Res) + return Res; + + // The remaining flags are treated as a single argument. + SkipNextArg = false; + + // These flags are all of the form -Flag and have no second argument. + Res = llvm::StringSwitch<bool>(Flag) + .Cases("-M", "-MM", "-MG", "-MP", "-MD", true) + .Case("-MMD", true) + .Default(false); + + // Match found. + if (Res) + return Res; + + // These flags are treated as a single argument (e.g., -F<Dir>). + if (FlagRef.startswith("-F") || FlagRef.startswith("-I")) + return true; + + return false; +} + +static bool quoteNextArg(const char *flag) { + return llvm::StringSwitch<bool>(flag) + .Case("-D", true) + .Default(false); +} + +void Compilation::PrintDiagnosticJob(raw_ostream &OS, const Job &J) const { + if (const Command *C = dyn_cast<Command>(&J)) { + OS << C->getExecutable(); + unsigned QuoteNextArg = 0; + for (ArgStringList::const_iterator it = C->getArguments().begin(), + ie = C->getArguments().end(); it != ie; ++it) { + + bool SkipNext; + if (skipArg(*it, SkipNext)) { + if (SkipNext) ++it; + continue; + } + + if (!QuoteNextArg) + QuoteNextArg = quoteNextArg(*it) ? 2 : 0; + + OS << ' '; + + if (QuoteNextArg == 1) + OS << '"'; + + if (!std::strpbrk(*it, " \"\\$")) { + OS << *it; + } else { + // Quote the argument and escape shell special characters; this isn't + // really complete but is good enough. + OS << '"'; + for (const char *s = *it; *s; ++s) { + if (*s == '"' || *s == '\\' || *s == '$') + OS << '\\'; + OS << *s; + } + OS << '"'; + } + + if (QuoteNextArg) { + if (QuoteNextArg == 1) + OS << '"'; + --QuoteNextArg; + } + } + OS << '\n'; + } else { + const JobList *Jobs = cast<JobList>(&J); + for (JobList::const_iterator + it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it) + PrintDiagnosticJob(OS, **it); + } +} + bool Compilation::CleanupFileList(const ArgStringList &Files, bool IssueErrors) const { bool Success = true; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 5c20c23e56..ac1e112f71 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -362,11 +362,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C, std::string Cmd; llvm::raw_string_ostream OS(Cmd); if (FailingCommand) - C.PrintJob(OS, *FailingCommand, "\n", false); + C.PrintDiagnosticJob(OS, *FailingCommand); else // Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an // associated FailingCommand, so just pass all jobs. - C.PrintJob(OS, C.getJobs(), "\n", false); + C.PrintDiagnosticJob(OS, C.getJobs()); OS.flush(); // Clear stale state and suppress tool output. @@ -464,57 +464,6 @@ void Driver::generateCompilationDiagnostics(Compilation &C, Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + Err; } else { - // Strip away options not necessary to reproduce the crash. - // FIXME: This doesn't work with quotes (e.g., -D "foo bar"). - SmallVector<std::string, 16> Flag; - Flag.push_back("-D "); - Flag.push_back("-F"); - Flag.push_back("-I "); - Flag.push_back("-M "); - Flag.push_back("-MD "); - Flag.push_back("-MF "); - Flag.push_back("-MG "); - Flag.push_back("-MM "); - Flag.push_back("-MMD "); - Flag.push_back("-MP "); - Flag.push_back("-MQ "); - Flag.push_back("-MT "); - Flag.push_back("-o "); - Flag.push_back("-coverage-file "); - Flag.push_back("-dependency-file "); - Flag.push_back("-fdebug-compilation-dir "); - Flag.push_back("-fmodule-cache-path "); - Flag.push_back("-idirafter "); - Flag.push_back("-include "); - Flag.push_back("-include-pch "); - Flag.push_back("-internal-isystem "); - Flag.push_back("-internal-externc-isystem "); - Flag.push_back("-iprefix "); - Flag.push_back("-iwithprefix "); - Flag.push_back("-iwithprefixbefore "); - Flag.push_back("-isysroot "); - Flag.push_back("-isystem "); - Flag.push_back("-iquote "); - Flag.push_back("-resource-dir "); - Flag.push_back("-serialize-diagnostic-file "); - for (unsigned i = 0, e = Flag.size(); i < e; ++i) { - size_t I = 0, E = 0; - do { - I = Cmd.find(Flag[i], I); - if (I == std::string::npos) break; - - E = Cmd.find(" ", I + Flag[i].length()); - if (E == std::string::npos) break; - // The -D option is not removed. Instead, the argument is quoted. - if (Flag[i] != "-D ") { - Cmd.erase(I, E - I + 1); - } else { - Cmd.insert(I+3, "\""); - Cmd.insert(++E, "\""); - I = E; - } - } while(1); - } // Append the new filename with correct preprocessed suffix. size_t I, E; I = Cmd.find("-main-file-name "); |