1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[CommandLine] Allow Options to specify multiple OptionCategory's.

Summary:
It's not uncommon for separate components to share common
Options, e.g., it's common for related Passes to share Options in
addition to the Pass specific ones.

With this change, components can use OptionCategory's to simply help
output even if some of the options are shared.

Reviewed By: MaskRay

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D61574

llvm-svn: 360179
This commit is contained in:
Don Hinton 2019-05-07 18:57:01 +00:00
parent 7b21a4a264
commit 42885681b9
3 changed files with 92 additions and 24 deletions

View File

@ -281,7 +281,8 @@ public:
StringRef ArgStr; // The argument string itself (ex: "help", "o")
StringRef HelpStr; // The descriptive text message for -help
StringRef ValueStr; // String describing what the value of this option is
OptionCategory *Category; // The Category this option belongs to
SmallVector<OptionCategory *, 2>
Categories; // The Categories this option belongs to
SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
bool FullyInitialized = false; // Has addArgument been called?
@ -333,14 +334,16 @@ public:
void setFormattingFlag(enum FormattingFlags V) { Formatting = V; }
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
void setPosition(unsigned pos) { Position = pos; }
void setCategory(OptionCategory &C) { Category = &C; }
void addCategory(OptionCategory &C);
void addSubCommand(SubCommand &S) { Subs.insert(&S); }
protected:
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
enum OptionHidden Hidden)
: Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden),
Formatting(NormalFormatting), Misc(0), Category(&GeneralCategory) {}
Formatting(NormalFormatting), Misc(0) {
Categories.push_back(&GeneralCategory);
}
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
@ -451,7 +454,7 @@ struct cat {
cat(OptionCategory &c) : Category(c) {}
template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
template <class Opt> void apply(Opt &O) const { O.addCategory(Category); }
};
// sub - Specify the subcommand that this option belongs to.
@ -1770,7 +1773,7 @@ class alias : public Option {
if (!Subs.empty())
error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
Subs = AliasFor->Subs;
Category = AliasFor->Category;
Categories = AliasFor->Categories;
addArgument();
}

View File

@ -425,6 +425,17 @@ void Option::setArgStr(StringRef S) {
setMiscFlag(Grouping);
}
void Option::addCategory(OptionCategory &C) {
assert(!Categories.empty() && "Categories cannot be empty.");
// Maintain backward compatibility by replacing the default GeneralCategory
// if it's still set. Otherwise, just add the new one. The GeneralCategory
// must be explicitly added if you want multiple categories that include it.
if (&C != &GeneralCategory && Categories[0] == &GeneralCategory)
Categories[0] = &C;
else
Categories.push_back(&C);
}
void Option::reset() {
NumOccurrences = 0;
setDefault();
@ -2132,9 +2143,11 @@ protected:
// options within categories will also be alphabetically sorted.
for (size_t I = 0, E = Opts.size(); I != E; ++I) {
Option *Opt = Opts[I].second;
assert(CategorizedOptions.count(Opt->Category) > 0 &&
"Option has an unregistered category");
CategorizedOptions[Opt->Category].push_back(Opt);
for (auto &Cat : Opt->Categories) {
assert(CategorizedOptions.count(Cat) > 0 &&
"Option has an unregistered category");
CategorizedOptions[Cat].push_back(Opt);
}
}
// Now do printing.
@ -2391,21 +2404,21 @@ cl::getRegisteredSubcommands() {
void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
for (auto &I : Sub.OptionsMap) {
if (I.second->Category != &Category &&
I.second->Category != &GenericCategory)
I.second->setHiddenFlag(cl::ReallyHidden);
for (auto &Cat : I.second->Categories) {
if (Cat != &Category &&
Cat != &GenericCategory)
I.second->setHiddenFlag(cl::ReallyHidden);
}
}
}
void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
SubCommand &Sub) {
auto CategoriesBegin = Categories.begin();
auto CategoriesEnd = Categories.end();
for (auto &I : Sub.OptionsMap) {
if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
CategoriesEnd &&
I.second->Category != &GenericCategory)
I.second->setHiddenFlag(cl::ReallyHidden);
for (auto &Cat : I.second->Categories) {
if (find(Categories, Cat) == Categories.end() && Cat != &GenericCategory)
I.second->setHiddenFlag(cl::ReallyHidden);
}
}
}

View File

@ -95,12 +95,20 @@ TEST(CommandLineTest, ModifyExisitingOption) {
cl::Option *Retrieved = Map["test-option"];
ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) <<
"Incorrect default option category.";
ASSERT_NE(Retrieved->Categories.end(),
find_if(Retrieved->Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &cl::GeneralCategory;
}))
<< "Incorrect default option category.";
Retrieved->setCategory(TestCategory);
ASSERT_EQ(&TestCategory,Retrieved->Category) <<
"Failed to modify option's option category.";
Retrieved->addCategory(TestCategory);
ASSERT_NE(Retrieved->Categories.end(),
find_if(Retrieved->Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &TestCategory;
}))
<< "Failed to modify option's option category.";
Retrieved->setDescription(Description);
ASSERT_STREQ(Retrieved->HelpStr.data(), Description)
@ -152,8 +160,52 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
TEST(CommandLineTest, UseOptionCategory) {
StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
"Category.";
ASSERT_NE(TestOption2.Categories.end(),
find_if(TestOption2.Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &TestCategory;
}))
<< "Failed to assign Option Category.";
}
TEST(CommandLineTest, UseMultipleCategories) {
StackOption<int> TestOption2("test-option2", cl::cat(TestCategory),
cl::cat(cl::GeneralCategory));
ASSERT_NE(TestOption2.Categories.end(),
find_if(TestOption2.Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &TestCategory;
}))
<< "Failed to assign Option Category.";
ASSERT_NE(TestOption2.Categories.end(),
find_if(TestOption2.Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &cl::GeneralCategory;
}))
<< "Failed to assign General Category.";
cl::OptionCategory AnotherCategory("Additional test Options", "Description");
StackOption<int> TestOption("test-option", cl::cat(TestCategory),
cl::cat(AnotherCategory));
ASSERT_EQ(TestOption.Categories.end(),
find_if(TestOption.Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &cl::GeneralCategory;
}))
<< "Failed to remove General Category.";
ASSERT_NE(TestOption.Categories.end(),
find_if(TestOption.Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &TestCategory;
}))
<< "Failed to assign Option Category.";
ASSERT_NE(TestOption.Categories.end(),
find_if(TestOption.Categories,
[&](const llvm::cl::OptionCategory *Cat) {
return Cat == &AnotherCategory;
}))
<< "Failed to assign Another Category.";
}
typedef void ParserFunction(StringRef Source, StringSaver &Saver,