Loading llvm/docs/CommandLine.rst +51 −0 Original line number Diff line number Diff line Loading @@ -1267,6 +1267,57 @@ only consists of one function `cl::ParseCommandLineOptions`_) and three main classes: `cl::opt`_, `cl::list`_, and `cl::alias`_. This section describes these three classes in detail. .. _cl::getRegisteredOptions: The ``cl::getRegisteredOptions`` function ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``cl::getRegisteredOptions`` function is designed to give a programmer access to declared non positional command line options so that how they appear in ``-help`` can be modified prior to calling `cl::ParseCommandLineOptions`_. Note this method should not be called during any static initialisation because it cannot be guaranteed that all options will have been initialised. Hence it should be called from ``main``. This function can be used to gain access to options declared in libraries that the tool writter may not have direct access to. The function retrieves a :ref:`StringMap <dss_stringmap>` that maps the option string (e.g. ``-help``) to an ``Option*``. Here is an example of how the function could be used: .. code-block:: c++ using namespace llvm; int main(int argc, char **argv) { cl::OptionCategory AnotherCategory("Some options"); StringMap<cl::Option*> Map; cl::getRegisteredOptions(Map); //Unhide useful option and put it in a different category assert(Map.count("print-all-options") > 0); Map["print-all-options"]->setHiddenFlag(cl::NotHidden); Map["print-all-options"]->setCategory(AnotherCategory); //Hide an option we don't want to see assert(Map.count("enable-no-infs-fp-math") > 0); Map["enable-no-infs-fp-math"]->setHiddenFlag(cl::Hidden); //Change --version to --show-version assert(Map.count("version") > 0); Map["version"]->setArgStr("show-version"); //Change --help description assert(Map.count("help") > 0); Map["help"]->setDescription("Shows help"); cl::ParseCommandLineOptions(argc, argv, "This is a small program to demo the LLVM CommandLine API"); ... } .. _cl::ParseCommandLineOptions: The ``cl::ParseCommandLineOptions`` function Loading llvm/include/llvm/Support/CommandLine.h +34 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include <cassert> Loading Loading @@ -1713,6 +1714,39 @@ void PrintVersionMessage(); /// \param categorized if true print options in categories void PrintHelpMessage(bool Hidden=false, bool Categorized=false); //===----------------------------------------------------------------------===// // Public interface for accessing registered options. // /// \brief Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// /// \param [out] map will be filled with mappings where the key is the /// Option argument string (e.g. "help") and value is the corresponding /// Option*. /// /// Access to unnamed arguments (i.e. positional) are not provided because /// it is expected that the client already has access to these. /// /// Typical usage: /// \code /// main(int argc,char* argv[]) { /// StringMap<llvm::cl::Option*> opts; /// llvm::cl::getRegisteredOptions(opts); /// assert(opts.count("help") == 1) /// opts["help"]->setDescription("Show alphabetical help information") /// // More code /// llvm::cl::ParseCommandLineOptions(argc,argv); /// //More code /// } /// \endcode /// /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). void getRegisteredOptions(StringMap<Option*> &Map); } // End namespace cl } // End namespace llvm Loading llvm/lib/Support/CommandLine.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -1596,3 +1596,13 @@ void cl::AddExtraVersionPrinter(void (*func)()) { ExtraVersionPrinters->push_back(func); } void cl::getRegisteredOptions(StringMap<Option*> &Map) { // Get all the options. SmallVector<Option*, 4> PositionalOpts; //NOT USED SmallVector<Option*, 4> SinkOpts; //NOT USED assert(Map.size() == 0 && "StringMap must be empty"); GetOptionInfo(PositionalOpts, SinkOpts, Map); return; } llvm/unittests/Support/CommandLineTest.cpp +47 −3 Original line number Diff line number Diff line Loading @@ -41,6 +41,45 @@ class TempEnvVar { const char *const name; }; cl::OptionCategory TestCategory("Test Options", "Description"); cl::opt<int> TestOption("test-option", cl::desc("old description")); TEST(CommandLineTest, ModifyExisitingOption) { const char Description[] = "New description"; const char ArgString[] = "new-test-option"; const char ValueString[] = "Integer"; StringMap<cl::Option*> Map; cl::getRegisteredOptions(Map); ASSERT_TRUE(Map.count("test-option") == 1) << "Could not find option in map."; cl::Option *Retrieved = Map["test-option"]; ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option."; ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) << "Incorrect default option category."; Retrieved->setCategory(TestCategory); ASSERT_EQ(&TestCategory,Retrieved->Category) << "Failed to modify option's option category."; Retrieved->setDescription(Description); ASSERT_STREQ(Retrieved->HelpStr, Description) << "Changing option description failed."; Retrieved->setArgStr(ArgString); ASSERT_STREQ(ArgString, Retrieved->ArgStr) << "Failed to modify option's Argument string."; Retrieved->setValueStr(ValueString); ASSERT_STREQ(Retrieved->ValueStr, ValueString) << "Failed to modify option's Value string."; Retrieved->setHiddenFlag(cl::Hidden); ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) << "Failed to modify option's hidden flag."; } #ifndef SKIP_ENVIRONMENT_TESTS const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS"; Loading @@ -55,6 +94,12 @@ TEST(CommandLineTest, ParseEnvironment) { // This test used to make valgrind complain // ("Conditional jump or move depends on uninitialised value(s)") // // Warning: Do not run any tests after this one that try to gain access to // registered command line options because this will likely result in a // SEGFAULT. This can occur because the cl::opt in the test below is declared // on the stack which will be destroyed after the test completes but the // command line system will still hold a pointer to a deallocated cl::Option. TEST(CommandLineTest, ParseEnvironmentToLocalVar) { // Put cl::opt on stack to check for proper initialization of fields. cl::opt<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); Loading @@ -67,10 +112,9 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) { #endif // SKIP_ENVIRONMENT_TESTS TEST(CommandLineTest, UseOptionCategory) { cl::OptionCategory TestCategory("Test Options", "Description"); cl::opt<int> TestOption("test-option", cl::cat(TestCategory)); cl::opt<int> TestOption2("test-option", cl::cat(TestCategory)); ASSERT_EQ(&TestCategory,TestOption.Category) << "Failed to assign Option " ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option " "Category."; } Loading Loading
llvm/docs/CommandLine.rst +51 −0 Original line number Diff line number Diff line Loading @@ -1267,6 +1267,57 @@ only consists of one function `cl::ParseCommandLineOptions`_) and three main classes: `cl::opt`_, `cl::list`_, and `cl::alias`_. This section describes these three classes in detail. .. _cl::getRegisteredOptions: The ``cl::getRegisteredOptions`` function ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``cl::getRegisteredOptions`` function is designed to give a programmer access to declared non positional command line options so that how they appear in ``-help`` can be modified prior to calling `cl::ParseCommandLineOptions`_. Note this method should not be called during any static initialisation because it cannot be guaranteed that all options will have been initialised. Hence it should be called from ``main``. This function can be used to gain access to options declared in libraries that the tool writter may not have direct access to. The function retrieves a :ref:`StringMap <dss_stringmap>` that maps the option string (e.g. ``-help``) to an ``Option*``. Here is an example of how the function could be used: .. code-block:: c++ using namespace llvm; int main(int argc, char **argv) { cl::OptionCategory AnotherCategory("Some options"); StringMap<cl::Option*> Map; cl::getRegisteredOptions(Map); //Unhide useful option and put it in a different category assert(Map.count("print-all-options") > 0); Map["print-all-options"]->setHiddenFlag(cl::NotHidden); Map["print-all-options"]->setCategory(AnotherCategory); //Hide an option we don't want to see assert(Map.count("enable-no-infs-fp-math") > 0); Map["enable-no-infs-fp-math"]->setHiddenFlag(cl::Hidden); //Change --version to --show-version assert(Map.count("version") > 0); Map["version"]->setArgStr("show-version"); //Change --help description assert(Map.count("help") > 0); Map["help"]->setDescription("Shows help"); cl::ParseCommandLineOptions(argc, argv, "This is a small program to demo the LLVM CommandLine API"); ... } .. _cl::ParseCommandLineOptions: The ``cl::ParseCommandLineOptions`` function Loading
llvm/include/llvm/Support/CommandLine.h +34 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include <cassert> Loading Loading @@ -1713,6 +1714,39 @@ void PrintVersionMessage(); /// \param categorized if true print options in categories void PrintHelpMessage(bool Hidden=false, bool Categorized=false); //===----------------------------------------------------------------------===// // Public interface for accessing registered options. // /// \brief Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// /// \param [out] map will be filled with mappings where the key is the /// Option argument string (e.g. "help") and value is the corresponding /// Option*. /// /// Access to unnamed arguments (i.e. positional) are not provided because /// it is expected that the client already has access to these. /// /// Typical usage: /// \code /// main(int argc,char* argv[]) { /// StringMap<llvm::cl::Option*> opts; /// llvm::cl::getRegisteredOptions(opts); /// assert(opts.count("help") == 1) /// opts["help"]->setDescription("Show alphabetical help information") /// // More code /// llvm::cl::ParseCommandLineOptions(argc,argv); /// //More code /// } /// \endcode /// /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). void getRegisteredOptions(StringMap<Option*> &Map); } // End namespace cl } // End namespace llvm Loading
llvm/lib/Support/CommandLine.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -1596,3 +1596,13 @@ void cl::AddExtraVersionPrinter(void (*func)()) { ExtraVersionPrinters->push_back(func); } void cl::getRegisteredOptions(StringMap<Option*> &Map) { // Get all the options. SmallVector<Option*, 4> PositionalOpts; //NOT USED SmallVector<Option*, 4> SinkOpts; //NOT USED assert(Map.size() == 0 && "StringMap must be empty"); GetOptionInfo(PositionalOpts, SinkOpts, Map); return; }
llvm/unittests/Support/CommandLineTest.cpp +47 −3 Original line number Diff line number Diff line Loading @@ -41,6 +41,45 @@ class TempEnvVar { const char *const name; }; cl::OptionCategory TestCategory("Test Options", "Description"); cl::opt<int> TestOption("test-option", cl::desc("old description")); TEST(CommandLineTest, ModifyExisitingOption) { const char Description[] = "New description"; const char ArgString[] = "new-test-option"; const char ValueString[] = "Integer"; StringMap<cl::Option*> Map; cl::getRegisteredOptions(Map); ASSERT_TRUE(Map.count("test-option") == 1) << "Could not find option in map."; cl::Option *Retrieved = Map["test-option"]; ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option."; ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) << "Incorrect default option category."; Retrieved->setCategory(TestCategory); ASSERT_EQ(&TestCategory,Retrieved->Category) << "Failed to modify option's option category."; Retrieved->setDescription(Description); ASSERT_STREQ(Retrieved->HelpStr, Description) << "Changing option description failed."; Retrieved->setArgStr(ArgString); ASSERT_STREQ(ArgString, Retrieved->ArgStr) << "Failed to modify option's Argument string."; Retrieved->setValueStr(ValueString); ASSERT_STREQ(Retrieved->ValueStr, ValueString) << "Failed to modify option's Value string."; Retrieved->setHiddenFlag(cl::Hidden); ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) << "Failed to modify option's hidden flag."; } #ifndef SKIP_ENVIRONMENT_TESTS const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS"; Loading @@ -55,6 +94,12 @@ TEST(CommandLineTest, ParseEnvironment) { // This test used to make valgrind complain // ("Conditional jump or move depends on uninitialised value(s)") // // Warning: Do not run any tests after this one that try to gain access to // registered command line options because this will likely result in a // SEGFAULT. This can occur because the cl::opt in the test below is declared // on the stack which will be destroyed after the test completes but the // command line system will still hold a pointer to a deallocated cl::Option. TEST(CommandLineTest, ParseEnvironmentToLocalVar) { // Put cl::opt on stack to check for proper initialization of fields. cl::opt<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); Loading @@ -67,10 +112,9 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) { #endif // SKIP_ENVIRONMENT_TESTS TEST(CommandLineTest, UseOptionCategory) { cl::OptionCategory TestCategory("Test Options", "Description"); cl::opt<int> TestOption("test-option", cl::cat(TestCategory)); cl::opt<int> TestOption2("test-option", cl::cat(TestCategory)); ASSERT_EQ(&TestCategory,TestOption.Category) << "Failed to assign Option " ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option " "Category."; } Loading