Index: include/llvm/Support/CommandLine.h =================================================================== --- include/llvm/Support/CommandLine.h +++ include/llvm/Support/CommandLine.h @@ -845,9 +845,20 @@ template class basic_parser : public basic_parser_impl { public: using parser_data_type = DataType; + + using Val = DataType; + using ValParam = typename std::conditional::value, + Val, const Val&>::type; using OptVal = OptionValue; + using OptValParam = typename std::conditional::value, + OptVal, const OptVal&>::type; basic_parser(Option &O) : basic_parser_impl(O) {} + + virtual void printOptionDiff(const Option &O, ValParam V, OptValParam Default, + size_t GlobalWidth) const { + printOptionNoValue(O, GlobalWidth); + } protected: ~basic_parser() = default; @@ -873,7 +884,7 @@ StringRef getValueName() const override { return StringRef(); } void printOptionDiff(const Option &O, bool V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -899,7 +910,7 @@ StringRef getValueName() const override { return StringRef(); } void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -921,7 +932,7 @@ StringRef getValueName() const override { return "int"; } void printOptionDiff(const Option &O, int V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -943,7 +954,7 @@ StringRef getValueName() const override { return "uint"; } void printOptionDiff(const Option &O, unsigned V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -968,7 +979,7 @@ StringRef getValueName() const override { return "uint"; } void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -990,7 +1001,7 @@ StringRef getValueName() const override { return "number"; } void printOptionDiff(const Option &O, double V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -1012,7 +1023,7 @@ StringRef getValueName() const override { return "number"; } void printOptionDiff(const Option &O, float V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -1036,8 +1047,9 @@ // getValueName - Overload in subclass to provide a better default value. StringRef getValueName() const override { return "string"; } - void printOptionDiff(const Option &O, StringRef V, const OptVal &Default, - size_t GlobalWidth) const; + void printOptionDiff(const Option &O, const std::string &V, + const OptVal &Default, + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -1062,7 +1074,7 @@ StringRef getValueName() const override { return "char"; } void printOptionDiff(const Option &O, char V, OptVal Default, - size_t GlobalWidth) const; + size_t GlobalWidth) const override; // An out-of-line virtual method to provide a 'home' for this class. void anchor() override; @@ -1087,7 +1099,7 @@ // 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*/, + void print(const Option &O, const basic_parser &P, const ValDT & /*V*/, const OptionValue & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } @@ -1096,7 +1108,7 @@ // 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, + void print(const Option &O, const basic_parser
&P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); } @@ -1109,10 +1121,8 @@ 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); + printer.print(O, P, V, Default, GlobalWidth); } //===----------------------------------------------------------------------===// Index: lib/Support/CommandLine.cpp =================================================================== --- lib/Support/CommandLine.cpp +++ lib/Support/CommandLine.cpp @@ -1649,7 +1649,7 @@ PRINT_OPT_DIFF(float) PRINT_OPT_DIFF(char) -void parser::printOptionDiff(const Option &O, StringRef V, +void parser::printOptionDiff(const Option &O, const std::string &V, const OptionValue &D, size_t GlobalWidth) const { printOptionName(O, GlobalWidth); Index: unittests/Support/CommandLineTest.cpp =================================================================== --- unittests/Support/CommandLineTest.cpp +++ unittests/Support/CommandLineTest.cpp @@ -50,9 +50,10 @@ const char *const name; }; -template -class StackOption : public cl::opt { - typedef cl::opt Base; +template > +class StackOption : public cl::opt { + typedef cl::opt Base; public: // One option... template @@ -648,4 +649,41 @@ EXPECT_TRUE(Opt3 == 3); } +/// Custom dummy parser for int options. +struct CustomIntParser final : cl::basic_parser { + static const int MAGIC_NR = 42; + static int printOptionDiffCount; + CustomIntParser(cl::Option &O) : cl::basic_parser(O) {} + bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, int &Value) { + Value = MAGIC_NR; + return false; + } + void printOptionDiff(const cl::Option &O, int V, OptVal Default, + size_t GlobalWidth) const { + //printOptionName(O, GlobalWidth); + //llvm::outs() << "= *always " << MAGIC_NR << "*\n"; + printOptionDiffCount++; + } +}; +int CustomIntParser::printOptionDiffCount = 0; + +TEST(CommandLineTest, PrintOptionValueWithCustomParser) { + cl::ResetCommandLineParser(); + + StackOption Opt1("opt1", cl::init(0)); + + const char *args[] = {"prog", "-opt1=0"}; + EXPECT_TRUE( + cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls())); + + EXPECT_TRUE(Opt1 == CustomIntParser::MAGIC_NR); + + for (auto &OM : cl::getRegisteredOptions(*cl::TopLevelSubCommand)) { + cl::Option *O = OM.second; + O->printOptionValue(8, true); + } + + EXPECT_TRUE(CustomIntParser::printOptionDiffCount > 0); +} + } // anonymous namespace