public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC: bash completion
@ 2018-04-24 15:00 Martin Liška
  2018-04-24 16:49 ` David Malcolm
  2018-06-29 15:04 ` [PATCH] Add new tests for --completion option Martin Liška
  0 siblings, 2 replies; 9+ messages in thread
From: Martin Liška @ 2018-04-24 15:00 UTC (permalink / raw)
  To: GCC Development; +Cc: David Malcolm

[-- 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


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: bash completion
  2018-04-24 15:00 RFC: bash completion Martin Liška
@ 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
  1 sibling, 2 replies; 9+ messages in thread
From: David Malcolm @ 2018-04-24 16:49 UTC (permalink / raw)
  To: Martin Liška, GCC Development

On Tue, 2018-04-24 at 16:45 +0200, Martin Liška wrote:
> 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.htm
> l
> 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

Overall, looks good (albeit with various nits).  I like how you're
reusing the m_option_suggestions machinery from the misspelled options
code.  There are some awkward issues e.g. arch-specific completions,
lang-specific completions, custom option-handling etc, but given that
as-is this patch seems to be an improvement over the status quo, I'd
prefer to tackle those later.

The patch doesn't have tests.  There would need to be some way to
achieve test coverage for the completion code (especially as we start
to tackle the more interesting cases).  I wonder what the best way to
do that is; perhaps a combination of selftest and DejaGnu?  (e.g. what
about arch-specific completions? what about the interaction with bash?
etc)

A few nits:
* Do we want to hardcode that logging path in gcc.sh?

* Looks like m_option_suggestions isn't needed for handling the "-
param" case, so maybe put the param-handling case before the "Lazily
populate m_option_suggestions" code.

* You use "l" ("ell") as a variable name in two places, which I don't
like, as IMHO it's too close to "1" (one) in some fonts.

Thanks
Dave

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: bash completion
  2018-04-24 16:49 ` David Malcolm
@ 2018-04-25 13:13   ` Martin Liška
  2018-04-25 13:53   ` Martin Liška
  1 sibling, 0 replies; 9+ messages in thread
From: Martin Liška @ 2018-04-25 13:13 UTC (permalink / raw)
  To: David Malcolm, GCC Development

[-- Attachment #1: Type: text/plain, Size: 4619 bytes --]

On 04/24/2018 06:27 PM, David Malcolm wrote:
> On Tue, 2018-04-24 at 16:45 +0200, Martin Liška wrote:
>> 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.htm
>> l
>> 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
> 
> Overall, looks good (albeit with various nits).  I like how you're
> reusing the m_option_suggestions machinery from the misspelled options
> code.  There are some awkward issues e.g. arch-specific completions,
> lang-specific completions, custom option-handling etc, but given that
> as-is this patch seems to be an improvement over the status quo, I'd
> prefer to tackle those later.

I'm sending second version of the patch. I did isolation of m_option_suggestions machinery
to a separate file. Mainly due to selftests that are linked with cc1.

> 
> The patch doesn't have tests.  There would need to be some way to
> achieve test coverage for the completion code (especially as we start
> to tackle the more interesting cases).  I wonder what the best way to
> do that is; perhaps a combination of selftest and DejaGnu?  (e.g. what
> about arch-specific completions? what about the interaction with bash?
> etc)

For now I come up with quite some selftests. Integration with bash&DejaGNU
would be challenging.

> 
> A few nits:
> * Do we want to hardcode that logging path in gcc.sh?

Sure, that needs to be purged. Crucial question here is where the gcc.sh script
should live. Note that clang has it in: ./tools/clang/utils/bash-autocomplete.sh
and:

head -n1 ./tools/clang/utils/bash-autocomplete.sh
# Please add "source /path/to/bash-autocomplete.sh" to your .bashrc to use this.

Which is not ideal. I would prefer to integrate the script into:
https://github.com/scop/bash-completion/blob/master/completions/gcc

Thoughts?

> 
> * Looks like m_option_suggestions isn't needed for handling the "-
> param" case, so maybe put the param-handling case before the "Lazily
> populate m_option_suggestions" code.
> 
> * You use "l" ("ell") as a variable name in two places, which I don't
> like, as IMHO it's too close to "1" (one) in some fonts.

Fixed both notes.
Thanks for fast review.

Martin

> 
> Thanks
> Dave
> 


[-- Attachment #2: 0001-Come-up-with-new-completion-option.patch --]
[-- Type: text/x-patch, Size: 30678 bytes --]

From 80d34e28ac6db6e63a0efe7d389bd9bfde40e434 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 23 Feb 2018 12:28:43 +0100
Subject: [PATCH] Come up with new --completion option.

---
 gcc.sh                     |  51 ++++++
 gcc/Makefile.in            |   2 +-
 gcc/c-family/cppspec.c     |   1 +
 gcc/common.opt             |   4 +
 gcc/fortran/gfortranspec.c |   1 +
 gcc/gcc-main.c             |   1 +
 gcc/gcc.c                  | 127 ++------------
 gcc/gcc.h                  |   4 +-
 gcc/opt-proposer.c         | 420 +++++++++++++++++++++++++++++++++++++++++++++
 gcc/opt-proposer.h         |  84 +++++++++
 gcc/opts.c                 |   3 +
 gcc/selftest-run-tests.c   |   1 +
 gcc/selftest.c             |  33 ++++
 gcc/selftest.h             |  21 +++
 14 files changed, 638 insertions(+), 115 deletions(-)
 create mode 100644 gcc.sh
 create mode 100644 gcc/opt-proposer.c
 create mode 100644 gcc/opt-proposer.h

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/Makefile.in b/gcc/Makefile.in
index 20bee0494b1..26fa3dd17df 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1617,7 +1617,7 @@ OBJS-libcommon = diagnostic.o diagnostic-color.o diagnostic-show-locus.o \
 # compiler and containing target-dependent code.
 OBJS-libcommon-target = $(common_out_object_file) prefix.o params.o \
 	opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \
-	hash-table.o file-find.o spellcheck.o selftest.o
+	hash-table.o file-find.o spellcheck.o selftest.o opt-proposer.o
 
 # This lists all host objects for the front ends.
 ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
diff --git a/gcc/c-family/cppspec.c b/gcc/c-family/cppspec.c
index 1e0a8bcd294..794b3ced529 100644
--- a/gcc/c-family/cppspec.c
+++ b/gcc/c-family/cppspec.c
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "opt-proposer.h"
 #include "gcc.h"
 #include "opts.h"
 
diff --git a/gcc/common.opt b/gcc/common.opt
index d6ef85928f3..9b4ba28f287 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -254,6 +254,10 @@ Driver Alias(S)
 -compile
 Driver Alias(c)
 
+-completion=
+Common Driver Joined Undocumented
+--param Bash completion.
+
 -coverage
 Driver Alias(coverage)
 
diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index fe1ec0447b3..b95c8810d0f 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "opt-proposer.h"
 #include "gcc.h"
 #include "opts.h"
 
diff --git a/gcc/gcc-main.c b/gcc/gcc-main.c
index 9e6de743adc..3cfdfdc57fa 100644
--- a/gcc/gcc-main.c
+++ b/gcc/gcc-main.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "obstack.h"
 #include "intl.h"
 #include "prefix.h"
+#include "opt-proposer.h"
 #include "gcc.h"
 
 /* Implement the top-level "main" within the driver in terms of
diff --git a/gcc/gcc.c b/gcc/gcc.c
index a716f708259..e9207bb9823 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -36,6 +36,7 @@ compilation is specified by a string called a "spec".  */
 #include "obstack.h"
 #include "intl.h"
 #include "prefix.h"
+#include "opt-proposer.h"
 #include "gcc.h"
 #include "diagnostic.h"
 #include "flags.h"
@@ -220,6 +221,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 +3821,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;
 
@@ -7262,8 +7270,7 @@ compare_files (char *cmpfile[])
 
 driver::driver (bool can_finalize, bool debug) :
   explicit_link_files (NULL),
-  decoded_options (NULL),
-  m_option_suggestions (NULL)
+  decoded_options (NULL)
 {
   env.init (can_finalize, debug);
 }
@@ -7272,14 +7279,6 @@ driver::~driver ()
 {
   XDELETEVEC (explicit_link_files);
   XDELETEVEC (decoded_options);
-  if (m_option_suggestions)
-    {
-      int i;
-      char *str;
-      FOR_EACH_VEC_ELT (*m_option_suggestions, i, str)
-	free (str);
-      delete m_option_suggestions;
-    }
 }
 
 /* driver::main is implemented as a series of driver:: method calls.  */
@@ -7300,6 +7299,12 @@ driver::main (int argc, char **argv)
   maybe_putenv_OFFLOAD_TARGETS ();
   handle_unrecognized_options ();
 
+  if (completion)
+    {
+      m_option_proposer.suggest_completion (completion);
+      return 0;
+    }
+
   if (!maybe_print_and_exit ())
     return 0;
 
@@ -7768,106 +7773,6 @@ driver::maybe_putenv_OFFLOAD_TARGETS () const
   offload_targets = NULL;
 }
 
-/* Helper function for driver::suggest_option.  Populate
-   m_option_suggestions with candidate strings for misspelled options.
-   The strings will be freed by the driver's dtor.  */
-
-void
-driver::build_option_suggestions (void)
-{
-  gcc_assert (m_option_suggestions == NULL);
-  m_option_suggestions = new auto_vec <char *> ();
-
-  /* We build a vec of m_option_suggestions, using add_misspelling_candidates
-     to add copies of strings, without a leading dash.  */
-
-  for (unsigned int i = 0; i < cl_options_count; i++)
-    {
-      const struct cl_option *option = &cl_options[i];
-      const char *opt_text = option->opt_text;
-      switch (i)
-	{
-	default:
-	  if (option->var_type == CLVC_ENUM)
-	    {
-	      const struct cl_enum *e = &cl_enums[option->var_enum];
-	      for (unsigned j = 0; e->values[j].arg != NULL; j++)
-		{
-		  char *with_arg = concat (opt_text, e->values[j].arg, NULL);
-		  add_misspelling_candidates (m_option_suggestions, option,
-					      with_arg);
-		  free (with_arg);
-		}
-	    }
-	  else
-	    add_misspelling_candidates (m_option_suggestions, option,
-					opt_text);
-	  break;
-
-	case OPT_fsanitize_:
-	case OPT_fsanitize_recover_:
-	  /* -fsanitize= and -fsanitize-recover= can take
-	     a comma-separated list of arguments.  Given that combinations
-	     are supported, we can't add all potential candidates to the
-	     vec, but if we at least add them individually without commas,
-	     we should do a better job e.g. correcting
-	       "-sanitize=address"
-	     to
-	       "-fsanitize=address"
-	     rather than to "-Wframe-address" (PR driver/69265).  */
-	  {
-	    for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
-	      {
-		struct cl_option optb;
-		/* -fsanitize=all is not valid, only -fno-sanitize=all.
-		   So don't register the positive misspelling candidates
-		   for it.  */
-		if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_)
-		  {
-		    optb = *option;
-		    optb.opt_text = opt_text = "-fno-sanitize=";
-		    optb.cl_reject_negative = true;
-		    option = &optb;
-		  }
-		/* Get one arg at a time e.g. "-fsanitize=address".  */
-		char *with_arg = concat (opt_text,
-					 sanitizer_opts[j].name,
-					 NULL);
-		/* Add with_arg and all of its variant spellings e.g.
-		   "-fno-sanitize=address" to candidates (albeit without
-		   leading dashes).  */
-		add_misspelling_candidates (m_option_suggestions, option,
-					    with_arg);
-		free (with_arg);
-	      }
-	  }
-	  break;
-	}
-    }
-}
-
-/* Helper function for driver::handle_unrecognized_options.
-
-   Given an unrecognized option BAD_OPT (without the leading dash),
-   locate the closest reasonable matching option (again, without the
-   leading dash), or NULL.
-
-   The returned string is owned by the driver instance.  */
-
-const char *
-driver::suggest_option (const char *bad_opt)
-{
-  /* Lazily populate m_option_suggestions.  */
-  if (!m_option_suggestions)
-    build_option_suggestions ();
-  gcc_assert (m_option_suggestions);
-
-  /* "m_option_suggestions" is now populated.  Use it.  */
-  return find_closest_string
-    (bad_opt,
-     (auto_vec <const char *> *) m_option_suggestions);
-}
-
 /* Reject switches that no pass was interested in.  */
 
 void
@@ -7876,7 +7781,7 @@ driver::handle_unrecognized_options ()
   for (size_t i = 0; (int) i < n_switches; i++)
     if (! switches[i].validated)
       {
-	const char *hint = suggest_option (switches[i].part1);
+	const char *hint = m_option_proposer.suggest_option (switches[i].part1);
 	if (hint)
 	  error ("unrecognized command line option %<-%s%>;"
 		 " did you mean %<-%s%>?",
diff --git a/gcc/gcc.h b/gcc/gcc.h
index ddbf42f78ea..a7606183393 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -45,8 +45,6 @@ class driver
   void putenv_COLLECT_GCC (const char *argv0) const;
   void maybe_putenv_COLLECT_LTO_WRAPPER () const;
   void maybe_putenv_OFFLOAD_TARGETS () const;
-  void build_option_suggestions (void);
-  const char *suggest_option (const char *bad_opt);
   void handle_unrecognized_options ();
   int maybe_print_and_exit () const;
   bool prepare_infiles ();
@@ -59,7 +57,7 @@ class driver
   char *explicit_link_files;
   struct cl_decoded_option *decoded_options;
   unsigned int decoded_options_count;
-  auto_vec <char *> *m_option_suggestions;
+  option_proposer m_option_proposer;
 };
 
 /* The mapping of a spec function name to the C function that
diff --git a/gcc/opt-proposer.c b/gcc/opt-proposer.c
new file mode 100644
index 00000000000..08379f0b631
--- /dev/null
+++ b/gcc/opt-proposer.c
@@ -0,0 +1,420 @@
+/* Provide option suggestion for --complete option and a misspelled
+   used by a user.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "opts.h"
+#include "params.h"
+#include "spellcheck.h"
+#include "opt-proposer.h"
+#include "selftest.h"
+
+option_proposer::~option_proposer ()
+{
+  if (m_option_suggestions)
+    {
+      int i;
+      char *str;
+      FOR_EACH_VEC_ELT (*m_option_suggestions, i, str)
+       free (str);
+      delete m_option_suggestions;
+    }
+
+  release_completion_results ();
+}
+
+const char *
+option_proposer::suggest_option (const char *bad_opt)
+{
+  /* Lazily populate m_option_suggestions.  */
+  if (!m_option_suggestions)
+    build_option_suggestions ();
+  gcc_assert (m_option_suggestions);
+
+  /* "m_option_suggestions" is now populated.  Use it.  */
+  return find_closest_string
+    (bad_opt,
+     (auto_vec <const char *> *) m_option_suggestions);
+}
+
+void
+option_proposer::build_completions (const char *starting)
+{
+  release_completion_results ();
+
+  /* Bail out for an invalid input.  */
+  if (starting == NULL || starting[0] == '\0')
+    return;
+
+  if (starting[0] == '-')
+    starting++;
+
+  size_t length = strlen (starting);
+
+  /* Handle parameters.  */
+  const char *prefix = "-param";
+  if (length >= 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 == '=')
+	find_param_completions (separator, starting);
+    }
+  else
+    {
+      /* Lazily populate m_option_suggestions.  */
+      if (!m_option_suggestions)
+	build_option_suggestions ();
+      gcc_assert (m_option_suggestions);
+
+      for (unsigned i = 0; i < m_option_suggestions->length (); i++)
+	{
+	  char *candidate = (*m_option_suggestions)[i];
+	  if (strlen (candidate) >= length
+	      && strstr (candidate, starting) == candidate)
+	    m_completion_results.safe_push (concat ("-", candidate, NULL));
+	}
+    }
+}
+
+void
+option_proposer::suggest_completion (const char *starting)
+{
+  build_completions (starting);
+  print_completion_results ();
+  release_completion_results ();
+}
+
+auto_vec <char *> *
+option_proposer::get_completion_suggestions (const char *starting)
+{
+  build_completions (starting);
+  return &m_completion_results;
+}
+
+void
+option_proposer::build_option_suggestions (void)
+{
+  gcc_assert (m_option_suggestions == NULL);
+  m_option_suggestions = new auto_vec <char *> ();
+
+  /* We build a vec of m_option_suggestions, using add_misspelling_candidates
+     to add copies of strings, without a leading dash.  */
+
+  for (unsigned int i = 0; i < cl_options_count; i++)
+    {
+      const struct cl_option *option = &cl_options[i];
+      const char *opt_text = option->opt_text;
+      switch (i)
+	{
+	default:
+	  if (option->var_type == CLVC_ENUM)
+	    {
+	      const struct cl_enum *e = &cl_enums[option->var_enum];
+	      for (unsigned j = 0; e->values[j].arg != NULL; j++)
+		{
+		  char *with_arg = concat (opt_text, e->values[j].arg, NULL);
+		  add_misspelling_candidates (m_option_suggestions, option,
+					      with_arg);
+		  free (with_arg);
+		}
+	    }
+	  else
+	    add_misspelling_candidates (m_option_suggestions, option,
+					opt_text);
+	  break;
+
+	case OPT_fsanitize_:
+	case OPT_fsanitize_recover_:
+	  /* -fsanitize= and -fsanitize-recover= can take
+	     a comma-separated list of arguments.  Given that combinations
+	     are supported, we can't add all potential candidates to the
+	     vec, but if we at least add them individually without commas,
+	     we should do a better job e.g. correcting
+	       "-sanitize=address"
+	     to
+	       "-fsanitize=address"
+	     rather than to "-Wframe-address" (PR driver/69265).  */
+	  {
+	    for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
+	      {
+		struct cl_option optb;
+		/* -fsanitize=all is not valid, only -fno-sanitize=all.
+		   So don't register the positive misspelling candidates
+		   for it.  */
+		if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_)
+		  {
+		    optb = *option;
+		    optb.opt_text = opt_text = "-fno-sanitize=";
+		    optb.cl_reject_negative = true;
+		    option = &optb;
+		  }
+		/* Get one arg at a time e.g. "-fsanitize=address".  */
+		char *with_arg = concat (opt_text,
+					 sanitizer_opts[j].name,
+					 NULL);
+		/* Add with_arg and all of its variant spellings e.g.
+		   "-fno-sanitize=address" to candidates (albeit without
+		   leading dashes).  */
+		add_misspelling_candidates (m_option_suggestions, option,
+					    with_arg);
+		free (with_arg);
+	      }
+	  }
+	  break;
+	}
+    }
+}
+
+void
+option_proposer::find_param_completions (const char separator,
+					 const char *starting)
+{
+  char separator_str[] {separator, '\0'};
+  size_t length = strlen (starting);
+  for (unsigned i = 0; i < get_num_compiler_params (); ++i)
+    {
+      const char *candidate = compiler_params[i].option;
+      if (strlen (candidate) >= length
+	  && strstr (candidate, starting) == candidate)
+	m_completion_results.safe_push (concat ("--param", separator_str,
+						candidate, NULL));
+    }
+}
+
+void
+option_proposer::print_completion_results ()
+{
+  for (unsigned i = 0; i < m_completion_results.length (); i++)
+    printf ("%s\n", m_completion_results[i]);
+}
+
+void
+option_proposer::release_completion_results ()
+{
+  for (unsigned i = 0; i < m_completion_results.length (); i++)
+    free (m_completion_results[i]);
+
+  m_completion_results.truncate (0);
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+static void
+test_valid_option (option_proposer &proposer, const char *option)
+{
+  auto_vec <char *> *suggestions = proposer.get_completion_suggestions (option);
+  ASSERT_GT (suggestions->length (), 0);
+
+  for (unsigned i = 0; i < suggestions->length (); i++)
+    ASSERT_STR_STARTSWITH ((*suggestions)[i], option);
+}
+
+/* Verify that valid options works correctly.  */
+
+static void
+test_completion_valid_options (option_proposer &proposer)
+{
+  const char *needles[]
+  {
+    "-fno-var-tracking-assignments-toggle",
+    "-fpredictive-commoning",
+    "--param=stack-clash-protection-guard-size",
+    "--param=max-predicted-iterations",
+    "-ftree-loop-distribute-patterns",
+    "-fno-var-tracking",
+    "-Walloc-zero",
+    "--param=ipa-cp-value-list-size",
+    "-Wsync-nand",
+    "-Wno-attributes",
+    "--param=tracer-dynamic-coverage-feedback",
+    "-Wno-format-contains-nul",
+    "-Wnamespaces",
+    "-fisolate-erroneous-paths-attribute",
+    "-Wno-underflow",
+    "-Wtarget-lifetime",
+    "--param=asan-globals",
+    "-Wno-empty-body",
+    "-Wno-odr",
+    "-Wformat-zero-length",
+    "-Wstringop-truncation",
+    "-fno-ipa-vrp",
+    "-fmath-errno",
+    "-Warray-temporaries",
+    "-Wno-unused-label",
+    "-Wreturn-local-addr",
+    "--param=sms-dfa-history",
+    "--param=asan-instrument-reads",
+    "-Wreturn-type",
+    "-Wc++17-compat",
+    "-Wno-effc++",
+    "--param=max-fields-for-field-sensitive",
+    "-fisolate-erroneous-paths-dereference",
+    "-fno-defer-pop",
+    "-Wcast-align=strict",
+    "-foptimize-strlen",
+    "-Wpacked-not-aligned",
+    "-funroll-loops",
+    "-fif-conversion2",
+    "-Wdesignated-init",
+    "--param=max-iterations-computation-cost",
+    "-Wmultiple-inheritance",
+    "-fno-sel-sched-reschedule-pipelined",
+    "-Wassign-intercept",
+    "-Wno-format-security",
+    "-fno-sched-stalled-insns",
+    "-fbtr-bb-exclusive",
+    "-fno-tree-tail-merge",
+    "-Wlong-long",
+    "-Wno-unused-but-set-parameter",
+    NULL
+  };
+
+  for (const char **ptr = needles; *ptr != NULL; ptr++)
+    test_valid_option (proposer, *ptr);
+}
+
+/* Verify that valid parameter works correctly.  */
+
+static void
+test_completion_valid_params (option_proposer &proposer)
+{
+  const char *needles[]
+  {
+    "--param=sched-state-edge-prob-cutoff",
+    "--param=iv-consider-all-candidates-bound",
+    "--param=align-threshold",
+    "--param=prefetch-min-insn-to-mem-ratio",
+    "--param=max-unrolled-insns",
+    "--param=max-early-inliner-iterations",
+    "--param=max-vartrack-reverse-op-size",
+    "--param=ipa-cp-loop-hint-bonus",
+    "--param=tracer-min-branch-ratio",
+    "--param=graphite-max-arrays-per-scop",
+    "--param=sink-frequency-threshold",
+    "--param=max-cse-path-length",
+    "--param=sra-max-scalarization-size-Osize",
+    "--param=prefetch-latency",
+    "--param=dse-max-object-size",
+    "--param=asan-globals",
+    "--param=max-vartrack-size",
+    "--param=case-values-threshold",
+    "--param=max-slsr-cand-scan",
+    "--param=min-insn-to-prefetch-ratio",
+    "--param=tracer-min-branch-probability",
+    "--param sink-frequency-threshold",
+    "--param max-cse-path-length",
+    "--param sra-max-scalarization-size-Osize",
+    "--param prefetch-latency",
+    "--param dse-max-object-size",
+    "--param asan-globals",
+    "--param max-vartrack-size",
+    NULL
+  };
+
+  for (const char **ptr = needles; *ptr != NULL; ptr++)
+    test_valid_option (proposer, *ptr);
+}
+
+/* Return true when EXPECTED is one of completions for OPTION string.  */
+
+static bool
+in_completion_p (option_proposer &proposer, const char *option,
+		 const char *expected)
+{
+  auto_vec <char *> *suggestions = proposer.get_completion_suggestions (option);
+
+  for (unsigned i = 0; i < suggestions->length (); i++)
+    {
+      char *r = (*suggestions)[i];
+      if (strcmp (r, expected) == 0)
+	return true;
+    }
+
+  return false;
+}
+
+static bool
+empty_completion_p (option_proposer &proposer, const char *option)
+{
+  auto_vec <char *> *suggestions = proposer.get_completion_suggestions (option);
+  return suggestions->is_empty ();
+}
+
+/* Verify partial completions.  */
+
+static void
+test_completion_partial_match (option_proposer &proposer)
+{
+  ASSERT_TRUE (in_completion_p (proposer, "-fsani", "-fsanitize=address"));
+  ASSERT_TRUE (in_completion_p (proposer, "-fsani",
+				"-fsanitize-address-use-after-scope"));
+  ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf-functions"));
+  ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf"));
+  ASSERT_TRUE (in_completion_p (proposer, "--param=",
+				"--param=max-vartrack-reverse-op-size"));
+  ASSERT_TRUE (in_completion_p (proposer, "--param ",
+				"--param max-vartrack-reverse-op-size"));
+
+  ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf", "-fipa"));
+  ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf-functions", "-fipa-icf"));
+}
+
+/* Verify that a garbage does not return a completion match.  */
+
+static void
+test_completion_garbage (option_proposer &proposer)
+{
+  ASSERT_TRUE (empty_completion_p (proposer, NULL));
+  ASSERT_TRUE (empty_completion_p (proposer, ""));
+  ASSERT_TRUE (empty_completion_p (proposer, "- "));
+  ASSERT_TRUE (empty_completion_p (proposer, "123456789"));
+  ASSERT_TRUE (empty_completion_p (proposer, "---------"));
+  ASSERT_TRUE (empty_completion_p (proposer, "#########"));
+  ASSERT_TRUE (empty_completion_p (proposer, "- - - - - -"));
+  ASSERT_TRUE (empty_completion_p (proposer, "-fsanitize=address2"));
+
+  ASSERT_FALSE (empty_completion_p (proposer, "-"));
+  ASSERT_FALSE (empty_completion_p (proposer, "-fipa"));
+  ASSERT_FALSE (empty_completion_p (proposer, "--par"));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+opt_proposer_c_tests ()
+{
+  option_proposer proposer;
+
+  test_completion_valid_options (proposer);
+  test_completion_valid_params (proposer);
+  test_completion_partial_match (proposer);
+  test_completion_garbage (proposer);
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/opt-proposer.h b/gcc/opt-proposer.h
new file mode 100644
index 00000000000..b673f02dc70
--- /dev/null
+++ b/gcc/opt-proposer.h
@@ -0,0 +1,84 @@
+/* Provide option suggestion for --complete option and a misspelled
+   used by a user.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_OPT_PROPOSER_H
+#define GCC_OPT_PROPOSER_H
+
+/* Option proposer is class used by driver in order to provide hints
+   for wrong options provided.  And it's used by --complete option that's
+   intended to be invoked by BASH in order to provide better option
+   completion support.  */
+
+class option_proposer
+{
+public:
+  /* Default constructor.  */
+  option_proposer (): m_option_suggestions (NULL), m_completion_results ()
+  {}
+
+  /* Default destructor.  */
+  ~option_proposer ();
+
+  /* Helper function for driver::handle_unrecognized_options.
+
+     Given an unrecognized option BAD_OPT (without the leading dash),
+     locate the closest reasonable matching option (again, without the
+     leading dash), or NULL.
+
+     The returned string is owned by the option_proposer instance.  */
+  const char *suggest_option (const char *bad_opt);
+
+  /* Print to stdout all options that start with STARTING.  */
+  void suggest_completion (const char *starting);
+
+  /* Return vector with completion suggestions that start with STARTING.
+
+     The returned strings are owned by the option_proposer instance.  */
+  auto_vec <char *> *get_completion_suggestions (const char *starting);
+
+private:
+  /* Helper function for option_proposer::suggest_option.  Populate
+     m_option_suggestions with candidate strings for misspelled options.
+     The strings will be freed by the option_proposer's dtor.  */
+  void build_option_suggestions ();
+
+  /* Build completions that start with STARTING and save them
+     into m_completion_results vector.  */
+  void build_completions (const char *starting);
+
+  /* Find parameter completions for --param format with SEPARATOR.
+     Again, save the completions into m_completion_results.  */
+  void find_param_completions (const char separator, const char *starting);
+
+  /* Print found completions in m_completion_results to stdout.  */
+  void print_completion_results ();
+
+  /* Free content of m_completion_results.  */
+  void release_completion_results ();
+
+private:
+  /* Cache with all suggestions.  */
+  auto_vec <char *> *m_option_suggestions;
+
+  /* Completion cache.  */
+  auto_vec <char *> m_completion_results;
+};
+
+#endif  /* GCC_OPT_PROPOSER_H */
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/selftest-run-tests.c b/gcc/selftest-run-tests.c
index fe221ff8946..0b45c479192 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -70,6 +70,7 @@ selftest::run_tests ()
   fibonacci_heap_c_tests ();
   typed_splay_tree_c_tests ();
   unique_ptr_tests_cc_tests ();
+  opt_proposer_c_tests ();
 
   /* Mid-level data structures.  */
   input_c_tests ();
diff --git a/gcc/selftest.c b/gcc/selftest.c
index 5709110c291..4cff89d2909 100644
--- a/gcc/selftest.c
+++ b/gcc/selftest.c
@@ -118,6 +118,39 @@ assert_str_contains (const location &loc,
 	 desc_haystack, desc_needle, val_haystack, val_needle);
 }
 
+/* Implementation detail of ASSERT_STR_STARTSWITH.
+   Use strstr to determine if val_haystack starts with val_needle.
+   ::selftest::pass if it starts.
+   ::selftest::fail if it does not start.  */
+
+void
+assert_str_startswith (const location &loc,
+		       const char *desc_haystack,
+		       const char *desc_needle,
+		       const char *val_haystack,
+		       const char *val_needle)
+{
+  /* If val_haystack is NULL, fail with a custom error message.  */
+  if (val_haystack == NULL)
+    fail_formatted (loc, "ASSERT_STR_STARTSWITH (%s, %s) haystack=NULL",
+		    desc_haystack, desc_needle);
+
+  /* If val_needle is NULL, fail with a custom error message.  */
+  if (val_needle == NULL)
+    fail_formatted (loc,
+		    "ASSERT_STR_STARTSWITH (%s, %s) haystack=\"%s\" needle=NULL",
+		    desc_haystack, desc_needle, val_haystack);
+
+  const char *test = strstr (val_haystack, val_needle);
+  if (test == val_haystack)
+    pass (loc, "ASSERT_STR_STARTSWITH");
+  else
+    fail_formatted
+	(loc, "ASSERT_STR_STARTSWITH (%s, %s) haystack=\"%s\" needle=\"%s\"",
+	 desc_haystack, desc_needle, val_haystack, val_needle);
+}
+
+
 /* Constructor.  Generate a name for the file.  */
 
 named_temp_file::named_temp_file (const char *suffix)
diff --git a/gcc/selftest.h b/gcc/selftest.h
index e3117c6bfc4..b5d7eeef86e 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -78,6 +78,15 @@ extern void assert_str_contains (const location &loc,
 				 const char *val_haystack,
 				 const char *val_needle);
 
+/* Implementation detail of ASSERT_STR_STARTSWITH.  */
+
+extern void assert_str_startswith (const location &loc,
+				   const char *desc_expected,
+				   const char *desc_actual,
+				   const char *val_expected,
+				   const char *val_actual);
+
+
 /* A named temporary file for use in selftests.
    Usable for writing out files, and as the base class for
    temp_source_file.
@@ -216,6 +225,7 @@ extern void wide_int_cc_tests ();
 extern void predict_c_tests ();
 extern void simplify_rtx_c_tests ();
 extern void vec_perm_indices_c_tests ();
+extern void opt_proposer_c_tests ();
 
 extern int num_passes;
 
@@ -401,6 +411,17 @@ extern int num_passes;
 				   (HAYSTACK), (NEEDLE));		\
   SELFTEST_END_STMT
 
+/* Evaluate HAYSTACK and NEEDLE and use strstr to determine if HAYSTACK
+   starts with NEEDLE.
+   ::selftest::pass if starts.
+   ::selftest::fail if does not start.  */
+
+#define ASSERT_STR_STARTSWITH(HAYSTACK, NEEDLE)				    \
+  SELFTEST_BEGIN_STMT							    \
+  ::selftest::assert_str_startswith (SELFTEST_LOCATION, #HAYSTACK, #NEEDLE, \
+				     (HAYSTACK), (NEEDLE));		    \
+  SELFTEST_END_STMT
+
 /* Evaluate PRED1 (VAL1), calling ::selftest::pass if it is true,
    ::selftest::fail if it is false.  */
 
-- 
2.16.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: bash completion
  2018-04-24 16:49 ` David Malcolm
  2018-04-25 13:13   ` Martin Liška
@ 2018-04-25 13:53   ` Martin Liška
  1 sibling, 0 replies; 9+ messages in thread
From: Martin Liška @ 2018-04-25 13:53 UTC (permalink / raw)
  To: David Malcolm, GCC Development

On 04/24/2018 06:27 PM, David Malcolm wrote:
> The patch doesn't have tests.  There would need to be some way to
> achieve test coverage for the completion code (especially as we start
> to tackle the more interesting cases).  I wonder what the best way to
> do that is; perhaps a combination of selftest and DejaGnu?  (e.g. what
> about arch-specific completions? what about the interaction with bash?
> etc)

Maybe there's some hint how to test that:
https://brbsix.github.io/2015/11/29/accessing-tab-completion-programmatically-in-bash/

Martin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] Add new tests for --completion option.
  2018-04-24 15:00 RFC: bash completion Martin Liška
  2018-04-24 16:49 ` David Malcolm
@ 2018-06-29 15:04 ` Martin Liška
  2018-06-29 17:19   ` Jeff Law
  2018-06-29 18:04   ` Eric Gallager
  1 sibling, 2 replies; 9+ messages in thread
From: Martin Liška @ 2018-06-29 15:04 UTC (permalink / raw)
  To: GCC Development; +Cc: David Malcolm

[-- Attachment #1: Type: text/plain, Size: 92 bytes --]

Hi.

I would like to add some DejaGNU tests for completion option.

Ready for trunk?
Martin

[-- Attachment #2: 0001-Add-new-tests-for-completion-option.patch --]
[-- Type: text/x-patch, Size: 2249 bytes --]

From a735068032aa9ce82e5f56172f1b99bc2c90ac0f Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 29 Jun 2018 11:18:21 +0200
Subject: [PATCH] Add new tests for --completion option.

gcc/testsuite/ChangeLog:

2018-06-29  Martin Liska  <mliska@suse.cz>

	* gcc.dg/completion-1.c: New test.
	* gcc.dg/completion-2.c: New test.
	* gcc.dg/completion-3.c: New test.
---
 gcc/testsuite/gcc.dg/completion-1.c |  8 ++++++++
 gcc/testsuite/gcc.dg/completion-2.c | 10 ++++++++++
 gcc/testsuite/gcc.dg/completion-3.c | 13 +++++++++++++
 3 files changed, 31 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/completion-1.c
 create mode 100644 gcc/testsuite/gcc.dg/completion-2.c
 create mode 100644 gcc/testsuite/gcc.dg/completion-3.c

diff --git a/gcc/testsuite/gcc.dg/completion-1.c b/gcc/testsuite/gcc.dg/completion-1.c
new file mode 100644
index 00000000000..64da64f1c69
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/completion-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "--completion=-fipa-ic" } */
+
+/* { dg-begin-multiline-output "" }
+-fipa-icf
+-fipa-icf-functions
+-fipa-icf-variables
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/completion-2.c b/gcc/testsuite/gcc.dg/completion-2.c
new file mode 100644
index 00000000000..ac7508591de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/completion-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "--completion=-flto-parti" } */
+
+/* { dg-begin-multiline-output "" }
+-flto-partition=1to1
+-flto-partition=balanced
+-flto-partition=max
+-flto-partition=none
+-flto-partition=one
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/completion-3.c b/gcc/testsuite/gcc.dg/completion-3.c
new file mode 100644
index 00000000000..3c4a89ffdd5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/completion-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "--completion=--param=asan-" } */
+
+/* { dg-begin-multiline-output "" }
+--param=asan-stack
+--param=asan-instrument-allocas
+--param=asan-globals
+--param=asan-instrument-writes
+--param=asan-instrument-reads
+--param=asan-memintrin
+--param=asan-use-after-return
+--param=asan-instrumentation-with-call-threshold
+   { dg-end-multiline-output "" } */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add new tests for --completion option.
  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
  1 sibling, 0 replies; 9+ messages in thread
From: Jeff Law @ 2018-06-29 17:19 UTC (permalink / raw)
  To: Martin Liška, GCC Development; +Cc: David Malcolm

On 06/29/2018 03:20 AM, Martin Liška wrote:
> Hi.
> 
> I would like to add some DejaGNU tests for completion option.
> 
> Ready for trunk?
> Martin
> 
> 
> 0001-Add-new-tests-for-completion-option.patch
> 
> 
> From a735068032aa9ce82e5f56172f1b99bc2c90ac0f Mon Sep 17 00:00:00 2001
> From: marxin <mliska@suse.cz>
> Date: Fri, 29 Jun 2018 11:18:21 +0200
> Subject: [PATCH] Add new tests for --completion option.
> 
> gcc/testsuite/ChangeLog:
> 
> 2018-06-29  Martin Liska  <mliska@suse.cz>
> 
> 	* gcc.dg/completion-1.c: New test.
> 	* gcc.dg/completion-2.c: New test.
> 	* gcc.dg/completion-3.c: New test.
OK
jeff

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add new tests for --completion option.
  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
  1 sibling, 1 reply; 9+ messages in thread
From: Eric Gallager @ 2018-06-29 18:04 UTC (permalink / raw)
  To: Martin Liška; +Cc: GCC Development, David Malcolm

On 6/29/18, Martin Liška <mliska@suse.cz> wrote:
> Hi.
>
> I would like to add some DejaGNU tests for completion option.
>
> Ready for trunk?
> Martin
>

So, correct me if I'm wrong, but these tests would need to be updated
every time a new option starting like one of those is added, right? If
so, can you think of any ways to ease the increased maintenance
efforts?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add new tests for --completion option.
  2018-06-29 18:04   ` Eric Gallager
@ 2018-06-29 22:41     ` David Malcolm
  2018-07-02  9:52       ` Martin Liška
  0 siblings, 1 reply; 9+ messages in thread
From: David Malcolm @ 2018-06-29 22:41 UTC (permalink / raw)
  To: Eric Gallager, Martin Liška; +Cc: GCC Development

On Fri, 2018-06-29 at 13:19 -0400, Eric Gallager wrote:
> On 6/29/18, Martin Liška <mliska@suse.cz> wrote:
> > Hi.
> > 
> > I would like to add some DejaGNU tests for completion option.
> > 
> > Ready for trunk?
> > Martin

Presumably the point of the DejaGnu tests is:
(a) to give us some integration testing, to complement the unit-tests
expressed via "selftest::" in the code
(b) in future, to allow for target-specific tests for the aspects of
completion (some target-specific options have non-standard arg-parsing, 
iirc, so might need special-casing if the completion code is to be
perfect).  Also, it allows for other DejaGnu-based filters to be used.

> So, correct me if I'm wrong, but these tests would need to be updated
> every time a new option starting like one of those is added, right? 

You're correct.

> If
> so, can you think of any ways to ease the increased maintenance
> efforts?

I think/hope Martin picked option prefixes for which the results are
relatively stable.

If it turns out to be a pain, other options can be chosen, but I guess
we can cross that bridge when we come to it.

Dave

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Add new tests for --completion option.
  2018-06-29 22:41     ` David Malcolm
@ 2018-07-02  9:52       ` Martin Liška
  0 siblings, 0 replies; 9+ messages in thread
From: Martin Liška @ 2018-07-02  9:52 UTC (permalink / raw)
  To: David Malcolm, Eric Gallager; +Cc: GCC Development

On 06/29/2018 08:04 PM, David Malcolm wrote:
> On Fri, 2018-06-29 at 13:19 -0400, Eric Gallager wrote:
>> On 6/29/18, Martin Liška <mliska@suse.cz> wrote:
>>> Hi.
>>>
>>> I would like to add some DejaGNU tests for completion option.
>>>
>>> Ready for trunk?
>>> Martin
> 
> Presumably the point of the DejaGnu tests is:
> (a) to give us some integration testing, to complement the unit-tests
> expressed via "selftest::" in the code
> (b) in future, to allow for target-specific tests for the aspects of
> completion (some target-specific options have non-standard arg-parsing,
> iirc, so might need special-casing if the completion code is to be
> perfect).  Also, it allows for other DejaGnu-based filters to be used.

Interesting idea to cover target specialities. I'll write that on my TODO
list. It's closely related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83193
where I plan some enhancements.

> 
>> So, correct me if I'm wrong, but these tests would need to be updated
>> every time a new option starting like one of those is added, right?
> 
> You're correct.
> 
>> If
>> so, can you think of any ways to ease the increased maintenance
>> efforts?
> 
> I think/hope Martin picked option prefixes for which the results are
> relatively stable.

Exactly, it should be relatively stable over a time.

Martin

> 
> If it turns out to be a pain, other options can be chosen, but I guess
> we can cross that bridge when we come to it.
> 
> Dave
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-07-02  9:52 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-24 15:00 RFC: bash completion Martin Liška
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

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).