diff --git a/clang/include/clang/Driver/Arg.h b/clang/include/clang/Driver/Arg.h index 57d2afe170cf..149f39a74d8e 100644 --- a/clang/include/clang/Driver/Arg.h +++ b/clang/include/clang/Driver/Arg.h @@ -15,8 +15,6 @@ #ifndef CLANG_DRIVER_ARG_H_ #define CLANG_DRIVER_ARG_H_ -#include "clang/Driver/Option.h" - #include "Util.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -25,6 +23,7 @@ namespace clang { namespace driver { class ArgList; + class Option; /// \brief A concrete instance of a particular driver option. /// @@ -39,7 +38,7 @@ namespace driver { private: /// \brief The option this argument is an instance of. - const Option Opt; + const Option *Opt; /// \brief The argument this argument was derived from (during tool chain /// argument translation), if any. @@ -61,14 +60,14 @@ namespace driver { SmallVector Values; public: - Arg(const Option Opt, unsigned Index, const Arg *BaseArg = 0); - Arg(const Option Opt, unsigned Index, + Arg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); + Arg(const Option *Opt, unsigned Index, const char *Value0, const Arg *BaseArg = 0); - Arg(const Option Opt, unsigned Index, + Arg(const Option *Opt, unsigned Index, const char *Value0, const char *Value1, const Arg *BaseArg = 0); ~Arg(); - const Option getOption() const { return Opt; } + const Option &getOption() const { return *Opt; } unsigned getIndex() const { return Index; } /// \brief Return the base argument which generated this arg. diff --git a/clang/include/clang/Driver/ArgList.h b/clang/include/clang/Driver/ArgList.h index 72ed7bf58604..b2570b01dd46 100644 --- a/clang/include/clang/Driver/ArgList.h +++ b/clang/include/clang/Driver/ArgList.h @@ -11,7 +11,6 @@ #define CLANG_DRIVER_ARGLIST_H_ #include "clang/Basic/LLVM.h" -#include "clang/Driver/Option.h" #include "clang/Driver/OptSpecifier.h" #include "clang/Driver/Util.h" #include "llvm/ADT/SmallVector.h" @@ -375,14 +374,14 @@ namespace driver { /// AddFlagArg - Construct a new FlagArg for the given option \p Id and /// append it to the argument list. - void AddFlagArg(const Arg *BaseArg, const Option Opt) { + void AddFlagArg(const Arg *BaseArg, const Option *Opt) { append(MakeFlagArg(BaseArg, Opt)); } /// AddPositionalArg - Construct a new Positional arg for the given option /// \p Id, with the provided \p Value and append it to the argument /// list. - void AddPositionalArg(const Arg *BaseArg, const Option Opt, + void AddPositionalArg(const Arg *BaseArg, const Option *Opt, StringRef Value) { append(MakePositionalArg(BaseArg, Opt, Value)); } @@ -391,7 +390,7 @@ namespace driver { /// AddSeparateArg - Construct a new Positional arg for the given option /// \p Id, with the provided \p Value and append it to the argument /// list. - void AddSeparateArg(const Arg *BaseArg, const Option Opt, + void AddSeparateArg(const Arg *BaseArg, const Option *Opt, StringRef Value) { append(MakeSeparateArg(BaseArg, Opt, Value)); } @@ -399,28 +398,28 @@ namespace driver { /// AddJoinedArg - Construct a new Positional arg for the given option /// \p Id, with the provided \p Value and append it to the argument list. - void AddJoinedArg(const Arg *BaseArg, const Option Opt, + void AddJoinedArg(const Arg *BaseArg, const Option *Opt, StringRef Value) { append(MakeJoinedArg(BaseArg, Opt, Value)); } /// MakeFlagArg - Construct a new FlagArg for the given option \p Id. - Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const; + Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const; /// MakePositionalArg - Construct a new Positional arg for the /// given option \p Id, with the provided \p Value. - Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt, + Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt, StringRef Value) const; /// MakeSeparateArg - Construct a new Positional arg for the /// given option \p Id, with the provided \p Value. - Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt, + Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt, StringRef Value) const; /// MakeJoinedArg - Construct a new Positional arg for the /// given option \p Id, with the provided \p Value. - Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt, + Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt, StringRef Value) const; /// @} diff --git a/clang/include/clang/Driver/OptTable.h b/clang/include/clang/Driver/OptTable.h index 678d9676595d..ea7e57b12be1 100644 --- a/clang/include/clang/Driver/OptTable.h +++ b/clang/include/clang/Driver/OptTable.h @@ -47,6 +47,15 @@ namespace driver { const Info *OptionInfos; unsigned NumOptionInfos; + /// \brief The lazily constructed options table, indexed by option::ID - 1. + mutable Option **Options; + + /// \brief Prebound input option instance. + const Option *TheInputOption; + + /// \brief Prebound unknown option instance. + const Option *TheUnknownOption; + /// The index of the first option which can be parsed (i.e., is not a /// special option like 'input' or 'unknown', and is not an option group). unsigned FirstSearchableIndex; @@ -58,6 +67,8 @@ namespace driver { return OptionInfos[id - 1]; } + Option *CreateOption(unsigned id) const; + protected: OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos); public: @@ -70,7 +81,17 @@ namespace driver { /// if necessary. /// /// \return The option, or null for the INVALID option id. - const Option getOption(OptSpecifier Opt) const; + const Option *getOption(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + if (id == 0) + return 0; + + assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); + Option *&Entry = Options[id - 1]; + if (!Entry) + Entry = CreateOption(id); + return Entry; + } /// \brief Lookup the name of the given option. const char *getOptionName(OptSpecifier id) const { diff --git a/clang/include/clang/Driver/Option.h b/clang/include/clang/Driver/Option.h index dc69fa230001..6fc8bef5daaa 100644 --- a/clang/include/clang/Driver/Option.h +++ b/clang/include/clang/Driver/Option.h @@ -76,15 +76,11 @@ namespace options { Option(const OptTable::Info *Info, const OptTable *Owner); ~Option(); - bool isValid() const { - return Info != 0; - } - unsigned getID() const { return Info->ID; } OptionClass getKind() const { return OptionClass(Info->Kind); } StringRef getName() const { return Info->Name; } - const Option getGroup() const { return Owner->getOption(Info->GroupID); } - const Option getAlias() const { return Owner->getOption(Info->AliasID); } + const Option *getGroup() const { return Owner->getOption(Info->GroupID); } + const Option *getAlias() const { return Owner->getOption(Info->AliasID); } unsigned getNumArgs() const { return Info->Param; } @@ -134,16 +130,16 @@ namespace options { /// getUnaliasedOption - Return the final option this option /// aliases (itself, if the option has no alias). - const Option getUnaliasedOption() const { - const Option Alias = getAlias(); - if (Alias.isValid()) return Alias.getUnaliasedOption(); - return *this; + const Option *getUnaliasedOption() const { + const Option *Alias = getAlias(); + if (Alias) return Alias->getUnaliasedOption(); + return this; } /// getRenderName - Return the name to use when rendering this /// option. StringRef getRenderName() const { - return getUnaliasedOption().getName(); + return getUnaliasedOption()->getName(); } /// matches - Predicate for whether this option is part of the diff --git a/clang/lib/Driver/Arg.cpp b/clang/lib/Driver/Arg.cpp index b156d7cf7146..c0a2a506a6ba 100644 --- a/clang/lib/Driver/Arg.cpp +++ b/clang/lib/Driver/Arg.cpp @@ -16,19 +16,19 @@ using namespace clang::driver; -Arg::Arg(const Option _Opt, unsigned _Index, const Arg *_BaseArg) +Arg::Arg(const Option *_Opt, unsigned _Index, const Arg *_BaseArg) : Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false), OwnsValues(false) { } -Arg::Arg(const Option _Opt, unsigned _Index, +Arg::Arg(const Option *_Opt, unsigned _Index, const char *Value0, const Arg *_BaseArg) : Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false), OwnsValues(false) { Values.push_back(Value0); } -Arg::Arg(const Option _Opt, unsigned _Index, +Arg::Arg(const Option *_Opt, unsigned _Index, const char *Value0, const char *Value1, const Arg *_BaseArg) : Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false), OwnsValues(false) { @@ -47,7 +47,7 @@ void Arg::dump() const { llvm::errs() << "<"; llvm::errs() << " Opt:"; - Opt.dump(); + Opt->dump(); llvm::errs() << " Index:" << Index; @@ -104,7 +104,7 @@ void Arg::render(const ArgList &Args, ArgStringList &Output) const { Output.push_back(Args.MakeArgString(OS.str())); break; } - + case Option::RenderJoinedStyle: Output.push_back(Args.GetOrMakeJoinedArgString( getIndex(), getOption().getName(), getValue(Args, 0))); diff --git a/clang/lib/Driver/ArgList.cpp b/clang/lib/Driver/ArgList.cpp index 3b824f7c8190..7fd439e63082 100644 --- a/clang/lib/Driver/ArgList.cpp +++ b/clang/lib/Driver/ArgList.cpp @@ -362,13 +362,13 @@ 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, 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); @@ -376,19 +376,19 @@ Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt, 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); + unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value); Arg *A = new Arg(Opt, 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()); + unsigned Index = BaseArgs.MakeIndex(Opt->getName().str() + Value.str()); Arg *A = new Arg(Opt, Index, - BaseArgs.getArgString(Index) + Opt.getName().size(), + BaseArgs.getArgString(Index) + Opt->getName().size(), BaseArg); SynthesizedArgs.push_back(A); return A; diff --git a/clang/lib/Driver/OptTable.cpp b/clang/lib/Driver/OptTable.cpp index 433c3869b5ce..e108106fa7e9 100644 --- a/clang/lib/Driver/OptTable.cpp +++ b/clang/lib/Driver/OptTable.cpp @@ -11,7 +11,6 @@ #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 @@ -80,16 +79,22 @@ OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos), - FirstSearchableIndex(0) + 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) * 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); } else if (Kind == Option::UnknownClass) { + assert(!TheUnknownOption && "Cannot have multiple input options!"); + TheUnknownOption = getOption(i + 1); } else if (Kind != Option::GroupClass) { FirstSearchableIndex = i; break; @@ -110,8 +115,8 @@ 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!"); } } @@ -119,27 +124,26 @@ OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) } OptTable::~OptTable() { -} - -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); + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + delete Options[i]; + delete[] Options; } bool OptTable::isOptionHelpHidden(OptSpecifier id) const { return getInfo(id).Flags & options::HelpHidden; } +Option *OptTable::CreateOption(unsigned id) const { + return new Option(&getInfo(id), this); +} + 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(getOption(options::OPT_INPUT), Index++, Str); + return new Arg(TheInputOption, Index++, Str); const Info *Start = OptionInfos + FirstSearchableIndex; const Info *End = OptionInfos + getNumOptions(); @@ -165,7 +169,7 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { break; // See if this option matches. - if (Arg *A = getOption(Start - OptionInfos + 1).accept(Args, Index)) + if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index)) return A; // Otherwise, see if this argument was missing values. @@ -173,7 +177,7 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { return 0; } - return new Arg(getOption(options::OPT_UNKNOWN), Index++, Str); + return new Arg(TheUnknownOption, Index++, Str); } InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, diff --git a/clang/lib/Driver/Option.cpp b/clang/lib/Driver/Option.cpp index a250d8740a97..117021b880ce 100644 --- a/clang/lib/Driver/Option.cpp +++ b/clang/lib/Driver/Option.cpp @@ -23,8 +23,7 @@ Option::Option(const OptTable::Info *info, const OptTable *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((!getAlias().isValid() || (!getAlias().getAlias().isValid() && - !getGroup().isValid())) && + assert((!getAlias() || (!getAlias()->getAlias() && !getGroup())) && "Multi-level aliases and aliases with groups are unsupported."); } @@ -50,16 +49,16 @@ void Option::dump() const { llvm::errs() << " Name:\"" << getName() << '"'; - const Option Group = getGroup(); - if (Group.isValid()) { + const Option *Group = getGroup(); + if (Group) { llvm::errs() << " Group:"; - Group.dump(); + Group->dump(); } - const Option Alias = getAlias(); - if (Alias.isValid()) { + const Option *Alias = getAlias(); + if (Alias) { llvm::errs() << " Alias:"; - Alias.dump(); + Alias->dump(); } if (getKind() == MultiArgClass) @@ -70,17 +69,17 @@ void Option::dump() const { bool Option::matches(OptSpecifier Opt) const { // Aliases are never considered in matching, look through them. - const Option Alias = getAlias(); - if (Alias.isValid()) - return Alias.matches(Opt); + const Option *Alias = getAlias(); + if (Alias) + return Alias->matches(Opt); // Check exact match. if (getID() == Opt.getID()) return true; - const Option Group = getGroup(); - if (Group.isValid()) - return Group.matches(Opt); + const Option *Group = getGroup(); + if (Group) + return Group->matches(Opt); return false; } @@ -156,7 +155,7 @@ Arg *Option::accept(const ArgList &Args, unsigned &Index) const { // 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 new Arg(this, Index++, Value); } // Otherwise it must be separate. diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index de18f53fbe0e..529f7bff48b6 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -485,7 +485,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } // 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); + const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); OSXVersion = Args.MakeJoinedArg(0, O, "10.6"); Args.append(OSXVersion); break; @@ -559,21 +559,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); } @@ -835,8 +835,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.