[llvm] b9123f7 - [Support] Remove cl::Grouping (#224958)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 19:50:54 PDT 2026
Author: Fangrui Song
Date: 2026-09-24T19:50:45-07:00
New Revision: b9123f788eb3e62c5cf18fd7d7b093dd3206b60d
URL: https://github.com/llvm/llvm-project/commit/b9123f788eb3e62c5cf18fd7d7b093dd3206b60d
DIFF: https://github.com/llvm/llvm-project/commit/b9123f788eb3e62c5cf18fd7d7b093dd3206b60d.diff
LOG: [Support] Remove cl::Grouping (#224958)
This feature emulates POSIX's grouped short options in a non-perfect
way. https://reviews.llvm.org/D61270 made every single-character
cl::option implicitly group, leading to weird error message for `opt
-foo=bar`: `opt: for the -o option: may not occur within a group!`
Every tool (primarily binutils-style tools) has since migrated to
OptTable,
with llvm-cov gcov the last (#224955).
Delete this feature, which would block TableGen based representation.
LLM-aided
Added:
Modified:
llvm/docs/CommandLine.md
llvm/include/llvm/Support/CommandLine.h
llvm/lib/Support/CommandLine.cpp
llvm/unittests/Support/CommandLineTest.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandLine.md b/llvm/docs/CommandLine.md
index 3dd499e2a2f6c..fb3bccd242382 100644
--- a/llvm/docs/CommandLine.md
+++ b/llvm/docs/CommandLine.md
@@ -58,8 +58,7 @@ CommandLine library to have the following features:
1. Capable: The CommandLine library can handle lots of
diff erent forms of
options often found in real programs. For example, {ref}`positional <positional>` arguments,
- `ls` style {ref}`grouping <grouping>` options (to allow processing '`ls -lad`'
- naturally), `ld` style {ref}`prefix <prefix>` options (to parse '`-lmalloc
+ `ld` style {ref}`prefix <prefix>` options (to parse '`-lmalloc
-L/usr/lib`'), and interpreter style options.
This document will hopefully let you jump in and start using CommandLine in your
@@ -1155,55 +1154,6 @@ As usual, you can only specify one of these arguments at most.
**cl::Prefix** options must not have the **cl::ValueDisallowed** modifier
specified.
-(grouping)=
-(cl::Grouping)=
-
-#### Controlling options grouping
-
-The **cl::Grouping** modifier can be combined with any formatting types except
-for {ref}`cl::Positional <cl::Positional>`. It is used to implement Unix-style tools (like `ls`)
-that have lots of single letter arguments, but only require a single dash.
-For example, the '`ls -labF`' command actually enables four
diff erent options,
-all of which are single letters.
-
-Note that **cl::Grouping** options can have values only if they are used
-separately or at the end of the groups. For {ref}`cl::ValueRequired <cl::ValueRequired>`, it is
-a runtime error if such an option is used elsewhere in the group.
-
-The CommandLine library does not restrict how you use the **cl::Prefix** or
-**cl::Grouping** modifiers, but it is possible to specify ambiguous argument
-settings. Thus, it is possible to have multiple letter options that are prefix
-or grouping options, and they will still work as designed.
-
-To do this, the CommandLine library uses a greedy algorithm to parse the input
-option into (potentially multiple) prefix and grouping options. The strategy
-basically looks like this:
-
-```
-parse(string OrigInput) {
-
-1. string Input = OrigInput;
-2. if (isOption(Input)) return getOption(Input).parse(); // Normal option
-3. while (!Input.empty() && !isOption(Input)) Input.pop_back(); // Remove the last letter
-4. while (!Input.empty()) {
- string MaybeValue = OrigInput.substr(Input.length())
- if (getOption(Input).isPrefix())
- return getOption(Input).parse(MaybeValue)
- if (!MaybeValue.empty() && MaybeValue[0] == '=')
- return getOption(Input).parse(MaybeValue.substr(1))
- if (!getOption(Input).isGrouping())
- return error()
- getOption(Input).parse()
- Input = OrigInput = MaybeValue
- while (!Input.empty() && !isOption(Input)) Input.pop_back();
- if (!Input.empty() && !getOption(Input).isGrouping())
- return error()
- }
-5. if (!OrigInput.empty()) error();
-
-}
-```
-
#### Miscellaneous option modifiers
The miscellaneous option modifiers are the only flags where you can specify more
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index 15fbb8c56a0b0..7537d4c74f212 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -161,12 +161,6 @@ enum FormattingFlags {
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?
-
- // Can this option group with other options?
- // If this is enabled, multiple letter options are allowed to bunch together
- // with only a single hyphen for the whole group. This allows emulation
- // of the behavior that ls uses for example: ls -la === ls -l -a
- Grouping = 0x08,
};
//===----------------------------------------------------------------------===//
@@ -1331,11 +1325,7 @@ template <> struct applicator<FormattingFlags> {
};
template <> struct applicator<MiscFlags> {
- static void opt(MiscFlags MF, Option &O) {
- assert((MF != Grouping || O.ArgStr.size() == 1) &&
- "cl::Grouping can only apply to single character Options.");
- O.setMiscFlag(MF);
- }
+ static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
};
// Apply modifiers to an option in a type safe way.
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 70eca48ee6635..b19984a0eeb03 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -140,15 +140,6 @@ static SmallString<8> argPrefix(StringRef ArgName, size_t Pad = DefaultPad) {
return Prefix;
}
-// Option predicates...
-static inline bool isGrouping(const Option *O) {
- return O->getMiscFlags() & cl::Grouping;
-}
-static inline bool isPrefixedOrGrouping(const Option *O) {
- return isGrouping(O) || O->getFormattingFlag() == cl::Prefix ||
- O->getFormattingFlag() == cl::AlwaysPrefix;
-}
-
using OptionsMapTy = DenseMap<StringRef, Option *>;
namespace {
@@ -393,7 +384,8 @@ class CommandLineParser {
Option *LookupLongOption(SubCommand &Sub, StringRef &Arg, StringRef &Value,
bool LongOptionsUseDoubleDash, bool HaveDoubleDash) {
Option *Opt = LookupOption(Sub, Arg, Value);
- if (Opt && LongOptionsUseDoubleDash && !HaveDoubleDash && !isGrouping(Opt))
+ if (Opt && LongOptionsUseDoubleDash && !HaveDoubleDash &&
+ Opt->ArgStr.size() != 1)
return nullptr;
return Opt;
}
@@ -456,8 +448,6 @@ void Option::setArgStr(StringRef S) {
globalParser().updateArgStr(this, S);
assert(!S.starts_with("-") && "Option can't start with '-");
ArgStr = S;
- if (ArgStr.size() == 1)
- setMiscFlag(Grouping);
}
void Option::addCategory(OptionCategory &C) {
@@ -688,92 +678,44 @@ bool llvm::cl::ProvidePositionalOption(Option *Handler, StringRef Arg, int i) {
return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy);
}
-// getOptionPred - Check to see if there are any options that satisfy the
-// specified predicate with names that are the prefixes in Name. This is
-// checked by progressively stripping characters off of the name, checking to
-// see if there options that satisfy the predicate. If we find one, return it,
-// otherwise return null.
-//
-static Option *getOptionPred(StringRef Name, size_t &Length,
- bool (*Pred)(const Option *),
- const OptionsMapTy &OptionsMap) {
- auto OMI = OptionsMap.find(Name);
- if (OMI != OptionsMap.end() && !Pred(OMI->second))
- OMI = OptionsMap.end();
-
- // Loop while we haven't found an option and Name still has at least two
- // characters in it (so that the next iteration will not be the empty
- // string.
- while (OMI == OptionsMap.end() && Name.size() > 1) {
- Name = Name.drop_back();
- OMI = OptionsMap.find(Name);
- if (OMI != OptionsMap.end() && !Pred(OMI->second))
- OMI = OptionsMap.end();
- }
-
- if (OMI != OptionsMap.end() && Pred(OMI->second)) {
- Length = Name.size();
- return OMI->second; // Found one!
- }
- return nullptr; // No option found!
-}
-
-/// HandlePrefixedOrGroupedOption - The specified argument string (which started
-/// with at least one '-') does not fully match an available option. Check to
-/// see if this is a prefix or grouped option. If so, split arg into output an
-/// Arg/Value pair and return the Option to parse it with.
-static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value,
- bool &ErrorParsing,
- const OptionsMapTy &OptionsMap) {
+// Find the cl::Prefix or cl::AlwaysPrefix option whose name is the longest
+// prefix of Name.
+static Option *findPrefixOption(StringRef Name, size_t &Length,
+ const OptionsMapTy &OptionsMap) {
+ for (; !Name.empty(); Name = Name.drop_back()) {
+ Option *O = OptionsMap.lookup(Name);
+ if (O && (O->getFormattingFlag() == cl::Prefix ||
+ O->getFormattingFlag() == cl::AlwaysPrefix)) {
+ Length = Name.size();
+ return O;
+ }
+ }
+ return nullptr;
+}
+
+/// The specified argument string (which started with at least one '-') does not
+/// fully match an available option. Check to see if this is a prefix option.
+/// If so, split arg into output an Arg/Value pair and return the Option to
+/// parse it with.
+static Option *HandlePrefixedOption(StringRef &Arg, StringRef &Value,
+ const OptionsMapTy &OptionsMap) {
if (Arg.size() == 1)
return nullptr;
- // Do the lookup!
size_t Length = 0;
- Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap);
- if (!PGOpt)
+ Option *POpt = findPrefixOption(Arg, Length, OptionsMap);
+ if (!POpt)
return nullptr;
- do {
- StringRef MaybeValue =
- (Length < Arg.size()) ? Arg.substr(Length) : StringRef();
- Arg = Arg.substr(0, Length);
- assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt);
-
- // cl::Prefix options do not preserve '=' when used separately.
- // The behavior for them with grouped options should be the same.
- if (MaybeValue.empty() || PGOpt->getFormattingFlag() == cl::AlwaysPrefix ||
- (PGOpt->getFormattingFlag() == cl::Prefix && MaybeValue[0] != '=')) {
- Value = MaybeValue;
- return PGOpt;
- }
-
- if (MaybeValue[0] == '=') {
- Value = MaybeValue.substr(1);
- return PGOpt;
- }
-
- // This must be a grouped option.
- assert(isGrouping(PGOpt) && "Broken getOptionPred!");
-
- // Grouping options inside a group can't have values.
- if (PGOpt->getValueExpectedFlag() == cl::ValueRequired) {
- ErrorParsing |= PGOpt->error("may not occur within a group!");
- return nullptr;
- }
-
- // Because the value for the option is not required, we don't need to pass
- // argc/argv in.
- int Dummy = 0;
- ErrorParsing |= ProvideOption(PGOpt, Arg, StringRef(), 0, nullptr, Dummy);
+ StringRef MaybeValue =
+ (Length < Arg.size()) ? Arg.substr(Length) : StringRef();
+ Arg = Arg.substr(0, Length);
- // Get the next grouping option.
- Arg = MaybeValue;
- PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap);
- } while (PGOpt);
-
- // We could not find a grouping option in the remainder of Arg.
- return nullptr;
+ // cl::Prefix options do not preserve '=' when used separately.
+ if (POpt->getFormattingFlag() == cl::Prefix && MaybeValue.starts_with("="))
+ MaybeValue = MaybeValue.drop_front();
+ Value = MaybeValue;
+ return POpt;
}
static bool RequiresValue(const Option *O) {
@@ -1651,10 +1593,9 @@ bool CommandLineParser::ParseCommandLineOptions(
Handler = LookupLongOption(SubCommand::getTopLevel(), ArgName, Value,
LongOptionsUseDoubleDash, HaveDoubleDash);
- // Check to see if this "option" is really a prefixed or grouped argument.
+ // Check to see if this "option" is really a prefixed argument.
if (!Handler && !(LongOptionsUseDoubleDash && HaveDoubleDash))
- Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,
- OptionsMap);
+ Handler = HandlePrefixedOption(ArgName, Value, OptionsMap);
// Otherwise, look for the closest available option to report to the user
// in the upcoming error.
diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp
index 6af5ec7ccc774..d354d3ccf6d9b 100644
--- a/llvm/unittests/Support/CommandLineTest.cpp
+++ b/llvm/unittests/Support/CommandLineTest.cpp
@@ -1707,197 +1707,22 @@ TEST(CommandLineTest, PrefixOptions) {
EXPECT_EQ(MacroDefs.front().compare("HAVE_FOO"), 0);
}
-TEST(CommandLineTest, GroupingWithValue) {
+TEST(CommandLineTest, NoGrouping) {
cl::ResetCommandLineParser();
- StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
- StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
- StackOption<bool> OptD("d", cl::Grouping, cl::ValueDisallowed,
- cl::desc("ValueDisallowed option"));
- StackOption<std::string> OptV("v", cl::Grouping,
- cl::desc("ValueRequired option"));
- StackOption<std::string> OptO("o", cl::Grouping, cl::ValueOptional,
- cl::desc("ValueOptional option"));
-
- // Should be possible to use an option which requires a value
- // at the end of a group.
- const char *args1[] = {"prog", "-fv", "val1"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("val1", OptV.c_str());
- OptV.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should not crash if it is accidentally used elsewhere in the group.
- const char *args2[] = {"prog", "-vf", "val2"};
- EXPECT_FALSE(
- cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
- OptV.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should allow the "opt=value" form at the end of the group
- const char *args3[] = {"prog", "-fv=val3"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("val3", OptV.c_str());
- OptV.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should allow assigning a value for a ValueOptional option
- // at the end of the group
- const char *args4[] = {"prog", "-fo=val4"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("val4", OptO.c_str());
- OptO.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should assign an empty value if a ValueOptional option is used elsewhere
- // in the group.
- const char *args5[] = {"prog", "-fob"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args5, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_EQ(1, OptO.getNumOccurrences());
- EXPECT_EQ(1, OptB.getNumOccurrences());
- EXPECT_TRUE(OptO.empty());
- cl::ResetAllOptionOccurrences();
-
- // Should not allow an assignment for a ValueDisallowed option.
- const char *args6[] = {"prog", "-fd=false"};
- EXPECT_FALSE(
- cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
-}
-
-TEST(CommandLineTest, GroupingAndPrefix) {
- cl::ResetCommandLineParser();
-
- StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
- StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
- StackOption<std::string> OptP("p", cl::Prefix, cl::Grouping,
- cl::desc("Prefix and Grouping"));
- StackOption<std::string> OptA("a", cl::AlwaysPrefix, cl::Grouping,
- cl::desc("AlwaysPrefix and Grouping"));
-
- // Should be possible to use a cl::Prefix option without grouping.
- const char *args1[] = {"prog", "-pval1"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
- EXPECT_STREQ("val1", OptP.c_str());
- OptP.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should be possible to pass a value in a separate argument.
- const char *args2[] = {"prog", "-p", "val2"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
- EXPECT_STREQ("val2", OptP.c_str());
- OptP.clear();
- cl::ResetAllOptionOccurrences();
-
- // The "-opt=value" form should work, too.
- const char *args3[] = {"prog", "-p=val3"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
- EXPECT_STREQ("val3", OptP.c_str());
- OptP.clear();
- cl::ResetAllOptionOccurrences();
-
- // All three previous cases should work the same way if an option with both
- // cl::Prefix and cl::Grouping modifiers is used at the end of a group.
- const char *args4[] = {"prog", "-fpval4"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("val4", OptP.c_str());
- OptP.clear();
- cl::ResetAllOptionOccurrences();
-
- const char *args5[] = {"prog", "-fp", "val5"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("val5", OptP.c_str());
- OptP.clear();
- cl::ResetAllOptionOccurrences();
+ StackOption<bool> OptF("f", cl::desc("Some flag"));
+ StackOption<bool> OptB("b", cl::desc("Another flag"));
- const char *args6[] = {"prog", "-fp=val6"};
+ const char *args1[] = {"prog", "-f", "-b"};
EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("val6", OptP.c_str());
- OptP.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should assign a value even if the part after a cl::Prefix option is equal
- // to the name of another option.
- const char *args7[] = {"prog", "-fpb"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args7, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("b", OptP.c_str());
- EXPECT_FALSE(OptB);
- OptP.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should be possible to use a cl::AlwaysPrefix option without grouping.
- const char *args8[] = {"prog", "-aval8"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args8, StringRef(), &llvm::nulls()));
- EXPECT_STREQ("val8", OptA.c_str());
- OptA.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should not be possible to pass a value in a separate argument.
- const char *args9[] = {"prog", "-a", "val9"};
- EXPECT_FALSE(
- cl::ParseCommandLineOptions(3, args9, StringRef(), &llvm::nulls()));
- cl::ResetAllOptionOccurrences();
-
- // With the "-opt=value" form, the "=" symbol should be preserved.
- const char *args10[] = {"prog", "-a=val10"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args10, StringRef(), &llvm::nulls()));
- EXPECT_STREQ("=val10", OptA.c_str());
- OptA.clear();
- cl::ResetAllOptionOccurrences();
-
- // All three previous cases should work the same way if an option with both
- // cl::AlwaysPrefix and cl::Grouping modifiers is used at the end of a group.
- const char *args11[] = {"prog", "-faval11"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args11, StringRef(), &llvm::nulls()));
+ cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
EXPECT_TRUE(OptF);
- EXPECT_STREQ("val11", OptA.c_str());
- OptA.clear();
+ EXPECT_TRUE(OptB);
cl::ResetAllOptionOccurrences();
- const char *args12[] = {"prog", "-fa", "val12"};
+ const char *args2[] = {"prog", "-fb"};
EXPECT_FALSE(
- cl::ParseCommandLineOptions(3, args12, StringRef(), &llvm::nulls()));
- cl::ResetAllOptionOccurrences();
-
- const char *args13[] = {"prog", "-fa=val13"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args13, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("=val13", OptA.c_str());
- OptA.clear();
- cl::ResetAllOptionOccurrences();
-
- // Should assign a value even if the part after a cl::AlwaysPrefix option
- // is equal to the name of another option.
- const char *args14[] = {"prog", "-fab"};
- EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args14, StringRef(), &llvm::nulls()));
- EXPECT_TRUE(OptF);
- EXPECT_STREQ("b", OptA.c_str());
- EXPECT_FALSE(OptB);
- OptA.clear();
- cl::ResetAllOptionOccurrences();
+ cl::ParseCommandLineOptions(2, args2, StringRef(), &llvm::nulls()));
}
TEST(CommandLineTest, LongOptions) {
@@ -1937,8 +1762,7 @@ TEST(CommandLineTest, LongOptions) {
EXPECT_TRUE(Errs.empty()); Errs.clear();
cl::ResetAllOptionOccurrences();
- // Fails because `-ab` and `--ab` are treated the same and appear more than
- // once. Also, `val1` is unexpected.
+ // Fails because `val1` is unexpected.
EXPECT_FALSE(
cl::ParseCommandLineOptions(4, args3, StringRef(), &OS));
outs()<< Errs << "\n";
@@ -1950,8 +1774,8 @@ TEST(CommandLineTest, LongOptions) {
// `--` for long options.
//
- // Fails because `-ab` is treated as `-a -b`, so `-a` is seen twice, and
- // `val1` is unexpected.
+ // Fails because `-ab` is neither a short option nor `--ab`, and `val1` is
+ // unexpected.
EXPECT_FALSE(cl::ParseCommandLineOptions(4, args1, StringRef(), &OS, nullptr,
nullptr, true));
EXPECT_FALSE(Errs.empty()); Errs.clear();
@@ -1963,13 +1787,11 @@ TEST(CommandLineTest, LongOptions) {
EXPECT_TRUE(Errs.empty()); Errs.clear();
cl::ResetAllOptionOccurrences();
- // Works because `-ab` is treated as `-a -b`, and `--ab` is a long option.
- EXPECT_TRUE(cl::ParseCommandLineOptions(4, args3, StringRef(), &OS, nullptr,
- nullptr, true));
- EXPECT_TRUE(OptA);
- EXPECT_TRUE(OptBLong);
- EXPECT_STREQ("val1", OptAB.c_str());
- EXPECT_TRUE(Errs.empty()); Errs.clear();
+ // Fails because `-ab` is not `--ab`.
+ EXPECT_FALSE(cl::ParseCommandLineOptions(4, args3, StringRef(), &OS, nullptr,
+ nullptr, true));
+ EXPECT_FALSE(Errs.empty());
+ Errs.clear();
cl::ResetAllOptionOccurrences();
}
More information about the llvm-commits
mailing list