Index: llvm/trunk/include/llvm/Option/OptParser.td =================================================================== --- llvm/trunk/include/llvm/Option/OptParser.td +++ llvm/trunk/include/llvm/Option/OptParser.td @@ -44,6 +44,8 @@ // 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: llvm/trunk/include/llvm/Option/Option.h =================================================================== --- llvm/trunk/include/llvm/Option/Option.h +++ llvm/trunk/include/llvm/Option/Option.h @@ -50,6 +50,7 @@ FlagClass, JoinedClass, SeparateClass, + RemainingArgsClass, CommaJoinedClass, MultiArgClass, JoinedOrSeparateClass, @@ -149,6 +150,7 @@ case SeparateClass: case MultiArgClass: case JoinedOrSeparateClass: + case RemainingArgsClass: return RenderSeparateStyle; } llvm_unreachable("Unexpected kind!"); Index: llvm/trunk/lib/Option/OptTable.cpp =================================================================== --- llvm/trunk/lib/Option/OptTable.cpp +++ llvm/trunk/lib/Option/OptTable.cpp @@ -259,6 +259,8 @@ 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 @@ break; case Option::SeparateClass: case Option::JoinedOrSeparateClass: + case Option::RemainingArgsClass: Name += ' '; // FALLTHROUGH case Option::JoinedClass: case Option::CommaJoinedClass: Index: llvm/trunk/lib/Option/Option.cpp =================================================================== --- llvm/trunk/lib/Option/Option.cpp +++ llvm/trunk/lib/Option/Option.cpp @@ -52,6 +52,7 @@ P(MultiArgClass); P(JoinedOrSeparateClass); P(JoinedAndSeparateClass); + P(RemainingArgsClass); #undef P } @@ -214,6 +215,16 @@ 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: llvm/trunk/unittests/Option/OptionParsingTest.cpp =================================================================== --- llvm/trunk/unittests/Option/OptionParsingTest.cpp +++ llvm/trunk/unittests/Option/OptionParsingTest.cpp @@ -169,3 +169,30 @@ 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 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 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: llvm/trunk/unittests/Option/Opts.td =================================================================== --- llvm/trunk/unittests/Option/Opts.td +++ llvm/trunk/unittests/Option/Opts.td @@ -22,3 +22,5 @@ def J : Flag<["-"], "J">, Alias, AliasArgs<["foo"]>; def Joo : Flag<["-"], "Joo">, Alias, AliasArgs<["bar"]>; + +def Slurp : Option<["-"], "slurp", KIND_REMAINING_ARGS>;