summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2014-01-29 18:54:17 +0000
committerJordan Rose <jordan_rose@apple.com>2014-01-29 18:54:17 +0000
commitc2d631000d6018e8cd1734544d6c9980c6da5222 (patch)
tree2c0e4f5b571fca92adf68d051c94976bec915443
parentb492843e53dbc86a34bbddc4c8155f3d23e21185 (diff)
downloadllvm-c2d631000d6018e8cd1734544d6c9980c6da5222.tar.gz
llvm-c2d631000d6018e8cd1734544d6c9980c6da5222.tar.bz2
llvm-c2d631000d6018e8cd1734544d6c9980c6da5222.tar.xz
[CommandLine] Aliases require an value if their target requires a value.
This can still be overridden by explicitly setting a value requirement on the alias option, but by default it should be the same. PR18649 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200407 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Support/CommandLine.h10
-rw-r--r--lib/Support/CommandLine.cpp7
-rw-r--r--unittests/Support/CommandLineTest.cpp55
3 files changed, 70 insertions, 2 deletions
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index 774c214933..515b0bd00f 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -249,6 +249,12 @@ public:
//
void addArgument();
+ /// Unregisters this option from the CommandLine system.
+ ///
+ /// This option must have been the last option registered.
+ /// For testing purposes only.
+ void removeArgument();
+
Option *getNextRegisteredOption() const { return NextRegistered; }
// Return the width of the option tag for printing...
@@ -1646,6 +1652,10 @@ class alias : public Option {
virtual void printOptionValue(size_t /*GlobalWidth*/,
bool /*Force*/) const LLVM_OVERRIDE {}
+ virtual ValueExpected getValueExpectedFlagDefault() const LLVM_OVERRIDE {
+ return AliasFor->getValueExpectedFlag();
+ }
+
void done() {
if (!hasArgStr())
error("cl::alias must have argument name specified!");
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 1b4d2c7287..16db4d6396 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -111,6 +111,13 @@ void Option::addArgument() {
MarkOptionsChanged();
}
+void Option::removeArgument() {
+ assert(NextRegistered != 0 && "argument never registered");
+ assert(RegisteredOptionList == this && "argument is not the last registered");
+ RegisteredOptionList = NextRegistered;
+ MarkOptionsChanged();
+}
+
// This collects the different option categories that have been registered.
typedef SmallPtrSet<OptionCategory*,16> OptionCatSet;
static ManagedStatic<OptionCatSet> RegisteredOptionCategories;
diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp
index a132eadad0..e1d1fa59e5 100644
--- a/unittests/Support/CommandLineTest.cpp
+++ b/unittests/Support/CommandLineTest.cpp
@@ -42,6 +42,33 @@ class TempEnvVar {
const char *const name;
};
+template <typename T>
+class StackOption : public cl::opt<T> {
+ using Base = cl::opt<T>;
+public:
+ // One option...
+ template<class M0t>
+ explicit StackOption(const M0t &M0) : Base(M0) {}
+
+ // Two options...
+ template<class M0t, class M1t>
+ StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {}
+
+ // Three options...
+ template<class M0t, class M1t, class M2t>
+ StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {}
+
+ // Four options...
+ template<class M0t, class M1t, class M2t, class M3t>
+ StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
+ : Base(M0, M1, M2, M3) {}
+
+ ~StackOption() {
+ this->removeArgument();
+ }
+};
+
+
cl::OptionCategory TestCategory("Test Options", "Description");
cl::opt<int> TestOption("test-option", cl::desc("old description"));
TEST(CommandLineTest, ModifyExisitingOption) {
@@ -103,7 +130,7 @@ TEST(CommandLineTest, ParseEnvironment) {
// 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");
+ StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local");
TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local");
EXPECT_EQ("", EnvironmentTestOptionLocal);
cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
@@ -113,7 +140,7 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
#endif // SKIP_ENVIRONMENT_TESTS
TEST(CommandLineTest, UseOptionCategory) {
- cl::opt<int> TestOption2("test-option", cl::cat(TestCategory));
+ StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
"Category.";
@@ -161,4 +188,28 @@ TEST(CommandLineTest, TokenizeWindowsCommandLine) {
array_lengthof(Output));
}
+TEST(CommandLineTest, AliasesWithArguments) {
+ static const size_t ARGC = 3;
+ const char *const Inputs[][ARGC] = {
+ { "-tool", "-actual=x", "-extra" },
+ { "-tool", "-actual", "x" },
+ { "-tool", "-alias=x", "-extra" },
+ { "-tool", "-alias", "x" }
+ };
+
+ for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) {
+ StackOption<std::string> Actual("actual");
+ StackOption<bool> Extra("extra");
+ StackOption<std::string> Input(cl::Positional);
+
+ cl::alias Alias("alias", llvm::cl::aliasopt(Actual));
+
+ cl::ParseCommandLineOptions(ARGC, Inputs[i]);
+ EXPECT_EQ("x", Actual);
+ EXPECT_EQ(0, Input.getNumOccurrences());
+
+ Alias.removeArgument();
+ }
+}
+
} // anonymous namespace