diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Driver.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 171 |
1 files changed, 93 insertions, 78 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 1664d0d..0f3ebef 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -17,6 +17,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/ArrayRef.h" @@ -44,21 +45,19 @@ using namespace clang::driver; using namespace clang; using namespace llvm::opt; -Driver::Driver(StringRef ClangExecutable, - StringRef DefaultTargetTriple, +Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple, DiagnosticsEngine &Diags) - : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), - ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), - UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple), - DriverTitle("clang LLVM compiler"), - CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), - CCLogDiagnosticsFilename(nullptr), - CCCPrintBindings(false), - CCPrintHeaders(false), CCLogDiagnostics(false), - CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), - CCCUsePCH(true), SuppressMissingInputWarning(false) { - - Name = llvm::sys::path::stem(ClangExecutable); + : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), + SaveTemps(SaveTempsNone), ClangExecutable(ClangExecutable), + SysRoot(DEFAULT_SYSROOT), UseStdLib(true), + DefaultTargetTriple(DefaultTargetTriple), + DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr), + CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), + CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), + CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), + CCCUsePCH(true), SuppressMissingInputWarning(false) { + + Name = llvm::sys::path::filename(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); // Compute the path to the resource directory. @@ -141,10 +140,8 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) { } } - for (arg_iterator it = Args->filtered_begin(options::OPT_UNKNOWN), - ie = Args->filtered_end(); it != ie; ++it) { - Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args); - } + for (const Arg *A : Args->filtered(options::OPT_UNKNOWN)) + Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args); return Args; } @@ -280,7 +277,8 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // Add a default value of -mlinker-version=, if one was given and the user // didn't specify one. #if defined(HOST_LINK_VERSION) - if (!Args.hasArg(options::OPT_mlinker_version_EQ)) { + if (!Args.hasArg(options::OPT_mlinker_version_EQ) && + strlen(HOST_LINK_VERSION) > 0) { DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ), HOST_LINK_VERSION); DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim(); @@ -348,9 +346,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { DefaultTargetTriple = A->getValue(); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) Dir = InstalledDir = A->getValue(); - for (arg_iterator it = Args->filtered_begin(options::OPT_B), - ie = Args->filtered_end(); it != ie; ++it) { - const Arg *A = *it; + for (const Arg *A : Args->filtered(options::OPT_B)) { A->claim(); PrefixDirs.push_back(A->getValue(0)); } @@ -364,6 +360,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (const Arg *A = Args->getLastArg(options::OPT_resource_dir)) ResourceDir = A->getValue(); + if (const Arg *A = Args->getLastArg(options::OPT_save_temps_EQ)) { + SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue()) + .Case("cwd", SaveTempsCwd) + .Case("obj", SaveTempsObj) + .Default(SaveTempsCwd); + } + // Perform the default argument translations. DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args); @@ -504,7 +507,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // If any of the preprocessing commands failed, clean up and exit. if (!FailingCommands.empty()) { - if (!C.getArgs().hasArg(options::OPT_save_temps)) + if (!isSaveTempsEnabled()) C.CleanupFileList(C.getTempFiles(), true); Diag(clang::diag::note_drv_command_failed_diag_msg) @@ -545,6 +548,9 @@ void Driver::generateCompilationDiagnostics(Compilation &C, Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + EC.message(); } else { + ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" + << "# Original command: "; + Cmd.Print(ScriptOS, "\n", /*Quote=*/true); Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; } @@ -612,7 +618,7 @@ int Driver::ExecuteCompilation(Compilation &C, const Command *FailingCommand = it->second; // Remove result files if we're not saving temps. - if (!C.getArgs().hasArg(options::OPT_save_temps)) { + if (!isSaveTempsEnabled()) { const JobAction *JA = cast<JobAction>(&FailingCommand->getSource()); C.CleanupFileMap(C.getResultFiles(), JA, true); @@ -809,9 +815,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return true; } +// Display an action graph human-readably. Action A is the "sink" node +// and latest-occuring action. Traversal is in pre-order, visiting the +// inputs to each action before printing the action itself. static unsigned PrintActions1(const Compilation &C, Action *A, std::map<Action*, unsigned> &Ids) { - if (Ids.count(A)) + if (Ids.count(A)) // A was already visited. return Ids[A]; std::string str; @@ -842,6 +851,8 @@ static unsigned PrintActions1(const Compilation &C, Action *A, return Id; } +// Print the action graphs in a compilation C. +// For example "clang -c file1.c file2.c" is composed of two subgraphs. void Driver::PrintActions(const Compilation &C) const { std::map<Action*, unsigned> Ids; for (ActionList::const_iterator it = C.getActions().begin(), @@ -970,7 +981,7 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, SmallString<64> Path(Value); if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { - if (!llvm::sys::path::is_absolute(Path.str())) { + if (!llvm::sys::path::is_absolute(Path)) { SmallString<64> Directory(WorkDir->getValue()); llvm::sys::path::append(Directory, Value); Path.assign(Directory); @@ -980,10 +991,11 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, if (llvm::sys::fs::exists(Twine(Path))) return true; - if (D.IsCLMode() && llvm::sys::Process::FindInEnvPath("LIB", Value)) + if (D.IsCLMode() && !llvm::sys::path::is_absolute(Twine(Path)) && + llvm::sys::Process::FindInEnvPath("LIB", Value)) return true; - D.Diag(clang::diag::err_drv_no_such_file) << Path.str(); + D.Diag(clang::diag::err_drv_no_such_file) << Path; return false; } @@ -1264,7 +1276,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, continue; // Otherwise construct the appropriate action. - Current = ConstructPhaseAction(Args, Phase, std::move(Current)); + Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current)); if (Current->getType() == types::TY_Nothing) break; } @@ -1290,7 +1302,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, } std::unique_ptr<Action> -Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, +Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, + phases::ID Phase, std::unique_ptr<Action> Input) const { llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Build the appropriate action. @@ -1371,10 +1384,7 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, } bool Driver::IsUsingLTO(const ArgList &Args) const { - if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false)) - return true; - - return false; + return Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false); } void Driver::BuildJobs(Compilation &C) const { @@ -1453,9 +1463,8 @@ void Driver::BuildJobs(Compilation &C) const { if (Opt.getKind() == Option::FlagClass) { bool DuplicateClaimed = false; - for (arg_iterator it = C.getArgs().filtered_begin(&Opt), - ie = C.getArgs().filtered_end(); it != ie; ++it) { - if ((*it)->isClaimed()) { + for (const Arg *AA : C.getArgs().filtered(&Opt)) { + if (AA->isClaimed()) { DuplicateClaimed = true; break; } @@ -1471,8 +1480,8 @@ void Driver::BuildJobs(Compilation &C) const { } } -static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, - const JobAction *JA, +static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps, + const ToolChain *TC, const JobAction *JA, const ActionList *&Inputs) { const Tool *ToolForJob = nullptr; @@ -1481,7 +1490,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, // compiler input. if (TC->useIntegratedAs() && - !C.getArgs().hasArg(options::OPT_save_temps) && + !SaveTemps && !C.getArgs().hasArg(options::OPT_via_file_asm) && !C.getArgs().hasArg(options::OPT__SLASH_FA) && !C.getArgs().hasArg(options::OPT__SLASH_Fa) && @@ -1512,8 +1521,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, const Tool *Compiler = TC->SelectTool(*CompileJA); if (!Compiler) return nullptr; - if (!Compiler->canEmitIR() || - !C.getArgs().hasArg(options::OPT_save_temps)) { + if (!Compiler->canEmitIR() || !SaveTemps) { Inputs = &(*Inputs)[0]->getInputs(); ToolForJob = Compiler; } @@ -1529,7 +1537,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) && !C.getArgs().hasArg(options::OPT_no_integrated_cpp) && !C.getArgs().hasArg(options::OPT_traditional_cpp) && - !C.getArgs().hasArg(options::OPT_save_temps) && + !SaveTemps && !C.getArgs().hasArg(options::OPT_rewrite_objc) && ToolForJob->hasIntegratedCPP()) Inputs = &(*Inputs)[0]->getInputs(); @@ -1555,8 +1563,9 @@ void Driver::BuildJobsForAction(Compilation &C, if (Input.getOption().matches(options::OPT_INPUT)) { const char *Name = Input.getValue(); Result = InputInfo(Name, A->getType(), Name); - } else + } else { Result = InputInfo(&Input, A->getType(), ""); + } return; } @@ -1577,7 +1586,7 @@ void Driver::BuildJobsForAction(Compilation &C, const ActionList *Inputs = &A->getInputs(); const JobAction *JA = cast<JobAction>(A); - const Tool *T = SelectToolForJob(C, TC, JA, Inputs); + const Tool *T = SelectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs); if (!T) return; @@ -1684,8 +1693,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, assert(AtTopLevel && isa<PreprocessJobAction>(JA)); StringRef BaseName = llvm::sys::path::filename(BaseInput); StringRef NameArg; - if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi, - options::OPT__SLASH_o)) + if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi)) NameArg = A->getValue(); return C.addResultFile(MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C), &JA); @@ -1708,7 +1716,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } // Output to a temporary file? - if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) && + if ((!AtTopLevel && !isSaveTempsEnabled() && !C.getArgs().hasArg(options::OPT__SLASH_Fo)) || CCGenDiagnostics) { StringRef Name = llvm::sys::path::filename(BaseInput); @@ -1780,11 +1788,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C, NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str()); } + // Prepend object file path if -save-temps=obj + if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) && + JA.getType() != types::TY_PCH) { + Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); + SmallString<128> TempPath(FinalOutput->getValue()); + llvm::sys::path::remove_filename(TempPath); + StringRef OutputFileName = llvm::sys::path::filename(NamedOutput); + llvm::sys::path::append(TempPath, OutputFileName); + NamedOutput = C.getArgs().MakeArgString(TempPath.c_str()); + } + // If we're saving temps and the temp file conflicts with the input file, // then avoid overwriting input file. - if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) && - NamedOutput == BaseName) { - + if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) { bool SameFile = false; SmallString<256> Result; llvm::sys::fs::current_path(Result); @@ -1856,8 +1873,8 @@ void Driver::generatePrefixedToolNames(const char *Tool, const ToolChain &TC, SmallVectorImpl<std::string> &Names) const { // FIXME: Needs a better variable than DefaultTargetTriple - Names.push_back(DefaultTargetTriple + "-" + Tool); - Names.push_back(Tool); + Names.emplace_back(DefaultTargetTriple + "-" + Tool); + Names.emplace_back(Tool); } static bool ScanDirForExecutable(SmallString<128> &Dir, @@ -2003,12 +2020,15 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, const ToolChain &Driver::getToolChain(const ArgList &Args, StringRef DarwinArchName) const { - llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args, - DarwinArchName); + llvm::Triple Target = + computeTargetTriple(DefaultTargetTriple, Args, DarwinArchName); ToolChain *&TC = ToolChains[Target.str()]; if (!TC) { switch (Target.getOS()) { + case llvm::Triple::CloudABI: + TC = new toolchains::CloudABI(*this, Target, Args); + break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: @@ -2038,6 +2058,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, else TC = new toolchains::Linux(*this, Target, Args); break; + case llvm::Triple::NaCl: + TC = new toolchains::NaCl_TC(*this, Target, Args); + break; case llvm::Triple::Solaris: TC = new toolchains::Solaris(*this, Target, Args); break; @@ -2069,29 +2092,22 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, } break; default: - // TCE is an OSless target - if (Target.getArchName() == "tce") { + // Of these targets, Hexagon is the only one that might have + // an OS of Linux, in which case it got handled above already. + if (Target.getArchName() == "tce") TC = new toolchains::TCEToolChain(*this, Target, Args); - break; - } - // If Hexagon is configured as an OSless target - if (Target.getArch() == llvm::Triple::hexagon) { + else if (Target.getArch() == llvm::Triple::hexagon) TC = new toolchains::Hexagon_TC(*this, Target, Args); - break; - } - if (Target.getArch() == llvm::Triple::xcore) { + else if (Target.getArch() == llvm::Triple::xcore) TC = new toolchains::XCore(*this, Target, Args); - break; - } - if (Target.isOSBinFormatELF()) { + else if (Target.getArch() == llvm::Triple::shave) + TC = new toolchains::SHAVEToolChain(*this, Target, Args); + else if (Target.isOSBinFormatELF()) TC = new toolchains::Generic_ELF(*this, Target, Args); - break; - } - if (Target.isOSBinFormatMachO()) { + else if (Target.isOSBinFormatMachO()) TC = new toolchains::MachO(*this, Target, Args); - break; - } - TC = new toolchains::Generic_GCC(*this, Target, Args); + else + TC = new toolchains::Generic_GCC(*this, Target, Args); break; } } @@ -2099,13 +2115,12 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, } bool Driver::ShouldUseClangCompiler(const JobAction &JA) const { - // Check if user requested no clang, or clang doesn't understand this type (we - // only handle single inputs for now). + // Say "no" if there is not exactly one input of a type clang understands. if (JA.size() != 1 || !types::isAcceptedByClang((*JA.begin())->getType())) return false; - // Otherwise make sure this is an action clang understands. + // And say "no" if this is not a kind of action clang understands. if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA)) return false; @@ -2125,7 +2140,7 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major, Major = Minor = Micro = 0; if (*Str == '\0') - return true; + return false; char *End; Major = (unsigned) strtol(Str, &End, 10); @@ -2166,6 +2181,6 @@ std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const { return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask); } -bool clang::driver::isOptimizationLevelFast(const llvm::opt::ArgList &Args) { +bool clang::driver::isOptimizationLevelFast(const ArgList &Args) { return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false); } |