diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Action.cpp | 9 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ArgList.cpp | 53 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Compilation.cpp | 45 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 367 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Job.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/OptTable.cpp | 13 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Option.cpp | 12 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Phases.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp | 34 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 792 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.h | 27 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 880 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.h | 16 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Types.cpp | 10 |
15 files changed, 1502 insertions, 768 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp index 549ce0a..52c0dbb 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Action.h" +#include "llvm/Support/ErrorHandling.h" #include <cassert> using namespace clang::driver; @@ -31,10 +32,10 @@ const char *Action::getClassName(ActionClass AC) { case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; case DsymutilJobClass: return "dsymutil"; + case VerifyJobClass: return "verify"; } - assert(0 && "invalid class"); - return 0; + llvm_unreachable("invalid class"); } InputAction::InputAction(const Arg &_Input, types::ID _Type) @@ -84,3 +85,7 @@ LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type) DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) : JobAction(DsymutilJobClass, Inputs, Type) { } + +VerifyJobAction::VerifyJobAction(ActionList &Inputs, types::ID Type) + : JobAction(VerifyJobClass, Inputs, Type) { +} diff --git a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp index b8af9cc..ca9b944 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp @@ -46,6 +46,17 @@ void ArgList::append(Arg *A) { Args.push_back(A); } +void ArgList::eraseArg(OptSpecifier Id) { + for (iterator it = begin(), ie = end(); it != ie; ) { + if ((*it)->getOption().matches(Id)) { + it = Args.erase(it); + ie = end(); + } else { + ++it; + } + } +} + Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { // FIXME: Make search efficient? for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) @@ -117,19 +128,19 @@ bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { return Default; } -llvm::StringRef ArgList::getLastArgValue(OptSpecifier Id, - llvm::StringRef Default) const { +StringRef ArgList::getLastArgValue(OptSpecifier Id, + StringRef Default) const { if (Arg *A = getLastArg(Id)) return A->getValue(*this); return Default; } int ArgList::getLastArgIntValue(OptSpecifier Id, int Default, - clang::Diagnostic &Diags) const { + clang::DiagnosticsEngine &Diags) const { int Res = Default; if (Arg *A = getLastArg(Id)) { - if (llvm::StringRef(A->getValue(*this)).getAsInteger(10, Res)) + if (StringRef(A->getValue(*this)).getAsInteger(10, Res)) Diags.Report(diag::err_drv_invalid_int_value) << A->getAsString(*this) << A->getValue(*this); } @@ -138,7 +149,7 @@ int ArgList::getLastArgIntValue(OptSpecifier Id, int Default, } std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const { - llvm::SmallVector<const char *, 16> Values; + SmallVector<const char *, 16> Values; AddAllArgValues(Values, Id); return std::vector<std::string>(Values.begin(), Values.end()); } @@ -177,7 +188,7 @@ void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, (*it)->claim(); if (Joined) { - Output.push_back(MakeArgString(llvm::StringRef(Translation) + + Output.push_back(MakeArgString(StringRef(Translation) + (*it)->getValue(*this, 0))); } else { Output.push_back(Translation); @@ -192,16 +203,22 @@ void ArgList::ClaimAllArgs(OptSpecifier Id0) const { (*it)->claim(); } -const char *ArgList::MakeArgString(const llvm::Twine &T) const { +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); return MakeArgString(Str.str()); } const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, - llvm::StringRef LHS, - llvm::StringRef RHS) const { - llvm::StringRef Cur = getArgString(Index); + StringRef LHS, + StringRef RHS) const { + StringRef Cur = getArgString(Index); if (Cur.size() == LHS.size() + RHS.size() && Cur.startswith(LHS) && Cur.endswith(RHS)) return Cur.data(); @@ -223,7 +240,7 @@ InputArgList::~InputArgList() { delete *it; } -unsigned InputArgList::MakeIndex(llvm::StringRef String0) const { +unsigned InputArgList::MakeIndex(StringRef String0) const { unsigned Index = ArgStrings.size(); // Tuck away so we have a reliable const char *. @@ -233,8 +250,8 @@ unsigned InputArgList::MakeIndex(llvm::StringRef String0) const { return Index; } -unsigned InputArgList::MakeIndex(llvm::StringRef String0, - llvm::StringRef String1) const { +unsigned InputArgList::MakeIndex(StringRef String0, + StringRef String1) const { unsigned Index0 = MakeIndex(String0); unsigned Index1 = MakeIndex(String1); assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!"); @@ -242,7 +259,7 @@ unsigned InputArgList::MakeIndex(llvm::StringRef String0, return Index0; } -const char *InputArgList::MakeArgString(llvm::StringRef Str) const { +const char *InputArgList::MakeArgString(StringRef Str) const { return getArgString(MakeIndex(Str)); } @@ -259,7 +276,7 @@ DerivedArgList::~DerivedArgList() { delete *it; } -const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const { +const char *DerivedArgList::MakeArgString(StringRef Str) const { return BaseArgs.MakeArgString(Str); } @@ -270,7 +287,7 @@ Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const { } Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt, - llvm::StringRef Value) const { + StringRef Value) const { unsigned Index = BaseArgs.MakeIndex(Value); Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index), BaseArg); SynthesizedArgs.push_back(A); @@ -278,7 +295,7 @@ Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt, } Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt, - llvm::StringRef Value) const { + StringRef Value) const { unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value); Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index + 1), BaseArg); SynthesizedArgs.push_back(A); @@ -286,7 +303,7 @@ Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt, } Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt, - llvm::StringRef Value) const { + StringRef Value) const { unsigned Index = BaseArgs.MakeIndex(Opt->getName().str() + Value.str()); Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index) + Opt->getName().size(), diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index 2657faa..d02da95 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -16,16 +16,19 @@ #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> #include <errno.h> + using namespace clang::driver; +using namespace clang; 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() { @@ -43,6 +46,13 @@ Compilation::~Compilation() { 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, @@ -60,14 +70,14 @@ const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC, return *Entry; } -void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J, +void Compilation::PrintJob(raw_ostream &OS, const Job &J, const char *Terminator, bool Quote) const { if (const Command *C = dyn_cast<Command>(&J)) { OS << " \"" << C->getExecutable() << '"'; for (ArgStringList::const_iterator it = C->getArguments().begin(), ie = C->getArguments().end(); it != ie; ++it) { OS << ' '; - if (!Quote) { + if (!Quote && !std::strpbrk(*it, " \"\\$")) { OS << *it; continue; } @@ -135,9 +145,9 @@ int Compilation::ExecuteCommand(const Command &C, 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)) { - llvm::raw_ostream *OS = &llvm::errs(); + 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 // output stream. @@ -167,7 +177,7 @@ int Compilation::ExecuteCommand(const Command &C, 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()) { @@ -195,3 +205,24 @@ int Compilation::ExecuteJob(const Job &J, 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(); +} diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 0860572..4e2d7b6 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -25,7 +25,6 @@ #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" -#include "clang/Driver/Types.h" #include "clang/Basic/Version.h" @@ -33,6 +32,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/FileSystem.h" @@ -46,11 +46,11 @@ using namespace clang::driver; using namespace clang; -Driver::Driver(llvm::StringRef ClangExecutable, - llvm::StringRef DefaultHostTriple, - llvm::StringRef DefaultImageName, - bool IsProduction, bool CXXIsProduction, - Diagnostic &Diags) +Driver::Driver(StringRef ClangExecutable, + StringRef DefaultHostTriple, + StringRef DefaultImageName, + bool IsProduction, + DiagnosticsEngine &Diags) : Opts(createDriverOptTable()), Diags(Diags), ClangExecutable(ClangExecutable), UseStdLib(true), DefaultHostTriple(DefaultHostTriple), DefaultImageName(DefaultImageName), @@ -60,9 +60,9 @@ Driver::Driver(llvm::StringRef ClangExecutable, 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++. @@ -73,16 +73,13 @@ Driver::Driver(llvm::StringRef ClangExecutable, CCCClangArchs.insert(llvm::Triple::x86); CCCClangArchs.insert(llvm::Triple::x86_64); CCCClangArchs.insert(llvm::Triple::arm); - - if (!CXXIsProduction) - CCCUseClangCXX = false; } Name = llvm::sys::path::stem(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); // Compute the path to the resource directory. - llvm::StringRef ClangResourceDir(CLANG_RESOURCE_DIR); + StringRef ClangResourceDir(CLANG_RESOURCE_DIR); llvm::SmallString<128> P(Dir); if (ClangResourceDir != "") llvm::sys::path::append(P, ClangResourceDir); @@ -96,7 +93,7 @@ Driver::~Driver() { delete Host; } -InputArgList *Driver::ParseArgStrings(llvm::ArrayRef<const char *> ArgList) { +InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned MissingArgIndex, MissingArgCount; InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(), @@ -120,6 +117,43 @@ InputArgList *Driver::ParseArgStrings(llvm::ArrayRef<const char *> ArgList) { return Args; } +// Determine which compilation mode we are in. We look for options which +// affect the phase, starting with the earliest phases, and record which +// option we used to determine the final phase. +phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg) +const { + Arg *PhaseArg = 0; + phases::ID FinalPhase; + + // -{E,M,MM} only run the preprocessor. + if (CCCIsCPP || + (PhaseArg = DAL.getLastArg(options::OPT_E)) || + (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) { + FinalPhase = phases::Preprocess; + + // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT__analyze, + options::OPT__analyze_auto)) || + (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) || + (PhaseArg = DAL.getLastArg(options::OPT_S))) { + FinalPhase = phases::Compile; + + // -c only runs up to the assembler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) { + FinalPhase = phases::Assemble; + + // Otherwise do everything. + } else + FinalPhase = phases::Link; + + if (FinalPhaseArg) + *FinalPhaseArg = PhaseArg; + + return FinalPhase; +} + DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { DerivedArgList *DAL = new DerivedArgList(Args); @@ -142,7 +176,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // Add the remaining values as Xlinker arguments. for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) - if (llvm::StringRef(A->getValue(Args, i)) != "--no-demangle") + if (StringRef(A->getValue(Args, i)) != "--no-demangle") DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker), A->getValue(Args, i)); @@ -154,10 +188,10 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // care to encourage this usage model. if (A->getOption().matches(options::OPT_Wp_COMMA) && A->getNumValues() == 2 && - (A->getValue(Args, 0) == llvm::StringRef("-MD") || - A->getValue(Args, 0) == llvm::StringRef("-MMD"))) { + (A->getValue(Args, 0) == StringRef("-MD") || + A->getValue(Args, 0) == StringRef("-MMD"))) { // Rewrite to -MD/-MMD along with -MF. - if (A->getValue(Args, 0) == llvm::StringRef("-MD")) + if (A->getValue(Args, 0) == StringRef("-MD")) DAL->AddFlagArg(A, Opts->getOption(options::OPT_MD)); else DAL->AddFlagArg(A, Opts->getOption(options::OPT_MMD)); @@ -168,7 +202,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // Rewrite reserved library names. if (A->getOption().matches(options::OPT_l)) { - llvm::StringRef Value = A->getValue(Args); + StringRef Value = A->getValue(Args); // Rewrite unless -nostdlib is present. if (!HasNostdlib && Value == "stdc++") { @@ -201,12 +235,20 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { return DAL; } -Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) { +Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); - // FIXME: Handle environment options which effect driver behavior, somewhere - // (client?). GCC_EXEC_PREFIX, COMPILER_PATH, LIBRARY_PATH, LPATH, - // CC_PRINT_OPTIONS. + // FIXME: Handle environment options which affect driver behavior, somewhere + // (client?). GCC_EXEC_PREFIX, LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS. + + if (char *env = ::getenv("COMPILER_PATH")) { + StringRef CompilerPath = env; + while (!CompilerPath.empty()) { + std::pair<StringRef, StringRef> Split = CompilerPath.split(':'); + PrefixDirs.push_back(Split.first); + CompilerPath = Split.second; + } + } // FIXME: What are we going to do with -V and -b? @@ -242,11 +284,11 @@ Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) { CCCUseClang = !Args->hasArg(options::OPT_ccc_no_clang); CCCUseClangCPP = !Args->hasArg(options::OPT_ccc_no_clang_cpp); if (const Arg *A = Args->getLastArg(options::OPT_ccc_clang_archs)) { - llvm::StringRef Cur = A->getValue(*Args); + StringRef Cur = A->getValue(*Args); CCCClangArchs.clear(); while (!Cur.empty()) { - std::pair<llvm::StringRef, llvm::StringRef> Split = Cur.split(','); + std::pair<StringRef, StringRef> Split = Cur.split(','); if (!Split.first.empty()) { llvm::Triple::ArchType Arch = @@ -296,12 +338,17 @@ Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) { if (!HandleImmediateArgs(*C)) return C; + // Construct the list of inputs. + InputList Inputs; + BuildInputs(C->getDefaultToolChain(), C->getArgs(), Inputs); + // Construct the list of abstract actions to perform for this compilation. if (Host->useDriverDriver()) BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(), - C->getActions()); + Inputs, C->getActions()); else - BuildActions(C->getDefaultToolChain(), C->getArgs(), C->getActions()); + BuildActions(C->getDefaultToolChain(), C->getArgs(), Inputs, + C->getActions()); if (CCCPrintActions) { PrintActions(*C); @@ -313,7 +360,112 @@ Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) { 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(); + Diags.Reset(); + + // Construct the list of inputs. + InputList Inputs; + BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs); + + for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) { + bool IgnoreInput = false; + + // Ignore input from stdin or any inputs that cannot be preprocessed. + if (!strcmp(it->second->getValue(C.getArgs()), "-")) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s) - ignoring input from stdin" + "."; + IgnoreInput = true; + } else if (types::getPreprocessedType(it->first) == types::TY_INVALID) { + IgnoreInput = true; + } + + if (IgnoreInput) { + it = Inputs.erase(it); + ie = Inputs.end(); + } else { + ++it; + } + } + + // Don't attempt to generate preprocessed files if multiple -arch options are + // used. + int Archs = 0; + for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); + it != ie; ++it) { + Arg *A = *it; + if (A->getOption().matches(options::OPT_arch)) { + Archs++; + if (Archs > 1) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s) - cannot generate " + "preprocessed source with multiple -arch options."; + return; + } + } + } + + if (Inputs.empty()) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s) - no preprocessable inputs."; + return; + } + + // Construct the list of abstract actions to perform for this compilation. + if (Host->useDriverDriver()) + BuildUniversalActions(C.getDefaultToolChain(), C.getArgs(), + Inputs, C.getActions()); + else + BuildActions(C.getDefaultToolChain(), C.getArgs(), Inputs, + 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); @@ -321,10 +473,9 @@ int Driver::ExecuteCompilation(const Compilation &C) const { } // 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. @@ -382,7 +533,7 @@ void Driver::PrintHelp(bool ShowHidden) const { ShowHidden); } -void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const { +void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { // FIXME: The following handlers should use a callback mechanism, we don't // know what the client would like to do. OS << getClangFullVersion() << '\n'; @@ -397,7 +548,7 @@ void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const { /// PrintDiagnosticCategories - Implement the --print-diagnostic-categories /// option. -static void PrintDiagnosticCategories(llvm::raw_ostream &OS) { +static void PrintDiagnosticCategories(raw_ostream &OS) { // Skip the empty category. for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max; ++i) @@ -457,7 +608,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { llvm::outs() << *it; } llvm::outs() << "\n"; - llvm::outs() << "libraries: ="; + llvm::outs() << "libraries: =" << ResourceDir; std::string sysroot; if (Arg *A = C.getArgs().getLastArg(options::OPT__sysroot_EQ)) @@ -465,8 +616,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(), ie = TC.getFilePaths().end(); it != ie; ++it) { - if (it != TC.getFilePaths().begin()) - llvm::outs() << ':'; + llvm::outs() << ':'; const char *path = it->c_str(); if (path[0] == '=') llvm::outs() << sysroot << path + 1; @@ -594,12 +744,13 @@ static bool ContainsCompileOrAssembleAction(const Action *A) { void Driver::BuildUniversalActions(const ToolChain &TC, const DerivedArgList &Args, + const InputList &BAInputs, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building universal build actions"); // Collect the list of architectures. Duplicates are allowed, but should only // be handled once (in the order seen). llvm::StringSet<> ArchNames; - llvm::SmallVector<const char *, 4> Archs; + SmallVector<const char *, 4> Archs; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { Arg *A = *it; @@ -638,7 +789,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, } ActionList SingleActions; - BuildActions(TC, Args, SingleActions); + BuildActions(TC, Args, BAInputs, SingleActions); // Add in arch bindings for every top level action, as well as lipo and // dsymutil steps if needed. @@ -683,23 +834,33 @@ void Driver::BuildUniversalActions(const ToolChain &TC, Actions.pop_back(); Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); + + // Verify the debug output if we're in assert mode. + // TODO: The verifier is noisy by default so put this under an + // option for now. + #ifndef NDEBUG + if (Args.hasArg(options::OPT_verify)) { + ActionList VerifyInputs; + VerifyInputs.push_back(Actions.back()); + Actions.pop_back(); + Actions.push_back(new VerifyJobAction(VerifyInputs, + types::TY_Nothing)); + } + #endif } } } } -void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, - ActionList &Actions) const { - llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); - // Start by constructing the list of inputs and their types. - +// Construct a the list of inputs and their types. +void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, + InputList &Inputs) const { // Track the current user specified (-x) input. We also explicitly track the // argument used to set the type; we only want to claim the type when we // actually use it, so we warn about unused -x arguments. types::ID InputType = types::TY_Nothing; Arg *InputTypeArg = 0; - llvm::SmallVector<std::pair<types::ID, const Arg*>, 16> Inputs; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { Arg *A = *it; @@ -803,7 +964,6 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, } } } - if (CCCIsCPP && Inputs.empty()) { // If called as standalone preprocessor, stdin is processed // if no other input is present. @@ -812,40 +972,19 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, A->claim(); Inputs.push_back(std::make_pair(types::TY_C, A)); } +} + +void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, + const InputList &Inputs, ActionList &Actions) const { + llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); if (!SuppressMissingInputWarning && Inputs.empty()) { Diag(clang::diag::err_drv_no_input_files); return; } - // Determine which compilation mode we are in. We look for options which - // affect the phase, starting with the earliest phases, and record which - // option we used to determine the final phase. - Arg *FinalPhaseArg = 0; - phases::ID FinalPhase; - - // -{E,M,MM} only run the preprocessor. - if (CCCIsCPP || - (FinalPhaseArg = Args.getLastArg(options::OPT_E)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) { - FinalPhase = phases::Preprocess; - - // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. - } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_rewrite_objc)) || - (FinalPhaseArg = Args.getLastArg(options::OPT__analyze, - options::OPT__analyze_auto)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_emit_ast)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_S))) { - FinalPhase = phases::Compile; - - // -c only runs up to the assembler. - } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) { - FinalPhase = phases::Assemble; - - // Otherwise do everything. - } else - FinalPhase = phases::Link; + Arg *FinalPhaseArg; + phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); // Reject -Z* at the top level, these options should never have been exposed // by gcc. @@ -935,7 +1074,7 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Build the appropriate action. switch (Phase) { - case phases::Link: assert(0 && "link action invalid here."); + case phases::Link: llvm_unreachable("link action invalid here."); case phases::Preprocess: { types::ID OutputTy; // -{M, MM} alter the output type. @@ -971,8 +1110,7 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, return new AssembleJobAction(Input, types::TY_Object); } - assert(0 && "invalid phase in ConstructPhaseAction"); - return 0; + llvm_unreachable("invalid phase in ConstructPhaseAction"); } bool Driver::IsUsingLTO(const ArgList &Args) const { @@ -1048,7 +1186,8 @@ void Driver::BuildJobs(Compilation &C) const { Arg *A = *it; // FIXME: It would be nice to be able to send the argument to the - // Diagnostic, so that extra values, position, and so on could be printed. + // DiagnosticsEngine, so that extra values, position, and so on could be + // printed. if (!A->isClaimed()) { if (A->getOption().hasNoArgumentUnused()) continue; @@ -1091,7 +1230,7 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) || C.getArgs().hasArg(options::OPT_static) || C.getArgs().hasArg(options::OPT_fapple_kext)); - bool IsDarwin = TC->getTriple().getOS() == llvm::Triple::Darwin; + bool IsDarwin = TC->getTriple().isOSDarwin(); bool IsIADefault = TC->IsIntegratedAssemblerDefault() && !(HasStatic && IsDarwin); if (C.getArgs().hasFlag(options::OPT_integrated_as, @@ -1176,6 +1315,11 @@ void Driver::BuildJobsForAction(Compilation &C, if (AtTopLevel && isa<DsymutilJobAction>(A)) SubJobAtTopLevel = true; + // Also treat verify sub-jobs as being at the top-level. They don't + // produce any output and so don't need temporary output names. + if (AtTopLevel && isa<VerifyJobAction>(A)) + SubJobAtTopLevel = true; + InputInfo II; BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, LinkingOutput, II); @@ -1198,7 +1342,7 @@ void Driver::BuildJobsForAction(Compilation &C, 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) { @@ -1219,27 +1363,31 @@ const char *Driver::GetNamedOutputPath(Compilation &C, bool AtTopLevel) const { llvm::PrettyStackTraceString CrashInfo("Computing output path"); // Output to a user requested destination? - if (AtTopLevel && !isa<DsymutilJobAction>(JA)) { + if (AtTopLevel && !isa<DsymutilJobAction>(JA) && + !isa<VerifyJobAction>(JA)) { if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) return C.addResultFile(FinalOutput->getValue(C.getArgs())); } // 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) { + StringRef Name = llvm::sys::path::filename(BaseInput); + std::pair<StringRef, StringRef> Split = Name.split('.'); std::string TmpName = - GetTemporaryPath(types::getTypeTempSuffix(JA.getType())); + GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType())); return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); } llvm::SmallString<128> BasePath(BaseInput); - llvm::StringRef BaseName; + StringRef BaseName; // Dsymutil actions should use the full path. - if (isa<DsymutilJobAction>(JA)) + if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA)) BaseName = BasePath; else BaseName = llvm::sys::path::filename(BasePath); @@ -1261,12 +1409,14 @@ const char *Driver::GetNamedOutputPath(Compilation &C, NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str()); } - // If we're saving temps and the temp filename conflicts with the input + // If we're saving temps and the temp filename conflicts with the input // filename, then avoid overwriting input file. if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) && - NamedOutput == BaseName) { + NamedOutput == BaseName) { + StringRef Name = llvm::sys::path::filename(BaseInput); + std::pair<StringRef, StringRef> Split = Name.split('.'); std::string TmpName = - GetTemporaryPath(types::getTypeTempSuffix(JA.getType())); + GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType())); return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); } @@ -1300,6 +1450,12 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { return P.str(); } + llvm::sys::Path P(ResourceDir); + P.appendComponent(Name); + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) + return P.str(); + const ToolChain::path_list &List = TC.getFilePaths(); for (ToolChain::path_list::const_iterator it = List.begin(), ie = List.end(); it != ie; ++it) { @@ -1318,40 +1474,53 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { return Name; } +static bool isPathExecutable(llvm::sys::Path &P, bool WantFile) { + bool Exists; + return (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists + : P.canExecute()); +} + std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, bool WantFile) const { + std::string TargetSpecificExecutable(DefaultHostTriple + "-" + Name); // Respect a limited subset of the '-Bprefix' functionality in GCC by // attempting to use this prefix when lokup up program paths. for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), ie = PrefixDirs.end(); it != ie; ++it) { llvm::sys::Path P(*it); + P.appendComponent(TargetSpecificExecutable); + if (isPathExecutable(P, WantFile)) return P.str(); + P.eraseComponent(); P.appendComponent(Name); - bool Exists; - if (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists - : P.canExecute()) - return P.str(); + if (isPathExecutable(P, WantFile)) return P.str(); } const ToolChain::path_list &List = TC.getProgramPaths(); for (ToolChain::path_list::const_iterator it = List.begin(), ie = List.end(); it != ie; ++it) { llvm::sys::Path P(*it); + P.appendComponent(TargetSpecificExecutable); + if (isPathExecutable(P, WantFile)) return P.str(); + P.eraseComponent(); P.appendComponent(Name); - bool Exists; - if (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists - : P.canExecute()) - return P.str(); + if (isPathExecutable(P, WantFile)) return P.str(); } // If all else failed, search the path. - llvm::sys::Path P(llvm::sys::Program::FindProgramByName(Name)); + llvm::sys::Path + P(llvm::sys::Program::FindProgramByName(TargetSpecificExecutable)); + if (!P.empty()) + return P.str(); + + P = llvm::sys::Path(llvm::sys::Program::FindProgramByName(Name)); if (!P.empty()) return P.str(); return Name; } -std::string Driver::GetTemporaryPath(const char *Suffix) const { +std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) + const { // FIXME: This is lame; sys::Path should provide this function (in particular, // it should know how to find the temporary files dir). std::string Error; @@ -1363,7 +1532,7 @@ std::string Driver::GetTemporaryPath(const char *Suffix) const { if (!TmpDir) TmpDir = "/tmp"; llvm::sys::Path P(TmpDir); - P.appendComponent("cc"); + P.appendComponent(Prefix); if (P.makeUnique(false, &Error)) { Diag(clang::diag::err_drv_unable_to_make_temp) << Error; return ""; @@ -1388,6 +1557,8 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { case llvm::Triple::AuroraUX: return createAuroraUXHostInfo(*this, Triple); case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: return createDarwinHostInfo(*this, Triple); case llvm::Triple::DragonFly: return createDragonFlyHostInfo(*this, Triple); diff --git a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp index 3b1c2c7..292678b 100644 --- a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp @@ -188,7 +188,7 @@ bool UnknownHostInfo::useDriverDriver() const { ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, const char *ArchName) const { assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); + "Unexpected arch name on platform without driver support."); // Automatically handle some instances of -m32/-m64 we know about. std::string Arch = getArchName(); diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp index 51055e9..5443d70 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp @@ -9,6 +9,8 @@ #include "clang/Driver/Job.h" +#include "llvm/ADT/STLExtras.h" + #include <cassert> using namespace clang::driver; @@ -28,6 +30,10 @@ JobList::~JobList() { delete *it; } +void JobList::clear() { + DeleteContainerPointers(Jobs); +} + void Job::addCommand(Command *C) { cast<JobList>(this)->addJob(C); } diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp index 0252b3e..4f5390b 100644 --- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp @@ -12,11 +12,12 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" #include <algorithm> -#include <cassert> #include <map> using namespace clang::driver; using namespace clang::driver::options; +using namespace clang; // Ordering on Info. The ordering is *almost* lexicographic, with two // exceptions. First, '\0' comes at the end of the alphabet instead of @@ -116,7 +117,7 @@ OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) if (!(getInfo(i) < getInfo(i + 1))) { getOption(i)->dump(); getOption(i + 1)->dump(); - assert(0 && "Options are not in order!"); + llvm_unreachable("Options are not in order!"); } } #endif @@ -268,10 +269,10 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { // Add metavar, if used. switch (Opts.getOptionKind(Id)) { case Option::GroupClass: case Option::InputClass: case Option::UnknownClass: - assert(0 && "Invalid option with help text."); + llvm_unreachable("Invalid option with help text."); case Option::MultiArgClass: - assert(0 && "Cannot print metavar for this kind of option."); + llvm_unreachable("Cannot print metavar for this kind of option."); case Option::FlagClass: break; @@ -291,7 +292,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { return Name; } -static void PrintHelpOptionList(llvm::raw_ostream &OS, llvm::StringRef Title, +static void PrintHelpOptionList(raw_ostream &OS, StringRef Title, std::vector<std::pair<std::string, const char*> > &OptionHelp) { OS << Title << ":\n"; @@ -342,7 +343,7 @@ static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) { return getOptionHelpGroup(Opts, GroupID); } -void OptTable::PrintHelp(llvm::raw_ostream &OS, const char *Name, +void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title, bool ShowHidden) const { OS << "OVERVIEW: " << Title << "\n"; OS << '\n'; diff --git a/contrib/llvm/tools/clang/lib/Driver/Option.cpp b/contrib/llvm/tools/clang/lib/Driver/Option.cpp index 90d21a3..ee1963f 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Option.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Option.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" #include <cassert> #include <algorithm> using namespace clang::driver; @@ -61,7 +62,7 @@ void Option::dump() const { llvm::errs() << "<"; switch (Kind) { default: - assert(0 && "Invalid kind"); + llvm_unreachable("Invalid kind"); #define P(N) case N: llvm::errs() << #N; break P(GroupClass); P(InputClass); @@ -114,8 +115,7 @@ OptionGroup::OptionGroup(OptSpecifier ID, const char *Name, } Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const { - assert(0 && "accept() should never be called on an OptionGroup"); - return 0; + llvm_unreachable("accept() should never be called on an OptionGroup"); } InputOption::InputOption(OptSpecifier ID) @@ -123,8 +123,7 @@ InputOption::InputOption(OptSpecifier ID) } Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const { - assert(0 && "accept() should never be called on an InputOption"); - return 0; + llvm_unreachable("accept() should never be called on an InputOption"); } UnknownOption::UnknownOption(OptSpecifier ID) @@ -132,8 +131,7 @@ UnknownOption::UnknownOption(OptSpecifier ID) } Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const { - assert(0 && "accept() should never be called on an UnknownOption"); - return 0; + llvm_unreachable("accept() should never be called on an UnknownOption"); } FlagOption::FlagOption(OptSpecifier ID, const char *Name, diff --git a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp index f360002..b885eee 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Phases.h" +#include "llvm/Support/ErrorHandling.h" #include <cassert> @@ -22,6 +23,5 @@ const char *phases::getPhaseName(ID Id) { case Link: return "linker"; } - assert(0 && "Invalid phase id."); - return 0; + llvm_unreachable("Invalid phase id."); } diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index 74b6591..d09ab16 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -18,11 +18,11 @@ #include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/Options.h" #include "llvm/Support/ErrorHandling.h" - using namespace clang::driver; +using namespace clang; -ToolChain::ToolChain(const HostInfo &_Host, const llvm::Triple &_Triple) - : Host(_Host), Triple(_Triple) { +ToolChain::ToolChain(const HostInfo &H, const llvm::Triple &T) + : Host(H), Triple(T) { } ToolChain::~ToolChain() { @@ -79,7 +79,7 @@ static const char *getARMTargetCPU(const ArgList &Args, if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(Args); - llvm::StringRef MArch; + StringRef MArch; if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { // Otherwise, if we have -march= choose the base CPU for that arch. MArch = A->getValue(Args); @@ -134,7 +134,7 @@ static const char *getARMTargetCPU(const ArgList &Args, // // FIXME: This is redundant with -mcpu, why does LLVM use this. // FIXME: tblgen this, or kill it! -static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) { +static const char *getLLVMArchSuffixForARM(StringRef CPU) { if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" || CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" || CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" || @@ -169,7 +169,8 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) { return ""; } -std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const { +std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, + types::ID InputType) const { switch (getTriple().getArch()) { default: return getTripleString(); @@ -182,12 +183,14 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const { // Thumb2 is the default for V7 on Darwin. // // FIXME: Thumb should just be another -target-feaure, not in the triple. - llvm::StringRef Suffix = + StringRef Suffix = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); - bool ThumbDefault = - (Suffix == "v7" && getTriple().getOS() == llvm::Triple::Darwin); + bool ThumbDefault = (Suffix == "v7" && getTriple().isOSDarwin()); std::string ArchName = "arm"; - if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) + + // Assembly files should start in ARM mode. + if (InputType != types::TY_PP_Asm && + Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) ArchName = "thumb"; Triple.setArchName(ArchName + Suffix.str()); @@ -196,25 +199,26 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const { } } -std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const { +std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { // Diagnose use of Darwin OS deployment target arguments on non-Darwin. if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, options::OPT_miphoneos_version_min_EQ, options::OPT_mios_simulator_version_min_EQ)) - getDriver().Diag(clang::diag::err_drv_clang_unsupported) + getDriver().Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); - return ComputeLLVMTriple(Args); + return ComputeLLVMTriple(Args, InputType); } ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { - llvm::StringRef Value = A->getValue(Args); + StringRef Value = A->getValue(Args); if (Value == "libc++") return ToolChain::CST_Libcxx; if (Value == "libstdc++") return ToolChain::CST_Libstdcxx; - getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name) + getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); } diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 29abb6d..4c62543 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -27,6 +27,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -45,12 +46,14 @@ using namespace clang::driver; using namespace clang::driver::toolchains; +using namespace clang; /// Darwin - Darwin tool chain for i386 and x86_64. Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple) : ToolChain(Host, Triple), TargetInitialized(false), - ARCRuntimeForSimulator(ARCSimulator_None) + ARCRuntimeForSimulator(ARCSimulator_None), + LibCXXForSimulator(LibCXXSimulator_None) { // Compute the initial Darwin version based on the host. bool HadExtra; @@ -58,7 +61,7 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple) if (!Driver::GetReleaseVersion(&OSName.c_str()[6], DarwinVersion[0], DarwinVersion[1], DarwinVersion[2], HadExtra)) - getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName; + getDriver().Diag(diag::err_drv_invalid_darwin_version) << OSName; llvm::raw_string_ostream(MacosxVersionMin) << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.' @@ -112,52 +115,40 @@ void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const { runtime.HasTerminate = false; } -// FIXME: Can we tablegen this? -static const char *GetArmArchForMArch(llvm::StringRef Value) { - if (Value == "armv6k") - return "armv6"; - - if (Value == "armv5tej") - return "armv5"; - - if (Value == "xscale") - return "xscale"; - - if (Value == "armv4t") - return "armv4t"; - - if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" || - Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" || - Value == "armv7m") - return "armv7"; - - return 0; -} - -// FIXME: Can we tablegen this? -static const char *GetArmArchForMCpu(llvm::StringRef Value) { - if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" || - Value == "arm946e-s" || Value == "arm966e-s" || - Value == "arm968e-s" || Value == "arm10e" || - Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" || - Value == "arm1026ej-s") - return "armv5"; - - if (Value == "xscale") - return "xscale"; - - if (Value == "arm1136j-s" || Value == "arm1136jf-s" || - Value == "arm1176jz-s" || Value == "arm1176jzf-s" || - Value == "cortex-m0" ) - return "armv6"; - - if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3") - return "armv7"; - - return 0; -} - -llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const { +/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. +bool Darwin::hasBlocksRuntime() const { + if (isTargetIPhoneOS()) + return !isIPhoneOSVersionLT(3, 2); + else + return !isMacosxVersionLT(10, 6); +} + +static const char *GetArmArchForMArch(StringRef Value) { + return llvm::StringSwitch<const char*>(Value) + .Case("armv6k", "armv6") + .Case("armv5tej", "armv5") + .Case("xscale", "xscale") + .Case("armv4t", "armv4t") + .Case("armv7", "armv7") + .Cases("armv7a", "armv7-a", "armv7") + .Cases("armv7r", "armv7-r", "armv7") + .Cases("armv7m", "armv7-m", "armv7") + .Default(0); +} + +static const char *GetArmArchForMCpu(StringRef Value) { + return llvm::StringSwitch<const char *>(Value) + .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "arm926ej-s","armv5") + .Cases("arm10e", "arm10tdmi", "armv5") + .Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5") + .Case("xscale", "xscale") + .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", + "arm1176jzf-s", "cortex-m0", "armv6") + .Cases("cortex-a8", "cortex-r4", "cortex-m3", "cortex-a9", "armv7") + .Default(0); +} + +StringRef Darwin::getDarwinArchName(const ArgList &Args) const { switch (getTriple().getArch()) { default: return getArchName(); @@ -184,8 +175,9 @@ Darwin::~Darwin() { delete it->second; } -std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const { - llvm::Triple Triple(ComputeLLVMTriple(Args)); +std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { + llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); // If the target isn't initialized (e.g., an unknown Darwin platform, return // the default triple). @@ -212,9 +204,10 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, // Fallback to llvm-gcc for i386 kext compiles, we don't support that ABI. if (Inputs.size() == 1 && types::isCXX(Inputs[0]->getType()) && - getTriple().getOS() == llvm::Triple::Darwin && + getTriple().isOSDarwin() && getTriple().getArch() == llvm::Triple::x86 && - C.getArgs().getLastArg(options::OPT_fapple_kext)) + (C.getArgs().getLastArg(options::OPT_fapple_kext) || + C.getArgs().getLastArg(options::OPT_mkernel))) Key = JA.getKind(); else Key = Action::AnalyzeJobClass; @@ -236,7 +229,7 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, switch (Key) { case Action::InputClass: case Action::BindArchClass: - assert(0 && "Invalid tool kind."); + llvm_unreachable("Invalid tool kind."); case Action::PreprocessJobClass: T = new tools::darwin::Preprocess(*this); break; case Action::AnalyzeJobClass: @@ -257,6 +250,8 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, T = new tools::darwin::Lipo(*this); break; case Action::DsymutilJobClass: T = new tools::darwin::Dsymutil(*this); break; + case Action::VerifyJobClass: + T = new tools::darwin::VerifyDebug(*this); break; } } @@ -267,8 +262,6 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) : Darwin(Host, Triple) { - std::string UsrPrefix = "llvm-gcc-4.2/"; - getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -281,16 +274,24 @@ DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) // For fallback, we need to know how to find the GCC cc1 executables, so we // also add the GCC libexec paths. This is legacy code that can be removed // once fallback is no longer useful. + AddGCCLibexecPath(DarwinVersion[0]); + AddGCCLibexecPath(DarwinVersion[0] - 2); + AddGCCLibexecPath(DarwinVersion[0] - 1); + AddGCCLibexecPath(DarwinVersion[0] + 1); + AddGCCLibexecPath(DarwinVersion[0] + 2); +} + +void DarwinClang::AddGCCLibexecPath(unsigned darwinVersion) { std::string ToolChainDir = "i686-apple-darwin"; - ToolChainDir += llvm::utostr(DarwinVersion[0]); + ToolChainDir += llvm::utostr(darwinVersion); ToolChainDir += "/4.2.1"; std::string Path = getDriver().Dir; - Path += "/../" + UsrPrefix + "libexec/gcc/"; + Path += "/../llvm-gcc-4.2/libexec/gcc/"; Path += ToolChainDir; getProgramPaths().push_back(Path); - Path = "/usr/" + UsrPrefix + "libexec/gcc/"; + Path = "/usr/llvm-gcc-4.2/libexec/gcc/"; Path += ToolChainDir; getProgramPaths().push_back(Path); } @@ -308,7 +309,7 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, P.appendComponent("gcc"); switch (getTriple().getArch()) { default: - assert(0 && "Invalid Darwin arch!"); + llvm_unreachable("Invalid Darwin arch!"); case llvm::Triple::x86: case llvm::Triple::x86_64: P.appendComponent("i686-apple-darwin10"); @@ -332,7 +333,7 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, case llvm::Triple::arm: case llvm::Triple::thumb: { std::string Triple = ComputeLLVMTriple(Args); - llvm::StringRef TripleStr = Triple; + StringRef TripleStr = Triple; if (TripleStr.startswith("armv5") || TripleStr.startswith("thumbv5")) ArchSpecificDir = "v5"; else if (TripleStr.startswith("armv6") || TripleStr.startswith("thumbv6")) @@ -364,8 +365,8 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, void DarwinClang::AddLinkARCArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - - CmdArgs.push_back("-force_load"); + + CmdArgs.push_back("-force_load"); llvm::sys::Path P(getDriver().ClangExecutable); P.eraseComponent(); // 'clang' P.eraseComponent(); // 'bin' @@ -387,13 +388,13 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, } void DarwinClang::AddLinkRuntimeLib(const ArgList &Args, - ArgStringList &CmdArgs, + ArgStringList &CmdArgs, const char *DarwinStaticLib) const { llvm::sys::Path P(getDriver().ResourceDir); P.appendComponent("lib"); P.appendComponent("darwin"); P.appendComponent(DarwinStaticLib); - + // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build. bool Exists; @@ -412,7 +413,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // cares. This is useful in situations where someone wants to statically link // something like libstdc++, and needs its runtime support routines. if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) { - getDriver().Diag(clang::diag::err_drv_unsupported_opt) + getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args); return; } @@ -425,8 +426,9 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, if (isTargetIPhoneOS()) { // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, // it never went into the SDK. - if (!isTargetIOSSimulator()) - CmdArgs.push_back("-lgcc_s.1"); + // Linking against libgcc_s.1 isn't needed for iOS 5.0+ + if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator()) + CmdArgs.push_back("-lgcc_s.1"); // We currently always need a static runtime library for iOS. AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a"); @@ -456,7 +458,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, } } -static inline llvm::StringRef SimulatorVersionDefineName() { +static inline StringRef SimulatorVersionDefineName() { return "__IPHONE_OS_VERSION_MIN_REQUIRED"; } @@ -465,11 +467,11 @@ static inline llvm::StringRef SimulatorVersionDefineName() { // and return the grouped values as integers, e.g: // __IPHONE_OS_VERSION_MIN_REQUIRED=40201 // will return Major=4, Minor=2, Micro=1. -static bool GetVersionFromSimulatorDefine(llvm::StringRef define, +static bool GetVersionFromSimulatorDefine(StringRef define, unsigned &Major, unsigned &Minor, unsigned &Micro) { assert(define.startswith(SimulatorVersionDefineName())); - llvm::StringRef name, version; + StringRef name, version; llvm::tie(name, version) = define.split('='); if (version.empty()) return false; @@ -500,13 +502,15 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (!iOSVersion) { for (arg_iterator it = Args.filtered_begin(options::OPT_D), ie = Args.filtered_end(); it != ie; ++it) { - llvm::StringRef define = (*it)->getValue(Args); + StringRef define = (*it)->getValue(Args); if (define.startswith(SimulatorVersionDefineName())) { - unsigned Major, Minor, Micro; + unsigned Major = 0, Minor = 0, Micro = 0; if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) && Major < 10 && Minor < 100 && Micro < 100) { ARCRuntimeForSimulator = Major < 5 ? ARCSimulator_NoARCRuntime : ARCSimulator_HasARCRuntime; + LibCXXForSimulator = Major < 5 ? LibCXXSimulator_NotAvailable + : LibCXXSimulator_Available; } break; } @@ -514,61 +518,78 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } if (OSXVersion && (iOSVersion || iOSSimVersion)) { - getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) << (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args); iOSVersion = iOSSimVersion = 0; } else if (iOSVersion && iOSSimVersion) { - getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) << iOSVersion->getAsString(Args) << iOSSimVersion->getAsString(Args); iOSSimVersion = 0; } else if (!OSXVersion && !iOSVersion && !iOSSimVersion) { - // If not deployment target was specified on the command line, check for + // If no deployment target was specified on the command line, check for // environment defines. - const char *OSXTarget = ::getenv("MACOSX_DEPLOYMENT_TARGET"); - const char *iOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"); - const char *iOSSimTarget = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET"); - - // Ignore empty strings. - if (OSXTarget && OSXTarget[0] == '\0') - OSXTarget = 0; - if (iOSTarget && iOSTarget[0] == '\0') - iOSTarget = 0; - if (iOSSimTarget && iOSSimTarget[0] == '\0') - iOSSimTarget = 0; + StringRef OSXTarget; + StringRef iOSTarget; + StringRef iOSSimTarget; + if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET")) + OSXTarget = env; + if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET")) + iOSTarget = env; + if (char *env = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET")) + iOSSimTarget = env; + + // If no '-miphoneos-version-min' specified on the command line and + // IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default + // based on isysroot. + if (iOSTarget.empty()) { + if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { + StringRef first, second; + StringRef isysroot = A->getValue(Args); + llvm::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS")); + if (second != "") + iOSTarget = second.substr(0,3); + } + } + + // If no OSX or iOS target has been specified and we're compiling for armv7, + // go ahead as assume we're targeting iOS. + if (OSXTarget.empty() && iOSTarget.empty()) + if (getDarwinArchName(Args) == "armv7") + iOSTarget = "0.0"; // Handle conflicting deployment targets // // FIXME: Don't hardcode default here. // Do not allow conflicts with the iOS simulator target. - if (iOSSimTarget && (OSXTarget || iOSTarget)) { - getDriver().Diag(clang::diag::err_drv_conflicting_deployment_targets) + if (!iOSSimTarget.empty() && (!OSXTarget.empty() || !iOSTarget.empty())) { + getDriver().Diag(diag::err_drv_conflicting_deployment_targets) << "IOS_SIMULATOR_DEPLOYMENT_TARGET" - << (OSXTarget ? "MACOSX_DEPLOYMENT_TARGET" : + << (!OSXTarget.empty() ? "MACOSX_DEPLOYMENT_TARGET" : "IPHONEOS_DEPLOYMENT_TARGET"); } // Allow conflicts among OSX and iOS for historical reasons, but choose the // default platform. - if (OSXTarget && iOSTarget) { + if (!OSXTarget.empty() && !iOSTarget.empty()) { if (getTriple().getArch() == llvm::Triple::arm || getTriple().getArch() == llvm::Triple::thumb) - OSXTarget = 0; + OSXTarget = ""; else - iOSTarget = 0; + iOSTarget = ""; } - if (OSXTarget) { + if (!OSXTarget.empty()) { const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget); Args.append(OSXVersion); - } else if (iOSTarget) { + } else if (!iOSTarget.empty()) { const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget); Args.append(iOSVersion); - } else if (iOSSimTarget) { + } else if (!iOSSimTarget.empty()) { const Option *O = Opts.getOption( options::OPT_mios_simulator_version_min_EQ); iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget); @@ -584,7 +605,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // Reject invalid architecture combinations. if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 && getTriple().getArch() != llvm::Triple::x86_64)) { - getDriver().Diag(clang::diag::err_drv_invalid_arch_for_deployment_target) + getDriver().Diag(diag::err_drv_invalid_arch_for_deployment_target) << getTriple().getArchName() << iOSSimVersion->getAsString(Args); } @@ -596,7 +617,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor, Micro, HadExtra) || HadExtra || Major != 10 || Minor >= 100 || Micro >= 100) - getDriver().Diag(clang::diag::err_drv_invalid_version_number) + getDriver().Diag(diag::err_drv_invalid_version_number) << OSXVersion->getAsString(Args); } else { const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion; @@ -604,7 +625,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (!Driver::GetReleaseVersion(Version->getValue(Args), Major, Minor, Micro, HadExtra) || HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) - getDriver().Diag(clang::diag::err_drv_invalid_version_number) + getDriver().Diag(diag::err_drv_invalid_version_number) << Version->getAsString(Args); } @@ -708,7 +729,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // triple arch, or the arch being bound. // // FIXME: Canonicalize name. - llvm::StringRef XarchArch = A->getValue(Args, 0); + StringRef XarchArch = A->getValue(Args, 0); if (!(XarchArch == getArchName() || (BoundArch && XarchArch == BoundArch))) continue; @@ -727,11 +748,11 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // use isDriverOption() as an approximation, although things // like -O4 are going to slip through. if (!XarchArg || Index > Prev + 1) { - getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument_with_args) + getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) << A->getAsString(Args); continue; } else if (XarchArg->getOption().isDriverOption()) { - getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument_isdriver) + getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver) << A->getAsString(Args); continue; } @@ -768,7 +789,6 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, case options::OPT_fapple_kext: DAL->append(A); DAL->AddFlagArg(A, Opts.getOption(options::OPT_static)); - DAL->AddFlagArg(A, Opts.getOption(options::OPT_static)); break; case options::OPT_dependency_file: @@ -788,12 +808,6 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, Opts.getOption(options::OPT_feliminate_unused_debug_symbols)); break; - case options::OPT_fterminated_vtables: - case options::OPT_findirect_virtual_calls: - DAL->AddFlagArg(A, Opts.getOption(options::OPT_fapple_kext)); - DAL->AddFlagArg(A, Opts.getOption(options::OPT_static)); - break; - case options::OPT_shared: DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib)); break; @@ -834,7 +848,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // Add the arch options based on the particular spelling of -arch, to match // how the driver driver works. if (BoundArch) { - llvm::StringRef Name = BoundArch; + StringRef Name = BoundArch; const Option *MCpu = Opts.getOption(options::OPT_mcpu_EQ); const Option *MArch = Opts.getOption(options::OPT_march_EQ); @@ -904,6 +918,28 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // argument. AddDeploymentTarget(*DAL); + // Validate the C++ standard library choice. + CXXStdlibType Type = GetCXXStdlibType(*DAL); + if (Type == ToolChain::CST_Libcxx) { + switch (LibCXXForSimulator) { + case LibCXXSimulator_None: + // Handle non-simulator cases. + if (isTargetIPhoneOS()) { + if (isIPhoneOSVersionLT(5, 0)) { + getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) + << "iOS 5.0"; + } + } + break; + case LibCXXSimulator_NotAvailable: + getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) + << "iOS 5.0"; + break; + case LibCXXSimulator_Available: + break; + } + } + return DAL; } @@ -946,8 +982,9 @@ bool Darwin::SupportsObjCGC() const { } std::string -Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const { - return ComputeLLVMTriple(Args); +Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { + return ComputeLLVMTriple(Args, InputType); } /// Generic_GCC - A tool chain using the 'gcc' command to perform @@ -982,7 +1019,7 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, switch (Key) { case Action::InputClass: case Action::BindArchClass: - assert(0 && "Invalid tool kind."); + llvm_unreachable("Invalid tool kind."); case Action::PreprocessJobClass: T = new tools::gcc::Preprocess(*this); break; case Action::PrecompileJobClass: @@ -1002,6 +1039,8 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, T = new tools::darwin::Lipo(*this); break; case Action::DsymutilJobClass: T = new tools::darwin::Dsymutil(*this); break; + case Action::VerifyJobClass: + T = new tools::darwin::VerifyDebug(*this); break; } } @@ -1071,7 +1110,7 @@ Tool &TCEToolChain::SelectTool(const Compilation &C, case Action::AnalyzeJobClass: T = new tools::Clang(*this); break; default: - assert(false && "Unsupported action for TCE target."); + llvm_unreachable("Unsupported action for TCE target."); } } return *T; @@ -1350,32 +1389,24 @@ static bool IsUbuntu(enum LinuxDistro Distro) { Distro == UbuntuNatty || Distro == UbuntuOneiric; } -static bool IsDebianBased(enum LinuxDistro Distro) { - return IsDebian(Distro) || IsUbuntu(Distro); -} - +// FIXME: This should be deleted. We should assume a multilib environment, and +// fallback gracefully if any parts of it are absent. static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) { if (Arch == llvm::Triple::x86_64) { bool Exists; if (Distro == Exherbo && (llvm::sys::fs::exists("/usr/lib32/libc.so", Exists) || !Exists)) return false; - - return true; } - if (Arch == llvm::Triple::ppc64) - return true; - if ((Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) && - IsDebianBased(Distro)) - return true; - return false; + + return true; } static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { llvm::OwningPtr<llvm::MemoryBuffer> File; if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) { - llvm::StringRef Data = File.get()->getBuffer(); - llvm::SmallVector<llvm::StringRef, 8> Lines; + StringRef Data = File.get()->getBuffer(); + SmallVector<StringRef, 8> Lines; Data.split(Lines, "\n"); for (unsigned int i = 0, s = Lines.size(); i < s; ++ i) { if (Lines[i] == "DISTRIB_CODENAME=hardy") @@ -1399,7 +1430,7 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { } if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) { - llvm::StringRef Data = File.get()->getBuffer(); + StringRef Data = File.get()->getBuffer(); if (Data.startswith("Fedora release 15")) return Fedora15; else if (Data.startswith("Fedora release 14")) @@ -1407,24 +1438,24 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { else if (Data.startswith("Fedora release 13")) return Fedora13; else if (Data.startswith("Fedora release") && - Data.find("Rawhide") != llvm::StringRef::npos) + Data.find("Rawhide") != StringRef::npos) return FedoraRawhide; else if (Data.startswith("Red Hat Enterprise Linux") && - Data.find("release 6") != llvm::StringRef::npos) + Data.find("release 6") != StringRef::npos) return RHEL6; else if ((Data.startswith("Red Hat Enterprise Linux") || Data.startswith("CentOS")) && - Data.find("release 5") != llvm::StringRef::npos) + Data.find("release 5") != StringRef::npos) return RHEL5; else if ((Data.startswith("Red Hat Enterprise Linux") || Data.startswith("CentOS")) && - Data.find("release 4") != llvm::StringRef::npos) + Data.find("release 4") != StringRef::npos) return RHEL4; return UnknownDistro; } if (!llvm::MemoryBuffer::getFile("/etc/debian_version", File)) { - llvm::StringRef Data = File.get()->getBuffer(); + StringRef Data = File.get()->getBuffer(); if (Data[0] == '5') return DebianLenny; else if (Data.startswith("squeeze/sid")) @@ -1435,7 +1466,7 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { } if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File)) { - llvm::StringRef Data = File.get()->getBuffer(); + StringRef Data = File.get()->getBuffer(); if (Data.startswith("openSUSE 11.3")) return OpenSuse11_3; else if (Data.startswith("openSUSE 11.4")) @@ -1455,164 +1486,282 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { return UnknownDistro; } -static std::string findGCCBaseLibDir(const std::string &GccTriple) { - // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but - // avoids adding yet another option to configure/cmake. - // It would probably be cleaner to break it in two variables - // CXX_GCC_ROOT with just /foo/bar - // CXX_GCC_VER with 4.5.2 - // Then we would have - // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER - // and this function would return - // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER - llvm::SmallString<128> CxxIncludeRoot(CXX_INCLUDE_ROOT); - if (CxxIncludeRoot != "") { - // This is of the form /foo/bar/include/c++/4.5.2/ - if (CxxIncludeRoot.back() == '/') - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the / - llvm::StringRef Version = llvm::sys::path::filename(CxxIncludeRoot); - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++ - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include - std::string ret(CxxIncludeRoot.c_str()); - ret.append("/lib/gcc/"); - ret.append(CXX_INCLUDE_ARCH); - ret.append("/"); - ret.append(Version); - return ret; - } - static const char* GccVersions[] = {"4.6.1", "4.6.0", "4.6", - "4.5.2", "4.5.1", "4.5", - "4.4.5", "4.4.4", "4.4.3", "4.4", - "4.3.4", "4.3.3", "4.3.2", "4.3", - "4.2.4", "4.2.3", "4.2.2", "4.2.1", - "4.2", "4.1.1"}; +/// \brief Trivial helper function to simplify code checking path existence. +static bool PathExists(StringRef Path) { bool Exists; - for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) { - std::string Suffix = GccTriple + "/" + GccVersions[i]; - std::string t1 = "/usr/lib/gcc/" + Suffix; - if (!llvm::sys::fs::exists(t1 + "/crtbegin.o", Exists) && Exists) - return t1; - std::string t2 = "/usr/lib64/gcc/" + Suffix; - if (!llvm::sys::fs::exists(t2 + "/crtbegin.o", Exists) && Exists) - return t2; - std::string t3 = "/usr/lib/" + GccTriple + "/gcc/" + Suffix; - if (!llvm::sys::fs::exists(t3 + "/crtbegin.o", Exists) && Exists) - return t3; - } - return ""; + if (!llvm::sys::fs::exists(Path, Exists)) + return Exists; + return false; } -Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) - : Generic_ELF(Host, Triple) { - llvm::Triple::ArchType Arch = - llvm::Triple(getDriver().DefaultHostTriple).getArch(); +namespace { +/// \brief This is a class to find a viable GCC installation for Clang to use. +/// +/// This class tries to find a GCC installation on the system, and report +/// information about it. It starts from the host information provided to the +/// Driver, and has logic for fuzzing that where appropriate. +class GCCInstallationDetector { + /// \brief Struct to store and manipulate GCC versions. + /// + /// We rely on assumptions about the form and structure of GCC version + /// numbers: they consist of at most three '.'-separated components, and each + /// component is a non-negative integer. + struct GCCVersion { + unsigned Major, Minor, Patch; + + static GCCVersion Parse(StringRef VersionText) { + const GCCVersion BadVersion = {0, 0, 0}; + std::pair<StringRef, StringRef> First = VersionText.split('.'); + std::pair<StringRef, StringRef> Second = First.second.split('.'); + + GCCVersion GoodVersion = {0, 0, 0}; + if (First.first.getAsInteger(10, GoodVersion.Major)) + return BadVersion; + if (Second.first.getAsInteger(10, GoodVersion.Minor)) + return BadVersion; + // We accept a number, or a string for the patch version, in case there + // is a strang suffix, or other mangling: '4.1.x', '4.1.2-rc3'. When it + // isn't a number, we just use '0' as the number but accept it. + if (Second.first.getAsInteger(10, GoodVersion.Patch)) + GoodVersion.Patch = 0; + return GoodVersion; + } - std::string Suffix32 = ""; - if (Arch == llvm::Triple::x86_64) - Suffix32 = "/32"; + bool operator<(const GCCVersion &RHS) const { + if (Major < RHS.Major) return true; + if (Major > RHS.Major) return false; + if (Minor < RHS.Minor) return true; + if (Minor > RHS.Minor) return false; + return Patch < RHS.Patch; + } + bool operator>(const GCCVersion &RHS) const { return RHS < *this; } + bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); } + bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } + }; + + bool IsValid; + std::string GccTriple; + + // FIXME: These might be better as path objects. + std::string GccInstallPath; + std::string GccParentLibPath; + + llvm::SmallString<128> CxxIncludeRoot; + +public: + /// \brief Construct a GCCInstallationDetector from the driver. + /// + /// This performs all of the autodetection and sets up the various paths. + /// Once constructed, a GCCInstallation is esentially immutable. + GCCInstallationDetector(const Driver &D) + : IsValid(false), + GccTriple(D.DefaultHostTriple), + CxxIncludeRoot(CXX_INCLUDE_ROOT) { + // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but + // avoids adding yet another option to configure/cmake. + // It would probably be cleaner to break it in two variables + // CXX_GCC_ROOT with just /foo/bar + // CXX_GCC_VER with 4.5.2 + // Then we would have + // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER + // and this function would return + // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER + if (CxxIncludeRoot != "") { + // This is of the form /foo/bar/include/c++/4.5.2/ + if (CxxIncludeRoot.back() == '/') + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the / + StringRef Version = llvm::sys::path::filename(CxxIncludeRoot); + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++ + llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include + GccInstallPath = CxxIncludeRoot.str(); + GccInstallPath.append("/lib/gcc/"); + GccInstallPath.append(CXX_INCLUDE_ARCH); + GccInstallPath.append("/"); + GccInstallPath.append(Version); + GccParentLibPath = GccInstallPath + "/../../.."; + IsValid = true; + return; + } - std::string Suffix64 = ""; - if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) - Suffix64 = "/64"; + llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch(); + // The library directories which may contain GCC installations. + SmallVector<StringRef, 4> CandidateLibDirs; + // The compatible GCC triples for this particular architecture. + SmallVector<StringRef, 10> CandidateTriples; + CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples); + + // Always include the default host triple as the final fallback if no + // specific triple is detected. + CandidateTriples.push_back(D.DefaultHostTriple); + + // Compute the set of prefixes for our search. + SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), + D.PrefixDirs.end()); + Prefixes.push_back(D.SysRoot); + Prefixes.push_back(D.SysRoot + "/usr"); + Prefixes.push_back(D.InstalledDir + "/.."); + + // Loop over the various components which exist and select the best GCC + // installation available. GCC installs are ranked by version number. + GCCVersion BestVersion = {0, 0, 0}; + for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) { + if (!PathExists(Prefixes[i])) + continue; + for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) { + const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); + if (!PathExists(LibDir)) + continue; + for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k) + ScanLibDirForGCCTriple(LibDir, CandidateTriples[k], BestVersion); + } + } + } - std::string Lib32 = "lib"; + /// \brief Check whether we detected a valid GCC install. + bool isValid() const { return IsValid; } + + /// \brief Get the GCC triple for the detected install. + const std::string &getTriple() const { return GccTriple; } + + /// \brief Get the detected GCC installation path. + const std::string &getInstallPath() const { return GccInstallPath; } + + /// \brief Get the detected GCC parent lib path. + const std::string &getParentLibPath() const { return GccParentLibPath; } + +private: + static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch, + SmallVectorImpl<StringRef> &LibDirs, + SmallVectorImpl<StringRef> &Triples) { + if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) { + static const char *const ARMLibDirs[] = { "/lib" }; + static const char *const ARMTriples[] = { "arm-linux-gnueabi" }; + LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); + Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); + } else if (HostArch == llvm::Triple::x86_64) { + static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; + static const char *const X86_64Triples[] = { + "x86_64-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-pc-linux-gnu", + "x86_64-redhat-linux6E", + "x86_64-redhat-linux", + "x86_64-suse-linux", + "x86_64-manbo-linux-gnu", + "x86_64-linux-gnu", + "x86_64-slackware-linux" + }; + LibDirs.append(X86_64LibDirs, + X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); + Triples.append(X86_64Triples, + X86_64Triples + llvm::array_lengthof(X86_64Triples)); + } else if (HostArch == llvm::Triple::x86) { + static const char *const X86LibDirs[] = { "/lib32", "/lib" }; + static const char *const X86Triples[] = { + "i686-linux-gnu", + "i386-linux-gnu", + "i686-pc-linux-gnu", + "i486-linux-gnu", + "i686-redhat-linux", + "i386-redhat-linux", + "i586-suse-linux", + "i486-slackware-linux" + }; + LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); + Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); + } else if (HostArch == llvm::Triple::ppc) { + static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; + static const char *const PPCTriples[] = { + "powerpc-linux-gnu", + "powerpc-unknown-linux-gnu" + }; + LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); + Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); + } else if (HostArch == llvm::Triple::ppc64) { + static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; + static const char *const PPC64Triples[] = { + "powerpc64-unknown-linux-gnu" + }; + LibDirs.append(PPC64LibDirs, + PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); + Triples.append(PPC64Triples, + PPC64Triples + llvm::array_lengthof(PPC64Triples)); + } + } - bool Exists; - if (!llvm::sys::fs::exists("/lib32", Exists) && Exists) - Lib32 = "lib32"; - - std::string Lib64 = "lib"; - bool Symlink; - if (!llvm::sys::fs::exists("/lib64", Exists) && Exists && - (llvm::sys::fs::is_symlink("/lib64", Symlink) || !Symlink)) - Lib64 = "lib64"; - - std::string GccTriple = ""; - if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { - if (!llvm::sys::fs::exists("/usr/lib/gcc/arm-linux-gnueabi", Exists) && - Exists) - GccTriple = "arm-linux-gnueabi"; - } else if (Arch == llvm::Triple::x86_64) { - if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-linux-gnu", Exists) && - Exists) - GccTriple = "x86_64-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-unknown-linux-gnu", - Exists) && Exists) - GccTriple = "x86_64-unknown-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-pc-linux-gnu", - Exists) && Exists) - GccTriple = "x86_64-pc-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-redhat-linux6E", - Exists) && Exists) - GccTriple = "x86_64-redhat-linux6E"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-redhat-linux", - Exists) && Exists) - GccTriple = "x86_64-redhat-linux"; - else if (!llvm::sys::fs::exists("/usr/lib64/gcc/x86_64-suse-linux", - Exists) && Exists) - GccTriple = "x86_64-suse-linux"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-manbo-linux-gnu", - Exists) && Exists) - GccTriple = "x86_64-manbo-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/x86_64-linux-gnu/gcc", - Exists) && Exists) - GccTriple = "x86_64-linux-gnu"; - } else if (Arch == llvm::Triple::x86) { - if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-linux-gnu", Exists) && Exists) - GccTriple = "i686-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-pc-linux-gnu", Exists) && - Exists) - GccTriple = "i686-pc-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-linux-gnu", Exists) && - Exists) - GccTriple = "i486-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-redhat-linux", Exists) && - Exists) - GccTriple = "i686-redhat-linux"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/i586-suse-linux", Exists) && - Exists) - GccTriple = "i586-suse-linux"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-slackware-linux", Exists) - && Exists) - GccTriple = "i486-slackware-linux"; - } else if (Arch == llvm::Triple::ppc) { - if (!llvm::sys::fs::exists("/usr/lib/powerpc-linux-gnu", Exists) && Exists) - GccTriple = "powerpc-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib/gcc/powerpc-unknown-linux-gnu", - Exists) && Exists) - GccTriple = "powerpc-unknown-linux-gnu"; - } else if (Arch == llvm::Triple::ppc64) { - if (!llvm::sys::fs::exists("/usr/lib/gcc/powerpc64-unknown-linux-gnu", - Exists) && Exists) - GccTriple = "powerpc64-unknown-linux-gnu"; - else if (!llvm::sys::fs::exists("/usr/lib64/gcc/" - "powerpc64-unknown-linux-gnu", Exists) && - Exists) - GccTriple = "powerpc64-unknown-linux-gnu"; + void ScanLibDirForGCCTriple(const std::string &LibDir, + StringRef CandidateTriple, + GCCVersion &BestVersion) { + // There are various different suffixes involving the triple we + // check for. We also record what is necessary to walk from each back + // up to the lib directory. + const std::string Suffixes[] = { + "/gcc/" + CandidateTriple.str(), + "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), + + // Ubuntu has a strange mis-matched pair of triples that this happens to + // match. + // FIXME: It may be worthwhile to generalize this and look for a second + // triple. + "/" + CandidateTriple.str() + "/gcc/i686-linux-gnu" + }; + const std::string InstallSuffixes[] = { + "/../../..", + "/../../../..", + "/../../../.." + }; + // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. + const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) - + (CandidateTriple != "i386-linux-gnu")); + for (unsigned i = 0; i < NumSuffixes; ++i) { + StringRef Suffix = Suffixes[i]; + llvm::error_code EC; + for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); + static const GCCVersion MinVersion = { 4, 1, 1 }; + if (CandidateVersion < MinVersion) + continue; + if (CandidateVersion <= BestVersion) + continue; + if (!PathExists(LI->path() + "/crtbegin.o")) + continue; + + BestVersion = CandidateVersion; + GccTriple = CandidateTriple.str(); + // FIXME: We hack together the directory name here instead of + // using LI to ensure stable path separators across Windows and + // Linux. + GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str(); + GccParentLibPath = GccInstallPath + InstallSuffixes[i]; + IsValid = true; + } + } } +}; +} - std::string Base = findGCCBaseLibDir(GccTriple); - path_list &Paths = getFilePaths(); - bool Is32Bits = (getArch() == llvm::Triple::x86 || - getArch() == llvm::Triple::ppc); +static void addPathIfExists(const std::string &Path, + ToolChain::path_list &Paths) { + if (PathExists(Path)) Paths.push_back(Path); +} - std::string Suffix; - std::string Lib; +Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) + : Generic_ELF(Host, Triple) { + llvm::Triple::ArchType Arch = + llvm::Triple(getDriver().DefaultHostTriple).getArch(); + const std::string &SysRoot = getDriver().SysRoot; + GCCInstallationDetector GCCInstallation(getDriver()); - if (Is32Bits) { - Suffix = Suffix32; - Lib = Lib32; - } else { - Suffix = Suffix64; - Lib = Lib64; - } + // OpenSuse stores the linker with the compiler, add that to the search + // path. + ToolChain::path_list &PPaths = getProgramPaths(); + PPaths.push_back(GCCInstallation.getParentLibPath() + "/../" + + GCCInstallation.getTriple() + "/bin"); - llvm::sys::Path LinkerPath(Base + "/../../../../" + GccTriple + "/bin/ld"); - if (!llvm::sys::fs::exists(LinkerPath.str(), Exists) && Exists) - Linker = LinkerPath.str(); - else - Linker = GetProgramPath("ld"); + Linker = GetProgramPath("ld"); LinuxDistro Distro = DetectLinuxDistro(Arch); @@ -1646,29 +1795,63 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) if (IsOpenSuse(Distro)) ExtraOpts.push_back("--enable-new-dtags"); - if (Distro == ArchLinux) - Lib = "lib"; + // The selection of paths to try here is designed to match the patterns which + // the GCC driver itself uses, as this is part of the GCC-compatible driver. + // This was determined by running GCC in a fake filesystem, creating all + // possible permutations of these directories, and seeing which ones it added + // to the link paths. + path_list &Paths = getFilePaths(); + const bool Is32Bits = (getArch() == llvm::Triple::x86 || + getArch() == llvm::Triple::ppc); + + const std::string Suffix32 = Arch == llvm::Triple::x86_64 ? "/32" : ""; + const std::string Suffix64 = Arch == llvm::Triple::x86_64 ? "" : "/64"; + const std::string Suffix = Is32Bits ? Suffix32 : Suffix64; + const std::string Multilib = Is32Bits ? "lib32" : "lib64"; - Paths.push_back(Base + Suffix); + // FIXME: Because we add paths only when they exist on the system, I think we + // should remove the concept of 'HasMultilib'. It's more likely to break the + // behavior than to preserve any useful invariant on the system. if (HasMultilib(Arch, Distro)) { - if (IsOpenSuse(Distro) && Is32Bits) - Paths.push_back(Base + "/../../../../" + GccTriple + "/lib/../lib"); - Paths.push_back(Base + "/../../../../" + Lib); + // Add the multilib suffixed paths. + if (GCCInstallation.isValid()) { + const std::string &LibPath = GCCInstallation.getParentLibPath(); + const std::string &GccTriple = GCCInstallation.getTriple(); + // FIXME: This OpenSuse-specific path shouldn't be needed any more, but + // I don't want to remove it without finding someone to test. + if (IsOpenSuse(Distro) && Is32Bits) + Paths.push_back(LibPath + "/../" + GccTriple + "/lib/../lib"); + + addPathIfExists(GCCInstallation.getInstallPath() + Suffix, Paths); + addPathIfExists(LibPath + "/../" + GccTriple + "/lib/../" + Multilib, + Paths); + addPathIfExists(LibPath + "/../" + Multilib, Paths); + } + addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths); + addPathIfExists(SysRoot + "/usr/lib/../" + Multilib, Paths); + + // Try walking via the GCC triple path in case of multiarch GCC + // installations with strange symlinks. + if (GCCInstallation.isValid()) + addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple() + + "/../../" + Multilib, Paths); } - // FIXME: This is in here to find crt1.o. It is provided by libc, and - // libc (like gcc), can be installed in any directory. Once we are - // fetching this from a config file, we should have a libc prefix. - Paths.push_back("/lib/../" + Lib); - Paths.push_back("/usr/lib/../" + Lib); + // Add the non-multilib suffixed paths (if potentially different). + if (GCCInstallation.isValid()) { + const std::string &LibPath = GCCInstallation.getParentLibPath(); + const std::string &GccTriple = GCCInstallation.getTriple(); + if (!Suffix.empty() || !HasMultilib(Arch, Distro)) + addPathIfExists(GCCInstallation.getInstallPath(), Paths); + addPathIfExists(LibPath + "/../" + GccTriple + "/lib", Paths); + addPathIfExists(LibPath, Paths); + } + addPathIfExists(SysRoot + "/lib", Paths); + addPathIfExists(SysRoot + "/usr/lib", Paths); - if (!Suffix.empty()) - Paths.push_back(Base); - if (IsOpenSuse(Distro)) - Paths.push_back(Base + "/../../../../" + GccTriple + "/lib"); - Paths.push_back(Base + "/../../.."); - if (Arch == getArch() && IsUbuntu(Distro)) - Paths.push_back("/usr/lib/" + GccTriple); + // Add a multiarch lib directory whenever it exists and is plausible. + if (GCCInstallation.isValid() && Arch == getArch()) + addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple(), Paths); } bool Linux::HasNativeLLVMSupport() const { @@ -1756,6 +1939,10 @@ Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, else Key = JA.getKind(); + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIntegratedAssemblerDefault()); + Tool *&T = Tools[Key]; if (!T) { switch (Key) { @@ -1763,14 +1950,19 @@ Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, case Action::BindArchClass: case Action::LipoJobClass: case Action::DsymutilJobClass: - assert(0 && "Invalid tool kind."); + case Action::VerifyJobClass: + llvm_unreachable("Invalid tool kind."); case Action::PreprocessJobClass: case Action::PrecompileJobClass: case Action::AnalyzeJobClass: case Action::CompileJobClass: T = new tools::Clang(*this); break; case Action::AssembleJobClass: - T = new tools::ClangAs(*this); break; + if (!UseIntegratedAs && getTriple().getEnvironment() == llvm::Triple::MachO) + T = new tools::darwin::Assemble(*this); + else + T = new tools::ClangAs(*this); + break; case Action::LinkJobClass: T = new tools::visualstudio::Link(*this); break; } diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index d68016b..dfcb253 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -66,6 +66,12 @@ private: ARCSimulator_NoARCRuntime } ARCRuntimeForSimulator; + mutable enum { + LibCXXSimulator_None, + LibCXXSimulator_NotAvailable, + LibCXXSimulator_Available + } LibCXXForSimulator; + private: /// Whether we are targeting iPhoneOS target. mutable bool TargetIsIPhoneOS; @@ -89,7 +95,8 @@ public: Darwin(const HostInfo &Host, const llvm::Triple& Triple); ~Darwin(); - std::string ComputeEffectiveClangTriple(const ArgList &Args) const; + std::string ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const; /// @name Darwin Specific Toolchain API /// { @@ -139,7 +146,7 @@ public: /// getDarwinArchName - Get the "Darwin" arch name for a particular compiler /// invocation. For example, Darwin treats different ARM variations as /// distinct architectures. - llvm::StringRef getDarwinArchName(const ArgList &Args) const; + StringRef getDarwinArchName(const ArgList &Args) const; static bool isVersionLT(unsigned (&A)[3], unsigned (&B)[3]) { for (unsigned i=0; i < 3; ++i) { @@ -187,6 +194,7 @@ public: virtual bool HasNativeLLVMSupport() const; virtual void configureObjCRuntime(ObjCRuntime &runtime) const; + virtual bool hasBlocksRuntime() const; virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const; @@ -237,9 +245,12 @@ public: return !(!isTargetIPhoneOS() && isMacosxVersionLT(10, 6)); } virtual bool IsUnwindTablesDefault() const; - virtual unsigned GetDefaultStackProtectorLevel() const { - // Stack protectors default to on for 10.6 and beyond. - return !isTargetIPhoneOS() && !isMacosxVersionLT(10, 6); + virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { + // Stack protectors default to on for user code on 10.5, + // and for everything in 10.6 and beyond + return !isTargetIPhoneOS() && + (!isMacosxVersionLT(10, 6) || + (!isMacosxVersionLT(10, 5) && !KernelOrKext)); } virtual const char *GetDefaultRelocationModel() const; virtual const char *GetForcedPicModel() const; @@ -257,6 +268,9 @@ public: /// DarwinClang - The Darwin toolchain used by Clang. class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { +private: + void AddGCCLibexecPath(unsigned darwinVersion); + public: DarwinClang(const HostInfo &Host, const llvm::Triple& Triple); @@ -288,7 +302,8 @@ public: Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) : Generic_GCC(Host, Triple) {} - std::string ComputeEffectiveClangTriple(const ArgList &Args) const; + std::string ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const; virtual const char *GetDefaultRelocationModel() const { return "pic"; } }; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 64ad146..94849a6 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -45,25 +45,14 @@ using namespace clang::driver; using namespace clang::driver::tools; - -/// FindTargetProgramPath - Return path of the target specific version of -/// ProgName. If it doesn't exist, return path of ProgName itself. -static std::string FindTargetProgramPath(const ToolChain &TheToolChain, - const std::string TripleString, - const char *ProgName) { - std::string Executable(TripleString + "-" + ProgName); - std::string Path(TheToolChain.GetProgramPath(Executable.c_str())); - if (Path != Executable) - return Path; - return TheToolChain.GetProgramPath(ProgName); -} +using namespace clang; /// CheckPreprocessingOptions - Perform some validation of preprocessing /// arguments that is shared with gcc. static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP) - D.Diag(clang::diag::err_drv_argument_only_allowed_with) + D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; } @@ -74,14 +63,14 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { if (Args.hasArg(options::OPT_static)) if (const Arg *A = Args.getLastArg(options::OPT_dynamic, options::OPT_mdynamic_no_pic)) - D.Diag(clang::diag::err_drv_argument_not_allowed_with) + D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "-static"; } // Quote target names for inclusion in GNU Make dependency files. // Only the characters '$', '#', ' ', '\t' are quoted. -static void QuoteTarget(llvm::StringRef Target, - llvm::SmallVectorImpl<char> &Res) { +static void QuoteTarget(StringRef Target, + SmallVectorImpl<char> &Res) { for (unsigned i = 0, e = Target.size(); i != e; ++i) { switch (Target[i]) { case ' ': @@ -126,7 +115,7 @@ static void AddLinkerInputs(const ToolChain &TC, II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) - D.Diag(clang::diag::err_drv_no_linker_llvm_support) + D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString(); } @@ -168,20 +157,52 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, // the link line. We cannot do the same thing because unlike gcov there is a // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is // not supported by old linkers. - llvm::Twine ProfileRT = - llvm::Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.a"; + Twine ProfileRT = + Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.a"; - if (Triple.getOS() == llvm::Triple::Darwin) { + if (Triple.isOSDarwin()) { // On Darwin, if the static library doesn't exist try the dylib. bool Exists; if (llvm::sys::fs::exists(ProfileRT.str(), Exists) || !Exists) ProfileRT = - llvm::Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.dylib"; + Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.dylib"; } CmdArgs.push_back(Args.MakeArgString(ProfileRT)); } +static void AddIncludeDirectoryList(const ArgList &Args, + ArgStringList &CmdArgs, + const char *ArgName, + const char *DirList) { + if (!DirList) + return; // Nothing to do. + + StringRef Dirs(DirList); + if (Dirs.empty()) // Empty string should not add '.'. + return; + + StringRef::size_type Delim; + while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) { + if (Delim == 0) { // Leading colon. + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } else { + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); + } + Dirs = Dirs.substr(Delim + 1); + } + + if (Dirs.empty()) { // Trailing colon. + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } else { // Add the last path. + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs)); + } +} + void Clang::AddPreprocessingOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, @@ -245,7 +266,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, if (Args.hasArg(options::OPT_MG)) { if (!A || A->getOption().matches(options::OPT_MD) || A->getOption().matches(options::OPT_MMD)) - D.Diag(clang::diag::err_drv_mg_requires_m_or_mm); + D.Diag(diag::err_drv_mg_requires_m_or_mm); CmdArgs.push_back("-MG"); } @@ -328,7 +349,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, continue; } else { // Ignore the PCH if not first on command line and emit warning. - D.Diag(clang::diag::warn_drv_pch_not_first_include) + D.Diag(diag::warn_drv_pch_not_first_include) << P.str() << A->getAsString(Args); } } @@ -340,14 +361,15 @@ void Clang::AddPreprocessingOptions(const Driver &D, } Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U); - Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F); + Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F, + options::OPT_index_header_map); // Add C++ include arguments, if needed. types::ID InputType = Inputs[0].getType(); if (types::isCXX(InputType)) { bool ObjCXXAutoRefCount = types::isObjC(InputType) && isObjCAutoRefCount(Args); - getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs, + getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs, ObjCXXAutoRefCount); Args.AddAllArgs(CmdArgs, options::OPT_stdlib_EQ); } @@ -363,7 +385,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, // -I- is a deprecated GCC feature, reject it. if (Arg *A = Args.getLastArg(options::OPT_I_)) - D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args); + D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args); // If we have a --sysroot, and don't have an explicit -isysroot flag, add an // -isysroot to the CC1 invocation. @@ -373,6 +395,39 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back(A->getValue(Args)); } } + + // If a module path was provided, pass it along. Otherwise, use a temporary + // directory. + if (Arg *A = Args.getLastArg(options::OPT_fmodule_cache_path)) { + A->claim(); + A->render(Args, CmdArgs); + } else { + llvm::SmallString<128> DefaultModuleCache; + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, + DefaultModuleCache); + llvm::sys::path::append(DefaultModuleCache, "clang-module-cache"); + CmdArgs.push_back("-fmodule-cache-path"); + CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); + } + + Args.AddAllArgs(CmdArgs, options::OPT_fauto_module_import); + + // Parse additional include paths from environment variables. + // CPATH - included following the user specified includes (but prior to + // builtin and standard includes). + AddIncludeDirectoryList(Args, CmdArgs, "-I", ::getenv("CPATH")); + // C_INCLUDE_PATH - system includes enabled when compiling C. + AddIncludeDirectoryList(Args, CmdArgs, "-c-isystem", + ::getenv("C_INCLUDE_PATH")); + // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++. + AddIncludeDirectoryList(Args, CmdArgs, "-cxx-isystem", + ::getenv("CPLUS_INCLUDE_PATH")); + // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC. + AddIncludeDirectoryList(Args, CmdArgs, "-objc-isystem", + ::getenv("OBJC_INCLUDE_PATH")); + // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++. + AddIncludeDirectoryList(Args, CmdArgs, "-objcxx-isystem", + ::getenv("OBJCPLUS_INCLUDE_PATH")); } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. @@ -386,7 +441,7 @@ static const char *getARMTargetCPU(const ArgList &Args, if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(Args); - llvm::StringRef MArch; + StringRef MArch; if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { // Otherwise, if we have -march= choose the base CPU for that arch. MArch = A->getValue(Args); @@ -395,45 +450,27 @@ static const char *getARMTargetCPU(const ArgList &Args, MArch = Triple.getArchName(); } - if (MArch == "armv2" || MArch == "armv2a") - return "arm2"; - if (MArch == "armv3") - return "arm6"; - if (MArch == "armv3m") - return "arm7m"; - if (MArch == "armv4" || MArch == "armv4t") - return "arm7tdmi"; - if (MArch == "armv5" || MArch == "armv5t") - return "arm10tdmi"; - if (MArch == "armv5e" || MArch == "armv5te") - return "arm1026ejs"; - if (MArch == "armv5tej") - return "arm926ej-s"; - if (MArch == "armv6" || MArch == "armv6k") - return "arm1136jf-s"; - if (MArch == "armv6j") - return "arm1136j-s"; - if (MArch == "armv6z" || MArch == "armv6zk") - return "arm1176jzf-s"; - if (MArch == "armv6t2") - return "arm1156t2-s"; - if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") - return "cortex-a8"; - if (MArch == "armv7r" || MArch == "armv7-r") - return "cortex-r4"; - if (MArch == "armv7m" || MArch == "armv7-m") - return "cortex-m3"; - if (MArch == "ep9312") - return "ep9312"; - if (MArch == "iwmmxt") - return "iwmmxt"; - if (MArch == "xscale") - return "xscale"; - if (MArch == "armv6m" || MArch == "armv6-m") - return "cortex-m0"; - - // If all else failed, return the most base CPU LLVM supports. - return "arm7tdmi"; + return llvm::StringSwitch<const char *>(MArch) + .Cases("armv2", "armv2a","arm2") + .Case("armv3", "arm6") + .Case("armv3m", "arm7m") + .Cases("armv4", "armv4t", "arm7tdmi") + .Cases("armv5", "armv5t", "arm10tdmi") + .Cases("armv5e", "armv5te", "arm1026ejs") + .Case("armv5tej", "arm926ej-s") + .Cases("armv6", "armv6k", "arm1136jf-s") + .Case("armv6j", "arm1136j-s") + .Cases("armv6z", "armv6zk", "arm1176jzf-s") + .Case("armv6t2", "arm1156t2-s") + .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") + .Cases("armv7r", "armv7-r", "cortex-r4") + .Cases("armv7m", "armv7-m", "cortex-m3") + .Case("ep9312", "ep9312") + .Case("iwmmxt", "iwmmxt") + .Case("xscale", "xscale") + .Cases("armv6m", "armv6-m", "cortex-m0") + // If all else failed, return the most base CPU LLVM supports. + .Default("arm7tdmi"); } /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular @@ -441,33 +478,21 @@ static const char *getARMTargetCPU(const ArgList &Args, // // FIXME: This is redundant with -mcpu, why does LLVM use this. // FIXME: tblgen this, or kill it! -static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) { - if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" || - CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" || - CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" || - CPU == "arm940t" || CPU == "ep9312") - return "v4t"; - - if (CPU == "arm10tdmi" || CPU == "arm1020t") - return "v5"; - - if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" || - CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" || - CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" || - CPU == "iwmmxt") - return "v5e"; - - if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" || - CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore") - return "v6"; - - if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s") - return "v6t2"; - - if (CPU == "cortex-a8" || CPU == "cortex-a9") - return "v7"; - - return ""; +static const char *getLLVMArchSuffixForARM(StringRef CPU) { + return llvm::StringSwitch<const char *>(CPU) + .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") + .Cases("arm720t", "arm9", "arm9tdmi", "v4t") + .Cases("arm920", "arm920t", "arm922t", "v4t") + .Cases("arm940t", "ep9312","v4t") + .Cases("arm10tdmi", "arm1020t", "v5") + .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") + .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") + .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") + .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") + .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") + .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") + .Cases("cortex-a8", "cortex-a9", "v7") + .Default(""); } // FIXME: Move to target hook. @@ -479,7 +504,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { case llvm::Triple::arm: case llvm::Triple::ppc: case llvm::Triple::ppc64: - if (Triple.getOS() == llvm::Triple::Darwin) + if (Triple.isOSDarwin()) return true; return false; @@ -494,12 +519,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args, const Driver &D = getToolChain().getDriver(); llvm::Triple Triple = getToolChain().getTriple(); - // Disable movt generation, if requested. -#ifdef DISABLE_ARM_DARWIN_USE_MOVT - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-darwin-use-movt=0"); -#endif - // Select the ABI to use. // // FIXME: Support -meabi. @@ -528,7 +547,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. - llvm::StringRef FloatABI; + StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, options::OPT_mfloat_abi_EQ)) { @@ -539,7 +558,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, else { FloatABI = A->getValue(Args); if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") { - D.Diag(clang::diag::err_drv_invalid_mfloat_abi) + D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); FloatABI = "soft"; } @@ -550,11 +569,13 @@ void Clang::AddARMTargetArgs(const ArgList &Args, if (FloatABI.empty()) { const llvm::Triple &Triple = getToolChain().getTriple(); switch (Triple.getOS()) { - case llvm::Triple::Darwin: { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: { // Darwin defaults to "softfp" for v6 and v7. // // FIXME: Factor out an ARM class so we can cache the arch somewhere. - llvm::StringRef ArchName = + StringRef ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); if (ArchName.startswith("v6") || ArchName.startswith("v7")) FloatABI = "softfp"; @@ -583,7 +604,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; - D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; break; } } @@ -630,7 +651,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // FIXME: Centralize feature selection, defaulting shouldn't be also in the // frontend target. if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) { - llvm::StringRef FPU = A->getValue(Args); + StringRef FPU = A->getValue(Args); // Set the target features based on the FPU. if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { @@ -651,7 +672,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back("-target-feature"); CmdArgs.push_back("+neon"); } else - D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } // Setting -msoft-float effectively disables NEON because of the GCC @@ -670,42 +691,84 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back("-arm-strict-align"); // The kext linker doesn't know how to deal with movw/movt. -#ifndef DISABLE_ARM_DARWIN_USE_MOVT CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-darwin-use-movt=0"); -#endif + } + + // Setting -mno-global-merge disables the codegen global merge pass. Setting + // -mglobal-merge has no effect as the pass is enabled by default. + if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, + options::OPT_mno_global_merge)) { + if (A->getOption().matches(options::OPT_mno_global_merge)) + CmdArgs.push_back("-mno-global-merge"); } } +// Get default architecture. +static const char* getMipsArchFromCPU(StringRef CPUName) { + if (CPUName == "mips32r1" || CPUName == "4ke") + return "mips"; + + assert((CPUName == "mips64r1" || CPUName == "mips64r2") && + "Unexpected cpu name."); + + return "mips64"; +} + +// Get default target cpu. +static const char* getMipsCPUFromArch(StringRef ArchName, const Driver &D) { + if (ArchName == "mips" || ArchName == "mipsel") + return "mips32r1"; + else if (ArchName == "mips64" || ArchName == "mips64el") + return "mips64r1"; + else + D.Diag(diag::err_drv_invalid_arch_name) << ArchName; + + return 0; +} + +// Get default ABI. +static const char* getMipsABIFromArch(StringRef ArchName) { + if (ArchName == "mips" || ArchName == "mipsel") + return "o32"; + + assert((ArchName == "mips64" || ArchName == "mips64el") && + "Unexpected arch name."); + return "n64"; +} + void Clang::AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); + StringRef ArchName; + const char *CPUName; + + // Set target cpu and architecture. + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + CPUName = A->getValue(Args); + ArchName = getMipsArchFromCPU(CPUName); + } + else { + ArchName = Args.MakeArgString(getToolChain().getArchName()); + CPUName = getMipsCPUFromArch(ArchName, D); + } + + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(CPUName); + // Select the ABI to use. const char *ABIName = 0; - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(Args); - } else { - ABIName = "o32"; - } + else + ABIName = getMipsABIFromArch(ArchName); CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - llvm::StringRef MArch = A->getValue(Args); - CmdArgs.push_back("-target-cpu"); - - if ((MArch == "r2000") || (MArch == "r3000")) - CmdArgs.push_back("mips1"); - else if (MArch == "r6000") - CmdArgs.push_back("mips2"); - else - CmdArgs.push_back(Args.MakeArgString(MArch)); - } - // Select the float ABI as determined by -msoft-float, -mhard-float, and - llvm::StringRef FloatABI; + StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { if (A->getOption().matches(options::OPT_msoft_float)) @@ -718,7 +781,7 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, if (FloatABI.empty()) { // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; - D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; } if (FloatABI == "soft") { @@ -737,13 +800,13 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, const Driver &D = getToolChain().getDriver(); if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - llvm::StringRef MArch = A->getValue(Args); + StringRef MArch = A->getValue(Args); CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(MArch.str().c_str()); } // Select the float ABI as determined by -msoft-float, -mhard-float, and - llvm::StringRef FloatABI; + StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { if (A->getOption().matches(options::OPT_msoft_float)) @@ -758,7 +821,7 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; - D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; break; } } @@ -792,7 +855,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, const char *CPUName = 0; if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (llvm::StringRef(A->getValue(Args)) == "native") { + if (StringRef(A->getValue(Args)) == "native") { // FIXME: Reject attempts to use -march=native unless the target matches // the host. // @@ -808,7 +871,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, // Select the default CPU if none was given (or detection failed). if (!CPUName) { // FIXME: Need target hooks. - if (getToolChain().getOS().startswith("darwin")) { + if (getToolChain().getTriple().isOSDarwin()) { if (getToolChain().getArch() == llvm::Triple::x86_64) CPUName = "core2"; else if (getToolChain().getArch() == llvm::Triple::x86) @@ -856,7 +919,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, std::vector<const char*> Features; for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group), ie = Args.filtered_end(); it != ie; ++it) { - llvm::StringRef Name = (*it)->getOption().getName(); + StringRef Name = (*it)->getOption().getName(); (*it)->claim(); // Skip over "-m". @@ -881,7 +944,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } } -static bool +static bool shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion, const llvm::Triple &Triple) { // We use the zero-cost exception tables for Objective-C if the non-fragile @@ -891,12 +954,12 @@ shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion, if (objcABIVersion >= 2) return true; - if (Triple.getOS() != llvm::Triple::Darwin) + if (!Triple.isOSDarwin()) return false; return (!Triple.isMacOSXVersionLT(10,5) && (Triple.getArch() == llvm::Triple::x86_64 || - Triple.getArch() == llvm::Triple::arm)); + Triple.getArch() == llvm::Triple::arm)); } /// addExceptionArgs - Adds exception related arguments to the driver command @@ -922,7 +985,7 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fexceptions)) ExceptionsEnabled = true; - else + else ExceptionsEnabled = false; DidHaveExplicitExceptionFlag = true; @@ -938,20 +1001,20 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, // Obj-C exceptions are enabled by default, regardless of -fexceptions. This // is not necessarily sensible, but follows GCC. if (types::isObjC(InputType) && - Args.hasFlag(options::OPT_fobjc_exceptions, + Args.hasFlag(options::OPT_fobjc_exceptions, options::OPT_fno_objc_exceptions, true)) { CmdArgs.push_back("-fobjc-exceptions"); - ShouldUseExceptionTables |= + ShouldUseExceptionTables |= shouldUseExceptionTablesForObjCExceptions(objcABIVersion, Triple); } if (types::isCXX(InputType)) { bool CXXExceptionsEnabled = ExceptionsEnabled; - if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, - options::OPT_fno_cxx_exceptions, + if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, + options::OPT_fno_cxx_exceptions, options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fcxx_exceptions)) @@ -973,7 +1036,7 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, static bool ShouldDisableCFI(const ArgList &Args, const ToolChain &TC) { - if (TC.getTriple().getOS() == llvm::Triple::Darwin) { + if (TC.getTriple().isOSDarwin()) { // The native darwin assembler doesn't support cfi directives, so // we disable them if we think the .s file will be passed to it. @@ -1079,7 +1142,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->claim(); for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { - llvm::StringRef Value = A->getValue(Args, i); + StringRef Value = A->getValue(Args, i); if (Value == "-force_cpusubtype_ALL") { // Do nothing, this is the default and we don't support anything else. @@ -1091,7 +1154,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (Value == "--noexecstack") { CmdArgs.push_back("-mnoexecstack"); } else { - D.Diag(clang::diag::err_drv_unsupported_option_argument) + D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; } } @@ -1217,7 +1280,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else Model = getToolChain().GetDefaultRelocationModel(); } - if (llvm::StringRef(Model) != "pic") { + if (StringRef(Model) != "pic") { CmdArgs.push_back("-mrelocation-model"); CmdArgs.push_back(Model); } @@ -1275,13 +1338,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Enable -mconstructor-aliases except on darwin, where we have to // work around a linker bug; see <rdar://problem/7651567>. - if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin) + if (!getToolChain().getTriple().isOSDarwin()) CmdArgs.push_back("-mconstructor-aliases"); // Darwin's kernel doesn't support guard variables; just die if we // try to use them. - if (KernelOrKext && - getToolChain().getTriple().getOS() == llvm::Triple::Darwin) + if (KernelOrKext && getToolChain().getTriple().isOSDarwin()) CmdArgs.push_back("-fforbid-guard-variables"); if (Args.hasArg(options::OPT_mms_bitfields)) { @@ -1325,6 +1387,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::mips: case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: AddMIPSTargetArgs(Args, CmdArgs); break; @@ -1347,7 +1411,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -mno-omit-leaf-frame-pointer is the default on Darwin. if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer, options::OPT_mno_omit_leaf_frame_pointer, - getToolChain().getTriple().getOS() != llvm::Triple::Darwin)) + !getToolChain().getTriple().isOSDarwin())) CmdArgs.push_back("-momit-leaf-frame-pointer"); // -fno-math-errno is default. @@ -1362,21 +1426,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; if ((Unsupported = Args.getLastArg(options::OPT_iframework))) - D.Diag(clang::diag::err_drv_clang_unsupported) + D.Diag(diag::err_drv_clang_unsupported) << Unsupported->getOption().getName(); if (types::isCXX(InputType) && - getToolChain().getTriple().getOS() == llvm::Triple::Darwin && + getToolChain().getTriple().isOSDarwin() && getToolChain().getTriple().getArch() == llvm::Triple::x86) { - if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext))) - D.Diag(clang::diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) + if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) || + (Unsupported = Args.getLastArg(options::OPT_mkernel))) + D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) << Unsupported->getOption().getName(); } } 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 : "-"); @@ -1384,7 +1449,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 : "-"); @@ -1417,9 +1482,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - Args.AddLastArg(CmdArgs, options::OPT_nostdinc); - Args.AddLastArg(CmdArgs, options::OPT_nostdincxx); - Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc); + // Pass options for controlling the default header search paths. + if (Args.hasArg(options::OPT_nostdinc)) { + CmdArgs.push_back("-nostdsysteminc"); + CmdArgs.push_back("-nobuiltininc"); + } else { + if (Args.hasArg(options::OPT_nostdlibinc)) + CmdArgs.push_back("-nostdsysteminc"); + Args.AddLastArg(CmdArgs, options::OPT_nostdincxx); + Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc); + } // Pass the path to compiler resource files. CmdArgs.push_back("-resource-dir"); @@ -1444,11 +1516,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-arcmt-migrate"); CmdArgs.push_back("-arcmt-migrate-directory"); CmdArgs.push_back(A->getValue(Args)); + + Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output); + Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors); break; } } } - + // Add preprocessing options like -I, -D, etc. if we are using the // preprocessor. // @@ -1456,6 +1531,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (types::getPreprocessedType(InputType) != types::TY_INVALID) AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs); + // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes + // that "The compiler can only warn and ignore the option if not recognized". + // When building with ccache, it will pass -D options to clang even on + // preprocessed inputs and configure concludes that -fPIC is not supported. + Args.ClaimAllArgs(options::OPT_D); + // Manually translate -O to -O2 and -O4 to -O3; let clang reject // others. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { @@ -1584,7 +1665,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // If -fmessage-length=N was not specified, determine whether this is a // terminal and, if so, implicitly define -fmessage-length appropriately. unsigned N = llvm::sys::Process::StandardErrColumns(); - CmdArgs.push_back(Args.MakeArgString(llvm::Twine(N))); + CmdArgs.push_back(Args.MakeArgString(Twine(N))); } if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) { @@ -1630,7 +1711,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -ftrap_function= options to the backend. if (Arg *A = Args.getLastArg(options::OPT_ftrap_function_EQ)) { - llvm::StringRef FuncName = A->getValue(Args); + StringRef FuncName = A->getValue(Args); CmdArgs.push_back("-backend-option"); CmdArgs.push_back(Args.MakeArgString("-trap-func=" + FuncName)); } @@ -1660,11 +1741,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, StackProtectorLevel = 1; else if (A->getOption().matches(options::OPT_fstack_protector_all)) StackProtectorLevel = 2; - } else - StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel(); + } else { + StackProtectorLevel = + getToolChain().GetDefaultStackProtectorLevel(KernelOrKext); + } if (StackProtectorLevel) { CmdArgs.push_back("-stack-protector"); - CmdArgs.push_back(Args.MakeArgString(llvm::Twine(StackProtectorLevel))); + CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel))); } // Translate -mstackrealign @@ -1672,7 +1755,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-force-align-stack"); } - + // Forward -f options with positive and negative forms; we translate // these by hand. @@ -1697,6 +1780,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.hasArg(options::OPT_fobjc_nonfragile_abi) && !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); + + if (!Args.hasArg(options::OPT_fgnu_runtime) && + !getToolChain().hasBlocksRuntime()) + CmdArgs.push_back("-fblocks-runtime-optional"); } // -faccess-control is default. @@ -1744,11 +1831,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) CmdArgs.push_back("-fms-extensions"); + // -fms-compatibility=0 is default. + if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, + getToolChain().getTriple().getOS() == llvm::Triple::Win32)) + CmdArgs.push_back("-fms-compatibility"); + // -fmsc-version=1300 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, getToolChain().getTriple().getOS() == llvm::Triple::Win32) || Args.hasArg(options::OPT_fmsc_version)) { - llvm::StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); + StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); if (msc_ver.empty()) CmdArgs.push_back("-fmsc-version=1300"); else @@ -1761,10 +1853,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_borland_extensions, false)) CmdArgs.push_back("-fborland-extensions"); - // -fno-delayed-template-parsing is default. + // -fno-delayed-template-parsing is default, except for Windows where MSVC STL + // needs it. if (Args.hasFlag(options::OPT_fdelayed_template_parsing, options::OPT_fno_delayed_template_parsing, - false)) + getToolChain().getTriple().getOS() == llvm::Triple::Win32)) CmdArgs.push_back("-fdelayed-template-parsing"); // -fgnu-keywords default varies depending on language; only pass if @@ -1781,96 +1874,90 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fobjc-nonfragile-abi=0 is default. ObjCRuntime objCRuntime; unsigned objcABIVersion = 0; - if (types::isObjC(InputType)) { - bool NeXTRuntimeIsDefault - = (IsRewriter || getToolChain().getTriple().isOSDarwin()); - if (Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime, - NeXTRuntimeIsDefault)) { - objCRuntime.setKind(ObjCRuntime::NeXT); - } else { - CmdArgs.push_back("-fgnu-runtime"); - objCRuntime.setKind(ObjCRuntime::GNU); - } - getToolChain().configureObjCRuntime(objCRuntime); - if (objCRuntime.HasARC) - CmdArgs.push_back("-fobjc-runtime-has-arc"); - if (objCRuntime.HasWeak) - CmdArgs.push_back("-fobjc-runtime-has-weak"); - if (objCRuntime.HasTerminate) - CmdArgs.push_back("-fobjc-runtime-has-terminate"); - - // Compute the Objective-C ABI "version" to use. Version numbers are - // slightly confusing for historical reasons: - // 1 - Traditional "fragile" ABI - // 2 - Non-fragile ABI, version 1 - // 3 - Non-fragile ABI, version 2 - objcABIVersion = 1; - // If -fobjc-abi-version= is present, use that to set the version. - if (Arg *A = Args.getLastArg(options::OPT_fobjc_abi_version_EQ)) { - if (llvm::StringRef(A->getValue(Args)) == "1") - objcABIVersion = 1; - else if (llvm::StringRef(A->getValue(Args)) == "2") - objcABIVersion = 2; - else if (llvm::StringRef(A->getValue(Args)) == "3") - objcABIVersion = 3; - else - D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); - } else { - // Otherwise, determine if we are using the non-fragile ABI. - if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi, - options::OPT_fno_objc_nonfragile_abi, - getToolChain().IsObjCNonFragileABIDefault())) { - // Determine the non-fragile ABI version to use. + bool NeXTRuntimeIsDefault + = (IsRewriter || getToolChain().getTriple().isOSDarwin()); + if (Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime, + NeXTRuntimeIsDefault)) { + objCRuntime.setKind(ObjCRuntime::NeXT); + } else { + CmdArgs.push_back("-fgnu-runtime"); + objCRuntime.setKind(ObjCRuntime::GNU); + } + getToolChain().configureObjCRuntime(objCRuntime); + if (objCRuntime.HasARC) + CmdArgs.push_back("-fobjc-runtime-has-arc"); + if (objCRuntime.HasWeak) + CmdArgs.push_back("-fobjc-runtime-has-weak"); + if (objCRuntime.HasTerminate) + CmdArgs.push_back("-fobjc-runtime-has-terminate"); + + // Compute the Objective-C ABI "version" to use. Version numbers are + // slightly confusing for historical reasons: + // 1 - Traditional "fragile" ABI + // 2 - Non-fragile ABI, version 1 + // 3 - Non-fragile ABI, version 2 + objcABIVersion = 1; + // If -fobjc-abi-version= is present, use that to set the version. + if (Arg *A = Args.getLastArg(options::OPT_fobjc_abi_version_EQ)) { + if (StringRef(A->getValue(Args)) == "1") + objcABIVersion = 1; + else if (StringRef(A->getValue(Args)) == "2") + objcABIVersion = 2; + else if (StringRef(A->getValue(Args)) == "3") + objcABIVersion = 3; + else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + } else { + // Otherwise, determine if we are using the non-fragile ABI. + bool NonFragileABIIsDefault + = (!IsRewriter && getToolChain().IsObjCNonFragileABIDefault()); + if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi, + options::OPT_fno_objc_nonfragile_abi, + NonFragileABIIsDefault)) { + // Determine the non-fragile ABI version to use. #ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO - unsigned NonFragileABIVersion = 1; + unsigned NonFragileABIVersion = 1; #else - unsigned NonFragileABIVersion = 2; + unsigned NonFragileABIVersion = 2; #endif - if (Arg *A = Args.getLastArg( - options::OPT_fobjc_nonfragile_abi_version_EQ)) { - if (llvm::StringRef(A->getValue(Args)) == "1") - NonFragileABIVersion = 1; - else if (llvm::StringRef(A->getValue(Args)) == "2") - NonFragileABIVersion = 2; - else - D.Diag(clang::diag::err_drv_clang_unsupported) - << A->getAsString(Args); - } - - objcABIVersion = 1 + NonFragileABIVersion; - } else { - objcABIVersion = 1; - } - } - - if (objcABIVersion == 2 || objcABIVersion == 3) { - CmdArgs.push_back("-fobjc-nonfragile-abi"); - - // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and - // legacy is the default. - if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch, - options::OPT_fno_objc_legacy_dispatch, - getToolChain().IsObjCLegacyDispatchDefault())) { - if (getToolChain().UseObjCMixedDispatch()) - CmdArgs.push_back("-fobjc-dispatch-method=mixed"); + if (Arg *A = Args.getLastArg( + options::OPT_fobjc_nonfragile_abi_version_EQ)) { + if (StringRef(A->getValue(Args)) == "1") + NonFragileABIVersion = 1; + else if (StringRef(A->getValue(Args)) == "2") + NonFragileABIVersion = 2; else - CmdArgs.push_back("-fobjc-dispatch-method=non-legacy"); + D.Diag(diag::err_drv_clang_unsupported) + << A->getAsString(Args); } + + objcABIVersion = 1 + NonFragileABIVersion; + } else { + objcABIVersion = 1; } + } - // FIXME: Don't expose -fobjc-default-synthesize-properties as a top-level - // driver flag yet. This feature is still under active development - // and shouldn't be exposed as a user visible feature (which may change). - // Clang still supports this as a -cc1 option for development and testing. -#if 0 - // -fobjc-default-synthesize-properties=0 is default. - if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties, - options::OPT_fno_objc_default_synthesize_properties, - getToolChain().IsObjCDefaultSynthPropertiesDefault())) { - CmdArgs.push_back("-fobjc-default-synthesize-properties"); + if (objcABIVersion == 1) { + CmdArgs.push_back("-fobjc-fragile-abi"); + } else { + // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and + // legacy is the default. + if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch, + options::OPT_fno_objc_legacy_dispatch, + getToolChain().IsObjCLegacyDispatchDefault())) { + if (getToolChain().UseObjCMixedDispatch()) + CmdArgs.push_back("-fobjc-dispatch-method=mixed"); + else + CmdArgs.push_back("-fobjc-dispatch-method=non-legacy"); } -#endif + } + + // -fobjc-default-synthesize-properties=0 is default. + if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties, + options::OPT_fno_objc_default_synthesize_properties, + getToolChain().IsObjCDefaultSynthPropertiesDefault())) { + CmdArgs.push_back("-fobjc-default-synthesize-properties"); } // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc. @@ -1891,7 +1978,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // rewriter. if (IsRewriter) CmdArgs.push_back("-fno-objc-infer-related-result-type"); - + // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only // takes precedence. const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only); @@ -1899,13 +1986,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, GCArg = Args.getLastArg(options::OPT_fobjc_gc); if (GCArg) { if (ARC) { - D.Diag(clang::diag::err_drv_objc_gc_arr) + D.Diag(diag::err_drv_objc_gc_arr) << GCArg->getAsString(Args); } else if (getToolChain().SupportsObjCGC()) { GCArg->render(Args, CmdArgs); } else { // FIXME: We should move this to a hard error. - D.Diag(clang::diag::warn_drv_objc_gc_unsupported) + D.Diag(diag::warn_drv_objc_gc_unsupported) << GCArg->getAsString(Args); } } @@ -1948,11 +2035,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fpascal-strings"); + // Honor -fpack-struct= and -fpack-struct, if given. Note that + // -fno-pack-struct doesn't apply to -fpack-struct=. + if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) { + CmdArgs.push_back("-fpack-struct"); + CmdArgs.push_back(A->getValue(Args)); + } else if (Args.hasFlag(options::OPT_fpack_struct, + options::OPT_fno_pack_struct, false)) { + CmdArgs.push_back("-fpack-struct"); + CmdArgs.push_back("1"); + } + if (Args.hasArg(options::OPT_mkernel) || Args.hasArg(options::OPT_fapple_kext)) { if (!Args.hasArg(options::OPT_fcommon)) CmdArgs.push_back("-fno-common"); } + // -fcommon is default, only pass non-default. else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common)) CmdArgs.push_back("-fno-common"); @@ -1961,13 +2060,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -funsigned-bitfields. if (!Args.hasFlag(options::OPT_fsigned_bitfields, options::OPT_funsigned_bitfields)) - D.Diag(clang::diag::warn_drv_clang_unsupported) + D.Diag(diag::warn_drv_clang_unsupported) << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args); // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope. if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope)) - D.Diag(clang::diag::err_drv_clang_unsupported) + D.Diag(diag::err_drv_clang_unsupported) << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args); // -fcaret-diagnostics is default. @@ -1979,7 +2078,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info, options::OPT_fno_diagnostics_fixit_info)) CmdArgs.push_back("-fno-diagnostics-fixit-info"); - + // Enable -fdiagnostics-show-name by default. if (Args.hasFlag(options::OPT_fdiagnostics_show_name, options::OPT_fno_diagnostics_show_name, false)) @@ -2055,14 +2154,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time, options::OPT_fno_unit_at_a_time)) { if (A->getOption().matches(options::OPT_fno_unit_at_a_time)) - D.Diag(clang::diag::warn_drv_clang_unsupported) << A->getAsString(Args); + D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); } // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM. // // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941. #if 0 - if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin && + if (getToolChain().getTriple().isOSDarwin() && (getToolChain().getTriple().getArch() == llvm::Triple::arm || getToolChain().getTriple().getArch() == llvm::Triple::thumb)) { if (!Args.hasArg(options::OPT_fbuiltin_strcat)) @@ -2077,8 +2176,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_traditional_cpp)) { if (isa<PreprocessJobAction>(JA)) CmdArgs.push_back("-traditional-cpp"); - else - D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } Args.AddLastArg(CmdArgs, options::OPT_dM); @@ -2093,7 +2192,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // We translate this by hand to the -cc1 argument, since nightly test uses // it and developers have been trained to spell it with -mllvm. - if (llvm::StringRef((*it)->getValue(Args, 0)) == "-disable-llvm-optzns") + if (StringRef((*it)->getValue(Args, 0)) == "-disable-llvm-optzns") CmdArgs.push_back("-disable-llvm-optzns"); else (*it)->render(Args, CmdArgs); @@ -2145,7 +2244,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_pg)) if (Args.hasArg(options::OPT_fomit_frame_pointer)) - D.Diag(clang::diag::err_drv_argument_not_allowed_with) + D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); // Claim some arguments which clang supports automatically. @@ -2189,7 +2288,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Add the "effective" target triple. CmdArgs.push_back("-triple"); - std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); + std::string TripleStr = + getToolChain().ComputeEffectiveClangTriple(Args, Input.getType()); CmdArgs.push_back(Args.MakeArgString(TripleStr)); // Set the output mode, we currently only expect to be used as a real @@ -2252,7 +2352,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // If using a driver driver, force the arch. const std::string &Arch = getToolChain().getArchName(); - if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin) { + if (getToolChain().getTriple().isOSDarwin()) { CmdArgs.push_back("-arch"); // FIXME: Remove these special cases. @@ -2298,10 +2398,10 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // Don't try to pass LLVM or AST inputs to a generic gcc. if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) - D.Diag(clang::diag::err_drv_no_linker_llvm_support) + D.Diag(diag::err_drv_no_linker_llvm_support) << getToolChain().getTripleString(); else if (II.getType() == types::TY_AST) - D.Diag(clang::diag::err_drv_no_ast_support) + D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString(); if (types::canTypeBeUserSpecified(II.getType())) { @@ -2364,7 +2464,7 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, CmdArgs.push_back("-c"); else { if (JA.getType() != types::TY_PP_Asm) - D.Diag(clang::diag::err_drv_invalid_gcc_output_type) + D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType()); CmdArgs.push_back("-S"); @@ -2384,19 +2484,21 @@ void gcc::Link::RenderExtraToolArgs(const JobAction &JA, const char *darwin::CC1::getCC1Name(types::ID Type) const { switch (Type) { default: - assert(0 && "Unexpected type for Darwin CC1 tool."); + llvm_unreachable("Unexpected type for Darwin CC1 tool."); case types::TY_Asm: case types::TY_C: case types::TY_CHeader: case types::TY_PP_C: case types::TY_PP_CHeader: return "cc1"; case types::TY_ObjC: case types::TY_ObjCHeader: - case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader: + case types::TY_PP_ObjC: case types::TY_PP_ObjC_Alias: + case types::TY_PP_ObjCHeader: return "cc1obj"; case types::TY_CXX: case types::TY_CXXHeader: case types::TY_PP_CXX: case types::TY_PP_CXXHeader: return "cc1plus"; case types::TY_ObjCXX: case types::TY_ObjCXXHeader: - case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader: + case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXX_Alias: + case types::TY_PP_ObjCXXHeader: return "cc1objplus"; } } @@ -2425,14 +2527,145 @@ darwin::CC1::getDependencyFileName(const ArgList &Args, if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { std::string Str(OutputOpt->getValue(Args)); - Res = Str.substr(0, Str.rfind('.')); - } else + } else { Res = darwin::CC1::getBaseInputStem(Args, Inputs); - + } return Args.MakeArgString(Res + ".d"); } +void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { + for (ArgStringList::iterator it = CmdArgs.begin(), ie = CmdArgs.end(); + it != ie;) { + + StringRef Option = *it; + bool RemoveOption = false; + + // Remove -faltivec + if (Option.equals("-faltivec")) { + it = CmdArgs.erase(it); + ie = CmdArgs.end(); + continue; + } + + // Handle machine specific options. + if (Option.startswith("-m")) { + RemoveOption = llvm::StringSwitch<bool>(Option) + .Case("-mthumb", true) + .Case("-mno-thumb", true) + .Case("-mno-fused-madd", true) + .Case("-mlong-branch", true) + .Case("-mlongcall", true) + .Case("-mcpu=G4", true) + .Case("-mcpu=G5", true) + .Default(false); + } + + // Handle warning options. + if (Option.startswith("-W")) { + // Remove -W/-Wno- to reduce the number of cases. + if (Option.startswith("-Wno-")) + Option = Option.substr(5); + else + Option = Option.substr(2); + + RemoveOption = llvm::StringSwitch<bool>(Option) + .Case("address-of-temporary", true) + .Case("ambiguous-member-template", true) + .Case("analyzer-incompatible-plugin", true) + .Case("array-bounds", true) + .Case("array-bounds-pointer-arithmetic", true) + .Case("bind-to-temporary-copy", true) + .Case("bitwise-op-parentheses", true) + .Case("bool-conversions", true) + .Case("builtin-macro-redefined", true) + .Case("c++-hex-floats", true) + .Case("c++0x-compat", true) + .Case("c++0x-extensions", true) + .Case("c++0x-narrowing", true) + .Case("c++11-compat", true) + .Case("c++11-extensions", true) + .Case("c++11-narrowing", true) + .Case("conditional-uninitialized", true) + .Case("constant-conversion", true) + .Case("CFString-literal", true) + .Case("constant-logical-operand", true) + .Case("custom-atomic-properties", true) + .Case("default-arg-special-member", true) + .Case("delegating-ctor-cycles", true) + .Case("delete-non-virtual-dtor", true) + .Case("deprecated-implementations", true) + .Case("deprecated-writable-strings", true) + .Case("distributed-object-modifiers", true) + .Case("duplicate-method-arg", true) + .Case("dynamic-class-memaccess", true) + .Case("enum-compare", true) + .Case("exit-time-destructors", true) + .Case("gnu", true) + .Case("gnu-designator", true) + .Case("header-hygiene", true) + .Case("idiomatic-parentheses", true) + .Case("ignored-qualifiers", true) + .Case("implicit-atomic-properties", true) + .Case("incompatible-pointer-types", true) + .Case("incomplete-implementation", true) + .Case("initializer-overrides", true) + .Case("invalid-noreturn", true) + .Case("invalid-token-paste", true) + .Case("language-extension-token", true) + .Case("literal-conversion", true) + .Case("literal-range", true) + .Case("local-type-template-args", true) + .Case("logical-op-parentheses", true) + .Case("method-signatures", true) + .Case("microsoft", true) + .Case("mismatched-tags", true) + .Case("missing-method-return-type", true) + .Case("non-pod-varargs", true) + .Case("nonfragile-abi2", true) + .Case("null-arithmetic", true) + .Case("null-dereference", true) + .Case("out-of-line-declaration", true) + .Case("overriding-method-mismatch", true) + .Case("readonly-setter-attrs", true) + .Case("return-stack-address", true) + .Case("self-assign", true) + .Case("semicolon-before-method-body", true) + .Case("sentinel", true) + .Case("shift-overflow", true) + .Case("shift-sign-overflow", true) + .Case("sign-conversion", true) + .Case("sizeof-array-argument", true) + .Case("sizeof-pointer-memaccess", true) + .Case("string-compare", true) + .Case("super-class-method-mismatch", true) + .Case("tautological-compare", true) + .Case("typedef-redefinition", true) + .Case("typename-missing", true) + .Case("undefined-reinterpret-cast", true) + .Case("unknown-warning-option", true) + .Case("unnamed-type-template-args", true) + .Case("unneeded-internal-declaration", true) + .Case("unneeded-member-function", true) + .Case("unused-comparison", true) + .Case("unused-exception-parameter", true) + .Case("unused-member-function", true) + .Case("unused-result", true) + .Case("vector-conversions", true) + .Case("vla", true) + .Case("used-but-marked-unused", true) + .Case("weak-vtables", true) + .Default(false); + } // if (Option.startswith("-W")) + if (RemoveOption) { + it = CmdArgs.erase(it); + ie = CmdArgs.end(); + } else { + ++it; + } + } +} + void darwin::CC1::AddCC1Args(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); @@ -2470,7 +2703,7 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, if (Arg *A = Args.getLastArg(options::OPT_pg)) if (Args.hasArg(options::OPT_fomit_frame_pointer)) - D.Diag(clang::diag::err_drv_argument_not_allowed_with) + D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "-fomit-frame-pointer"; AddCC1Args(Args, CmdArgs); @@ -2742,6 +2975,8 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_d_Group); + RemoveCC1UnsupportedArgs(CmdArgs); + const char *CC1Name = getCC1Name(Inputs[0].getType()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(CC1Name)); @@ -2761,7 +2996,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, types::ID InputType = Inputs[0].getType(); const Arg *A; if ((A = Args.getLastArg(options::OPT_traditional))) - D.Diag(clang::diag::err_drv_argument_only_allowed_with) + D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; if (JA.getType() == types::TY_LLVM_IR || @@ -2771,11 +3006,11 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, JA.getType() == types::TY_LTO_BC) CmdArgs.push_back("-emit-llvm-bc"); else if (Output.getType() == types::TY_AST) - D.Diag(clang::diag::err_drv_no_ast_support) + D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString(); else if (JA.getType() != types::TY_PP_Asm && JA.getType() != types::TY_PCH) - D.Diag(clang::diag::err_drv_invalid_gcc_output_type) + D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType()); ArgStringList OutputArgs; @@ -2809,7 +3044,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, // Reject AST inputs. if (II.getType() == types::TY_AST) { - D.Diag(clang::diag::err_drv_no_ast_support) + D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString(); return; } @@ -2831,12 +3066,23 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); // NOTE: gcc uses a temp .s file for this, but there doesn't seem // to be a good reason. - CmdArgs.push_back("/dev/null"); + const char *TmpPath = C.getArgs().MakeArgString( + D.GetTemporaryPath("cc", "s")); + C.addTempFile(TmpPath); + CmdArgs.push_back(TmpPath); - CmdArgs.push_back("--output-pch="); - CmdArgs.push_back(Output.getFilename()); + // If we're emitting a pch file with the last 4 characters of ".pth" + // and falling back to llvm-gcc we want to use ".gch" instead. + std::string OutputFile(Output.getFilename()); + size_t loc = OutputFile.rfind(".pth"); + if (loc != std::string::npos) + OutputFile.replace(loc, 4, ".gch"); + const char *Tmp = C.getArgs().MakeArgString("--output-pch="+OutputFile); + CmdArgs.push_back(Tmp); } + RemoveCC1UnsupportedArgs(CmdArgs); + const char *CC1Name = getCC1Name(Inputs[0].getType()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(CC1Name)); @@ -2861,7 +3107,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } // Forward -g, assuming we are dealing with an actual assembly file. - if (SourceAction->getType() == types::TY_Asm || + if (SourceAction->getType() == types::TY_Asm || SourceAction->getType() == types::TY_PP_Asm) { if (Args.hasArg(options::OPT_gstabs)) CmdArgs.push_back("--gstabs"); @@ -2903,7 +3149,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const { - llvm::StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); + StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); // Derived from darwin_arch spec. CmdArgs.push_back("-arch"); @@ -2926,7 +3172,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, if (!Driver::GetReleaseVersion(A->getValue(Args), Version[0], Version[1], Version[2], HadExtra) || HadExtra) - D.Diag(clang::diag::err_drv_invalid_version_number) + D.Diag(diag::err_drv_invalid_version_number) << A->getAsString(Args); } @@ -2950,7 +3196,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) - if (llvm::StringRef(A->getValue(Args, i)) == "-kext") + if (StringRef(A->getValue(Args, i)) == "-kext") UsesLdClassic = true; } } @@ -2963,7 +3209,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, // dsymutil step. if (Version[0] >= 116 && D.IsUsingLTO(Args)) { const char *TmpPath = C.getArgs().MakeArgString( - D.GetTemporaryPath(types::getTypeTempSuffix(types::TY_Object))); + D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object))); C.addTempFile(TmpPath); CmdArgs.push_back("-object_path_lto"); CmdArgs.push_back(TmpPath); @@ -2991,7 +3237,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, if ((A = Args.getLastArg(options::OPT_compatibility__version)) || (A = Args.getLastArg(options::OPT_current__version)) || (A = Args.getLastArg(options::OPT_install__name))) - D.Diag(clang::diag::err_drv_argument_only_allowed_with) + D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-dynamiclib"; Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace); @@ -3007,7 +3253,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, (A = Args.getLastArg(options::OPT_force__flat__namespace)) || (A = Args.getLastArg(options::OPT_keep__private__externs)) || (A = Args.getLastArg(options::OPT_private__bundle))) - D.Diag(clang::diag::err_drv_argument_not_allowed_with) + D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "-dynamiclib"; Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version, @@ -3054,9 +3300,9 @@ void darwin::Link::AddLinkArgs(Compilation &C, CmdArgs.push_back("-iphoneos_version_min"); else CmdArgs.push_back("-macosx_version_min"); - CmdArgs.push_back(Args.MakeArgString(llvm::Twine(TargetVersion[0]) + "." + - llvm::Twine(TargetVersion[1]) + "." + - llvm::Twine(TargetVersion[2]))); + CmdArgs.push_back(Args.MakeArgString(Twine(TargetVersion[0]) + "." + + Twine(TargetVersion[1]) + "." + + Twine(TargetVersion[2]))); Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); @@ -3139,6 +3385,18 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // more information. ArgStringList CmdArgs; + /// Hack(tm) to ignore linking errors when we are doing ARC migration. + if (Args.hasArg(options::OPT_ccc_arcmt_check, + options::OPT_ccc_arcmt_migrate)) { + for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) + (*I)->claim(); + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("touch")); + CmdArgs.push_back(Output.getFilename()); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + return; + } + // I'm not sure why this particular decomposition exists in gcc, but // we follow suite for ease of comparison. AddLinkArgs(C, Args, CmdArgs); @@ -3346,6 +3604,26 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + CmdArgs.push_back("--verify"); + + assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); + const InputInfo &Input = Inputs[0]; + assert(Input.isFilename() && "Unexpected verify input"); + + // Grabbing the output of the earlier dsymutil run. + CmdArgs.push_back(Input.getFilename()); + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -3664,9 +3942,11 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("gcrt1.o"))); - else + else { + const char *crt = Args.hasArg(options::OPT_pie) ? "Scrt1.o" : "crt1.o"; CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crt1.o"))); + getToolChain().GetFilePath(crt))); + } CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString( @@ -3683,7 +3963,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const ToolChain::path_list Paths = getToolChain().getFilePaths(); for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) - CmdArgs.push_back(Args.MakeArgString(llvm::StringRef("-L") + *i)); + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -3798,9 +4078,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); } - const char *Exec = Args.MakeArgString(FindTargetProgramPath(getToolChain(), - ToolTriple.getTriple(), - "as")); + const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -3916,9 +4194,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - const char *Exec = Args.MakeArgString(FindTargetProgramPath(getToolChain(), - ToolTriple.getTriple(), - "ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -3936,7 +4212,7 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } else if (getToolChain().getArch() == llvm::Triple::x86_64) { CmdArgs.push_back("--64"); } else if (getToolChain().getArch() == llvm::Triple::arm) { - llvm::StringRef MArch = getToolChain().getArchName(); + StringRef MArch = getToolChain().getArchName(); if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") CmdArgs.push_back("-mfpu=neon"); } @@ -4000,7 +4276,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-m"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("elf_i386"); - else if (ToolChain.getArch() == llvm::Triple::arm + else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); else if (ToolChain.getArch() == llvm::Triple::ppc) @@ -4071,7 +4347,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) - CmdArgs.push_back(Args.MakeArgString(llvm::StringRef("-L") + *i)); + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index 1741d05..a4f732e 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -178,6 +178,7 @@ namespace darwin { const char *getCC1Name(types::ID Type) const; void AddCC1Args(const ArgList &Args, ArgStringList &CmdArgs) const; + void RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const; void AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, const InputInfoList &Inputs, const ArgStringList &OutputArgs) const; @@ -276,6 +277,21 @@ namespace darwin { const ArgList &TCArgs, const char *LinkingOutput) const; }; + + class LLVM_LIBRARY_VISIBILITY VerifyDebug : public DarwinTool { + public: + VerifyDebug(const ToolChain &TC) : DarwinTool("darwin::VerifyDebug", + "dwarfdump", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + } /// openbsd -- Directly call GNU Binutils assembler and linker diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp index 4a4312b..d61ab68 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp @@ -79,10 +79,11 @@ bool types::isAcceptedByClang(ID Id) { case TY_C: case TY_PP_C: case TY_CL: case TY_CUDA: - case TY_ObjC: case TY_PP_ObjC: + case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: case TY_CXX: case TY_PP_CXX: - case TY_ObjCXX: case TY_PP_ObjCXX: + case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: case TY_CHeader: case TY_PP_CHeader: + case TY_CLHeader: case TY_ObjCHeader: case TY_PP_ObjCHeader: case TY_CXXHeader: case TY_PP_CXXHeader: case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: @@ -110,10 +111,10 @@ bool types::isObjC(ID Id) { default: return false; - case TY_ObjC: case TY_PP_ObjC: + case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: case TY_ObjCXX: case TY_PP_ObjCXX: case TY_ObjCHeader: case TY_PP_ObjCHeader: - case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: + case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias: return true; } } @@ -144,6 +145,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) { .Case("F", TY_Fortran) .Case("s", TY_PP_Asm) .Case("S", TY_Asm) + .Case("o", TY_Object) .Case("ii", TY_PP_CXX) .Case("mi", TY_PP_ObjC) .Case("mm", TY_ObjCXX) |