[GSoC] Flag value completion for clang
This is patch for GSoC project, bash-completion for clang. To use this on bash, please run `source clang/utils/bash-autocomplete.sh`. bash-autocomplete.sh is code for bash-completion. In this patch, Options.td was mainly changed in order to add value class in Options.inc. llvm-svn: 305805
This commit is contained in:
parent
7f5313cb9f
commit
ba5d4af490
|
@ -39,8 +39,9 @@ enum ClangFlags {
|
|||
|
||||
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
|
||||
|
|
|
@ -493,7 +493,7 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, Flags<[CC
|
|||
def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group<opencl_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<opencl_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<opencl_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<opencl_Group>, Flags<[CC1Option]>,
|
||||
|
@ -804,7 +804,7 @@ def fno_sanitize_coverage
|
|||
: CommaJoined<["-"], "fno-sanitize-coverage=">,
|
||||
Group<f_clang_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<f_clang_Group>,
|
||||
HelpText<"Enable origins tracking in MemorySanitizer">;
|
||||
|
@ -923,7 +923,7 @@ def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Op
|
|||
def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
|
||||
def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_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<f_Group>;
|
||||
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
|
||||
|
@ -1000,7 +1000,7 @@ def flat__namespace : Flag<["-"], "flat_namespace">;
|
|||
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
|
||||
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
|
||||
def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group<f_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<f_Group>,
|
||||
HelpText<"Enable LTO in 'full' mode">;
|
||||
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>,
|
||||
|
@ -1158,7 +1158,7 @@ def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-m
|
|||
Group<f_clang_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Disables an experimental new pass manager in LLVM.">;
|
||||
def fveclib : Joined<["-"], "fveclib=">, Group<f_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<f_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<f_Group>,
|
||||
|
@ -1342,7 +1342,7 @@ def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1
|
|||
HelpText<"Force wchar_t to be an unsigned int">;
|
||||
def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_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<f_Group>, Flags<[CC1Option]>;
|
||||
def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>;
|
||||
def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
|
||||
|
@ -1456,7 +1456,7 @@ def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1
|
|||
def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>;
|
||||
def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
|
||||
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_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<f_Group>,
|
||||
HelpText<"Give inline C++ member functions default visibility by default">,
|
||||
Flags<[CC1Option]>;
|
||||
|
@ -1677,7 +1677,7 @@ def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group<clang_ig
|
|||
def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group<clang_ignored_m_Group>;
|
||||
def malign_double : Flag<["-"], "malign-double">, Group<m_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Align doubles to two words in structs (x86 only)">;
|
||||
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>;
|
||||
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,softfp,hard">;
|
||||
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
|
||||
def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
|
||||
def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
|
||||
|
@ -1709,9 +1709,9 @@ def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags
|
|||
def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Set the stack probe size">;
|
||||
def mthread_model : Separate<["-"], "mthread-model">, Group<m_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<m_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<m_x86_Features_Group>;
|
||||
def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
|
||||
|
@ -2205,7 +2205,7 @@ def std_default_EQ : Joined<["-"], "std-default=">;
|
|||
def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
|
||||
Group<CompileOnly_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=">,
|
||||
|
|
|
@ -1227,7 +1227,25 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
|
|||
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<std::string> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ using namespace llvm::opt;
|
|||
#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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 integrity.
|
||||
local w1="${COMP_WORDS[$cword - 1]}"
|
||||
local w2="${COMP_WORDS[$cword - 2]}"
|
||||
if [[ "$cur" == -* ]]; then
|
||||
# -foo<tab>
|
||||
arg="$cur"
|
||||
elif [[ "$w1" == -* && "$cur" == '=' ]]; then
|
||||
# -foo=<tab>
|
||||
arg="$w1=,"
|
||||
elif [[ "$w1" == -* ]]; then
|
||||
# -foo <tab> or -foo bar<tab>
|
||||
arg="$w1,$cur"
|
||||
elif [[ "$w2" == -* && "$w1" == '=' ]]; then
|
||||
# -foo=bar<tab>
|
||||
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" ) )
|
||||
|
|
|
@ -178,7 +178,7 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects);
|
|||
// 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
|
||||
};
|
||||
|
|
|
@ -640,11 +640,9 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) {
|
|||
|
||||
// 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
|
||||
};
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
// 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
|
||||
};
|
||||
|
|
|
@ -42,9 +42,9 @@ using namespace lld::elf;
|
|||
|
||||
// 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
|
||||
};
|
||||
|
|
|
@ -61,9 +61,9 @@ namespace {
|
|||
// 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 @@ enum {
|
|||
|
||||
// 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
|
||||
};
|
||||
|
|
|
@ -92,6 +92,7 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
|
|||
int NumArgs = 0;
|
||||
string HelpText = ?;
|
||||
string MetaVarName = ?;
|
||||
string Values = ?;
|
||||
list<OptionFlag> Flags = [];
|
||||
OptionGroup Group = ?;
|
||||
Option Alias = ?;
|
||||
|
@ -126,6 +127,7 @@ class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
|
|||
class Group<OptionGroup group> { OptionGroup Group = group; }
|
||||
class HelpText<string text> { string HelpText = text; }
|
||||
class MetaVarName<string name> { string MetaVarName = name; }
|
||||
class Values<string value> { string Values = value; }
|
||||
|
||||
// Predefined options.
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
unsigned short GroupID;
|
||||
unsigned short AliasID;
|
||||
const char *AliasArgs;
|
||||
const char *Values;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -120,6 +121,19 @@ public:
|
|||
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<std::string> suggestValueCompletions(StringRef Option,
|
||||
StringRef Arg) const;
|
||||
|
||||
/// Find flags from OptTable which starts with Cur.
|
||||
///
|
||||
/// \param [in] Cur - String prefix that all returned flags need
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
UnknownClass,
|
||||
FlagClass,
|
||||
JoinedClass,
|
||||
ValuesClass,
|
||||
SeparateClass,
|
||||
RemainingArgsClass,
|
||||
RemainingArgsJoinedClass,
|
||||
|
@ -155,6 +156,7 @@ public:
|
|||
case CommaJoinedClass:
|
||||
return RenderCommaJoinedStyle;
|
||||
case FlagClass:
|
||||
case ValuesClass:
|
||||
case SeparateClass:
|
||||
case MultiArgClass:
|
||||
case JoinedOrSeparateClass:
|
||||
|
|
|
@ -194,6 +194,37 @@ static unsigned matchOption(const OptTable::Info *I, StringRef Str,
|
|||
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<std::string>
|
||||
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<StringRef, 8> Candidates;
|
||||
StringRef(In.Values).split(Candidates, ",", -1, false);
|
||||
|
||||
std::vector<std::string> Result;
|
||||
for (StringRef Val : Candidates)
|
||||
if (Val.startswith(Arg))
|
||||
Result.push_back(Val);
|
||||
return Result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string> OptTable::findByPrefix(StringRef Cur) const {
|
||||
std::vector<std::string> Ret;
|
||||
for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) {
|
||||
|
@ -336,6 +367,9 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
|
|||
case Option::FlagClass:
|
||||
break;
|
||||
|
||||
case Option::ValuesClass:
|
||||
break;
|
||||
|
||||
case Option::SeparateClass: case Option::JoinedOrSeparateClass:
|
||||
case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass:
|
||||
Name += ' ';
|
||||
|
|
|
@ -47,6 +47,7 @@ void Option::print(raw_ostream &O) const {
|
|||
P(UnknownClass);
|
||||
P(FlagClass);
|
||||
P(JoinedClass);
|
||||
P(ValuesClass);
|
||||
P(SeparateClass);
|
||||
P(CommaJoinedClass);
|
||||
P(MultiArgClass);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace {
|
|||
|
||||
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 @@ enum {
|
|||
#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
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace {
|
|||
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 @@ enum ID {
|
|||
|
||||
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
|
||||
};
|
||||
|
|
|
@ -18,8 +18,9 @@ using namespace llvm::opt;
|
|||
|
||||
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 @@ enum OptionFlags {
|
|||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
|
|
@ -196,6 +196,9 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
|
|||
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 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
|
|||
else
|
||||
OS << "nullptr";
|
||||
|
||||
// The option Values. Used for shell autocompletion.
|
||||
OS << ", ";
|
||||
if (!isa<UnsetInit>(R.getValueInit("Values")))
|
||||
write_cstring(OS, R.getValueAsString("Values"));
|
||||
else
|
||||
OS << "nullptr";
|
||||
|
||||
OS << ")\n";
|
||||
}
|
||||
OS << "#endif // OPTION\n";
|
||||
|
|
Loading…
Reference in New Issue