[llvm] r187537 - Option parsing: add support for alias arguments.

Michael Gottesman mgottesman at apple.com
Thu Aug 1 18:26:35 PDT 2013


This breaks the phase 1 llvmlab bot.

Can you fix or revert?

http://lab.llvm.org:8013/builders/phase1%20-%20sanity/builds/9735

Michael

On Jul 31, 2013, at 3:44 PM, Hans Wennborg <hans at hanshq.net> wrote:

> Author: hans
> Date: Wed Jul 31 17:44:41 2013
> New Revision: 187537
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=187537&view=rev
> Log:
> Option parsing: add support for alias arguments.
> 
> This makes option aliases more powerful by enabling them to
> pass along arguments to the option they're aliasing.
> 
> For example, if we have a joined option "-foo=", we can now
> specify a flag option "-bar" to be an alias of that, with the
> argument "baz".
> 
> This is especially useful for the cl.exe compatible clang driver,
> where many options are aliases. For example, this patch enables
> us to alias "/Ox" to "-O3" (-O is a joined option), and "/WX" to
> "-Werror" (again, -W is a joined option).
> 
> Differential Revision: http://llvm-reviews.chandlerc.com/D1245
> 
> Modified:
>    llvm/trunk/include/llvm/Option/OptParser.td
>    llvm/trunk/include/llvm/Option/OptTable.h
>    llvm/trunk/include/llvm/Option/Option.h
>    llvm/trunk/lib/Option/Option.cpp
>    llvm/trunk/unittests/Option/OptionParsingTest.cpp
>    llvm/trunk/unittests/Option/Opts.td
>    llvm/trunk/utils/TableGen/OptParserEmitter.cpp
> 
> Modified: llvm/trunk/include/llvm/Option/OptParser.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/OptParser.td?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/OptParser.td (original)
> +++ llvm/trunk/include/llvm/Option/OptParser.td Wed Jul 31 17:44:41 2013
> @@ -89,6 +89,7 @@ class Option<list<string> prefixes, stri
>   list<OptionFlag> Flags = [];
>   OptionGroup Group = ?;
>   Option Alias = ?;
> +  list<string> AliasArgs = [];
> }
> 
> // Helpers for defining options.
> @@ -113,6 +114,7 @@ class JoinedAndSeparate<list<string> pre
> // Mix-ins for adding optional attributes.
> 
> class Alias<Option alias> { Option Alias = alias; }
> +class AliasArgs<list<string> aliasargs> { list<string> AliasArgs = aliasargs; }
> class EnumName<string name> { string EnumName = name; }
> class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
> class Group<OptionGroup group> { OptionGroup Group = group; }
> 
> Modified: llvm/trunk/include/llvm/Option/OptTable.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/OptTable.h?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/OptTable.h (original)
> +++ llvm/trunk/include/llvm/Option/OptTable.h Wed Jul 31 17:44:41 2013
> @@ -44,6 +44,7 @@ public:
>     unsigned short Flags;
>     unsigned short GroupID;
>     unsigned short AliasID;
> +    const char *AliasArgs;
>   };
> 
> private:
> 
> Modified: llvm/trunk/include/llvm/Option/Option.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/Option.h?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/Option.h (original)
> +++ llvm/trunk/include/llvm/Option/Option.h Wed Jul 31 17:44:41 2013
> @@ -103,6 +103,16 @@ public:
>     return Owner->getOption(Info->AliasID);
>   }
> 
> +  /// \brief Get the alias arguments as a \0 separated list.
> +  /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
> +  const char *getAliasArgs() const {
> +    assert(Info && "Must have a valid info!");
> +    assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) &&
> +           "AliasArgs should be either 0 or non-empty.");
> +
> +    return Info->AliasArgs;
> +  }
> +
>   /// \brief Get the default prefix for this option.
>   StringRef getPrefix() const {
>     const char *Prefix = *Info->Prefixes;
> 
> Modified: llvm/trunk/lib/Option/Option.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/Option.cpp?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Option/Option.cpp (original)
> +++ llvm/trunk/lib/Option/Option.cpp Wed Jul 31 17:44:41 2013
> @@ -26,6 +26,13 @@ Option::Option(const OptTable::Info *inf
>   // tracking, it is not an inherent limitation.
>   assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
>          "Multi-level aliases are not supported.");
> +
> +  if (Info && getAliasArgs()) {
> +    assert(getAlias().isValid() && "Only alias options can have alias args.");
> +    assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
> +    assert(getAlias().getKind() != FlagClass &&
> +           "Cannot provide alias args to a flag option.");
> +  }
> }
> 
> Option::~Option() {
> @@ -106,11 +113,22 @@ Arg *Option::accept(const ArgList &Args,
>   }
> 
>   switch (getKind()) {
> -  case FlagClass:
> +  case FlagClass: {
>     if (ArgSize != strlen(Args.getArgString(Index)))
>       return 0;
> 
> -    return new Arg(UnaliasedOption, Spelling, Index++);
> +    Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
> +    if (getAliasArgs()) {
> +      const char *Val = getAliasArgs();
> +      while (*Val != '\0') {
> +        A->getValues().push_back(Val);
> +
> +        // Move past the '\0' to the next argument.
> +        Val += strlen(Val) + 1;
> +      }
> +    }
> +    return A;
> +  }
>   case JoinedClass: {
>     const char *Value = Args.getArgString(Index) + ArgSize;
>     return new Arg(UnaliasedOption, Spelling, Index++, Value);
> 
> Modified: llvm/trunk/unittests/Option/OptionParsingTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Option/OptionParsingTest.cpp?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/Option/OptionParsingTest.cpp (original)
> +++ llvm/trunk/unittests/Option/OptionParsingTest.cpp Wed Jul 31 17:44:41 2013
> @@ -17,9 +17,11 @@
> using namespace llvm;
> using namespace llvm::opt;
> 
> +#define SUPPORT_ALIASARGS // FIXME: Remove when no longer necessary.
> +
> enum ID {
>   OPT_INVALID = 0, // This is not an option ID.
> -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
>               HELPTEXT, METAVAR) OPT_##ID,
> #include "Opts.inc"
>   LastOption
> @@ -37,10 +39,10 @@ enum OptionFlags {
> };
> 
> static const OptTable::Info InfoTable[] = {
> -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
>                HELPTEXT, METAVAR)   \
>   { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
> -    FLAGS, OPT_##GROUP, OPT_##ALIAS },
> +    FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
> #include "Opts.inc"
> #undef OPTION
> };
> @@ -145,3 +147,14 @@ TEST(Option, ParseAliasInGroup) {
>   OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
>   EXPECT_TRUE(AL->hasArg(OPT_H));
> }
> +
> +TEST(Option, AliasArgs) {
> +  TestOptTable T;
> +  unsigned MAI, MAC;
> +
> +  const char *MyArgs[] = { "-J", "-Joo" };
> +  OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
> +  EXPECT_TRUE(AL->hasArg(OPT_B));
> +  EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo");
> +  EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar");
> +}
> 
> Modified: llvm/trunk/unittests/Option/Opts.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Option/Opts.td?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/Option/Opts.td (original)
> +++ llvm/trunk/unittests/Option/Opts.td Wed Jul 31 17:44:41 2013
> @@ -19,3 +19,6 @@ def H : Flag<["-"], "H">, Flags<[HelpHid
> 
> def my_group : OptionGroup<"my group">;
> 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"]>;
> 
> Modified: llvm/trunk/utils/TableGen/OptParserEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/OptParserEmitter.cpp?rev=187537&r1=187536&r2=187537&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/OptParserEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/OptParserEmitter.cpp Wed Jul 31 17:44:41 2013
> @@ -152,11 +152,22 @@ void EmitOptParser(RecordKeeper &Records
>   OS << "/////////\n";
>   OS << "// Groups\n\n";
>   OS << "#ifdef OPTION\n";
> +
> +  // FIXME: Remove when option parsing clients are updated.
> +  OS << "#ifdef SUPPORT_ALIASARGS\n";
> +  OS << "#define OPTIONX OPTION\n";
> +  OS << "#else\n";
> +  OS << "#define OPTIONX(prefix, name, id, kind, group, alias, aliasargs, "
> +     << "flags, param, helptext, metavar) "
> +     << "OPTION(prefix, name, id, kind, "
> +     << "group, alias, flags, param, helptext, metavar)\n";
> +  OS << "#endif\n";
> +
>   for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
>     const Record &R = *Groups[i];
> 
>     // Start a single option entry.
> -    OS << "OPTION(";
> +    OS << "OPTIONX(";
> 
>     // The option prefix;
>     OS << "0";
> @@ -178,7 +189,7 @@ void EmitOptParser(RecordKeeper &Records
>       OS << "INVALID";
> 
>     // The other option arguments (unused for groups).
> -    OS << ", INVALID, 0, 0";
> +    OS << ", INVALID, 0, 0, 0";
> 
>     // The option help text.
>     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
> @@ -199,7 +210,7 @@ void EmitOptParser(RecordKeeper &Records
>     const Record &R = *Opts[i];
> 
>     // Start a single option entry.
> -    OS << "OPTION(";
> +    OS << "OPTIONX(";
> 
>     // The option prefix;
>     std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
> @@ -228,6 +239,21 @@ void EmitOptParser(RecordKeeper &Records
>     else
>       OS << "INVALID";
> 
> +    // The option alias arguments (if any).
> +    // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
> +    // would become "foo\0bar\0". Note that the compiler adds an implicit
> +    // terminating \0 at the end.
> +    OS << ", ";
> +    std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
> +    if (AliasArgs.size() == 0) {
> +      OS << "0";
> +    } else {
> +      OS << "\"";
> +      for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
> +        OS << AliasArgs[i] << "\\0";
> +      OS << "\"";
> +    }
> +
>     // The option flags.
>     const ListInit *LI = R.getValueAsListInit("Flags");
>     if (LI->empty()) {
> @@ -261,6 +287,7 @@ void EmitOptParser(RecordKeeper &Records
> 
>     OS << ")\n";
>   }
> +  OS << "#undef OPTIONX\n"; // FIXME: Remove when option clients are updated.
>   OS << "#endif\n";
> }
> } // end namespace llvm
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130801/5208021f/attachment.html>


More information about the llvm-commits mailing list