Options: Add new option kind that consumes remaining arguments

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
This commit is contained in:
Hans Wennborg 2013-08-13 21:09:50 +00:00
parent 3f70e908c3
commit af9e355755
6 changed files with 47 additions and 0 deletions

View 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.

View 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!");

View 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:

View 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!");
}

View 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");
}

View 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>;