X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FCommandLine.h;h=c6d430115427e38ff9dd6f8284a3e82ddb2935e4;hp=3ee2313b9a3dca49f2e6b474133642247fc9959d;hb=9cc5055248bdde9e0f61dfa818bfd0be7a347afd;hpb=47afe4e806eb16dd3d90670adf3ea5f9bca72132 diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 3ee2313b9a3..c6d43011542 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,10 +20,11 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H -#include "llvm/Support/type_traits.h" -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" #include #include #include @@ -31,7 +32,7 @@ #include namespace llvm { - + /// cl Namespace - This namespace contains all of the command line option /// processing machinery. It is intentionally a short name to make qualified /// usage concise. @@ -40,17 +41,15 @@ namespace cl { //===----------------------------------------------------------------------===// // ParseCommandLineOptions - Command line option processing entry point. // -void ParseCommandLineOptions(int argc, char **argv, - const char *Overview = 0, - bool ReadResponseFiles = false); +void ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview = nullptr); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate // entry point. // void ParseEnvironmentOptions(const char *progName, const char *envvar, - const char *Overview = 0, - bool ReadResponseFiles = false); + const char *Overview = nullptr); ///===---------------------------------------------------------------------===// /// SetVersionPrinter - Override the default (LLVM specific) version printer @@ -59,19 +58,42 @@ void ParseEnvironmentOptions(const char *progName, const char *envvar, /// CommandLine utilities to print their own version string. void SetVersionPrinter(void (*func)()); - -// MarkOptionsChanged - Internal helper function. -void MarkOptionsChanged(); +///===---------------------------------------------------------------------===// +/// AddExtraVersionPrinter - Add an extra printer to use in addition to the +/// default one. This can be called multiple times, +/// and each time it adds a new function to the list +/// which will be called after the basic LLVM version +/// printing is complete. Each can then add additional +/// information specific to the tool. +void AddExtraVersionPrinter(void (*func)()); + +// PrintOptionValues - Print option values. +// With -print-options print the difference between option values and defaults. +// With -print-all-options print all option values. +// (Currently not perfect, but best-effort.) +void PrintOptionValues(); + +// Forward declaration - AddLiteralOption needs to be up here to make gcc happy. +class Option; + +/// \brief Adds a new option for parsing and provides the option it refers to. +/// +/// \param O pointer to the option +/// \param Name the string name for the option to handle during parsing +/// +/// Literal options are used by some parsers to register special option values. +/// This is how the PassNameParser registers pass names for opt. +void AddLiteralOption(Option &O, const char *Name); //===----------------------------------------------------------------------===// // Flags permitted to be passed to command line arguments // -enum NumOccurrencesFlag { // Flags for the number of occurrences allowed - Optional = 0x01, // Zero or One occurrence - ZeroOrMore = 0x02, // Zero or more occurrences allowed - Required = 0x03, // One occurrence required - OneOrMore = 0x04, // One or more occurrences required +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x00, // Zero or One occurrence + ZeroOrMore = 0x01, // Zero or more occurrences allowed + Required = 0x02, // One occurrence required + OneOrMore = 0x03, // One or more occurrences required // ConsumeAfter - Indicates that this option is fed anything that follows the // last positional argument required by the application (it is an error if @@ -80,23 +102,20 @@ enum NumOccurrencesFlag { // Flags for the number of occurrences allowed // found. Once a filename is found, all of the succeeding arguments are // passed, unprocessed, to the ConsumeAfter option. // - ConsumeAfter = 0x05, - - OccurrencesMask = 0x07 + ConsumeAfter = 0x04 }; -enum ValueExpected { // Is a value required for the option? - ValueOptional = 0x08, // The value can appear... or not - ValueRequired = 0x10, // The value is required to appear! - ValueDisallowed = 0x18, // A value may not be specified (for flags) - ValueMask = 0x18 +enum ValueExpected { // Is a value required for the option? + // zero reserved for the unspecified value + ValueOptional = 0x01, // The value can appear... or not + ValueRequired = 0x02, // The value is required to appear! + ValueDisallowed = 0x03 // A value may not be specified (for flags) }; -enum OptionHidden { // Control whether -help shows this option - NotHidden = 0x20, // Option included in --help & --help-hidden - Hidden = 0x40, // -help doesn't, but --help-hidden does - ReallyHidden = 0x60, // Neither --help nor --help-hidden show this arg - HiddenMask = 0x60 +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x00, // Option included in -help & -help-hidden + Hidden = 0x01, // -help doesn't, but -help-hidden does + ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg }; // Formatting flags - This controls special features that the option might have @@ -115,21 +134,39 @@ enum OptionHidden { // Control whether -help shows this option // enum FormattingFlags { - NormalFormatting = 0x000, // Nothing special - Positional = 0x080, // Is a positional argument, no '-' required - Prefix = 0x100, // Can this option directly prefix its value? - Grouping = 0x180, // Can this option group with other options? - FormattingMask = 0x180 // Union of the above flags. + NormalFormatting = 0x00, // Nothing special + Positional = 0x01, // Is a positional argument, no '-' required + Prefix = 0x02, // Can this option directly prefix its value? + Grouping = 0x03 // Can this option group with other options? }; -enum MiscFlags { // Miscellaneous flags to adjust argument - CommaSeparated = 0x200, // Should this cl::list split between commas? - PositionalEatsArgs = 0x400, // Should this positional cl::list eat -args? - Sink = 0x800, // Should this cl::list eat all unknown options? - MiscMask = 0xE00 // Union of the above flags. +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x01, // Should this cl::list split between commas? + PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? + Sink = 0x04 // Should this cl::list eat all unknown options? }; +//===----------------------------------------------------------------------===// +// Option Category class +// +class OptionCategory { +private: + const char *const Name; + const char *const Description; + void registerCategory(); +public: + OptionCategory(const char *const Name, + const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerCategory(); + } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } +}; + +// The general Option Category (used as default category). +extern OptionCategory GeneralCategory; //===----------------------------------------------------------------------===// // Option Base class @@ -152,33 +189,39 @@ class Option { // Out of line virtual function to provide home for the class. virtual void anchor(); - int NumOccurrences; // The number of times specified - int Flags; // Flags for the argument - unsigned Position; // Position of last occurrence of the option - unsigned AdditionalVals;// Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. + int NumOccurrences; // The number of times specified + // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid + // problems with signed enums in bitfields. + unsigned Occurrences : 3; // enum NumOccurrencesFlag + // not using the enum type for 'Value' because zero is an implementation + // detail representing the non-value + unsigned Value : 2; + unsigned HiddenFlag : 2; // enum OptionHidden + unsigned Formatting : 2; // enum FormattingFlags + unsigned Misc : 3; + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals; // Greater than 0 for multi-valued option. + public: - const char *ArgStr; // The argument string itself (ex: "help", "o") - const char *HelpStr; // The descriptive text message for --help - const char *ValueStr; // String describing what the value of this option is + const char *ArgStr; // The argument string itself (ex: "help", "o") + const char *HelpStr; // The descriptive text message for -help + const char *ValueStr; // String describing what the value of this option is + OptionCategory *Category; // The Category this option belongs to + bool FullyInitialized; // Has addArguemnt been called? inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { - return static_cast(Flags & OccurrencesMask); + return (enum NumOccurrencesFlag)Occurrences; } inline enum ValueExpected getValueExpectedFlag() const { - int VE = Flags & ValueMask; - return VE ? static_cast(VE) - : getValueExpectedFlagDefault(); + return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault(); } inline enum OptionHidden getOptionHiddenFlag() const { - return static_cast(Flags & HiddenMask); + return (enum OptionHidden)HiddenFlag; } inline enum FormattingFlags getFormattingFlag() const { - return static_cast(Flags & FormattingMask); - } - inline unsigned getMiscFlags() const { - return Flags & MiscMask; + return (enum FormattingFlags)Formatting; } + inline unsigned getMiscFlags() const { return Misc; } inline unsigned getPosition() const { return Position; } inline unsigned getNumAdditionalVals() const { return AdditionalVals; } @@ -188,39 +231,37 @@ public: //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers // - void setArgStr(const char *S) { ArgStr = S; } + void setArgStr(const char *S); void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } - - void setFlag(unsigned Flag, unsigned FlagMask) { - Flags &= ~FlagMask; - Flags |= Flag; - } - - void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { - setFlag(Val, OccurrencesMask); - } - void setValueExpectedFlag(enum ValueExpected Val) { setFlag(Val, ValueMask); } - void setHiddenFlag(enum OptionHidden Val) { setFlag(Val, HiddenMask); } - void setFormattingFlag(enum FormattingFlags V) { setFlag(V, FormattingMask); } - void setMiscFlag(enum MiscFlags M) { setFlag(M, M); } + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } + void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; } + void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; } + void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } + void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } + void setCategory(OptionCategory &C) { Category = &C; } + protected: - explicit Option(unsigned DefaultFlags) - : NumOccurrences(0), Flags(DefaultFlags | NormalFormatting), Position(0), - AdditionalVals(0), NextRegistered(0), - ArgStr(""), HelpStr(""), ValueStr("") { - assert(getNumOccurrencesFlag() != 0 && - getOptionHiddenFlag() != 0 && "Not all default flags specified!"); - } + explicit Option(enum NumOccurrencesFlag OccurrencesFlag, + enum OptionHidden Hidden) + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), + AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), + Category(&GeneralCategory), FullyInitialized(false) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } + public: // addArgument - Register this argument with the commandline system. // void addArgument(); - Option *getNextRegisteredOption() const { return NextRegistered; } + /// Unregisters this option from the CommandLine system. + /// + /// This option must have been the last option registered. + /// For testing purposes only. + void removeArgument(); // Return the width of the option tag for printing... virtual size_t getOptionWidth() const = 0; @@ -230,12 +271,14 @@ public: // virtual void printOptionInfo(size_t GlobalWidth) const = 0; - virtual void getExtraOptionNames(SmallVectorImpl &) {} + virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; + + virtual void getExtraOptionNames(SmallVectorImpl &) {} // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -245,20 +288,19 @@ public: virtual ~Option() {} }; - //===----------------------------------------------------------------------===// // Command line option modifiers that can be used to modify the behavior of // command line option parsers... // -// desc - Modifier to set the description shown in the --help output... +// desc - Modifier to set the description shown in the -help output... struct desc { const char *Desc; desc(const char *Str) : Desc(Str) {} void apply(Option &O) const { O.setDescription(Desc); } }; -// value_desc - Modifier to set the value description shown in the --help +// value_desc - Modifier to set the value description shown in the -help // output... struct value_desc { const char *Desc; @@ -270,57 +312,200 @@ struct value_desc { // the default constructor for the argument type does not give you what you // want. This is only valid on "opt" arguments, not on "list" arguments. // -template -struct initializer { +template struct initializer { const Ty &Init; initializer(const Ty &Val) : Init(Val) {} - template - void apply(Opt &O) const { O.setInitialValue(Init); } + template void apply(Opt &O) const { O.setInitialValue(Init); } }; -template -initializer init(const Ty &Val) { +template initializer init(const Ty &Val) { return initializer(Val); } - // location - Allow the user to specify which external variable they want to // store the results of the command line argument processing into, if they don't // want to store it in the option itself. // -template -struct LocationClass { +template struct LocationClass { Ty &Loc; LocationClass(Ty &L) : Loc(L) {} - template - void apply(Opt &O) const { O.setLocation(O, Loc); } + template void apply(Opt &O) const { O.setLocation(O, Loc); } +}; + +template LocationClass location(Ty &L) { + return LocationClass(L); +} + +// cat - Specifiy the Option category for the command line argument to belong +// to. +struct cat { + OptionCategory &Category; + cat(OptionCategory &c) : Category(c) {} + + template void apply(Opt &O) const { O.setCategory(Category); } +}; + +//===----------------------------------------------------------------------===// +// OptionValue class + +// Support value comparison outside the template. +struct GenericOptionValue { + virtual bool compare(const GenericOptionValue &V) const = 0; + +protected: + ~GenericOptionValue() = default; + GenericOptionValue() = default; + GenericOptionValue(const GenericOptionValue&) = default; + GenericOptionValue &operator=(const GenericOptionValue &) = default; + +private: + virtual void anchor(); +}; + +template struct OptionValue; + +// The default value safely does nothing. Option value printing is only +// best-effort. +template +struct OptionValueBase : public GenericOptionValue { + // Temporary storage for argument passing. + typedef OptionValue WrapperType; + + bool hasValue() const { return false; } + + const DataType &getValue() const { llvm_unreachable("no default value"); } + + // Some options may take their value from a different data type. + template void setValue(const DT & /*V*/) {} + + bool compare(const DataType & /*V*/) const { return false; } + + bool compare(const GenericOptionValue & /*V*/) const override { + return false; + } + +protected: + ~OptionValueBase() = default; +}; + +// Simple copy of the option value. +template class OptionValueCopy : public GenericOptionValue { + DataType Value; + bool Valid; + +protected: + ~OptionValueCopy() = default; + OptionValueCopy(const OptionValueCopy&) = default; + OptionValueCopy &operator=(const OptionValueCopy&) = default; + +public: + OptionValueCopy() : Valid(false) {} + + bool hasValue() const { return Valid; } + + const DataType &getValue() const { + assert(Valid && "invalid option value"); + return Value; + } + + void setValue(const DataType &V) { + Valid = true; + Value = V; + } + + bool compare(const DataType &V) const { return Valid && (Value != V); } + + bool compare(const GenericOptionValue &V) const override { + const OptionValueCopy &VC = + static_cast &>(V); + if (!VC.hasValue()) + return false; + return compare(VC.getValue()); + } +}; + +// Non-class option values. +template +struct OptionValueBase : OptionValueCopy { + typedef DataType WrapperType; + +protected: + ~OptionValueBase() = default; + OptionValueBase() = default; + OptionValueBase(const OptionValueBase&) = default; + OptionValueBase &operator=(const OptionValueBase&) = default; +}; + +// Top-level option class. +template +struct OptionValue final + : OptionValueBase::value> { + OptionValue() = default; + + OptionValue(const DataType &V) { this->setValue(V); } + // Some options may take their value from a different data type. + template OptionValue &operator=(const DT &V) { + this->setValue(V); + return *this; + } +}; + +// Other safe-to-copy-by-value common option types. +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template <> +struct OptionValue final + : OptionValueCopy { + typedef cl::boolOrDefault WrapperType; + + OptionValue() {} + + OptionValue(const cl::boolOrDefault &V) { this->setValue(V); } + OptionValue &operator=(const cl::boolOrDefault &V) { + setValue(V); + return *this; + } + +private: + void anchor() override; }; -template -LocationClass location(Ty &L) { return LocationClass(L); } +template <> +struct OptionValue final : OptionValueCopy { + typedef StringRef WrapperType; + + OptionValue() {} + OptionValue(const std::string &V) { this->setValue(V); } + OptionValue &operator=(const std::string &V) { + setValue(V); + return *this; + } + +private: + void anchor() override; +}; //===----------------------------------------------------------------------===// // Enum valued command line option // #define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC #define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC -#define clEnumValEnd (reinterpret_cast(0)) +#define clEnumValEnd (reinterpret_cast(0)) // values - For custom data types, allow specifying a group of values together // as the values that go into the mapping that the option handler uses. Note // that the values list must always have a 0 at the end of the list to indicate // that the list has ended. // -template -class ValuesClass { +template class ValuesClass { // Use a vector instead of a map, because the lists should be short, // the overhead is less, and most importantly, it keeps them in the order // inserted so we can print our option out nicely. - SmallVector >,4> Values; + SmallVector>, 4> Values; void processValues(va_list Vals); + public: ValuesClass(const char *EnumName, DataType Val, const char *Desc, va_list ValueArgs) { @@ -331,31 +516,28 @@ public: while (const char *enumName = va_arg(ValueArgs, const char *)) { DataType EnumVal = static_cast(va_arg(ValueArgs, int)); const char *EnumDesc = va_arg(ValueArgs, const char *); - Values.push_back(std::make_pair(enumName, // Add value to value map + Values.push_back(std::make_pair(enumName, // Add value to value map std::make_pair(EnumVal, EnumDesc))); } } - template - void apply(Opt &O) const { - for (unsigned i = 0, e = static_cast(Values.size()); - i != e; ++i) + template void apply(Opt &O) const { + for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); } }; -template -ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, - const char *Desc, ...) { - va_list ValueArgs; - va_start(ValueArgs, Desc); - ValuesClass Vals(Arg, Val, Desc, ValueArgs); - va_end(ValueArgs); - return Vals; +template +ValuesClass LLVM_END_WITH_NULL +values(const char *Arg, DataType Val, const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; } - //===----------------------------------------------------------------------===// // parser class - Parameterizable parser for different data types. By default, // known data types (string, int, bool) have specialized parsers, that do what @@ -368,8 +550,20 @@ ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, // not need replicated for every instance of the generic parser. This also // allows us to put stuff into CommandLine.cpp // -struct generic_parser_base { - virtual ~generic_parser_base() {} // Base class should have virtual-dtor +class generic_parser_base { +protected: + class GenericOptionInfo { + public: + GenericOptionInfo(const char *name, const char *helpStr) + : Name(name), HelpStr(helpStr) {} + const char *Name; + const char *HelpStr; + }; + +public: + generic_parser_base(Option &O) : Owner(O) {} + + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to // indicate how many entries are in Values. @@ -385,28 +579,39 @@ struct generic_parser_base { // Return the width of the option tag for printing... virtual size_t getOptionWidth(const Option &O) const; + virtual const GenericOptionValue &getOptionValue(unsigned N) const = 0; + // printOptionInfo - Print out information about this option. The // to-be-maintained width is specified. // virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const; - void initialize(Option &O) { - // All of the modifiers for the option have been processed by now, so the - // argstr field should be stable, copy it down now. - // - hasArgStr = O.hasArgStr(); + void printGenericOptionDiff(const Option &O, const GenericOptionValue &V, + const GenericOptionValue &Default, + size_t GlobalWidth) const; + + // printOptionDiff - print the value of an option and it's default. + // + // Template definition ensures that the option and default have the same + // DataType (via the same AnyOptionValue). + template + void printOptionDiff(const Option &O, const AnyOptionValue &V, + const AnyOptionValue &Default, + size_t GlobalWidth) const { + printGenericOptionDiff(O, V, Default, GlobalWidth); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void initialize() {} + + void getExtraOptionNames(SmallVectorImpl &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. - if (!hasArgStr) + if (!Owner.hasArgStr()) for (unsigned i = 0, e = getNumOptions(); i != e; ++i) OptionNames.push_back(getOption(i)); } - enum ValueExpected getValueExpectedFlagDefault() const { // If there is an ArgStr specified, then we are of the form: // @@ -419,7 +624,7 @@ struct generic_parser_base { // // If this is the case, we cannot allow a value. // - if (hasArgStr) + if (Owner.hasArgStr()) return ValueRequired; else return ValueDisallowed; @@ -431,42 +636,52 @@ struct generic_parser_base { unsigned findOption(const char *Name); protected: - bool hasArgStr; + Option &Owner; }; // Default parser implementation - This implementation depends on having a // mapping of recognized options to values of some sort. In addition to this, // each entry in the mapping also tracks a help message that is printed with the -// command line option for --help. Because this is a simple mapping parser, the +// command line option for -help. Because this is a simple mapping parser, the // data type can be any unsupported type. // -template -class parser : public generic_parser_base { +template class parser : public generic_parser_base { protected: - SmallVector >, 8> Values; + class OptionInfo : public GenericOptionInfo { + public: + OptionInfo(const char *name, DataType v, const char *helpStr) + : GenericOptionInfo(name, helpStr), V(v) {} + OptionValue V; + }; + SmallVector Values; + public: + parser(Option &O) : generic_parser_base(O) {} typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base - unsigned getNumOptions() const { return unsigned(Values.size()); } - const char *getOption(unsigned N) const { return Values[N].first; } - const char *getDescription(unsigned N) const { - return Values[N].second.second; + unsigned getNumOptions() const override { return unsigned(Values.size()); } + const char *getOption(unsigned N) const override { return Values[N].Name; } + const char *getDescription(unsigned N) const override { + return Values[N].HelpStr; + } + + // getOptionValue - Return the value of option name N. + const GenericOptionValue &getOptionValue(unsigned N) const override { + return Values[N].V; } // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { StringRef ArgVal; - if (hasArgStr) + if (Owner.hasArgStr()) ArgVal = Arg; else ArgVal = ArgName; - for (unsigned i = 0, e = static_cast(Values.size()); - i != e; ++i) - if (Values[i].first == ArgVal) { - V = Values[i].second.first; + for (size_t i = 0, e = Values.size(); i != e; ++i) + if (Values[i].Name == ArgVal) { + V = Values[i].V.getValue(); return false; } @@ -478,9 +693,9 @@ public: template void addLiteralOption(const char *Name, const DT &V, const char *HelpStr) { assert(findOption(Name) == Values.size() && "Option already exists!"); - Values.push_back(std::make_pair(Name, - std::make_pair(static_cast(V),HelpStr))); - MarkOptionsChanged(); + OptionInfo X(Name, static_cast(V), HelpStr); + Values.push_back(X); + AddLiteralOption(Owner, Name); } /// removeLiteralOption - Remove the specified option. @@ -488,24 +703,25 @@ public: void removeLiteralOption(const char *Name) { unsigned N = findOption(Name); assert(N != Values.size() && "Option not found!"); - Values.erase(Values.begin()+N); + Values.erase(Values.begin() + N); } }; //-------------------------------------------------- // basic_parser - Super class of parsers to provide boilerplate code // -class basic_parser_impl { // non-template implementation of basic_parser +class basic_parser_impl { // non-template implementation of basic_parser public: - virtual ~basic_parser_impl() {} + basic_parser_impl(Option &O) {} + enum ValueExpected getValueExpectedFlagDefault() const { return ValueRequired; } - void getExtraOptionNames(SmallVectorImpl &) {} + void getExtraOptionNames(SmallVectorImpl &) {} - void initialize(Option &) {} + void initialize() {} // Return the width of the option tag for printing... size_t getOptionWidth(const Option &O) const; @@ -515,57 +731,71 @@ public: // void printOptionInfo(const Option &O, size_t GlobalWidth) const; + // printOptionNoValue - Print a placeholder for options that don't yet support + // printOptionDiff(). + void printOptionNoValue(const Option &O, size_t GlobalWidth) const; + // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "value"; } // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); + +protected: + ~basic_parser_impl() = default; + // A helper for basic_parser::printOptionDiff. + void printOptionName(const Option &O, size_t GlobalWidth) const; }; // basic_parser - The real basic parser is just a template wrapper that provides // a typedef for the provided data type. // -template -class basic_parser : public basic_parser_impl { +template class basic_parser : public basic_parser_impl { public: + basic_parser(Option &O) : basic_parser_impl(O) {} typedef DataType parser_data_type; + typedef OptionValue OptVal; + +protected: + // Workaround Clang PR22793 + ~basic_parser() {} }; //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { - const char *ArgStr; +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template - void initialize(Opt &O) { - ArgStr = O.ArgStr; - } + void initialize() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; } // getValueName - Do not print = at all. - virtual const char *getValueName() const { return 0; } + const char *getValueName() const override { return nullptr; } + + void printOptionDiff(const Option &O, bool V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser -enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; -template<> -class parser : public basic_parser { +template <> +class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -574,10 +804,13 @@ public: } // getValueName - Do not print = at all. - virtual const char *getValueName() const { return 0; } + const char *getValueName() const override { return nullptr; } + + void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); @@ -585,54 +818,90 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "int"; } + const char *getValueName() const override { return "int"; } + + void printOptionDiff(const Option &O, int V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); - //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "uint"; } + const char *getValueName() const override { return "uint"; } + + void printOptionDiff(const Option &O, unsigned V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +//-------------------------------------------------- +// parser +// +template <> +class parser final + : public basic_parser { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, + unsigned long long &Val); + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "uint"; } + + void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "number"; } + const char *getValueName() const override { return "number"; } + + void printOptionDiff(const Option &O, double V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); @@ -640,17 +909,21 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "number"; } + const char *getValueName() const override { return "number"; } + + void printOptionDiff(const Option &O, float V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); @@ -658,9 +931,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { Value = Arg.str(); @@ -668,10 +942,13 @@ public: } // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "string"; } + const char *getValueName() const override { return "string"; } + + void printOptionDiff(const Option &O, StringRef V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); @@ -679,9 +956,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser final : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { Value = Arg[0]; @@ -689,63 +967,117 @@ public: } // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "char"; } + const char *getValueName() const override { return "char"; } + + void printOptionDiff(const Option &O, char V, OptVal Default, + size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +//-------------------------------------------------- +// PrintOptionDiff +// +// This collection of wrappers is the intermediary between class opt and class +// parser to handle all the template nastiness. + +// This overloaded function is selected by the generic parser. +template +void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, + const OptionValue
&Default, size_t GlobalWidth) { + OptionValue
OV = V; + P.printOptionDiff(O, OV, Default, GlobalWidth); +} + +// This is instantiated for basic parsers when the parsed value has a different +// type than the option value. e.g. HelpPrinter. +template struct OptionDiffPrinter { + void print(const Option &O, const parser &P, const ValDT & /*V*/, + const OptionValue & /*Default*/, size_t GlobalWidth) { + P.printOptionNoValue(O, GlobalWidth); + } +}; + +// This is instantiated for basic parsers when the parsed value has the same +// type as the option value. +template struct OptionDiffPrinter { + void print(const Option &O, const parser
&P, const DT &V, + const OptionValue
&Default, size_t GlobalWidth) { + P.printOptionDiff(O, V, Default, GlobalWidth); + } +}; + +// This overloaded function is selected by the basic parser, which may parse a +// different type than the option type. +template +void printOptionDiff( + const Option &O, + const basic_parser &P, + const ValDT &V, const OptionValue &Default, size_t GlobalWidth) { + + OptionDiffPrinter printer; + printer.print(O, static_cast(P), V, Default, + GlobalWidth); +} + //===----------------------------------------------------------------------===// // applicator class - This class is used because we must use partial // specialization to handle literal string arguments specially (const char* does // not correctly respond to the apply method). Because the syntax to use this // is a pain, we have the 'apply' method below to handle the nastiness... // -template struct applicator { - template - static void opt(const Mod &M, Opt &O) { M.apply(O); } +template struct applicator { + template static void opt(const Mod &M, Opt &O) { M.apply(O); } }; // Handle const char* as a special case... -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <> struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { - static void opt(NumOccurrencesFlag NO, Option &O) { - O.setNumOccurrencesFlag(NO); +template <> struct applicator { + static void opt(NumOccurrencesFlag N, Option &O) { + O.setNumOccurrencesFlag(N); } }; -template<> struct applicator { +template <> struct applicator { static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } }; -template<> struct applicator { +template <> struct applicator { static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } }; -template<> struct applicator { +template <> struct applicator { static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } }; -template<> struct applicator { +template <> struct applicator { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; -// apply method - Apply a modifier to an option in a type safe way. -template -void apply(const Mod &M, Opt *O) { +// apply method - Apply modifiers to an option in a type safe way. +template +void apply(Opt *O, const Mod &M, const Mods &... Ms) { applicator::opt(M, *O); + apply(O, Ms...); } +template void apply(Opt *O, const Mod &M) { + applicator::opt(M, *O); +} //===----------------------------------------------------------------------===// // opt_storage class @@ -754,190 +1086,167 @@ void apply(const Mod &M, Opt *O) { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template +template class opt_storage { - DataType *Location; // Where to store the object... + DataType *Location; // Where to store the object... + OptionValue Default; - void check() const { - assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage, " - "or cl::init specified before cl::location()!!"); + void check_location() const { + assert(Location && "cl::location(...) not specified for a command " + "line option with external storage, " + "or cl::init specified before cl::location()!!"); } + public: - opt_storage() : Location(0) {} + opt_storage() : Location(nullptr) {} bool setLocation(Option &O, DataType &L) { if (Location) return O.error("cl::location(x) specified more than once!"); Location = &L; + Default = L; return false; } - template - void setValue(const T &V) { - check(); + template void setValue(const T &V, bool initial = false) { + check_location(); *Location = V; + if (initial) + Default = V; + } + + DataType &getValue() { + check_location(); + return *Location; + } + const DataType &getValue() const { + check_location(); + return *Location; } - DataType &getValue() { check(); return *Location; } - const DataType &getValue() const { check(); return *Location; } - operator DataType() const { return this->getValue(); } -}; + const OptionValue &getDefault() const { return Default; } +}; // Define how to hold a class type object, such as a string. Since we can // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template -class opt_storage : public DataType { +template +class opt_storage : public DataType { public: - template - void setValue(const T &V) { DataType::operator=(V); } + OptionValue Default; + + template void setValue(const T &V, bool initial = false) { + DataType::operator=(V); + if (initial) + Default = V; + } DataType &getValue() { return *this; } const DataType &getValue() const { return *this; } + + const OptionValue &getDefault() const { return Default; } }; // Define a partial specialization to handle things we cannot inherit from. In // this case, we store an instance through containment, and overload operators // to get at the value. // -template -class opt_storage { +template class opt_storage { public: DataType Value; + OptionValue Default; // Make sure we initialize the value with the default constructor for the // type. - opt_storage() : Value(DataType()) {} + opt_storage() : Value(DataType()), Default(DataType()) {} - template - void setValue(const T &V) { Value = V; } + template void setValue(const T &V, bool initial = false) { + Value = V; + if (initial) + Default = V; + } DataType &getValue() { return Value; } DataType getValue() const { return Value; } + const OptionValue &getDefault() const { return Default; } + operator DataType() const { return getValue(); } // If the datatype is a pointer, support -> on it. DataType operator->() const { return Value; } }; - //===----------------------------------------------------------------------===// // opt - A scalar command line option. // template > + class ParserClass = parser> class opt : public Option, public opt_storage::value> { + std::is_class::value> { ParserClass Parser; - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, - StringRef Arg) { + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse error! + return true; // Parse error! this->setValue(Val); this->setPosition(pos); return false; } - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } + void printOptionValue(size_t GlobalWidth, bool Force) const override { + if (Force || this->getDefault().compare(this->getValue())) { + cl::printOptionDiff(*this, Parser, this->getValue(), + this->getDefault(), GlobalWidth); + } + } + void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; + public: // setInitialValue - Used by the cl::init modifier... - void setInitialValue(const DataType &V) { this->setValue(V); } + void setInitialValue(const DataType &V) { this->setValue(V, true); } ParserClass &getParser() { return Parser; } - template - DataType &operator=(const T &Val) { + template DataType &operator=(const T &Val) { this->setValue(Val); return this->getValue(); } - // One option... - template - explicit opt(const M0t &M0) : Option(Optional | NotHidden) { - apply(M0, this); - done(); - } - - // Two options... - template - opt(const M0t &M0, const M1t &M1) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - - // Three options... - template - opt(const M0t &M0, const M1t &M1, - const M2t &M2) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, - const M3t &M3) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, - const M6t &M6) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(Optional | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit opt(const Mods &... Ms) + : Option(Optional, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -955,9 +1264,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt); // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class list_storage { - StorageClass *Location; // Where to store the object... +template class list_storage { + StorageClass *Location; // Where to store the object... public: list_storage() : Location(0) {} @@ -969,64 +1277,125 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); Location->push_back(V); } }; - -// Define how to hold a class type object, such as a string. Since we can -// inherit from a class, we do so. This makes us exactly compatible with the -// object in all cases that it is used. +// Define how to hold a class type object, such as a string. +// Originally this code inherited from std::vector. In transitioning to a new +// API for command line options we should change this. The new implementation +// of this list_storage specialization implements the minimum subset of the +// std::vector API required for all the current clients. // -template -class list_storage : public std::vector { +// FIXME: Reduce this API to a more narrow subset of std::vector +// +template class list_storage { + std::vector Storage; + public: - template - void addValue(const T &V) { std::vector::push_back(V); } -}; + typedef typename std::vector::iterator iterator; + + iterator begin() { return Storage.begin(); } + iterator end() { return Storage.end(); } + + typedef typename std::vector::const_iterator const_iterator; + const_iterator begin() const { return Storage.begin(); } + const_iterator end() const { return Storage.end(); } + + typedef typename std::vector::size_type size_type; + size_type size() const { return Storage.size(); } + + bool empty() const { return Storage.empty(); } + void push_back(const DataType &value) { Storage.push_back(value); } + void push_back(DataType &&value) { Storage.push_back(value); } + + typedef typename std::vector::reference reference; + typedef typename std::vector::const_reference const_reference; + reference operator[](size_type pos) { return Storage[pos]; } + const_reference operator[](size_type pos) const { return Storage[pos]; } + + iterator erase(const_iterator pos) { return Storage.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { + return Storage.erase(first, last); + } + + iterator erase(iterator pos) { return Storage.erase(pos); } + iterator erase(iterator first, iterator last) { + return Storage.erase(first, last); + } + + iterator insert(const_iterator pos, const DataType &value) { + return Storage.insert(pos, value); + } + iterator insert(const_iterator pos, DataType &&value) { + return Storage.insert(pos, value); + } + + reference front() { return Storage.front(); } + const_reference front() const { return Storage.front(); } + + operator std::vector&() { return Storage; } + operator ArrayRef() { return Storage; } + std::vector *operator&() { return &Storage; } + const std::vector *operator&() const { return &Storage; } + + template void addValue(const T &V) { Storage.push_back(V); } +}; //===----------------------------------------------------------------------===// // list - A list of command line options. // -template > -class list : public Option, public list_storage { +template > +class list : public Option, public list_storage { std::vector Positions; ParserClass Parser; - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! - list_storage::addValue(Val); + return true; // Parse Error! + list_storage::addValue(Val); setPosition(pos); Positions.push_back(pos); return false; } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } + // Unimplemented: list options don't currently store their default value. + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } + void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + list(const list &) = delete; + list &operator=(const list &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1035,71 +1404,12 @@ public: return Positions[optnum]; } - void setNumAdditionalVals(unsigned n) { - Option::setNumAdditionalVals(n); - } + void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } - // One option... - template - explicit list(const M0t &M0) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template - list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit list(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1110,10 +1420,11 @@ struct multi_val { explicit multi_val(unsigned N) : AdditionalVals(N) {} template - void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } + void apply(list &L) const { + L.setNumAdditionalVals(AdditionalVals); + } }; - //===----------------------------------------------------------------------===// // bits_storage class @@ -1121,20 +1432,18 @@ struct multi_val { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class bits_storage { - unsigned *Location; // Where to store the bits... +template class bits_storage { + unsigned *Location; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = reinterpret_cast(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } public: - bits_storage() : Location(0) {} + bits_storage() : Location(nullptr) {} bool setLocation(Option &O, unsigned &L) { if (Location) @@ -1143,89 +1452,90 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); *Location |= Bit(V); } unsigned getBits() { return *Location; } - template - bool isSet(const T &V) { + template bool isSet(const T &V) { return (*Location & Bit(V)) != 0; } }; - // Define how to hold bits. Since we can inherit from a class, we do so. // This makes us exactly compatible with the bits in all cases that it is used. // -template -class bits_storage { - unsigned Bits; // Where to store the bits... +template class bits_storage { + unsigned Bits; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = (unsigned)V; assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } public: - template - void addValue(const T &V) { - Bits |= Bit(V); - } + template void addValue(const T &V) { Bits |= Bit(V); } unsigned getBits() { return Bits; } - template - bool isSet(const T &V) { - return (Bits & Bit(V)) != 0; - } + template bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } }; - //===----------------------------------------------------------------------===// // bits - A bit vector of command options. // template > + class ParserClass = parser> class bits : public Option, public bits_storage { std::vector Positions; ParserClass Parser; - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! - addValue(Val); + return true; // Parse Error! + this->addValue(Val); setPosition(pos); Positions.push_back(pos); return false; } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } + // Unimplemented: bits options don't currently store their default values. + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } + void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + bits(const bits &) = delete; + bits &operator=(const bits &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1234,67 +1544,10 @@ public: return Positions[optnum]; } - // One option... - template - explicit bits(const M0t &M0) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template - bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore | NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit bits(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1305,21 +1558,38 @@ public: class alias : public Option { Option *AliasFor; - virtual bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) { + bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value, + bool MultiArg = false) override { + return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); + } // Handle printing stuff... - virtual size_t getOptionWidth() const; - virtual void printOptionInfo(size_t GlobalWidth) const; + size_t getOptionWidth() const override; + void printOptionInfo(size_t GlobalWidth) const override; + + // Aliases do not need to print their values. + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } + + ValueExpected getValueExpectedFlagDefault() const override { + return AliasFor->getValueExpectedFlag(); + } void done() { if (!hasArgStr()) error("cl::alias must have argument name specified!"); - if (AliasFor == 0) + if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); - addArgument(); + addArgument(); } + + // Command line options should not be copyable + alias(const alias &) = delete; + alias &operator=(const alias &) = delete; + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1327,30 +1597,10 @@ public: AliasFor = &O; } - // One option... - template - explicit alias(const M0t &M0) : Option(Optional | Hidden), AliasFor(0) { - apply(M0, this); - done(); - } - // Two options... - template - alias(const M0t &M0, const M1t &M1) : Option(Optional | Hidden), AliasFor(0) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional | Hidden), AliasFor(0) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional | Hidden), AliasFor(0) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template + explicit alias(const Mods &... Ms) + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(this, Ms...); done(); } }; @@ -1367,15 +1617,140 @@ struct aliasopt { // printed to stderr at the end of the regular help, just before // exit is called. struct extrahelp { - const char * morehelp; - explicit extrahelp(const char* help); + const char *morehelp; + explicit extrahelp(const char *help); }; void PrintVersionMessage(); -// This function just prints the help message, exactly the same way as if the -// --help option had been given on the command line. -// NOTE: THIS FUNCTION TERMINATES THE PROGRAM! -void PrintHelpMessage(); + +/// This function just prints the help message, exactly the same way as if the +/// -help or -help-hidden option had been given on the command line. +/// +/// NOTE: THIS FUNCTION TERMINATES THE PROGRAM! +/// +/// \param Hidden if true will print hidden options +/// \param Categorized if true print options in categories +void PrintHelpMessage(bool Hidden = false, bool Categorized = false); + +//===----------------------------------------------------------------------===// +// Public interface for accessing registered options. +// + +/// \brief Use this to get a StringMap to all registered named options +/// (e.g. -help). Note \p Map Should be an empty StringMap. +/// +/// \return A reference to the StringMap used by the cl APIs to parse options. +/// +/// Access to unnamed arguments (i.e. positional) are not provided because +/// it is expected that the client already has access to these. +/// +/// Typical usage: +/// \code +/// main(int argc,char* argv[]) { +/// StringMap &opts = llvm::cl::getRegisteredOptions(); +/// assert(opts.count("help") == 1) +/// opts["help"]->setDescription("Show alphabetical help information") +/// // More code +/// llvm::cl::ParseCommandLineOptions(argc,argv); +/// //More code +/// } +/// \endcode +/// +/// This interface is useful for modifying options in libraries that are out of +/// the control of the client. The options should be modified before calling +/// llvm::cl::ParseCommandLineOptions(). +/// +/// Hopefully this API can be depricated soon. Any situation where options need +/// to be modified by tools or libraries should be handled by sane APIs rather +/// than just handing around a global list. +StringMap