diff options
Diffstat (limited to 'lib/Driver/Driver.cpp')
| -rw-r--r-- | lib/Driver/Driver.cpp | 129 | 
1 files changed, 74 insertions, 55 deletions
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1664d0d49d46..65d0049b0b49 100644 --- a/lib/Driver/Driver.cpp +++ b/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. @@ -364,6 +363,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 +510,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 +551,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 +621,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); @@ -970,7 +979,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 +989,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 +1274,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 +1300,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. @@ -1349,7 +1360,7 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,                                                 types::TY_LLVM_BC);    }    case phases::Backend: { -    if (IsUsingLTO(Args)) { +    if (IsUsingLTO(TC, Args)) {        types::ID Output =          Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;        return llvm::make_unique<BackendJobAction>(std::move(Input), Output); @@ -1370,7 +1381,10 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,    llvm_unreachable("invalid phase in ConstructPhaseAction");  } -bool Driver::IsUsingLTO(const ArgList &Args) const { +bool Driver::IsUsingLTO(const ToolChain &TC, const ArgList &Args) const { +  if (TC.getSanitizerArgs().needsLTO()) +    return true; +    if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false))      return true; @@ -1471,8 +1485,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 +1495,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 +1526,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 +1542,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(); @@ -1577,7 +1590,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; @@ -1708,7 +1721,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 +1793,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); @@ -2003,12 +2025,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 +2063,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 +2097,20 @@ 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.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;      }    } @@ -2125,7 +2144,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);  | 
