From: "Martin Liška" <mliska@suse.cz>
To: GCC Development <gcc@gcc.gnu.org>
Cc: David Malcolm <dmalcolm@redhat.com>
Subject: RFC: bash completion
Date: Tue, 24 Apr 2018 15:00:00 -0000 [thread overview]
Message-ID: <3c2e7f32-438a-57a3-96a8-3e9d3fc7f605@suse.cz> (raw)
[-- Attachment #1: Type: text/plain, Size: 2372 bytes --]
Hi.
Some time ago, I investigated quite new feature of clang which
is support of --autocomplete argument. That can be run from bash completion
script and one gets more precise completion hints:
http://blog.llvm.org/2017/09/clang-bash-better-auto-completion-is.html
https://www.youtube.com/watch?v=zLPwPdZBpSY
I like the idea and I would describe how is that better to current GCC completion
script sitting here:
https://github.com/scop/bash-completion/blob/master/completions/gcc
1) gcc -fsanitize=^ - no support for option enum values
2) gcc -fno-sa^ - no support for negative options
3) gcc --param=^ - no support for param names
These are main limitations I see. I'm attaching working prototype, which you
can test by installed GCC, setting it on $PATH and doing:
$ source gcc.sh
Then bash completion is provided via the newly added option. Some examples:
1)
$ gcc -fsanitize=
address bounds enum integer-divide-by-zero nonnull-attribute pointer-compare return shift-base thread vla-bound
alignment bounds-strict float-cast-overflow kernel-address null pointer-overflow returns-nonnull-attribute shift-exponent undefined vptr
bool builtin float-divide-by-zero leak object-size pointer-subtract shift signed-integer-overflow unreachable
2)
$ gcc -fno-ipa-
-fno-ipa-bit-cp -fno-ipa-cp-alignment -fno-ipa-icf -fno-ipa-icf-variables -fno-ipa-profile -fno-ipa-pure-const -fno-ipa-reference -fno-ipa-struct-reorg
-fno-ipa-cp -fno-ipa-cp-clone -fno-ipa-icf-functions -fno-ipa-matrix-reorg -fno-ipa-pta -fno-ipa-ra -fno-ipa-sra -fno-ipa-vrp
3)
$ gcc --param=lto-
lto-max-partition lto-min-partition lto-partitions
4)
gcc --param lto-
lto-max-partition lto-min-partition lto-partitions
The patch is quite lean and if people like, I will prepare a proper
patch submission. I know about some limitations that can be then
handled incrementally.
Thoughts?
Martin
[-- Attachment #2: 0001-First-version-of-prototype.patch --]
[-- Type: text/x-patch, Size: 6619 bytes --]
From 7bf882961cd81d3f12df017398625ee190c9808f Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 23 Feb 2018 12:28:43 +0100
Subject: [PATCH] First version of prototype.
---
gcc.sh | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
gcc/common.opt | 4 ++++
gcc/gcc.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
gcc/gcc.h | 1 +
gcc/opts.c | 3 +++
gcc/params.c | 13 +++++++++++++
gcc/params.h | 1 +
7 files changed, 121 insertions(+)
create mode 100644 gcc.sh
diff --git a/gcc.sh b/gcc.sh
new file mode 100644
index 00000000000..06b16b3152b
--- /dev/null
+++ b/gcc.sh
@@ -0,0 +1,51 @@
+# Please add "source /path/to/bash-autocomplete.sh" to your .bashrc to use this.
+
+log()
+{
+ echo $1 >> /tmp/bash-completion.log
+}
+
+_gcc()
+{
+ local cur prev prev2 words cword argument prefix
+ _init_completion || return
+ _expand || return
+
+ # extract also for situations like: -fsanitize=add
+ if [[ $cword > 2 ]]; then
+ prev2="${COMP_WORDS[$cword - 2]}"
+ fi
+
+ log "cur: '$cur', prev: '$prev': prev2: '$prev2' cword: '$cword'"
+
+ # sample: -fsan
+ if [[ "$cur" == -* ]]; then
+ argument=$cur
+ # sample: -fsanitize=
+ elif [[ "$cur" == "=" && $prev == -* ]]; then
+ argument=$prev$cur
+ prefix=$prev$cur
+ # sample: -fsanitize=add
+ elif [[ "$prev" == "=" && $prev2 == -* ]]; then
+ argument=$prev2$prev$cur
+ prefix=$prev2$prev
+ # sample: --param lto-
+ elif [[ "$prev" == "--param" ]]; then
+ argument="$prev $cur"
+ prefix="$prev "
+ fi
+
+ log "argument: '$argument', prefix: '$prefix'"
+
+ if [[ "$argument" == "" ]]; then
+ _filedir
+ else
+ # In situation like '-fsanitize=add' $cur is equal to last token.
+ # Thus we need to strip the beginning of suggested option.
+ flags=$( gcc --completion="$argument" 2>/dev/null | sed "s/^$prefix//")
+ log "compgen: $flags"
+ [[ "${flags: -1}" == '=' ]] && compopt -o nospace 2> /dev/null
+ COMPREPLY=( $( compgen -W "$flags" -- "") )
+ fi
+}
+complete -F _gcc gcc
diff --git a/gcc/common.opt b/gcc/common.opt
index d6ef85928f3..389d4fa0385 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -254,6 +254,10 @@ Driver Alias(S)
-compile
Driver Alias(c)
+-completion=
+Common Driver Joined
+--param Bash completion.
+
-coverage
Driver Alias(coverage)
diff --git a/gcc/gcc.c b/gcc/gcc.c
index a716f708259..dab88f44d27 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -220,6 +220,8 @@ static int print_help_list;
static int print_version;
+static const char *completion = NULL;
+
/* Flag indicating whether we should ONLY print the command and
arguments (like verbose_flag) without executing the command.
Displayed arguments are quoted so that the generated command
@@ -3818,6 +3820,11 @@ driver_handle_option (struct gcc_options *opts,
add_linker_option ("--version", strlen ("--version"));
break;
+ case OPT__completion_:
+ validated = true;
+ completion = decoded->arg;
+ break;
+
case OPT__help:
print_help_list = 1;
@@ -7300,6 +7307,12 @@ driver::main (int argc, char **argv)
maybe_putenv_OFFLOAD_TARGETS ();
handle_unrecognized_options ();
+ if (completion)
+ {
+ suggest_completion (completion);
+ return 0;
+ }
+
if (!maybe_print_and_exit ())
return 0;
@@ -7868,6 +7881,41 @@ driver::suggest_option (const char *bad_opt)
(auto_vec <const char *> *) m_option_suggestions);
}
+void
+driver::suggest_completion (const char *starting)
+{
+ /* Lazily populate m_option_suggestions. */
+ if (!m_option_suggestions)
+ build_option_suggestions ();
+ gcc_assert (m_option_suggestions);
+
+ if (starting[0] == '-')
+ starting++;
+
+ size_t l = strlen (starting);
+ const char *prefix = "-param";
+ if (l >= strlen (prefix) && strstr (starting, prefix) == starting)
+ {
+ /* We support both '-param-xyz=123' and '-param xyz=123' */
+ starting += strlen (prefix);
+ char separator = starting[0];
+ starting++;
+ if (separator != ' ' && separator != '=')
+ return;
+
+ param_print_candidates (separator, starting);
+ return;
+ }
+
+ for (int i = 0; i < m_option_suggestions->length (); i++)
+ {
+ char *candidate = (*m_option_suggestions)[i];
+ if (strlen (candidate) >= l
+ && strstr (candidate, starting) == candidate)
+ printf ("-%s\n", candidate);
+ }
+}
+
/* Reject switches that no pass was interested in. */
void
diff --git a/gcc/gcc.h b/gcc/gcc.h
index ddbf42f78ea..e786e912943 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -47,6 +47,7 @@ class driver
void maybe_putenv_OFFLOAD_TARGETS () const;
void build_option_suggestions (void);
const char *suggest_option (const char *bad_opt);
+ void suggest_completion (const char *starting);
void handle_unrecognized_options ();
int maybe_print_and_exit () const;
bool prepare_infiles ();
diff --git a/gcc/opts.c b/gcc/opts.c
index 33efcc0d6e7..ed102c05c22 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1982,6 +1982,9 @@ common_handle_option (struct gcc_options *opts,
opts->x_exit_after_options = true;
break;
+ case OPT__completion_:
+ break;
+
case OPT_fsanitize_:
opts->x_flag_sanitize
= parse_sanitizer_options (arg, loc, code,
diff --git a/gcc/params.c b/gcc/params.c
index 623296ce49b..6b97e524984 100644
--- a/gcc/params.c
+++ b/gcc/params.c
@@ -179,6 +179,19 @@ param_string_value_p (enum compiler_param index, const char *value_name,
return true;
}
+void
+param_print_candidates (const char separator, const char *starting)
+{
+ size_t l = strlen (starting);
+ for (unsigned i = 0; i < num_compiler_params; ++i)
+ {
+ const char *candidate = compiler_params[i].option;
+ if (strlen (candidate) >= l
+ && strstr (candidate, starting) == candidate)
+ printf ("--param%c%s\n", separator, candidate);
+ }
+}
+
/* Set the VALUE associated with the parameter given by NAME in PARAMS
and PARAMS_SET. */
diff --git a/gcc/params.h b/gcc/params.h
index 98249d2a1f6..7118fea9f14 100644
--- a/gcc/params.h
+++ b/gcc/params.h
@@ -91,6 +91,7 @@ enum compiler_param
extern bool find_param (const char *, enum compiler_param *);
extern const char *find_param_fuzzy (const char *name);
extern bool param_string_value_p (enum compiler_param, const char *, int *);
+extern void param_print_candidates (const char separator, const char *starting);
/* The value of the parameter given by ENUM. Not an lvalue. */
#define PARAM_VALUE(ENUM) \
--
2.16.3
next reply other threads:[~2018-04-24 14:45 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-24 15:00 Martin Liška [this message]
2018-04-24 16:49 ` David Malcolm
2018-04-25 13:13 ` Martin Liška
2018-04-25 13:53 ` Martin Liška
2018-06-29 15:04 ` [PATCH] Add new tests for --completion option Martin Liška
2018-06-29 17:19 ` Jeff Law
2018-06-29 18:04 ` Eric Gallager
2018-06-29 22:41 ` David Malcolm
2018-07-02 9:52 ` Martin Liška
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3c2e7f32-438a-57a3-96a8-3e9d3fc7f605@suse.cz \
--to=mliska@suse.cz \
--cc=dmalcolm@redhat.com \
--cc=gcc@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).