diff options
Diffstat (limited to 'lib/Driver')
-rw-r--r-- | lib/Driver/ArgList.cpp | 59 | ||||
-rw-r--r-- | lib/Driver/CC1Options.cpp | 43 | ||||
-rw-r--r-- | lib/Driver/CMakeLists.txt | 4 | ||||
-rw-r--r-- | lib/Driver/Compilation.cpp | 1 | ||||
-rw-r--r-- | lib/Driver/Driver.cpp | 54 | ||||
-rw-r--r-- | lib/Driver/DriverOptions.cpp | 42 | ||||
-rw-r--r-- | lib/Driver/HostInfo.cpp | 10 | ||||
-rw-r--r-- | lib/Driver/OptTable.cpp | 220 | ||||
-rw-r--r-- | lib/Driver/Option.cpp | 53 | ||||
-rw-r--r-- | lib/Driver/ToolChains.cpp | 11 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 30 | ||||
-rw-r--r-- | lib/Driver/Types.cpp | 6 |
12 files changed, 289 insertions, 244 deletions
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp index 8d2138d..ea75c34 100644 --- a/lib/Driver/ArgList.cpp +++ b/lib/Driver/ArgList.cpp @@ -27,38 +27,41 @@ void ArgList::append(Arg *A) { Args.push_back(A); } -Arg *ArgList::getLastArg(options::ID Id, bool Claim) const { +Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { // FIXME: Make search efficient? - for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) { - if ((*it)->getOption().matches(Id)) { - if (Claim) (*it)->claim(); + for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) + if ((*it)->getOption().matches(Id)) return *it; - } - } - return 0; } -Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const { - Arg *Res, *A0 = getLastArg(Id0, false), *A1 = getLastArg(Id1, false); +Arg *ArgList::getLastArg(OptSpecifier Id) const { + Arg *A = getLastArgNoClaim(Id); + if (A) + A->claim(); + return A; +} + +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const { + Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1); if (A0 && A1) Res = A0->getIndex() > A1->getIndex() ? A0 : A1; else Res = A0 ? A0 : A1; - if (Claim && Res) + if (Res) Res->claim(); return Res; } -Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, - bool Claim) const { +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, + OptSpecifier Id2) const { Arg *Res = 0; - Arg *A0 = getLastArg(Id0, false); - Arg *A1 = getLastArg(Id1, false); - Arg *A2 = getLastArg(Id2, false); + Arg *A0 = getLastArgNoClaim(Id0); + Arg *A1 = getLastArgNoClaim(Id1); + Arg *A2 = getLastArgNoClaim(Id2); int A0Idx = A0 ? A0->getIndex() : -1; int A1Idx = A1 ? A1->getIndex() : -1; @@ -76,26 +79,26 @@ Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, Res = A2; } - if (Claim && Res) + if (Res) Res->claim(); return Res; } -bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const { +bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { if (Arg *A = getLastArg(Pos, Neg)) return A->getOption().matches(Pos); return Default; } -void ArgList::AddLastArg(ArgStringList &Output, options::ID Id) const { +void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { if (Arg *A = getLastArg(Id)) { A->claim(); A->render(*this, Output); } } -void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const { +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -106,8 +109,8 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const { } } -void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, - options::ID Id1) const { +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -118,8 +121,8 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, } } -void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, - options::ID Id1, options::ID Id2) const { +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1, OptSpecifier Id2) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -131,7 +134,7 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, } } -void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const { +void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -143,8 +146,8 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const { } } -void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0, - options::ID Id1) const { +void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -156,7 +159,7 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0, } } -void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0, +void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, const char *Translation, bool Joined) const { // FIXME: Make fast. @@ -177,7 +180,7 @@ void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0, } } -void ArgList::ClaimAllArgs(options::ID Id0) const { +void ArgList::ClaimAllArgs(OptSpecifier Id0) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; diff --git a/lib/Driver/CC1Options.cpp b/lib/Driver/CC1Options.cpp new file mode 100644 index 0000000..672fe04 --- /dev/null +++ b/lib/Driver/CC1Options.cpp @@ -0,0 +1,43 @@ +//===--- CC1Options.cpp - Clang CC1 Options Table -----------------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/CC1Options.h" +#include "clang/Driver/OptTable.h" +#include "clang/Driver/Option.h" + +using namespace clang::driver; +using namespace clang::driver::options; +using namespace clang::driver::cc1options; + +static OptTable::Info CC1InfoTable[] = { + // The InputOption info + { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID }, + // The UnknownOption info + { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID }, + +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + OPT_##GROUP, OPT_##ALIAS }, +#include "clang/Driver/CC1Options.inc" +}; + +namespace { + +class CC1OptTable : public OptTable { +public: + CC1OptTable() + : OptTable(CC1InfoTable, sizeof(CC1InfoTable) / sizeof(CC1InfoTable[0])) {} +}; + +} + +OptTable *clang::driver::createCC1OptTable() { + return new CC1OptTable(); +} diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index b6998ab..60d8e9c 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -4,8 +4,10 @@ add_clang_library(clangDriver Action.cpp Arg.cpp ArgList.cpp + CC1Options.cpp Compilation.cpp Driver.cpp + DriverOptions.cpp HostInfo.cpp Job.cpp OptTable.cpp @@ -18,4 +20,4 @@ add_clang_library(clangDriver Types.cpp ) -add_dependencies(clangDriver ClangDiagnosticDriver) +add_dependencies(clangDriver ClangDiagnosticDriver ClangDriverOptions ClangCC1Options) diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index c12f5aa..ffa627a 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index b4693f2..b40dc27 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -16,6 +16,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/HostInfo.h" #include "clang/Driver/Job.h" +#include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" @@ -44,7 +45,7 @@ Driver::Driver(const char *_Name, const char *_Dir, const char *_DefaultHostTriple, const char *_DefaultImageName, bool IsProduction, Diagnostic &_Diags) - : Opts(new OptTable()), Diags(_Diags), + : Opts(createDriverOptTable()), Diags(_Diags), Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple), DefaultImageName(_DefaultImageName), Host(0), @@ -75,40 +76,23 @@ Driver::~Driver() { InputArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); - InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); + unsigned MissingArgIndex, MissingArgCount; + InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd, + MissingArgIndex, MissingArgCount); - // FIXME: Handle '@' args (or at least error on them). - - unsigned Index = 0, End = ArgEnd - ArgBegin; - while (Index < End) { - // gcc's handling of empty arguments doesn't make sense, but this is not a - // common use case. :) - // - // We just ignore them here (note that other things may still take them as - // arguments). - if (Args->getArgString(Index)[0] == '\0') { - ++Index; - continue; - } - - unsigned Prev = Index; - Arg *A = getOpts().ParseOneArg(*Args, Index); - assert(Index > Prev && "Parser failed to consume argument."); - - // Check for missing argument error. - if (!A) { - assert(Index >= End && "Unexpected parser error."); - Diag(clang::diag::err_drv_missing_argument) - << Args->getArgString(Prev) - << (Index - Prev - 1); - break; - } + // Check for missing argument error. + if (MissingArgCount) + Diag(clang::diag::err_drv_missing_argument) + << Args->getArgString(MissingArgIndex) << MissingArgCount; + // Check for unsupported options. + for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); + it != ie; ++it) { + Arg *A = *it; if (A->getOption().isUnsupported()) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } - Args->append(A); } return Args; @@ -340,8 +324,8 @@ void Driver::PrintHelp(bool ShowHidden) const { // Render help text into (option, help) pairs. std::vector< std::pair<std::string, const char*> > OptionHelp; - for (unsigned i = options::OPT_INPUT, e = options::LastOption; i != e; ++i) { - options::ID Id = (options::ID) i; + for (unsigned i = 0, e = getOpts().getNumOptions(); i != e; ++i) { + options::ID Id = (options::ID) (i + 1); if (const char *Text = getOpts().getOptionHelpText(Id)) OptionHelp.push_back(std::make_pair(getOptionHelpName(getOpts(), Id), Text)); @@ -591,7 +575,7 @@ void Driver::BuildUniversalActions(const ArgList &Args, it != ie; ++it) { Arg *A = *it; - if (A->getOption().getId() == options::OPT_arch) { + if (A->getOption().matches(options::OPT_arch)) { // 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 = @@ -686,7 +670,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const { // // Otherwise emit an error but still use a valid type to avoid // spurious errors (e.g., no inputs). - if (!Args.hasArg(options::OPT_E, false)) + if (!Args.hasArgNoClaim(options::OPT_E)) Diag(clang::diag::err_drv_unknown_stdin_type); Ty = types::TY_C; } else { @@ -730,7 +714,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const { // necessary. Inputs.push_back(std::make_pair(types::TY_Object, A)); - } else if (A->getOption().getId() == options::OPT_x) { + } else if (A->getOption().matches(options::OPT_x)) { InputTypeArg = A; InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args)); @@ -984,7 +968,7 @@ void Driver::BuildJobs(Compilation &C) const { // FIXME: Use iterator. for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { - if ((*it)->isClaimed() && (*it)->getOption().matches(Opt.getId())) { + if ((*it)->isClaimed() && (*it)->getOption().matches(&Opt)) { DuplicateClaimed = true; break; } diff --git a/lib/Driver/DriverOptions.cpp b/lib/Driver/DriverOptions.cpp new file mode 100644 index 0000000..eddaee0 --- /dev/null +++ b/lib/Driver/DriverOptions.cpp @@ -0,0 +1,42 @@ +//===--- DriverOptions.cpp - Driver Options Table -----------------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/Options.h" +#include "clang/Driver/OptTable.h" +#include "clang/Driver/Option.h" + +using namespace clang::driver; +using namespace clang::driver::options; + +static OptTable::Info InfoTable[] = { + // The InputOption info + { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID }, + // The UnknownOption info + { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID }, + +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + OPT_##GROUP, OPT_##ALIAS }, +#include "clang/Driver/Options.inc" +}; + +namespace { + +class DriverOptTable : public OptTable { +public: + DriverOptTable() + : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {} +}; + +} + +OptTable *clang::driver::createDriverOptTable() { + return new DriverOptTable(); +} diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 08c4ef4..ed73b17 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -122,7 +122,7 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, // // FIXME: Should this information be in llvm::Triple? if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (A->getOption().getId() == options::OPT_m32) { + if (A->getOption().matches(options::OPT_m32)) { if (Arch == llvm::Triple::x86_64) Arch = llvm::Triple::x86; if (Arch == llvm::Triple::ppc64) @@ -205,11 +205,11 @@ ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64"; + (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64"; + (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } @@ -478,11 +478,11 @@ ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args, if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64"; + (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64"; + (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp index affd1c5..f68a1d8 100644 --- a/lib/Driver/OptTable.cpp +++ b/lib/Driver/OptTable.cpp @@ -1,4 +1,4 @@ -//===--- Options.cpp - Option info table --------------------------------*-===// +//===--- OptTable.cpp - Option Table Implementation ---------------------*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/Driver/Options.h" - +#include "clang/Driver/OptTable.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" @@ -18,18 +17,6 @@ using namespace clang::driver; using namespace clang::driver::options; -struct Info { - const char *Name; - const char *Flags; - const char *HelpText; - const char *MetaVar; - - Option::OptionClass Kind; - unsigned GroupID; - unsigned AliasID; - unsigned Param; -}; - // Ordering on Info. The ordering is *almost* lexicographic, with two // exceptions. First, '\0' comes at the end of the alphabet instead of // the beginning (thus options preceed any other options which prefix @@ -56,7 +43,9 @@ static int StrCmpOptionName(const char *A, const char *B) { return (a < b) ? -1 : 1; } -static inline bool operator<(const Info &A, const Info &B) { +namespace clang { +namespace driver { +static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { if (&A == &B) return false; @@ -70,57 +59,62 @@ static inline bool operator<(const Info &A, const Info &B) { return B.Kind == Option::JoinedClass; } +// Support lower_bound between info and an option name. +static inline bool operator<(const OptTable::Info &I, const char *Name) { + return StrCmpOptionName(I.Name, Name) == -1; +} +static inline bool operator<(const char *Name, const OptTable::Info &I) { + return StrCmpOptionName(Name, I.Name) == -1; +} +} +} + // -static Info OptionInfos[] = { - // The InputOption info - { "<input>", "d", 0, 0, Option::InputClass, OPT_INVALID, OPT_INVALID, 0 }, - // The UnknownOption info - { "<unknown>", "", 0, 0, Option::UnknownClass, OPT_INVALID, OPT_INVALID, 0 }, - -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ - { NAME, FLAGS, HELPTEXT, METAVAR, \ - Option::KIND##Class, OPT_##GROUP, OPT_##ALIAS, PARAM }, -#include "clang/Driver/Options.def" -}; -static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]); - -static Info &getInfo(unsigned id) { - assert(id > 0 && id - 1 < numOptions && "Invalid Option ID."); - return OptionInfos[id - 1]; -} +OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} -OptTable::OptTable() : Options(new Option*[numOptions]) { +// + +OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) + : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos), + Options(new Option*[NumOptionInfos]), + TheInputOption(0), TheUnknownOption(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) * numOptions); + memset(Options, 0, sizeof(*Options) * NumOptionInfos); // Find start of normal options. - FirstSearchableOption = 0; - for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) { - if (getInfo(i).Kind != Option::GroupClass) { - FirstSearchableOption = i; + 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); + } else if (Kind == Option::UnknownClass) { + assert(!TheUnknownOption && "Cannot have multiple input options!"); + TheUnknownOption = getOption(i + 1); + } else if (Kind != Option::GroupClass) { + FirstSearchableIndex = i; break; } } - assert(FirstSearchableOption != 0 && "No searchable options?"); + assert(FirstSearchableIndex != 0 && "No searchable options?"); #ifndef NDEBUG // Check that everything after the first searchable option is a // regular option class. - for (unsigned i = FirstSearchableOption; i < LastOption; ++i) { - Option::OptionClass Kind = getInfo(i).Kind; + for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) { + Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind; assert((Kind != Option::InputClass && Kind != Option::UnknownClass && Kind != Option::GroupClass) && "Special options should be defined first!"); } // Check that options are in order. - for (unsigned i = FirstSearchableOption + 1; i < LastOption; ++i) { - if (!(getInfo(i - 1) < getInfo(i))) { - getOption((options::ID) (i - 1))->dump(); - getOption((options::ID) i)->dump(); + for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) { + if (!(getInfo(i) < getInfo(i + 1))) { + getOption(i)->dump(); + getOption(i + 1)->dump(); assert(0 && "Options are not in order!"); } } @@ -128,56 +122,23 @@ OptTable::OptTable() : Options(new Option*[numOptions]) { } OptTable::~OptTable() { - for (unsigned i = 0; i < numOptions; ++i) + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) delete Options[i]; delete[] Options; } -unsigned OptTable::getNumOptions() const { - return numOptions; -} - -const char *OptTable::getOptionName(options::ID id) const { - return getInfo(id).Name; -} - -unsigned OptTable::getOptionKind(options::ID id) const { - return getInfo(id).Kind; -} - -const char *OptTable::getOptionHelpText(options::ID id) const { - return getInfo(id).HelpText; -} - -const char *OptTable::getOptionMetaVar(options::ID id) const { - return getInfo(id).MetaVar; -} - -const Option *OptTable::getOption(options::ID id) const { - if (id == OPT_INVALID) - return 0; - - assert((unsigned) (id - 1) < numOptions && "Invalid ID."); - - Option *&Entry = Options[id - 1]; - if (!Entry) - Entry = constructOption(id); - - return Entry; -} - -Option *OptTable::constructOption(options::ID id) const { - Info &info = getInfo(id); +Option *OptTable::CreateOption(unsigned id) const { + const Info &info = getInfo(id); const OptionGroup *Group = - cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID)); - const Option *Alias = getOption((options::ID) info.AliasID); + 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(); break; + Opt = new InputOption(id); break; case Option::UnknownClass: - Opt = new UnknownOption(); break; + Opt = new UnknownOption(id); break; case Option::GroupClass: Opt = new OptionGroup(id, info.Name, Group); break; case Option::FlagClass: @@ -196,44 +157,38 @@ Option *OptTable::constructOption(options::ID id) const { Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break; } - for (const char *s = info.Flags; *s; ++s) { - switch (*s) { - default: assert(0 && "Invalid option flag."); - case 'J': - assert(info.Kind == Option::SeparateClass && "Invalid option."); - Opt->setForceJoinedRender(true); break; - case 'S': - assert(info.Kind == Option::JoinedClass && "Invalid option."); - Opt->setForceSeparateRender(true); break; - case 'd': Opt->setDriverOption(true); break; - case 'i': Opt->setNoOptAsInput(true); break; - case 'l': Opt->setLinkerInput(true); break; - case 'q': Opt->setNoArgumentUnused(true); break; - case 'u': Opt->setUnsupported(true); break; - } + if (info.Flags & DriverOption) + Opt->setDriverOption(true); + if (info.Flags & LinkerInput) + Opt->setLinkerInput(true); + if (info.Flags & NoArgumentUnused) + Opt->setNoArgumentUnused(true); + if (info.Flags & RenderAsInput) + Opt->setNoOptAsInput(true); + if (info.Flags & RenderJoined) { + assert(info.Kind == Option::SeparateClass && "Invalid option."); + Opt->setForceJoinedRender(true); } + if (info.Flags & RenderSeparate) { + assert(info.Kind == Option::JoinedClass && "Invalid option."); + Opt->setForceSeparateRender(true); + } + if (info.Flags & Unsupported) + Opt->setUnsupported(true); return Opt; } -// Support lower_bound between info and an option name. -static inline bool operator<(struct Info &I, const char *Name) { - return StrCmpOptionName(I.Name, Name) == -1; -} -static inline bool operator<(const char *Name, struct Info &I) { - return StrCmpOptionName(Name, I.Name) == -1; -} - Arg *OptTable::ParseOneArg(const InputArgList &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 PositionalArg(getOption(OPT_INPUT), Index++); + return new PositionalArg(TheInputOption, Index++); - struct Info *Start = OptionInfos + FirstSearchableOption - 1; - struct Info *End = OptionInfos + LastOption - 1; + const Info *Start = OptionInfos + FirstSearchableIndex; + const Info *End = OptionInfos + getNumOptions(); // Search for the first next option which could be a prefix. Start = std::lower_bound(Start, End, Str); @@ -255,8 +210,7 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const { break; // See if this option matches. - options::ID id = (options::ID) (Start - OptionInfos + 1); - if (Arg *A = getOption(id)->accept(Args, Index)) + if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index)) return A; // Otherwise, see if this argument was missing values. @@ -264,6 +218,40 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const { return 0; } - return new PositionalArg(getOption(OPT_UNKNOWN), Index++); + return new PositionalArg(TheUnknownOption, Index++); } +InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd, + unsigned &MissingArgIndex, + unsigned &MissingArgCount) const { + InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); + + // FIXME: Handle '@' args (or at least error on them). + + MissingArgIndex = MissingArgCount = 0; + unsigned Index = 0, End = ArgEnd - ArgBegin; + while (Index < End) { + // Ignore empty arguments (other things may still take them as arguments). + if (Args->getArgString(Index)[0] == '\0') { + ++Index; + continue; + } + + unsigned Prev = Index; + Arg *A = ParseOneArg(*Args, Index); + assert(Index > Prev && "Parser failed to consume argument."); + + // Check for missing argument error. + if (!A) { + assert(Index >= End && "Unexpected parser error."); + assert(Index - Prev - 1 && "No missing arguments!"); + MissingArgIndex = Prev; + MissingArgCount = Index - Prev - 1; + break; + } + + Args->append(A); + } + + return Args; +} diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp index c2ace05..17d00f5 100644 --- a/lib/Driver/Option.cpp +++ b/lib/Driver/Option.cpp @@ -16,9 +16,9 @@ #include <algorithm> using namespace clang::driver; -Option::Option(OptionClass _Kind, options::ID _ID, const char *_Name, +Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name, const OptionGroup *_Group, const Option *_Alias) - : Kind(_Kind), ID(_ID), Name(_Name), Group(_Group), Alias(_Alias), + : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias), Unsupported(false), LinkerInput(false), NoOptAsInput(false), ForceSeparateRender(false), ForceJoinedRender(false), DriverOption(false), NoArgumentUnused(false) { @@ -70,14 +70,13 @@ void Option::dump() const { llvm::errs() << ">\n"; } -bool Option::matches(const Option *Opt) const { - // Aliases are never considered in matching. - if (Opt->getAlias()) - return matches(Opt->getAlias()); +bool Option::matches(OptSpecifier Opt) const { + // Aliases are never considered in matching, look through them. if (Alias) return Alias->matches(Opt); - if (this == Opt) + // Check exact match. + if (ID == Opt) return true; if (Group) @@ -85,23 +84,7 @@ bool Option::matches(const Option *Opt) const { return false; } -bool Option::matches(options::ID Id) const { - // FIXME: Decide what to do here; we should either pull out the - // handling of alias on the option for Id from the other matches, or - // find some other solution (which hopefully doesn't require using - // the option table). - if (Alias) - return Alias->matches(Id); - - if (ID == Id) - return true; - - if (Group) - return Group->matches(Id); - return false; -} - -OptionGroup::OptionGroup(options::ID ID, const char *Name, +OptionGroup::OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group) : Option(Option::GroupClass, ID, Name, Group, 0) { } @@ -111,8 +94,8 @@ Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const { return 0; } -InputOption::InputOption() - : Option(Option::InputClass, options::OPT_INPUT, "<input>", 0, 0) { +InputOption::InputOption(OptSpecifier ID) + : Option(Option::InputClass, ID, "<input>", 0, 0) { } Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const { @@ -120,8 +103,8 @@ Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const { return 0; } -UnknownOption::UnknownOption() - : Option(Option::UnknownClass, options::OPT_UNKNOWN, "<unknown>", 0, 0) { +UnknownOption::UnknownOption(OptSpecifier ID) + : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) { } Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const { @@ -129,7 +112,7 @@ Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const { return 0; } -FlagOption::FlagOption(options::ID ID, const char *Name, +FlagOption::FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::FlagClass, ID, Name, Group, Alias) { } @@ -143,7 +126,7 @@ Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const { return new FlagArg(this, Index++); } -JoinedOption::JoinedOption(options::ID ID, const char *Name, +JoinedOption::JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::JoinedClass, ID, Name, Group, Alias) { } @@ -153,7 +136,7 @@ Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const { return new JoinedArg(this, Index++); } -CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name, +CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) { @@ -170,7 +153,7 @@ Arg *CommaJoinedOption::accept(const InputArgList &Args, return new CommaJoinedArg(this, Index++, Suffix); } -SeparateOption::SeparateOption(options::ID ID, const char *Name, +SeparateOption::SeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::SeparateClass, ID, Name, Group, Alias) { } @@ -188,7 +171,7 @@ Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const { return new SeparateArg(this, Index - 2, 1); } -MultiArgOption::MultiArgOption(options::ID ID, const char *Name, +MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias, unsigned _NumArgs) : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) { @@ -208,7 +191,7 @@ Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const { return new SeparateArg(this, Index - 1 - NumArgs, NumArgs); } -JoinedOrSeparateOption::JoinedOrSeparateOption(options::ID ID, const char *Name, +JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) { @@ -229,7 +212,7 @@ Arg *JoinedOrSeparateOption::accept(const InputArgList &Args, return new SeparateArg(this, Index - 2, 1); } -JoinedAndSeparateOption::JoinedAndSeparateOption(options::ID ID, +JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index ae8119d..af63952 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -14,7 +14,9 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/HostInfo.h" +#include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" +#include "clang/Driver/Options.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -303,9 +305,9 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args, // and try to push it down into tool specific logic. Arg *OSXVersion = - Args.getLastArg(options::OPT_mmacosx_version_min_EQ, false); + Args.getLastArgNoClaim(options::OPT_mmacosx_version_min_EQ); Arg *iPhoneVersion = - Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false); + Args.getLastArgNoClaim(options::OPT_miphoneos_version_min_EQ); if (OSXVersion && iPhoneVersion) { getHost().getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) @@ -365,8 +367,7 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args, // Sob. These is strictly gcc compatible for the time being. Apple // gcc translates options twice, which means that self-expanding // options add duplicates. - options::ID id = A->getOption().getId(); - switch (id) { + switch ((options::ID) A->getOption().getID()) { default: DAL->append(A); break; @@ -440,7 +441,7 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args, if (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64) - if (!Args.hasArg(options::OPT_mtune_EQ, false)) + if (!Args.hasArgNoClaim(options::OPT_mtune_EQ)) DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), "core2")); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 34154f3..5f0551b 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -18,6 +18,7 @@ #include "clang/Driver/Job.h" #include "clang/Driver/HostInfo.h" #include "clang/Driver/Option.h" +#include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" @@ -81,8 +82,8 @@ void Clang::AddPreprocessingOptions(const Driver &D, DepFile = Output.getFilename(); } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(Args); - } else if (A->getOption().getId() == options::OPT_M || - A->getOption().getId() == options::OPT_MM) { + } else if (A->getOption().matches(options::OPT_M) || + A->getOption().matches(options::OPT_MM)) { DepFile = "-"; } else { DepFile = darwin::CC1::getDependencyFileName(Args, Inputs); @@ -116,8 +117,8 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back(DepTarget); } - if (A->getOption().getId() == options::OPT_M || - A->getOption().getId() == options::OPT_MD) + if (A->getOption().matches(options::OPT_M) || + A->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); } @@ -778,12 +779,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; } - if (Args.hasFlag(options::OPT_fmath_errno, + // -fmath-errno is default. + if (!Args.hasFlag(options::OPT_fmath_errno, options::OPT_fno_math_errno, getToolChain().IsMathErrnoDefault())) - CmdArgs.push_back("--fmath-errno=1"); - else - CmdArgs.push_back("--fmath-errno=0"); + CmdArgs.push_back("-fno-math-errno"); if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("--limit-float-precision"); @@ -822,7 +822,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Manually translate -O to -O2 and -O4 to -O3; let clang reject // others. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { - if (A->getOption().getId() == options::OPT_O4) + if (A->getOption().matches(options::OPT_O4)) CmdArgs.push_back("-O3"); else if (A->getValue(Args)[0] == '\0') CmdArgs.push_back("-O2"); @@ -864,7 +864,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - if (Args.hasArg(options::OPT__relocatable_pch, true)) + if (Args.hasArg(options::OPT__relocatable_pch)) CmdArgs.push_back("--relocatable-pch"); if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) { @@ -922,7 +922,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fbuiltin is default. if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) - CmdArgs.push_back("-fbuiltin=0"); + CmdArgs.push_back("-fno-builtin"); // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, @@ -938,7 +938,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frtti is default. if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti)) - CmdArgs.push_back("-frtti=0"); + CmdArgs.push_back("-fno-rtti"); // -fsigned-char is default. if (!Args.hasFlag(options::OPT_fsigned_char, @@ -2609,6 +2609,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // the default system libraries. Just mimic this for now. CmdArgs.push_back("-lgcc"); + if (D.CCCIsCXX) + CmdArgs.push_back("-lstdc++"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-lgcc_eh"); } else { @@ -2638,10 +2640,6 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o"))); - // FIXME: g++ is more complicated here, it tries to put -lstdc++ - // before -lm, for example. - if (D.CCCIsCXX) - CmdArgs.push_back("-lstdc++"); } const char *Exec = diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp index 30893e7..750286b 100644 --- a/lib/Driver/Types.cpp +++ b/lib/Driver/Types.cpp @@ -16,14 +16,14 @@ using namespace clang::driver; using namespace clang::driver::types; -struct Info { +struct TypeInfo { const char *Name; const char *Flags; const char *TempSuffix; ID PreprocessedType; }; -static Info TypeInfos[] = { +static TypeInfo TypeInfos[] = { #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \ { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, }, #include "clang/Driver/Types.def" @@ -31,7 +31,7 @@ static Info TypeInfos[] = { }; static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]); -static Info &getInfo(unsigned id) { +static TypeInfo &getInfo(unsigned id) { assert(id > 0 && id - 1 < numTypes && "Invalid Type ID."); return TypeInfos[id - 1]; } |