Index: clang/include/clang/Driver/Options.h =================================================================== --- clang/include/clang/Driver/Options.h +++ clang/include/clang/Driver/Options.h @@ -39,8 +39,9 @@ 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, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + 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 @@ -493,7 +493,7 @@ def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group, Flags<[CC1Option]>, HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">; def cl_std_EQ : Joined<["-"], "cl-std=">, Group, Flags<[CC1Option]>, - HelpText<"OpenCL language standard to compile for.">; + HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0">; def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group, Flags<[CC1Option]>, HelpText<"OpenCL only. Allow denormals to be flushed to zero.">; def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group, Flags<[CC1Option]>, @@ -804,7 +804,7 @@ : CommaJoined<["-"], "fno-sanitize-coverage=">, Group, Flags<[CoreOption, DriverOption]>, HelpText<"Disable specified features of coverage instrumentation for " - "Sanitizers">; + "Sanitizers">, Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters">; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, Group, HelpText<"Enable origins tracking in MemorySanitizer">; @@ -923,7 +923,7 @@ def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group, Flags<[CC1Option]>; def ffp_contract : Joined<["-"], "ffp-contract=">, Group, Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" - " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; + " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">; def ffor_scope : Flag<["-"], "ffor-scope">, Group; def fno_for_scope : Flag<["-"], "fno-for-scope">, Group; @@ -996,7 +996,7 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group, - HelpText<"Set LTO mode to either 'full' or 'thin'">; + HelpText<"Set LTO mode to either 'full' or 'thin'">, Values<"thin,full">; def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group, HelpText<"Enable LTO in 'full' mode">; def fno_lto : Flag<["-"], "fno-lto">, Group, @@ -1154,7 +1154,7 @@ Group, Flags<[CC1Option]>, HelpText<"Disables an experimental new pass manager in LLVM.">; def fveclib : Joined<["-"], "fveclib=">, Group, Flags<[CC1Option]>, - HelpText<"Use the given vector functions library">; + HelpText<"Use the given vector functions library">, Values<"Accelerate,SVML,none">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>; def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group, @@ -1338,7 +1338,7 @@ HelpText<"Force wchar_t to be an unsigned int">; def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group, Flags<[CC1Option]>, HelpText<"Which overload candidates to show when overload resolution fails: " - "best|all; defaults to all">; + "best|all; defaults to all">, Values<"best,all">; def fshow_column : Flag<["-"], "fshow-column">, Group, Flags<[CC1Option]>; def fshow_source_location : Flag<["-"], "fshow-source-location">, Group; def fspell_checking : Flag<["-"], "fspell-checking">, Group; @@ -1452,7 +1452,7 @@ def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group; def fverbose_asm : Flag<["-"], "fverbose-asm">, Group; def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group, - HelpText<"Set the default symbol visibility for all global declarations">; + HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, HelpText<"Give inline C++ member functions default visibility by default">, Flags<[CC1Option]>; @@ -1673,7 +1673,7 @@ def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group; def malign_double : Flag<["-"], "malign-double">, Group, Flags<[CC1Option]>, HelpText<"Align doubles to two words in structs (x86 only)">; -def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group; +def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group, Values<"soft,softfp,hard">; def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group; def mfpu_EQ : Joined<["-"], "mfpu=">, Group; def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group; @@ -1705,9 +1705,9 @@ def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group, Flags<[CC1Option]>, HelpText<"Set the stack probe size">; def mthread_model : Separate<["-"], "mthread-model">, Group, Flags<[CC1Option]>, - HelpText<"The thread model to use, e.g. posix, single (posix by default)">; + HelpText<"The thread model to use, e.g. posix, single (posix by default)">, Values<"posix,single">; def meabi : Separate<["-"], "meabi">, Group, Flags<[CC1Option]>, - HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">; + HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">, Values<"default,4,5,gnu">; def mmmx : Flag<["-"], "mmmx">, Group; def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group; @@ -2201,7 +2201,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">, Values<"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 @@ -1227,7 +1227,25 @@ 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 PassedFlags = A->getValue(); + std::vector SuggestedCompletions; + + if (PassedFlags.find(',') == StringRef::npos) { + // If the flag is in the form of "--autocomplete=-foo", + // we were requested to print out all option names that start with "-foo". + // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only". + SuggestedCompletions = Opts->findByPrefix(PassedFlags); + } else { + // If the flag is in the form of "--autocomplete=foo,bar", we were + // requested to print out all option values for "-foo" that start with + // "bar". For example, + // "--autocomplete=-stdlib=,l" is expanded to "libc++" and "libstdc++". + StringRef Option, Arg; + std::tie(Option, Arg) = PassedFlags.split(','); + SuggestedCompletions = Opts->suggestValueCompletions(Option, Arg); + } + + llvm::outs() << llvm::join(SuggestedCompletions, " ") << '\n'; return false; } Index: clang/lib/Driver/DriverOptions.cpp =================================================================== --- clang/lib/Driver/DriverOptions.cpp +++ clang/lib/Driver/DriverOptions.cpp @@ -21,10 +21,10 @@ #undef PREFIX static const OptTable::Info InfoTable[] = { -#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, ALIASARGS }, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES}, #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,33 @@ // STD: -std={{.*}}-stdlib= // RUN: %clang --autocomplete=foo | not FileCheck %s -check-prefix=NONE // NONE: foo +// RUN: %clang --autocomplete=-stdlib=,l | FileCheck %s -check-prefix=STDLIB +// STDLIB: libc++ libstdc++ +// RUN: %clang --autocomplete=-stdlib=, | FileCheck %s -check-prefix=STDLIBALL +// STDLIBALL: libc++ libstdc++ platform +// RUN: %clang --autocomplete=-meabi,d | FileCheck %s -check-prefix=MEABI +// MEABI: default +// RUN: %clang --autocomplete=-meabi, | FileCheck %s -check-prefix=MEABIALL +// MEABIALL: default 4 5 gnu +// RUN: %clang --autocomplete=-cl-std=,CL2 | FileCheck %s -check-prefix=CLSTD +// CLSTD: CL2.0 +// RUN: %clang --autocomplete=-cl-std=, | FileCheck %s -check-prefix=CLSTDALL +// CLSTDALL: cl CL cl1.1 CL1.1 cl1.2 CL1.2 cl2.0 CL2.0 +// RUN: %clang --autocomplete=-fno-sanitize-coverage=,f | FileCheck %s -check-prefix=FNOSANICOVER +// FNOSANICOVER: func +// RUN: %clang --autocomplete=-fno-sanitize-coverage=, | FileCheck %s -check-prefix=FNOSANICOVERALL +// FNOSANICOVERALL: func bb edge indirect-calls trace-bb trace-cmp trace-div trace-gep 8bit-counters trace-pc trace-pc-guard no-prune inline-8bit-counters +// RUN: %clang --autocomplete=-ffp-contract=, | FileCheck %s -check-prefix=FFPALL +// FFPALL: fast on off +// RUN: %clang --autocomplete=-flto=, | FileCheck %s -check-prefix=FLTOALL +// FLTOALL: thin full +// RUN: %clang --autocomplete=-fveclib=, | FileCheck %s -check-prefix=FVECLIBALL +// FVECLIBALL: Accelerate SVML none +// RUN: %clang --autocomplete=-fshow-overloads=, | FileCheck %s -check-prefix=FSOVERALL +// FSOVERALL: best all +// RUN: %clang --autocomplete=-fvisibility=, | FileCheck %s -check-prefix=FVISIBILITYALL +// FVISIBILITYALL: hidden default +// RUN: %clang --autocomplete=-mfloat-abi=, | FileCheck %s -check-prefix=MFLOATABIALL +// MFLOATABIALL: soft softfp hard +// RUN: %clang --autocomplete=-mthread-model, | FileCheck %s -check-prefix=MTHREADMODELALL +// MTHREADMODELALL: posix single Index: clang/utils/bash-autocomplete.sh =================================================================== --- clang/utils/bash-autocomplete.sh +++ clang/utils/bash-autocomplete.sh @@ -1,11 +1,35 @@ # Please add "source /path/to/bash-autocomplete.sh" to your .bashrc to use this. _clang() { - local cur prev words cword flags + local cur prev words cword arg _init_completion -n : || return - flags=$( clang --autocomplete="$cur" ) - if [[ "$flags" == "" || "$cur" == "" ]]; then + # bash always separates '=' as a token even if there's no space before/after '='. + # On the other hand, '=' is just a regular character for clang options that + # contain '='. For example, "-stdlib=" is defined as is, instead of "-stdlib" and "=". + # So, we need to partially undo bash tokenization here for impedance matching. + local w1="${COMP_WORDS[$cword - 1]}" + local w2="${COMP_WORDS[$cword - 2]}" + if [[ "$cur" == -* ]]; then + # -foo + arg="$cur" + elif [[ "$w1" == -* && "$cur" == '=' ]]; then + # -foo= + arg="$w1=," + elif [[ "$w1" == -* ]]; then + # -foo or -foo bar + arg="$w1,$cur" + elif [[ "$w2" == -* && "$w1" == '=' ]]; then + # -foo=bar + arg="$w2=,$cur" + else + _filedir + fi + + local flags=$( clang --autocomplete="$arg" ) + if [[ "$cur" == "=" ]]; then + COMPREPLY=( $( compgen -W "$flags" -- "") ) + elif [[ "$flags" == "" ]]; then _filedir else COMPREPLY=( $( compgen -W "$flags" -- "$cur" ) ) Index: lld/COFF/Driver.h =================================================================== --- lld/COFF/Driver.h +++ lld/COFF/Driver.h @@ -178,7 +178,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 @@ -657,11 +657,9 @@ // 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) \ - { \ - X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ - OPT_##GROUP, OPT_##ALIAS, X6 \ - }, +#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, 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 @@ -61,9 +61,9 @@ // Create enum with OPT_xxx values for each option in DarwinLdOptions.td enum { OPT_INVALID = 0, -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELP, META) \ - OPT_##ID, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELP, META, VALUES) \ + OPT_##ID, #include "DarwinLdOptions.inc" #undef OPTION }; @@ -75,10 +75,12 @@ // 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) \ - { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ - PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS }, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, #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 Values = ?; 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 Values { string Values = 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 *Values; }; private: @@ -113,6 +114,19 @@ return getInfo(id).MetaVar; } + /// Find possible value for given flags. This is used for shell + /// autocompletion. + /// + /// \param [in] Option - Key flag like "-stdlib=" when "-stdlib=l" + /// was passed to clang. + /// + /// \param [in] Arg - Value which we want to autocomplete like "l" + /// when "-stdlib=l" was passed to clang. + /// + /// \return The vector of possible values. + std::vector suggestValueCompletions(StringRef Option, + StringRef Arg) 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, + ValuesClass, SeparateClass, RemainingArgsClass, RemainingArgsJoinedClass, @@ -147,6 +148,7 @@ case CommaJoinedClass: return RenderCommaJoinedStyle; case FlagClass: + case ValuesClass: 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,37 @@ return 0; } +// Returns true if one of the Prefixes + In.Names matches Option +static bool optionMatches(const OptTable::Info &In, StringRef Option) { + if (In.Values && In.Prefixes) + for (size_t I = 0; In.Prefixes[I]; I++) + if (Option == std::string(In.Prefixes[I]) + In.Name) + return true; + return false; +} + +// This function is for flag value completion. +// Eg. When "-stdlib=" and "l" was passed to this function, it will return +// appropiriate values for stdlib, which starts with l. +std::vector +OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const { + // Search all options and return possible values. + for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) { + if (!optionMatches(In, Option)) + continue; + + SmallVector Candidates; + StringRef(In.Values).split(Candidates, ",", -1, false); + + std::vector Result; + for (StringRef Val : Candidates) + if (Val.startswith(Arg)) + Result.push_back(Val); + return Result; + } + return {}; +} + std::vector OptTable::findByPrefix(StringRef Cur) const { std::vector Ret; for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) { @@ -328,6 +359,9 @@ case Option::FlagClass: break; + case Option::ValuesClass: + 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(ValuesClass); 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 @@ -31,7 +31,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 }; @@ -41,11 +41,9 @@ #undef PREFIX static const llvm::opt::OptTable::Info infoTable[] = { -#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ - { \ - X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ - OPT_##GROUP, OPT_##ALIAS, X6 \ - }, +#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, 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 @@ -37,7 +37,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, VALUES) \ OPT_##ID, #include "Opts.inc" #undef OPTION @@ -49,12 +49,12 @@ static const opt::OptTable::Info InfoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ + HELPTEXT, METAVAR, VALUES) \ { \ - PREFIX, NAME, HELPTEXT, \ - METAVAR, OPT_##ID, opt::Option::KIND##Class, \ - PARAM, FLAGS, OPT_##GROUP, \ - OPT_##ALIAS, ALIASARGS}, + PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, #include "Opts.inc" #undef OPTION }; Index: llvm/unittests/Option/OptionParsingTest.cpp =================================================================== --- llvm/unittests/Option/OptionParsingTest.cpp +++ llvm/unittests/Option/OptionParsingTest.cpp @@ -18,8 +18,9 @@ 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, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + OPT_##ID, #include "Opts.inc" LastOption #undef OPTION @@ -36,10 +37,10 @@ }; static const OptTable::Info InfoTable[] = { -#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, ALIASARGS }, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES}, #include "Opts.inc" #undef OPTION }; Index: llvm/utils/TableGen/OptParserEmitter.cpp =================================================================== --- llvm/utils/TableGen/OptParserEmitter.cpp +++ llvm/utils/TableGen/OptParserEmitter.cpp @@ -196,6 +196,9 @@ OS << ", nullptr"; // The option meta-variable name (unused). + OS << ", nullptr"; + + // The option Values (unused for groups). OS << ", nullptr)\n"; } OS << "\n"; @@ -285,6 +288,13 @@ else OS << "nullptr"; + // The option Values. Used for shell autocompletion. + OS << ", "; + if (!isa(R.getValueInit("Values"))) + write_cstring(OS, R.getValueAsString("Values")); + else + OS << "nullptr"; + OS << ")\n"; } OS << "#endif // OPTION\n";