summaryrefslogtreecommitdiff
path: root/clang/tools
diff options
context:
space:
mode:
Diffstat (limited to 'clang/tools')
-rw-r--r--clang/tools/driver/cc1_main.cpp10
-rw-r--r--clang/tools/driver/cc1as_main.cpp44
-rw-r--r--clang/tools/driver/cc1gen_reproducer_main.cpp1
-rw-r--r--clang/tools/driver/driver.cpp106
4 files changed, 94 insertions, 67 deletions
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index b551e9f4cf829..0872015e0ab05 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -69,7 +70,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
// We cannot recover from llvm errors. When reporting a fatal error, exit
// with status 70 to generate crash diagnostics. For BSD systems this is
// defined as an internal software error. Otherwise, exit with status 1.
- exit(GenCrashDiag ? 70 : 1);
+ llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);
}
#ifdef CLANG_HAVE_RLIMITS
@@ -176,7 +177,7 @@ static int PrintSupportedCPUs(std::string TargetStr) {
// the target machine will handle the mcpu printing
llvm::TargetOptions Options;
std::unique_ptr<llvm::TargetMachine> TheTargetMachine(
- TheTarget->createTargetMachine(TargetStr, "", "+cpuHelp", Options, None));
+ TheTarget->createTargetMachine(TargetStr, "", "+cpuhelp", Options, None));
return 0;
}
@@ -202,8 +203,8 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
- bool Success =
- CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, Diags);
+ bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),
+ Argv, Diags, Argv0);
if (Clang->getFrontendOpts().TimeTrace) {
llvm::timeTraceProfilerInitialize(
@@ -258,6 +259,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
// FIXME(ibiryukov): make profilerOutput flush in destructor instead.
profilerOutput->flush();
llvm::timeTraceProfilerCleanup();
+ Clang->clearOutputFiles(false);
}
}
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index 53c8a9d642dc0..77b99b2013640 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -46,6 +46,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
@@ -206,7 +207,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Target Options
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
- Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
+ Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
Opts.Features = Args.getAllArgValues(OPT_target_feature);
// Use the default target triple if unspecified.
@@ -237,13 +238,19 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
- Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
- Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer);
- Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
- Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
-
- for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
- Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
+ Opts.DwarfDebugFlags =
+ std::string(Args.getLastArgValue(OPT_dwarf_debug_flags));
+ Opts.DwarfDebugProducer =
+ std::string(Args.getLastArgValue(OPT_dwarf_debug_producer));
+ Opts.DebugCompilationDir =
+ std::string(Args.getLastArgValue(OPT_fdebug_compilation_dir));
+ Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name));
+
+ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
+ auto Split = StringRef(Arg).split('=');
+ Opts.DebugPrefixMap.insert(
+ {std::string(Split.first), std::string(Split.second)});
+ }
// Frontend Options
if (Args.hasArg(OPT_INPUT)) {
@@ -259,8 +266,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
}
}
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
- Opts.OutputPath = Args.getLastArgValue(OPT_o);
- Opts.SplitDwarfOutput = Args.getLastArgValue(OPT_split_dwarf_output);
+ Opts.OutputPath = std::string(Args.getLastArgValue(OPT_o));
+ Opts.SplitDwarfOutput =
+ std::string(Args.getLastArgValue(OPT_split_dwarf_output));
if (Arg *A = Args.getLastArg(OPT_filetype)) {
StringRef Name = A->getValue();
unsigned OutputType = StringSwitch<unsigned>(Name)
@@ -288,8 +296,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);
- Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
- Opts.TargetABI = Args.getLastArgValue(OPT_target_abi);
+ Opts.RelocationModel =
+ std::string(Args.getLastArgValue(OPT_mrelocation_model, "pic"));
+ Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi));
Opts.IncrementalLinkerCompatible =
Args.hasArg(OPT_mincremental_linker_compatible);
Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
@@ -420,12 +429,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());
// Build up the feature string from the target feature list.
- std::string FS;
- if (!Opts.Features.empty()) {
- FS = Opts.Features[0];
- for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i)
- FS += "," + Opts.Features[i];
- }
+ std::string FS = llvm::join(Opts.Features, ",");
std::unique_ptr<MCStreamer> Str;
@@ -489,7 +493,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
MCSection *AsmLabel = Ctx.getMachOSection(
"__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
Str.get()->SwitchSection(AsmLabel);
- Str.get()->EmitZeros(1);
+ Str.get()->emitZeros(1);
}
// Assembly to object compilation should leverage assembly info.
@@ -547,7 +551,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
Diags.Report(diag::err_fe_error_backend) << Message;
// We cannot recover from llvm errors.
- exit(1);
+ sys::Process::Exit(1);
}
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp
index 4aadab7301bc9..472055ee21708 100644
--- a/clang/tools/driver/cc1gen_reproducer_main.cpp
+++ b/clang/tools/driver/cc1gen_reproducer_main.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLTraits.h"
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index 4cdf8015b1bfc..f24fd61e61a54 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -30,6 +30,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/ErrorHandling.h"
@@ -37,6 +38,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
@@ -60,7 +62,7 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
if (llvm::ErrorOr<std::string> P =
llvm::sys::findProgramByName(ExecutablePath))
ExecutablePath = *P;
- return ExecutablePath.str();
+ return std::string(ExecutablePath.str());
}
// This just needs to be some symbol in the binary; C++ doesn't
@@ -71,7 +73,7 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
static const char *GetStableCStr(std::set<std::string> &SavedStrings,
StringRef S) {
- return SavedStrings.insert(S).first->c_str();
+ return SavedStrings.insert(std::string(S)).first->c_str();
}
/// ApplyQAOverride - Apply a list of edits to the input argument lists.
@@ -241,8 +243,6 @@ static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
*NumberSignPtr = '=';
}
-static int ExecuteCC1Tool(ArrayRef<const char *> argv);
-
static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
// Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
@@ -258,27 +258,6 @@ static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
if (TheDriver.CCLogDiagnostics)
TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
-
- // Whether the cc1 tool should be called inside the current process, or if we
- // should spawn a new clang process (old behavior).
- // Not having an additional process saves some execution time of Windows,
- // and makes debugging easier.
- bool UseNewCC1Process = CLANG_SPAWN_CC1;
-
- StringRef SpawnCC1Str = ::getenv("CLANG_SPAWN_CC1");
- if (!SpawnCC1Str.empty()) {
- if (SpawnCC1Str != "0" && SpawnCC1Str != "1") {
- llvm::errs() << "error: the value of the environment variable "
- "CLANG_SPAWN_CC1 must be either 0 or 1.\n";
- ::exit(1);
- }
- UseNewCC1Process = SpawnCC1Str[0] - '0';
- }
- if (!UseNewCC1Process) {
- TheDriver.CC1Main = &ExecuteCC1Tool;
- // Ensure the CC1Command actually catches cc1 crashes
- llvm::CrashRecoveryContext::Enable();
- }
}
static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
@@ -288,13 +267,13 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
StringRef ExeBasename(llvm::sys::path::stem(Path));
if (ExeBasename.equals_lower("cl"))
ExeBasename = "clang-cl";
- DiagClient->setPrefix(ExeBasename);
+ DiagClient->setPrefix(std::string(ExeBasename));
}
// This lets us create the DiagnosticsEngine with a properly-filled-out
// DiagnosticOptions instance.
static DiagnosticOptions *
-CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) {
+CreateAndPopulateDiagOpts(ArrayRef<const char *> argv, bool &UseNewCC1Process) {
auto *DiagOpts = new DiagnosticOptions;
unsigned MissingArgIndex, MissingArgCount;
InputArgList Args = getDriverOptTable().ParseArgs(
@@ -303,6 +282,12 @@ CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) {
// Any errors that would be diagnosed here will also be diagnosed later,
// when the DiagnosticsEngine actually exists.
(void)ParseDiagnosticArgs(*DiagOpts, Args);
+
+ UseNewCC1Process =
+ Args.hasFlag(clang::driver::options::OPT_fno_integrated_cc1,
+ clang::driver::options::OPT_fintegrated_cc1,
+ /*Default=*/CLANG_SPAWN_CC1);
+
return DiagOpts;
}
@@ -328,21 +313,27 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv,
TheDriver.setInstalledDir(InstalledPathParent);
}
-static int ExecuteCC1Tool(ArrayRef<const char *> argv) {
+static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV) {
// If we call the cc1 tool from the clangDriver library (through
- // Driver::CC1Main), we need to cleanup the options usage count. The options
+ // Driver::CC1Main), we need to clean up the options usage count. The options
// are currently global, and they might have been used previously by the
// driver.
llvm::cl::ResetAllOptionOccurrences();
- StringRef Tool = argv[1];
- void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath;
+
+ llvm::BumpPtrAllocator A;
+ llvm::StringSaver Saver(A);
+ llvm::cl::ExpandResponseFiles(Saver, &llvm::cl::TokenizeGNUCommandLine, ArgV,
+ /*MarkEOLs=*/false);
+ StringRef Tool = ArgV[1];
+ void *GetExecutablePathVP = (void *)(intptr_t)GetExecutablePath;
if (Tool == "-cc1")
- return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
+ return cc1_main(makeArrayRef(ArgV).slice(1), ArgV[0], GetExecutablePathVP);
if (Tool == "-cc1as")
- return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP);
+ return cc1as_main(makeArrayRef(ArgV).slice(2), ArgV[0],
+ GetExecutablePathVP);
if (Tool == "-cc1gen-reproducer")
- return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP);
-
+ return cc1gen_reproducer_main(makeArrayRef(ArgV).slice(2), ArgV[0],
+ GetExecutablePathVP);
// Reject unknown tools.
llvm::errs() << "error: unknown integrated tool '" << Tool << "'. "
<< "Valid tools include '-cc1' and '-cc1as'.\n";
@@ -352,6 +343,9 @@ static int ExecuteCC1Tool(ArrayRef<const char *> argv) {
int main(int argc_, const char **argv_) {
noteBottomOfStack();
llvm::InitLLVM X(argc_, argv_);
+ llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL
+ " and include the crash backtrace, preprocessed "
+ "source, and associated run script.\n");
SmallVector<const char *, 256> argv(argv_, argv_ + argc_);
if (llvm::sys::Process::FixupStandardFileDescriptors())
@@ -413,6 +407,8 @@ int main(int argc_, const char **argv_) {
return ExecuteCC1Tool(argv);
}
+ // Handle options that need handling before the real command line parsing in
+ // Driver::BuildCompilation()
bool CanonicalPrefixes = true;
for (int i = 1, size = argv.size(); i < size; ++i) {
// Skip end-of-line response file markers
@@ -457,8 +453,14 @@ int main(int argc_, const char **argv_) {
std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes);
+ // Whether the cc1 tool should be called inside the current process, or if we
+ // should spawn a new clang subprocess (old behavior).
+ // Not having an additional process saves some execution time of Windows,
+ // and makes debugging and profiling easier.
+ bool UseNewCC1Process;
+
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
- CreateAndPopulateDiagOpts(argv);
+ CreateAndPopulateDiagOpts(argv, UseNewCC1Process);
TextDiagnosticPrinter *DiagClient
= new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
@@ -486,8 +488,15 @@ int main(int argc_, const char **argv_) {
SetBackdoorDriverOutputsFromEnvVars(TheDriver);
+ if (!UseNewCC1Process) {
+ TheDriver.CC1Main = &ExecuteCC1Tool;
+ // Ensure the CC1Command actually catches cc1 crashes
+ llvm::CrashRecoveryContext::Enable();
+ }
+
std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));
int Res = 1;
+ bool IsCrash = false;
if (C && !C->containsError()) {
SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
@@ -502,6 +511,11 @@ int main(int argc_, const char **argv_) {
for (const auto &J : C->getJobs())
if (const Command *C = dyn_cast<Command>(&J))
FailingCommands.push_back(std::make_pair(-1, C));
+
+ // Print the bug report message that would be printed if we did actually
+ // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH.
+ if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
+ llvm::dbgs() << llvm::getBugReportMsg();
}
for (const auto &P : FailingCommands) {
@@ -514,11 +528,11 @@ int main(int argc_, const char **argv_) {
// If result status is 70, then the driver command reported a fatal error.
// On Windows, abort will return an exit code of 3. In these cases,
// generate additional diagnostic information if possible.
- bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70;
+ IsCrash = CommandRes < 0 || CommandRes == 70;
#ifdef _WIN32
- DiagnoseCrash |= CommandRes == 3;
+ IsCrash |= CommandRes == 3;
#endif
- if (DiagnoseCrash) {
+ if (IsCrash) {
TheDriver.generateCompilationDiagnostics(*C, *FailingCommand);
break;
}
@@ -527,10 +541,16 @@ int main(int argc_, const char **argv_) {
Diags.getClient()->finish();
- // 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());
- llvm::TimerGroup::clearAll();
+ if (!UseNewCC1Process && IsCrash) {
+ // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because
+ // the internal linked list might point to already released stack frames.
+ llvm::BuryPointer(llvm::TimerGroup::aquireDefaultGroup());
+ } else {
+ // 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());
+ llvm::TimerGroup::clearAll();
+ }
#ifdef _WIN32
// Exit status should not be negative on Win32, unless abnormal termination.