<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Sep 12, 2016 at 6:57 PM Dean Michael Berris <<a href="mailto:dberris@google.com">dberris@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">dberris created this revision.<br class="gmail_msg">
dberris added reviewers: zturner, dblaikie, echristo.<br class="gmail_msg">
dberris added a subscriber: llvm-commits.<br class="gmail_msg">
Herald added a subscriber: mehdi_amini.<br class="gmail_msg">
<br class="gmail_msg">
This should allow users of the library to get a range to iterate through<br class="gmail_msg">
all the subcommands that are registered to the global parser. This<br class="gmail_msg">
allows users to define subcommands in libraries that self-register to<br class="gmail_msg">
have dispatch done at a different stage (like main). It allows for<br class="gmail_msg">
writing code like the following:<br class="gmail_msg">
<br class="gmail_msg">
    for (auto *S : cl::getRegisteredSubcommands()) {<br class="gmail_msg">
      if (*S) {<br class="gmail_msg">
        // Dispatch on S->getName().<br class="gmail_msg">
      }<br class="gmail_msg">
    }<br class="gmail_msg"></blockquote><div><br>FWIW: I wasn't expecting/suggesting we should have to compare by strings (stringly typed isn't ideal, of course) - I was hoping/figuring we could declaer the subcommand in the header (along with the single entry point function) and then define it over in the file that defines the single entry point along with the subcommand's flags.<br><br>Did this not work for some reason?<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br class="gmail_msg">
This change also contains tests that show this usage pattern.<br class="gmail_msg">
<br class="gmail_msg">
<a href="https://reviews.llvm.org/D24489" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D24489</a><br class="gmail_msg">
<br class="gmail_msg">
Files:<br class="gmail_msg">
  include/llvm/Support/CommandLine.h<br class="gmail_msg">
  lib/Support/CommandLine.cpp<br class="gmail_msg">
  unittests/Support/CommandLineTest.cpp<br class="gmail_msg">
<br class="gmail_msg">
Index: unittests/Support/CommandLineTest.cpp<br class="gmail_msg">
===================================================================<br class="gmail_msg">
--- unittests/Support/CommandLineTest.cpp<br class="gmail_msg">
+++ unittests/Support/CommandLineTest.cpp<br class="gmail_msg">
@@ -476,4 +476,26 @@<br class="gmail_msg">
   EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, nullptr, true));<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
+TEST(CommandLineTest, GetRegisteredSubcommands) {<br class="gmail_msg">
+  cl::ResetCommandLineParser();<br class="gmail_msg">
+<br class="gmail_msg">
+  StackSubCommand SC1("sc1", "First Subcommand");<br class="gmail_msg">
+  StackSubCommand SC2("sc2", "Second subcommand");<br class="gmail_msg">
+<br class="gmail_msg">
+  const char *args0[] = {"prog", "sc1"};<br class="gmail_msg">
+  const char *args1[] = {"prog", "sc2"};<br class="gmail_msg">
+<br class="gmail_msg">
+  EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, nullptr, true));<br class="gmail_msg">
+  for (auto* S : cl::getRegisteredSubcommands()) {<br class="gmail_msg">
+    if (*S) EXPECT_STREQ("sc1", S->getName());<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  cl::ResetAllOptionOccurrences();<br class="gmail_msg">
+  EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1, nullptr, true));<br class="gmail_msg">
+  for (auto* S : cl::getRegisteredSubcommands()) {<br class="gmail_msg">
+    if (*S) EXPECT_STREQ("sc2", S->getName());<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
 }  // anonymous namespace<br class="gmail_msg">
Index: lib/Support/CommandLine.cpp<br class="gmail_msg">
===================================================================<br class="gmail_msg">
--- lib/Support/CommandLine.cpp<br class="gmail_msg">
+++ lib/Support/CommandLine.cpp<br class="gmail_msg">
@@ -309,6 +309,12 @@<br class="gmail_msg">
     RegisteredSubCommands.erase(sub);<br class="gmail_msg">
   }<br class="gmail_msg">
<br class="gmail_msg">
+  iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator><br class="gmail_msg">
+  getRegisteredSubcommands() {<br class="gmail_msg">
+    return make_range(RegisteredSubCommands.begin(),<br class="gmail_msg">
+                      RegisteredSubCommands.end());<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
   void reset() {<br class="gmail_msg">
     ActiveSubCommand = nullptr;<br class="gmail_msg">
     ProgramName.clear();<br class="gmail_msg">
@@ -2105,6 +2111,11 @@<br class="gmail_msg">
   return Sub.OptionsMap;<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
+iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator><br class="gmail_msg">
+cl::getRegisteredSubcommands() {<br class="gmail_msg">
+  return GlobalParser->getRegisteredSubcommands();<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
 void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {<br class="gmail_msg">
   for (auto &I : Sub.OptionsMap) {<br class="gmail_msg">
     if (I.second->Category != &Category &&<br class="gmail_msg">
Index: include/llvm/Support/CommandLine.h<br class="gmail_msg">
===================================================================<br class="gmail_msg">
--- include/llvm/Support/CommandLine.h<br class="gmail_msg">
+++ include/llvm/Support/CommandLine.h<br class="gmail_msg">
@@ -1736,6 +1736,28 @@<br class="gmail_msg">
 /// than just handing around a global list.<br class="gmail_msg">
 StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand);<br class="gmail_msg">
<br class="gmail_msg">
+/// \brief Use this to get all registered SubCommands from the provided parser.<br class="gmail_msg">
+///<br class="gmail_msg">
+/// \return A range of all SubCommand pointers registered with the parser.<br class="gmail_msg">
+///<br class="gmail_msg">
+/// Typical usage:<br class="gmail_msg">
+/// \code<br class="gmail_msg">
+/// main(int argc, char* argv[]) {<br class="gmail_msg">
+///   llvm::cl::ParseCommandLineOptions(argc, argv);<br class="gmail_msg">
+///   for (auto* S : llvm::cl::getRegisteredSubcommands()) {<br class="gmail_msg">
+///     if (*S) {<br class="gmail_msg">
+///       std::cout << "Executing subcommand: " << S->getName() << std::endl;<br class="gmail_msg">
+///       // Execute some function based on the name...<br class="gmail_msg">
+///     }<br class="gmail_msg">
+///   }<br class="gmail_msg">
+/// }<br class="gmail_msg">
+/// \endcode<br class="gmail_msg">
+///<br class="gmail_msg">
+/// This interface is useful for defining subcommands in libraries and<br class="gmail_msg">
+/// the dispatch from a single point (like in the main function).<br class="gmail_msg">
+iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator><br class="gmail_msg">
+getRegisteredSubcommands();<br class="gmail_msg">
+<br class="gmail_msg">
 //===----------------------------------------------------------------------===//<br class="gmail_msg">
 // Standalone command line processing utilities.<br class="gmail_msg">
 //<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
</blockquote></div></div>