Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions llvm/include/llvm/Support/CommandLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,31 @@ class LLVM_ABI parser<std::string> : public basic_parser<std::string> {

//--------------------------------------------------

template <>
class LLVM_ABI parser<std::optional<std::string>>
: public basic_parser<std::optional<std::string>> {
public:
parser(Option &O) : basic_parser(O) {}

// Return true on error.
bool parse(Option &, StringRef, StringRef Arg,
std::optional<std::string> &Value) {
Value = Arg.str();
return false;
}

// Overload in subclass to provide a better default value.
StringRef getValueName() const override { return "optional string"; }

void printOptionDiff(const Option &O, std::optional<StringRef> V,
const OptVal &Default, size_t GlobalWidth) const;

// An out-of-line virtual method to provide a 'home' for this class.
void anchor() override;
};

//--------------------------------------------------

extern template class LLVM_TEMPLATE_ABI basic_parser<char>;

template <> class LLVM_ABI parser<char> : public basic_parser<char> {
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Support/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ void parser<unsigned long long>::anchor() {}
void parser<double>::anchor() {}
void parser<float>::anchor() {}
void parser<std::string>::anchor() {}
void parser<std::optional<std::string>>::anchor() {}
void parser<char>::anchor() {}

// These anchor functions instantiate opt<T> and reference its virtual
Expand Down Expand Up @@ -2259,6 +2260,22 @@ void parser<std::string>::printOptionDiff(const Option &O, StringRef V,
outs() << ")\n";
}

void parser<std::optional<std::string>>::printOptionDiff(
const Option &O, std::optional<StringRef> V,
const OptionValue<std::optional<std::string>> &D,
size_t GlobalWidth) const {
printOptionName(O, GlobalWidth);
outs() << "= " << V;
size_t VSize = V.has_value() ? V.value().size() : 0;
size_t NumSpaces = MaxOptWidth > VSize ? MaxOptWidth - VSize : 0;
outs().indent(NumSpaces) << " (default: ";
if (D.hasValue() && D.getValue().has_value())
outs() << D.getValue();
else
outs() << "*no value*";
outs() << ")\n";
}

// Print a placeholder for options that don't yet support printOptionDiff().
void basic_parser_impl::printOptionNoValue(const Option &O,
size_t GlobalWidth) const {
Expand Down
16 changes: 16 additions & 0 deletions llvm/unittests/Support/CommandLineTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,22 @@ TEST(CommandLineTest, ConsumeAfterTwoPositionals) {
EXPECT_TRUE(Errs.empty());
}

TEST(CommandLineTest, ConsumeOptionalString) {
cl::ResetCommandLineParser();

StackOption<std::optional<std::string>, cl::opt<std::optional<std::string>>>
Input("input");

const char *Args[] = {"prog", "--input=\"value\""};

std::string Errs;
raw_string_ostream OS(Errs);
ASSERT_TRUE(cl::ParseCommandLineOptions(2, Args, StringRef(), &OS));
ASSERT_TRUE(Input.has_value());
EXPECT_EQ("\"value\"", *Input);
EXPECT_TRUE(Errs.empty());
}

TEST(CommandLineTest, ResetAllOptionOccurrences) {
cl::ResetCommandLineParser();

Expand Down