Index: clang/include/clang/Driver/Options.h =================================================================== --- clang/include/clang/Driver/Options.h +++ clang/include/clang/Driver/Options.h @@ -40,7 +40,7 @@ enum ID { OPT_INVALID = 0, // This is not an option ID. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) OPT_##ID, + HELPTEXT, METAVAR, VALUE) OPT_##ID, #include "clang/Driver/Options.inc" LastOption #undef OPTION Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2195,7 +2195,7 @@ def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, Group, HelpText<"Language standard to compile for">; def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>, - HelpText<"C++ standard library to use">; + HelpText<"C++ standard library to use">, Value<"libc++,libstdc++,platform">; def sub__library : JoinedOrSeparate<["-"], "sub_library">; def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">; def system_header_prefix : Joined<["--"], "system-header-prefix=">, Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -1219,7 +1219,13 @@ if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) { // Print out all options that start with a given argument. This is used for // shell autocompletion. - llvm::outs() << llvm::join(Opts->findByPrefix(A->getValue()), " ") << '\n'; + StringRef S = A->getValue(); + SmallVector Split; + S.split(Split, ",", -1, false); + std::vector V = Opts->findByPrefix(Split[0]); + if (V.empty()) + V = Opts->findByValue(Split); + llvm::outs() << llvm::join(V, " ") << '\n'; return false; } Index: clang/lib/Driver/DriverOptions.cpp =================================================================== --- clang/lib/Driver/DriverOptions.cpp +++ clang/lib/Driver/DriverOptions.cpp @@ -22,9 +22,9 @@ static const OptTable::Info InfoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ + HELPTEXT, METAVAR, VALUE) \ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \ - FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS }, + FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUE }, #include "clang/Driver/Options.inc" #undef OPTION }; Index: clang/test/Driver/autocomplete.c =================================================================== --- clang/test/Driver/autocomplete.c +++ clang/test/Driver/autocomplete.c @@ -4,3 +4,5 @@ // STD: -std={{.*}}-stdlib= // RUN: %clang --autocomplete=foo | not FileCheck %s -check-prefix=NONE // NONE: foo +// RUN: %clang --autocomplete=l,=,-stdlib | FileCheck %s -check-prefix=STDLIB +// STDLIB: libc++ libstdc++ Index: clang/utils/bash-autocomplete.sh =================================================================== --- clang/utils/bash-autocomplete.sh +++ clang/utils/bash-autocomplete.sh @@ -4,11 +4,17 @@ local cur prev words cword flags _init_completion -n : || return - flags=$( clang --autocomplete="$cur" ) + arg="" + for (( i = $cword; i >= 1; i-- )) ; + do + arg="$arg""${COMP_WORDS[$i]}," + done + + flags=$( clang --autocomplete="$arg" ) if [[ "$flags" == "" || "$cur" == "" ]]; then _filedir else COMPREPLY=( $( compgen -W "$flags" -- "$cur" ) ) fi -} +} complete -F _clang clang Index: lld/COFF/Driver.h =================================================================== --- lld/COFF/Driver.h +++ lld/COFF/Driver.h @@ -185,7 +185,7 @@ // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, -#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, #include "Options.inc" #undef OPTION }; Index: lld/COFF/DriverUtils.cpp =================================================================== --- lld/COFF/DriverUtils.cpp +++ lld/COFF/DriverUtils.cpp @@ -659,10 +659,10 @@ // Create table mapping all options defined in Options.td static const llvm::opt::OptTable::Info infoTable[] = { -#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10, X11) \ { \ X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ - OPT_##GROUP, OPT_##ALIAS, X6 \ + OPT_##GROUP, OPT_##ALIAS, X6, X11 \ }, #include "Options.inc" #undef OPTION Index: lld/ELF/Driver.h =================================================================== --- lld/ELF/Driver.h +++ lld/ELF/Driver.h @@ -58,7 +58,7 @@ // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, -#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, #include "Options.inc" #undef OPTION }; Index: lld/ELF/DriverUtils.cpp =================================================================== --- lld/ELF/DriverUtils.cpp +++ lld/ELF/DriverUtils.cpp @@ -42,9 +42,9 @@ // Create table mapping all options defined in Options.td static const opt::OptTable::Info OptInfo[] = { -#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10, X11) \ {X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, \ - X8, X7, OPT_##GROUP, OPT_##ALIAS, X6}, + X8, X7, OPT_##GROUP, OPT_##ALIAS, X6, X11}, #include "Options.inc" #undef OPTION }; Index: lld/lib/Driver/DarwinLdDriver.cpp =================================================================== --- lld/lib/Driver/DarwinLdDriver.cpp +++ lld/lib/Driver/DarwinLdDriver.cpp @@ -62,7 +62,7 @@ enum { OPT_INVALID = 0, #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELP, META) \ + HELP, META, VALUE) \ OPT_##ID, #include "DarwinLdOptions.inc" #undef OPTION @@ -76,9 +76,9 @@ // Create table mapping all options defined in DarwinLdOptions.td static const llvm::opt::OptTable::Info infoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ + HELPTEXT, METAVAR, VALUE) \ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ - PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS }, + PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUE }, #include "DarwinLdOptions.inc" #undef OPTION }; Index: llvm/include/llvm/Option/OptParser.td =================================================================== --- llvm/include/llvm/Option/OptParser.td +++ llvm/include/llvm/Option/OptParser.td @@ -92,6 +92,7 @@ int NumArgs = 0; string HelpText = ?; string MetaVarName = ?; + string Value = ?; list Flags = []; OptionGroup Group = ?; Option Alias = ?; @@ -126,6 +127,7 @@ class Group { OptionGroup Group = group; } class HelpText { string HelpText = text; } class MetaVarName { string MetaVarName = name; } +class Value { string Value = value; } // Predefined options. Index: llvm/include/llvm/Option/OptTable.h =================================================================== --- llvm/include/llvm/Option/OptTable.h +++ llvm/include/llvm/Option/OptTable.h @@ -46,6 +46,7 @@ unsigned short GroupID; unsigned short AliasID; const char *AliasArgs; + const char *Value; }; private: @@ -113,6 +114,7 @@ return getInfo(id).MetaVar; } + std::vector findByValue(const SmallVectorImpl &Command) const; /// Find flags from OptTable which starts with Cur. /// /// \param [in] Cur - String prefix that all returned flags need Index: llvm/include/llvm/Option/Option.h =================================================================== --- llvm/include/llvm/Option/Option.h +++ llvm/include/llvm/Option/Option.h @@ -49,6 +49,7 @@ UnknownClass, FlagClass, JoinedClass, + ValueClass, SeparateClass, RemainingArgsClass, RemainingArgsJoinedClass, @@ -147,6 +148,7 @@ case CommaJoinedClass: return RenderCommaJoinedStyle; case FlagClass: + case ValueClass: case SeparateClass: case MultiArgClass: case JoinedOrSeparateClass: Index: llvm/lib/Option/OptTable.cpp =================================================================== --- llvm/lib/Option/OptTable.cpp +++ llvm/lib/Option/OptTable.cpp @@ -186,6 +186,30 @@ return 0; } +std::vector +OptTable::findByValue(const SmallVectorImpl &Command) const { + if (Command.size() <= 1) + return {}; + + std::vector Ret; + for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) { + if (!In.Value) + continue; + std::string S = "-" + std::string(In.Name); + std::string C = (Command[1] == "=") ? + std::string(Command[2]) + "=" : std::string(Command[1]); + if (S != C) + continue; + + SmallVector Values; + StringRef(In.Value).split(Values, ",", -1, false); + for (StringRef Val : Values) + if (Val.startswith(Command[0])) + Ret.push_back(Val); + } + return Ret; +} + std::vector OptTable::findByPrefix(StringRef Cur) const { std::vector Ret; for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) { @@ -328,6 +352,9 @@ case Option::FlagClass: break; + case Option::ValueClass: + break; + case Option::SeparateClass: case Option::JoinedOrSeparateClass: case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass: Name += ' '; Index: llvm/lib/Option/Option.cpp =================================================================== --- llvm/lib/Option/Option.cpp +++ llvm/lib/Option/Option.cpp @@ -45,6 +45,7 @@ P(UnknownClass); P(FlagClass); P(JoinedClass); + P(ValueClass); P(SeparateClass); P(CommaJoinedClass); P(MultiArgClass); Index: llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp =================================================================== --- llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp +++ llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp @@ -30,7 +30,7 @@ enum { OPT_INVALID = 0, -#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, #include "Options.inc" #undef OPTION }; @@ -40,10 +40,10 @@ #undef PREFIX static const llvm::opt::OptTable::Info infoTable[] = { -#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10, X11) \ { \ X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ - OPT_##GROUP, OPT_##ALIAS, X6 \ + OPT_##GROUP, OPT_##ALIAS, X6, X11 \ }, #include "Options.inc" #undef OPTION Index: llvm/tools/llvm-cvtres/llvm-cvtres.cpp =================================================================== --- llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -31,7 +31,7 @@ enum ID { OPT_INVALID = 0, // This is not an option ID. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ + HELPTEXT, METAVAR, VALUE) \ OPT_##ID, #include "Opts.inc" #undef OPTION @@ -43,12 +43,12 @@ static const opt::OptTable::Info InfoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ + HELPTEXT, METAVAR, VALUE) \ { \ PREFIX, NAME, HELPTEXT, \ METAVAR, OPT_##ID, opt::Option::KIND##Class, \ PARAM, FLAGS, OPT_##GROUP, \ - OPT_##ALIAS, ALIASARGS}, + OPT_##ALIAS, ALIASARGS, VALUE }, #include "Opts.inc" #undef OPTION }; Index: llvm/unittests/Option/OptionParsingTest.cpp =================================================================== --- llvm/unittests/Option/OptionParsingTest.cpp +++ llvm/unittests/Option/OptionParsingTest.cpp @@ -19,7 +19,8 @@ enum ID { OPT_INVALID = 0, // This is not an option ID. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) OPT_##ID, + HELPTEXT, METAVAR, VALUE) \ + OPT_##ID, #include "Opts.inc" LastOption #undef OPTION @@ -37,9 +38,9 @@ static const OptTable::Info InfoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ + HELPTEXT, METAVAR, VALUE) \ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \ - FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS }, + FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUE }, #include "Opts.inc" #undef OPTION }; Index: llvm/utils/TableGen/OptParserEmitter.cpp =================================================================== --- llvm/utils/TableGen/OptParserEmitter.cpp +++ llvm/utils/TableGen/OptParserEmitter.cpp @@ -194,6 +194,8 @@ OS << ", nullptr"; // The option meta-variable name (unused). + OS << ", nullptr"; + OS << ", nullptr)\n"; } OS << "\n"; @@ -283,6 +285,12 @@ else OS << "nullptr"; + OS << ", "; + if (!isa(R.getValueInit("Value"))) + write_cstring(OS, R.getValueAsString("Value")); + else + OS << "nullptr"; + OS << ")\n"; } OS << "#endif // OPTION\n";