From c91b41a64ccce6d1097d85c8c7354ea63a5566a0 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 31 Oct 2012 18:31:33 +0000 Subject: [driver] Completely rework how superfluous options are stripped out of the crash diagnostics script. This addresses the FIXME pertaining to quoted arguments. We also delineate between those flags that have an argument (e.g., -D macro, -MF file) and those that do not (e.g., -M, -MM, -MG). Finally, we add the -dwarf-debug-flags to the list of flags to be removed. rdar://12329974 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167152 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/Compilation.cpp | 100 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) (limited to 'lib/Driver/Compilation.cpp') 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 @@ -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 . + SkipNextArg = true; + + // These flags are all of the form -Flag and are treated as two + // arguments. Therefore, we need to skip the flag and the next argument. + bool Res = llvm::StringSwitch(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(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). + if (FlagRef.startswith("-F") || FlagRef.startswith("-I")) + return true; + + return false; +} + +static bool quoteNextArg(const char *flag) { + return llvm::StringSwitch(flag) + .Case("-D", true) + .Default(false); +} + +void Compilation::PrintDiagnosticJob(raw_ostream &OS, const Job &J) const { + if (const Command *C = dyn_cast(&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(&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; -- cgit v1.2.3-70-g09d2