// (Currently not perfect, but best-effort.)
void PrintOptionValues();
-// MarkOptionsChanged - Internal helper function.
-void MarkOptionsChanged();
+// 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
unsigned Misc : 3;
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.
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
OptionCategory *Category; // The Category this option belongs to
+ bool FullyInitialized; // Has addArguemnt been called?
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
return (enum NumOccurrencesFlag)Occurrences;
//-------------------------------------------------------------------------===
// 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 setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; }
enum OptionHidden Hidden)
: NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0),
- AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""),
- ValueStr(""), Category(&GeneralCategory) {}
+ AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""),
+ Category(&GeneralCategory), FullyInitialized(false) {}
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
/// For testing purposes only.
void removeArgument();
- Option *getNextRegisteredOption() const { return NextRegistered; }
-
// Return the width of the option tag for printing...
virtual size_t getOptionWidth() const = 0;
// Support value comparison outside the template.
struct GenericOptionValue {
- virtual ~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();
};
bool compare(const GenericOptionValue & /*V*/) const override {
return false;
}
+
+protected:
+ ~OptionValueBase() = default;
};
// Simple copy of the option value.
DataType Value;
bool Valid;
+protected:
+ ~OptionValueCopy() = default;
+ OptionValueCopy(const OptionValueCopy&) = default;
+ OptionValueCopy &operator=(const OptionValueCopy&) = default;
+
public:
OptionValueCopy() : Valid(false) {}
template <class DataType>
struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
typedef DataType WrapperType;
+
+protected:
+ ~OptionValueBase() = default;
+ OptionValueBase() = default;
+ OptionValueBase(const OptionValueBase&) = default;
+ OptionValueBase &operator=(const OptionValueBase&) = default;
};
// Top-level option class.
template <class DataType>
-struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> {
- OptionValue() {}
+struct OptionValue final
+ : OptionValueBase<DataType, std::is_class<DataType>::value> {
+ OptionValue() = default;
OptionValue(const DataType &V) { this->setValue(V); }
// Some options may take their value from a different data type.
// Other safe-to-copy-by-value common option types.
enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
template <>
-struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> {
+struct OptionValue<cl::boolOrDefault> final
+ : OptionValueCopy<cl::boolOrDefault> {
typedef cl::boolOrDefault WrapperType;
OptionValue() {}
void anchor() override;
};
-template <> struct OptionValue<std::string> : OptionValueCopy<std::string> {
+template <>
+struct OptionValue<std::string> final : OptionValueCopy<std::string> {
typedef StringRef WrapperType;
OptionValue() {}
assert(findOption(Name) == Values.size() && "Option already exists!");
OptionInfo X(Name, static_cast<DataType>(V), HelpStr);
Values.push_back(X);
- MarkOptionsChanged();
+ AddLiteralOption(Owner, Name);
}
/// removeLiteralOption - Remove the specified option.
public:
basic_parser_impl(Option &O) {}
- virtual ~basic_parser_impl() {}
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueRequired;
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(Option &O) : basic_parser_impl(O) {}
typedef DataType parser_data_type;
typedef OptionValue<DataType> OptVal;
+
+protected:
+ // Workaround Clang PR22793
+ ~basic_parser() {}
};
//--------------------------------------------------
// parser<bool>
//
-template <> class parser<bool> : public basic_parser<bool> {
+template <> class parser<bool> final : public basic_parser<bool> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<boolOrDefault>
-template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
+template <>
+class parser<boolOrDefault> final : public basic_parser<boolOrDefault> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<int>
//
-template <> class parser<int> : public basic_parser<int> {
+template <> class parser<int> final : public basic_parser<int> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<unsigned>
//
-template <> class parser<unsigned> : public basic_parser<unsigned> {
+template <> class parser<unsigned> final : public basic_parser<unsigned> {
public:
parser(Option &O) : basic_parser(O) {}
// parser<unsigned long long>
//
template <>
-class parser<unsigned long long> : public basic_parser<unsigned long long> {
+class parser<unsigned long long> final
+ : public basic_parser<unsigned long long> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<double>
//
-template <> class parser<double> : public basic_parser<double> {
+template <> class parser<double> final : public basic_parser<double> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<float>
//
-template <> class parser<float> : public basic_parser<float> {
+template <> class parser<float> final : public basic_parser<float> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<std::string>
//
-template <> class parser<std::string> : public basic_parser<std::string> {
+template <> class parser<std::string> final : public basic_parser<std::string> {
public:
parser(Option &O) : basic_parser(O) {}
//--------------------------------------------------
// parser<char>
//
-template <> class parser<char> : public basic_parser<char> {
+template <> class parser<char> final : public basic_parser<char> {
public:
parser(Option &O) : basic_parser(O) {}
// This is instantiated for basic parsers when the parsed value has a different
// type than the option value. e.g. HelpPrinter.
template <class ParserDT, class ValDT> struct OptionDiffPrinter {
- void print(const Option &O, const parser<ParserDT> P, const ValDT & /*V*/,
+ void print(const Option &O, const parser<ParserDT> &P, const ValDT & /*V*/,
const OptionValue<ValDT> & /*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 <class DT> struct OptionDiffPrinter<DT, DT> {
- void print(const Option &O, const parser<DT> P, const DT &V,
+ void print(const Option &O, const parser<DT> &P, const DT &V,
const OptionValue<DT> &Default, size_t GlobalWidth) {
P.printOptionDiff(O, V, Default, GlobalWidth);
}
static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
};
-// apply method - Apply a modifier to an option in a type safe way.
-template <class Mod, class Opt> void apply(const Mod &M, Opt *O) {
+// apply method - Apply modifiers to an option in a type safe way.
+template <class Opt, class Mod, class... Mods>
+void apply(Opt *O, const Mod &M, const Mods &... Ms) {
+ applicator<Mod>::opt(M, *O);
+ apply(O, Ms...);
+}
+
+template <class Opt, class Mod> void apply(Opt *O, const Mod &M) {
applicator<Mod>::opt(M, *O);
}
}
// Command line options should not be copyable
- opt(const opt &) LLVM_DELETED_FUNCTION;
- opt &operator=(const opt &) LLVM_DELETED_FUNCTION;
+ opt(const opt &) = delete;
+ opt &operator=(const opt &) = delete;
public:
// setInitialValue - Used by the cl::init modifier...
return this->getValue();
}
- // One option...
- template <class M0t>
- explicit opt(const M0t &M0)
- : Option(Optional, NotHidden), Parser(*this) {
- apply(M0, this);
- done();
- }
-
- // Two options...
- template <class M0t, class M1t>
- opt(const M0t &M0, const M1t &M1)
+ template <class... Mods>
+ explicit opt(const Mods &... Ms)
: Option(Optional, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
-
- // Three options...
- template <class M0t, class M1t, class M2t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(Optional, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(Optional, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- done();
- }
- // Five options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4)
- : Option(Optional, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- done();
- }
- // Six options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
- opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
- const M5t &M5)
- : Option(Optional, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- done();
- }
- // Seven options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t>
- 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), Parser(*this) {
- 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 <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t, class M7t>
- 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), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- apply(M7, this);
+ apply(this, Ms...);
done();
}
};
}
// Command line options should not be copyable
- list(const list &) LLVM_DELETED_FUNCTION;
- list &operator=(const list &) LLVM_DELETED_FUNCTION;
+ list(const list &) = delete;
+ list &operator=(const list &) = delete;
public:
ParserClass &getParser() { return Parser; }
void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); }
- // One option...
- template <class M0t>
- explicit list(const M0t &M0)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- done();
- }
- // Two options...
- template <class M0t, class M1t>
- list(const M0t &M0, const M1t &M1)
+ template <class... Mods>
+ explicit list(const Mods &... Ms)
: Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
- // Three options...
- template <class M0t, class M1t, class M2t>
- list(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- done();
- }
- // Five options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- done();
- }
- // Six options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
- list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- done();
- }
- // Seven options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t>
- 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), Parser(*this) {
- 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 <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t, class M7t>
- 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), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- apply(M7, this);
+ apply(this, Ms...);
done();
}
};
}
// Command line options should not be copyable
- bits(const bits &) LLVM_DELETED_FUNCTION;
- bits &operator=(const bits &) LLVM_DELETED_FUNCTION;
+ bits(const bits &) = delete;
+ bits &operator=(const bits &) = delete;
public:
ParserClass &getParser() { return Parser; }
return Positions[optnum];
}
- // One option...
- template <class M0t>
- explicit bits(const M0t &M0)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- done();
- }
- // Two options...
- template <class M0t, class M1t>
- bits(const M0t &M0, const M1t &M1)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
- // Three options...
- template <class M0t, class M1t, class M2t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2)
+ template <class... Mods>
+ explicit bits(const Mods &... Ms)
: Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- done();
- }
- // Five options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- done();
- }
- // Six options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
- bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
- const M4t &M4, const M5t &M5)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- done();
- }
- // Seven options...
- template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t>
- 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), Parser(*this) {
- 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 <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t,
- class M6t, class M7t>
- 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), Parser(*this) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
- apply(M4, this);
- apply(M5, this);
- apply(M6, this);
- apply(M7, this);
+ apply(this, Ms...);
done();
}
};
}
// Command line options should not be copyable
- alias(const alias &) LLVM_DELETED_FUNCTION;
- alias &operator=(const alias &) LLVM_DELETED_FUNCTION;
+ alias(const alias &) = delete;
+ alias &operator=(const alias &) = delete;
public:
void setAliasFor(Option &O) {
AliasFor = &O;
}
- // One option...
- template <class M0t>
- explicit alias(const M0t &M0)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- done();
- }
- // Two options...
- template <class M0t, class M1t>
- alias(const M0t &M0, const M1t &M1)
+ template <class... Mods>
+ explicit alias(const Mods &... Ms)
: Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- apply(M1, this);
- done();
- }
- // Three options...
- template <class M0t, class M1t, class M2t>
- alias(const M0t &M0, const M1t &M1, const M2t &M2)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- done();
- }
- // Four options...
- template <class M0t, class M1t, class M2t, class M3t>
- alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- apply(M1, this);
- apply(M2, this);
- apply(M3, this);
+ apply(this, Ms...);
done();
}
};
/// \brief Use this to get a StringMap to all registered named options
/// (e.g. -help). Note \p Map Should be an empty StringMap.
///
-/// \param [out] Map will be filled with mappings where the key is the
-/// Option argument string (e.g. "help") and value is the corresponding
-/// Option*.
+/// \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<llvm::cl::Option*> opts;
-/// llvm::cl::getRegisteredOptions(opts);
+/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions();
/// assert(opts.count("help") == 1)
/// opts["help"]->setDescription("Show alphabetical help information")
/// // More code
/// 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().
-void getRegisteredOptions(StringMap<Option *> &Map);
+///
+/// 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<Option *> &getRegisteredOptions();
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
/// Some tools (like clang-format) like to be able to hide all options that are
/// not specific to the tool. This function allows a tool to specify a single
/// option category to display in the -help output.
-void HideUnrelatedOptions(ArrayRef<cl::OptionCategory *> Categories);
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
} // End namespace cl