Options: Add new option kind that consumes remaining arguments
authorHans Wennborg <hans@hanshq.net>
Tue, 13 Aug 2013 21:09:50 +0000 (21:09 +0000)
committerHans Wennborg <hans@hanshq.net>
Tue, 13 Aug 2013 21:09:50 +0000 (21:09 +0000)
This adds KIND_REMAINING_ARGS, a class of options that consume
all remaining arguments on the command line.

This will be used to support /link in clang-cl, which is used
to forward all remaining arguments to the linker.

It also allows us to remove the hard-coded handling of "--",
allowing clients (clang and lld) to implement that functionality
themselves with this new option class.

Differential Revision: http://llvm-reviews.chandlerc.com/D1387

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188314 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Option/OptParser.td
include/llvm/Option/Option.h
lib/Option/OptTable.cpp
lib/Option/Option.cpp
unittests/Option/OptionParsingTest.cpp
unittests/Option/Opts.td

index 32cc2c0cd5b2eda128582fb667d9511c6e684c35..963389f0bc6fdc86e35d5c93d2c522d8d7e5f00f 100644 (file)
@@ -44,6 +44,8 @@ def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">;
 // An option which is both joined to its (first) value, and followed by its
 // (second) value.
 def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">;
+// An option which consumes all remaining arguments if there are any.
+def KIND_REMAINING_ARGS : OptionKind<"RemainingArgs">;
 
 // Define the option flags.
 
index 47fd8174c5a19b53d3077557883be45584f724d6..03d4774829fbc618523eebe90cdf4a25ca613727 100644 (file)
@@ -50,6 +50,7 @@ public:
     FlagClass,
     JoinedClass,
     SeparateClass,
+    RemainingArgsClass,
     CommaJoinedClass,
     MultiArgClass,
     JoinedOrSeparateClass,
@@ -149,6 +150,7 @@ public:
     case SeparateClass:
     case MultiArgClass:
     case JoinedOrSeparateClass:
+    case RemainingArgsClass:
       return RenderSeparateStyle;
     }
     llvm_unreachable("Unexpected kind!");
index 98e63bc2de9e7c0bcd9e7ac2bf28880eabd7f6f8..650aec8a678644e06cad353f1dab4bdec3064ce4 100644 (file)
@@ -259,6 +259,8 @@ InputArgList *OptTable::ParseArgs(const char *const *ArgBegin,
       continue;
     }
 
+    // FIXME: Remove once clients are updated to use a KIND_REMAINING_ARGS
+    // option to handle this explicitly instead.
     if (Str == "--") {
       // Everything after -- is a filename.
       ++Index;
@@ -308,6 +310,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
     break;
 
   case Option::SeparateClass: case Option::JoinedOrSeparateClass:
+  case Option::RemainingArgsClass:
     Name += ' ';
     // FALLTHROUGH
   case Option::JoinedClass: case Option::CommaJoinedClass:
index 1d6a3d38040e9081b7d0cf95a5281dee4297422c..7b5ff2be9a7926c8c07927499afda479ffc66e37 100644 (file)
@@ -52,6 +52,7 @@ void Option::dump() const {
     P(MultiArgClass);
     P(JoinedOrSeparateClass);
     P(JoinedAndSeparateClass);
+    P(RemainingArgsClass);
 #undef P
   }
 
@@ -214,6 +215,16 @@ Arg *Option::accept(const ArgList &Args,
     return new Arg(UnaliasedOption, Spelling, Index - 2,
                    Args.getArgString(Index - 2) + ArgSize,
                    Args.getArgString(Index - 1));
+  case RemainingArgsClass: {
+    // Matches iff this is an exact match.
+    // FIXME: Avoid strlen.
+    if (ArgSize != strlen(Args.getArgString(Index)))
+      return 0;
+    Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
+    while (Index < Args.getNumInputArgStrings())
+      A->getValues().push_back(Args.getArgString(Index++));
+    return A;
+  }
   default:
     llvm_unreachable("Invalid option kind!");
   }
index 5a76d65d0fa382d342aa1b6da27cb651cc05eb8a..4a7b7b1106dde9c4d747ec9f72961f574c4404fb 100644 (file)
@@ -169,3 +169,30 @@ TEST(Option, DashDash) {
   EXPECT_EQ(AL->getAllArgValues(OPT_INPUT)[0], "-B");
   EXPECT_EQ(AL->getAllArgValues(OPT_INPUT)[1], "--");
 }
+
+TEST(Option, SlurpEmpty) {
+  TestOptTable T;
+  unsigned MAI, MAC;
+
+  const char *MyArgs[] = { "-A", "-slurp" };
+  OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+  EXPECT_TRUE(AL->hasArg(OPT_A));
+  EXPECT_TRUE(AL->hasArg(OPT_Slurp));
+  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0);
+}
+
+TEST(Option, Slurp) {
+  TestOptTable T;
+  unsigned MAI, MAC;
+
+  const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
+  OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+  EXPECT_EQ(AL->size(), 2U);
+  EXPECT_TRUE(AL->hasArg(OPT_A));
+  EXPECT_FALSE(AL->hasArg(OPT_B));
+  EXPECT_TRUE(AL->hasArg(OPT_Slurp));
+  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 3U);
+  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[0], "-B");
+  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[1], "--");
+  EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[2], "foo");
+}
index 986b3122af71f7bca3ca47f722650c226d5e5650..aaed6b2101e00311c4ec8bdb39fec68b57d025f9 100644 (file)
@@ -22,3 +22,5 @@ def I : Flag<["-"], "I">, Alias<H>, Group<my_group>;
 
 def J : Flag<["-"], "J">, Alias<B>, AliasArgs<["foo"]>;
 def Joo : Flag<["-"], "Joo">, Alias<B>, AliasArgs<["bar"]>;
+
+def Slurp : Option<["-"], "slurp", KIND_REMAINING_ARGS>;