Skip to content

Commit 90a6884

Browse files
authored
Enable parsing of optional strings (#154364)
Previously a "opt<std::optional<std::string>>>" would fail to parse/would attempt to parse option value as argument.
1 parent 223cfa8 commit 90a6884

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

llvm/include/llvm/Support/CommandLine.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,31 @@ class LLVM_ABI parser<std::string> : public basic_parser<std::string> {
11931193

11941194
//--------------------------------------------------
11951195

1196+
template <>
1197+
class LLVM_ABI parser<std::optional<std::string>>
1198+
: public basic_parser<std::optional<std::string>> {
1199+
public:
1200+
parser(Option &O) : basic_parser(O) {}
1201+
1202+
// Return true on error.
1203+
bool parse(Option &, StringRef, StringRef Arg,
1204+
std::optional<std::string> &Value) {
1205+
Value = Arg.str();
1206+
return false;
1207+
}
1208+
1209+
// Overload in subclass to provide a better default value.
1210+
StringRef getValueName() const override { return "optional string"; }
1211+
1212+
void printOptionDiff(const Option &O, std::optional<StringRef> V,
1213+
const OptVal &Default, size_t GlobalWidth) const;
1214+
1215+
// An out-of-line virtual method to provide a 'home' for this class.
1216+
void anchor() override;
1217+
};
1218+
1219+
//--------------------------------------------------
1220+
11961221
extern template class LLVM_TEMPLATE_ABI basic_parser<char>;
11971222

11981223
template <> class LLVM_ABI parser<char> : public basic_parser<char> {

llvm/lib/Support/CommandLine.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ void parser<unsigned long long>::anchor() {}
101101
void parser<double>::anchor() {}
102102
void parser<float>::anchor() {}
103103
void parser<std::string>::anchor() {}
104+
void parser<std::optional<std::string>>::anchor() {}
104105
void parser<char>::anchor() {}
105106

106107
// These anchor functions instantiate opt<T> and reference its virtual
@@ -2261,6 +2262,22 @@ void parser<std::string>::printOptionDiff(const Option &O, StringRef V,
22612262
outs() << ")\n";
22622263
}
22632264

2265+
void parser<std::optional<std::string>>::printOptionDiff(
2266+
const Option &O, std::optional<StringRef> V,
2267+
const OptionValue<std::optional<std::string>> &D,
2268+
size_t GlobalWidth) const {
2269+
printOptionName(O, GlobalWidth);
2270+
outs() << "= " << V;
2271+
size_t VSize = V.has_value() ? V.value().size() : 0;
2272+
size_t NumSpaces = MaxOptWidth > VSize ? MaxOptWidth - VSize : 0;
2273+
outs().indent(NumSpaces) << " (default: ";
2274+
if (D.hasValue() && D.getValue().has_value())
2275+
outs() << D.getValue();
2276+
else
2277+
outs() << "*no value*";
2278+
outs() << ")\n";
2279+
}
2280+
22642281
// Print a placeholder for options that don't yet support printOptionDiff().
22652282
void basic_parser_impl::printOptionNoValue(const Option &O,
22662283
size_t GlobalWidth) const {

llvm/unittests/Support/CommandLineTest.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,22 @@ TEST(CommandLineTest, ConsumeAfterTwoPositionals) {
21172117
EXPECT_TRUE(Errs.empty());
21182118
}
21192119

2120+
TEST(CommandLineTest, ConsumeOptionalString) {
2121+
cl::ResetCommandLineParser();
2122+
2123+
StackOption<std::optional<std::string>, cl::opt<std::optional<std::string>>>
2124+
Input("input");
2125+
2126+
const char *Args[] = {"prog", "--input=\"value\""};
2127+
2128+
std::string Errs;
2129+
raw_string_ostream OS(Errs);
2130+
ASSERT_TRUE(cl::ParseCommandLineOptions(2, Args, StringRef(), &OS));
2131+
ASSERT_TRUE(Input.has_value());
2132+
EXPECT_EQ("\"value\"", *Input);
2133+
EXPECT_TRUE(Errs.empty());
2134+
}
2135+
21202136
TEST(CommandLineTest, ResetAllOptionOccurrences) {
21212137
cl::ResetCommandLineParser();
21222138

0 commit comments

Comments
 (0)