diff mbox

Pass cl_decoded_option structures to more option handling interfaces

Message ID Pine.LNX.4.64.1008110044450.32339@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Aug. 11, 2010, 12:45 a.m. UTC
In the course of preparing the patch that makes the driver use the
shared option processing machinery to handle its own options, I found
that in various cases it is useful for the option handlers in the
driver to have direct access to the cl_decoded_option structure
instead of just the parts of it currently passed to handlers as
separate arguments - specifically, having the canonical form of an
option-plus-arguments is useful for the driver code saving options for
subsequent spec processing.

This patch accordingly arranges for various handlers to take
cl_decoded_option structures.  Where they then pass on the separate
arguments to other functions, they assert that options with more than
one argument are not involved (at present such options can only arise
through SWITCH_TAKES_ARG/WORD_SWITCH_TAKES_ARG, but with the move of
all driver options to the .opt machinery such options will be
describable in .opt files in future), since the separate arguments are
not sufficient to describe such options.

handle_option is called recursively to handle options implied by other
options, in the context of -Werror=some-option in particular.  These
recursive calls do not naturally have a cl_decoded_option structure; I
added handle_generated_option, which reconstructs such a structure
from the separate arguments, for use of those calls.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
commit?

2010-08-10  Joseph Myers  <joseph@codesourcery.com>

	* opts.h (struct cl_option_handler_func): Make handler take
	cl_decoded_option structure as parameter, not individual elements.
	(struct cl_option_handlers): Make callbacks take cl_decoded_option
	structure as parameter, not individual elements.
	(handle_option): Take cl_decoded_option structure as parameter,
	not individual elements.
	(handle_generated_option): Declare.
	* opts-common.c (handle_option): Take cl_decoded_option structure
	as parameter, not individual elements.  Update calls to callback
	and handler functions.
	(handle_generated_option): New.
	(read_cmdline_option): Update calls to callback functions and
	handle_option.
	* opts.c (common_handle_option, complain_wrong_lang,
	unknown_option_callback, post_handling_callback,
	lang_handle_option, target_handle_option): Take cl_decoded_option
	structure as parameter, not individual elements.
	(lang_handle_option, target_handle_option, common_handle_option):
	Assert option has at most one argument.
	(enable_warning_as_error): Call handle_generated_option instead of
	handle_option.  Do not pass -Werror argument as argument of
	generated option.

c-family:
2010-08-10  Joseph Myers  <joseph@codesourcery.com>

	* c-opts.c (c_common_handle_option): Call handle_generated_option
	instead of handle_option.

Comments

Richard Biener Aug. 11, 2010, 8:59 a.m. UTC | #1
On Wed, Aug 11, 2010 at 2:45 AM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> In the course of preparing the patch that makes the driver use the
> shared option processing machinery to handle its own options, I found
> that in various cases it is useful for the option handlers in the
> driver to have direct access to the cl_decoded_option structure
> instead of just the parts of it currently passed to handlers as
> separate arguments - specifically, having the canonical form of an
> option-plus-arguments is useful for the driver code saving options for
> subsequent spec processing.
>
> This patch accordingly arranges for various handlers to take
> cl_decoded_option structures.  Where they then pass on the separate
> arguments to other functions, they assert that options with more than
> one argument are not involved (at present such options can only arise
> through SWITCH_TAKES_ARG/WORD_SWITCH_TAKES_ARG, but with the move of
> all driver options to the .opt machinery such options will be
> describable in .opt files in future), since the separate arguments are
> not sufficient to describe such options.
>
> handle_option is called recursively to handle options implied by other
> options, in the context of -Werror=some-option in particular.  These
> recursive calls do not naturally have a cl_decoded_option structure; I
> added handle_generated_option, which reconstructs such a structure
> from the separate arguments, for use of those calls.
>
> Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
> commit?

Ok.

Thanks,
Richard.

> 2010-08-10  Joseph Myers  <joseph@codesourcery.com>
>
>        * opts.h (struct cl_option_handler_func): Make handler take
>        cl_decoded_option structure as parameter, not individual elements.
>        (struct cl_option_handlers): Make callbacks take cl_decoded_option
>        structure as parameter, not individual elements.
>        (handle_option): Take cl_decoded_option structure as parameter,
>        not individual elements.
>        (handle_generated_option): Declare.
>        * opts-common.c (handle_option): Take cl_decoded_option structure
>        as parameter, not individual elements.  Update calls to callback
>        and handler functions.
>        (handle_generated_option): New.
>        (read_cmdline_option): Update calls to callback functions and
>        handle_option.
>        * opts.c (common_handle_option, complain_wrong_lang,
>        unknown_option_callback, post_handling_callback,
>        lang_handle_option, target_handle_option): Take cl_decoded_option
>        structure as parameter, not individual elements.
>        (lang_handle_option, target_handle_option, common_handle_option):
>        Assert option has at most one argument.
>        (enable_warning_as_error): Call handle_generated_option instead of
>        handle_option.  Do not pass -Werror argument as argument of
>        generated option.
>
> c-family:
> 2010-08-10  Joseph Myers  <joseph@codesourcery.com>
>
>        * c-opts.c (c_common_handle_option): Call handle_generated_option
>        instead of handle_option.
>
> Index: gcc/opts-common.c
> ===================================================================
> --- gcc/opts-common.c   (revision 162909)
> +++ gcc/opts-common.c   (working copy)
> @@ -496,17 +496,19 @@ done:
>   free (options);
>  }
>
> -/* Handle option OPT_INDEX, and argument ARG, for the language
> -   indicated by LANG_MASK, using the handlers in HANDLERS.  VALUE is
> -   the option value as for the value field of cl_decoded_option.  KIND
> -   is the diagnostic_t if this is a diagnostics option, DK_UNSPECIFIED
> -   otherwise.  Returns false if the switch was invalid.  */
> +/* Handle option DECODED for the language indicated by LANG_MASK,
> +   using the handlers in HANDLERS.  KIND is the diagnostic_t if this
> +   is a diagnostics option, DK_UNSPECIFIED otherwise.  Returns false
> +   if the switch was invalid.  */
>
>  bool
> -handle_option (size_t opt_index, const char *arg, int value,
> +handle_option (const struct cl_decoded_option *decoded,
>               unsigned int lang_mask, int kind,
>               const struct cl_option_handlers *handlers)
>  {
> +  size_t opt_index = decoded->opt_index;
> +  const char *arg = decoded->arg;
> +  int value = decoded->value;
>   const struct cl_option *option = &cl_options[opt_index];
>   size_t i;
>
> @@ -516,17 +518,68 @@ handle_option (size_t opt_index, const c
>   for (i = 0; i < handlers->num_handlers; i++)
>     if (option->flags & handlers->handlers[i].mask)
>       {
> -       if (!handlers->handlers[i].handler (opt_index, arg, value,
> +       if (!handlers->handlers[i].handler (decoded,
>                                            lang_mask, kind, handlers))
>          return false;
>        else
> -         handlers->post_handling_callback (opt_index, arg, value,
> +         handlers->post_handling_callback (decoded,
>                                            handlers->handlers[i].mask);
>       }
>
>   return true;
>  }
>
> +/* Like handle_option, but OPT_INDEX, ARG and VALUE describe the
> +   option instead of DECODED.  This is used for callbacks when one
> +   option implies another instead of an option being decoded from the
> +   command line.  */
> +
> +bool
> +handle_generated_option (size_t opt_index, const char *arg, int value,
> +                        unsigned int lang_mask, int kind,
> +                        const struct cl_option_handlers *handlers)
> +{
> +  const struct cl_option *option = &cl_options[opt_index];
> +  struct cl_decoded_option decoded;
> +
> +  decoded.opt_index = opt_index;
> +  decoded.arg = arg;
> +  decoded.canonical_option[2] = NULL;
> +  decoded.canonical_option[3] = NULL;
> +  decoded.value = value;
> +  decoded.errors = 0;
> +
> +  if (arg)
> +    {
> +      if (option->flags & CL_SEPARATE)
> +       {
> +         decoded.orig_option_with_args_text = concat (option->opt_text, " ",
> +                                                      arg, NULL);
> +         decoded.canonical_option[0] = option->opt_text;
> +         decoded.canonical_option[1] = arg;
> +         decoded.canonical_option_num_elements = 2;
> +       }
> +      else
> +       {
> +         gcc_assert (option->flags & CL_JOINED);
> +         decoded.orig_option_with_args_text = concat (option->opt_text, arg,
> +                                                      NULL);
> +         decoded.canonical_option[0] = decoded.orig_option_with_args_text;
> +         decoded.canonical_option[1] = NULL;
> +         decoded.canonical_option_num_elements = 1;
> +       }
> +    }
> +  else
> +    {
> +      decoded.orig_option_with_args_text = option->opt_text;
> +      decoded.canonical_option[0] = option->opt_text;
> +      decoded.canonical_option[1] = NULL;
> +      decoded.canonical_option_num_elements = 1;
> +    }
> +
> +  return handle_option (&decoded, lang_mask, kind, handlers);
> +}
> +
>  /* Handle the switch DECODED for the language indicated by LANG_MASK,
>    using the handlers in *HANDLERS.  */
>
> @@ -540,10 +593,8 @@ read_cmdline_option (struct cl_decoded_o
>
>   if (decoded->opt_index == OPT_SPECIAL_unknown)
>     {
> -      opt = decoded->arg;
> -
> -      if (handlers->unknown_option_callback (opt))
> -       error ("unrecognized command line option %qs", opt);
> +      if (handlers->unknown_option_callback (decoded))
> +       error ("unrecognized command line option %qs", decoded->arg);
>       return;
>     }
>
> @@ -559,7 +610,7 @@ read_cmdline_option (struct cl_decoded_o
>
>   if (decoded->errors & CL_ERR_WRONG_LANG)
>     {
> -      handlers->wrong_lang_callback (opt, option, lang_mask);
> +      handlers->wrong_lang_callback (decoded, lang_mask);
>       return;
>     }
>
> @@ -581,8 +632,7 @@ read_cmdline_option (struct cl_decoded_o
>
>   gcc_assert (!decoded->errors);
>
> -  if (!handle_option (decoded->opt_index, decoded->arg, decoded->value,
> -                     lang_mask, DK_UNSPECIFIED, handlers))
> +  if (!handle_option (decoded, lang_mask, DK_UNSPECIFIED, handlers))
>     error ("unrecognized command line option %qs", opt);
>  }
>
> Index: gcc/c-family/c-opts.c
> ===================================================================
> --- gcc/c-family/c-opts.c       (revision 162909)
> +++ gcc/c-family/c-opts.c       (working copy)
> @@ -437,8 +437,8 @@ c_common_handle_option (size_t scode, co
>     case OPT_Wall:
>       warn_unused = value;
>       set_Wformat (value);
> -      handle_option (OPT_Wimplicit, NULL, value, c_family_lang_mask, kind,
> -                    handlers);
> +      handle_generated_option (OPT_Wimplicit, NULL, value,
> +                              c_family_lang_mask, kind, handlers);
>       warn_char_subscripts = value;
>       warn_missing_braces = value;
>       warn_parentheses = value;
> @@ -539,11 +539,11 @@ c_common_handle_option (size_t scode, co
>     case OPT_Wimplicit:
>       gcc_assert (value == 0 || value == 1);
>       if (warn_implicit_int == -1)
> -       handle_option (OPT_Wimplicit_int, NULL, value,
> -                      c_family_lang_mask, kind, handlers);
> +       handle_generated_option (OPT_Wimplicit_int, NULL, value,
> +                                c_family_lang_mask, kind, handlers);
>       if (warn_implicit_function_declaration == -1)
> -       handle_option (OPT_Wimplicit_function_declaration, NULL, value,
> -                      c_family_lang_mask, kind, handlers);
> +       handle_generated_option (OPT_Wimplicit_function_declaration, NULL,
> +                                value, c_family_lang_mask, kind, handlers);
>       break;
>
>     case OPT_Wimport:
> Index: gcc/opts.c
> ===================================================================
> --- gcc/opts.c  (revision 162909)
> +++ gcc/opts.c  (working copy)
> @@ -372,12 +372,12 @@ bool flag_warn_unused_result = false;
>  const char **in_fnames;
>  unsigned num_in_fnames;
>
> -static bool common_handle_option (size_t scode, const char *arg, int value,
> +static bool common_handle_option (const struct cl_decoded_option *decoded,
>                                  unsigned int lang_mask, int kind,
>                                  const struct cl_option_handlers *handlers);
>  static void handle_param (const char *);
>  static char *write_langs (unsigned int lang_mask);
> -static void complain_wrong_lang (const char *, const struct cl_option *,
> +static void complain_wrong_lang (const struct cl_decoded_option *,
>                                 unsigned int lang_mask);
>  static void set_debug_level (enum debug_info_type type, int extended,
>                             const char *arg);
> @@ -410,11 +410,14 @@ write_langs (unsigned int mask)
>   return result;
>  }
>
> -/* Complain that switch OPT_INDEX does not apply to this front end.  */
> +/* Complain that switch DECODED does not apply to this front end (mask
> +   LANG_MASK).  */
>  static void
> -complain_wrong_lang (const char *text, const struct cl_option *option,
> +complain_wrong_lang (const struct cl_decoded_option *decoded,
>                     unsigned int lang_mask)
>  {
> +  const struct cl_option *option = &cl_options[decoded->opt_index];
> +  const char *text = decoded->orig_option_with_args_text;
>   char *ok_langs, *bad_lang;
>
>   if (!lang_hooks.complain_wrong_lang_p (option))
> @@ -461,12 +464,14 @@ void print_ignored_options (void)
>   input_location = saved_loc;
>  }
>
> -/* Handle an unknown option ARG, returning true if an error should be
> +/* Handle an unknown option DECODED, returning true if an error should be
>    given.  */
>
>  static bool
> -unknown_option_callback (const char *opt)
> +unknown_option_callback (const struct cl_decoded_option *decoded)
>  {
> +  const char *opt = decoded->arg;
> +
>   if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
>     {
>       /* We don't generate warnings for unknown -Wno-* options unless
> @@ -478,17 +483,16 @@ unknown_option_callback (const char *opt
>     return true;
>  }
>
> -/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
> -   has been successfully handled with a handler for mask MASK.  */
> +/* Note that an option DECODED has been successfully handled with a
> +   handler for mask MASK.  */
>
>  static void
> -post_handling_callback (size_t opt_index ATTRIBUTE_UNUSED,
> -                       const char *arg ATTRIBUTE_UNUSED,
> -                       int value ATTRIBUTE_UNUSED,
> +post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
>                        unsigned int mask ATTRIBUTE_UNUSED)
>  {
>  #ifdef ENABLE_LTO
> -  lto_register_user_option (opt_index, arg, value, mask);
> +  lto_register_user_option (decoded->opt_index, decoded->arg,
> +                           decoded->value, mask);
>  #endif
>  }
>
> @@ -496,23 +500,27 @@ post_handling_callback (size_t opt_index
>    handle_option.  */
>
>  static bool
> -lang_handle_option (size_t opt_index, const char *arg, int value,
> +lang_handle_option (const struct cl_decoded_option *decoded,
>                    unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
>                    const struct cl_option_handlers *handlers)
>  {
> -  return lang_hooks.handle_option (opt_index, arg, value, kind, handlers);
> +  gcc_assert (decoded->canonical_option_num_elements <= 2);
> +  return lang_hooks.handle_option (decoded->opt_index, decoded->arg,
> +                                  decoded->value, kind, handlers);
>  }
>
>  /* Handle a back-end option; arguments and return value as for
>    handle_option.  */
>
>  static bool
> -target_handle_option (size_t opt_index, const char *arg, int value,
> -                   unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
> -                   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
> +target_handle_option (const struct cl_decoded_option *decoded,
> +                     unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
> +                     const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>  {
> +  gcc_assert (decoded->canonical_option_num_elements <= 2);
>   gcc_assert (kind == DK_UNSPECIFIED);
> -  return targetm.handle_option (opt_index, arg, value);
> +  return targetm.handle_option (decoded->opt_index, decoded->arg,
> +                               decoded->value);
>  }
>
>  /* Handle FILENAME from the command line.  */
> @@ -1386,16 +1394,21 @@ print_specific_help (unsigned int includ
>  /* Handle target- and language-independent options.  Return zero to
>    generate an "unknown option" message.  Only options that need
>    extra handling need to be listed here; if you simply want
> -   VALUE assigned to a variable, it happens automatically.  */
> +   DECODED->value assigned to a variable, it happens automatically.  */
>
>  static bool
> -common_handle_option (size_t scode, const char *arg, int value,
> +common_handle_option (const struct cl_decoded_option *decoded,
>                      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
>                      const struct cl_option_handlers *handlers)
>  {
> +  size_t scode = decoded->opt_index;
> +  const char *arg = decoded->arg;
> +  int value = decoded->value;
>   static bool verbose = false;
>   enum opt_code code = (enum opt_code) scode;
>
> +  gcc_assert (decoded->canonical_option_num_elements <= 2);
> +
>   switch (code)
>     {
>     case OPT__param:
> @@ -2357,8 +2370,8 @@ enable_warning_as_error (const char *arg
>
>          /* -Werror=foo implies -Wfoo.  */
>          if (option->var_type == CLVC_BOOLEAN)
> -           handle_option (option_index, arg, value, lang_mask, (int)kind,
> -                          handlers);
> +           handle_generated_option (option_index, NULL, value, lang_mask,
> +                                    (int)kind, handlers);
>
>          if (warning_as_error_callback)
>            warning_as_error_callback (option_index);
> Index: gcc/opts.h
> ===================================================================
> --- gcc/opts.h  (revision 162909)
> +++ gcc/opts.h  (working copy)
> @@ -142,7 +142,7 @@ struct cl_decoded_option
>  struct cl_option_handler_func
>  {
>   /* The function called to handle the option.  */
> -  bool (*handler) (size_t opt_index, const char *arg, int value,
> +  bool (*handler) (const struct cl_decoded_option *decoded,
>                   unsigned int lang_mask, int kind,
>                   const struct cl_option_handlers *handlers);
>
> @@ -159,17 +159,16 @@ struct cl_option_handlers
>      error for it, and possibly store information to diagnose the
>      option at a later point.  Return true if an error should be
>      given, false otherwise.  */
> -  bool (*unknown_option_callback) (const char *opt);
> +  bool (*unknown_option_callback) (const struct cl_decoded_option *decoded);
>
>   /* Callback to handle, and possibly diagnose, an option for another
>      language.  */
> -  void (*wrong_lang_callback) (const char *text,
> -                              const struct cl_option *option,
> +  void (*wrong_lang_callback) (const struct cl_decoded_option *decoded,
>                               unsigned int lang_mask);
>
>   /* Callback to call after the successful handling of any option.  */
> -  void (*post_handling_callback) (size_t opt_index, const char *arg,
> -                                 int value, unsigned int mask);
> +  void (*post_handling_callback) (const struct cl_decoded_option *decoded,
> +                                 unsigned int mask);
>
>   /* The number of individual handlers.  */
>   size_t num_handlers;
> @@ -200,9 +199,12 @@ extern void decode_options (unsigned int
>  extern int option_enabled (int opt_idx);
>  extern bool get_option_state (int, struct cl_option_state *);
>  extern void set_option (int opt_index, int value, const char *arg, int);
> -bool handle_option (size_t opt_index, const char *arg, int value,
> +bool handle_option (const struct cl_decoded_option *decoded,
>                    unsigned int lang_mask, int kind,
>                    const struct cl_option_handlers *handlers);
> +bool handle_generated_option (size_t opt_index, const char *arg, int value,
> +                             unsigned int lang_mask, int kind,
> +                             const struct cl_option_handlers *handlers);
>  extern void read_cmdline_option (struct cl_decoded_option *decoded,
>                                 unsigned int lang_mask,
>                                 const struct cl_option_handlers *handlers);
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>
diff mbox

Patch

Index: gcc/opts-common.c
===================================================================
--- gcc/opts-common.c	(revision 162909)
+++ gcc/opts-common.c	(working copy)
@@ -496,17 +496,19 @@  done:
   free (options);
 }
 
-/* Handle option OPT_INDEX, and argument ARG, for the language
-   indicated by LANG_MASK, using the handlers in HANDLERS.  VALUE is
-   the option value as for the value field of cl_decoded_option.  KIND
-   is the diagnostic_t if this is a diagnostics option, DK_UNSPECIFIED
-   otherwise.  Returns false if the switch was invalid.  */
+/* Handle option DECODED for the language indicated by LANG_MASK,
+   using the handlers in HANDLERS.  KIND is the diagnostic_t if this
+   is a diagnostics option, DK_UNSPECIFIED otherwise.  Returns false
+   if the switch was invalid.  */
 
 bool
-handle_option (size_t opt_index, const char *arg, int value,
+handle_option (const struct cl_decoded_option *decoded,
 	       unsigned int lang_mask, int kind,
 	       const struct cl_option_handlers *handlers)
 {
+  size_t opt_index = decoded->opt_index;
+  const char *arg = decoded->arg;
+  int value = decoded->value;
   const struct cl_option *option = &cl_options[opt_index];
   size_t i;
 
@@ -516,17 +518,68 @@  handle_option (size_t opt_index, const c
   for (i = 0; i < handlers->num_handlers; i++)
     if (option->flags & handlers->handlers[i].mask)
       {
-	if (!handlers->handlers[i].handler (opt_index, arg, value,
+	if (!handlers->handlers[i].handler (decoded,
 					    lang_mask, kind, handlers))
 	  return false;
 	else
-	  handlers->post_handling_callback (opt_index, arg, value,
+	  handlers->post_handling_callback (decoded,
 					    handlers->handlers[i].mask);
       }
   
   return true;
 }
 
+/* Like handle_option, but OPT_INDEX, ARG and VALUE describe the
+   option instead of DECODED.  This is used for callbacks when one
+   option implies another instead of an option being decoded from the
+   command line.  */
+
+bool
+handle_generated_option (size_t opt_index, const char *arg, int value,
+			 unsigned int lang_mask, int kind,
+			 const struct cl_option_handlers *handlers)
+{
+  const struct cl_option *option = &cl_options[opt_index];
+  struct cl_decoded_option decoded;
+
+  decoded.opt_index = opt_index;
+  decoded.arg = arg;
+  decoded.canonical_option[2] = NULL;
+  decoded.canonical_option[3] = NULL;
+  decoded.value = value;
+  decoded.errors = 0;
+
+  if (arg)
+    {
+      if (option->flags & CL_SEPARATE)
+	{
+	  decoded.orig_option_with_args_text = concat (option->opt_text, " ",
+						       arg, NULL);
+	  decoded.canonical_option[0] = option->opt_text;
+	  decoded.canonical_option[1] = arg;
+	  decoded.canonical_option_num_elements = 2;
+	}
+      else
+	{
+	  gcc_assert (option->flags & CL_JOINED);
+	  decoded.orig_option_with_args_text = concat (option->opt_text, arg,
+						       NULL);
+	  decoded.canonical_option[0] = decoded.orig_option_with_args_text;
+	  decoded.canonical_option[1] = NULL;
+	  decoded.canonical_option_num_elements = 1;
+	}
+    }
+  else
+    {
+      decoded.orig_option_with_args_text = option->opt_text;
+      decoded.canonical_option[0] = option->opt_text;
+      decoded.canonical_option[1] = NULL;
+      decoded.canonical_option_num_elements = 1;
+    }
+
+  return handle_option (&decoded, lang_mask, kind, handlers);
+}
+
 /* Handle the switch DECODED for the language indicated by LANG_MASK,
    using the handlers in *HANDLERS.  */
 
@@ -540,10 +593,8 @@  read_cmdline_option (struct cl_decoded_o
 
   if (decoded->opt_index == OPT_SPECIAL_unknown)
     {
-      opt = decoded->arg;
-
-      if (handlers->unknown_option_callback (opt))
-	error ("unrecognized command line option %qs", opt);
+      if (handlers->unknown_option_callback (decoded))
+	error ("unrecognized command line option %qs", decoded->arg);
       return;
     }
 
@@ -559,7 +610,7 @@  read_cmdline_option (struct cl_decoded_o
 
   if (decoded->errors & CL_ERR_WRONG_LANG)
     {
-      handlers->wrong_lang_callback (opt, option, lang_mask);
+      handlers->wrong_lang_callback (decoded, lang_mask);
       return;
     }
 
@@ -581,8 +632,7 @@  read_cmdline_option (struct cl_decoded_o
 
   gcc_assert (!decoded->errors);
 
-  if (!handle_option (decoded->opt_index, decoded->arg, decoded->value,
-		      lang_mask, DK_UNSPECIFIED, handlers))
+  if (!handle_option (decoded, lang_mask, DK_UNSPECIFIED, handlers))
     error ("unrecognized command line option %qs", opt);
 }
 
Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c	(revision 162909)
+++ gcc/c-family/c-opts.c	(working copy)
@@ -437,8 +437,8 @@  c_common_handle_option (size_t scode, co
     case OPT_Wall:
       warn_unused = value;
       set_Wformat (value);
-      handle_option (OPT_Wimplicit, NULL, value, c_family_lang_mask, kind,
-		     handlers);
+      handle_generated_option (OPT_Wimplicit, NULL, value,
+			       c_family_lang_mask, kind, handlers);
       warn_char_subscripts = value;
       warn_missing_braces = value;
       warn_parentheses = value;
@@ -539,11 +539,11 @@  c_common_handle_option (size_t scode, co
     case OPT_Wimplicit:
       gcc_assert (value == 0 || value == 1);
       if (warn_implicit_int == -1)
-	handle_option (OPT_Wimplicit_int, NULL, value,
-		       c_family_lang_mask, kind, handlers);
+	handle_generated_option (OPT_Wimplicit_int, NULL, value,
+				 c_family_lang_mask, kind, handlers);
       if (warn_implicit_function_declaration == -1)
-	handle_option (OPT_Wimplicit_function_declaration, NULL, value,
-		       c_family_lang_mask, kind, handlers);
+	handle_generated_option (OPT_Wimplicit_function_declaration, NULL,
+				 value, c_family_lang_mask, kind, handlers);
       break;
 
     case OPT_Wimport:
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	(revision 162909)
+++ gcc/opts.c	(working copy)
@@ -372,12 +372,12 @@  bool flag_warn_unused_result = false;
 const char **in_fnames;
 unsigned num_in_fnames;
 
-static bool common_handle_option (size_t scode, const char *arg, int value,
+static bool common_handle_option (const struct cl_decoded_option *decoded,
 				  unsigned int lang_mask, int kind,
 				  const struct cl_option_handlers *handlers);
 static void handle_param (const char *);
 static char *write_langs (unsigned int lang_mask);
-static void complain_wrong_lang (const char *, const struct cl_option *,
+static void complain_wrong_lang (const struct cl_decoded_option *,
 				 unsigned int lang_mask);
 static void set_debug_level (enum debug_info_type type, int extended,
 			     const char *arg);
@@ -410,11 +410,14 @@  write_langs (unsigned int mask)
   return result;
 }
 
-/* Complain that switch OPT_INDEX does not apply to this front end.  */
+/* Complain that switch DECODED does not apply to this front end (mask
+   LANG_MASK).  */
 static void
-complain_wrong_lang (const char *text, const struct cl_option *option,
+complain_wrong_lang (const struct cl_decoded_option *decoded,
 		     unsigned int lang_mask)
 {
+  const struct cl_option *option = &cl_options[decoded->opt_index];
+  const char *text = decoded->orig_option_with_args_text;
   char *ok_langs, *bad_lang;
 
   if (!lang_hooks.complain_wrong_lang_p (option))
@@ -461,12 +464,14 @@  void print_ignored_options (void)
   input_location = saved_loc;
 }
 
-/* Handle an unknown option ARG, returning true if an error should be
+/* Handle an unknown option DECODED, returning true if an error should be
    given.  */
 
 static bool
-unknown_option_callback (const char *opt)
+unknown_option_callback (const struct cl_decoded_option *decoded)
 {
+  const char *opt = decoded->arg;
+
   if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
     {
       /* We don't generate warnings for unknown -Wno-* options unless
@@ -478,17 +483,16 @@  unknown_option_callback (const char *opt
     return true;
 }
 
-/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
-   has been successfully handled with a handler for mask MASK.  */
+/* Note that an option DECODED has been successfully handled with a
+   handler for mask MASK.  */
 
 static void
-post_handling_callback (size_t opt_index ATTRIBUTE_UNUSED,
-			const char *arg ATTRIBUTE_UNUSED,
-			int value ATTRIBUTE_UNUSED,
+post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
 			unsigned int mask ATTRIBUTE_UNUSED)
 {
 #ifdef ENABLE_LTO
-  lto_register_user_option (opt_index, arg, value, mask);
+  lto_register_user_option (decoded->opt_index, decoded->arg,
+			    decoded->value, mask);
 #endif
 }
 
@@ -496,23 +500,27 @@  post_handling_callback (size_t opt_index
    handle_option.  */
 
 static bool
-lang_handle_option (size_t opt_index, const char *arg, int value,
+lang_handle_option (const struct cl_decoded_option *decoded,
 		    unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
 		    const struct cl_option_handlers *handlers)
 {
-  return lang_hooks.handle_option (opt_index, arg, value, kind, handlers);
+  gcc_assert (decoded->canonical_option_num_elements <= 2);
+  return lang_hooks.handle_option (decoded->opt_index, decoded->arg,
+				   decoded->value, kind, handlers);
 }
 
 /* Handle a back-end option; arguments and return value as for
    handle_option.  */
 
 static bool
-target_handle_option (size_t opt_index, const char *arg, int value,
-		    unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
-		    const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
+target_handle_option (const struct cl_decoded_option *decoded,
+		      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
+		      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
+  gcc_assert (decoded->canonical_option_num_elements <= 2);
   gcc_assert (kind == DK_UNSPECIFIED);
-  return targetm.handle_option (opt_index, arg, value);
+  return targetm.handle_option (decoded->opt_index, decoded->arg,
+				decoded->value);
 }
 
 /* Handle FILENAME from the command line.  */
@@ -1386,16 +1394,21 @@  print_specific_help (unsigned int includ
 /* Handle target- and language-independent options.  Return zero to
    generate an "unknown option" message.  Only options that need
    extra handling need to be listed here; if you simply want
-   VALUE assigned to a variable, it happens automatically.  */
+   DECODED->value assigned to a variable, it happens automatically.  */
 
 static bool
-common_handle_option (size_t scode, const char *arg, int value,
+common_handle_option (const struct cl_decoded_option *decoded,
 		      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
 		      const struct cl_option_handlers *handlers)
 {
+  size_t scode = decoded->opt_index;
+  const char *arg = decoded->arg;
+  int value = decoded->value;
   static bool verbose = false;
   enum opt_code code = (enum opt_code) scode;
 
+  gcc_assert (decoded->canonical_option_num_elements <= 2);
+
   switch (code)
     {
     case OPT__param:
@@ -2357,8 +2370,8 @@  enable_warning_as_error (const char *arg
 
 	  /* -Werror=foo implies -Wfoo.  */
 	  if (option->var_type == CLVC_BOOLEAN)
-	    handle_option (option_index, arg, value, lang_mask, (int)kind,
-			   handlers);
+	    handle_generated_option (option_index, NULL, value, lang_mask,
+				     (int)kind, handlers);
 
 	  if (warning_as_error_callback)
 	    warning_as_error_callback (option_index);
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 162909)
+++ gcc/opts.h	(working copy)
@@ -142,7 +142,7 @@  struct cl_decoded_option
 struct cl_option_handler_func
 {
   /* The function called to handle the option.  */
-  bool (*handler) (size_t opt_index, const char *arg, int value,
+  bool (*handler) (const struct cl_decoded_option *decoded,
 		   unsigned int lang_mask, int kind,
 		   const struct cl_option_handlers *handlers);
 
@@ -159,17 +159,16 @@  struct cl_option_handlers
      error for it, and possibly store information to diagnose the
      option at a later point.  Return true if an error should be
      given, false otherwise.  */
-  bool (*unknown_option_callback) (const char *opt);
+  bool (*unknown_option_callback) (const struct cl_decoded_option *decoded);
 
   /* Callback to handle, and possibly diagnose, an option for another
      language.  */
-  void (*wrong_lang_callback) (const char *text,
-			       const struct cl_option *option,
+  void (*wrong_lang_callback) (const struct cl_decoded_option *decoded,
 			       unsigned int lang_mask);
 
   /* Callback to call after the successful handling of any option.  */
-  void (*post_handling_callback) (size_t opt_index, const char *arg,
-				  int value, unsigned int mask);
+  void (*post_handling_callback) (const struct cl_decoded_option *decoded,
+				  unsigned int mask);
 
   /* The number of individual handlers.  */
   size_t num_handlers;
@@ -200,9 +199,12 @@  extern void decode_options (unsigned int
 extern int option_enabled (int opt_idx);
 extern bool get_option_state (int, struct cl_option_state *);
 extern void set_option (int opt_index, int value, const char *arg, int);
-bool handle_option (size_t opt_index, const char *arg, int value,
+bool handle_option (const struct cl_decoded_option *decoded,
 		    unsigned int lang_mask, int kind,
 		    const struct cl_option_handlers *handlers);
+bool handle_generated_option (size_t opt_index, const char *arg, int value,
+			      unsigned int lang_mask, int kind,
+			      const struct cl_option_handlers *handlers);
 extern void read_cmdline_option (struct cl_decoded_option *decoded,
 				 unsigned int lang_mask,
 				 const struct cl_option_handlers *handlers);