diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Arg.cpp | 34 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ArgList.cpp | 41 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp | 14 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Compilation.cpp | 100 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 248 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp | 14 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/OptTable.cpp | 158 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Option.cpp | 333 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h | 106 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp | 61 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 481 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.h | 43 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 974 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.h | 5 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Types.cpp | 14 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp | 14 |
16 files changed, 1549 insertions, 1091 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp index c0a2a50..93d70a9 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Arg.h" +#include "clang/Basic/LLVM.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" #include "llvm/ADT/SmallString.h" @@ -15,22 +16,23 @@ #include "llvm/Support/raw_ostream.h" using namespace clang::driver; +using clang::StringRef; -Arg::Arg(const Option *_Opt, unsigned _Index, const Arg *_BaseArg) - : Opt(_Opt), BaseArg(_BaseArg), Index(_Index), +Arg::Arg(const Option _Opt, StringRef S, unsigned _Index, const Arg *_BaseArg) + : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index), Claimed(false), OwnsValues(false) { } -Arg::Arg(const Option *_Opt, unsigned _Index, +Arg::Arg(const Option _Opt, StringRef S, unsigned _Index, const char *Value0, const Arg *_BaseArg) - : Opt(_Opt), BaseArg(_BaseArg), Index(_Index), + : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index), Claimed(false), OwnsValues(false) { Values.push_back(Value0); } -Arg::Arg(const Option *_Opt, unsigned _Index, +Arg::Arg(const Option _Opt, StringRef S, unsigned _Index, const char *Value0, const char *Value1, const Arg *_BaseArg) - : Opt(_Opt), BaseArg(_BaseArg), Index(_Index), + : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index), Claimed(false), OwnsValues(false) { Values.push_back(Value0); Values.push_back(Value1); @@ -47,7 +49,7 @@ void Arg::dump() const { llvm::errs() << "<"; llvm::errs() << " Opt:"; - Opt->dump(); + Opt.dump(); llvm::errs() << " Index:" << Index; @@ -83,39 +85,39 @@ void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const { } for (unsigned i = 0, e = getNumValues(); i != e; ++i) - Output.push_back(getValue(Args, i)); + Output.push_back(getValue(i)); } void Arg::render(const ArgList &Args, ArgStringList &Output) const { switch (getOption().getRenderStyle()) { case Option::RenderValuesStyle: for (unsigned i = 0, e = getNumValues(); i != e; ++i) - Output.push_back(getValue(Args, i)); + Output.push_back(getValue(i)); break; case Option::RenderCommaJoinedStyle: { SmallString<256> Res; llvm::raw_svector_ostream OS(Res); - OS << getOption().getName(); + OS << getSpelling(); for (unsigned i = 0, e = getNumValues(); i != e; ++i) { if (i) OS << ','; - OS << getValue(Args, i); + OS << getValue(i); } Output.push_back(Args.MakeArgString(OS.str())); break; } - + case Option::RenderJoinedStyle: Output.push_back(Args.GetOrMakeJoinedArgString( - getIndex(), getOption().getName(), getValue(Args, 0))); + getIndex(), getSpelling(), getValue(0))); for (unsigned i = 1, e = getNumValues(); i != e; ++i) - Output.push_back(getValue(Args, i)); + Output.push_back(getValue(i)); break; case Option::RenderSeparateStyle: - Output.push_back(getOption().getName().data()); + Output.push_back(Args.MakeArgString(getSpelling())); for (unsigned i = 0, e = getNumValues(); i != e; ++i) - Output.push_back(getValue(Args, i)); + Output.push_back(getValue(i)); break; } } diff --git a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp index 7fd439e..b3a43df 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp @@ -211,7 +211,7 @@ bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { StringRef ArgList::getLastArgValue(OptSpecifier Id, StringRef Default) const { if (Arg *A = getLastArg(Id)) - return A->getValue(*this); + return A->getValue(); return Default; } @@ -220,10 +220,10 @@ int ArgList::getLastArgIntValue(OptSpecifier Id, int Default, int Res = Default; if (Arg *A = getLastArg(Id)) { - if (StringRef(A->getValue(*this)).getAsInteger(10, Res)) { + if (StringRef(A->getValue()).getAsInteger(10, Res)) { if (Diags) Diags->Report(diag::err_drv_invalid_int_value) - << A->getAsString(*this) << A->getValue(*this); + << A->getAsString(*this) << A->getValue(); } } @@ -258,7 +258,7 @@ void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, ie = filtered_end(); it != ie; ++it) { (*it)->claim(); for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i) - Output.push_back((*it)->getValue(*this, i)); + Output.push_back((*it)->getValue(i)); } } @@ -271,10 +271,10 @@ void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, if (Joined) { Output.push_back(MakeArgString(StringRef(Translation) + - (*it)->getValue(*this, 0))); + (*it)->getValue(0))); } else { Output.push_back(Translation); - Output.push_back((*it)->getValue(*this, 0)); + Output.push_back((*it)->getValue(0)); } } } @@ -362,33 +362,40 @@ const char *DerivedArgList::MakeArgString(StringRef Str) const { return BaseArgs.MakeArgString(Str); } -Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const { - Arg *A = new Arg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg); +Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const { + Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + + Twine(Opt.getName())), + BaseArgs.MakeIndex(Opt.getName()), BaseArg); SynthesizedArgs.push_back(A); return A; } -Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt, +Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt, StringRef Value) const { unsigned Index = BaseArgs.MakeIndex(Value); - Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index), BaseArg); + Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + + Twine(Opt.getName())), + Index, BaseArgs.getArgString(Index), BaseArg); SynthesizedArgs.push_back(A); return A; } -Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt, +Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt, StringRef Value) const { - unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value); - Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index + 1), BaseArg); + unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value); + Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + + Twine(Opt.getName())), + Index, BaseArgs.getArgString(Index + 1), BaseArg); SynthesizedArgs.push_back(A); return A; } -Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt, +Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt, StringRef Value) const { - unsigned Index = BaseArgs.MakeIndex(Opt->getName().str() + Value.str()); - Arg *A = new Arg(Opt, Index, - BaseArgs.getArgString(Index) + Opt->getName().size(), + unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str()); + Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) + + Twine(Opt.getName())), Index, + BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg); SynthesizedArgs.push_back(A); return A; diff --git a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp index ea80f5a..4f89b73 100644 --- a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp @@ -15,11 +15,19 @@ using namespace clang::driver; using namespace clang::driver::options; using namespace clang::driver::cc1asoptions; +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) +#include "clang/Driver/CC1AsOptions.inc" +#undef OPTION +#undef PREFIX + static const OptTable::Info CC1AsInfoTable[] = { -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ +#define PREFIX(NAME, VALUE) +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) \ - { NAME, HELPTEXT, METAVAR, Option::KIND##Class, PARAM, FLAGS, \ - OPT_##GROUP, OPT_##ALIAS }, + { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \ + FLAGS, OPT_##GROUP, OPT_##ALIAS }, #include "clang/Driver/CC1AsOptions.inc" }; diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index c962fca..124e50c 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -17,6 +17,7 @@ #include "clang/Driver/ToolChain.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Program.h" #include <sys/stat.h> @@ -101,6 +102,105 @@ void Compilation::PrintJob(raw_ostream &OS, const Job &J, } } +static bool skipArg(const char *Flag, bool &SkipNextArg) { + StringRef FlagRef(Flag); + + // Assume we're going to see -Flag <Arg>. + SkipNextArg = true; + + // These flags are all of the form -Flag <Arg> and are treated as two + // arguments. Therefore, we need to skip the flag and the next argument. + bool Res = llvm::StringSwitch<bool>(Flag) + .Cases("-I", "-MF", "-MT", "-MQ", true) + .Cases("-o", "-coverage-file", "-dependency-file", true) + .Cases("-fdebug-compilation-dir", "-fmodule-cache-path", "-idirafter", true) + .Cases("-include", "-include-pch", "-internal-isystem", true) + .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true) + .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true) + .Cases("-resource-dir", "-serialize-diagnostic-file", true) + .Case("-dwarf-debug-flags", true) + .Default(false); + + // Match found. + if (Res) + return Res; + + // The remaining flags are treated as a single argument. + SkipNextArg = false; + + // These flags are all of the form -Flag and have no second argument. + Res = llvm::StringSwitch<bool>(Flag) + .Cases("-M", "-MM", "-MG", "-MP", "-MD", true) + .Case("-MMD", true) + .Default(false); + + // Match found. + if (Res) + return Res; + + // These flags are treated as a single argument (e.g., -F<Dir>). + if (FlagRef.startswith("-F") || FlagRef.startswith("-I")) + return true; + + return false; +} + +static bool quoteNextArg(const char *flag) { + return llvm::StringSwitch<bool>(flag) + .Case("-D", true) + .Default(false); +} + +void Compilation::PrintDiagnosticJob(raw_ostream &OS, const Job &J) const { + if (const Command *C = dyn_cast<Command>(&J)) { + OS << C->getExecutable(); + unsigned QuoteNextArg = 0; + for (ArgStringList::const_iterator it = C->getArguments().begin(), + ie = C->getArguments().end(); it != ie; ++it) { + + bool SkipNext; + if (skipArg(*it, SkipNext)) { + if (SkipNext) ++it; + continue; + } + + if (!QuoteNextArg) + QuoteNextArg = quoteNextArg(*it) ? 2 : 0; + + OS << ' '; + + if (QuoteNextArg == 1) + OS << '"'; + + if (!std::strpbrk(*it, " \"\\$")) { + OS << *it; + } else { + // Quote the argument and escape shell special characters; this isn't + // really complete but is good enough. + OS << '"'; + for (const char *s = *it; *s; ++s) { + if (*s == '"' || *s == '\\' || *s == '$') + OS << '\\'; + OS << *s; + } + OS << '"'; + } + + if (QuoteNextArg) { + if (QuoteNextArg == 1) + OS << '"'; + --QuoteNextArg; + } + } + OS << '\n'; + } else { + const JobList *Jobs = cast<JobList>(&J); + for (JobList::const_iterator + it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it) + PrintDiagnosticJob(OS, **it); + } +} + bool Compilation::CleanupFileList(const ArgStringList &Files, bool IssueErrors) const { bool Success = true; diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 57b3417..3c410bb 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -52,25 +52,13 @@ Driver::Driver(StringRef ClangExecutable, ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple), DefaultImageName(DefaultImageName), - DriverTitle("clang \"gcc-compatible\" driver"), + DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), CCLogDiagnosticsFilename(0), CCCIsCXX(false), CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), - CCCUseClang(true), CCCUseClangCXX(true), CCCUseClangCPP(true), - ForcedClangUse(false), CCCUsePCH(true), SuppressMissingInputWarning(false) { - if (IsProduction) { - // In a "production" build, only use clang on architectures we expect to - // work. - // - // During development its more convenient to always have the driver use - // clang, but we don't want users to be confused when things don't work, or - // to file bugs for things we don't support. - CCCClangArchs.insert(llvm::Triple::x86); - CCCClangArchs.insert(llvm::Triple::x86_64); - CCCClangArchs.insert(llvm::Triple::arm); - } + CCCUsePCH(true), SuppressMissingInputWarning(false) { Name = llvm::sys::path::stem(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); @@ -109,7 +97,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); it != ie; ++it) { Arg *A = *it; - if (A->getOption().isUnsupported()) { + if (A->getOption().hasFlag(options::Unsupported)) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } @@ -186,9 +174,9 @@ 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 (StringRef(A->getValue(Args, i)) != "--no-demangle") + if (StringRef(A->getValue(i)) != "--no-demangle") DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker), - A->getValue(Args, i)); + A->getValue(i)); continue; } @@ -197,22 +185,22 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { // some build systems. We don't try to be complete here because we don't // care to encourage this usage model. if (A->getOption().matches(options::OPT_Wp_COMMA) && - A->getNumValues() == 2 && - (A->getValue(Args, 0) == StringRef("-MD") || - A->getValue(Args, 0) == StringRef("-MMD"))) { + (A->getValue(0) == StringRef("-MD") || + A->getValue(0) == StringRef("-MMD"))) { // Rewrite to -MD/-MMD along with -MF. - if (A->getValue(Args, 0) == StringRef("-MD")) + if (A->getValue(0) == StringRef("-MD")) DAL->AddFlagArg(A, Opts->getOption(options::OPT_MD)); else DAL->AddFlagArg(A, Opts->getOption(options::OPT_MMD)); - DAL->AddSeparateArg(A, Opts->getOption(options::OPT_MF), - A->getValue(Args, 1)); + if (A->getNumValues() == 2) + DAL->AddSeparateArg(A, Opts->getOption(options::OPT_MF), + A->getValue(1)); continue; } // Rewrite reserved library names. if (A->getOption().matches(options::OPT_l)) { - StringRef Value = A->getValue(Args); + StringRef Value = A->getValue(); // Rewrite unless -nostdlib is present. if (!HasNostdlib && Value == "stdc++") { @@ -285,48 +273,23 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX; CCCEcho = Args->hasArg(options::OPT_ccc_echo); if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name)) - CCCGenericGCCName = A->getValue(*Args); - CCCUseClangCXX = Args->hasFlag(options::OPT_ccc_clang_cxx, - options::OPT_ccc_no_clang_cxx, - CCCUseClangCXX); + CCCGenericGCCName = A->getValue(); CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth); - 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)) { - StringRef Cur = A->getValue(*Args); - - CCCClangArchs.clear(); - while (!Cur.empty()) { - std::pair<StringRef, StringRef> Split = Cur.split(','); - - if (!Split.first.empty()) { - llvm::Triple::ArchType Arch = - llvm::Triple(Split.first, "", "").getArch(); - - if (Arch == llvm::Triple::UnknownArch) - Diag(clang::diag::err_drv_invalid_arch_name) << Split.first; - - CCCClangArchs.insert(Arch); - } - - Cur = Split.second; - } - } // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld // and getToolChain is const. if (const Arg *A = Args->getLastArg(options::OPT_target)) - DefaultTargetTriple = A->getValue(*Args); + DefaultTargetTriple = A->getValue(); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) - Dir = InstalledDir = A->getValue(*Args); + Dir = InstalledDir = A->getValue(); for (arg_iterator it = Args->filtered_begin(options::OPT_B), ie = Args->filtered_end(); it != ie; ++it) { const Arg *A = *it; A->claim(); - PrefixDirs.push_back(A->getValue(*Args, 0)); + PrefixDirs.push_back(A->getValue(0)); } if (const Arg *A = Args->getLastArg(options::OPT__sysroot_EQ)) - SysRoot = A->getValue(*Args); + SysRoot = A->getValue(); if (Args->hasArg(options::OPT_nostdlib)) UseStdLib = false; @@ -399,11 +362,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C, std::string Cmd; llvm::raw_string_ostream OS(Cmd); if (FailingCommand) - C.PrintJob(OS, *FailingCommand, "\n", false); + C.PrintDiagnosticJob(OS, *FailingCommand); else // Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an // associated FailingCommand, so just pass all jobs. - C.PrintJob(OS, C.getJobs(), "\n", false); + C.PrintDiagnosticJob(OS, C.getJobs()); OS.flush(); // Clear stale state and suppress tool output. @@ -418,7 +381,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, bool IgnoreInput = false; // Ignore input from stdin or any inputs that cannot be preprocessed. - if (!strcmp(it->second->getValue(C.getArgs()), "-")) { + if (!strcmp(it->second->getValue(), "-")) { Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating preprocessed source(s) - ignoring input from stdin" "."; @@ -442,7 +405,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, it != ie; ++it) { Arg *A = *it; if (A->getOption().matches(options::OPT_arch)) { - StringRef ArchName = A->getValue(C.getArgs()); + StringRef ArchName = A->getValue(); ArchNames.insert(ArchName); } } @@ -501,57 +464,6 @@ void Driver::generateCompilationDiagnostics(Compilation &C, Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + Err; } else { - // Strip away options not necessary to reproduce the crash. - // FIXME: This doesn't work with quotes (e.g., -D "foo bar"). - SmallVector<std::string, 16> Flag; - Flag.push_back("-D "); - Flag.push_back("-F"); - Flag.push_back("-I "); - Flag.push_back("-M "); - Flag.push_back("-MD "); - Flag.push_back("-MF "); - Flag.push_back("-MG "); - Flag.push_back("-MM "); - Flag.push_back("-MMD "); - Flag.push_back("-MP "); - Flag.push_back("-MQ "); - Flag.push_back("-MT "); - Flag.push_back("-o "); - Flag.push_back("-coverage-file "); - Flag.push_back("-dependency-file "); - Flag.push_back("-fdebug-compilation-dir "); - Flag.push_back("-fmodule-cache-path "); - Flag.push_back("-idirafter "); - Flag.push_back("-include "); - Flag.push_back("-include-pch "); - Flag.push_back("-internal-isystem "); - Flag.push_back("-internal-externc-isystem "); - Flag.push_back("-iprefix "); - Flag.push_back("-iwithprefix "); - Flag.push_back("-iwithprefixbefore "); - Flag.push_back("-isysroot "); - Flag.push_back("-isystem "); - Flag.push_back("-iquote "); - Flag.push_back("-resource-dir "); - Flag.push_back("-serialize-diagnostic-file "); - for (unsigned i = 0, e = Flag.size(); i < e; ++i) { - size_t I = 0, E = 0; - do { - I = Cmd.find(Flag[i], I); - if (I == std::string::npos) break; - - E = Cmd.find(" ", I + Flag[i].length()); - if (E == std::string::npos) break; - // The -D option is not removed. Instead, the argument is quoted. - if (Flag[i] != "-D ") { - Cmd.erase(I, E - I + 1); - } else { - Cmd.insert(I+3, "\""); - Cmd.insert(++E, "\""); - I = E; - } - } while(1); - } // Append the new filename with correct preprocessed suffix. size_t I, E; I = Cmd.find("-main-file-name "); @@ -639,12 +551,12 @@ void Driver::PrintOptions(const ArgList &Args) const { it != ie; ++it, ++i) { Arg *A = *it; llvm::errs() << "Option " << i << " - " - << "Name: \"" << A->getOption().getName() << "\", " + << "Name: \"" << A->getOption().getPrefixedName() << "\", " << "Values: {"; for (unsigned j = 0; j < A->getNumValues(); ++j) { if (j) llvm::errs() << ", "; - llvm::errs() << '"' << A->getValue(Args, j) << '"'; + llvm::errs() << '"' << A->getValue(j) << '"'; } llvm::errs() << "}\n"; } @@ -652,7 +564,9 @@ void Driver::PrintOptions(const ArgList &Args) const { void Driver::PrintHelp(bool ShowHidden) const { getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(), - ShowHidden); + /*Include*/0, + /*Exclude*/options::NoDriverOption | + (ShowHidden ? 0 : options::HelpHidden)); } void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { @@ -750,12 +664,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { // FIXME: The following handlers should use a callback mechanism, we don't // know what the client would like to do. if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) { - llvm::outs() << GetFilePath(A->getValue(C.getArgs()), TC) << "\n"; + llvm::outs() << GetFilePath(A->getValue(), TC) << "\n"; return false; } if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) { - llvm::outs() << GetProgramPath(A->getValue(C.getArgs()), TC) << "\n"; + llvm::outs() << GetProgramPath(A->getValue(), TC) << "\n"; return false; } @@ -818,7 +732,7 @@ static unsigned PrintActions1(const Compilation &C, Action *A, os << Action::getClassName(A->getKind()) << ", "; if (InputAction *IA = dyn_cast<InputAction>(A)) { - os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\""; + os << "\"" << IA->getInputArg().getValue() << "\""; } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { os << '"' << BIA->getArchName() << '"' << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}"; @@ -878,7 +792,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, // Validate the option here; we don't save the type here because its // particular spelling may participate in other driver choices. llvm::Triple::ArchType Arch = - llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); + tools::darwin::getArchTypeForDarwinArchName(A->getValue()); if (Arch == llvm::Triple::UnknownArch) { Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); @@ -886,15 +800,15 @@ void Driver::BuildUniversalActions(const ToolChain &TC, } A->claim(); - if (ArchNames.insert(A->getValue(Args))) - Archs.push_back(A->getValue(Args)); + if (ArchNames.insert(A->getValue())) + Archs.push_back(A->getValue()); } } // When there is no explicit arch for this platform, make sure we still bind // the architecture (to the default) so that -Xarch_ is handled correctly. if (!Archs.size()) - Archs.push_back(Args.MakeArgString(TC.getArchName())); + Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName())); // FIXME: We killed off some others but these aren't yet detected in a // functional manner. If we added information to jobs about which "auxiliary" @@ -981,8 +895,8 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, it != ie; ++it) { Arg *A = *it; - if (isa<InputOption>(A->getOption())) { - const char *Value = A->getValue(Args); + if (A->getOption().getKind() == Option::InputClass) { + const char *Value = A->getValue(); types::ID Ty = types::TY_INVALID; // Infer the input type if necessary. @@ -1049,8 +963,8 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, if (CheckInputsExist && memcmp(Value, "-", 2) != 0) { SmallString<64> Path(Value); if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { - SmallString<64> Directory(WorkDir->getValue(Args)); - if (llvm::sys::path::is_absolute(Directory.str())) { + if (!llvm::sys::path::is_absolute(Path.str())) { + SmallString<64> Directory(WorkDir->getValue()); llvm::sys::path::append(Directory, Value); Path.assign(Directory); } @@ -1064,21 +978,21 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, } else Inputs.push_back(std::make_pair(Ty, A)); - } else if (A->getOption().isLinkerInput()) { + } else if (A->getOption().hasFlag(options::LinkerInput)) { // Just treat as object type, we could make a special type for this if // necessary. Inputs.push_back(std::make_pair(types::TY_Object, A)); } else if (A->getOption().matches(options::OPT_x)) { InputTypeArg = A; - InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args)); + InputType = types::lookupTypeForTypeSpecifier(A->getValue()); A->claim(); // Follow gcc behavior and treat as linker input for invalid -x // options. Its not clear why we shouldn't just revert to unknown; but // this isn't very important, we might as well be bug compatible. if (!InputType) { - Diag(clang::diag::err_drv_unknown_language) << A->getValue(Args); + Diag(clang::diag::err_drv_unknown_language) << A->getValue(); InputType = types::TY_Object; } } @@ -1301,7 +1215,7 @@ void Driver::BuildJobs(Compilation &C) const { const char *LinkingOutput = 0; if (isa<LipoJobAction>(A)) { if (FinalOutput) - LinkingOutput = FinalOutput->getValue(C.getArgs()); + LinkingOutput = FinalOutput->getValue(); else LinkingOutput = DefaultImageName.c_str(); } @@ -1331,13 +1245,13 @@ void Driver::BuildJobs(Compilation &C) const { // DiagnosticsEngine, so that extra values, position, and so on could be // printed. if (!A->isClaimed()) { - if (A->getOption().hasNoArgumentUnused()) + if (A->getOption().hasFlag(options::NoArgumentUnused)) continue; // Suppress the warning automatically if this is just a flag, and it is an // instance of an argument we already claimed. const Option &Opt = A->getOption(); - if (isa<FlagOption>(Opt)) { + if (Opt.getKind() == Option::FlagClass) { bool DuplicateClaimed = false; for (arg_iterator it = C.getArgs().filtered_begin(&Opt), @@ -1392,6 +1306,7 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, !C.getArgs().hasArg(options::OPT_no_integrated_cpp) && !C.getArgs().hasArg(options::OPT_traditional_cpp) && !C.getArgs().hasArg(options::OPT_save_temps) && + !C.getArgs().hasArg(options::OPT_rewrite_objc) && ToolForJob->hasIntegratedCPP()) Inputs = &(*Inputs)[0]->getInputs(); @@ -1413,7 +1328,7 @@ void Driver::BuildJobsForAction(Compilation &C, const Arg &Input = IA->getInputArg(); Input.claim(); if (Input.getOption().matches(options::OPT_INPUT)) { - const char *Name = Input.getValue(C.getArgs()); + const char *Name = Input.getValue(); Result = InputInfo(Name, A->getType(), Name); } else Result = InputInfo(&Input, A->getType(), ""); @@ -1502,7 +1417,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) { if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) - return C.addResultFile(FinalOutput->getValue(C.getArgs())); + return C.addResultFile(FinalOutput->getValue()); } // Default to writing to stdout? @@ -1580,7 +1495,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { // Respect a limited subset of the '-Bprefix' functionality in GCC by - // attempting to use this prefix when lokup up program paths. + // attempting to use this prefix when looking for file paths. for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), ie = PrefixDirs.end(); it != ie; ++it) { std::string Dir(*it); @@ -1619,26 +1534,26 @@ 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 Driver::GetProgramPath(const char *Name, + const ToolChain &TC) const { // FIXME: Needs a better variable than DefaultTargetTriple std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name); // Respect a limited subset of the '-Bprefix' functionality in GCC by - // attempting to use this prefix when lokup up program paths. + // attempting to use this prefix when looking for 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); - if (isPathExecutable(P, WantFile)) return P.str(); + bool IsDirectory; + if (!llvm::sys::fs::is_directory(*it, IsDirectory) && IsDirectory) { + llvm::sys::Path P(*it); + P.appendComponent(TargetSpecificExecutable); + if (P.canExecute()) return P.str(); + P.eraseComponent(); + P.appendComponent(Name); + if (P.canExecute()) return P.str(); + } else { + llvm::sys::Path P(*it + Name); + if (P.canExecute()) return P.str(); + } } const ToolChain::path_list &List = TC.getProgramPaths(); @@ -1646,10 +1561,10 @@ std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, it = List.begin(), ie = List.end(); it != ie; ++it) { llvm::sys::Path P(*it); P.appendComponent(TargetSpecificExecutable); - if (isPathExecutable(P, WantFile)) return P.str(); + if (P.canExecute()) return P.str(); P.eraseComponent(); P.appendComponent(Name); - if (isPathExecutable(P, WantFile)) return P.str(); + if (P.canExecute()) return P.str(); } // If all else failed, search the path. @@ -1701,7 +1616,7 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, StringRef DarwinArchName) { // FIXME: Already done in Compilation *Driver::BuildCompilation if (const Arg *A = Args.getLastArg(options::OPT_target)) - DefaultTargetTriple = A->getValue(Args); + DefaultTargetTriple = A->getValue(); llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); @@ -1710,14 +1625,14 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, // If an explict Darwin arch name is given, that trumps all. if (!DarwinArchName.empty()) { Target.setArch( - llvm::Triple::getArchTypeForDarwinArchName(DarwinArchName)); + tools::darwin::getArchTypeForDarwinArchName(DarwinArchName)); return Target; } // Handle the Darwin '-arch' flag. if (Arg *A = Args.getLastArg(options::OPT_arch)) { llvm::Triple::ArchType DarwinArch - = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); + = tools::darwin::getArchTypeForDarwinArchName(A->getValue()); if (DarwinArch != llvm::Triple::UnknownArch) Target.setArch(DarwinArch); } @@ -1820,37 +1735,14 @@ bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, const llvm::Triple &Triple) const { // Check if user requested no clang, or clang doesn't understand this type (we // only handle single inputs for now). - if (!CCCUseClang || JA.size() != 1 || + if (JA.size() != 1 || !types::isAcceptedByClang((*JA.begin())->getType())) return false; // Otherwise make sure this is an action clang understands. - if (isa<PreprocessJobAction>(JA)) { - if (!CCCUseClangCPP) { - Diag(clang::diag::warn_drv_not_using_clang_cpp); - return false; - } - } else if (!isa<PrecompileJobAction>(JA) && !isa<CompileJobAction>(JA)) - return false; - - // Use clang for C++? - if (!CCCUseClangCXX && types::isCXX((*JA.begin())->getType())) { - Diag(clang::diag::warn_drv_not_using_clang_cxx); + if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) && + !isa<CompileJobAction>(JA)) return false; - } - - // Always use clang for precompiling, AST generation, and rewriting, - // regardless of archs. - if (isa<PrecompileJobAction>(JA) || - types::isOnlyAcceptedByClang(JA.getType())) - return true; - - // Finally, don't use clang if this isn't one of the user specified archs to - // build. - if (!CCCClangArchs.empty() && !CCCClangArchs.count(Triple.getArch())) { - Diag(clang::diag::warn_drv_not_using_clang_arch) << Triple.getArchName(); - return false; - } return true; } diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp index 715819d..3925b8a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp @@ -14,11 +14,19 @@ using namespace clang::driver; using namespace clang::driver::options; +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) +#include "clang/Driver/Options.inc" +#undef OPTION +#undef PREFIX + static const OptTable::Info InfoTable[] = { -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ +#define PREFIX(NAME, VALUE) +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) \ - { NAME, HELPTEXT, METAVAR, Option::KIND##Class, PARAM, FLAGS, \ - OPT_##GROUP, OPT_##ALIAS }, + { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \ + FLAGS, OPT_##GROUP, OPT_##ALIAS }, #include "clang/Driver/Options.inc" }; diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp index a3e38b2..6e7b695 100644 --- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp @@ -11,6 +11,7 @@ #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" +#include "clang/Driver/Options.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -54,6 +55,13 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { if (int N = StrCmpOptionName(A.Name, B.Name)) return N == -1; + for (const char * const *APre = A.Prefixes, + * const *BPre = B.Prefixes; + *APre != 0 && *BPre != 0; ++APre, ++BPre) { + if (int N = StrCmpOptionName(*APre, *BPre)) + return N == -1; + } + // Names are the same, check that classes are in order; exactly one // should be joined, and it should succeed the other. assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) && @@ -78,23 +86,24 @@ OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} // OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) - : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos), - Options(new Option*[NumOptionInfos]), - TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0) + : OptionInfos(_OptionInfos), + NumOptionInfos(_NumOptionInfos), + TheInputOptionID(0), + TheUnknownOptionID(0), + FirstSearchableIndex(0) { // Explicitly zero initialize the error to work around a bug in array // value-initialization on MinGW with gcc 4.3.5. - memset(Options, 0, sizeof(*Options) * NumOptionInfos); // Find start of normal options. for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { unsigned Kind = getInfo(i + 1).Kind; if (Kind == Option::InputClass) { - assert(!TheInputOption && "Cannot have multiple input options!"); - TheInputOption = getOption(i + 1); + assert(!TheInputOptionID && "Cannot have multiple input options!"); + TheInputOptionID = getInfo(i + 1).ID; } else if (Kind == Option::UnknownClass) { - assert(!TheUnknownOption && "Cannot have multiple input options!"); - TheUnknownOption = getOption(i + 1); + assert(!TheUnknownOptionID && "Cannot have multiple unknown options!"); + TheUnknownOptionID = getInfo(i + 1).ID; } else if (Kind != Option::GroupClass) { FirstSearchableIndex = i; break; @@ -115,91 +124,80 @@ OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) // Check that options are in order. for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) { if (!(getInfo(i) < getInfo(i + 1))) { - getOption(i)->dump(); - getOption(i + 1)->dump(); + getOption(i).dump(); + getOption(i + 1).dump(); llvm_unreachable("Options are not in order!"); } } #endif + + // Build prefixes. + for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) { + if (const char *const *P = getInfo(i).Prefixes) { + for (; *P != 0; ++P) { + PrefixesUnion.insert(*P); + } + } + } + + // Build prefix chars. + for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(), + E = PrefixesUnion.end(); I != E; ++I) { + StringRef Prefix = I->getKey(); + for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end(); + C != CE; ++C) + if (std::find(PrefixChars.begin(), PrefixChars.end(), *C) + == PrefixChars.end()) + PrefixChars.push_back(*C); + } } OptTable::~OptTable() { - for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - delete Options[i]; - delete[] Options; } -Option *OptTable::CreateOption(unsigned id) const { - const Info &info = getInfo(id); - const OptionGroup *Group = - cast_or_null<OptionGroup>(getOption(info.GroupID)); - const Option *Alias = getOption(info.AliasID); - - Option *Opt = 0; - switch (info.Kind) { - case Option::InputClass: - Opt = new InputOption(id); break; - case Option::UnknownClass: - Opt = new UnknownOption(id); break; - case Option::GroupClass: - Opt = new OptionGroup(id, info.Name, Group); break; - case Option::FlagClass: - Opt = new FlagOption(id, info.Name, Group, Alias); break; - case Option::JoinedClass: - Opt = new JoinedOption(id, info.Name, Group, Alias); break; - case Option::SeparateClass: - Opt = new SeparateOption(id, info.Name, Group, Alias); break; - case Option::CommaJoinedClass: - Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break; - case Option::MultiArgClass: - Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break; - case Option::JoinedOrSeparateClass: - Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break; - case Option::JoinedAndSeparateClass: - Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break; - } +const Option OptTable::getOption(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + if (id == 0) + return Option(0, 0); + assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); + return Option(&getInfo(id), this); +} - if (info.Flags & DriverOption) - Opt->setDriverOption(true); - if (info.Flags & LinkerInput) - Opt->setLinkerInput(true); - if (info.Flags & NoArgumentUnused) - Opt->setNoArgumentUnused(true); - if (info.Flags & NoForward) - Opt->setNoForward(true); - if (info.Flags & RenderAsInput) - Opt->setNoOptAsInput(true); - if (info.Flags & RenderJoined) { - assert((info.Kind == Option::JoinedOrSeparateClass || - info.Kind == Option::SeparateClass) && "Invalid option."); - Opt->setRenderStyle(Option::RenderJoinedStyle); - } - if (info.Flags & RenderSeparate) { - assert((info.Kind == Option::JoinedOrSeparateClass || - info.Kind == Option::JoinedClass) && "Invalid option."); - Opt->setRenderStyle(Option::RenderSeparateStyle); - } - if (info.Flags & Unsupported) - Opt->setUnsupported(true); - if (info.Flags & CC1Option) - Opt->setIsCC1Option(true); +static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) { + if (Arg == "-") + return true; + for (llvm::StringSet<>::const_iterator I = Prefixes.begin(), + E = Prefixes.end(); I != E; ++I) + if (Arg.startswith(I->getKey())) + return false; + return true; +} - return Opt; +/// \returns Matched size. 0 means no match. +static unsigned matchOption(const OptTable::Info *I, StringRef Str) { + for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) { + StringRef Prefix(*Pre); + if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name)) + return Prefix.size() + StringRef(I->Name).size(); + } + return 0; } Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { unsigned Prev = Index; const char *Str = Args.getArgString(Index); - // Anything that doesn't start with '-' is an input, as is '-' itself. - if (Str[0] != '-' || Str[1] == '\0') - return new Arg(TheInputOption, Index++, Str); + // Anything that doesn't start with PrefixesUnion is an input, as is '-' + // itself. + if (isInput(PrefixesUnion, Str)) + return new Arg(getOption(TheInputOptionID), Str, Index++, Str); const Info *Start = OptionInfos + FirstSearchableIndex; const Info *End = OptionInfos + getNumOptions(); + StringRef Name = StringRef(Str).ltrim(PrefixChars); // Search for the first next option which could be a prefix. - Start = std::lower_bound(Start, End, Str); + Start = std::lower_bound(Start, End, Name.data()); // Options are stored in sorted order, with '\0' at the end of the // alphabet. Since the only options which can accept a string must @@ -210,15 +208,16 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { // blanking on the simplest way to make it fast. We can solve this // problem when we move to TableGen. for (; Start != End; ++Start) { + unsigned ArgSize = 0; // Scan for first option which is a proper prefix. for (; Start != End; ++Start) - if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0) + if ((ArgSize = matchOption(Start, Str))) break; if (Start == End) break; // See if this option matches. - if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index)) + if (Arg *A = Option(Start, this).accept(Args, Index, ArgSize)) return A; // Otherwise, see if this argument was missing values. @@ -226,7 +225,7 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { return 0; } - return new Arg(TheUnknownOption, Index++, Str); + return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str); } InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, @@ -266,10 +265,11 @@ InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, } static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { - std::string Name = Opts.getOptionName(Id); + const Option O = Opts.getOption(Id); + std::string Name = O.getPrefixedName(); // Add metavar, if used. - switch (Opts.getOptionKind(Id)) { + switch (O.getKind()) { case Option::GroupClass: case Option::InputClass: case Option::UnknownClass: llvm_unreachable("Invalid option with help text."); @@ -346,7 +346,8 @@ static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) { } void OptTable::PrintHelp(raw_ostream &OS, const char *Name, - const char *Title, bool ShowHidden) const { + const char *Title, unsigned short FlagsToInclude, + unsigned short FlagsToExclude) const { OS << "OVERVIEW: " << Title << "\n"; OS << '\n'; OS << "USAGE: " << Name << " [options] <inputs>\n"; @@ -365,7 +366,8 @@ void OptTable::PrintHelp(raw_ostream &OS, const char *Name, if (getOptionKind(Id) == Option::GroupClass) continue; - if (!ShowHidden && isOptionHelpHidden(Id)) + if ((FlagsToInclude && !(getInfo(Id).Flags & FlagsToInclude)) || + getInfo(Id).Flags & FlagsToExclude) continue; if (const char *Text = getOptionHelpText(Id)) { diff --git a/contrib/llvm/tools/clang/lib/Driver/Option.cpp b/contrib/llvm/tools/clang/lib/Driver/Option.cpp index 03360ea..9a34df5 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Option.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Option.cpp @@ -13,46 +13,20 @@ #include "clang/Driver/ArgList.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/Twine.h" #include <cassert> #include <algorithm> using namespace clang::driver; -Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name, - const OptionGroup *_Group, const Option *_Alias) - : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias), - Unsupported(false), LinkerInput(false), NoOptAsInput(false), - DriverOption(false), NoArgumentUnused(false), NoForward(false) { +Option::Option(const OptTable::Info *info, const OptTable *owner) + : Info(info), Owner(owner) { // Multi-level aliases are not supported, and alias options cannot // have groups. This just simplifies option tracking, it is not an // inherent limitation. - assert((!Alias || (!Alias->Alias && !Group)) && + assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() && + !getGroup().isValid())) && "Multi-level aliases and aliases with groups are unsupported."); - - // Initialize rendering options based on the class. - switch (Kind) { - case GroupClass: - case InputClass: - case UnknownClass: - RenderStyle = RenderValuesStyle; - break; - - case JoinedClass: - case JoinedAndSeparateClass: - RenderStyle = RenderJoinedStyle; - break; - - case CommaJoinedClass: - RenderStyle = RenderCommaJoinedStyle; - break; - - case FlagClass: - case SeparateClass: - case MultiArgClass: - case JoinedOrSeparateClass: - RenderStyle = RenderSeparateStyle; - break; - } } Option::~Option() { @@ -60,7 +34,7 @@ Option::~Option() { void Option::dump() const { llvm::errs() << "<"; - switch (Kind) { + switch (getKind()) { #define P(N) case N: llvm::errs() << #N; break P(GroupClass); P(InputClass); @@ -75,206 +49,153 @@ void Option::dump() const { #undef P } - llvm::errs() << " Name:\"" << Name << '"'; + llvm::errs() << " Prefixes:["; + for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) { + llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", "); + } + llvm::errs() << ']'; - if (Group) { + llvm::errs() << " Name:\"" << getName() << '"'; + + const Option Group = getGroup(); + if (Group.isValid()) { llvm::errs() << " Group:"; - Group->dump(); + Group.dump(); } - if (Alias) { + const Option Alias = getAlias(); + if (Alias.isValid()) { llvm::errs() << " Alias:"; - Alias->dump(); + Alias.dump(); } - if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this)) - llvm::errs() << " NumArgs:" << MOA->getNumArgs(); + if (getKind() == MultiArgClass) + llvm::errs() << " NumArgs:" << getNumArgs(); llvm::errs() << ">\n"; } bool Option::matches(OptSpecifier Opt) const { // Aliases are never considered in matching, look through them. - if (Alias) - return Alias->matches(Opt); + const Option Alias = getAlias(); + if (Alias.isValid()) + return Alias.matches(Opt); // Check exact match. - if (ID == Opt) + if (getID() == Opt.getID()) return true; - if (Group) - return Group->matches(Opt); + const Option Group = getGroup(); + if (Group.isValid()) + return Group.matches(Opt); return false; } -OptionGroup::OptionGroup(OptSpecifier ID, const char *Name, - const OptionGroup *Group) - : Option(Option::GroupClass, ID, Name, Group, 0) { -} - -Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const { - llvm_unreachable("accept() should never be called on an OptionGroup"); -} - -InputOption::InputOption(OptSpecifier ID) - : Option(Option::InputClass, ID, "<input>", 0, 0) { -} - -Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const { - llvm_unreachable("accept() should never be called on an InputOption"); -} - -UnknownOption::UnknownOption(OptSpecifier ID) - : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) { -} - -Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const { - llvm_unreachable("accept() should never be called on an UnknownOption"); -} - -FlagOption::FlagOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias) - : Option(Option::FlagClass, ID, Name, Group, Alias) { -} - -Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const { - // Matches iff this is an exact match. - // FIXME: Avoid strlen. - if (getName().size() != strlen(Args.getArgString(Index))) - return 0; - - return new Arg(getUnaliasedOption(), Index++); -} - -JoinedOption::JoinedOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias) - : Option(Option::JoinedClass, ID, Name, Group, Alias) { -} - -Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const { - // Always matches. - const char *Value = Args.getArgString(Index) + getName().size(); - return new Arg(getUnaliasedOption(), Index++, Value); -} - -CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, - const Option *Alias) - : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) { -} - -Arg *CommaJoinedOption::accept(const ArgList &Args, - unsigned &Index) const { - // Always matches. - const char *Str = Args.getArgString(Index) + getName().size(); - Arg *A = new Arg(getUnaliasedOption(), Index++); +Arg *Option::accept(const ArgList &Args, + unsigned &Index, + unsigned ArgSize) const { + const Option &UnaliasedOption = getUnaliasedOption(); + StringRef Spelling; + // If the option was an alias, get the spelling from the unaliased one. + if (getID() == UnaliasedOption.getID()) { + Spelling = StringRef(Args.getArgString(Index), ArgSize); + } else { + Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) + + Twine(UnaliasedOption.getName())); + } - // Parse out the comma separated values. - const char *Prev = Str; - for (;; ++Str) { - char c = *Str; + switch (getKind()) { + case FlagClass: + if (ArgSize != strlen(Args.getArgString(Index))) + return 0; - if (!c || c == ',') { - if (Prev != Str) { - char *Value = new char[Str - Prev + 1]; - memcpy(Value, Prev, Str - Prev); - Value[Str - Prev] = '\0'; - A->getValues().push_back(Value); + return new Arg(UnaliasedOption, Spelling, Index++); + case JoinedClass: { + const char *Value = Args.getArgString(Index) + ArgSize; + return new Arg(UnaliasedOption, Spelling, Index++, Value); + } + case CommaJoinedClass: { + // Always matches. + const char *Str = Args.getArgString(Index) + ArgSize; + Arg *A = new Arg(UnaliasedOption, Spelling, Index++); + + // Parse out the comma separated values. + const char *Prev = Str; + for (;; ++Str) { + char c = *Str; + + if (!c || c == ',') { + if (Prev != Str) { + char *Value = new char[Str - Prev + 1]; + memcpy(Value, Prev, Str - Prev); + Value[Str - Prev] = '\0'; + A->getValues().push_back(Value); + } + + if (!c) + break; + + Prev = Str + 1; } - - if (!c) - break; - - Prev = Str + 1; } - } - A->setOwnsValues(true); - - return A; -} - -SeparateOption::SeparateOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias) - : Option(Option::SeparateClass, ID, Name, Group, Alias) { -} - -Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const { - // Matches iff this is an exact match. - // FIXME: Avoid strlen. - if (getName().size() != strlen(Args.getArgString(Index))) - return 0; - - Index += 2; - if (Index > Args.getNumInputArgStrings()) - return 0; - - return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1)); -} - -MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias, - unsigned _NumArgs) - : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) { - assert(NumArgs > 1 && "Invalid MultiArgOption!"); -} - -Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const { - // Matches iff this is an exact match. - // FIXME: Avoid strlen. - if (getName().size() != strlen(Args.getArgString(Index))) - return 0; - - Index += 1 + NumArgs; - if (Index > Args.getNumInputArgStrings()) - return 0; + A->setOwnsValues(true); - Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs, - Args.getArgString(Index - NumArgs)); - for (unsigned i = 1; i != NumArgs; ++i) - A->getValues().push_back(Args.getArgString(Index - NumArgs + i)); - return A; -} - -JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID, - const char *Name, - const OptionGroup *Group, - const Option *Alias) - : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) { -} - -Arg *JoinedOrSeparateOption::accept(const ArgList &Args, - unsigned &Index) const { - // If this is not an exact match, it is a joined arg. - // FIXME: Avoid strlen. - if (getName().size() != strlen(Args.getArgString(Index))) { - const char *Value = Args.getArgString(Index) + getName().size(); - return new Arg(this, Index++, Value); + return A; } + case SeparateClass: + // Matches iff this is an exact match. + // FIXME: Avoid strlen. + if (ArgSize != strlen(Args.getArgString(Index))) + return 0; + + Index += 2; + if (Index > Args.getNumInputArgStrings()) + return 0; + + return new Arg(UnaliasedOption, Spelling, + Index - 2, Args.getArgString(Index - 1)); + case MultiArgClass: { + // Matches iff this is an exact match. + // FIXME: Avoid strlen. + if (ArgSize != strlen(Args.getArgString(Index))) + return 0; + + Index += 1 + getNumArgs(); + if (Index > Args.getNumInputArgStrings()) + return 0; + + Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(), + Args.getArgString(Index - getNumArgs())); + for (unsigned i = 1; i != getNumArgs(); ++i) + A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i)); + return A; + } + case JoinedOrSeparateClass: { + // If this is not an exact match, it is a joined arg. + // FIXME: Avoid strlen. + if (ArgSize != strlen(Args.getArgString(Index))) { + const char *Value = Args.getArgString(Index) + ArgSize; + return new Arg(*this, Spelling, Index++, Value); + } - // Otherwise it must be separate. - Index += 2; - if (Index > Args.getNumInputArgStrings()) - return 0; - - return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1)); -} - -JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID, - const char *Name, - const OptionGroup *Group, - const Option *Alias) - : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) { -} - -Arg *JoinedAndSeparateOption::accept(const ArgList &Args, - unsigned &Index) const { - // Always matches. - - Index += 2; - if (Index > Args.getNumInputArgStrings()) - return 0; + // Otherwise it must be separate. + Index += 2; + if (Index > Args.getNumInputArgStrings()) + return 0; - return new Arg(getUnaliasedOption(), Index - 2, - Args.getArgString(Index-2)+getName().size(), - Args.getArgString(Index-1)); + return new Arg(UnaliasedOption, Spelling, + Index - 2, Args.getArgString(Index - 1)); + } + case JoinedAndSeparateClass: + // Always matches. + Index += 2; + if (Index > Args.getNumInputArgStrings()) + return 0; + + return new Arg(UnaliasedOption, Spelling, Index - 2, + Args.getArgString(Index - 2) + ArgSize, + Args.getArgString(Index - 1)); + default: + llvm_unreachable("Invalid option kind!"); + } } diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h new file mode 100644 index 0000000..ecb396e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h @@ -0,0 +1,106 @@ +//===--- SanitizerArgs.h - Arguments for sanitizer tools -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_ +#define CLANG_LIB_DRIVER_SANITIZERARGS_H_ + +#include "clang/Driver/ArgList.h" + +namespace clang { +namespace driver { + +class SanitizerArgs { + /// Assign ordinals to sanitizer flags. We'll use the ordinal values as + /// bit positions within \c Kind. + enum SanitizeOrdinal { +#define SANITIZER(NAME, ID) SO_##ID, +#include "clang/Basic/Sanitizers.def" + SO_Count + }; + + /// Bugs to catch at runtime. + enum SanitizeKind { +#define SANITIZER(NAME, ID) ID = 1 << SO_##ID, +#define SANITIZER_GROUP(NAME, ID, ALIAS) ID = ALIAS, +#include "clang/Basic/Sanitizers.def" + NeedsAsanRt = Address, + NeedsTsanRt = Thread, + NeedsUbsanRt = Undefined + }; + unsigned Kind; + + public: + SanitizerArgs() : Kind(0) {} + /// Parses the sanitizer arguments from an argument list. + SanitizerArgs(const Driver &D, const ArgList &Args); + + bool needsAsanRt() const { return Kind & NeedsAsanRt; } + bool needsTsanRt() const { return Kind & NeedsTsanRt; } + bool needsUbsanRt() const { return Kind & NeedsUbsanRt; } + + bool sanitizesVptr() const { return Kind & Vptr; } + + void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + if (!Kind) + return; + llvm::SmallString<256> SanitizeOpt("-fsanitize="); +#define SANITIZER(NAME, ID) \ + if (Kind & ID) \ + SanitizeOpt += NAME ","; +#include "clang/Basic/Sanitizers.def" + SanitizeOpt.pop_back(); + CmdArgs.push_back(Args.MakeArgString(SanitizeOpt)); + } + + private: + /// Parse a single value from a -fsanitize= or -fno-sanitize= value list. + /// Returns a member of the \c SanitizeKind enumeration, or \c 0 if \p Value + /// is not known. + static unsigned parse(const char *Value) { + return llvm::StringSwitch<SanitizeKind>(Value) +#define SANITIZER(NAME, ID) .Case(NAME, ID) +#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID) +#include "clang/Basic/Sanitizers.def" + .Default(SanitizeKind()); + } + + /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any + /// invalid components. + static unsigned parse(const Driver &D, const Arg *A) { + unsigned Kind = 0; + for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) { + if (unsigned K = parse(A->getValue(I))) + Kind |= K; + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(I); + } + return Kind; + } + + /// Produce an argument string from argument \p A, which shows how it provides + /// a value in \p Mask. For instance, the argument + /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce + /// "-fsanitize=alignment". + static std::string describeSanitizeArg(const ArgList &Args, const Arg *A, + unsigned Mask) { + if (!A->getOption().matches(options::OPT_fsanitize_EQ)) + return A->getAsString(Args); + + for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) + if (parse(A->getValue(I)) & Mask) + return std::string("-fsanitize=") + A->getValue(I); + + llvm_unreachable("arg didn't provide expected value"); + } +}; + +} // namespace driver +} // namespace clang + +#endif // CLANG_LIB_DRIVER_SANITIZERARGS_H_ diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index 48ed044..de8ed1d 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -14,6 +14,7 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Option.h" #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" @@ -32,13 +33,32 @@ const Driver &ToolChain::getDriver() const { return D; } +std::string ToolChain::getDefaultUniversalArchName() const { + // In universal driver terms, the arch name accepted by -arch isn't exactly + // the same as the ones that appear in the triple. Roughly speaking, this is + // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the + // only interesting special case is powerpc. + switch (Triple.getArch()) { + case llvm::Triple::ppc: + return "ppc"; + case llvm::Triple::ppc64: + return "ppc64"; + default: + return Triple.getArchName(); + } +} + +bool ToolChain::IsUnwindTablesDefault() const { + return false; +} + std::string ToolChain::GetFilePath(const char *Name) const { return D.GetFilePath(Name, *this); } -std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const { - return D.GetProgramPath(Name, *this, WantFile); +std::string ToolChain::GetProgramPath(const char *Name) const { + return D.GetProgramPath(Name, *this); } types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { @@ -66,13 +86,13 @@ static const char *getARMTargetCPU(const ArgList &Args, // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) - return A->getValue(Args); + return A->getValue(); } 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); + MArch = A->getValue(); } else { // Otherwise, use the Arch from the triple. MArch = Triple.getArchName(); @@ -91,6 +111,8 @@ static const char *getARMTargetCPU(const ArgList &Args, .Cases("armv6z", "armv6zk", "arm1176jzf-s") .Case("armv6t2", "arm1156t2-s") .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") + .Cases("armv7f", "armv7-f", "cortex-a9-mp") + .Cases("armv7s", "armv7-s", "swift") .Cases("armv7r", "armv7-r", "cortex-r4") .Cases("armv7m", "armv7-m", "cortex-m3") .Case("ep9312", "ep9312") @@ -119,10 +141,12 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) { .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") + .Cases("cortex-a8", "cortex-a9", "cortex-a15", "v7") .Case("cortex-m3", "v7m") .Case("cortex-m4", "v7m") .Case("cortex-m0", "v6m") + .Case("cortex-a9-mp", "v7f") + .Case("swift", "v7s") .Default(""); } @@ -142,7 +166,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, // FIXME: Thumb should just be another -target-feaure, not in the triple. StringRef Suffix = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); - bool ThumbDefault = (Suffix == "v7" && getTriple().isOSDarwin()); + bool ThumbDefault = (Suffix.startswith("v7") && getTriple().isOSDarwin()); std::string ArchName = "arm"; // Assembly files should start in ARM mode. @@ -180,7 +204,7 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) { - StringRef Value = A->getValue(Args); + StringRef Value = A->getValue(); if (Value == "compiler-rt") return ToolChain::RLT_CompilerRT; if (Value == "libgcc") @@ -194,7 +218,7 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { - StringRef Value = A->getValue(Args); + StringRef Value = A->getValue(); if (Value == "libc++") return ToolChain::CST_Libcxx; if (Value == "libstdc++") @@ -273,3 +297,24 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CmdArgs.push_back("-lcc_kext"); } + +bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Check if -ffast-math or -funsafe-math is enabled. + Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations); + + if (!A || A->getOption().getID() == options::OPT_fno_fast_math || + A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) + return false; + + // If crtfastmath.o exists add it to the arguments. + std::string Path = GetFilePath("crtfastmath.o"); + if (Path == "crtfastmath.o") // Not found. + return false; + + CmdArgs.push_back(Args.MakeArgString(Path)); + return true; +} diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 01c6623..a2ccb35 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -31,6 +31,8 @@ #include "llvm/Support/Path.h" #include "llvm/Support/system_error.h" +#include "SanitizerArgs.h" + #include <cstdlib> // ::getenv #include "clang/Config/config.h" // for GCC_INSTALL_PREFIX @@ -80,17 +82,11 @@ bool Darwin::HasNativeLLVMSupport() const { /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { - if (isTargetIPhoneOS()) { + if (isTargetIPhoneOS()) return ObjCRuntime(ObjCRuntime::iOS, TargetVersion); - } else if (TargetSimulatorVersionFromDefines != VersionTuple()) { - return ObjCRuntime(ObjCRuntime::iOS, TargetSimulatorVersionFromDefines); - } else { - if (isNonFragile) { - return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion); - } else { - return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion); - } - } + if (isNonFragile) + return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion); + return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion); } /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. @@ -111,6 +107,9 @@ static const char *GetArmArchForMArch(StringRef Value) { .Cases("armv7a", "armv7-a", "armv7") .Cases("armv7r", "armv7-r", "armv7") .Cases("armv7m", "armv7-m", "armv7") + .Cases("armv7f", "armv7-f", "armv7f") + .Cases("armv7k", "armv7-k", "armv7k") + .Cases("armv7s", "armv7-s", "armv7s") .Default(0); } @@ -122,7 +121,10 @@ static const char *GetArmArchForMCpu(StringRef Value) { .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") + .Cases("cortex-a8", "cortex-r4", "cortex-m3", "cortex-a9", "cortex-a15", + "armv7") + .Case("cortex-a9-mp", "armv7f") + .Case("swift", "armv7s") .Default(0); } @@ -134,11 +136,11 @@ StringRef Darwin::getDarwinArchName(const ArgList &Args) const { case llvm::Triple::thumb: case llvm::Triple::arm: { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) - if (const char *Arch = GetArmArchForMArch(A->getValue(Args))) + if (const char *Arch = GetArmArchForMArch(A->getValue())) return Arch; if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) - if (const char *Arch = GetArmArchForMCpu(A->getValue(Args))) + if (const char *Arch = GetArmArchForMCpu(A->getValue())) return Arch; return "arm"; @@ -175,24 +177,11 @@ void Generic_ELF::anchor() {} Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { Action::ActionClass Key = JA.getKind(); - bool useClang = false; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) { - useClang = true; - // Fallback to llvm-gcc for i386 kext compiles, we don't support that ABI. - if (!getDriver().shouldForceClangUse() && - Inputs.size() == 1 && - types::isCXX(Inputs[0]->getType()) && - getTriple().isOSDarwin() && - getTriple().getArch() == llvm::Triple::x86 && - (C.getArgs().getLastArg(options::OPT_fapple_kext) || - C.getArgs().getLastArg(options::OPT_mkernel))) - useClang = false; - } - - // FIXME: This seems like a hacky way to choose clang frontend. - if (useClang) + // FIXME: This seems like a hacky way to choose clang frontend. Key = Action::AnalyzeJobClass; + } bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, options::OPT_no_integrated_as, @@ -245,30 +234,6 @@ DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple) getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); - - // 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); - ToolChainDir += "/4.2.1"; - - std::string Path = getDriver().Dir; - Path += "/../llvm-gcc-4.2/libexec/gcc/"; - Path += ToolChainDir; - getProgramPaths().push_back(Path); - - Path = "/usr/llvm-gcc-4.2/libexec/gcc/"; - Path += ToolChainDir; - getProgramPaths().push_back(Path); } void DarwinClang::AddLinkARCArgs(const ArgList &Args, @@ -287,9 +252,6 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, s += "iphonesimulator"; else if (isTargetIPhoneOS()) s += "iphoneos"; - // FIXME: Remove this once we depend fully on -mios-simulator-version-min. - else if (TargetSimulatorVersionFromDefines != VersionTuple()) - s += "iphonesimulator"; else s += "macosx"; s += ".a"; @@ -320,13 +282,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, break; default: getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform) - << Args.getLastArg(options::OPT_rtlib_EQ)->getValue(Args) << "darwin"; + << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin"; return; } // Darwin doesn't support real static executables, don't link any runtime // libraries with -static. - if (Args.hasArg(options::OPT_static)) + if (Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_fapple_kext) || + Args.hasArg(options::OPT_mkernel)) return; // Reject -static-libgcc for now, we can deal with this when and if someone @@ -351,15 +315,16 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, } } + SanitizerArgs Sanitize(getDriver(), Args); + // Add ASAN runtime library, if required. Dynamic libraries and bundles // should not be linked with the runtime library. - if (Args.hasFlag(options::OPT_faddress_sanitizer, - options::OPT_fno_address_sanitizer, false)) { + if (Sanitize.needsAsanRt()) { if (Args.hasArg(options::OPT_dynamiclib) || Args.hasArg(options::OPT_bundle)) return; if (isTargetIPhoneOS()) { getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) - << "-faddress-sanitizer"; + << "-fsanitize=address"; } else { AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.asan_osx.a"); @@ -410,67 +375,28 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, } } -static inline StringRef SimulatorVersionDefineName() { - return "__IPHONE_OS_VERSION_MIN_REQUIRED"; -} - -/// \brief Parse the simulator version define: -/// __IPHONE_OS_VERSION_MIN_REQUIRED=([0-9])([0-9][0-9])([0-9][0-9]) -// 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(StringRef define, - unsigned &Major, unsigned &Minor, - unsigned &Micro) { - assert(define.startswith(SimulatorVersionDefineName())); - StringRef name, version; - llvm::tie(name, version) = define.split('='); - if (version.empty()) - return false; - std::string verstr = version.str(); - char *end; - unsigned num = (unsigned) strtol(verstr.c_str(), &end, 10); - if (*end != '\0') - return false; - Major = num / 10000; - num = num % 10000; - Minor = num / 100; - Micro = num % 100; - return true; -} - void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { const OptTable &Opts = getDriver().getOpts(); + // Support allowing the SDKROOT environment variable used by xcrun and other + // Xcode tools to define the default sysroot, by making it the default for + // isysroot. + if (!Args.hasArg(options::OPT_isysroot)) { + if (char *env = ::getenv("SDKROOT")) { + // We only use this value as the default if it is an absolute path and + // exists. + if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env)) { + Args.append(Args.MakeSeparateArg( + 0, Opts.getOption(options::OPT_isysroot), env)); + } + } + } + Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ); Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); Arg *iOSSimVersion = Args.getLastArg( options::OPT_mios_simulator_version_min_EQ); - // FIXME: HACK! When compiling for the simulator we don't get a - // '-miphoneos-version-min' to help us know whether there is an ARC runtime - // or not; try to parse a __IPHONE_OS_VERSION_MIN_REQUIRED - // define passed in command-line. - if (!iOSVersion && !iOSSimVersion) { - for (arg_iterator it = Args.filtered_begin(options::OPT_D), - ie = Args.filtered_end(); it != ie; ++it) { - StringRef define = (*it)->getValue(Args); - if (define.startswith(SimulatorVersionDefineName())) { - unsigned Major = 0, Minor = 0, Micro = 0; - if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) && - Major < 10 && Minor < 100 && Micro < 100) { - TargetSimulatorVersionFromDefines = VersionTuple(Major, Minor, Micro); - } - // When using the define to indicate the simulator, we force - // 10.6 macosx target. - const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); - OSXVersion = Args.MakeJoinedArg(0, O, "10.6"); - Args.append(OSXVersion); - break; - } - } - } - if (OSXVersion && (iOSVersion || iOSSimVersion)) { getDriver().Diag(diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) @@ -500,7 +426,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (iOSTarget.empty()) { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef first, second; - StringRef isysroot = A->getValue(Args); + StringRef isysroot = A->getValue(); llvm::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS")); if (second != "") iOSTarget = second.substr(0,3); @@ -510,7 +436,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // 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() && - getDarwinArchName(Args) == "armv7") + (getDarwinArchName(Args) == "armv7" || + getDarwinArchName(Args) == "armv7s")) iOSTarget = iOSVersionMin; // Handle conflicting deployment targets @@ -536,21 +463,21 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } if (!OSXTarget.empty()) { - const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); + const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget); Args.append(OSXVersion); } else if (!iOSTarget.empty()) { - const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); + const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget); Args.append(iOSVersion); } else if (!iOSSimTarget.empty()) { - const Option *O = Opts.getOption( + const Option O = Opts.getOption( options::OPT_mios_simulator_version_min_EQ); iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget); Args.append(iOSSimVersion); } else { // Otherwise, assume we are targeting OS X. - const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); + const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin); Args.append(OSXVersion); } @@ -568,7 +495,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { bool HadExtra; if (OSXVersion) { assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor, + if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || Major != 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) @@ -576,7 +503,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } else { const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion; assert(Version && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(Version->getValue(Args), Major, Minor, + if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) @@ -614,7 +541,7 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, // Check in the sysroot first. bool Exists; if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { - llvm::sys::Path P(A->getValue(Args)); + llvm::sys::Path P(A->getValue()); P.appendComponent("usr"); P.appendComponent("lib"); P.appendComponent("libstdc++.dylib"); @@ -655,7 +582,14 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args, llvm::sys::Path P(getDriver().ResourceDir); P.appendComponent("lib"); P.appendComponent("darwin"); - P.appendComponent("libclang_rt.cc_kext.a"); + + // Use the newer cc_kext for iOS ARM after 6.0. + if (!isTargetIPhoneOS() || isTargetIOSSimulator() || + !isIPhoneOSVersionLT(6, 0)) { + P.appendComponent("libclang_rt.cc_kext.a"); + } else { + P.appendComponent("libclang_rt.cc_kext_ios5.a"); + } // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build. @@ -683,15 +617,15 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, if (A->getOption().matches(options::OPT_Xarch__)) { // Skip this argument unless the architecture matches either the toolchain // triple arch, or the arch being bound. - // - // FIXME: Canonicalize name. - StringRef XarchArch = A->getValue(Args, 0); - if (!(XarchArch == getArchName() || - (BoundArch && XarchArch == BoundArch))) + llvm::Triple::ArchType XarchArch = + tools::darwin::getArchTypeForDarwinArchName(A->getValue(0)); + if (!(XarchArch == getArch() || + (BoundArch && XarchArch == + tools::darwin::getArchTypeForDarwinArchName(BoundArch)))) continue; Arg *OriginalArg = A; - unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(Args, 1)); + unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); unsigned Prev = Index; Arg *XarchArg = Opts.ParseOneArg(Args, Index); @@ -707,7 +641,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) << A->getAsString(Args); continue; - } else if (XarchArg->getOption().isDriverOption()) { + } else if (XarchArg->getOption().hasFlag(options::DriverOption)) { getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver) << A->getAsString(Args); continue; @@ -721,12 +655,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // Linker input arguments require custom handling. The problem is that we // have already constructed the phase actions, so we can not treat them as // "input arguments". - if (A->getOption().isLinkerInput()) { + if (A->getOption().hasFlag(options::LinkerInput)) { // Convert the argument into individual Zlinker_input_args. for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { DAL->AddSeparateArg(OriginalArg, Opts.getOption(options::OPT_Zlinker_input), - A->getValue(Args, i)); + A->getValue(i)); } continue; @@ -749,7 +683,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, case options::OPT_dependency_file: DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), - A->getValue(Args)); + A->getValue()); break; case options::OPT_gfull: @@ -805,8 +739,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // how the driver driver works. if (BoundArch) { StringRef Name = BoundArch; - const Option *MCpu = Opts.getOption(options::OPT_mcpu_EQ); - const Option *MArch = Opts.getOption(options::OPT_march_EQ); + const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ); + const Option MArch = Opts.getOption(options::OPT_march_EQ); // This code must be kept in sync with LLVM's getArchTypeForDarwinArch, // which defines the list of which architectures we accept. @@ -864,6 +798,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, DAL->AddJoinedArg(0, MArch, "armv6k"); else if (Name == "armv7") DAL->AddJoinedArg(0, MArch, "armv7a"); + else if (Name == "armv7f") + DAL->AddJoinedArg(0, MArch, "armv7f"); + else if (Name == "armv7k") + DAL->AddJoinedArg(0, MArch, "armv7k"); + else if (Name == "armv7s") + DAL->AddJoinedArg(0, MArch, "armv7s"); else llvm_unreachable("invalid Darwin arch"); @@ -875,6 +815,25 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, if (BoundArch) AddDeploymentTarget(*DAL); + // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext. + // FIXME: It would be far better to avoid inserting those -static arguments, + // but we can't check the deployment target in the translation code until + // it is set here. + if (isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) { + for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) { + Arg *A = *it; + ++it; + if (A->getOption().getID() != options::OPT_mkernel && + A->getOption().getID() != options::OPT_fapple_kext) + continue; + assert(it != ie && "unexpected argument translation"); + A = *it; + assert(A->getOption().getID() == options::OPT_static && + "missing expected -static argument"); + it = DAL->getArgs().erase(it); + } + } + // Validate the C++ standard library choice. CXXStdlibType Type = GetCXXStdlibType(*DAL); if (Type == ToolChain::CST_Libcxx) { @@ -882,13 +841,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, StringRef where; // Complain about targetting iOS < 5.0 in any way. - if (TargetSimulatorVersionFromDefines != VersionTuple()) { - if (TargetSimulatorVersionFromDefines < VersionTuple(5, 0)) - where = "iOS 5.0"; - } else if (isTargetIPhoneOS()) { - if (isIPhoneOSVersionLT(5, 0)) - where = "iOS 5.0"; - } + if (isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)) + where = "iOS 5.0"; if (where != StringRef()) { getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) @@ -900,9 +854,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, } bool Darwin::IsUnwindTablesDefault() const { - // FIXME: Gross; we should probably have some separate target - // definition, possibly even reusing the one in clang. - return getArchName() == "x86_64"; + return getArch() == llvm::Triple::x86_64; } bool Darwin::UseDwarfDebugFlags() const { @@ -917,19 +869,17 @@ bool Darwin::UseSjLjExceptions() const { getTriple().getArch() == llvm::Triple::thumb); } -const char *Darwin::GetDefaultRelocationModel() const { - return "pic"; +bool Darwin::isPICDefault() const { + return true; } -const char *Darwin::GetForcedPicModel() const { - if (getArchName() == "x86_64") - return "pic"; - return 0; +bool Darwin::isPICDefaultForced() const { + return getArch() == llvm::Triple::x86_64; } bool Darwin::SupportsProfiling() const { // Profiling instrumentation is only supported on x86. - return getArchName() == "i386" || getArchName() == "x86_64"; + return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64; } bool Darwin::SupportsObjCGC() const { @@ -937,8 +887,10 @@ bool Darwin::SupportsObjCGC() const { return !isTargetIPhoneOS(); } -bool Darwin::SupportsObjCARC() const { - return isTargetIPhoneOS() || !isMacosxVersionLT(10, 6); +void Darwin::CheckObjCARC() const { + if (isTargetIPhoneOS() || !isMacosxVersionLT(10, 6)) + return; + getDriver().Diag(diag::err_arc_unsupported_on_toolchain); } std::string @@ -1013,7 +965,7 @@ bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const { static StringRef getGCCToolchainDir(const ArgList &Args) { const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain); if (A) - return A->getValue(Args); + return A->getValue(); return GCC_INSTALL_PREFIX; } @@ -1072,7 +1024,8 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( if (!llvm::sys::fs::exists(LibDir)) continue; for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, LibDir, CandidateTripleAliases[k]); + ScanLibDirForGCCTriple(TargetArch, Args, LibDir, + CandidateTripleAliases[k]); } for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) { const std::string LibDir @@ -1081,7 +1034,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( continue; for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, LibDir, + ScanLibDirForGCCTriple(TargetArch, Args, LibDir, CandidateMultiarchTripleAliases[k], /*NeedsMultiarchSuffix=*/true); } @@ -1136,7 +1089,10 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( static const char *const MIPSLibDirs[] = { "/lib" }; static const char *const MIPSTriples[] = { "mips-linux-gnu" }; static const char *const MIPSELLibDirs[] = { "/lib" }; - static const char *const MIPSELTriples[] = { "mipsel-linux-gnu" }; + static const char *const MIPSELTriples[] = { + "mipsel-linux-gnu", + "mipsel-linux-android" + }; static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" }; static const char *const MIPS64Triples[] = { "mips64-linux-gnu" }; @@ -1264,8 +1220,32 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( MultiarchTripleAliases.push_back(MultiarchTriple.str()); } +// FIXME: There is the same routine in the Tools.cpp. +static bool hasMipsN32ABIArg(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef("n32")); +} + +static StringRef getTargetMultiarchSuffix(llvm::Triple::ArchType TargetArch, + const ArgList &Args) { + if (TargetArch == llvm::Triple::x86_64 || + TargetArch == llvm::Triple::ppc64) + return "/64"; + + if (TargetArch == llvm::Triple::mips64 || + TargetArch == llvm::Triple::mips64el) { + if (hasMipsN32ABIArg(Args)) + return "/n32"; + else + return "/64"; + } + + return "/32"; +} + void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( - llvm::Triple::ArchType TargetArch, const std::string &LibDir, + llvm::Triple::ArchType TargetArch, const ArgList &Args, + const std::string &LibDir, StringRef CandidateTriple, bool NeedsMultiarchSuffix) { // There are various different suffixes involving the triple we // check for. We also record what is necessary to walk from each back @@ -1274,6 +1254,10 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( "/gcc/" + CandidateTriple.str(), "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), + // The Freescale PPC SDK has the gcc libraries in + // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. + "/" + 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 @@ -1283,6 +1267,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( const std::string InstallSuffixes[] = { "/../../..", "/../../../..", + "/../..", "/../../../.." }; // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. @@ -1307,11 +1292,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // *if* there is a subdirectory of the right name with crtbegin.o in it, // we use that. If not, and if not a multiarch triple, we look for // crtbegin.o without the subdirectory. - StringRef MultiarchSuffix - = (TargetArch == llvm::Triple::x86_64 || - TargetArch == llvm::Triple::ppc64 || - TargetArch == llvm::Triple::mips64 || - TargetArch == llvm::Triple::mips64el) ? "/64" : "/32"; + StringRef MultiarchSuffix = getTargetMultiarchSuffix(TargetArch, Args); if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) { GCCMultiarchSuffix = MultiarchSuffix.str(); } else { @@ -1392,18 +1373,17 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, } bool Generic_GCC::IsUnwindTablesDefault() const { - // FIXME: Gross; we should probably have some separate target - // definition, possibly even reusing the one in clang. - return getArchName() == "x86_64"; + return getArch() == llvm::Triple::x86_64; } -const char *Generic_GCC::GetDefaultRelocationModel() const { - return "static"; +bool Generic_GCC::isPICDefault() const { + return false; } -const char *Generic_GCC::GetForcedPicModel() const { - return 0; +bool Generic_GCC::isPICDefaultForced() const { + return false; } + /// Hexagon Toolchain Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple& Triple) @@ -1457,21 +1437,14 @@ Tool &Hexagon_TC::SelectTool(const Compilation &C, return *T; } -bool Hexagon_TC::IsUnwindTablesDefault() const { - // FIXME: Gross; we should probably have some separate target - // definition, possibly even reusing the one in clang. - return getArchName() == "x86_64"; +bool Hexagon_TC::isPICDefault() const { + return false; } -const char *Hexagon_TC::GetDefaultRelocationModel() const { - return "static"; +bool Hexagon_TC::isPICDefaultForced() const { + return false; } -const char *Hexagon_TC::GetForcedPicModel() const { - return 0; -} // End Hexagon - - /// TCEToolChain - A tool chain using the llvm bitcode tools to perform /// all subcommands. See http://tce.cs.tut.fi for our peculiar target. /// Currently does not support anything else but compilation. @@ -1495,16 +1468,12 @@ bool TCEToolChain::IsMathErrnoDefault() const { return true; } -bool TCEToolChain::IsUnwindTablesDefault() const { +bool TCEToolChain::isPICDefault() const { return false; } -const char *TCEToolChain::GetDefaultRelocationModel() const { - return "static"; -} - -const char *TCEToolChain::GetForcedPicModel() const { - return 0; +bool TCEToolChain::isPICDefaultForced() const { + return false; } Tool &TCEToolChain::SelectTool(const Compilation &C, @@ -1613,19 +1582,43 @@ void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, DriverArgs.hasArg(options::OPT_nostdincxx)) return; - std::string Triple = getTriple().str(); - if (Triple.substr(0, 5) == "amd64") - Triple.replace(0, 5, "x86_64"); - - addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/4.6.2"); - addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/4.6.2/backward"); - addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/4.6.2/" + Triple); + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/include/c++/"); + break; + case ToolChain::CST_Libstdcxx: + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/include/c++/stdc++"); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/include/c++/stdc++/backward"); + StringRef Triple = getTriple().str(); + if (Triple.startswith("amd64")) + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" + + Triple.substr(5)); + else + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/include/c++/stdc++/" + + Triple); + break; + } } void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - CmdArgs.push_back("-lstdc++"); + switch (GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lcxxrt"); + // Include supc++ to provide Unwind until provided by libcxx. + CmdArgs.push_back("-lgcc"); + break; + case ToolChain::CST_Libstdcxx: + CmdArgs.push_back("-lstdc++"); + break; + } } /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. @@ -2020,6 +2013,46 @@ static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str()); } +static bool isMipsArch(llvm::Triple::ArchType Arch) { + return Arch == llvm::Triple::mips || + Arch == llvm::Triple::mipsel || + Arch == llvm::Triple::mips64 || + Arch == llvm::Triple::mips64el; +} + +static bool isMipsR2Arch(llvm::Triple::ArchType Arch, + const ArgList &Args) { + if (Arch != llvm::Triple::mips && + Arch != llvm::Triple::mipsel) + return false; + + Arg *A = Args.getLastArg(options::OPT_march_EQ, + options::OPT_mcpu_EQ, + options::OPT_mips_CPUs_Group); + + if (!A) + return false; + + if (A->getOption().matches(options::OPT_mips_CPUs_Group)) + return A->getOption().matches(options::OPT_mips32r2); + + return A->getValue() == StringRef("mips32r2"); +} + +static StringRef getMultilibDir(const llvm::Triple &Triple, + const ArgList &Args) { + if (!isMipsArch(Triple.getArch())) + return Triple.isArch32Bit() ? "lib32" : "lib64"; + + // lib32 directory has a special meaning on MIPS targets. + // It contains N32 ABI binaries. Use this folder if produce + // code for N32 ABI only. + if (hasMipsN32ABIArg(Args)) + return "lib32"; + + return Triple.isArch32Bit() ? "lib" : "lib64"; +} + Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { llvm::Triple::ArchType Arch = Triple.getArch(); @@ -2043,19 +2076,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) ExtraOpts.push_back("-X"); - const bool IsMips = Arch == llvm::Triple::mips || - Arch == llvm::Triple::mipsel || - Arch == llvm::Triple::mips64 || - Arch == llvm::Triple::mips64el; - - const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI; + const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android; // Do not use 'gnu' hash style for Mips targets because .gnu.hash // and the MIPS ABI require .dynsym to be sorted in different ways. // .gnu.hash needs symbols to be grouped by hash code whereas the MIPS // ABI requires a mapping between the GOT and the symbol table. // Android loader does not support .gnu.hash. - if (!IsMips && !IsAndroid) { + if (!isMipsArch(Arch) && !IsAndroid) { if (IsRedhat(Distro) || IsOpenSuse(Distro) || (IsUbuntu(Distro) && Distro >= UbuntuMaverick)) ExtraOpts.push_back("--hash-style=gnu"); @@ -2084,16 +2112,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // to the link paths. path_list &Paths = getFilePaths(); - const std::string Multilib = Triple.isArch32Bit() ? "lib32" : "lib64"; + const std::string Multilib = getMultilibDir(Triple, Args); const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot); // Add the multilib suffixed paths where they are available. if (GCCInstallation.isValid()) { const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); const std::string &LibPath = GCCInstallation.getParentLibPath(); - addPathIfExists((GCCInstallation.getInstallPath() + - GCCInstallation.getMultiarchSuffix()), - Paths); + + if (IsAndroid && isMipsR2Arch(Triple.getArch(), Args)) + addPathIfExists(GCCInstallation.getInstallPath() + + GCCInstallation.getMultiarchSuffix() + + "/mips-r2", + Paths); + else + addPathIfExists((GCCInstallation.getInstallPath() + + GCCInstallation.getMultiarchSuffix()), + Paths); // If the GCC installation we found is inside of the sysroot, we want to // prefer libraries installed in the parent prefix of the GCC installation. @@ -2108,6 +2143,11 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); addPathIfExists(LibPath + "/../" + Multilib, Paths); } + // On Android, libraries in the parent prefix of the GCC installation are + // preferred to the ones under sysroot. + if (IsAndroid) { + addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths); + } } addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths); addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths); @@ -2326,16 +2366,25 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, StringRef LibDir = GCCInstallation.getParentLibPath(); StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef Version = GCCInstallation.getVersion().Text; - if (!addLibStdCXXIncludePaths(LibDir + "/../include/c++/" + Version, - (GCCInstallation.getTriple().str() + - GCCInstallation.getMultiarchSuffix()), - DriverArgs, CC1Args)) { + StringRef TripleStr = GCCInstallation.getTriple().str(); + + const std::string IncludePathCandidates[] = { + LibDir.str() + "/../include/c++/" + Version.str(), // Gentoo is weird and places its headers inside the GCC install, so if the // first attempt to find the headers fails, try this pattern. - addLibStdCXXIncludePaths(InstallDir + "/include/g++-v4", - (GCCInstallation.getTriple().str() + - GCCInstallation.getMultiarchSuffix()), - DriverArgs, CC1Args); + InstallDir.str() + "/include/g++-v4", + // Android standalone toolchain has C++ headers in yet another place. + LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.str(), + // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++, + // without a subdirectory corresponding to the gcc version. + LibDir.str() + "/../include/c++", + }; + + for (unsigned i = 0; i < llvm::array_lengthof(IncludePathCandidates); ++i) { + if (addLibStdCXXIncludePaths(IncludePathCandidates[i], (TripleStr + + GCCInstallation.getMultiarchSuffix()), + DriverArgs, CC1Args)) + break; } } diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index 95a11be..4c267e8 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -111,6 +111,7 @@ protected: SmallVectorImpl<StringRef> &MultiarchTripleAliases); void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, + const ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, bool NeedsMultiarchSuffix = false); @@ -128,8 +129,8 @@ public: const ActionList &Inputs) const; virtual bool IsUnwindTablesDefault() const; - virtual const char *GetDefaultRelocationModel() const; - virtual const char *GetForcedPicModel() const; + virtual bool isPICDefault() const; + virtual bool isPICDefaultForced() const; protected: /// \name ToolChain Implementation Helper Functions @@ -155,9 +156,8 @@ public: virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; - virtual bool IsUnwindTablesDefault() const; - virtual const char *GetDefaultRelocationModel() const; - virtual const char *GetForcedPicModel() const; + virtual bool isPICDefault() const; + virtual bool isPICDefaultForced() const; }; /// Darwin - The base Darwin tool chain. @@ -185,11 +185,6 @@ private: /// The OS version we are targeting. mutable VersionTuple TargetVersion; -protected: - // FIXME: Remove this once there is a proper way to detect an ARC runtime - // for the simulator. - mutable VersionTuple TargetSimulatorVersionFromDefines; - private: /// The default macosx-version-min of this tool chain; empty until /// initialized. @@ -243,9 +238,7 @@ public: } bool isTargetMacOS() const { - return !isTargetIOSSimulator() && - !isTargetIPhoneOS() && - TargetSimulatorVersionFromDefines == VersionTuple(); + return !isTargetIOSSimulator() && !isTargetIPhoneOS(); } bool isTargetInitialized() const { return TargetInitialized; } @@ -325,6 +318,10 @@ public: return true; } + virtual bool IsEncodeExtendedBlockSignatureDefault() const { + return true; + } + virtual bool IsObjCNonFragileABIDefault() const { // Non-fragile ABI is default for everything but i386. return getTriple().getArch() != llvm::Triple::x86; @@ -347,14 +344,14 @@ public: virtual RuntimeLibType GetDefaultRuntimeLibType() const { return ToolChain::RLT_CompilerRT; } - virtual const char *GetDefaultRelocationModel() const; - virtual const char *GetForcedPicModel() const; + virtual bool isPICDefault() const; + virtual bool isPICDefaultForced() const; virtual bool SupportsProfiling() const; virtual bool SupportsObjCGC() const; - virtual bool SupportsObjCARC() const; + virtual void CheckObjCARC() const; virtual bool UseDwarfDebugFlags() const; @@ -365,9 +362,6 @@ public: /// DarwinClang - The Darwin toolchain used by Clang. class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { -private: - void AddGCCLibexecPath(unsigned darwinVersion); - public: DarwinClang(const Driver &D, const llvm::Triple& Triple); @@ -399,7 +393,7 @@ public: std::string ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const; - virtual const char *GetDefaultRelocationModel() const { return "pic"; } + virtual bool isPICDefault() const { return false; }; }; class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC { @@ -540,9 +534,8 @@ public: virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; bool IsMathErrnoDefault() const; - bool IsUnwindTablesDefault() const; - const char* GetDefaultRelocationModel() const; - const char* GetForcedPicModel() const; + bool isPICDefault() const; + bool isPICDefaultForced() const; private: mutable llvm::DenseMap<unsigned, Tool*> Tools; @@ -564,8 +557,8 @@ public: virtual bool IsIntegratedAssemblerDefault() const; virtual bool IsUnwindTablesDefault() const; - virtual const char *GetDefaultRelocationModel() const; - virtual const char *GetForcedPicModel() const; + virtual bool isPICDefault() const; + virtual bool isPICDefaultForced() const; virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 936bde9..927ffe0 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/ErrorHandling.h" #include "InputInfo.h" +#include "SanitizerArgs.h" #include "ToolChains.h" using namespace clang::driver; @@ -93,9 +94,15 @@ static void addDirectoryList(const ArgList &Args, const char *ArgName, const char *EnvVar) { const char *DirList = ::getenv(EnvVar); + bool CombinedArg = false; + if (!DirList) return; // Nothing to do. + StringRef Name(ArgName); + if (Name.equals("-I") || Name.equals("-L")) + CombinedArg = true; + StringRef Dirs(DirList); if (Dirs.empty()) // Empty string should not add '.'. return; @@ -103,21 +110,37 @@ static void addDirectoryList(const ArgList &Args, 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("."); + if (CombinedArg) { + CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); + } else { + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } } else { - CmdArgs.push_back(ArgName); - CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); + if (CombinedArg) { + CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim))); + } 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("."); + if (CombinedArg) { + CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); + } else { + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } } else { // Add the last path. - CmdArgs.push_back(ArgName); - CmdArgs.push_back(Args.MakeArgString(Dirs)); + if (CombinedArg) { + CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs)); + } else { + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs)); + } } } @@ -200,6 +223,12 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(ProfileRT)); } +static bool forwardToGCC(const Option &O) { + return !O.hasFlag(options::NoForward) && + !O.hasFlag(options::DriverOption) && + !O.hasFlag(options::LinkerInput); +} + void Clang::AddPreprocessingOptions(Compilation &C, const Driver &D, const ArgList &Args, @@ -220,7 +249,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, // Determine the output location. const char *DepFile; if (Arg *MF = Args.getLastArg(options::OPT_MF)) { - DepFile = MF->getValue(Args); + DepFile = MF->getValue(); C.addFailureResultFile(DepFile); } else if (Output.getType() == types::TY_Dependencies) { DepFile = Output.getFilename(); @@ -242,7 +271,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, // when we are only generating a dependency file. Arg *OutputOpt = Args.getLastArg(options::OPT_o); if (OutputOpt && Output.getType() != types::TY_Dependencies) { - DepTarget = OutputOpt->getValue(Args); + DepTarget = OutputOpt->getValue(); } else { // Otherwise derive from the base input. // @@ -282,7 +311,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, if (A->getOption().matches(options::OPT_MQ)) { CmdArgs.push_back("-MT"); SmallString<128> Quoted; - QuoteTarget(A->getValue(Args), Quoted); + QuoteTarget(A->getValue(), Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); // -MT flag - no change @@ -310,7 +339,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, bool FoundPTH = false; bool FoundPCH = false; - llvm::sys::Path P(A->getValue(Args)); + llvm::sys::Path P(A->getValue()); bool Exists; if (UsePCH) { P.appendSuffix("pch"); @@ -442,10 +471,12 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) { .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") + .Cases("cortex-a8", "cortex-a9", "cortex-a15", "v7") .Case("cortex-m3", "v7m") .Case("cortex-m4", "v7m") .Case("cortex-m0", "v6m") + .Case("cortex-a9-mp", "v7f") + .Case("swift", "v7s") .Default(""); } @@ -458,7 +489,7 @@ static std::string getARMTargetCPU(const ArgList &Args, // If we have -mcpu=, use that. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef MCPU = A->getValue(Args); + StringRef MCPU = A->getValue(); // Handle -mcpu=native. if (MCPU == "native") return llvm::sys::getHostCPUName(); @@ -469,7 +500,7 @@ static std::string getARMTargetCPU(const ArgList &Args, 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); + MArch = A->getValue(); } else { // Otherwise, use the Arch from the triple. MArch = Triple.getArchName(); @@ -500,6 +531,8 @@ static std::string getARMTargetCPU(const ArgList &Args, .Cases("armv6z", "armv6zk", "arm1176jzf-s") .Case("armv6t2", "arm1156t2-s") .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") + .Cases("armv7f", "armv7-f", "cortex-a9-mp") + .Cases("armv7s", "armv7-s", "swift") .Cases("armv7r", "armv7-r", "cortex-r4") .Cases("armv7m", "armv7-m", "cortex-m3") .Case("ep9312", "ep9312") @@ -531,7 +564,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { // frontend target. static void addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args, ArgStringList &CmdArgs) { - StringRef FPU = A->getValue(Args); + StringRef FPU = A->getValue(); // Set the target features based on the FPU. if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { @@ -569,14 +602,15 @@ static void addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args, // Handle -mfpmath=. static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args, ArgStringList &CmdArgs, StringRef CPU) { - StringRef FPMath = A->getValue(Args); + StringRef FPMath = A->getValue(); // Set the target features based on the FPMath. if (FPMath == "neon") { CmdArgs.push_back("-target-feature"); CmdArgs.push_back("+neonfp"); - if (CPU != "cortex-a8" && CPU != "cortex-a9" && CPU != "cortex-a9-mp") + if (CPU != "cortex-a8" && CPU != "cortex-a9" && CPU != "cortex-a9-mp" && + CPU != "cortex-a15") D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU; } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" || @@ -603,7 +637,7 @@ static StringRef getARMFloatABI(const Driver &D, else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; else { - FloatABI = A->getValue(Args); + FloatABI = A->getValue(); if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") { D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); @@ -643,7 +677,7 @@ static StringRef getARMFloatABI(const Driver &D, // EABI is always AAPCS, and if it was not marked 'hard', it's softfp FloatABI = "softfp"; break; - case llvm::Triple::ANDROIDEABI: { + case llvm::Triple::Android: { std::string ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v7")) @@ -669,18 +703,29 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs, bool KernelOrKext) const { const Driver &D = getToolChain().getDriver(); - llvm::Triple Triple = getToolChain().getTriple(); + // Get the effective triple, which takes into account the deployment target. + std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); + llvm::Triple Triple(TripleStr); + std::string CPUName = getARMTargetCPU(Args, Triple); // Select the ABI to use. // // FIXME: Support -meabi. const char *ABIName = 0; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { - ABIName = A->getValue(Args); + ABIName = A->getValue(); + } else if (Triple.isOSDarwin()) { + // The backend is hardwired to assume AAPCS for M-class processors, ensure + // the frontend matches that. + if (StringRef(CPUName).startswith("cortex-m")) { + ABIName = "aapcs"; + } else { + ABIName = "apcs-gnu"; + } } else { // Select the default based on the platform. switch(Triple.getEnvironment()) { - case llvm::Triple::ANDROIDEABI: + case llvm::Triple::Android: case llvm::Triple::GNUEABI: case llvm::Triple::GNUEABIHF: ABIName = "aapcs-linux"; @@ -697,7 +742,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Set the CPU based on -march= and -mcpu=. CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(Args.MakeArgString(getARMTargetCPU(Args, Triple))); + CmdArgs.push_back(Args.MakeArgString(CPUName)); // Determine floating point ABI from the options & target defaults. StringRef FloatABI = getARMFloatABI(D, Args, Triple); @@ -754,8 +799,10 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Kernel code has more strict alignment requirements. if (KernelOrKext) { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-long-calls"); + if (Triple.getOS() != llvm::Triple::IOS || Triple.isOSVersionLT(6)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-long-calls"); + } CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-strict-align"); @@ -777,44 +824,18 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back("-no-implicit-float"); } -// Get default architecture. -static const char* getMipsArchFromCPU(StringRef CPUName) { - if (CPUName == "mips32" || CPUName == "mips32r2") - return "mips"; - - assert((CPUName == "mips64" || CPUName == "mips64r2") && - "Unexpected cpu name."); - - return "mips64"; -} - -// Check that ArchName is a known Mips architecture name. -static bool checkMipsArchName(StringRef ArchName) { - return ArchName == "mips" || - ArchName == "mipsel" || - ArchName == "mips64" || - ArchName == "mips64el"; -} - -// Get default target cpu. -static const char* getMipsCPUFromArch(StringRef ArchName) { - if (ArchName == "mips" || ArchName == "mipsel") +// Translate MIPS CPU name alias option to CPU name. +static StringRef getMipsCPUFromAlias(const Arg &A) { + if (A.getOption().matches(options::OPT_mips32)) return "mips32"; - - assert((ArchName == "mips64" || ArchName == "mips64el") && - "Unexpected arch name."); - - return "mips64"; -} - -// 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"; + if (A.getOption().matches(options::OPT_mips32r2)) + return "mips32r2"; + if (A.getOption().matches(options::OPT_mips64)) + return "mips64"; + if (A.getOption().matches(options::OPT_mips64r2)) + return "mips64r2"; + llvm_unreachable("Unexpected option"); + return ""; } // Get CPU and ABI names. They are not independent @@ -823,26 +844,53 @@ static void getMipsCPUAndABI(const ArgList &Args, const ToolChain &TC, StringRef &CPUName, StringRef &ABIName) { - StringRef ArchName; - - // Select target cpu and architecture. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - CPUName = A->getValue(Args); - ArchName = getMipsArchFromCPU(CPUName); - } - else { - ArchName = Args.MakeArgString(TC.getArchName()); - if (!checkMipsArchName(ArchName)) - TC.getDriver().Diag(diag::err_drv_invalid_arch_name) << ArchName; + const char *DefMips32CPU = "mips32"; + const char *DefMips64CPU = "mips64"; + + if (Arg *A = Args.getLastArg(options::OPT_march_EQ, + options::OPT_mcpu_EQ, + options::OPT_mips_CPUs_Group)) { + if (A->getOption().matches(options::OPT_mips_CPUs_Group)) + CPUName = getMipsCPUFromAlias(*A); else - CPUName = getMipsCPUFromArch(ArchName); + CPUName = A->getValue(); } - - // Select the ABI to use. + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) - ABIName = A->getValue(Args); - else - ABIName = getMipsABIFromArch(ArchName); + ABIName = A->getValue(); + + // Setup default CPU and ABI names. + if (CPUName.empty() && ABIName.empty()) { + switch (TC.getTriple().getArch()) { + default: + llvm_unreachable("Unexpected triple arch name"); + case llvm::Triple::mips: + case llvm::Triple::mipsel: + CPUName = DefMips32CPU; + break; + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + CPUName = DefMips64CPU; + break; + } + } + + if (!ABIName.empty()) { + // Deduce CPU name from ABI name. + CPUName = llvm::StringSwitch<const char *>(ABIName) + .Cases("o32", "eabi", DefMips32CPU) + .Cases("n32", "n64", DefMips64CPU) + .Default(""); + } + else if (!CPUName.empty()) { + // Deduce ABI name from CPU name. + ABIName = llvm::StringSwitch<const char *>(CPUName) + .Cases("mips32", "mips32r2", "o32") + .Cases("mips64", "mips64r2", "n64") + .Default(""); + } + + // FIXME: Warn on inconsistent cpu and abi usage. } // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, @@ -859,7 +907,7 @@ static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) { else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; else { - FloatABI = A->getValue(Args); + FloatABI = A->getValue(); if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") { D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); FloatABI = "hard"; @@ -941,12 +989,19 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, AddTargetFeature(Args, CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2, "dspr2"); + + if (Arg *A = Args.getLastArg(options::OPT_G)) { + StringRef v = A->getValue(); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v)); + A->claim(); + } } /// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting. static std::string getPPCTargetCPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef CPUName = A->getValue(Args); + StringRef CPUName = A->getValue(); if (CPUName == "native") { std::string CPU = llvm::sys::getHostCPUName(); @@ -978,6 +1033,8 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("970", "970") .Case("G5", "g5") .Case("a2", "a2") + .Case("e500mc", "e500mc") + .Case("e5500", "e5500") .Case("power6", "pwr6") .Case("power7", "pwr7") .Case("powerpc", "ppc") @@ -1015,7 +1072,7 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } // Select the float ABI as determined by -msoft-float, -mhard-float, and @@ -1054,6 +1111,8 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, void Clang::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + const bool isAndroid = + getToolChain().getTriple().getEnvironment() == llvm::Triple::Android; if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || @@ -1068,7 +1127,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, const char *CPUName = 0; if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (StringRef(A->getValue(Args)) == "native") { + if (StringRef(A->getValue()) == "native") { // FIXME: Reject attempts to use -march=native unless the target matches // the host. // @@ -1078,7 +1137,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, if (!CPU.empty() && CPU != "generic") CPUName = Args.MakeArgString(CPU); } else - CPUName = A->getValue(Args); + CPUName = A->getValue(); } // Select the default CPU if none was given (or detection failed). @@ -1118,7 +1177,9 @@ void Clang::AddX86TargetArgs(const ArgList &Args, if (getToolChain().getArch() == llvm::Triple::x86_64) CPUName = "x86-64"; else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "pentium4"; + // All x86 devices running Android have core2 as their common + // denominator. This makes a better choice than pentium4. + CPUName = isAndroid ? "core2" : "pentium4"; } } @@ -1141,8 +1202,8 @@ void Clang::AddX86TargetArgs(const ArgList &Args, (*it)->claim(); // Skip over "-m". - assert(Name.startswith("-m") && "Invalid feature name."); - Name = Name.substr(2); + assert(Name.startswith("m") && "Invalid feature name."); + Name = Name.substr(1); bool IsNegative = Name.startswith("no-"); if (IsNegative) @@ -1174,7 +1235,7 @@ static Arg* getLastHexagonArchArg (const ArgList &Args) A->claim(); } else if ((*it)->getOption().matches(options::OPT_m_Joined)){ - StringRef Value = (*it)->getValue(Args,0); + StringRef Value = (*it)->getValue(0); if (Value.startswith("v")) { A = *it; A->claim(); @@ -1191,7 +1252,7 @@ static StringRef getHexagonTargetCPU(const ArgList &Args) // Select the default CPU (v4) if none was given or detection failed. if ((A = getLastHexagonArchArg (Args))) { - WhichHexagon = A->getValue(Args); + WhichHexagon = A->getValue(); if (WhichHexagon == "") return "v4"; else @@ -1216,7 +1277,7 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, if (Arg *A = Args.getLastArg(options::OPT_G, options::OPT_msmall_data_threshold_EQ)) { std::string SmallDataThreshold="-small-data-threshold="; - SmallDataThreshold += A->getValue(Args); + SmallDataThreshold += A->getValue(); CmdArgs.push_back ("-mllvm"); CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold)); A->claim(); @@ -1392,25 +1453,80 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { RelaxDefault); } +SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) { + Kind = 0; + + const Arg *AsanArg, *TsanArg, *UbsanArg; + for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { + unsigned Add = 0, Remove = 0; + const char *DeprecatedReplacement = 0; + if ((*I)->getOption().matches(options::OPT_faddress_sanitizer)) { + Add = Address; + DeprecatedReplacement = "-fsanitize=address"; + } else if ((*I)->getOption().matches(options::OPT_fno_address_sanitizer)) { + Remove = Address; + DeprecatedReplacement = "-fno-sanitize=address"; + } else if ((*I)->getOption().matches(options::OPT_fthread_sanitizer)) { + Add = Thread; + DeprecatedReplacement = "-fsanitize=thread"; + } else if ((*I)->getOption().matches(options::OPT_fno_thread_sanitizer)) { + Remove = Thread; + DeprecatedReplacement = "-fno-sanitize=thread"; + } else if ((*I)->getOption().matches(options::OPT_fcatch_undefined_behavior)) { + Add = Undefined; + DeprecatedReplacement = "-fsanitize=undefined"; + } else if ((*I)->getOption().matches(options::OPT_fsanitize_EQ)) { + Add = parse(D, *I); + } else if ((*I)->getOption().matches(options::OPT_fno_sanitize_EQ)) { + Remove = parse(D, *I); + } else { + continue; + } + + (*I)->claim(); + + Kind |= Add; + Kind &= ~Remove; + + if (Add & NeedsAsanRt) AsanArg = *I; + if (Add & NeedsTsanRt) TsanArg = *I; + if (Add & NeedsUbsanRt) UbsanArg = *I; + + // If this is a deprecated synonym, produce a warning directing users + // towards the new spelling. + if (DeprecatedReplacement) + D.Diag(diag::warn_drv_deprecated_arg) + << (*I)->getAsString(Args) << DeprecatedReplacement; + } + + // Only one runtime library can be used at once. + // FIXME: Allow Ubsan to be combined with the other two. + bool NeedsAsan = needsAsanRt(); + bool NeedsTsan = needsTsanRt(); + bool NeedsUbsan = needsUbsanRt(); + if (NeedsAsan + NeedsTsan + NeedsUbsan > 1) + D.Diag(diag::err_drv_argument_not_allowed_with) + << describeSanitizeArg(Args, NeedsAsan ? AsanArg : TsanArg, + NeedsAsan ? NeedsAsanRt : NeedsTsanRt) + << describeSanitizeArg(Args, NeedsUbsan ? UbsanArg : TsanArg, + NeedsUbsan ? NeedsUbsanRt : NeedsTsanRt); +} + /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (!Args.hasFlag(options::OPT_faddress_sanitizer, - options::OPT_fno_address_sanitizer, false)) - return; - if(TC.getTriple().getEnvironment() == llvm::Triple::ANDROIDEABI) { + if(TC.getTriple().getEnvironment() == llvm::Triple::Android) { if (!Args.hasArg(options::OPT_shared)) { if (!Args.hasArg(options::OPT_pie)) TC.getDriver().Diag(diag::err_drv_asan_android_requires_pie); - // For an executable, we add a .preinit_array stub. - CmdArgs.push_back("-u"); - CmdArgs.push_back("__asan_preinit"); - CmdArgs.push_back("-lasan"); } - CmdArgs.push_back("-lasan_preload"); - CmdArgs.push_back("-ldl"); + SmallString<128> LibAsan(TC.getDriver().ResourceDir); + llvm::sys::path::append(LibAsan, "lib", "linux", + (Twine("libclang_rt.asan-") + + TC.getArchName() + "-android.so")); + CmdArgs.push_back(Args.MakeArgString(LibAsan)); } else { if (!Args.hasArg(options::OPT_shared)) { // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library @@ -1431,9 +1547,6 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, /// This needs to be called before we add the C run-time (malloc, etc). static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (!Args.hasFlag(options::OPT_fthread_sanitizer, - options::OPT_fno_thread_sanitizer, false)) - return; if (!Args.hasArg(options::OPT_shared)) { // LibTsan is "libclang_rt.tsan-<ArchName>.a" in the Linux library // resource directory. @@ -1448,6 +1561,22 @@ static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, } } +/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags +/// (Linux). +static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + if (!Args.hasArg(options::OPT_shared)) { + // LibUbsan is "libclang_rt.ubsan-<ArchName>.a" in the Linux library + // resource directory. + SmallString<128> LibUbsan(TC.getDriver().ResourceDir); + llvm::sys::path::append(LibUbsan, "lib", "linux", + (Twine("libclang_rt.ubsan-") + + TC.getArchName() + ".a")); + CmdArgs.push_back(Args.MakeArgString(LibUbsan)); + CmdArgs.push_back("-lpthread"); + } +} + static bool shouldUseFramePointer(const ArgList &Args, const llvm::Triple &Triple) { if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, @@ -1516,7 +1645,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->claim(); for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { - StringRef Value = A->getValue(Args, i); + StringRef Value = A->getValue(i); if (Value == "-force_cpusubtype_ALL") { // Do nothing, this is the default and we don't support anything else. @@ -1600,8 +1729,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-analyzer-eagerly-assume"); - CmdArgs.push_back("-analyzer-ipa=inlining"); - // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); @@ -1627,7 +1754,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // reasons. CmdArgs.push_back("-analyzer-output"); if (Arg *A = Args.getLastArg(options::OPT__analyzer_output)) - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); else CmdArgs.push_back("plist"); @@ -1642,67 +1769,90 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CheckCodeGenerationOptions(D, Args); - // Perform argument translation for LLVM backend. This - // takes some care in reconciling with llvm-gcc. The - // issue is that llvm-gcc translates these options based on - // the values in cc1, whereas we are processing based on - // the driver arguments. - - // This comes from the default translation the driver + cc1 - // would do to enable flag_pic. - - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - bool PICDisabled = false; - bool PICEnabled = false; - bool PICForPIE = false; - if (LastPICArg) { - PICForPIE = (LastPICArg->getOption().matches(options::OPT_fPIE) || - LastPICArg->getOption().matches(options::OPT_fpie)); - PICEnabled = (PICForPIE || - LastPICArg->getOption().matches(options::OPT_fPIC) || - LastPICArg->getOption().matches(options::OPT_fpic)); - PICDisabled = !PICEnabled; + // For the PIC and PIE flag options, this logic is different from the legacy + // logic in very old versions of GCC, as that logic was just a bug no one had + // ever fixed. This logic is both more rational and consistent with GCC's new + // logic now that the bugs are fixed. The last argument relating to either + // PIC or PIE wins, and no other argument is used. If the last argument is + // any flavor of the '-fno-...' arguments, both PIC and PIE are disabled. Any + // PIE option implicitly enables PIC at the same level. + bool PIE = false; + bool PIC = getToolChain().isPICDefault(); + bool IsPICLevelTwo = PIC; + if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, + options::OPT_fpie, options::OPT_fno_pie)) { + Option O = A->getOption(); + if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) || + O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) { + PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie); + PIC = PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic); + IsPICLevelTwo = O.matches(options::OPT_fPIE) || + O.matches(options::OPT_fPIC); + } else { + PIE = PIC = false; + } + } + // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness + // is forced, then neither PIC nor PIE flags will have no effect. + if (getToolChain().isPICDefaultForced()) { + PIE = false; + PIC = getToolChain().isPICDefault(); + IsPICLevelTwo = PIC; } + + // Inroduce a Darwin-specific hack. If the default is PIC but the flags + // specified while enabling PIC enabled level 1 PIC, just force it back to + // level 2 PIC instead. This matches the behavior of Darwin GCC (based on my + // informal testing). + if (PIC && getToolChain().getTriple().isOSDarwin()) + IsPICLevelTwo |= getToolChain().isPICDefault(); + // Note that these flags are trump-cards. Regardless of the order w.r.t. the // PIC or PIE options above, if these show up, PIC is disabled. - if (Args.hasArg(options::OPT_mkernel)) - PICDisabled = true; + llvm::Triple Triple(TripleStr); + if ((Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)) && + (Triple.getOS() != llvm::Triple::IOS || + Triple.isOSVersionLT(6))) + PIC = PIE = false; if (Args.hasArg(options::OPT_static)) - PICDisabled = true; - bool DynamicNoPIC = Args.hasArg(options::OPT_mdynamic_no_pic); - - // Select the relocation model. - const char *Model = getToolChain().GetForcedPicModel(); - if (!Model) { - if (DynamicNoPIC) - Model = "dynamic-no-pic"; - else if (PICDisabled) - Model = "static"; - else if (PICEnabled) - Model = "pic"; - else - Model = getToolChain().GetDefaultRelocationModel(); - } - StringRef ModelStr = Model ? Model : ""; - if (Model && ModelStr != "pic") { - CmdArgs.push_back("-mrelocation-model"); - CmdArgs.push_back(Model); - } + PIC = PIE = false; + + if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) { + // This is a very special mode. It trumps the other modes, almost no one + // uses it, and it isn't even valid on any OS but Darwin. + if (!getToolChain().getTriple().isOSDarwin()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << getToolChain().getTriple().str(); - // Infer the __PIC__ and __PIE__ values. - if (ModelStr == "pic" && PICForPIE) { - CmdArgs.push_back("-pie-level"); - CmdArgs.push_back((LastPICArg && - LastPICArg->getOption().matches(options::OPT_fPIE)) ? - "2" : "1"); - } else if (ModelStr == "pic" || ModelStr == "dynamic-no-pic") { - CmdArgs.push_back("-pic-level"); - CmdArgs.push_back(((ModelStr != "dynamic-no-pic" && LastPICArg && - LastPICArg->getOption().matches(options::OPT_fPIC)) || - getToolChain().getTriple().isOSDarwin()) ? "2" : "1"); + // FIXME: Warn when this flag trumps some other PIC or PIE flag. + + CmdArgs.push_back("-mrelocation-model"); + CmdArgs.push_back("dynamic-no-pic"); + + // Only a forced PIC mode can cause the actual compile to have PIC defines + // etc., no flags are sufficient. This behavior was selected to closely + // match that of llvm-gcc and Apple GCC before that. + if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) { + CmdArgs.push_back("-pic-level"); + CmdArgs.push_back("2"); + } + } else { + // Currently, LLVM only knows about PIC vs. static; the PIE differences are + // handled in Clang's IRGen by the -pie-level flag. + CmdArgs.push_back("-mrelocation-model"); + CmdArgs.push_back(PIC ? "pic" : "static"); + + if (PIC) { + CmdArgs.push_back("-pic-level"); + CmdArgs.push_back(IsPICLevelTwo ? "2" : "1"); + if (PIE) { + CmdArgs.push_back("-pie-level"); + CmdArgs.push_back(IsPICLevelTwo ? "2" : "1"); + } + } } if (!Args.hasFlag(options::OPT_fmerge_all_constants, @@ -1713,7 +1863,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) { CmdArgs.push_back("-mregparm"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) @@ -1741,25 +1891,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // flag disables them after the flag enabling them, enable the codegen // optimization. This is complicated by several "umbrella" flags. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, options::OPT_fhonor_infinities, options::OPT_fno_honor_infinities)) - if (A->getOption().getID() != options::OPT_fno_finite_math_only && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_finite_math_only && A->getOption().getID() != options::OPT_fhonor_infinities) CmdArgs.push_back("-menable-no-infs"); if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, options::OPT_fhonor_nans, options::OPT_fno_honor_nans)) - if (A->getOption().getID() != options::OPT_fno_finite_math_only && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_finite_math_only && A->getOption().getID() != options::OPT_fhonor_nans) CmdArgs.push_back("-menable-no-nans"); // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes. bool MathErrno = getToolChain().IsMathErrnoDefault(); if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_fmath_errno, options::OPT_fno_math_errno)) MathErrno = A->getOption().getID() == options::OPT_fmath_errno; @@ -1772,38 +1927,46 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // madness. bool AssociativeMath = false; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_fassociative_math, options::OPT_fno_associative_math)) - if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_fno_associative_math) AssociativeMath = true; bool ReciprocalMath = false; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_freciprocal_math, options::OPT_fno_reciprocal_math)) - if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_fno_reciprocal_math) ReciprocalMath = true; bool SignedZeros = true; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_fsigned_zeros, options::OPT_fno_signed_zeros)) - if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_fsigned_zeros) SignedZeros = false; bool TrappingMath = true; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_ftrapping_math, options::OPT_fno_trapping_math)) - if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_ftrapping_math) TrappingMath = false; if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros && @@ -1813,16 +1976,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Validate and pass through -fp-contract option. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_ffp_contract)) { if (A->getOption().getID() == options::OPT_ffp_contract) { - StringRef Val = A->getValue(Args); + StringRef Val = A->getValue(); if (Val == "fast" || Val == "on" || Val == "off") { CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val)); } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Val; } - } else { // A is OPT_ffast_math + } else if (A->getOption().getID() == options::OPT_ffast_math) { // If fast-math is set then set the fp-contract mode to fast. CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast")); } @@ -1833,10 +1997,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // preprocessor macros. This is distinct from enabling any optimizations as // these options induce language changes which must survive serialization // and deserialization, etc. - if (Args.hasArg(options::OPT_ffast_math)) - CmdArgs.push_back("-ffast-math"); - if (Args.hasArg(options::OPT_ffinite_math_only)) - CmdArgs.push_back("-ffinite-math-only"); + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math)) + if (A->getOption().matches(options::OPT_ffast_math)) + CmdArgs.push_back("-ffast-math"); + if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math)) + if (A->getOption().matches(options::OPT_ffinite_math_only)) + CmdArgs.push_back("-ffinite-math-only"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. @@ -1885,7 +2051,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("-mlimit-float-precision"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } // FIXME: Handle -mtune=. @@ -1893,7 +2059,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { CmdArgs.push_back("-mcode-model"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } // Add target specific cpu and features flags. @@ -1937,7 +2103,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Pass the linker version in use. if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { CmdArgs.push_back("-target-linker-version"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } // -mno-omit-leaf-frame-pointer is the default on Darwin. @@ -1991,6 +2157,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now. Args.ClaimAllArgs(options::OPT_g_flags_Group); + if (Args.hasArg(options::OPT_gcolumn_info)) + CmdArgs.push_back("-dwarf-column-info"); Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); @@ -2008,7 +2176,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.getArgs().hasArg(options::OPT_S)) { if (Output.isFilename()) { CmdArgs.push_back("-coverage-file"); - CmdArgs.push_back(Args.MakeArgString(Output.getFilename())); + SmallString<128> absFilename(Output.getFilename()); + llvm::sys::fs::make_absolute(absFilename); + CmdArgs.push_back(Args.MakeArgString(absFilename)); } } @@ -2047,7 +2217,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case options::OPT_ccc_arcmt_migrate: CmdArgs.push_back("-arcmt-migrate"); CmdArgs.push_back("-mt-migrate-directory"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output); Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors); @@ -2062,7 +2232,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, << A->getAsString(Args) << "-ccc-arcmt-migrate"; } CmdArgs.push_back("-mt-migrate-directory"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); if (!Args.hasArg(options::OPT_objcmt_migrate_literals, options::OPT_objcmt_migrate_subscripting)) { @@ -2094,7 +2264,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (A->getOption().matches(options::OPT_O4)) CmdArgs.push_back("-O3"); else if (A->getOption().matches(options::OPT_O) && - A->getValue(Args)[0] == '\0') + A->getValue()[0] == '\0') CmdArgs.push_back("-O2"); else A->render(Args, CmdArgs); @@ -2132,8 +2302,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // eventually we want to do all the standard defaulting here instead of // splitting it between the driver and clang -cc1. if (!types::isCXX(InputType)) - Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, - "-std=", /*Joined=*/true); + Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, + "-std=", /*Joined=*/true); + else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32) + CmdArgs.push_back("-std=c++11"); + Args.AddLastArg(CmdArgs, options::OPT_trigraphs); } @@ -2182,18 +2355,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_, options::OPT_ftemplate_depth_EQ)) { CmdArgs.push_back("-ftemplate-depth"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) { CmdArgs.push_back("-fconstexpr-depth"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ, options::OPT_Wlarge_by_value_copy_def)) { if (A->getNumValues()) { - StringRef bytes = A->getValue(Args); + StringRef bytes = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes)); } else CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value @@ -2202,50 +2375,50 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_fbounds_checking, options::OPT_fbounds_checking_EQ)) { if (A->getNumValues()) { - StringRef val = A->getValue(Args); + StringRef val = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-fbounds-checking=" + val)); } else CmdArgs.push_back("-fbounds-checking=1"); } - if (Args.hasArg(options::OPT__relocatable_pch)) + if (Args.hasArg(options::OPT_relocatable_pch)) CmdArgs.push_back("-relocatable-pch"); if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) { CmdArgs.push_back("-fconstant-string-class"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) { CmdArgs.push_back("-ftabstop"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } CmdArgs.push_back("-ferror-limit"); if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ)) - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); else CmdArgs.push_back("19"); if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) { CmdArgs.push_back("-fmacro-backtrace-limit"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) { CmdArgs.push_back("-ftemplate-backtrace-limit"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) { CmdArgs.push_back("-fconstexpr-backtrace-limit"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } // Pass -fmessage-length=. CmdArgs.push_back("-fmessage-length"); if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) { - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } else { // If -fmessage-length=N was not specified, determine whether this is a // terminal and, if so, implicitly define -fmessage-length appropriately. @@ -2255,7 +2428,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) { CmdArgs.push_back("-fvisibility"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); @@ -2268,7 +2441,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-ffreestanding"); // Forward -f (flag) options which we can pass directly. - Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior); Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); @@ -2279,6 +2451,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree); Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type); + SanitizerArgs Sanitize(D, Args); + Sanitize.addArgs(Args, CmdArgs); + // Report and error for -faltivec on anything other then PowerPC. if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc || @@ -2289,14 +2464,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); - if (Args.hasFlag(options::OPT_faddress_sanitizer, - options::OPT_fno_address_sanitizer, false)) - CmdArgs.push_back("-faddress-sanitizer"); - - if (Args.hasFlag(options::OPT_fthread_sanitizer, - options::OPT_fno_thread_sanitizer, false)) - CmdArgs.push_back("-fthread-sanitizer"); - // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, options::OPT_fno_lax_vector_conversions)) @@ -2317,7 +2484,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) { CmdArgs.push_back("-ftrapv-handler"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ); @@ -2338,6 +2505,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_pthread); + // -stack-protector=0 is default. unsigned StackProtectorLevel = 0; if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, @@ -2356,6 +2524,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel))); } + // --param ssp-buffer-size= + for (arg_iterator it = Args.filtered_begin(options::OPT__param), + ie = Args.filtered_end(); it != ie; ++it) { + StringRef Str((*it)->getValue()); + if (Str.startswith("ssp-buffer-size=")) { + if (StackProtectorLevel) { + CmdArgs.push_back("-stack-protector-buffer-size"); + // FIXME: Verify the argument is a valid integer. + CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16))); + } + (*it)->claim(); + } + } + // Translate -mstackrealign if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign, false)) { @@ -2371,6 +2553,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment); CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); } + if (Args.hasArg(options::OPT_mstrict_align)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-strict-align"); + } // Forward -f options with positive and negative forms; we translate // these by hand. @@ -2428,9 +2614,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frtti is default. if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || - KernelOrKext) + KernelOrKext) { CmdArgs.push_back("-fno-rtti"); + // -fno-rtti cannot usefully be combined with -fsanitize=vptr. + if (Sanitize.sanitizesVptr()) { + std::string NoRttiArg = + Args.getLastArg(options::OPT_mkernel, + options::OPT_fapple_kext, + options::OPT_fno_rtti)->getAsString(Args); + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fsanitize=vptr" << NoRttiArg; + } + } + // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums, @@ -2538,12 +2735,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fobjc-default-synthesize-properties"); } + // -fencode-extended-block-signature=1 is default. + if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) { + CmdArgs.push_back("-fencode-extended-block-signature"); + } + // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc. // NOTE: This logic is duplicated in ToolChains.cpp. bool ARC = isObjCAutoRefCount(Args); if (ARC) { - if (!getToolChain().SupportsObjCARC()) - D.Diag(diag::err_arc_unsupported); + getToolChain().CheckObjCARC(); CmdArgs.push_back("-fobjc-arc"); @@ -2630,7 +2831,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fno-pack-struct doesn't apply to -fpack-struct=. if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) { std::string PackStructStr = "-fpack-struct="; - PackStructStr += A->getValue(Args); + PackStructStr += A->getValue(); CmdArgs.push_back(Args.MakeArgString(PackStructStr)); } else if (Args.hasFlag(options::OPT_fpack_struct, options::OPT_fno_pack_struct, false)) { @@ -2679,13 +2880,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) { CmdArgs.push_back("-fdiagnostics-show-category"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) { CmdArgs.push_back("-fdiagnostics-format"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg( @@ -2777,9 +2978,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Handle serialized diagnostics. if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) { CmdArgs.push_back("-serialize-diagnostic-file"); - CmdArgs.push_back(Args.MakeArgString(A->getValue(Args))); + CmdArgs.push_back(Args.MakeArgString(A->getValue())); } + if (Args.hasArg(options::OPT_fretain_comments_from_system_headers)) + CmdArgs.push_back("-fretain-comments-from-system-headers"); + // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. Args.AddAllArgValues(CmdArgs, options::OPT_Xclang); @@ -2789,7 +2993,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 (StringRef((*it)->getValue(Args, 0)) == "-disable-llvm-optzns") + if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") CmdArgs.push_back("-disable-llvm-optzns"); else (*it)->render(Args, CmdArgs); @@ -2808,7 +3012,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back("-x"); - CmdArgs.push_back(types::getTypeName(II.getType())); + if (Args.hasArg(options::OPT_rewrite_objc)) + CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX)); + else + CmdArgs.push_back(types::getTypeName(II.getType())); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else @@ -2895,7 +3102,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, if (runtimeArg && runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) { ObjCRuntime runtime; - StringRef value = runtimeArg->getValue(args); + StringRef value = runtimeArg->getValue(); if (runtime.tryParse(value)) { getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime) << value; @@ -2913,7 +3120,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, unsigned objcABIVersion = 1; // If -fobjc-abi-version= is present, use that to set the version. if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) { - StringRef value = abiArg->getValue(args); + StringRef value = abiArg->getValue(); if (value == "1") objcABIVersion = 1; else if (value == "2") @@ -2941,7 +3148,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, if (Arg *abiArg = args.getLastArg( options::OPT_fobjc_nonfragile_abi_version_EQ)) { - StringRef value = abiArg->getValue(args); + StringRef value = abiArg->getValue(); if (value == "1") nonFragileABIVersion = 1; else if (value == "2") @@ -2994,7 +3201,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, // Legacy behaviour is to target the gnustep runtime if we are i // non-fragile mode or the GCC runtime in fragile mode. if (isNonFragile) - runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple()); + runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6)); else runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple()); } @@ -3117,7 +3324,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { Arg *A = *it; - if (A->getOption().hasForwardToGCC()) { + if (forwardToGCC(A->getOption())) { // Don't forward any -g arguments to assembly steps. if (isa<AssembleJobAction>(JA) && A->getOption().matches(options::OPT_g_Group)) @@ -3135,17 +3342,17 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, RenderExtraToolArgs(JA, CmdArgs); // If using a driver driver, force the arch. - const std::string &Arch = getToolChain().getArchName(); + llvm::Triple::ArchType Arch = getToolChain().getArch(); if (getToolChain().getTriple().isOSDarwin()) { CmdArgs.push_back("-arch"); // FIXME: Remove these special cases. - if (Arch == "powerpc") + if (Arch == llvm::Triple::ppc) CmdArgs.push_back("ppc"); - else if (Arch == "powerpc64") + else if (Arch == llvm::Triple::ppc64) CmdArgs.push_back("ppc64"); else - CmdArgs.push_back(Args.MakeArgString(Arch)); + CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName())); } // Try to force gcc to match the tool chain we want, if we recognize @@ -3153,9 +3360,9 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: The triple class should directly provide the information we want // here. - if (Arch == "i386" || Arch == "powerpc") + if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) CmdArgs.push_back("-m32"); - else if (Arch == "x86_64" || Arch == "powerpc64") + else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86_64) CmdArgs.push_back("-m64"); if (Output.isFilename()) { @@ -3342,7 +3549,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { Arg *A = *it; - if (A->getOption().hasForwardToGCC()) { + if (forwardToGCC(A->getOption())) { // Don't forward any -g arguments to assembly steps. if (isa<AssembleJobAction>(JA) && A->getOption().matches(options::OPT_g_Group)) @@ -3410,6 +3617,37 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, } // Hexagon tools end. +llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { + // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for + // archs which Darwin doesn't use. + + // The matching this routine does is fairly pointless, since it is neither the + // complete architecture list, nor a reasonable subset. The problem is that + // historically the driver driver accepts this and also ties its -march= + // handling to the architecture name, so we need to be careful before removing + // support for it. + + // This code must be kept in sync with Clang's Darwin specific argument + // translation. + + return llvm::StringSwitch<llvm::Triple::ArchType>(Str) + .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc) + .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc) + .Case("ppc64", llvm::Triple::ppc64) + .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86) + .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4", + llvm::Triple::x86) + .Case("x86_64", llvm::Triple::x86_64) + // This is derived from the driver driver. + .Cases("arm", "armv4t", "armv5", "armv6", llvm::Triple::arm) + .Cases("armv7", "armv7f", "armv7k", "armv7s", "xscale", llvm::Triple::arm) + .Case("r600", llvm::Triple::r600) + .Case("nvptx", llvm::Triple::nvptx) + .Case("nvptx64", llvm::Triple::nvptx64) + .Case("amdil", llvm::Triple::amdil) + .Case("spir", llvm::Triple::spir) + .Default(llvm::Triple::UnknownArch); +} const char *darwin::CC1::getCC1Name(types::ID Type) const { switch (Type) { @@ -3458,7 +3696,7 @@ darwin::CC1::getDependencyFileName(const ArgList &Args, std::string Res; if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { - std::string Str(OutputOpt->getValue(Args)); + std::string Str(OutputOpt->getValue()); Res = Str.substr(0, Str.rfind('.')); } else { Res = darwin::CC1::getBaseInputStem(Args, Inputs); @@ -3547,6 +3785,7 @@ void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { .Case("duplicate-method-arg", true) .Case("dynamic-class-memaccess", true) .Case("enum-compare", true) + .Case("enum-conversion", true) .Case("exit-time-destructors", true) .Case("gnu", true) .Case("gnu-designator", true) @@ -3556,6 +3795,7 @@ void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { .Case("implicit-atomic-properties", true) .Case("incompatible-pointer-types", true) .Case("incomplete-implementation", true) + .Case("int-conversion", true) .Case("initializer-overrides", true) .Case("invalid-noreturn", true) .Case("invalid-token-paste", true) @@ -3620,7 +3860,10 @@ void darwin::CC1::AddCC1Args(const ArgList &Args, CheckCodeGenerationOptions(D, Args); // Derived from cc1 spec. - if (!Args.hasArg(options::OPT_mkernel) && !Args.hasArg(options::OPT_static) && + if ((!Args.hasArg(options::OPT_mkernel) || + (getDarwinToolChain().isTargetIPhoneOS() && + !getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) && + !Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_mdynamic_no_pic)) CmdArgs.push_back("-fPIC"); @@ -3673,7 +3916,7 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, Args.hasArg(options::OPT_o)) { Arg *OutputOpt = Args.getLastArg(options::OPT_o); CmdArgs.push_back("-auxbase-strip"); - CmdArgs.push_back(OutputOpt->getValue(Args)); + CmdArgs.push_back(OutputOpt->getValue()); } else { CmdArgs.push_back("-auxbase"); CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs)); @@ -3812,7 +4055,7 @@ void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args, Args.AddLastArg(CmdArgs, options::OPT_P); // FIXME: Handle %I properly. - if (getToolChain().getArchName() == "x86_64") { + if (getToolChain().getArch() == llvm::Triple::x86_64) { CmdArgs.push_back("-imultilib"); CmdArgs.push_back("x86_64"); } @@ -3838,7 +4081,7 @@ void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args, (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) { if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { CmdArgs.push_back("-MQ"); - CmdArgs.push_back(OutputOpt->getValue(Args)); + CmdArgs.push_back(OutputOpt->getValue()); } } @@ -4074,9 +4317,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-force_cpusubtype_ALL"); if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 && - (Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_fapple_kext))) + (((Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)) && + (!getDarwinToolChain().isTargetIPhoneOS() || + getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) || + Args.hasArg(options::OPT_static))) CmdArgs.push_back("-static"); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -4111,16 +4356,29 @@ void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, CmdArgs.push_back("-force_cpusubtype_ALL"); } +bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const { + // We only need to generate a temp path for LTO if we aren't compiling object + // files. When compiling source files, we run 'dsymutil' after linking. We + // don't run 'dsymutil' when compiling object files. + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) + if (it->getType() != types::TY_Object) + return true; + + return false; +} + void darwin::Link::AddLinkArgs(Compilation &C, const ArgList &Args, - ArgStringList &CmdArgs) const { + ArgStringList &CmdArgs, + const InputInfoList &Inputs) const { const Driver &D = getToolChain().getDriver(); const toolchains::Darwin &DarwinTC = getDarwinToolChain(); unsigned Version[3] = { 0, 0, 0 }; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { bool HadExtra; - if (!Driver::GetReleaseVersion(A->getValue(Args), Version[0], + if (!Driver::GetReleaseVersion(A->getValue(), Version[0], Version[1], Version[2], HadExtra) || HadExtra) D.Diag(diag::err_drv_invalid_version_number) @@ -4141,7 +4399,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 (StringRef(A->getValue(Args, i)) == "-kext") + if (StringRef(A->getValue(i)) == "-kext") UsesLdClassic = true; } } @@ -4152,7 +4410,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, // If we are using LTO, then automatically create a temporary file path for // the linker to use, so that it's lifetime will extend past a possible // dsymutil step. - if (Version[0] >= 116 && D.IsUsingLTO(Args)) { + if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) { const char *TmpPath = C.getArgs().MakeArgString( D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object))); C.addTempFile(TmpPath); @@ -4287,7 +4545,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { CmdArgs.push_back("-syslibroot"); - CmdArgs.push_back(A->getValue(Args)); + CmdArgs.push_back(A->getValue()); } Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace); @@ -4339,7 +4597,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // I'm not sure why this particular decomposition exists in gcc, but // we follow suite for ease of comparison. - AddLinkArgs(C, Args, CmdArgs); + AddLinkArgs(C, Args, CmdArgs, Inputs); Args.AddAllArgs(CmdArgs, options::OPT_d_Flag); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -4424,7 +4682,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lcrt1.o"); - else + else if (getDarwinToolChain().isIPhoneOSVersionLT(6, 0)) CmdArgs.push_back("-lcrt1.3.1.o"); } else { if (getDarwinToolChain().isMacosxVersionLT(10, 5)) @@ -4452,11 +4710,12 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); - // If we're building a dynamic lib with -faddress-sanitizer, unresolved - // symbols may appear. Mark all of them as dynamic_lookup. - // Linking executables is handled in lib/Driver/ToolChains.cpp. - if (Args.hasFlag(options::OPT_faddress_sanitizer, - options::OPT_fno_address_sanitizer, false)) { + SanitizerArgs Sanitize(getToolChain().getDriver(), Args); + // If we're building a dynamic lib with -fsanitize=address, or + // -fsanitize=undefined, unresolved symbols may appear. Mark all + // of them as dynamic_lookup. Linking executables is handled in + // lib/Driver/ToolChains.cpp. + if (Sanitize.needsAsanRt() || Sanitize.needsUbsanRt()) { if (Args.hasArg(options::OPT_dynamiclib) || Args.hasArg(options::OPT_bundle)) { CmdArgs.push_back("-undefined"); @@ -4475,14 +4734,14 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, !Args.hasArg(options::OPT_nodefaultlibs)) { // Avoid linking compatibility stubs on i386 mac. if (!getDarwinToolChain().isTargetMacOS() || - getDarwinToolChain().getArchName() != "i386") { + getDarwinToolChain().getArch() != llvm::Triple::x86) { // If we don't have ARC or subscripting runtime support, link in the // runtime stubs. We have to do this *before* adding any of the normal // linker inputs so that its initializer gets run first. ObjCRuntime runtime = getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true); // We use arclite library for both ARC and subscripting support. - if ((!runtime.hasARC() && isObjCAutoRefCount(Args)) || + if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) || !runtime.hasSubscripting()) getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); } @@ -4938,14 +5197,21 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, // the default system libraries. Just mimic this for now. CmdArgs.push_back("-lgcc"); - if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-lpthread"); + if (Args.hasArg(options::OPT_pthread)) { + if (!Args.hasArg(options::OPT_shared) && + Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lpthread_p"); + else + CmdArgs.push_back("-lpthread"); + } + if (!Args.hasArg(options::OPT_shared)) { - if (Args.hasArg(options::OPT_pg)) + if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lc_p"); else CmdArgs.push_back("-lc"); } + CmdArgs.push_back("-lgcc"); } @@ -5057,8 +5323,14 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lm"); } - if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-lpthread"); + if (Args.hasArg(options::OPT_pthread)) { + if (!Args.hasArg(options::OPT_shared) && + Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lpthread_p"); + else + CmdArgs.push_back("-lpthread"); + } + if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lc_p"); @@ -5109,17 +5381,48 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on FreeBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. - if (getToolChain().getArchName() == "i386") + if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); - - if (getToolChain().getArchName() == "powerpc") + else if (getToolChain().getArch() == llvm::Triple::ppc) CmdArgs.push_back("-a32"); + else if (getToolChain().getArch() == llvm::Triple::mips || + getToolChain().getArch() == llvm::Triple::mipsel || + getToolChain().getArch() == llvm::Triple::mips64 || + getToolChain().getArch() == llvm::Triple::mips64el) { + StringRef CPUName; + StringRef ABIName; + getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); - // Set byte order explicitly - if (getToolChain().getArchName() == "mips") - CmdArgs.push_back("-EB"); - else if (getToolChain().getArchName() == "mipsel") - CmdArgs.push_back("-EL"); + CmdArgs.push_back("-march"); + CmdArgs.push_back(CPUName.data()); + + // Convert ABI name to the GNU tools acceptable variant. + if (ABIName == "o32") + ABIName = "32"; + else if (ABIName == "n64") + ABIName = "64"; + + CmdArgs.push_back("-mabi"); + CmdArgs.push_back(ABIName.data()); + + if (getToolChain().getArch() == llvm::Triple::mips || + getToolChain().getArch() == llvm::Triple::mips64) + CmdArgs.push_back("-EB"); + else + CmdArgs.push_back("-EL"); + + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, + options::OPT_fpie, options::OPT_fno_pie); + if (LastPICArg && + (LastPICArg->getOption().matches(options::OPT_fPIC) || + LastPICArg->getOption().matches(options::OPT_fpic) || + LastPICArg->getOption().matches(options::OPT_fPIE) || + LastPICArg->getOption().matches(options::OPT_fpie))) { + CmdArgs.push_back("-KPIC"); + } + } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -5143,7 +5446,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const Driver &D = getToolChain().getDriver(); + const toolchains::FreeBSD& ToolChain = + static_cast<const toolchains::FreeBSD&>(getToolChain()); + const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" @@ -5157,6 +5462,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_pie)) + CmdArgs.push_back("-pie"); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { @@ -5169,8 +5477,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/libexec/ld-elf.so.1"); } - if (getToolChain().getTriple().getOSMajorVersion() >= 9) { - llvm::Triple::ArchType Arch = getToolChain().getArch(); + if (ToolChain.getTriple().getOSMajorVersion() >= 9) { + llvm::Triple::ArchType Arch = ToolChain.getArch(); if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { CmdArgs.push_back("--hash-style=both"); @@ -5181,12 +5489,12 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on FreeBSD/amd64, we have to explicitly // instruct ld in the base system to link 32-bit code. - if (getToolChain().getArchName() == "i386") { + if (ToolChain.getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386_fbsd"); } - if (getToolChain().getArchName() == "powerpc") { + if (ToolChain.getArch() == llvm::Triple::ppc) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc_fbsd"); } @@ -5200,29 +5508,33 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { + const char *crt1 = NULL; if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("gcrt1.o"))); - else { - const char *crt = Args.hasArg(options::OPT_pie) ? "Scrt1.o" : "crt1.o"; - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath(crt))); - } - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crti.o"))); - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crtbegin.o"))); - } else { - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crti.o"))); - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crtbeginS.o"))); + crt1 = "gcrt1.o"; + else if (Args.hasArg(options::OPT_pie)) + crt1 = "Scrt1.o"; + else + crt1 = "crt1.o"; } + if (crt1) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); + + const char *crtbegin = NULL; + if (Args.hasArg(options::OPT_static)) + crtbegin = "crtbeginT.o"; + else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + crtbegin = "crtbeginS.o"; + else + crtbegin = "crtbegin.o"; + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); } Args.AddAllArgs(CmdArgs, options::OPT_L); - const ToolChain::path_list Paths = getToolChain().getFilePaths(); + const ToolChain::path_list Paths = ToolChain.getFilePaths(); for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); @@ -5233,12 +5545,12 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { - getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else @@ -5291,20 +5603,17 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - if (!Args.hasArg(options::OPT_shared)) - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "crtend.o"))); + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); else - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "crtendS.o"))); - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "crtn.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple()); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(ToolChain.GetProgramPath("ld")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5321,9 +5630,9 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--32"); // Set byte order explicitly - if (getToolChain().getArchName() == "mips") + if (getToolChain().getArch() == llvm::Triple::mips) CmdArgs.push_back("-EB"); - else if (getToolChain().getArchName() == "mipsel") + else if (getToolChain().getArch() == llvm::Triple::mipsel) CmdArgs.push_back("-EL"); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -5548,7 +5857,7 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, static void AddLibgcc(llvm::Triple Triple, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { - bool isAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI; + bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android; bool StaticLibgcc = isAndroid || Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_libgcc); if (!D.CCCIsCXX) @@ -5571,6 +5880,11 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D, CmdArgs.push_back("-lgcc"); } +static bool hasMipsN32ABIArg(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef("n32")); +} + void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -5579,8 +5893,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, const toolchains::Linux& ToolChain = static_cast<const toolchains::Linux&>(getToolChain()); const Driver &D = ToolChain.getDriver(); - const bool isAndroid = ToolChain.getTriple().getEnvironment() == - llvm::Triple::ANDROIDEABI; + const bool isAndroid = + ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; ArgStringList CmdArgs; @@ -5627,10 +5941,18 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("elf32btsmip"); else if (ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("elf32ltsmip"); - else if (ToolChain.getArch() == llvm::Triple::mips64) - CmdArgs.push_back("elf64btsmip"); - else if (ToolChain.getArch() == llvm::Triple::mips64el) - CmdArgs.push_back("elf64ltsmip"); + else if (ToolChain.getArch() == llvm::Triple::mips64) { + if (hasMipsN32ABIArg(Args)) + CmdArgs.push_back("elf32btsmipn32"); + else + CmdArgs.push_back("elf64btsmip"); + } + else if (ToolChain.getArch() == llvm::Triple::mips64el) { + if (hasMipsN32ABIArg(Args)) + CmdArgs.push_back("elf32ltsmipn32"); + else + CmdArgs.push_back("elf64ltsmip"); + } else CmdArgs.push_back("elf_x86_64"); @@ -5642,8 +5964,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-static"); } else if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); - if ((ToolChain.getArch() == llvm::Triple::arm - || ToolChain.getArch() == llvm::Triple::thumb) && isAndroid) { + if (isAndroid) { CmdArgs.push_back("-Bsymbolic"); } } @@ -5668,8 +5989,12 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("/lib/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::mips64 || - ToolChain.getArch() == llvm::Triple::mips64el) - CmdArgs.push_back("/lib64/ld.so.1"); + ToolChain.getArch() == llvm::Triple::mips64el) { + if (hasMipsN32ABIArg(Args)) + CmdArgs.push_back("/lib32/ld.so.1"); + else + CmdArgs.push_back("/lib64/ld.so.1"); + } else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("/lib/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::ppc64) @@ -5700,11 +6025,16 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *crtbegin; if (Args.hasArg(options::OPT_static)) crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; - else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + else if (Args.hasArg(options::OPT_shared)) crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; + else if (Args.hasArg(options::OPT_pie)) + crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; else crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + + // Add crtfastmath.o if available and fast math is enabled. + ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); } Args.AddAllArgs(CmdArgs, options::OPT_L); @@ -5729,6 +6059,12 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + SanitizerArgs Sanitize(D, Args); + + // Call this before we add the C++ ABI library. + if (Sanitize.needsUbsanRt()) + addUbsanRTLinux(getToolChain(), Args, CmdArgs); + if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -5743,8 +6079,10 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, } // Call this before we add the C run-time. - addAsanRTLinux(getToolChain(), Args, CmdArgs); - addTsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsAsanRt()) + addAsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsTsanRt()) + addTsanRTLinux(getToolChain(), Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { @@ -5767,8 +6105,10 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostartfiles)) { const char *crtend; - if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + if (Args.hasArg(options::OPT_shared)) crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; + else if (Args.hasArg(options::OPT_pie)) + crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; else crtend = isAndroid ? "crtend_android.o" : "crtend.o"; @@ -5874,7 +6214,7 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on DragonFly/pc64, we have to explicitly // instruct as in the base system to assemble 32-bit code. - if (getToolChain().getArchName() == "i386") + if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -5918,7 +6258,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on DragonFly/pc64, we have to explicitly // instruct ld in the base system to link 32-bit code. - if (getToolChain().getArchName() == "i386") { + if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); } diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index 999c57a..5898c66 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -202,6 +202,8 @@ namespace hexagon { namespace darwin { + llvm::Triple::ArchType getArchTypeForDarwinArchName(StringRef Str); + class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool { virtual void anchor(); protected: @@ -288,8 +290,9 @@ namespace darwin { }; class LLVM_LIBRARY_VISIBILITY Link : public DarwinTool { + bool NeedsTempPath(const InputInfoList &Inputs) const; void AddLinkArgs(Compilation &C, const ArgList &Args, - ArgStringList &CmdArgs) const; + ArgStringList &CmdArgs, const InputInfoList &Inputs) const; public: Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", TC) {} diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp index 9d8fcfd..862025e 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp @@ -94,20 +94,6 @@ bool types::isAcceptedByClang(ID Id) { } } -bool types::isOnlyAcceptedByClang(ID Id) { - switch (Id) { - default: - return false; - - case TY_AST: - case TY_LLVM_IR: - case TY_LLVM_BC: - case TY_RewrittenObjC: - case TY_RewrittenLegacyObjC: - return true; - } -} - bool types::isObjC(ID Id) { switch (Id) { default: diff --git a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp index 6827034..de2d535 100644 --- a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp @@ -81,19 +81,15 @@ bool Windows::IsIntegratedAssemblerDefault() const { } bool Windows::IsUnwindTablesDefault() const { - // FIXME: Gross; we should probably have some separate target - // definition, possibly even reusing the one in clang. - return getArchName() == "x86_64"; + return getArch() == llvm::Triple::x86_64; } -const char *Windows::GetDefaultRelocationModel() const { - return "static"; +bool Windows::isPICDefault() const { + return getArch() == llvm::Triple::x86_64; } -const char *Windows::GetForcedPicModel() const { - if (getArchName() == "x86_64") - return "pic"; - return 0; +bool Windows::isPICDefaultForced() const { + return getArch() == llvm::Triple::x86_64; } // FIXME: This probably should goto to some platform utils place. |