diff options
| author | Chad Rosier <mcrosier@apple.com> | 2011-07-20 20:26:32 +0000 |
|---|---|---|
| committer | Chad Rosier <mcrosier@apple.com> | 2011-07-20 20:26:32 +0000 |
| commit | e3805fc118216cb467a03d6890eb1fb9b06a8628 (patch) | |
| tree | 475cf801adf24e293a0e0f2f93da3c882a3361bf /clang/lib | |
| parent | e6f7f914db4ae4ca75a30fc2064cafe0c46fcf67 (diff) | |
| download | bcm5719-llvm-e3805fc118216cb467a03d6890eb1fb9b06a8628.tar.gz bcm5719-llvm-e3805fc118216cb467a03d6890eb1fb9b06a8628.zip | |
When the compiler crashes, the compiler driver now produces diagnostic information
including the fully preprocessed source file(s) and command line arguments. The
developer is asked to attach this diagnostic information to a bug report.
llvm-svn: 135614
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Driver/ArgList.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Driver/Compilation.cpp | 39 | ||||
| -rw-r--r-- | clang/lib/Driver/Driver.cpp | 74 | ||||
| -rw-r--r-- | clang/lib/Driver/Job.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Driver/Tools.cpp | 4 |
5 files changed, 124 insertions, 15 deletions
diff --git a/clang/lib/Driver/ArgList.cpp b/clang/lib/Driver/ArgList.cpp index b8af9cc47e0..30225fccb57 100644 --- a/clang/lib/Driver/ArgList.cpp +++ b/clang/lib/Driver/ArgList.cpp @@ -46,6 +46,16 @@ void ArgList::append(Arg *A) { Args.push_back(A); } +void ArgList::eraseArg(OptSpecifier Id) { + for (iterator it = begin(), ie = end(); it != ie; ++it) { + if ((*it)->getOption().matches(Id)) { + Args.erase(it); + it = begin(); + ie = end(); + } + } +} + Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { // FIXME: Make search efficient? for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) @@ -192,6 +202,12 @@ void ArgList::ClaimAllArgs(OptSpecifier Id0) const { (*it)->claim(); } +void ArgList::ClaimAllArgs() const { + for (const_iterator it = begin(), ie = end(); it != ie; ++it) + if (!(*it)->isClaimed()) + (*it)->claim(); +} + const char *ArgList::MakeArgString(const llvm::Twine &T) const { llvm::SmallString<256> Str; T.toVector(Str); diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index 2657faa0d3a..b0e46ff5aee 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -25,7 +25,7 @@ using namespace clang::driver; Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain, InputArgList *_Args, DerivedArgList *_TranslatedArgs) : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args), - TranslatedArgs(_TranslatedArgs) { + TranslatedArgs(_TranslatedArgs), Redirects(0) { } Compilation::~Compilation() { @@ -43,6 +43,13 @@ Compilation::~Compilation() { for (ActionList::iterator it = Actions.begin(), ie = Actions.end(); it != ie; ++it) delete *it; + + // Free redirections of stdout/stderr. + if (Redirects) { + delete Redirects[1]; + delete Redirects[2]; + delete Redirects; + } } const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC, @@ -135,8 +142,8 @@ int Compilation::ExecuteCommand(const Command &C, std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1); Argv[C.getArguments().size() + 1] = 0; - if (getDriver().CCCEcho || getDriver().CCPrintOptions || - getArgs().hasArg(options::OPT_v)) { + if ((getDriver().CCCEcho || getDriver().CCPrintOptions || + getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) { llvm::raw_ostream *OS = &llvm::errs(); // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the @@ -167,7 +174,7 @@ int Compilation::ExecuteCommand(const Command &C, std::string Error; int Res = llvm::sys::Program::ExecuteAndWait(Prog, Argv, - /*env*/0, /*redirects*/0, + /*env*/0, Redirects, /*secondsToWait*/0, /*memoryLimit*/0, &Error); if (!Error.empty()) { @@ -195,3 +202,27 @@ int Compilation::ExecuteJob(const Job &J, return 0; } } + +void Compilation::initCompilationForDiagnostics(void) { + // Free actions and jobs, if built. + for (ActionList::iterator it = Actions.begin(), ie = Actions.end(); + it != ie; ++it) + delete *it; + Actions.clear(); + Jobs.clear(); + + // Clear temporary and results file lists. + TempFiles.clear(); + ResultFiles.clear(); + + // Remove any user specified output. Claim any unclaimed arguments, so as + // to avoid emitting warnings about unused args. + if (TranslatedArgs->hasArg(options::OPT_o)) + TranslatedArgs->eraseArg(options::OPT_o); + TranslatedArgs->ClaimAllArgs(); + + // Redirect stdout/stderr to /dev/null. + Redirects = new const llvm::sys::Path*[3](); + Redirects[1] = new const llvm::sys::Path(); + Redirects[2] = new const llvm::sys::Path(); +} diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 789f6f7ae9c..b01e8fca1b4 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -60,9 +60,9 @@ Driver::Driver(llvm::StringRef ClangExecutable, CCLogDiagnosticsFilename(0), CCCIsCXX(false), CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), - CCCGenericGCCName(""), CheckInputsExist(true), CCCUseClang(true), - CCCUseClangCXX(true), CCCUseClangCPP(true), CCCUsePCH(true), - SuppressMissingInputWarning(false) { + CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), + CCCUseClang(true), CCCUseClangCXX(true), CCCUseClangCPP(true), + CCCUsePCH(true), SuppressMissingInputWarning(false) { if (IsProduction) { // In a "production" build, only use clang on architectures we expect to // work, and don't use clang C++. @@ -313,7 +313,63 @@ Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) { return C; } -int Driver::ExecuteCompilation(const Compilation &C) const { +// 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. +void Driver::generateCompilationDiagnostics(Compilation &C, + const Command *FailingCommand) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Please submit a bug report to " BUG_REPORT_URL " and include command" + " line arguments and all diagnostic information."; + + // Suppress driver output and emit preprocessor output to temp file. + CCCIsCPP = true; + CCGenDiagnostics = true; + + // Clear stale state and suppress tool output. + C.initCompilationForDiagnostics(); + + // Construct the list of abstract actions to perform for this compilation. + Diags.Reset(); + if (Host->useDriverDriver()) + BuildUniversalActions(C.getDefaultToolChain(), C.getArgs(), + C.getActions()); + else + BuildActions(C.getDefaultToolChain(), C.getArgs(), C.getActions()); + + BuildJobs(C); + + // If there were errors building the compilation, quit now. + if (Diags.hasErrorOccurred()) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s)."; + return; + } + + // Generate preprocessed output. + FailingCommand = 0; + int Res = C.ExecuteJob(C.getJobs(), FailingCommand); + + // If the command succeeded, we are done. + if (Res == 0) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Preprocessed source(s) are located at:"; + ArgStringList Files = C.getTempFiles(); + for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end(); + it != ie; ++it) + Diag(clang::diag::note_drv_command_failed_diag_msg) << *it; + } else { + // Failure, remove preprocessed files. + if (!C.getArgs().hasArg(options::OPT_save_temps)) + C.CleanupFileList(C.getTempFiles(), true); + + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s)."; + } +} + +int Driver::ExecuteCompilation(const Compilation &C, + const Command *&FailingCommand) const { // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { C.PrintJob(llvm::errs(), C.getJobs(), "\n", true); @@ -321,10 +377,9 @@ int Driver::ExecuteCompilation(const Compilation &C) const { } // If there were errors building the compilation, quit now. - if (getDiags().hasErrorOccurred()) + if (Diags.hasErrorOccurred()) return 1; - const Command *FailingCommand = 0; int Res = C.ExecuteJob(C.getJobs(), FailingCommand); // Remove temp files. @@ -1198,7 +1253,7 @@ void Driver::BuildJobsForAction(Compilation &C, A->getType(), BaseInput); } - if (CCCPrintBindings) { + if (CCCPrintBindings && !CCGenDiagnostics) { llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"' << " - \"" << T.getName() << "\", inputs: ["; for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) { @@ -1225,11 +1280,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } // Default to writing to stdout? - if (AtTopLevel && isa<PreprocessJobAction>(JA)) + if (AtTopLevel && isa<PreprocessJobAction>(JA) && !CCGenDiagnostics) return "-"; // Output to a temporary file? - if (!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) { + if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) || + CCGenDiagnostics) { std::string TmpName = GetTemporaryPath(types::getTypeTempSuffix(JA.getType())); return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 51055e93f55..1cd0abd595f 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -28,6 +28,12 @@ JobList::~JobList() { delete *it; } +void JobList::clear() { + for (iterator it = begin(), ie = end(); it != ie; ++it) + delete *it; + Jobs.clear(); +} + void Job::addCommand(Command *C) { cast<JobList>(this)->addJob(C); } diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index c54ced2d1d0..c30e55e6a84 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1376,7 +1376,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_v); Args.AddLastArg(CmdArgs, options::OPT_H); - if (D.CCPrintHeaders) { + if (D.CCPrintHeaders && !D.CCGenDiagnostics) { CmdArgs.push_back("-header-include-file"); CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename : "-"); @@ -1384,7 +1384,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_P); Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout); - if (D.CCLogDiagnostics) { + if (D.CCLogDiagnostics && !D.CCGenDiagnostics) { CmdArgs.push_back("-diagnostic-log-file"); CmdArgs.push_back(D.CCLogDiagnosticsFilename ? D.CCLogDiagnosticsFilename : "-"); |

