forked from OSchip/llvm-project
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
This commit is contained in:
parent
e6f7f914db
commit
e3805fc118
|
@ -123,4 +123,7 @@ def warn_drv_objc_gc_unsupported : Warning<
|
||||||
def warn_drv_pch_not_first_include : Warning<
|
def warn_drv_pch_not_first_include : Warning<
|
||||||
"precompiled header '%0' was ignored because '%1' is not first '-include'">;
|
"precompiled header '%0' was ignored because '%1' is not first '-include'">;
|
||||||
|
|
||||||
|
def note_drv_command_failed_diag_msg : Note<
|
||||||
|
"diagnostic msg: %0">;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,6 +149,13 @@ namespace driver {
|
||||||
return arg_iterator(Args.end(), *this);
|
return arg_iterator(Args.end(), *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Arg Removal
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// eraseArg - Remove any option matching \arg Id.
|
||||||
|
void eraseArg(OptSpecifier Id);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Arg Access
|
/// @name Arg Access
|
||||||
/// @{
|
/// @{
|
||||||
|
@ -242,6 +249,10 @@ namespace driver {
|
||||||
/// option id.
|
/// option id.
|
||||||
void ClaimAllArgs(OptSpecifier Id0) const;
|
void ClaimAllArgs(OptSpecifier Id0) const;
|
||||||
|
|
||||||
|
/// ClaimAllArgs - Claim all arguments.
|
||||||
|
///
|
||||||
|
void ClaimAllArgs() const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Arg Synthesis
|
/// @name Arg Synthesis
|
||||||
/// @{
|
/// @{
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "clang/Driver/Job.h"
|
#include "clang/Driver/Job.h"
|
||||||
#include "clang/Driver/Util.h"
|
#include "clang/Driver/Util.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace driver {
|
namespace driver {
|
||||||
|
@ -55,6 +56,9 @@ class Compilation {
|
||||||
/// Result files which should be removed on failure.
|
/// Result files which should be removed on failure.
|
||||||
ArgStringList ResultFiles;
|
ArgStringList ResultFiles;
|
||||||
|
|
||||||
|
/// Redirection for stdout, stderr, etc.
|
||||||
|
const llvm::sys::Path **Redirects;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
|
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
|
||||||
InputArgList *Args, DerivedArgList *TranslatedArgs);
|
InputArgList *Args, DerivedArgList *TranslatedArgs);
|
||||||
|
@ -131,6 +135,11 @@ public:
|
||||||
/// Command which failed.
|
/// Command which failed.
|
||||||
/// \return The accumulated result code of the job.
|
/// \return The accumulated result code of the job.
|
||||||
int ExecuteJob(const Job &J, const Command *&FailingCommand) const;
|
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
|
} // end namespace driver
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace clang {
|
||||||
namespace driver {
|
namespace driver {
|
||||||
class Action;
|
class Action;
|
||||||
class ArgList;
|
class ArgList;
|
||||||
|
class Command;
|
||||||
class Compilation;
|
class Compilation;
|
||||||
class DerivedArgList;
|
class DerivedArgList;
|
||||||
class HostInfo;
|
class HostInfo;
|
||||||
|
@ -133,6 +134,9 @@ public:
|
||||||
/// format.
|
/// format.
|
||||||
unsigned CCLogDiagnostics : 1;
|
unsigned CCLogDiagnostics : 1;
|
||||||
|
|
||||||
|
/// Whether the driver is generating diagnostics for debugging purposes.
|
||||||
|
unsigned CCGenDiagnostics : 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Name to use when invoking gcc/g++.
|
/// Name to use when invoking gcc/g++.
|
||||||
std::string CCCGenericGCCName;
|
std::string CCCGenericGCCName;
|
||||||
|
@ -262,7 +266,14 @@ public:
|
||||||
/// This routine handles additional processing that must be done in addition
|
/// This routine handles additional processing that must be done in addition
|
||||||
/// to just running the subprocesses, for example reporting errors, removing
|
/// to just running the subprocesses, for example reporting errors, removing
|
||||||
/// temporary files, etc.
|
/// 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
|
/// @name Helper Methods
|
||||||
|
|
|
@ -97,6 +97,9 @@ public:
|
||||||
/// Add a job to the list (taking ownership).
|
/// Add a job to the list (taking ownership).
|
||||||
void addJob(Job *J) { Jobs.push_back(J); }
|
void addJob(Job *J) { Jobs.push_back(J); }
|
||||||
|
|
||||||
|
/// Clear the job list.
|
||||||
|
void clear();
|
||||||
|
|
||||||
const list_type &getJobs() const { return Jobs; }
|
const list_type &getJobs() const { return Jobs; }
|
||||||
|
|
||||||
size_type size() const { return Jobs.size(); }
|
size_type size() const { return Jobs.size(); }
|
||||||
|
|
|
@ -46,6 +46,16 @@ void ArgList::append(Arg *A) {
|
||||||
Args.push_back(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 {
|
Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
|
||||||
// FIXME: Make search efficient?
|
// FIXME: Make search efficient?
|
||||||
for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
|
for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
|
||||||
|
@ -192,6 +202,12 @@ void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
|
||||||
(*it)->claim();
|
(*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 {
|
const char *ArgList::MakeArgString(const llvm::Twine &T) const {
|
||||||
llvm::SmallString<256> Str;
|
llvm::SmallString<256> Str;
|
||||||
T.toVector(Str);
|
T.toVector(Str);
|
||||||
|
|
|
@ -25,7 +25,7 @@ using namespace clang::driver;
|
||||||
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
|
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
|
||||||
InputArgList *_Args, DerivedArgList *_TranslatedArgs)
|
InputArgList *_Args, DerivedArgList *_TranslatedArgs)
|
||||||
: TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
|
: TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
|
||||||
TranslatedArgs(_TranslatedArgs) {
|
TranslatedArgs(_TranslatedArgs), Redirects(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Compilation::~Compilation() {
|
Compilation::~Compilation() {
|
||||||
|
@ -43,6 +43,13 @@ Compilation::~Compilation() {
|
||||||
for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
|
for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
|
||||||
it != ie; ++it)
|
it != ie; ++it)
|
||||||
delete *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,
|
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);
|
std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
|
||||||
Argv[C.getArguments().size() + 1] = 0;
|
Argv[C.getArguments().size() + 1] = 0;
|
||||||
|
|
||||||
if (getDriver().CCCEcho || getDriver().CCPrintOptions ||
|
if ((getDriver().CCCEcho || getDriver().CCPrintOptions ||
|
||||||
getArgs().hasArg(options::OPT_v)) {
|
getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
|
||||||
llvm::raw_ostream *OS = &llvm::errs();
|
llvm::raw_ostream *OS = &llvm::errs();
|
||||||
|
|
||||||
// Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
|
// 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;
|
std::string Error;
|
||||||
int Res =
|
int Res =
|
||||||
llvm::sys::Program::ExecuteAndWait(Prog, Argv,
|
llvm::sys::Program::ExecuteAndWait(Prog, Argv,
|
||||||
/*env*/0, /*redirects*/0,
|
/*env*/0, Redirects,
|
||||||
/*secondsToWait*/0, /*memoryLimit*/0,
|
/*secondsToWait*/0, /*memoryLimit*/0,
|
||||||
&Error);
|
&Error);
|
||||||
if (!Error.empty()) {
|
if (!Error.empty()) {
|
||||||
|
@ -195,3 +202,27 @@ int Compilation::ExecuteJob(const Job &J,
|
||||||
return 0;
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -60,9 +60,9 @@ Driver::Driver(llvm::StringRef ClangExecutable,
|
||||||
CCLogDiagnosticsFilename(0), CCCIsCXX(false),
|
CCLogDiagnosticsFilename(0), CCCIsCXX(false),
|
||||||
CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false),
|
CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false),
|
||||||
CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
|
CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
|
||||||
CCCGenericGCCName(""), CheckInputsExist(true), CCCUseClang(true),
|
CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
|
||||||
CCCUseClangCXX(true), CCCUseClangCPP(true), CCCUsePCH(true),
|
CCCUseClang(true), CCCUseClangCXX(true), CCCUseClangCPP(true),
|
||||||
SuppressMissingInputWarning(false) {
|
CCCUsePCH(true), SuppressMissingInputWarning(false) {
|
||||||
if (IsProduction) {
|
if (IsProduction) {
|
||||||
// In a "production" build, only use clang on architectures we expect to
|
// In a "production" build, only use clang on architectures we expect to
|
||||||
// work, and don't use clang C++.
|
// work, and don't use clang C++.
|
||||||
|
@ -313,7 +313,63 @@ Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) {
|
||||||
return C;
|
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.
|
// Just print if -### was present.
|
||||||
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
|
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
|
||||||
C.PrintJob(llvm::errs(), C.getJobs(), "\n", true);
|
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 there were errors building the compilation, quit now.
|
||||||
if (getDiags().hasErrorOccurred())
|
if (Diags.hasErrorOccurred())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const Command *FailingCommand = 0;
|
|
||||||
int Res = C.ExecuteJob(C.getJobs(), FailingCommand);
|
int Res = C.ExecuteJob(C.getJobs(), FailingCommand);
|
||||||
|
|
||||||
// Remove temp files.
|
// Remove temp files.
|
||||||
|
@ -1198,7 +1253,7 @@ void Driver::BuildJobsForAction(Compilation &C,
|
||||||
A->getType(), BaseInput);
|
A->getType(), BaseInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CCCPrintBindings) {
|
if (CCCPrintBindings && !CCGenDiagnostics) {
|
||||||
llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"'
|
llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"'
|
||||||
<< " - \"" << T.getName() << "\", inputs: [";
|
<< " - \"" << T.getName() << "\", inputs: [";
|
||||||
for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
|
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?
|
// Default to writing to stdout?
|
||||||
if (AtTopLevel && isa<PreprocessJobAction>(JA))
|
if (AtTopLevel && isa<PreprocessJobAction>(JA) && !CCGenDiagnostics)
|
||||||
return "-";
|
return "-";
|
||||||
|
|
||||||
// Output to a temporary file?
|
// 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 =
|
std::string TmpName =
|
||||||
GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
|
GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
|
||||||
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
|
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
|
||||||
|
|
|
@ -28,6 +28,12 @@ JobList::~JobList() {
|
||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JobList::clear() {
|
||||||
|
for (iterator it = begin(), ie = end(); it != ie; ++it)
|
||||||
|
delete *it;
|
||||||
|
Jobs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Job::addCommand(Command *C) {
|
void Job::addCommand(Command *C) {
|
||||||
cast<JobList>(this)->addJob(C);
|
cast<JobList>(this)->addJob(C);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
|
|
||||||
Args.AddAllArgs(CmdArgs, options::OPT_v);
|
Args.AddAllArgs(CmdArgs, options::OPT_v);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_H);
|
Args.AddLastArg(CmdArgs, options::OPT_H);
|
||||||
if (D.CCPrintHeaders) {
|
if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
|
||||||
CmdArgs.push_back("-header-include-file");
|
CmdArgs.push_back("-header-include-file");
|
||||||
CmdArgs.push_back(D.CCPrintHeadersFilename ?
|
CmdArgs.push_back(D.CCPrintHeadersFilename ?
|
||||||
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_P);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
|
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("-diagnostic-log-file");
|
||||||
CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
|
CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
|
||||||
D.CCLogDiagnosticsFilename : "-");
|
D.CCLogDiagnosticsFilename : "-");
|
||||||
|
|
|
@ -458,8 +458,14 @@ int main(int argc_, const char **argv_) {
|
||||||
|
|
||||||
llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv));
|
llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv));
|
||||||
int Res = 0;
|
int Res = 0;
|
||||||
|
const Command *FailingCommand = 0;
|
||||||
if (C.get())
|
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
|
// If any timers were active but haven't been destroyed yet, print their
|
||||||
// results now. This happens in -disable-free mode.
|
// results now. This happens in -disable-free mode.
|
||||||
|
|
Loading…
Reference in New Issue