[cfe-commits] r136702 - in /cfe/trunk: CMakeLists.txt include/clang/Basic/DiagnosticDriverKinds.td include/clang/Config/config.h.cmake include/clang/Driver/ArgList.h include/clang/Driver/Compilation.h include/clang/Driver/Driver.h include/clang/Driver/Job.h lib/Driver/ArgList.cpp lib/Driver/Compilation.cpp lib/Driver/Driver.cpp lib/Driver/Job.cpp lib/Driver/Tools.cpp tools/driver/driver.cpp

Chad Rosier mcrosier at apple.com
Tue Aug 2 10:58:05 PDT 2011


Author: mcrosier
Date: Tue Aug  2 12:58:04 2011
New Revision: 136702

URL: http://llvm.org/viewvc/llvm-project?rev=136702&view=rev
Log:
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.
rdar://9575623

Modified:
    cfe/trunk/CMakeLists.txt
    cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
    cfe/trunk/include/clang/Config/config.h.cmake
    cfe/trunk/include/clang/Driver/ArgList.h
    cfe/trunk/include/clang/Driver/Compilation.h
    cfe/trunk/include/clang/Driver/Driver.h
    cfe/trunk/include/clang/Driver/Job.h
    cfe/trunk/lib/Driver/ArgList.cpp
    cfe/trunk/lib/Driver/Compilation.cpp
    cfe/trunk/lib/Driver/Driver.cpp
    cfe/trunk/lib/Driver/Job.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/tools/driver/driver.cpp

Modified: cfe/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CMakeLists.txt?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/CMakeLists.txt (original)
+++ cfe/trunk/CMakeLists.txt Tue Aug  2 12:58:04 2011
@@ -272,3 +272,6 @@
     file(APPEND "${CLANG_SLN_FILENAME}" "\n# This should be regenerated!\n")
   endif()
 endif()
+
+set(BUG_REPORT_URL "http://llvm.org" CACHE STRING
+  "Default URL where bug reports are to be submitted.")

Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Tue Aug  2 12:58:04 2011
@@ -123,4 +123,7 @@
 def warn_drv_pch_not_first_include : Warning<
   "precompiled header '%0' was ignored because '%1' is not first '-include'">;
 
+def note_drv_command_failed_diag_msg : Note<
+  "diagnostic msg: %0">;
+
 }

Modified: cfe/trunk/include/clang/Config/config.h.cmake
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Config/config.h.cmake?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/include/clang/Config/config.h.cmake (original)
+++ cfe/trunk/include/clang/Config/config.h.cmake Tue Aug  2 12:58:04 2011
@@ -13,5 +13,8 @@
 /* Directory with the libstdc++ headers. */
 #define CXX_INCLUDE_ROOT "${CXX_INCLUDE_ROOT}"
 
-/* Directories clang will search for headers */
+/* Directories clang will search for headers. */
 #define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
+
+/* Define default bug reporting URL. */
+#cmakedefine BUG_REPORT_URL "${BUG_REPORT_URL}"

Modified: cfe/trunk/include/clang/Driver/ArgList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/ArgList.h?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/ArgList.h (original)
+++ cfe/trunk/include/clang/Driver/ArgList.h Tue Aug  2 12:58:04 2011
@@ -150,6 +150,13 @@
     }
 
     /// @}
+    /// @name Arg Removal
+    /// @{
+
+    /// eraseArg - Remove any option matching \arg Id.
+    void eraseArg(OptSpecifier Id);
+
+    /// @}
     /// @name Arg Access
     /// @{
 
@@ -242,6 +249,10 @@
     /// option id.
     void ClaimAllArgs(OptSpecifier Id0) const;
 
+    /// ClaimAllArgs - Claim all arguments.
+    ///
+    void ClaimAllArgs() const;
+
     /// @}
     /// @name Arg Synthesis
     /// @{

Modified: cfe/trunk/include/clang/Driver/Compilation.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Compilation.h?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Compilation.h (original)
+++ cfe/trunk/include/clang/Driver/Compilation.h Tue Aug  2 12:58:04 2011
@@ -13,6 +13,7 @@
 #include "clang/Driver/Job.h"
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Path.h"
 
 namespace clang {
 namespace driver {
@@ -55,6 +56,9 @@
   /// Result files which should be removed on failure.
   ArgStringList ResultFiles;
 
+  /// Redirection for stdout, stderr, etc.
+  const llvm::sys::Path **Redirects;
+
 public:
   Compilation(const Driver &D, const ToolChain &DefaultToolChain,
               InputArgList *Args, DerivedArgList *TranslatedArgs);
@@ -131,6 +135,11 @@
   /// Command which failed.
   /// \return The accumulated result code of the job.
   int ExecuteJob(const Job &J, const Command *&FailingCommand) const;
+
+  /// initCompilationForDiagnostics - Remove stale state and suppress output
+  /// so compilation can be reexecuted to generate additional diagnostic
+  /// information (e.g., preprocessed source(s)).
+  void initCompilationForDiagnostics();
 };
 
 } // end namespace driver

Modified: cfe/trunk/include/clang/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Driver.h?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Driver.h (original)
+++ cfe/trunk/include/clang/Driver/Driver.h Tue Aug  2 12:58:04 2011
@@ -31,6 +31,7 @@
   class Action;
   class Arg;
   class ArgList;
+  class Command;
   class Compilation;
   class DerivedArgList;
   class HostInfo;
@@ -134,6 +135,9 @@
   /// format.
   unsigned CCLogDiagnostics : 1;
 
+  /// Whether the driver is generating diagnostics for debugging purposes.
+  unsigned CCGenDiagnostics : 1;
+
 private:
   /// Name to use when invoking gcc/g++.
   std::string CCCGenericGCCName;
@@ -268,7 +272,14 @@
   /// This routine handles additional processing that must be done in addition
   /// to just running the subprocesses, for example reporting errors, removing
   /// temporary files, etc.
-  int ExecuteCompilation(const Compilation &C) const;
+  int ExecuteCompilation(const Compilation &C,
+                         const Command *&FailingCommand) const;
+  
+  /// generateCompilationDiagnostics - Generate diagnostics information 
+  /// including preprocessed source file(s).
+  /// 
+  void generateCompilationDiagnostics(Compilation &C,
+                                      const Command *FailingCommand);
 
   /// @}
   /// @name Helper Methods

Modified: cfe/trunk/include/clang/Driver/Job.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Job.h?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Job.h (original)
+++ cfe/trunk/include/clang/Driver/Job.h Tue Aug  2 12:58:04 2011
@@ -97,6 +97,9 @@
   /// Add a job to the list (taking ownership).
   void addJob(Job *J) { Jobs.push_back(J); }
 
+  /// Clear the job list.
+  void clear();
+
   const list_type &getJobs() const { return Jobs; }
 
   size_type size() const { return Jobs.size(); }

Modified: cfe/trunk/lib/Driver/ArgList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ArgList.cpp?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ArgList.cpp (original)
+++ cfe/trunk/lib/Driver/ArgList.cpp Tue Aug  2 12:58:04 2011
@@ -46,6 +46,16 @@
   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 @@
     (*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 Twine &T) const {
   llvm::SmallString<256> Str;
   T.toVector(Str);

Modified: cfe/trunk/lib/Driver/Compilation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Compilation.cpp?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Compilation.cpp (original)
+++ cfe/trunk/lib/Driver/Compilation.cpp Tue Aug  2 12:58:04 2011
@@ -16,6 +16,7 @@
 #include "clang/Driver/Options.h"
 #include "clang/Driver/ToolChain.h"
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Program.h"
 #include <sys/stat.h>
@@ -27,7 +28,7 @@
 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() {
@@ -45,6 +46,13 @@
   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,
@@ -137,8 +145,8 @@
   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) {
     raw_ostream *OS = &llvm::errs();
 
     // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
@@ -169,7 +177,7 @@
   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()) {
@@ -197,3 +205,24 @@
     return 0;
   }
 }
+
+void Compilation::initCompilationForDiagnostics(void) {
+  // Free actions and jobs.
+  DeleteContainerPointers(Actions);
+  Jobs.clear();
+
+  // Clear temporary/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();
+}

Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Tue Aug  2 12:58:04 2011
@@ -60,9 +60,9 @@
     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++.
@@ -367,7 +367,63 @@
   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);
@@ -375,10 +431,9 @@
   }
 
   // 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.
@@ -1226,7 +1281,7 @@
                        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) {
@@ -1253,11 +1308,12 @@
   }
 
   // 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()));

Modified: cfe/trunk/lib/Driver/Job.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Job.cpp?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Job.cpp (original)
+++ cfe/trunk/lib/Driver/Job.cpp Tue Aug  2 12:58:04 2011
@@ -9,6 +9,8 @@
 
 #include "clang/Driver/Job.h"
 
+#include "llvm/ADT/STLExtras.h"
+
 #include <cassert>
 using namespace clang::driver;
 
@@ -28,6 +30,10 @@
     delete *it;
 }
 
+void JobList::clear() {
+  DeleteContainerPointers(Jobs);
+}
+
 void Job::addCommand(Command *C) {
   cast<JobList>(this)->addJob(C);
 }

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Aug  2 12:58:04 2011
@@ -1378,7 +1378,7 @@
 
   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 : "-");
@@ -1386,7 +1386,7 @@
   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 : "-");

Modified: cfe/trunk/tools/driver/driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/driver.cpp?rev=136702&r1=136701&r2=136702&view=diff
==============================================================================
--- cfe/trunk/tools/driver/driver.cpp (original)
+++ cfe/trunk/tools/driver/driver.cpp Tue Aug  2 12:58:04 2011
@@ -458,9 +458,15 @@
 
   llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv));
   int Res = 0;
+  const Command *FailingCommand = 0;
   if (C.get())
-    Res = TheDriver.ExecuteCompilation(*C);
-  
+    Res = TheDriver.ExecuteCompilation(*C, FailingCommand);
+
+  // If result status is < 0, then the driver command signalled an error.
+  // In this case, generate additional diagnostic information if possible.
+  if (Res < 0)
+    TheDriver.generateCompilationDiagnostics(*C, FailingCommand);
+
   // If any timers were active but haven't been destroyed yet, print their
   // results now.  This happens in -disable-free mode.
   llvm::TimerGroup::printAll(llvm::errs());





More information about the cfe-commits mailing list