mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 12:50:00 +00:00
Implemented public interface for modifying registered (not positional or sink options) command line options at runtime.
Patch by Dan Liew! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b7ad33b719
commit
61e0172197
@ -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
|
||||
|
@ -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>
|
||||
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
||||
@ -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");
|
||||
@ -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…
Reference in New Issue
Block a user