From: Justin Bogner Date: Tue, 21 Oct 2014 17:24:44 +0000 (+0000) Subject: Driver: Move crash report command mangling into Command::Print X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=616830b9ae86876d60e4e408f46f2cf6bb4b98b5;p=clang Driver: Move crash report command mangling into Command::Print This pushes the logic for generating a crash reproduction script entirely into Command::Print, instead of Command doing half of the work and then relying on textual substitution for the rest. This makes this logic much easier to read and will simplify fixing a couple of issues in this area. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220305 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 2695f9eadb..685088d24a 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -29,6 +29,14 @@ class Tool; // Re-export this as clang::driver::ArgStringList. using llvm::opt::ArgStringList; +struct CrashReportInfo { + StringRef Filename; + StringRef VFSPath; + + CrashReportInfo(StringRef Filename, StringRef VFSPath) + : Filename(Filename), VFSPath(VFSPath) {} +}; + class Job { public: enum JobClass { @@ -52,9 +60,9 @@ public: /// \param OS - The stream to print on. /// \param Terminator - A string to print at the end of the line. /// \param Quote - Should separate arguments be quoted. - /// \param CrashReport - Whether to print for inclusion in a crash report. - virtual void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const = 0; + /// \param CrashInfo - Details for inclusion in a crash report. + virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, + CrashReportInfo *CrashInfo = nullptr) const = 0; }; /// Command - An executable path/name and argument vector to @@ -102,7 +110,7 @@ public: const llvm::opt::ArgStringList &_Arguments); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport = false) const override; + CrashReportInfo *CrashInfo = nullptr) const override; virtual int Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const; @@ -141,7 +149,7 @@ public: std::unique_ptr Fallback_); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport = false) const override; + CrashReportInfo *CrashInfo = nullptr) const override; int Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const override; @@ -170,7 +178,7 @@ public: virtual ~JobList() {} void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const override; + bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; /// Add a job to the list (taking ownership). void addJob(std::unique_ptr J) { Jobs.push_back(std::move(J)); } diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 2e9fcfe0ef..baf154fbc5 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -424,10 +424,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, CCGenDiagnostics = true; // Save the original job command(s). - std::string Cmd; - llvm::raw_string_ostream OS(Cmd); - FailingCommand.Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true); - OS.flush(); + Command Cmd = FailingCommand; // Keep track of whether we produce any errors while trying to produce // preprocessed sources. @@ -541,36 +538,16 @@ void Driver::generateCompilationDiagnostics(Compilation &C, } // Assume associated files are based off of the first temporary file. - const char *MainFile = TempFiles[0]; + CrashReportInfo CrashInfo(TempFiles[0], VFS); - std::string Script = StringRef(MainFile).rsplit('.').first.str() + ".sh"; + std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh"; std::error_code EC; llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::F_Excl); if (EC) { Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + EC.message(); } else { - // Replace the original filename with the preprocessed one. - size_t I, E; - I = Cmd.find("-main-file-name "); - assert(I != std::string::npos && "Expected to find -main-file-name"); - I += 16; - E = Cmd.find(" ", I); - assert(E != std::string::npos && "-main-file-name missing argument?"); - StringRef OldFilename = StringRef(Cmd).slice(I, E); - StringRef NewFilename = llvm::sys::path::filename(MainFile); - I = StringRef(Cmd).rfind(OldFilename); - E = I + OldFilename.size(); - if (E + 1 < Cmd.size() && Cmd[E] == '"') - ++E; // Replace a trailing quote if present. - I = Cmd.rfind(" ", I) + 1; - Cmd.replace(I, E - I, NewFilename.data(), NewFilename.size()); - if (!VFS.empty()) { - // Add the VFS overlay to the reproduction script. - I += NewFilename.size(); - Cmd.insert(I, std::string(" -ivfsoverlay ") + VFS.c_str()); - } - ScriptOS << Cmd; + Cmd.Print(ScriptOS, "\n", /*Quote=*/false, &CrashInfo); Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; } Diag(clang::diag::note_drv_command_failed_diag_msg) diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index c13b56e1be..34d38b904c 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -151,7 +151,7 @@ void Command::buildArgvForResponseFile( } void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport) const { + CrashReportInfo *CrashInfo) const { // Always quote the exe. OS << ' '; PrintArg(OS, Executable, /*Quote=*/true); @@ -163,25 +163,46 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, Args = ArrayRef(ArgsRespFile).slice(1); // no executable name } + StringRef MainFilename; + // We'll need the argument to -main-file-name to find the input file name. + if (CrashInfo) + for (size_t I = 0, E = Args.size(); I + 1 < E; ++I) + if (StringRef(Args[I]).equals("-main-file-name")) + MainFilename = Args[I + 1]; + for (size_t i = 0, e = Args.size(); i < e; ++i) { const char *const Arg = Args[i]; - if (CrashReport) { + if (CrashInfo) { if (int Skip = skipArgs(Arg)) { i += Skip - 1; continue; + } else if (llvm::sys::path::filename(Arg) == MainFilename && + (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) { + // 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); + continue; } } OS << ' '; PrintArg(OS, Arg, Quote); - if (CrashReport && quoteNextArg(Arg) && i + 1 < e) { + if (CrashInfo && quoteNextArg(Arg) && i + 1 < e) { OS << ' '; PrintArg(OS, Args[++i], true); } } + if (CrashInfo && !CrashInfo->VFSPath.empty()) { + OS << ' '; + PrintArg(OS, "-ivfsoverlay", Quote); + OS << ' '; + PrintArg(OS, CrashInfo->VFSPath.str().c_str(), Quote); + } + if (ResponseFile != nullptr) { OS << "\n Arguments passed via response file:\n"; writeResponseFile(OS); @@ -251,10 +272,10 @@ FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_, Fallback(std::move(Fallback_)) {} void FallbackCommand::Print(raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport) const { - Command::Print(OS, "", Quote, CrashReport); + bool Quote, CrashReportInfo *CrashInfo) const { + Command::Print(OS, "", Quote, CrashInfo); OS << " ||"; - Fallback->Print(OS, Terminator, Quote, CrashReport); + Fallback->Print(OS, Terminator, Quote, CrashInfo); } static bool ShouldFallback(int ExitCode) { @@ -286,9 +307,9 @@ int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg, JobList::JobList() : Job(JobListClass) {} void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport) const { + CrashReportInfo *CrashInfo) const { for (const auto &Job : *this) - Job.Print(OS, Terminator, Quote, CrashReport); + Job.Print(OS, Terminator, Quote, CrashInfo); } void JobList::clear() { Jobs.clear(); }