[llvm] r364141 - Revert [CommandLine] Remove OptionCategory and SubCommand caches from the Option class.

Don Hinton via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 22 16:32:36 PDT 2019


Author: dhinton
Date: Sat Jun 22 16:32:36 2019
New Revision: 364141

URL: http://llvm.org/viewvc/llvm-project?rev=364141&view=rev
Log:
Revert [CommandLine] Remove OptionCategory and SubCommand caches from the Option class.

This reverts r364134 (git commit a5b83bc9e3b8e8945b55068c762bd6c73621a4b0)

Caused errors in the asan bot, so the GeneralCategory global needs to
be changed to ManagedStatic.

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

Modified:
    llvm/trunk/include/llvm/Support/CommandLine.h
    llvm/trunk/lib/Support/CommandLine.cpp
    llvm/trunk/unittests/Support/CommandLineTest.cpp

Modified: llvm/trunk/include/llvm/Support/CommandLine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CommandLine.h?rev=364141&r1=364140&r2=364141&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/CommandLine.h (original)
+++ llvm/trunk/include/llvm/Support/CommandLine.h Sat Jun 22 16:32:36 2019
@@ -201,8 +201,6 @@ public:
 
   StringRef getName() const { return Name; }
   StringRef getDescription() const { return Description; }
-
-  SmallPtrSet<Option *, 16> MemberOptions;
 };
 
 // The general Option Category (used as default category).
@@ -285,12 +283,9 @@ 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
-
-  // Return the set of OptionCategories that this Option belongs to.
-  SmallPtrSet<OptionCategory *, 1> getCategories() const;
-
-  // Return the set of SubCommands that this Option belongs to.
-  SmallPtrSet<SubCommand *, 1> getSubCommands() const;
+  SmallVector<OptionCategory *, 1>
+      Categories;                    // The Categories this option belongs to
+  SmallPtrSet<SubCommand *, 1> Subs; // The subcommands this option belongs to.
 
   inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
     return (enum NumOccurrencesFlag)Occurrences;
@@ -322,6 +317,12 @@ public:
     return getNumOccurrencesFlag() == cl::ConsumeAfter;
   }
 
+  bool isInAllSubCommands() const {
+    return any_of(Subs, [](const SubCommand *SC) {
+      return SC == &*AllSubCommands;
+    });
+  }
+
   //-------------------------------------------------------------------------===
   // Accessor functions set by OptionModifiers
   //
@@ -335,13 +336,16 @@ public:
   void setMiscFlag(enum MiscFlags M) { Misc |= M; }
   void setPosition(unsigned pos) { Position = pos; }
   void addCategory(OptionCategory &C);
+  void addSubCommand(SubCommand &S) { Subs.insert(&S); }
 
 protected:
   explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
                   enum OptionHidden Hidden)
       : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
         HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0),
-        FullyInitialized(false), Position(0), AdditionalVals(0) {}
+        FullyInitialized(false), Position(0), AdditionalVals(0) {
+    Categories.push_back(&GeneralCategory);
+  }
 
   inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
 
@@ -350,14 +354,7 @@ public:
 
   // addArgument - Register this argument with the commandline system.
   //
-  virtual void addArgument(SubCommand &SC);
-
-  // addArgument - Only called in done() method to add default
-  // TopLevelSubCommand.
-  void addArgument() {
-    if (!FullyInitialized)
-      addArgument(*TopLevelSubCommand);
-  }
+  void addArgument();
 
   /// Unregisters this option from the CommandLine system.
   ///
@@ -468,7 +465,7 @@ struct sub {
 
   sub(SubCommand &S) : Sub(S) {}
 
-  template <class Opt> void apply(Opt &O) const { O.addArgument(Sub); }
+  template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
 };
 
 //===----------------------------------------------------------------------===//
@@ -1775,10 +1772,11 @@ class alias : public Option {
       error("cl::alias must have argument name specified!");
     if (!AliasFor)
       error("cl::alias must have an cl::aliasopt(option) specified!");
-    for(OptionCategory *Cat: AliasFor->getCategories())
-      addCategory(*Cat);
-    for(SubCommand *SC: AliasFor->getSubCommands())
-      Option::addArgument(*SC);
+    if (!Subs.empty())
+      error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
+    Subs = AliasFor->Subs;
+    Categories = AliasFor->Categories;
+    addArgument();
   }
 
 public:
@@ -1792,10 +1790,6 @@ public:
     AliasFor = &O;
   }
 
-  // Does nothing when called via apply.  Aliases call Option::addArgument
-  // directly in the done() method to actually add the option..
-  void addArgument(SubCommand &SC) override {}
-
   template <class... Mods>
   explicit alias(const Mods &... Ms)
       : Option(Optional, Hidden), AliasFor(nullptr) {

Modified: llvm/trunk/lib/Support/CommandLine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CommandLine.cpp?rev=364141&r1=364140&r2=364141&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CommandLine.cpp (original)
+++ llvm/trunk/lib/Support/CommandLine.cpp Sat Jun 22 16:32:36 2019
@@ -142,7 +142,7 @@ public:
   // This collects Options added with the cl::DefaultOption flag. Since they can
   // be overridden, they are not added to the appropriate SubCommands until
   // ParseCommandLineOptions actually runs.
-  SmallVector<std::pair<Option*, SubCommand*>, 4> DefaultOptions;
+  SmallVector<Option*, 4> DefaultOptions;
 
   // This collects the different option categories that have been registered.
   SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
@@ -182,16 +182,15 @@ public:
   }
 
   void addLiteralOption(Option &Opt, StringRef Name) {
-    for(SubCommand *SC: Opt.getSubCommands())
-      addLiteralOption(Opt, SC, Name);
-  }
-
-  void addOption(Option *O, SubCommand *SC, bool ProcessDefaultOptions = false) {
-    if (!ProcessDefaultOptions && O->isDefaultOption()) {
-      DefaultOptions.push_back(std::make_pair(O, SC));
-      return;
+    if (Opt.Subs.empty())
+      addLiteralOption(Opt, &*TopLevelSubCommand, Name);
+    else {
+      for (auto SC : Opt.Subs)
+        addLiteralOption(Opt, SC, Name);
     }
+  }
 
+  void addOption(Option *O, SubCommand *SC) {
     bool HadErrors = false;
     if (O->hasArgStr()) {
       // If it's a DefaultOption, check to make sure it isn't already there.
@@ -233,14 +232,22 @@ public:
       for (const auto &Sub : RegisteredSubCommands) {
         if (SC == Sub)
           continue;
-        addOption(O, Sub, ProcessDefaultOptions);
+        addOption(O, Sub);
       }
     }
   }
 
-  void addDefaultOptions() {
-    for (std::pair<Option *, SubCommand *> &DO : DefaultOptions) {
-      addOption(DO.first, DO.second, true);
+  void addOption(Option *O, bool ProcessDefaultOption = false) {
+    if (!ProcessDefaultOption && O->isDefaultOption()) {
+      DefaultOptions.push_back(O);
+      return;
+    }
+
+    if (O->Subs.empty()) {
+      addOption(O, &*TopLevelSubCommand);
+    } else {
+      for (auto SC : O->Subs)
+        addOption(O, SC);
     }
   }
 
@@ -278,8 +285,17 @@ public:
   }
 
   void removeOption(Option *O) {
-    for (auto SC : RegisteredSubCommands)
-      removeOption(O, SC);
+    if (O->Subs.empty())
+      removeOption(O, &*TopLevelSubCommand);
+    else {
+      if (O->isInAllSubCommands()) {
+        for (auto SC : RegisteredSubCommands)
+          removeOption(O, SC);
+      } else {
+        for (auto SC : O->Subs)
+          removeOption(O, SC);
+      }
+    }
   }
 
   bool hasOptions(const SubCommand &Sub) const {
@@ -308,8 +324,17 @@ public:
   }
 
   void updateArgStr(Option *O, StringRef NewName) {
-    for (auto SC : RegisteredSubCommands)
-      updateArgStr(O, NewName, SC);
+    if (O->Subs.empty())
+      updateArgStr(O, NewName, &*TopLevelSubCommand);
+    else {
+      if (O->isInAllSubCommands()) {
+        for (auto SC : RegisteredSubCommands)
+          updateArgStr(O, NewName, SC);
+      } else {
+        for (auto SC : O->Subs)
+          updateArgStr(O, NewName, SC);
+      }
+    }
   }
 
   void printOptionValues();
@@ -402,38 +427,13 @@ extrahelp::extrahelp(StringRef Help) : m
   GlobalParser->MoreHelp.push_back(Help);
 }
 
-void Option::addArgument(SubCommand &SC) {
-  GlobalParser->addOption(this, &SC);
+void Option::addArgument() {
+  GlobalParser->addOption(this);
   FullyInitialized = true;
 }
 
 void Option::removeArgument() { GlobalParser->removeOption(this); }
 
-SmallPtrSet<OptionCategory *, 1> Option::getCategories() const {
-  SmallPtrSet<OptionCategory *, 1> Cats;
-  for (OptionCategory *C: GlobalParser->RegisteredOptionCategories) {
-    if (C->MemberOptions.find(this) != C->MemberOptions.end())
-      Cats.insert(C);
-  }
-  if (Cats.empty())
-    Cats.insert(&GeneralCategory);
-  return Cats;
-}
-
-SmallPtrSet<SubCommand *, 1> Option::getSubCommands() const {
-  // This can happen for enums and literal options.
-  if (ArgStr.empty())
-    return SmallPtrSet<SubCommand *, 1>{&*TopLevelSubCommand};
-
-  SmallPtrSet<SubCommand *, 1> Subs;
-  for (SubCommand *SC : GlobalParser->getRegisteredSubcommands()) {
-    auto I = SC->OptionsMap.find(ArgStr);
-    if (I != SC->OptionsMap.end() && I->getValue() == this)
-      Subs.insert(SC);
-  }
-  return Subs;
-}
-
 void Option::setArgStr(StringRef S) {
   if (FullyInitialized)
     GlobalParser->updateArgStr(this, S);
@@ -444,7 +444,14 @@ void Option::setArgStr(StringRef S) {
 }
 
 void Option::addCategory(OptionCategory &C) {
-  C.MemberOptions.insert(this);
+  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 if (find(Categories, &C) == Categories.end())
+    Categories.push_back(&C);
 }
 
 void Option::reset() {
@@ -1295,7 +1302,9 @@ bool CommandLineParser::ParseCommandLine
   auto &SinkOpts = ChosenSubCommand->SinkOpts;
   auto &OptionsMap = ChosenSubCommand->OptionsMap;
 
-  addDefaultOptions();
+  for (auto O: DefaultOptions) {
+    addOption(O, true);
+  }
 
   if (ConsumeAfterOpt) {
     assert(PositionalOpts.size() > 0 &&
@@ -2195,7 +2204,7 @@ 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;
-      for (auto *Cat : Opt->getCategories()) {
+      for (auto &Cat : Opt->Categories) {
         assert(CategorizedOptions.count(Cat) > 0 &&
                "Option has an unregistered category");
         CategorizedOptions[Cat].push_back(Opt);
@@ -2456,7 +2465,7 @@ cl::getRegisteredSubcommands() {
 
 void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
   for (auto &I : Sub.OptionsMap) {
-    for (OptionCategory *Cat : I.second->getCategories()) {
+    for (auto &Cat : I.second->Categories) {
       if (Cat != &Category &&
           Cat != &GenericCategory)
         I.second->setHiddenFlag(cl::ReallyHidden);
@@ -2467,7 +2476,7 @@ void cl::HideUnrelatedOptions(cl::Option
 void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
                               SubCommand &Sub) {
   for (auto &I : Sub.OptionsMap) {
-    for (OptionCategory *Cat : I.second->getCategories()) {
+    for (auto &Cat : I.second->Categories) {
       if (find(Categories, Cat) == Categories.end() && Cat != &GenericCategory)
         I.second->setHiddenFlag(cl::ReallyHidden);
     }

Modified: llvm/trunk/unittests/Support/CommandLineTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CommandLineTest.cpp?rev=364141&r1=364140&r2=364141&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/CommandLineTest.cpp (original)
+++ llvm/trunk/unittests/Support/CommandLineTest.cpp Sat Jun 22 16:32:36 2019
@@ -95,16 +95,16 @@ TEST(CommandLineTest, ModifyExisitingOpt
   cl::Option *Retrieved = Map["test-option"];
   ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
 
-  ASSERT_NE(Retrieved->getCategories().end(),
-            find_if(Retrieved->getCategories(),
+  ASSERT_NE(Retrieved->Categories.end(),
+            find_if(Retrieved->Categories,
                     [&](const llvm::cl::OptionCategory *Cat) {
                       return Cat == &cl::GeneralCategory;
                     }))
       << "Incorrect default option category.";
 
   Retrieved->addCategory(TestCategory);
-  ASSERT_NE(Retrieved->getCategories().end(),
-            find_if(Retrieved->getCategories(),
+  ASSERT_NE(Retrieved->Categories.end(),
+            find_if(Retrieved->Categories,
                     [&](const llvm::cl::OptionCategory *Cat) {
                       return Cat == &TestCategory;
                     }))
@@ -160,8 +160,8 @@ TEST(CommandLineTest, ParseEnvironmentTo
 TEST(CommandLineTest, UseOptionCategory) {
   StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
 
-  ASSERT_NE(TestOption2.getCategories().end(),
-            find_if(TestOption2.getCategories(),
+  ASSERT_NE(TestOption2.Categories.end(),
+            find_if(TestOption2.Categories,
                          [&](const llvm::cl::OptionCategory *Cat) {
                            return Cat == &TestCategory;
                          }))
@@ -172,19 +172,18 @@ TEST(CommandLineTest, UseMultipleCategor
   StackOption<int> TestOption2("test-option2", cl::cat(TestCategory),
                                cl::cat(cl::GeneralCategory),
                                cl::cat(cl::GeneralCategory));
-  auto TestOption2Categories = TestOption2.getCategories();
 
   // Make sure cl::GeneralCategory wasn't added twice.
-  ASSERT_EQ(TestOption2Categories.size(), 2U);
+  ASSERT_EQ(TestOption2.Categories.size(), 2U);
 
-  ASSERT_NE(TestOption2Categories.end(),
-            find_if(TestOption2Categories,
+  ASSERT_NE(TestOption2.Categories.end(),
+            find_if(TestOption2.Categories,
                          [&](const llvm::cl::OptionCategory *Cat) {
                            return Cat == &TestCategory;
                          }))
       << "Failed to assign Option Category.";
-  ASSERT_NE(TestOption2Categories.end(),
-            find_if(TestOption2Categories,
+  ASSERT_NE(TestOption2.Categories.end(),
+            find_if(TestOption2.Categories,
                          [&](const llvm::cl::OptionCategory *Cat) {
                            return Cat == &cl::GeneralCategory;
                          }))
@@ -193,21 +192,20 @@ TEST(CommandLineTest, UseMultipleCategor
   cl::OptionCategory AnotherCategory("Additional test Options", "Description");
   StackOption<int> TestOption("test-option", cl::cat(TestCategory),
                               cl::cat(AnotherCategory));
-  auto TestOptionCategories = TestOption.getCategories();
-  ASSERT_EQ(TestOptionCategories.end(),
-            find_if(TestOptionCategories,
+  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(TestOptionCategories.end(),
-            find_if(TestOptionCategories,
+  ASSERT_NE(TestOption.Categories.end(),
+            find_if(TestOption.Categories,
                          [&](const llvm::cl::OptionCategory *Cat) {
                            return Cat == &TestCategory;
                          }))
       << "Failed to assign Option Category.";
-  ASSERT_NE(TestOptionCategories.end(),
-            find_if(TestOptionCategories,
+  ASSERT_NE(TestOption.Categories.end(),
+            find_if(TestOption.Categories,
                          [&](const llvm::cl::OptionCategory *Cat) {
                            return Cat == &AnotherCategory;
                          }))
@@ -380,30 +378,6 @@ TEST(CommandLineTest, AliasRequired) {
   testAliasRequired(array_lengthof(opts2), opts2);
 }
 
-TEST(CommandLineTest, AliasWithSubCommand) {
-  StackSubCommand SC1("sc1", "Subcommand 1");
-  StackOption<std::string> Option1("option", cl::value_desc("output file"),
-                                   cl::init("-"), cl::desc("Option"),
-                                   cl::sub(SC1));
-  StackOption<std::string, cl::alias> Alias1("o", llvm::cl::aliasopt(Option1),
-                                             cl::desc("Alias for --option"),
-                                             cl::sub(SC1));
-}
-
-TEST(CommandLineTest, AliasWithMultipleSubCommandsWithSameOption) {
-  StackSubCommand SC1("sc1", "Subcommand 1");
-  StackOption<std::string> Option1("option", cl::value_desc("output file"),
-                                   cl::init("-"), cl::desc("Option"),
-                                   cl::sub(SC1));
-  StackSubCommand SC2("sc2", "Subcommand 2");
-  StackOption<std::string> Option2("option", cl::value_desc("output file"),
-                                   cl::init("-"), cl::desc("Option"),
-                                   cl::sub(SC2));
-
-  StackOption<std::string, cl::alias> Alias1("o", llvm::cl::aliasopt(Option1),
-                                             cl::desc("Alias for --option"));
-}
-
 TEST(CommandLineTest, HideUnrelatedOptions) {
   StackOption<int> TestOption1("hide-option-1");
   StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory));




More information about the llvm-commits mailing list