Patchwork Move handle_option and read_cmdline_option to opts-common.c

login
register
mail settings
Submitter Joseph S. Myers
Date June 23, 2010, 12:50 a.m.
Message ID <Pine.LNX.4.64.1006230049250.28257@digraph.polyomino.org.uk>
Download mbox | patch
Permalink /patch/56580/
State New
Headers show

Comments

Joseph S. Myers - June 23, 2010, 12:50 a.m.
This patch is relative to a tree with
<http://gcc.gnu.org/ml/gcc-patches/2010-06/msg01968.html> and
<http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02150.html> applied.
The former needs C++ and Ada pieces approved; the latter needs C++
pieces approved.

Continuing the work towards sharing option processing code between the
driver and the compiler proper, this patch moves handle_option and
read_cmdline_option, and the set_option function they use, into
opts-common.c.  In various places where these functions do things that
may not be appropriate in the driver at least initially, appropriate
callbacks are provided, and a cl_option_handlers structure is used to
describe these callbacks.

The set of callbacks is needed by recursive handle_option calls (from
options enabling other options) and so some prototypes, including for
the handle_option langhook, are adjusted to pass the handlers
pointer.  The handle_option langhook is also adjusted to have a
boolean return value; the comments suggested a tristate return value
but nothing used or acted on a negative return value as was suggested
in the comments.  The Ada hook had useless checks for missing option
arguments (erroneous options don't get passed to these handlers),
which I removed.  The argument order of the handle_option function is
adjusted to match that of various related functions, by swapping the
arg and value operands.

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

2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* coretypes.h (struct cl_option_handlers): Declare.
	* hooks.c (hook_int_size_t_constcharptr_int_0): Remove.
	* hooks.h (hook_int_size_t_constcharptr_int_0): Remove.
	* langhooks-def.h (lhd_handle_option): Declare.
	(LANG_HOOKS_HANDLE_OPTION): Use lhd_handle_option.
	* langhooks.c (lhd_handle_option): New.
	* langhooks.h (struct lang_hooks): Update prototype and return
	value type of handle_option hook.
	* optc-gen.awk: Generate target_flags_explicit definition for the
	driver.
	* opts-common.c: Include diagnostic.h.
	(handle_option): Move from opts.c.  Update prototype and return
	value type.  Use handlers structure.
	(read_cmdline_option): Move from opts.c.  Update prototype.  Use
	handlers structure.
	(set_option): Move from opts.c.
	* opts.c (common_handle_option): Update prototype and return value
	type.  Update calls to handle_option and enable_warning_as_error.
	(unknown_option_callback, post_handling_callback,
	lang_handle_option, target_handle_option): New.
	(handle_option, read_cmdline_option): Move to opts-common.c.
	(read_cmdline_options): Update prototype.  Update call to
	read_cmdline_option.
	(decode_options): Initialize and use handlers structure.
	(set_option): Move to opts-common.c.
	(enable_warning_as_error): Update prototype.  Update call to
	handle_option.
	* opts.h (struct cl_option_handler_func, struct
	cl_option_handlers): New.
	(handle_option, enable_warning_as_error): Update prototypes.
	(read_cmdline_option): Declare.
	* Makefile.in (opts-common.o): Update dependencies.

ada:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* gcc-interface/misc.c (gnat_handle_option): Update prototype and
	return value type.  Don't check for missing arguments here.

c-family:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* c-common.h (c_common_handle_option): Update prototype and return
	value type.
	* c-opts.c (c_common_handle_option): Update prototype and return
	value type.  Update calls to handle_option and
	enable_warning_as_error.

fortran:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* gfortran.h (gfc_handle_option): Update prototype and return
	value type.
	* options.c (gfc_handle_option): Update prototype and return value
	type.

java:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* lang.c (java_handle_option): Update prototype and return value
	type.

lto:
2010-06-22  Joseph Myers  <joseph@codesourcery.com>

	* lto-lang.c (lto_handle_option): Update prototype and return
	value type.  Remove duplicate assignment to result.
Andrew Haley - June 23, 2010, 7:28 a.m.
On 06/23/2010 01:50 AM, Joseph S. Myers wrote:

> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
> 
> 	* coretypes.h (struct cl_option_handlers): Declare.
> 	* hooks.c (hook_int_size_t_constcharptr_int_0): Remove.
> 	* hooks.h (hook_int_size_t_constcharptr_int_0): Remove.
> 	* langhooks-def.h (lhd_handle_option): Declare.
> 	(LANG_HOOKS_HANDLE_OPTION): Use lhd_handle_option.
> 	* langhooks.c (lhd_handle_option): New.
> 	* langhooks.h (struct lang_hooks): Update prototype and return
> 	value type of handle_option hook.
> 	* optc-gen.awk: Generate target_flags_explicit definition for the
> 	driver.
> 	* opts-common.c: Include diagnostic.h.
> 	(handle_option): Move from opts.c.  Update prototype and return
> 	value type.  Use handlers structure.
> 	(read_cmdline_option): Move from opts.c.  Update prototype.  Use
> 	handlers structure.
> 	(set_option): Move from opts.c.
> 	* opts.c (common_handle_option): Update prototype and return value
> 	type.  Update calls to handle_option and enable_warning_as_error.
> 	(unknown_option_callback, post_handling_callback,
> 	lang_handle_option, target_handle_option): New.
> 	(handle_option, read_cmdline_option): Move to opts-common.c.
> 	(read_cmdline_options): Update prototype.  Update call to
> 	read_cmdline_option.
> 	(decode_options): Initialize and use handlers structure.
> 	(set_option): Move to opts-common.c.
> 	(enable_warning_as_error): Update prototype.  Update call to
> 	handle_option.
> 	* opts.h (struct cl_option_handler_func, struct
> 	cl_option_handlers): New.
> 	(handle_option, enable_warning_as_error): Update prototypes.
> 	(read_cmdline_option): Declare.
> 	* Makefile.in (opts-common.o): Update dependencies.

OK for Java.

Andrew.
Steve Kargl - June 23, 2010, 5:49 p.m.
On Wed, Jun 23, 2010 at 12:50:35AM +0000, Joseph S. Myers wrote:
> 
> fortran:
> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
> 
> 	* gfortran.h (gfc_handle_option): Update prototype and return
> 	value type.
> 	* options.c (gfc_handle_option): Update prototype and return value
> 	type.
> 

The Fortran bits are OK.
Richard Guenther - June 25, 2010, 2:28 p.m.
On Wed, Jun 23, 2010 at 2:50 AM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> This patch is relative to a tree with
> <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg01968.html> and
> <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02150.html> applied.
> The former needs C++ and Ada pieces approved; the latter needs C++
> pieces approved.
>
> Continuing the work towards sharing option processing code between the
> driver and the compiler proper, this patch moves handle_option and
> read_cmdline_option, and the set_option function they use, into
> opts-common.c.  In various places where these functions do things that
> may not be appropriate in the driver at least initially, appropriate
> callbacks are provided, and a cl_option_handlers structure is used to
> describe these callbacks.
>
> The set of callbacks is needed by recursive handle_option calls (from
> options enabling other options) and so some prototypes, including for
> the handle_option langhook, are adjusted to pass the handlers
> pointer.  The handle_option langhook is also adjusted to have a
> boolean return value; the comments suggested a tristate return value
> but nothing used or acted on a negative return value as was suggested
> in the comments.  The Ada hook had useless checks for missing option
> arguments (erroneous options don't get passed to these handlers),
> which I removed.  The argument order of the handle_option function is
> adjusted to match that of various related functions, by swapping the
> arg and value operands.
>
> Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
> commit?

Ok for the non-frontend specific changes.

Richard.

> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>
>        * coretypes.h (struct cl_option_handlers): Declare.
>        * hooks.c (hook_int_size_t_constcharptr_int_0): Remove.
>        * hooks.h (hook_int_size_t_constcharptr_int_0): Remove.
>        * langhooks-def.h (lhd_handle_option): Declare.
>        (LANG_HOOKS_HANDLE_OPTION): Use lhd_handle_option.
>        * langhooks.c (lhd_handle_option): New.
>        * langhooks.h (struct lang_hooks): Update prototype and return
>        value type of handle_option hook.
>        * optc-gen.awk: Generate target_flags_explicit definition for the
>        driver.
>        * opts-common.c: Include diagnostic.h.
>        (handle_option): Move from opts.c.  Update prototype and return
>        value type.  Use handlers structure.
>        (read_cmdline_option): Move from opts.c.  Update prototype.  Use
>        handlers structure.
>        (set_option): Move from opts.c.
>        * opts.c (common_handle_option): Update prototype and return value
>        type.  Update calls to handle_option and enable_warning_as_error.
>        (unknown_option_callback, post_handling_callback,
>        lang_handle_option, target_handle_option): New.
>        (handle_option, read_cmdline_option): Move to opts-common.c.
>        (read_cmdline_options): Update prototype.  Update call to
>        read_cmdline_option.
>        (decode_options): Initialize and use handlers structure.
>        (set_option): Move to opts-common.c.
>        (enable_warning_as_error): Update prototype.  Update call to
>        handle_option.
>        * opts.h (struct cl_option_handler_func, struct
>        cl_option_handlers): New.
>        (handle_option, enable_warning_as_error): Update prototypes.
>        (read_cmdline_option): Declare.
>        * Makefile.in (opts-common.o): Update dependencies.
>
> ada:
> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>
>        * gcc-interface/misc.c (gnat_handle_option): Update prototype and
>        return value type.  Don't check for missing arguments here.
>
> c-family:
> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>
>        * c-common.h (c_common_handle_option): Update prototype and return
>        value type.
>        * c-opts.c (c_common_handle_option): Update prototype and return
>        value type.  Update calls to handle_option and
>        enable_warning_as_error.
>
> fortran:
> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>
>        * gfortran.h (gfc_handle_option): Update prototype and return
>        value type.
>        * options.c (gfc_handle_option): Update prototype and return value
>        type.
>
> java:
> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>
>        * lang.c (java_handle_option): Update prototype and return value
>        type.
>
> lto:
> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>
>        * lto-lang.c (lto_handle_option): Update prototype and return
>        value type.  Remove duplicate assignment to result.
>
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/Makefile.in gcc-mainline/gcc/Makefile.in
> --- gcc-mainline-opt2/gcc/Makefile.in   2010-06-21 09:57:36.000000000 -0700
> +++ gcc-mainline/gcc/Makefile.in        2010-06-22 15:24:00.000000000 -0700
> @@ -2796,7 +2796,7 @@ opts.o : opts.c opts.h options.h $(TOPLE
>    $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h \
>    $(PLUGIN_H) $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
>  opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
> -   coretypes.h intl.h
> +   coretypes.h intl.h $(DIAGNOSTIC_H)
>  targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
>    $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
>    $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h \
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/ada/gcc-interface/misc.c gcc-mainline/gcc/ada/gcc-interface/misc.c
> --- gcc-mainline-opt2/gcc/ada/gcc-interface/misc.c      2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/ada/gcc-interface/misc.c   2010-06-22 16:02:04.000000000 -0700
> @@ -65,7 +65,8 @@ static bool gnat_init                 (void);
>  static unsigned int gnat_option_lang_mask (void);
>  static void gnat_init_options          (unsigned int,
>                                         struct cl_decoded_option *);
> -static int gnat_handle_option          (size_t, const char *, int, int);
> +static bool gnat_handle_option         (size_t, const char *, int, int,
> +                                        const struct cl_option_handlers *);
>  static bool gnat_post_options          (const char **);
>  static alias_set_type gnat_get_alias_set (tree);
>  static void gnat_print_decl            (FILE *, tree, int);
> @@ -187,23 +188,16 @@ gnat_parse_file (int set_yydebug ATTRIBU
>
>  /* Decode all the language specific options that cannot be decoded by GCC.
>    The option decoding phase of GCC calls this routine on the flags that
> -   it cannot decode.  Return the number of consecutive arguments from ARGV
> -   that have been successfully decoded or 0 on failure.  */
> +   are marked as Ada-specific.  Return true on success or false on failure.  */
>
> -static int
> +static bool
>  gnat_handle_option (size_t scode, const char *arg, int value,
> -                   int kind ATTRIBUTE_UNUSED)
> +                   int kind ATTRIBUTE_UNUSED,
> +                   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>  {
> -  const struct cl_option *option = &cl_options[scode];
>   enum opt_code code = (enum opt_code) scode;
>   char *q;
>
> -  if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
> -    {
> -      error ("missing argument to \"-%s\"", option->opt_text);
> -      return 1;
> -    }
> -
>   switch (code)
>     {
>     case OPT_I:
> @@ -280,7 +274,7 @@ gnat_handle_option (size_t scode, const
>       gcc_unreachable ();
>     }
>
> -  return 1;
> +  return true;
>  }
>
>  /* Return language mask for option processing.  */
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/c-family/c-common.h gcc-mainline/gcc/c-family/c-common.h
> --- gcc-mainline-opt2/gcc/c-family/c-common.h   2010-06-21 14:38:50.000000000 -0700
> +++ gcc-mainline/gcc/c-family/c-common.h        2010-06-22 15:08:11.000000000 -0700
> @@ -652,7 +652,8 @@ extern void set_Wformat (int);
>  extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
>  extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
>  extern bool attribute_takes_identifier_p (const_tree);
> -extern int c_common_handle_option (size_t code, const char *arg, int value, int kind);
> +extern bool c_common_handle_option (size_t, const char *, int, int,
> +                                   const struct cl_option_handlers *);
>  extern tree c_common_type_for_mode (enum machine_mode, int);
>  extern tree c_common_type_for_size (unsigned int, int);
>  extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/c-family/c-opts.c gcc-mainline/gcc/c-family/c-opts.c
> --- gcc-mainline-opt2/gcc/c-family/c-opts.c     2010-06-21 14:53:58.000000000 -0700
> +++ gcc-mainline/gcc/c-family/c-opts.c  2010-06-22 15:08:05.000000000 -0700
> @@ -319,16 +319,15 @@ c_common_init_options (unsigned int deco
>  }
>
>  /* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
> -   form of an -f or -W option was given.  Returns 0 if the switch was
> -   invalid, a negative number to prevent language-independent
> -   processing in toplev.c (a hack necessary for the short-term).  */
> -int
> +   form of an -f or -W option was given.  Returns false if the switch was
> +   invalid, true if valid.  Use HANDLERS in recursive handle_option calls.  */
> +bool
>  c_common_handle_option (size_t scode, const char *arg, int value,
> -                       int kind)
> +                       int kind, const struct cl_option_handlers *handlers)
>  {
>   const struct cl_option *option = &cl_options[scode];
>   enum opt_code code = (enum opt_code) scode;
> -  int result = 1;
> +  bool result = true;
>
>   /* Prevent resetting the language standard to a C dialect when the driver
>      has already determined that we're looking at assembler input.  */
> @@ -341,10 +340,10 @@ c_common_handle_option (size_t scode, co
>        {
>          if ((option->flags & CL_TARGET)
>              && ! targetcm.handle_c_option (scode, arg, value))
> -           result = 0;
> +           result = false;
>          break;
>        }
> -      result = 0;
> +      result = false;
>       break;
>
>     case OPT__output_pch_:
> @@ -438,7 +437,8 @@ c_common_handle_option (size_t scode, co
>     case OPT_Wall:
>       warn_unused = value;
>       set_Wformat (value);
> -      handle_option (OPT_Wimplicit, value, NULL, c_family_lang_mask, kind);
> +      handle_option (OPT_Wimplicit, NULL, value, c_family_lang_mask, kind,
> +                    handlers);
>       warn_char_subscripts = value;
>       warn_missing_braces = value;
>       warn_parentheses = value;
> @@ -524,7 +524,8 @@ c_common_handle_option (size_t scode, co
>     case OPT_Werror_implicit_function_declaration:
>       /* For backward compatibility, this is the same as
>         -Werror=implicit-function-declaration.  */
> -      enable_warning_as_error ("implicit-function-declaration", value, CL_C | CL_ObjC);
> +      enable_warning_as_error ("implicit-function-declaration", value,
> +                              CL_C | CL_ObjC, handlers);
>       break;
>
>     case OPT_Wformat:
> @@ -538,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, value, NULL,
> -                      c_family_lang_mask, kind);
> +       handle_option (OPT_Wimplicit_int, NULL, value,
> +                      c_family_lang_mask, kind, handlers);
>       if (warn_implicit_function_declaration == -1)
> -       handle_option (OPT_Wimplicit_function_declaration, value, NULL,
> -                      c_family_lang_mask, kind);
> +       handle_option (OPT_Wimplicit_function_declaration, NULL, value,
> +                      c_family_lang_mask, kind, handlers);
>       break;
>
>     case OPT_Wimport:
> @@ -655,7 +656,7 @@ c_common_handle_option (size_t scode, co
>
>     case OPT_fbuiltin_:
>       if (value)
> -       result = 0;
> +       result = false;
>       else
>        disable_builtin_function (arg);
>       break;
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/coretypes.h gcc-mainline/gcc/coretypes.h
> --- gcc-mainline-opt2/gcc/coretypes.h   2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/coretypes.h        2010-06-22 14:34:22.000000000 -0700
> @@ -68,6 +68,7 @@ struct cl_target_option;
>  struct cl_optimization;
>  struct cl_option;
>  struct cl_decoded_option;
> +struct cl_option_handlers;
>  struct gimple_seq_d;
>  typedef struct gimple_seq_d *gimple_seq;
>  typedef const struct gimple_seq_d *const_gimple_seq;
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/fortran/gfortran.h gcc-mainline/gcc/fortran/gfortran.h
> --- gcc-mainline-opt2/gcc/fortran/gfortran.h    2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/fortran/gfortran.h 2010-06-22 15:08:23.000000000 -0700
> @@ -2346,7 +2346,8 @@ int get_c_kind (const char *, CInteropKi
>  unsigned int gfc_option_lang_mask (void);
>  void gfc_init_options (unsigned int,
>                       struct cl_decoded_option *);
> -int gfc_handle_option (size_t, const char *, int, int);
> +bool gfc_handle_option (size_t, const char *, int, int,
> +                       const struct cl_option_handlers *);
>  bool gfc_post_options (const char **);
>
>  /* f95-lang.c */
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/fortran/options.c gcc-mainline/gcc/fortran/options.c
> --- gcc-mainline-opt2/gcc/fortran/options.c     2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/fortran/options.c  2010-06-22 15:08:27.000000000 -0700
> @@ -542,20 +542,21 @@ gfc_handle_runtime_check_option (const c
>  /* Handle command-line options.  Returns 0 if unrecognized, 1 if
>    recognized and handled.  */
>
> -int
> +bool
>  gfc_handle_option (size_t scode, const char *arg, int value,
> -                  int kind ATTRIBUTE_UNUSED)
> +                  int kind ATTRIBUTE_UNUSED,
> +                  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>  {
> -  int result = 1;
> +  bool result = true;
>   enum opt_code code = (enum opt_code) scode;
>
>   if (gfc_cpp_handle_option (scode, arg, value) == 1)
> -    return 1;
> +    return true;
>
>   switch (code)
>     {
>     default:
> -      result = 0;
> +      result = false;
>       break;
>
>     case OPT_Wall:
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/hooks.c gcc-mainline/gcc/hooks.c
> --- gcc-mainline-opt2/gcc/hooks.c       2010-06-21 14:38:03.000000000 -0700
> +++ gcc-mainline/gcc/hooks.c    2010-06-22 14:31:06.000000000 -0700
> @@ -160,14 +160,6 @@ hook_int_rtx_bool_0 (rtx a ATTRIBUTE_UNU
>   return 0;
>  }
>
> -int
> -hook_int_size_t_constcharptr_int_0 (size_t a ATTRIBUTE_UNUSED,
> -                                   const char *b ATTRIBUTE_UNUSED,
> -                                   int c ATTRIBUTE_UNUSED)
> -{
> -  return 0;
> -}
> -
>  unsigned int
>  hook_uint_void_0 (void)
>  {
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/hooks.h gcc-mainline/gcc/hooks.h
> --- gcc-mainline-opt2/gcc/hooks.h       2010-06-21 14:38:18.000000000 -0700
> +++ gcc-mainline/gcc/hooks.h    2010-06-22 14:31:17.000000000 -0700
> @@ -63,7 +63,6 @@ extern int hook_int_const_tree_0 (const_
>  extern int hook_int_const_tree_const_tree_1 (const_tree, const_tree);
>  extern int hook_int_rtx_0 (rtx);
>  extern int hook_int_rtx_bool_0 (rtx, bool);
> -extern int hook_int_size_t_constcharptr_int_0 (size_t, const char *, int);
>
>  extern tree hook_tree_const_tree_null (const_tree);
>
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/java/lang.c gcc-mainline/gcc/java/lang.c
> --- gcc-mainline-opt2/gcc/java/lang.c   2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/java/lang.c        2010-06-22 15:08:40.000000000 -0700
> @@ -51,7 +51,8 @@ static unsigned int java_option_lang_mas
>  static void java_init_options (unsigned int, struct cl_decoded_option *);
>  static bool java_post_options (const char **);
>
> -static int java_handle_option (size_t scode, const char *arg, int value, int kind);
> +static bool java_handle_option (size_t, const char *, int, int,
> +                               const struct cl_option_handlers *);
>  static void put_decl_string (const char *, int);
>  static void put_decl_node (tree, int);
>  static void java_print_error_function (diagnostic_context *, const char *,
> @@ -175,11 +176,12 @@ struct lang_hooks lang_hooks = LANG_HOOK
>
>  /*
>  * process java-specific compiler command-line options
> - * return 0, but do not complain if the option is not recognized.
> + * return false, but do not complain if the option is not recognized.
>  */
> -static int
> +static bool
>  java_handle_option (size_t scode, const char *arg, int value,
> -                   int kind ATTRIBUTE_UNUSED)
> +                   int kind ATTRIBUTE_UNUSED,
> +                   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>  {
>   enum opt_code code = (enum opt_code) scode;
>
> @@ -270,7 +272,7 @@ java_handle_option (size_t scode, const
>
>     case OPT_fdump_:
>       if (!dump_switch_p (arg))
> -       return 0;
> +       return false;
>       break;
>
>     case OPT_fencoding_:
> @@ -299,7 +301,7 @@ java_handle_option (size_t scode, const
>       gcc_unreachable ();
>     }
>
> -  return 1;
> +  return true;
>  }
>
>  /* Global open file.  */
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks-def.h gcc-mainline/gcc/langhooks-def.h
> --- gcc-mainline-opt2/gcc/langhooks-def.h       2010-06-21 14:39:18.000000000 -0700
> +++ gcc-mainline/gcc/langhooks-def.h    2010-06-22 15:13:56.000000000 -0700
> @@ -69,6 +69,8 @@ extern void lhd_initialize_diagnostics (
>  extern void lhd_init_options (unsigned int,
>                              struct cl_decoded_option *);
>  extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
> +extern bool lhd_handle_option (size_t, const char *, int, int,
> +                              const struct cl_option_handlers *);
>  extern tree lhd_callgraph_analyze_expr (tree *, int *);
>
>
> @@ -89,7 +91,7 @@ extern void lhd_omp_firstprivatize_type_
>  #define LANG_HOOKS_INIT_OPTIONS                lhd_init_options
>  #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
>  #define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
> -#define LANG_HOOKS_HANDLE_OPTION       hook_int_size_t_constcharptr_int_0
> +#define LANG_HOOKS_HANDLE_OPTION       lhd_handle_option
>  #define LANG_HOOKS_POST_OPTIONS                lhd_post_options
>  #define LANG_HOOKS_MISSING_NORETURN_OK_P hook_bool_tree_true
>  #define LANG_HOOKS_GET_ALIAS_SET       lhd_get_alias_set
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks.c gcc-mainline/gcc/langhooks.c
> --- gcc-mainline-opt2/gcc/langhooks.c   2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/langhooks.c        2010-06-22 15:08:49.000000000 -0700
> @@ -351,6 +351,16 @@ lhd_complain_wrong_lang_p (const struct
>   return true;
>  }
>
> +/* By default, no language-specific options are valid.  */
> +bool
> +lhd_handle_option (size_t code ATTRIBUTE_UNUSED,
> +                  const char *arg ATTRIBUTE_UNUSED,
> +                  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
> +                  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
> +{
> +  return false;
> +}
> +
>  /* The default function to print out name of current function that caused
>    an error.  */
>  void
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks.h gcc-mainline/gcc/langhooks.h
> --- gcc-mainline-opt2/gcc/langhooks.h   2010-06-21 14:39:04.000000000 -0700
> +++ gcc-mainline/gcc/langhooks.h        2010-06-22 15:08:54.000000000 -0700
> @@ -292,11 +292,12 @@ struct lang_hooks
>      which points to permanent storage.  The handler is responsible for
>      checking whether ARG is NULL, which indicates that no argument
>      was in fact supplied.  For -f and -W switches, VALUE is 1 or 0
> -     for the positive and negative forms respectively.
> +     for the positive and negative forms respectively.  HANDLERS should
> +     be passed to any recursive handle_option calls.
>
> -     Return 1 if the switch is valid, 0 if invalid, and -1 if it's
> -     valid and should not be treated as language-independent too.  */
> -  int (*handle_option) (size_t code, const char *arg, int value, int kind);
> +     Return true if the switch is valid, false if invalid.  */
> +  bool (*handle_option) (size_t code, const char *arg, int value, int kind,
> +                        const struct cl_option_handlers *handlers);
>
>   /* Called when all command line options have been parsed to allow
>      further processing and initialization
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/lto/lto-lang.c gcc-mainline/gcc/lto/lto-lang.c
> --- gcc-mainline-opt2/gcc/lto/lto-lang.c        2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/lto/lto-lang.c     2010-06-22 15:09:02.000000000 -0700
> @@ -630,18 +630,18 @@ lto_init_options (unsigned int decoded_o
>    of the option was supplied.  */
>
>  const char *resolution_file_name;
> -static int
> +static bool
>  lto_handle_option (size_t scode, const char *arg,
> -                  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED)
> +                  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
> +                  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>  {
>   enum opt_code code = (enum opt_code) scode;
> -  int result = 1;
> +  bool result = true;
>
>   switch (code)
>     {
>     case OPT_fresolution_:
>       resolution_file_name = arg;
> -      result = 1;
>       break;
>
>     case OPT_Wabi:
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/optc-gen.awk gcc-mainline/gcc/optc-gen.awk
> --- gcc-mainline-opt2/gcc/optc-gen.awk  2010-06-21 14:56:03.000000000 -0700
> +++ gcc-mainline/gcc/optc-gen.awk       2010-06-22 15:25:22.000000000 -0700
> @@ -73,6 +73,7 @@ print "#include " quote "intl.h" quote
>  print ""
>  print "#ifdef GCC_DRIVER"
>  print "int target_flags;"
> +print "int target_flags_explicit;"
>  print "#else"
>  print "#include " quote "flags.h" quote
>  print "#include " quote "target.h" quote
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts-common.c gcc-mainline/gcc/opts-common.c
> --- gcc-mainline-opt2/gcc/opts-common.c 2010-06-21 10:02:42.000000000 -0700
> +++ gcc-mainline/gcc/opts-common.c      2010-06-22 15:23:48.000000000 -0700
> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.
>  #include "coretypes.h"
>  #include "opts.h"
>  #include "options.h"
> +#include "diagnostic.h"
>
>  /* Perform a binary search to find which option the command-line INPUT
>    matches.  Returns its index in the option array, and
> @@ -453,3 +454,135 @@ 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.  */
> +
> +bool
> +handle_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];
> +  size_t i;
> +
> +  if (option->flag_var)
> +    set_option (opt_index, value, arg, kind);
> +
> +  for (i = 0; i < handlers->num_handlers; i++)
> +    if (option->flags & handlers->handlers[i].mask)
> +      {
> +       if (!handlers->handlers[i].handler (opt_index, arg, value,
> +                                           lang_mask, kind, handlers))
> +         return false;
> +       else
> +         handlers->post_handling_callback (opt_index, arg, value,
> +                                           handlers->handlers[i].mask);
> +      }
> +
> +  return true;
> +}
> +
> +/* Handle the switch DECODED for the language indicated by LANG_MASK,
> +   using the handlers in *HANDLERS.  */
> +
> +void
> +read_cmdline_option (struct cl_decoded_option *decoded,
> +                    unsigned int lang_mask,
> +                    const struct cl_option_handlers *handlers)
> +{
> +  const struct cl_option *option;
> +  const char *opt;
> +
> +  if (decoded->opt_index == OPT_SPECIAL_unknown)
> +    {
> +      opt = decoded->arg;
> +
> +      if (handlers->unknown_option_callback (opt))
> +       error ("unrecognized command line option %qs", opt);
> +      return;
> +    }
> +
> +  option = &cl_options[decoded->opt_index];
> +  opt = decoded->orig_option_with_args_text;
> +
> +  if (decoded->errors & CL_ERR_DISABLED)
> +    {
> +      error ("command line option %qs"
> +            " is not supported by this configuration", opt);
> +      return;
> +    }
> +
> +  if (decoded->errors & CL_ERR_WRONG_LANG)
> +    {
> +      handlers->wrong_lang_callback (opt, option, lang_mask);
> +      return;
> +    }
> +
> +  if (decoded->errors & CL_ERR_MISSING_ARG)
> +    {
> +      if (option->missing_argument_error)
> +       error (option->missing_argument_error, opt);
> +      else
> +       error ("missing argument to %qs", opt);
> +      return;
> +    }
> +
> +  if (decoded->errors & CL_ERR_UINT_ARG)
> +    {
> +      error ("argument to %qs should be a non-negative integer",
> +            option->opt_text);
> +      return;
> +    }
> +
> +  gcc_assert (!decoded->errors);
> +
> +  if (!handle_option (decoded->opt_index, decoded->arg, decoded->value,
> +                     lang_mask, DK_UNSPECIFIED, handlers))
> +    error ("unrecognized command line option %qs", opt);
> +}
> +
> +/* Set any variable for option OPT_INDEX according to VALUE and ARG,
> +   diagnostic kind KIND.  */
> +
> +void
> +set_option (int opt_index, int value, const char *arg, int kind)
> +{
> +  const struct cl_option *option = &cl_options[opt_index];
> +
> +  if (!option->flag_var)
> +    return;
> +
> +  switch (option->var_type)
> +    {
> +    case CLVC_BOOLEAN:
> +       *(int *) option->flag_var = value;
> +       break;
> +
> +    case CLVC_EQUAL:
> +       *(int *) option->flag_var = (value
> +                                    ? option->var_value
> +                                    : !option->var_value);
> +       break;
> +
> +    case CLVC_BIT_CLEAR:
> +    case CLVC_BIT_SET:
> +       if ((value != 0) == (option->var_type == CLVC_BIT_SET))
> +         *(int *) option->flag_var |= option->var_value;
> +       else
> +         *(int *) option->flag_var &= ~option->var_value;
> +       if (option->flag_var == &target_flags)
> +         target_flags_explicit |= option->var_value;
> +       break;
> +
> +    case CLVC_STRING:
> +       *(const char **) option->flag_var = arg;
> +       break;
> +    }
> +
> +  if ((diagnostic_t) kind != DK_UNSPECIFIED)
> +    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t) kind);
> +}
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts.c gcc-mainline/gcc/opts.c
> --- gcc-mainline-opt2/gcc/opts.c        2010-06-21 14:40:58.000000000 -0700
> +++ gcc-mainline/gcc/opts.c     2010-06-22 15:22:33.000000000 -0700
> @@ -372,8 +372,9 @@ bool flag_warn_unused_result = false;
>  const char **in_fnames;
>  unsigned num_in_fnames;
>
> -static int common_handle_option (size_t scode, const char *arg, int value,
> -                                unsigned int lang_mask, int kind);
> +static bool common_handle_option (size_t scode, const char *arg, int value,
> +                                 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 *,
> @@ -460,112 +461,58 @@ void print_ignored_options (void)
>   input_location = saved_loc;
>  }
>
> +/* Handle an unknown option ARG, returning true if an error should be
> +   given.  */
>
> -/* Handle option OPT_INDEX, and argument ARG, for the language
> -   indicated by LANG_MASK.  VALUE is true, unless no- form of an -f or
> -   -W option was given.  KIND is the diagnostic_t if this is a
> -   diagnostics option, DK_UNSPECIFIED otherwise.  Returns false if the
> -   switch was invalid.  */
> -bool
> -handle_option (int opt_index, int value, const char *arg,
> -               unsigned int lang_mask, int kind)
> +static bool
> +unknown_option_callback (const char *opt)
>  {
> -  const struct cl_option *option = &cl_options[opt_index];
> -
> -  if (option->flag_var)
> -    set_option (opt_index, value, arg, kind);
> -
> -  if (option->flags & lang_mask)
> +  if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
>     {
> -      if (lang_hooks.handle_option (opt_index, arg, value, kind) == 0)
> -       return false;
> -#ifdef ENABLE_LTO
> -      else
> -       lto_register_user_option (opt_index, arg, value, lang_mask);
> - #endif
> +      /* We don't generate warnings for unknown -Wno-* options unless
> +        we issue diagnostics.  */
> +      postpone_unknown_option_warning (opt);
> +      return false;
>     }
> +  else
> +    return true;
> +}
>
> -  if (option->flags & CL_COMMON)
> -    {
> -      if (common_handle_option (opt_index, arg, value, lang_mask, kind) == 0)
> -       return false;
> -#ifdef ENABLE_LTO
> -      else
> -       lto_register_user_option (opt_index, arg, value, CL_COMMON);
> -#endif
> -    }
> +/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
> +   has been successfully handled with a handler for mask MASK.  */
>
> -  if (option->flags & CL_TARGET)
> -    {
> -      if (!targetm.handle_option (opt_index, arg, value))
> -       return false;
> +static void
> +post_handling_callback (size_t opt_index ATTRIBUTE_UNUSED,
> +                       const char *arg ATTRIBUTE_UNUSED,
> +                       int value ATTRIBUTE_UNUSED,
> +                       unsigned int mask ATTRIBUTE_UNUSED)
> +{
>  #ifdef ENABLE_LTO
> -      else
> -       lto_register_user_option (opt_index, arg, value, CL_TARGET);
> +  lto_register_user_option (opt_index, arg, value, mask);
>  #endif
> -    }
> -  return true;
>  }
>
> -/* Handle the switch DECODED for the language indicated by
> -   LANG_MASK.  */
> -static void
> -read_cmdline_option (struct cl_decoded_option *decoded,
> -                    unsigned int lang_mask)
> -{
> -  const struct cl_option *option;
> -  const char *opt;
> -
> -  if (decoded->opt_index == OPT_SPECIAL_unknown)
> -    {
> -      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 we issue diagnostics.  */
> -         postpone_unknown_option_warning (opt);
> -      else
> -       error ("unrecognized command line option %qs", opt);
> -      return;
> -    }
> -
> -  option = &cl_options[decoded->opt_index];
> -  opt = decoded->orig_option_with_args_text;
> +/* Handle a front-end option; arguments and return value as for
> +   handle_option.  */
>
> -  if (decoded->errors & CL_ERR_DISABLED)
> -    {
> -      error ("command line option %qs"
> -            " is not supported by this configuration", opt);
> -      return;
> -    }
> -
> -  if (decoded->errors & CL_ERR_WRONG_LANG)
> -    {
> -      complain_wrong_lang (opt, option, lang_mask);
> -      return;
> -    }
> -
> -  if (decoded->errors & CL_ERR_MISSING_ARG)
> -    {
> -      if (option->missing_argument_error)
> -       error (option->missing_argument_error, opt);
> -      else
> -       error ("missing argument to %qs", opt);
> -      return;
> -    }
> -
> -  if (decoded->errors & CL_ERR_UINT_ARG)
> -    {
> -      error ("argument to %qs should be a non-negative integer",
> -            option->opt_text);
> -      return;
> -    }
> +static bool
> +lang_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)
> +{
> +  return lang_hooks.handle_option (opt_index, arg, value, kind, handlers);
> +}
>
> -  gcc_assert (!decoded->errors);
> +/* Handle a back-end option; arguments and return value as for
> +   handle_option.  */
>
> -  if (!handle_option (decoded->opt_index, decoded->value, decoded->arg,
> -                     lang_mask, DK_UNSPECIFIED))
> -    error ("unrecognized command line option %qs", opt);
> +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)
> +{
> +  gcc_assert (kind == DK_UNSPECIFIED);
> +  return targetm.handle_option (opt_index, arg, value);
>  }
>
>  /* Handle FILENAME from the command line.  */
> @@ -659,11 +606,12 @@ flag_instrument_functions_exclude_p (tre
>
>  /* Handle the vector of command line options.  LANG_MASK
>    contains has a single bit set representing the current
> -   language.  */
> +   language.  HANDLERS describes what functions to call for the options.  */
>  static void
>  read_cmdline_options (struct cl_decoded_option *decoded_options,
>                      unsigned int decoded_options_count,
> -                     unsigned int lang_mask)
> +                     unsigned int lang_mask,
> +                     const struct cl_option_handlers *handlers)
>  {
>   unsigned int i;
>
> @@ -681,7 +629,7 @@ read_cmdline_options (struct cl_decoded_
>          continue;
>        }
>
> -      read_cmdline_option (decoded_options + i, lang_mask);
> +      read_cmdline_option (decoded_options + i, lang_mask, handlers);
>     }
>  }
>
> @@ -698,6 +646,7 @@ decode_options (unsigned int argc, const
>   static int initial_max_fields_for_field_sensitive;
>   static int initial_loop_invariant_max_bbs_in_loop;
>   static unsigned int initial_lang_mask;
> +  struct cl_option_handlers handlers;
>
>   unsigned int i, lang_mask;
>   int opt1;
> @@ -730,6 +679,17 @@ decode_options (unsigned int argc, const
>     /* Perform language-specific options initialization.  */
>     lang_hooks.init_options (*decoded_options_count, *decoded_options);
>
> +  handlers.unknown_option_callback = unknown_option_callback;
> +  handlers.wrong_lang_callback = complain_wrong_lang;
> +  handlers.post_handling_callback = post_handling_callback;
> +  handlers.num_handlers = 3;
> +  handlers.handlers[0].handler = lang_handle_option;
> +  handlers.handlers[0].mask = lang_mask;
> +  handlers.handlers[1].handler = common_handle_option;
> +  handlers.handlers[1].mask = CL_COMMON;
> +  handlers.handlers[2].handler = target_handle_option;
> +  handlers.handlers[2].mask = CL_TARGET;
> +
>   /* Scan to see what optimization level has been specified.  That will
>      determine the default value of many flags.  */
>   for (i = 1; i < *decoded_options_count; i++)
> @@ -903,7 +863,7 @@ decode_options (unsigned int argc, const
>     }
>
>   /* Enable -Werror=coverage-mismatch by default */
> -  enable_warning_as_error("coverage-mismatch", 1, lang_mask);
> +  enable_warning_as_error ("coverage-mismatch", 1, lang_mask, &handlers);
>
>   if (first_time_p)
>     {
> @@ -931,7 +891,8 @@ decode_options (unsigned int argc, const
>   OPTIMIZATION_OPTIONS (optimize, optimize_size);
>  #endif
>
> -  read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask);
> +  read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask,
> +                       &handlers);
>
>   if (dump_base_name && ! IS_ABSOLUTE_PATH (dump_base_name))
>     {
> @@ -1425,9 +1386,10 @@ print_specific_help (unsigned int includ
>    extra handling need to be listed here; if you simply want
>    VALUE assigned to a variable, it happens automatically.  */
>
> -static int
> +static bool
>  common_handle_option (size_t scode, const char *arg, int value,
> -                     unsigned int lang_mask, int kind ATTRIBUTE_UNUSED)
> +                     unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
> +                     const struct cl_option_handlers *handlers)
>  {
>   static bool verbose = false;
>   enum opt_code code = (enum opt_code) scode;
> @@ -1609,7 +1571,7 @@ common_handle_option (size_t scode, cons
>       break;
>
>     case OPT_Werror_:
> -      enable_warning_as_error (arg, value, lang_mask);
> +      enable_warning_as_error (arg, value, lang_mask, handlers);
>       break;
>
>     case OPT_Wlarger_than_:
> @@ -1735,7 +1697,7 @@ common_handle_option (size_t scode, cons
>        diagnostic_prefixing_rule (global_dc)
>          = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
>       else
> -       return 0;
> +       return false;
>       break;
>
>     case OPT_fdiagnostics_show_option:
> @@ -1744,7 +1706,7 @@ common_handle_option (size_t scode, cons
>
>     case OPT_fdump_:
>       if (!dump_switch_p (arg))
> -       return 0;
> +       return false;
>       break;
>
>     case OPT_fexcess_precision_:
> @@ -1908,7 +1870,7 @@ common_handle_option (size_t scode, cons
>     case OPT_frandom_seed:
>       /* The real switch is -fno-random-seed.  */
>       if (value)
> -       return 0;
> +       return false;
>       set_random_seed (NULL);
>       break;
>
> @@ -1926,7 +1888,7 @@ common_handle_option (size_t scode, cons
>       fix_sched_param ("verbose", arg);
>       break;
>  #else
> -      return 0;
> +      return false;
>  #endif
>
>     case OPT_fsched_stalled_insns_:
> @@ -1973,7 +1935,7 @@ common_handle_option (size_t scode, cons
>     case OPT_fstack_limit:
>       /* The real switch is -fno-stack-limit.  */
>       if (value)
> -       return 0;
> +       return false;
>       stack_limit_rtx = NULL_RTX;
>       break;
>
> @@ -2140,7 +2102,7 @@ common_handle_option (size_t scode, cons
>       break;
>     }
>
> -  return 1;
> +  return true;
>  }
>
>  /* Handle --param NAME=VALUE.  */
> @@ -2355,48 +2317,6 @@ get_option_state (int option, struct cl_
>   return true;
>  }
>
> -/* Set *OPTION according to VALUE and ARG.  */
> -
> -void
> -set_option (int opt_index, int value, const char *arg, int kind)
> -{
> -  const struct cl_option *option = &cl_options[opt_index];
> -
> -  if (!option->flag_var)
> -    return;
> -
> -  switch (option->var_type)
> -    {
> -    case CLVC_BOOLEAN:
> -       *(int *) option->flag_var = value;
> -       break;
> -
> -    case CLVC_EQUAL:
> -       *(int *) option->flag_var = (value
> -                                    ? option->var_value
> -                                    : !option->var_value);
> -       break;
> -
> -    case CLVC_BIT_CLEAR:
> -    case CLVC_BIT_SET:
> -       if ((value != 0) == (option->var_type == CLVC_BIT_SET))
> -         *(int *) option->flag_var |= option->var_value;
> -       else
> -         *(int *) option->flag_var &= ~option->var_value;
> -       if (option->flag_var == &target_flags)
> -         target_flags_explicit |= option->var_value;
> -       break;
> -
> -    case CLVC_STRING:
> -       *(const char **) option->flag_var = arg;
> -       break;
> -    }
> -
> -  if ((diagnostic_t)kind != DK_UNSPECIFIED)
> -    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t)kind);
> -}
> -
> -
>  /* Callback function, called when -Werror= enables a warning.  */
>
>  static void (*warning_as_error_callback) (int) = NULL;
> @@ -2414,7 +2334,8 @@ register_warning_as_error_callback (void
>    also by legacy Werror-implicit-function-declaration.  */
>
>  void
> -enable_warning_as_error (const char *arg, int value, unsigned int lang_mask)
> +enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
> +                        const struct cl_option_handlers *handlers)
>  {
>   char *new_option;
>   int option_index;
> @@ -2438,7 +2359,8 @@ enable_warning_as_error (const char *arg
>
>          /* -Werror=foo implies -Wfoo.  */
>          if (option->var_type == CLVC_BOOLEAN)
> -           handle_option (option_index, value, arg, lang_mask, (int)kind);
> +           handle_option (option_index, arg, value, lang_mask, (int)kind,
> +                          handlers);
>
>          if (warning_as_error_callback)
>            warning_as_error_callback (option_index);
> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts.h gcc-mainline/gcc/opts.h
> --- gcc-mainline-opt2/gcc/opts.h        2010-06-21 15:24:55.000000000 -0700
> +++ gcc-mainline/gcc/opts.h     2010-06-22 15:15:44.000000000 -0700
> @@ -135,6 +135,47 @@ struct cl_decoded_option
>   int errors;
>  };
>
> +/* Structure describing a single option-handling callback.  */
> +
> +struct cl_option_handler_func
> +{
> +  /* The function called to handle the option.  */
> +  bool (*handler) (size_t opt_index, const char *arg, int value,
> +                  unsigned int lang_mask, int kind,
> +                  const struct cl_option_handlers *handlers);
> +
> +  /* The mask that must have some bit in common with the flags for the
> +     option for this particular handler to be used.  */
> +  unsigned int mask;
> +};
> +
> +/* Structure describing the callbacks used in handling options.  */
> +
> +struct cl_option_handlers
> +{
> +  /* Callback for an unknown option to determine whether to give an
> +     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);
> +
> +  /* Callback to handle, and possibly diagnose, an option for another
> +     language.  */
> +  void (*wrong_lang_callback) (const char *text,
> +                              const struct cl_option *option,
> +                              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);
> +
> +  /* The number of individual handlers.  */
> +  size_t num_handlers;
> +
> +  /* The handlers themselves.  */
> +  struct cl_option_handler_func handlers[3];
> +};
> +
>  /* Input file names.  */
>
>  extern const char **in_fnames;
> @@ -157,10 +198,15 @@ 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 (int opt_index, int value, const char *arg,
> -                   unsigned int lang_mask, int kind);
> +bool handle_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);
>  extern void register_warning_as_error_callback (void (*callback) (int));
>  extern void enable_warning_as_error (const char *arg, int value,
> -                                    unsigned int lang_mask);
> +                                    unsigned int lang_mask,
> +                                    const struct cl_option_handlers *handlers);
>  extern void print_ignored_options (void);
>  #endif
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>
Richard Guenther - June 25, 2010, 3:16 p.m.
On Fri, Jun 25, 2010 at 4:28 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Jun 23, 2010 at 2:50 AM, Joseph S. Myers
> <joseph@codesourcery.com> wrote:
>> This patch is relative to a tree with
>> <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg01968.html> and
>> <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02150.html> applied.
>> The former needs C++ and Ada pieces approved; the latter needs C++
>> pieces approved.
>>
>> Continuing the work towards sharing option processing code between the
>> driver and the compiler proper, this patch moves handle_option and
>> read_cmdline_option, and the set_option function they use, into
>> opts-common.c.  In various places where these functions do things that
>> may not be appropriate in the driver at least initially, appropriate
>> callbacks are provided, and a cl_option_handlers structure is used to
>> describe these callbacks.
>>
>> The set of callbacks is needed by recursive handle_option calls (from
>> options enabling other options) and so some prototypes, including for
>> the handle_option langhook, are adjusted to pass the handlers
>> pointer.  The handle_option langhook is also adjusted to have a
>> boolean return value; the comments suggested a tristate return value
>> but nothing used or acted on a negative return value as was suggested
>> in the comments.  The Ada hook had useless checks for missing option
>> arguments (erroneous options don't get passed to these handlers),
>> which I removed.  The argument order of the handle_option function is
>> adjusted to match that of various related functions, by swapping the
>> arg and value operands.
>>
>> Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
>> commit?
>
> Ok for the non-frontend specific changes.

Also for the LTO changes.  For your convenience consider them
middle-end or non-frontend specific when I approve these parts
(I tend to forget that LTO is not middle-end ...).

Richard.

> Richard.
>
>> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>>
>>        * coretypes.h (struct cl_option_handlers): Declare.
>>        * hooks.c (hook_int_size_t_constcharptr_int_0): Remove.
>>        * hooks.h (hook_int_size_t_constcharptr_int_0): Remove.
>>        * langhooks-def.h (lhd_handle_option): Declare.
>>        (LANG_HOOKS_HANDLE_OPTION): Use lhd_handle_option.
>>        * langhooks.c (lhd_handle_option): New.
>>        * langhooks.h (struct lang_hooks): Update prototype and return
>>        value type of handle_option hook.
>>        * optc-gen.awk: Generate target_flags_explicit definition for the
>>        driver.
>>        * opts-common.c: Include diagnostic.h.
>>        (handle_option): Move from opts.c.  Update prototype and return
>>        value type.  Use handlers structure.
>>        (read_cmdline_option): Move from opts.c.  Update prototype.  Use
>>        handlers structure.
>>        (set_option): Move from opts.c.
>>        * opts.c (common_handle_option): Update prototype and return value
>>        type.  Update calls to handle_option and enable_warning_as_error.
>>        (unknown_option_callback, post_handling_callback,
>>        lang_handle_option, target_handle_option): New.
>>        (handle_option, read_cmdline_option): Move to opts-common.c.
>>        (read_cmdline_options): Update prototype.  Update call to
>>        read_cmdline_option.
>>        (decode_options): Initialize and use handlers structure.
>>        (set_option): Move to opts-common.c.
>>        (enable_warning_as_error): Update prototype.  Update call to
>>        handle_option.
>>        * opts.h (struct cl_option_handler_func, struct
>>        cl_option_handlers): New.
>>        (handle_option, enable_warning_as_error): Update prototypes.
>>        (read_cmdline_option): Declare.
>>        * Makefile.in (opts-common.o): Update dependencies.
>>
>> ada:
>> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>>
>>        * gcc-interface/misc.c (gnat_handle_option): Update prototype and
>>        return value type.  Don't check for missing arguments here.
>>
>> c-family:
>> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>>
>>        * c-common.h (c_common_handle_option): Update prototype and return
>>        value type.
>>        * c-opts.c (c_common_handle_option): Update prototype and return
>>        value type.  Update calls to handle_option and
>>        enable_warning_as_error.
>>
>> fortran:
>> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>>
>>        * gfortran.h (gfc_handle_option): Update prototype and return
>>        value type.
>>        * options.c (gfc_handle_option): Update prototype and return value
>>        type.
>>
>> java:
>> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>>
>>        * lang.c (java_handle_option): Update prototype and return value
>>        type.
>>
>> lto:
>> 2010-06-22  Joseph Myers  <joseph@codesourcery.com>
>>
>>        * lto-lang.c (lto_handle_option): Update prototype and return
>>        value type.  Remove duplicate assignment to result.
>>
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/Makefile.in gcc-mainline/gcc/Makefile.in
>> --- gcc-mainline-opt2/gcc/Makefile.in   2010-06-21 09:57:36.000000000 -0700
>> +++ gcc-mainline/gcc/Makefile.in        2010-06-22 15:24:00.000000000 -0700
>> @@ -2796,7 +2796,7 @@ opts.o : opts.c opts.h options.h $(TOPLE
>>    $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h \
>>    $(PLUGIN_H) $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
>>  opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
>> -   coretypes.h intl.h
>> +   coretypes.h intl.h $(DIAGNOSTIC_H)
>>  targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
>>    $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
>>    $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h \
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/ada/gcc-interface/misc.c gcc-mainline/gcc/ada/gcc-interface/misc.c
>> --- gcc-mainline-opt2/gcc/ada/gcc-interface/misc.c      2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/ada/gcc-interface/misc.c   2010-06-22 16:02:04.000000000 -0700
>> @@ -65,7 +65,8 @@ static bool gnat_init                 (void);
>>  static unsigned int gnat_option_lang_mask (void);
>>  static void gnat_init_options          (unsigned int,
>>                                         struct cl_decoded_option *);
>> -static int gnat_handle_option          (size_t, const char *, int, int);
>> +static bool gnat_handle_option         (size_t, const char *, int, int,
>> +                                        const struct cl_option_handlers *);
>>  static bool gnat_post_options          (const char **);
>>  static alias_set_type gnat_get_alias_set (tree);
>>  static void gnat_print_decl            (FILE *, tree, int);
>> @@ -187,23 +188,16 @@ gnat_parse_file (int set_yydebug ATTRIBU
>>
>>  /* Decode all the language specific options that cannot be decoded by GCC.
>>    The option decoding phase of GCC calls this routine on the flags that
>> -   it cannot decode.  Return the number of consecutive arguments from ARGV
>> -   that have been successfully decoded or 0 on failure.  */
>> +   are marked as Ada-specific.  Return true on success or false on failure.  */
>>
>> -static int
>> +static bool
>>  gnat_handle_option (size_t scode, const char *arg, int value,
>> -                   int kind ATTRIBUTE_UNUSED)
>> +                   int kind ATTRIBUTE_UNUSED,
>> +                   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>>  {
>> -  const struct cl_option *option = &cl_options[scode];
>>   enum opt_code code = (enum opt_code) scode;
>>   char *q;
>>
>> -  if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
>> -    {
>> -      error ("missing argument to \"-%s\"", option->opt_text);
>> -      return 1;
>> -    }
>> -
>>   switch (code)
>>     {
>>     case OPT_I:
>> @@ -280,7 +274,7 @@ gnat_handle_option (size_t scode, const
>>       gcc_unreachable ();
>>     }
>>
>> -  return 1;
>> +  return true;
>>  }
>>
>>  /* Return language mask for option processing.  */
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/c-family/c-common.h gcc-mainline/gcc/c-family/c-common.h
>> --- gcc-mainline-opt2/gcc/c-family/c-common.h   2010-06-21 14:38:50.000000000 -0700
>> +++ gcc-mainline/gcc/c-family/c-common.h        2010-06-22 15:08:11.000000000 -0700
>> @@ -652,7 +652,8 @@ extern void set_Wformat (int);
>>  extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
>>  extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
>>  extern bool attribute_takes_identifier_p (const_tree);
>> -extern int c_common_handle_option (size_t code, const char *arg, int value, int kind);
>> +extern bool c_common_handle_option (size_t, const char *, int, int,
>> +                                   const struct cl_option_handlers *);
>>  extern tree c_common_type_for_mode (enum machine_mode, int);
>>  extern tree c_common_type_for_size (unsigned int, int);
>>  extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/c-family/c-opts.c gcc-mainline/gcc/c-family/c-opts.c
>> --- gcc-mainline-opt2/gcc/c-family/c-opts.c     2010-06-21 14:53:58.000000000 -0700
>> +++ gcc-mainline/gcc/c-family/c-opts.c  2010-06-22 15:08:05.000000000 -0700
>> @@ -319,16 +319,15 @@ c_common_init_options (unsigned int deco
>>  }
>>
>>  /* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
>> -   form of an -f or -W option was given.  Returns 0 if the switch was
>> -   invalid, a negative number to prevent language-independent
>> -   processing in toplev.c (a hack necessary for the short-term).  */
>> -int
>> +   form of an -f or -W option was given.  Returns false if the switch was
>> +   invalid, true if valid.  Use HANDLERS in recursive handle_option calls.  */
>> +bool
>>  c_common_handle_option (size_t scode, const char *arg, int value,
>> -                       int kind)
>> +                       int kind, const struct cl_option_handlers *handlers)
>>  {
>>   const struct cl_option *option = &cl_options[scode];
>>   enum opt_code code = (enum opt_code) scode;
>> -  int result = 1;
>> +  bool result = true;
>>
>>   /* Prevent resetting the language standard to a C dialect when the driver
>>      has already determined that we're looking at assembler input.  */
>> @@ -341,10 +340,10 @@ c_common_handle_option (size_t scode, co
>>        {
>>          if ((option->flags & CL_TARGET)
>>              && ! targetcm.handle_c_option (scode, arg, value))
>> -           result = 0;
>> +           result = false;
>>          break;
>>        }
>> -      result = 0;
>> +      result = false;
>>       break;
>>
>>     case OPT__output_pch_:
>> @@ -438,7 +437,8 @@ c_common_handle_option (size_t scode, co
>>     case OPT_Wall:
>>       warn_unused = value;
>>       set_Wformat (value);
>> -      handle_option (OPT_Wimplicit, value, NULL, c_family_lang_mask, kind);
>> +      handle_option (OPT_Wimplicit, NULL, value, c_family_lang_mask, kind,
>> +                    handlers);
>>       warn_char_subscripts = value;
>>       warn_missing_braces = value;
>>       warn_parentheses = value;
>> @@ -524,7 +524,8 @@ c_common_handle_option (size_t scode, co
>>     case OPT_Werror_implicit_function_declaration:
>>       /* For backward compatibility, this is the same as
>>         -Werror=implicit-function-declaration.  */
>> -      enable_warning_as_error ("implicit-function-declaration", value, CL_C | CL_ObjC);
>> +      enable_warning_as_error ("implicit-function-declaration", value,
>> +                              CL_C | CL_ObjC, handlers);
>>       break;
>>
>>     case OPT_Wformat:
>> @@ -538,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, value, NULL,
>> -                      c_family_lang_mask, kind);
>> +       handle_option (OPT_Wimplicit_int, NULL, value,
>> +                      c_family_lang_mask, kind, handlers);
>>       if (warn_implicit_function_declaration == -1)
>> -       handle_option (OPT_Wimplicit_function_declaration, value, NULL,
>> -                      c_family_lang_mask, kind);
>> +       handle_option (OPT_Wimplicit_function_declaration, NULL, value,
>> +                      c_family_lang_mask, kind, handlers);
>>       break;
>>
>>     case OPT_Wimport:
>> @@ -655,7 +656,7 @@ c_common_handle_option (size_t scode, co
>>
>>     case OPT_fbuiltin_:
>>       if (value)
>> -       result = 0;
>> +       result = false;
>>       else
>>        disable_builtin_function (arg);
>>       break;
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/coretypes.h gcc-mainline/gcc/coretypes.h
>> --- gcc-mainline-opt2/gcc/coretypes.h   2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/coretypes.h        2010-06-22 14:34:22.000000000 -0700
>> @@ -68,6 +68,7 @@ struct cl_target_option;
>>  struct cl_optimization;
>>  struct cl_option;
>>  struct cl_decoded_option;
>> +struct cl_option_handlers;
>>  struct gimple_seq_d;
>>  typedef struct gimple_seq_d *gimple_seq;
>>  typedef const struct gimple_seq_d *const_gimple_seq;
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/fortran/gfortran.h gcc-mainline/gcc/fortran/gfortran.h
>> --- gcc-mainline-opt2/gcc/fortran/gfortran.h    2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/fortran/gfortran.h 2010-06-22 15:08:23.000000000 -0700
>> @@ -2346,7 +2346,8 @@ int get_c_kind (const char *, CInteropKi
>>  unsigned int gfc_option_lang_mask (void);
>>  void gfc_init_options (unsigned int,
>>                       struct cl_decoded_option *);
>> -int gfc_handle_option (size_t, const char *, int, int);
>> +bool gfc_handle_option (size_t, const char *, int, int,
>> +                       const struct cl_option_handlers *);
>>  bool gfc_post_options (const char **);
>>
>>  /* f95-lang.c */
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/fortran/options.c gcc-mainline/gcc/fortran/options.c
>> --- gcc-mainline-opt2/gcc/fortran/options.c     2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/fortran/options.c  2010-06-22 15:08:27.000000000 -0700
>> @@ -542,20 +542,21 @@ gfc_handle_runtime_check_option (const c
>>  /* Handle command-line options.  Returns 0 if unrecognized, 1 if
>>    recognized and handled.  */
>>
>> -int
>> +bool
>>  gfc_handle_option (size_t scode, const char *arg, int value,
>> -                  int kind ATTRIBUTE_UNUSED)
>> +                  int kind ATTRIBUTE_UNUSED,
>> +                  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>>  {
>> -  int result = 1;
>> +  bool result = true;
>>   enum opt_code code = (enum opt_code) scode;
>>
>>   if (gfc_cpp_handle_option (scode, arg, value) == 1)
>> -    return 1;
>> +    return true;
>>
>>   switch (code)
>>     {
>>     default:
>> -      result = 0;
>> +      result = false;
>>       break;
>>
>>     case OPT_Wall:
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/hooks.c gcc-mainline/gcc/hooks.c
>> --- gcc-mainline-opt2/gcc/hooks.c       2010-06-21 14:38:03.000000000 -0700
>> +++ gcc-mainline/gcc/hooks.c    2010-06-22 14:31:06.000000000 -0700
>> @@ -160,14 +160,6 @@ hook_int_rtx_bool_0 (rtx a ATTRIBUTE_UNU
>>   return 0;
>>  }
>>
>> -int
>> -hook_int_size_t_constcharptr_int_0 (size_t a ATTRIBUTE_UNUSED,
>> -                                   const char *b ATTRIBUTE_UNUSED,
>> -                                   int c ATTRIBUTE_UNUSED)
>> -{
>> -  return 0;
>> -}
>> -
>>  unsigned int
>>  hook_uint_void_0 (void)
>>  {
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/hooks.h gcc-mainline/gcc/hooks.h
>> --- gcc-mainline-opt2/gcc/hooks.h       2010-06-21 14:38:18.000000000 -0700
>> +++ gcc-mainline/gcc/hooks.h    2010-06-22 14:31:17.000000000 -0700
>> @@ -63,7 +63,6 @@ extern int hook_int_const_tree_0 (const_
>>  extern int hook_int_const_tree_const_tree_1 (const_tree, const_tree);
>>  extern int hook_int_rtx_0 (rtx);
>>  extern int hook_int_rtx_bool_0 (rtx, bool);
>> -extern int hook_int_size_t_constcharptr_int_0 (size_t, const char *, int);
>>
>>  extern tree hook_tree_const_tree_null (const_tree);
>>
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/java/lang.c gcc-mainline/gcc/java/lang.c
>> --- gcc-mainline-opt2/gcc/java/lang.c   2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/java/lang.c        2010-06-22 15:08:40.000000000 -0700
>> @@ -51,7 +51,8 @@ static unsigned int java_option_lang_mas
>>  static void java_init_options (unsigned int, struct cl_decoded_option *);
>>  static bool java_post_options (const char **);
>>
>> -static int java_handle_option (size_t scode, const char *arg, int value, int kind);
>> +static bool java_handle_option (size_t, const char *, int, int,
>> +                               const struct cl_option_handlers *);
>>  static void put_decl_string (const char *, int);
>>  static void put_decl_node (tree, int);
>>  static void java_print_error_function (diagnostic_context *, const char *,
>> @@ -175,11 +176,12 @@ struct lang_hooks lang_hooks = LANG_HOOK
>>
>>  /*
>>  * process java-specific compiler command-line options
>> - * return 0, but do not complain if the option is not recognized.
>> + * return false, but do not complain if the option is not recognized.
>>  */
>> -static int
>> +static bool
>>  java_handle_option (size_t scode, const char *arg, int value,
>> -                   int kind ATTRIBUTE_UNUSED)
>> +                   int kind ATTRIBUTE_UNUSED,
>> +                   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>>  {
>>   enum opt_code code = (enum opt_code) scode;
>>
>> @@ -270,7 +272,7 @@ java_handle_option (size_t scode, const
>>
>>     case OPT_fdump_:
>>       if (!dump_switch_p (arg))
>> -       return 0;
>> +       return false;
>>       break;
>>
>>     case OPT_fencoding_:
>> @@ -299,7 +301,7 @@ java_handle_option (size_t scode, const
>>       gcc_unreachable ();
>>     }
>>
>> -  return 1;
>> +  return true;
>>  }
>>
>>  /* Global open file.  */
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks-def.h gcc-mainline/gcc/langhooks-def.h
>> --- gcc-mainline-opt2/gcc/langhooks-def.h       2010-06-21 14:39:18.000000000 -0700
>> +++ gcc-mainline/gcc/langhooks-def.h    2010-06-22 15:13:56.000000000 -0700
>> @@ -69,6 +69,8 @@ extern void lhd_initialize_diagnostics (
>>  extern void lhd_init_options (unsigned int,
>>                              struct cl_decoded_option *);
>>  extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
>> +extern bool lhd_handle_option (size_t, const char *, int, int,
>> +                              const struct cl_option_handlers *);
>>  extern tree lhd_callgraph_analyze_expr (tree *, int *);
>>
>>
>> @@ -89,7 +91,7 @@ extern void lhd_omp_firstprivatize_type_
>>  #define LANG_HOOKS_INIT_OPTIONS                lhd_init_options
>>  #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
>>  #define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
>> -#define LANG_HOOKS_HANDLE_OPTION       hook_int_size_t_constcharptr_int_0
>> +#define LANG_HOOKS_HANDLE_OPTION       lhd_handle_option
>>  #define LANG_HOOKS_POST_OPTIONS                lhd_post_options
>>  #define LANG_HOOKS_MISSING_NORETURN_OK_P hook_bool_tree_true
>>  #define LANG_HOOKS_GET_ALIAS_SET       lhd_get_alias_set
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks.c gcc-mainline/gcc/langhooks.c
>> --- gcc-mainline-opt2/gcc/langhooks.c   2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/langhooks.c        2010-06-22 15:08:49.000000000 -0700
>> @@ -351,6 +351,16 @@ lhd_complain_wrong_lang_p (const struct
>>   return true;
>>  }
>>
>> +/* By default, no language-specific options are valid.  */
>> +bool
>> +lhd_handle_option (size_t code ATTRIBUTE_UNUSED,
>> +                  const char *arg ATTRIBUTE_UNUSED,
>> +                  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
>> +                  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>> +{
>> +  return false;
>> +}
>> +
>>  /* The default function to print out name of current function that caused
>>    an error.  */
>>  void
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks.h gcc-mainline/gcc/langhooks.h
>> --- gcc-mainline-opt2/gcc/langhooks.h   2010-06-21 14:39:04.000000000 -0700
>> +++ gcc-mainline/gcc/langhooks.h        2010-06-22 15:08:54.000000000 -0700
>> @@ -292,11 +292,12 @@ struct lang_hooks
>>      which points to permanent storage.  The handler is responsible for
>>      checking whether ARG is NULL, which indicates that no argument
>>      was in fact supplied.  For -f and -W switches, VALUE is 1 or 0
>> -     for the positive and negative forms respectively.
>> +     for the positive and negative forms respectively.  HANDLERS should
>> +     be passed to any recursive handle_option calls.
>>
>> -     Return 1 if the switch is valid, 0 if invalid, and -1 if it's
>> -     valid and should not be treated as language-independent too.  */
>> -  int (*handle_option) (size_t code, const char *arg, int value, int kind);
>> +     Return true if the switch is valid, false if invalid.  */
>> +  bool (*handle_option) (size_t code, const char *arg, int value, int kind,
>> +                        const struct cl_option_handlers *handlers);
>>
>>   /* Called when all command line options have been parsed to allow
>>      further processing and initialization
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/lto/lto-lang.c gcc-mainline/gcc/lto/lto-lang.c
>> --- gcc-mainline-opt2/gcc/lto/lto-lang.c        2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/lto/lto-lang.c     2010-06-22 15:09:02.000000000 -0700
>> @@ -630,18 +630,18 @@ lto_init_options (unsigned int decoded_o
>>    of the option was supplied.  */
>>
>>  const char *resolution_file_name;
>> -static int
>> +static bool
>>  lto_handle_option (size_t scode, const char *arg,
>> -                  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED)
>> +                  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
>> +                  const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
>>  {
>>   enum opt_code code = (enum opt_code) scode;
>> -  int result = 1;
>> +  bool result = true;
>>
>>   switch (code)
>>     {
>>     case OPT_fresolution_:
>>       resolution_file_name = arg;
>> -      result = 1;
>>       break;
>>
>>     case OPT_Wabi:
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/optc-gen.awk gcc-mainline/gcc/optc-gen.awk
>> --- gcc-mainline-opt2/gcc/optc-gen.awk  2010-06-21 14:56:03.000000000 -0700
>> +++ gcc-mainline/gcc/optc-gen.awk       2010-06-22 15:25:22.000000000 -0700
>> @@ -73,6 +73,7 @@ print "#include " quote "intl.h" quote
>>  print ""
>>  print "#ifdef GCC_DRIVER"
>>  print "int target_flags;"
>> +print "int target_flags_explicit;"
>>  print "#else"
>>  print "#include " quote "flags.h" quote
>>  print "#include " quote "target.h" quote
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts-common.c gcc-mainline/gcc/opts-common.c
>> --- gcc-mainline-opt2/gcc/opts-common.c 2010-06-21 10:02:42.000000000 -0700
>> +++ gcc-mainline/gcc/opts-common.c      2010-06-22 15:23:48.000000000 -0700
>> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.
>>  #include "coretypes.h"
>>  #include "opts.h"
>>  #include "options.h"
>> +#include "diagnostic.h"
>>
>>  /* Perform a binary search to find which option the command-line INPUT
>>    matches.  Returns its index in the option array, and
>> @@ -453,3 +454,135 @@ 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.  */
>> +
>> +bool
>> +handle_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];
>> +  size_t i;
>> +
>> +  if (option->flag_var)
>> +    set_option (opt_index, value, arg, kind);
>> +
>> +  for (i = 0; i < handlers->num_handlers; i++)
>> +    if (option->flags & handlers->handlers[i].mask)
>> +      {
>> +       if (!handlers->handlers[i].handler (opt_index, arg, value,
>> +                                           lang_mask, kind, handlers))
>> +         return false;
>> +       else
>> +         handlers->post_handling_callback (opt_index, arg, value,
>> +                                           handlers->handlers[i].mask);
>> +      }
>> +
>> +  return true;
>> +}
>> +
>> +/* Handle the switch DECODED for the language indicated by LANG_MASK,
>> +   using the handlers in *HANDLERS.  */
>> +
>> +void
>> +read_cmdline_option (struct cl_decoded_option *decoded,
>> +                    unsigned int lang_mask,
>> +                    const struct cl_option_handlers *handlers)
>> +{
>> +  const struct cl_option *option;
>> +  const char *opt;
>> +
>> +  if (decoded->opt_index == OPT_SPECIAL_unknown)
>> +    {
>> +      opt = decoded->arg;
>> +
>> +      if (handlers->unknown_option_callback (opt))
>> +       error ("unrecognized command line option %qs", opt);
>> +      return;
>> +    }
>> +
>> +  option = &cl_options[decoded->opt_index];
>> +  opt = decoded->orig_option_with_args_text;
>> +
>> +  if (decoded->errors & CL_ERR_DISABLED)
>> +    {
>> +      error ("command line option %qs"
>> +            " is not supported by this configuration", opt);
>> +      return;
>> +    }
>> +
>> +  if (decoded->errors & CL_ERR_WRONG_LANG)
>> +    {
>> +      handlers->wrong_lang_callback (opt, option, lang_mask);
>> +      return;
>> +    }
>> +
>> +  if (decoded->errors & CL_ERR_MISSING_ARG)
>> +    {
>> +      if (option->missing_argument_error)
>> +       error (option->missing_argument_error, opt);
>> +      else
>> +       error ("missing argument to %qs", opt);
>> +      return;
>> +    }
>> +
>> +  if (decoded->errors & CL_ERR_UINT_ARG)
>> +    {
>> +      error ("argument to %qs should be a non-negative integer",
>> +            option->opt_text);
>> +      return;
>> +    }
>> +
>> +  gcc_assert (!decoded->errors);
>> +
>> +  if (!handle_option (decoded->opt_index, decoded->arg, decoded->value,
>> +                     lang_mask, DK_UNSPECIFIED, handlers))
>> +    error ("unrecognized command line option %qs", opt);
>> +}
>> +
>> +/* Set any variable for option OPT_INDEX according to VALUE and ARG,
>> +   diagnostic kind KIND.  */
>> +
>> +void
>> +set_option (int opt_index, int value, const char *arg, int kind)
>> +{
>> +  const struct cl_option *option = &cl_options[opt_index];
>> +
>> +  if (!option->flag_var)
>> +    return;
>> +
>> +  switch (option->var_type)
>> +    {
>> +    case CLVC_BOOLEAN:
>> +       *(int *) option->flag_var = value;
>> +       break;
>> +
>> +    case CLVC_EQUAL:
>> +       *(int *) option->flag_var = (value
>> +                                    ? option->var_value
>> +                                    : !option->var_value);
>> +       break;
>> +
>> +    case CLVC_BIT_CLEAR:
>> +    case CLVC_BIT_SET:
>> +       if ((value != 0) == (option->var_type == CLVC_BIT_SET))
>> +         *(int *) option->flag_var |= option->var_value;
>> +       else
>> +         *(int *) option->flag_var &= ~option->var_value;
>> +       if (option->flag_var == &target_flags)
>> +         target_flags_explicit |= option->var_value;
>> +       break;
>> +
>> +    case CLVC_STRING:
>> +       *(const char **) option->flag_var = arg;
>> +       break;
>> +    }
>> +
>> +  if ((diagnostic_t) kind != DK_UNSPECIFIED)
>> +    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t) kind);
>> +}
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts.c gcc-mainline/gcc/opts.c
>> --- gcc-mainline-opt2/gcc/opts.c        2010-06-21 14:40:58.000000000 -0700
>> +++ gcc-mainline/gcc/opts.c     2010-06-22 15:22:33.000000000 -0700
>> @@ -372,8 +372,9 @@ bool flag_warn_unused_result = false;
>>  const char **in_fnames;
>>  unsigned num_in_fnames;
>>
>> -static int common_handle_option (size_t scode, const char *arg, int value,
>> -                                unsigned int lang_mask, int kind);
>> +static bool common_handle_option (size_t scode, const char *arg, int value,
>> +                                 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 *,
>> @@ -460,112 +461,58 @@ void print_ignored_options (void)
>>   input_location = saved_loc;
>>  }
>>
>> +/* Handle an unknown option ARG, returning true if an error should be
>> +   given.  */
>>
>> -/* Handle option OPT_INDEX, and argument ARG, for the language
>> -   indicated by LANG_MASK.  VALUE is true, unless no- form of an -f or
>> -   -W option was given.  KIND is the diagnostic_t if this is a
>> -   diagnostics option, DK_UNSPECIFIED otherwise.  Returns false if the
>> -   switch was invalid.  */
>> -bool
>> -handle_option (int opt_index, int value, const char *arg,
>> -               unsigned int lang_mask, int kind)
>> +static bool
>> +unknown_option_callback (const char *opt)
>>  {
>> -  const struct cl_option *option = &cl_options[opt_index];
>> -
>> -  if (option->flag_var)
>> -    set_option (opt_index, value, arg, kind);
>> -
>> -  if (option->flags & lang_mask)
>> +  if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
>>     {
>> -      if (lang_hooks.handle_option (opt_index, arg, value, kind) == 0)
>> -       return false;
>> -#ifdef ENABLE_LTO
>> -      else
>> -       lto_register_user_option (opt_index, arg, value, lang_mask);
>> - #endif
>> +      /* We don't generate warnings for unknown -Wno-* options unless
>> +        we issue diagnostics.  */
>> +      postpone_unknown_option_warning (opt);
>> +      return false;
>>     }
>> +  else
>> +    return true;
>> +}
>>
>> -  if (option->flags & CL_COMMON)
>> -    {
>> -      if (common_handle_option (opt_index, arg, value, lang_mask, kind) == 0)
>> -       return false;
>> -#ifdef ENABLE_LTO
>> -      else
>> -       lto_register_user_option (opt_index, arg, value, CL_COMMON);
>> -#endif
>> -    }
>> +/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
>> +   has been successfully handled with a handler for mask MASK.  */
>>
>> -  if (option->flags & CL_TARGET)
>> -    {
>> -      if (!targetm.handle_option (opt_index, arg, value))
>> -       return false;
>> +static void
>> +post_handling_callback (size_t opt_index ATTRIBUTE_UNUSED,
>> +                       const char *arg ATTRIBUTE_UNUSED,
>> +                       int value ATTRIBUTE_UNUSED,
>> +                       unsigned int mask ATTRIBUTE_UNUSED)
>> +{
>>  #ifdef ENABLE_LTO
>> -      else
>> -       lto_register_user_option (opt_index, arg, value, CL_TARGET);
>> +  lto_register_user_option (opt_index, arg, value, mask);
>>  #endif
>> -    }
>> -  return true;
>>  }
>>
>> -/* Handle the switch DECODED for the language indicated by
>> -   LANG_MASK.  */
>> -static void
>> -read_cmdline_option (struct cl_decoded_option *decoded,
>> -                    unsigned int lang_mask)
>> -{
>> -  const struct cl_option *option;
>> -  const char *opt;
>> -
>> -  if (decoded->opt_index == OPT_SPECIAL_unknown)
>> -    {
>> -      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 we issue diagnostics.  */
>> -         postpone_unknown_option_warning (opt);
>> -      else
>> -       error ("unrecognized command line option %qs", opt);
>> -      return;
>> -    }
>> -
>> -  option = &cl_options[decoded->opt_index];
>> -  opt = decoded->orig_option_with_args_text;
>> +/* Handle a front-end option; arguments and return value as for
>> +   handle_option.  */
>>
>> -  if (decoded->errors & CL_ERR_DISABLED)
>> -    {
>> -      error ("command line option %qs"
>> -            " is not supported by this configuration", opt);
>> -      return;
>> -    }
>> -
>> -  if (decoded->errors & CL_ERR_WRONG_LANG)
>> -    {
>> -      complain_wrong_lang (opt, option, lang_mask);
>> -      return;
>> -    }
>> -
>> -  if (decoded->errors & CL_ERR_MISSING_ARG)
>> -    {
>> -      if (option->missing_argument_error)
>> -       error (option->missing_argument_error, opt);
>> -      else
>> -       error ("missing argument to %qs", opt);
>> -      return;
>> -    }
>> -
>> -  if (decoded->errors & CL_ERR_UINT_ARG)
>> -    {
>> -      error ("argument to %qs should be a non-negative integer",
>> -            option->opt_text);
>> -      return;
>> -    }
>> +static bool
>> +lang_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)
>> +{
>> +  return lang_hooks.handle_option (opt_index, arg, value, kind, handlers);
>> +}
>>
>> -  gcc_assert (!decoded->errors);
>> +/* Handle a back-end option; arguments and return value as for
>> +   handle_option.  */
>>
>> -  if (!handle_option (decoded->opt_index, decoded->value, decoded->arg,
>> -                     lang_mask, DK_UNSPECIFIED))
>> -    error ("unrecognized command line option %qs", opt);
>> +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)
>> +{
>> +  gcc_assert (kind == DK_UNSPECIFIED);
>> +  return targetm.handle_option (opt_index, arg, value);
>>  }
>>
>>  /* Handle FILENAME from the command line.  */
>> @@ -659,11 +606,12 @@ flag_instrument_functions_exclude_p (tre
>>
>>  /* Handle the vector of command line options.  LANG_MASK
>>    contains has a single bit set representing the current
>> -   language.  */
>> +   language.  HANDLERS describes what functions to call for the options.  */
>>  static void
>>  read_cmdline_options (struct cl_decoded_option *decoded_options,
>>                      unsigned int decoded_options_count,
>> -                     unsigned int lang_mask)
>> +                     unsigned int lang_mask,
>> +                     const struct cl_option_handlers *handlers)
>>  {
>>   unsigned int i;
>>
>> @@ -681,7 +629,7 @@ read_cmdline_options (struct cl_decoded_
>>          continue;
>>        }
>>
>> -      read_cmdline_option (decoded_options + i, lang_mask);
>> +      read_cmdline_option (decoded_options + i, lang_mask, handlers);
>>     }
>>  }
>>
>> @@ -698,6 +646,7 @@ decode_options (unsigned int argc, const
>>   static int initial_max_fields_for_field_sensitive;
>>   static int initial_loop_invariant_max_bbs_in_loop;
>>   static unsigned int initial_lang_mask;
>> +  struct cl_option_handlers handlers;
>>
>>   unsigned int i, lang_mask;
>>   int opt1;
>> @@ -730,6 +679,17 @@ decode_options (unsigned int argc, const
>>     /* Perform language-specific options initialization.  */
>>     lang_hooks.init_options (*decoded_options_count, *decoded_options);
>>
>> +  handlers.unknown_option_callback = unknown_option_callback;
>> +  handlers.wrong_lang_callback = complain_wrong_lang;
>> +  handlers.post_handling_callback = post_handling_callback;
>> +  handlers.num_handlers = 3;
>> +  handlers.handlers[0].handler = lang_handle_option;
>> +  handlers.handlers[0].mask = lang_mask;
>> +  handlers.handlers[1].handler = common_handle_option;
>> +  handlers.handlers[1].mask = CL_COMMON;
>> +  handlers.handlers[2].handler = target_handle_option;
>> +  handlers.handlers[2].mask = CL_TARGET;
>> +
>>   /* Scan to see what optimization level has been specified.  That will
>>      determine the default value of many flags.  */
>>   for (i = 1; i < *decoded_options_count; i++)
>> @@ -903,7 +863,7 @@ decode_options (unsigned int argc, const
>>     }
>>
>>   /* Enable -Werror=coverage-mismatch by default */
>> -  enable_warning_as_error("coverage-mismatch", 1, lang_mask);
>> +  enable_warning_as_error ("coverage-mismatch", 1, lang_mask, &handlers);
>>
>>   if (first_time_p)
>>     {
>> @@ -931,7 +891,8 @@ decode_options (unsigned int argc, const
>>   OPTIMIZATION_OPTIONS (optimize, optimize_size);
>>  #endif
>>
>> -  read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask);
>> +  read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask,
>> +                       &handlers);
>>
>>   if (dump_base_name && ! IS_ABSOLUTE_PATH (dump_base_name))
>>     {
>> @@ -1425,9 +1386,10 @@ print_specific_help (unsigned int includ
>>    extra handling need to be listed here; if you simply want
>>    VALUE assigned to a variable, it happens automatically.  */
>>
>> -static int
>> +static bool
>>  common_handle_option (size_t scode, const char *arg, int value,
>> -                     unsigned int lang_mask, int kind ATTRIBUTE_UNUSED)
>> +                     unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
>> +                     const struct cl_option_handlers *handlers)
>>  {
>>   static bool verbose = false;
>>   enum opt_code code = (enum opt_code) scode;
>> @@ -1609,7 +1571,7 @@ common_handle_option (size_t scode, cons
>>       break;
>>
>>     case OPT_Werror_:
>> -      enable_warning_as_error (arg, value, lang_mask);
>> +      enable_warning_as_error (arg, value, lang_mask, handlers);
>>       break;
>>
>>     case OPT_Wlarger_than_:
>> @@ -1735,7 +1697,7 @@ common_handle_option (size_t scode, cons
>>        diagnostic_prefixing_rule (global_dc)
>>          = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
>>       else
>> -       return 0;
>> +       return false;
>>       break;
>>
>>     case OPT_fdiagnostics_show_option:
>> @@ -1744,7 +1706,7 @@ common_handle_option (size_t scode, cons
>>
>>     case OPT_fdump_:
>>       if (!dump_switch_p (arg))
>> -       return 0;
>> +       return false;
>>       break;
>>
>>     case OPT_fexcess_precision_:
>> @@ -1908,7 +1870,7 @@ common_handle_option (size_t scode, cons
>>     case OPT_frandom_seed:
>>       /* The real switch is -fno-random-seed.  */
>>       if (value)
>> -       return 0;
>> +       return false;
>>       set_random_seed (NULL);
>>       break;
>>
>> @@ -1926,7 +1888,7 @@ common_handle_option (size_t scode, cons
>>       fix_sched_param ("verbose", arg);
>>       break;
>>  #else
>> -      return 0;
>> +      return false;
>>  #endif
>>
>>     case OPT_fsched_stalled_insns_:
>> @@ -1973,7 +1935,7 @@ common_handle_option (size_t scode, cons
>>     case OPT_fstack_limit:
>>       /* The real switch is -fno-stack-limit.  */
>>       if (value)
>> -       return 0;
>> +       return false;
>>       stack_limit_rtx = NULL_RTX;
>>       break;
>>
>> @@ -2140,7 +2102,7 @@ common_handle_option (size_t scode, cons
>>       break;
>>     }
>>
>> -  return 1;
>> +  return true;
>>  }
>>
>>  /* Handle --param NAME=VALUE.  */
>> @@ -2355,48 +2317,6 @@ get_option_state (int option, struct cl_
>>   return true;
>>  }
>>
>> -/* Set *OPTION according to VALUE and ARG.  */
>> -
>> -void
>> -set_option (int opt_index, int value, const char *arg, int kind)
>> -{
>> -  const struct cl_option *option = &cl_options[opt_index];
>> -
>> -  if (!option->flag_var)
>> -    return;
>> -
>> -  switch (option->var_type)
>> -    {
>> -    case CLVC_BOOLEAN:
>> -       *(int *) option->flag_var = value;
>> -       break;
>> -
>> -    case CLVC_EQUAL:
>> -       *(int *) option->flag_var = (value
>> -                                    ? option->var_value
>> -                                    : !option->var_value);
>> -       break;
>> -
>> -    case CLVC_BIT_CLEAR:
>> -    case CLVC_BIT_SET:
>> -       if ((value != 0) == (option->var_type == CLVC_BIT_SET))
>> -         *(int *) option->flag_var |= option->var_value;
>> -       else
>> -         *(int *) option->flag_var &= ~option->var_value;
>> -       if (option->flag_var == &target_flags)
>> -         target_flags_explicit |= option->var_value;
>> -       break;
>> -
>> -    case CLVC_STRING:
>> -       *(const char **) option->flag_var = arg;
>> -       break;
>> -    }
>> -
>> -  if ((diagnostic_t)kind != DK_UNSPECIFIED)
>> -    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t)kind);
>> -}
>> -
>> -
>>  /* Callback function, called when -Werror= enables a warning.  */
>>
>>  static void (*warning_as_error_callback) (int) = NULL;
>> @@ -2414,7 +2334,8 @@ register_warning_as_error_callback (void
>>    also by legacy Werror-implicit-function-declaration.  */
>>
>>  void
>> -enable_warning_as_error (const char *arg, int value, unsigned int lang_mask)
>> +enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
>> +                        const struct cl_option_handlers *handlers)
>>  {
>>   char *new_option;
>>   int option_index;
>> @@ -2438,7 +2359,8 @@ enable_warning_as_error (const char *arg
>>
>>          /* -Werror=foo implies -Wfoo.  */
>>          if (option->var_type == CLVC_BOOLEAN)
>> -           handle_option (option_index, value, arg, lang_mask, (int)kind);
>> +           handle_option (option_index, arg, value, lang_mask, (int)kind,
>> +                          handlers);
>>
>>          if (warning_as_error_callback)
>>            warning_as_error_callback (option_index);
>> diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts.h gcc-mainline/gcc/opts.h
>> --- gcc-mainline-opt2/gcc/opts.h        2010-06-21 15:24:55.000000000 -0700
>> +++ gcc-mainline/gcc/opts.h     2010-06-22 15:15:44.000000000 -0700
>> @@ -135,6 +135,47 @@ struct cl_decoded_option
>>   int errors;
>>  };
>>
>> +/* Structure describing a single option-handling callback.  */
>> +
>> +struct cl_option_handler_func
>> +{
>> +  /* The function called to handle the option.  */
>> +  bool (*handler) (size_t opt_index, const char *arg, int value,
>> +                  unsigned int lang_mask, int kind,
>> +                  const struct cl_option_handlers *handlers);
>> +
>> +  /* The mask that must have some bit in common with the flags for the
>> +     option for this particular handler to be used.  */
>> +  unsigned int mask;
>> +};
>> +
>> +/* Structure describing the callbacks used in handling options.  */
>> +
>> +struct cl_option_handlers
>> +{
>> +  /* Callback for an unknown option to determine whether to give an
>> +     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);
>> +
>> +  /* Callback to handle, and possibly diagnose, an option for another
>> +     language.  */
>> +  void (*wrong_lang_callback) (const char *text,
>> +                              const struct cl_option *option,
>> +                              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);
>> +
>> +  /* The number of individual handlers.  */
>> +  size_t num_handlers;
>> +
>> +  /* The handlers themselves.  */
>> +  struct cl_option_handler_func handlers[3];
>> +};
>> +
>>  /* Input file names.  */
>>
>>  extern const char **in_fnames;
>> @@ -157,10 +198,15 @@ 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 (int opt_index, int value, const char *arg,
>> -                   unsigned int lang_mask, int kind);
>> +bool handle_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);
>>  extern void register_warning_as_error_callback (void (*callback) (int));
>>  extern void enable_warning_as_error (const char *arg, int value,
>> -                                    unsigned int lang_mask);
>> +                                    unsigned int lang_mask,
>> +                                    const struct cl_option_handlers *handlers);
>>  extern void print_ignored_options (void);
>>  #endif
>>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com
>>
>

Patch

diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/Makefile.in gcc-mainline/gcc/Makefile.in
--- gcc-mainline-opt2/gcc/Makefile.in	2010-06-21 09:57:36.000000000 -0700
+++ gcc-mainline/gcc/Makefile.in	2010-06-22 15:24:00.000000000 -0700
@@ -2796,7 +2796,7 @@  opts.o : opts.c opts.h options.h $(TOPLE
    $(FLAGS_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H) debug.h \
    $(PLUGIN_H) $(EXCEPT_H) $(LTO_STREAMER_H) opts-diagnostic.h
 opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
-   coretypes.h intl.h
+   coretypes.h intl.h $(DIAGNOSTIC_H)
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
    $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
    $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h \
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/ada/gcc-interface/misc.c gcc-mainline/gcc/ada/gcc-interface/misc.c
--- gcc-mainline-opt2/gcc/ada/gcc-interface/misc.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/ada/gcc-interface/misc.c	2010-06-22 16:02:04.000000000 -0700
@@ -65,7 +65,8 @@  static bool gnat_init			(void);
 static unsigned int gnat_option_lang_mask (void);
 static void gnat_init_options		(unsigned int,
 					 struct cl_decoded_option *);
-static int gnat_handle_option		(size_t, const char *, int, int);
+static bool gnat_handle_option		(size_t, const char *, int, int,
+					 const struct cl_option_handlers *);
 static bool gnat_post_options		(const char **);
 static alias_set_type gnat_get_alias_set (tree);
 static void gnat_print_decl		(FILE *, tree, int);
@@ -187,23 +188,16 @@  gnat_parse_file (int set_yydebug ATTRIBU
 
 /* Decode all the language specific options that cannot be decoded by GCC.
    The option decoding phase of GCC calls this routine on the flags that
-   it cannot decode.  Return the number of consecutive arguments from ARGV
-   that have been successfully decoded or 0 on failure.  */
+   are marked as Ada-specific.  Return true on success or false on failure.  */
 
-static int
+static bool
 gnat_handle_option (size_t scode, const char *arg, int value,
-		    int kind ATTRIBUTE_UNUSED)
+		    int kind ATTRIBUTE_UNUSED,
+		    const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
-  const struct cl_option *option = &cl_options[scode];
   enum opt_code code = (enum opt_code) scode;
   char *q;
 
-  if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
-    {
-      error ("missing argument to \"-%s\"", option->opt_text);
-      return 1;
-    }
-
   switch (code)
     {
     case OPT_I:
@@ -280,7 +274,7 @@  gnat_handle_option (size_t scode, const 
       gcc_unreachable ();
     }
 
-  return 1;
+  return true;
 }
 
 /* Return language mask for option processing.  */
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/c-family/c-common.h gcc-mainline/gcc/c-family/c-common.h
--- gcc-mainline-opt2/gcc/c-family/c-common.h	2010-06-21 14:38:50.000000000 -0700
+++ gcc-mainline/gcc/c-family/c-common.h	2010-06-22 15:08:11.000000000 -0700
@@ -652,7 +652,8 @@  extern void set_Wformat (int);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
 extern bool attribute_takes_identifier_p (const_tree);
-extern int c_common_handle_option (size_t code, const char *arg, int value, int kind);
+extern bool c_common_handle_option (size_t, const char *, int, int,
+				    const struct cl_option_handlers *);
 extern tree c_common_type_for_mode (enum machine_mode, int);
 extern tree c_common_type_for_size (unsigned int, int);
 extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/c-family/c-opts.c gcc-mainline/gcc/c-family/c-opts.c
--- gcc-mainline-opt2/gcc/c-family/c-opts.c	2010-06-21 14:53:58.000000000 -0700
+++ gcc-mainline/gcc/c-family/c-opts.c	2010-06-22 15:08:05.000000000 -0700
@@ -319,16 +319,15 @@  c_common_init_options (unsigned int deco
 }
 
 /* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
-   form of an -f or -W option was given.  Returns 0 if the switch was
-   invalid, a negative number to prevent language-independent
-   processing in toplev.c (a hack necessary for the short-term).  */
-int
+   form of an -f or -W option was given.  Returns false if the switch was
+   invalid, true if valid.  Use HANDLERS in recursive handle_option calls.  */
+bool
 c_common_handle_option (size_t scode, const char *arg, int value,
-			int kind)
+			int kind, const struct cl_option_handlers *handlers)
 {
   const struct cl_option *option = &cl_options[scode];
   enum opt_code code = (enum opt_code) scode;
-  int result = 1;
+  bool result = true;
 
   /* Prevent resetting the language standard to a C dialect when the driver
      has already determined that we're looking at assembler input.  */
@@ -341,10 +340,10 @@  c_common_handle_option (size_t scode, co
 	{
 	  if ((option->flags & CL_TARGET)
 	      && ! targetcm.handle_c_option (scode, arg, value))
-	    result = 0;
+	    result = false;
 	  break;
 	}
-      result = 0;
+      result = false;
       break;
 
     case OPT__output_pch_:
@@ -438,7 +437,8 @@  c_common_handle_option (size_t scode, co
     case OPT_Wall:
       warn_unused = value;
       set_Wformat (value);
-      handle_option (OPT_Wimplicit, value, NULL, c_family_lang_mask, kind);
+      handle_option (OPT_Wimplicit, NULL, value, c_family_lang_mask, kind,
+		     handlers);
       warn_char_subscripts = value;
       warn_missing_braces = value;
       warn_parentheses = value;
@@ -524,7 +524,8 @@  c_common_handle_option (size_t scode, co
     case OPT_Werror_implicit_function_declaration:
       /* For backward compatibility, this is the same as
 	 -Werror=implicit-function-declaration.  */
-      enable_warning_as_error ("implicit-function-declaration", value, CL_C | CL_ObjC);
+      enable_warning_as_error ("implicit-function-declaration", value,
+			       CL_C | CL_ObjC, handlers);
       break;
 
     case OPT_Wformat:
@@ -538,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, value, NULL,
-		       c_family_lang_mask, kind);
+	handle_option (OPT_Wimplicit_int, NULL, value,
+		       c_family_lang_mask, kind, handlers);
       if (warn_implicit_function_declaration == -1)
-	handle_option (OPT_Wimplicit_function_declaration, value, NULL,
-		       c_family_lang_mask, kind);
+	handle_option (OPT_Wimplicit_function_declaration, NULL, value,
+		       c_family_lang_mask, kind, handlers);
       break;
 
     case OPT_Wimport:
@@ -655,7 +656,7 @@  c_common_handle_option (size_t scode, co
 
     case OPT_fbuiltin_:
       if (value)
-	result = 0;
+	result = false;
       else
 	disable_builtin_function (arg);
       break;
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/coretypes.h gcc-mainline/gcc/coretypes.h
--- gcc-mainline-opt2/gcc/coretypes.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/coretypes.h	2010-06-22 14:34:22.000000000 -0700
@@ -68,6 +68,7 @@  struct cl_target_option;
 struct cl_optimization;
 struct cl_option;
 struct cl_decoded_option;
+struct cl_option_handlers;
 struct gimple_seq_d;
 typedef struct gimple_seq_d *gimple_seq;
 typedef const struct gimple_seq_d *const_gimple_seq;
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/fortran/gfortran.h gcc-mainline/gcc/fortran/gfortran.h
--- gcc-mainline-opt2/gcc/fortran/gfortran.h	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/fortran/gfortran.h	2010-06-22 15:08:23.000000000 -0700
@@ -2346,7 +2346,8 @@  int get_c_kind (const char *, CInteropKi
 unsigned int gfc_option_lang_mask (void);
 void gfc_init_options (unsigned int,
 		       struct cl_decoded_option *);
-int gfc_handle_option (size_t, const char *, int, int);
+bool gfc_handle_option (size_t, const char *, int, int,
+			const struct cl_option_handlers *);
 bool gfc_post_options (const char **);
 
 /* f95-lang.c */
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/fortran/options.c gcc-mainline/gcc/fortran/options.c
--- gcc-mainline-opt2/gcc/fortran/options.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/fortran/options.c	2010-06-22 15:08:27.000000000 -0700
@@ -542,20 +542,21 @@  gfc_handle_runtime_check_option (const c
 /* Handle command-line options.  Returns 0 if unrecognized, 1 if
    recognized and handled.  */
 
-int
+bool
 gfc_handle_option (size_t scode, const char *arg, int value,
-		   int kind ATTRIBUTE_UNUSED)
+		   int kind ATTRIBUTE_UNUSED,
+		   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
-  int result = 1;
+  bool result = true;
   enum opt_code code = (enum opt_code) scode;
 
   if (gfc_cpp_handle_option (scode, arg, value) == 1)
-    return 1;
+    return true;
 
   switch (code)
     {
     default:
-      result = 0;
+      result = false;
       break;
 
     case OPT_Wall:
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/hooks.c gcc-mainline/gcc/hooks.c
--- gcc-mainline-opt2/gcc/hooks.c	2010-06-21 14:38:03.000000000 -0700
+++ gcc-mainline/gcc/hooks.c	2010-06-22 14:31:06.000000000 -0700
@@ -160,14 +160,6 @@  hook_int_rtx_bool_0 (rtx a ATTRIBUTE_UNU
   return 0;
 }
 
-int
-hook_int_size_t_constcharptr_int_0 (size_t a ATTRIBUTE_UNUSED,
-				    const char *b ATTRIBUTE_UNUSED,
-				    int c ATTRIBUTE_UNUSED)
-{
-  return 0;
-}
-
 unsigned int
 hook_uint_void_0 (void)
 {
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/hooks.h gcc-mainline/gcc/hooks.h
--- gcc-mainline-opt2/gcc/hooks.h	2010-06-21 14:38:18.000000000 -0700
+++ gcc-mainline/gcc/hooks.h	2010-06-22 14:31:17.000000000 -0700
@@ -63,7 +63,6 @@  extern int hook_int_const_tree_0 (const_
 extern int hook_int_const_tree_const_tree_1 (const_tree, const_tree);
 extern int hook_int_rtx_0 (rtx);
 extern int hook_int_rtx_bool_0 (rtx, bool);
-extern int hook_int_size_t_constcharptr_int_0 (size_t, const char *, int);
 
 extern tree hook_tree_const_tree_null (const_tree);
 
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/java/lang.c gcc-mainline/gcc/java/lang.c
--- gcc-mainline-opt2/gcc/java/lang.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/java/lang.c	2010-06-22 15:08:40.000000000 -0700
@@ -51,7 +51,8 @@  static unsigned int java_option_lang_mas
 static void java_init_options (unsigned int, struct cl_decoded_option *);
 static bool java_post_options (const char **);
 
-static int java_handle_option (size_t scode, const char *arg, int value, int kind);
+static bool java_handle_option (size_t, const char *, int, int,
+				const struct cl_option_handlers *);
 static void put_decl_string (const char *, int);
 static void put_decl_node (tree, int);
 static void java_print_error_function (diagnostic_context *, const char *,
@@ -175,11 +176,12 @@  struct lang_hooks lang_hooks = LANG_HOOK
 
 /*
  * process java-specific compiler command-line options
- * return 0, but do not complain if the option is not recognized.
+ * return false, but do not complain if the option is not recognized.
  */
-static int
+static bool
 java_handle_option (size_t scode, const char *arg, int value,
-		    int kind ATTRIBUTE_UNUSED)
+		    int kind ATTRIBUTE_UNUSED,
+		    const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
   enum opt_code code = (enum opt_code) scode;
 
@@ -270,7 +272,7 @@  java_handle_option (size_t scode, const 
 
     case OPT_fdump_:
       if (!dump_switch_p (arg))
-	return 0;
+	return false;
       break;
 
     case OPT_fencoding_:
@@ -299,7 +301,7 @@  java_handle_option (size_t scode, const 
       gcc_unreachable ();
     }
 
-  return 1;
+  return true;
 }
 
 /* Global open file.  */
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks-def.h gcc-mainline/gcc/langhooks-def.h
--- gcc-mainline-opt2/gcc/langhooks-def.h	2010-06-21 14:39:18.000000000 -0700
+++ gcc-mainline/gcc/langhooks-def.h	2010-06-22 15:13:56.000000000 -0700
@@ -69,6 +69,8 @@  extern void lhd_initialize_diagnostics (
 extern void lhd_init_options (unsigned int,
 			      struct cl_decoded_option *);
 extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
+extern bool lhd_handle_option (size_t, const char *, int, int,
+			       const struct cl_option_handlers *);
 extern tree lhd_callgraph_analyze_expr (tree *, int *);
 
 
@@ -89,7 +91,7 @@  extern void lhd_omp_firstprivatize_type_
 #define LANG_HOOKS_INIT_OPTIONS		lhd_init_options
 #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
 #define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
-#define LANG_HOOKS_HANDLE_OPTION	hook_int_size_t_constcharptr_int_0
+#define LANG_HOOKS_HANDLE_OPTION	lhd_handle_option
 #define LANG_HOOKS_POST_OPTIONS		lhd_post_options
 #define LANG_HOOKS_MISSING_NORETURN_OK_P hook_bool_tree_true
 #define LANG_HOOKS_GET_ALIAS_SET	lhd_get_alias_set
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks.c gcc-mainline/gcc/langhooks.c
--- gcc-mainline-opt2/gcc/langhooks.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/langhooks.c	2010-06-22 15:08:49.000000000 -0700
@@ -351,6 +351,16 @@  lhd_complain_wrong_lang_p (const struct 
   return true;
 }
 
+/* By default, no language-specific options are valid.  */
+bool
+lhd_handle_option (size_t code ATTRIBUTE_UNUSED,
+		   const char *arg ATTRIBUTE_UNUSED,
+		   int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+		   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
 /* The default function to print out name of current function that caused
    an error.  */
 void
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/langhooks.h gcc-mainline/gcc/langhooks.h
--- gcc-mainline-opt2/gcc/langhooks.h	2010-06-21 14:39:04.000000000 -0700
+++ gcc-mainline/gcc/langhooks.h	2010-06-22 15:08:54.000000000 -0700
@@ -292,11 +292,12 @@  struct lang_hooks
      which points to permanent storage.  The handler is responsible for
      checking whether ARG is NULL, which indicates that no argument
      was in fact supplied.  For -f and -W switches, VALUE is 1 or 0
-     for the positive and negative forms respectively.
+     for the positive and negative forms respectively.  HANDLERS should
+     be passed to any recursive handle_option calls.
 
-     Return 1 if the switch is valid, 0 if invalid, and -1 if it's
-     valid and should not be treated as language-independent too.  */
-  int (*handle_option) (size_t code, const char *arg, int value, int kind);
+     Return true if the switch is valid, false if invalid.  */
+  bool (*handle_option) (size_t code, const char *arg, int value, int kind,
+			 const struct cl_option_handlers *handlers);
 
   /* Called when all command line options have been parsed to allow
      further processing and initialization
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/lto/lto-lang.c gcc-mainline/gcc/lto/lto-lang.c
--- gcc-mainline-opt2/gcc/lto/lto-lang.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/lto/lto-lang.c	2010-06-22 15:09:02.000000000 -0700
@@ -630,18 +630,18 @@  lto_init_options (unsigned int decoded_o
    of the option was supplied.  */
 
 const char *resolution_file_name;
-static int
+static bool
 lto_handle_option (size_t scode, const char *arg,
-		   int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED)
+		   int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+		   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
   enum opt_code code = (enum opt_code) scode;
-  int result = 1;
+  bool result = true;
 
   switch (code)
     {
     case OPT_fresolution_:
       resolution_file_name = arg;
-      result = 1;
       break;
 
     case OPT_Wabi:
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/optc-gen.awk gcc-mainline/gcc/optc-gen.awk
--- gcc-mainline-opt2/gcc/optc-gen.awk	2010-06-21 14:56:03.000000000 -0700
+++ gcc-mainline/gcc/optc-gen.awk	2010-06-22 15:25:22.000000000 -0700
@@ -73,6 +73,7 @@  print "#include " quote "intl.h" quote
 print ""
 print "#ifdef GCC_DRIVER"
 print "int target_flags;"
+print "int target_flags_explicit;"
 print "#else"
 print "#include " quote "flags.h" quote
 print "#include " quote "target.h" quote
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts-common.c gcc-mainline/gcc/opts-common.c
--- gcc-mainline-opt2/gcc/opts-common.c	2010-06-21 10:02:42.000000000 -0700
+++ gcc-mainline/gcc/opts-common.c	2010-06-22 15:23:48.000000000 -0700
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  
 #include "coretypes.h"
 #include "opts.h"
 #include "options.h"
+#include "diagnostic.h"
 
 /* Perform a binary search to find which option the command-line INPUT
    matches.  Returns its index in the option array, and
@@ -453,3 +454,135 @@  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.  */
+
+bool
+handle_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];
+  size_t i;
+
+  if (option->flag_var)
+    set_option (opt_index, value, arg, kind);
+
+  for (i = 0; i < handlers->num_handlers; i++)
+    if (option->flags & handlers->handlers[i].mask)
+      {
+	if (!handlers->handlers[i].handler (opt_index, arg, value,
+					    lang_mask, kind, handlers))
+	  return false;
+	else
+	  handlers->post_handling_callback (opt_index, arg, value,
+					    handlers->handlers[i].mask);
+      }
+  
+  return true;
+}
+
+/* Handle the switch DECODED for the language indicated by LANG_MASK,
+   using the handlers in *HANDLERS.  */
+
+void
+read_cmdline_option (struct cl_decoded_option *decoded,
+		     unsigned int lang_mask,
+		     const struct cl_option_handlers *handlers)
+{
+  const struct cl_option *option;
+  const char *opt;
+
+  if (decoded->opt_index == OPT_SPECIAL_unknown)
+    {
+      opt = decoded->arg;
+
+      if (handlers->unknown_option_callback (opt))
+	error ("unrecognized command line option %qs", opt);
+      return;
+    }
+
+  option = &cl_options[decoded->opt_index];
+  opt = decoded->orig_option_with_args_text;
+
+  if (decoded->errors & CL_ERR_DISABLED)
+    {
+      error ("command line option %qs"
+	     " is not supported by this configuration", opt);
+      return;
+    }
+
+  if (decoded->errors & CL_ERR_WRONG_LANG)
+    {
+      handlers->wrong_lang_callback (opt, option, lang_mask);
+      return;
+    }
+
+  if (decoded->errors & CL_ERR_MISSING_ARG)
+    {
+      if (option->missing_argument_error)
+	error (option->missing_argument_error, opt);
+      else
+	error ("missing argument to %qs", opt);
+      return;
+    }
+
+  if (decoded->errors & CL_ERR_UINT_ARG)
+    {
+      error ("argument to %qs should be a non-negative integer",
+	     option->opt_text);
+      return;
+    }
+
+  gcc_assert (!decoded->errors);
+
+  if (!handle_option (decoded->opt_index, decoded->arg, decoded->value,
+		      lang_mask, DK_UNSPECIFIED, handlers))
+    error ("unrecognized command line option %qs", opt);
+}
+
+/* Set any variable for option OPT_INDEX according to VALUE and ARG,
+   diagnostic kind KIND.  */
+
+void
+set_option (int opt_index, int value, const char *arg, int kind)
+{
+  const struct cl_option *option = &cl_options[opt_index];
+
+  if (!option->flag_var)
+    return;
+
+  switch (option->var_type)
+    {
+    case CLVC_BOOLEAN:
+	*(int *) option->flag_var = value;
+	break;
+
+    case CLVC_EQUAL:
+	*(int *) option->flag_var = (value
+				     ? option->var_value
+				     : !option->var_value);
+	break;
+
+    case CLVC_BIT_CLEAR:
+    case CLVC_BIT_SET:
+	if ((value != 0) == (option->var_type == CLVC_BIT_SET))
+	  *(int *) option->flag_var |= option->var_value;
+	else
+	  *(int *) option->flag_var &= ~option->var_value;
+	if (option->flag_var == &target_flags)
+	  target_flags_explicit |= option->var_value;
+	break;
+
+    case CLVC_STRING:
+	*(const char **) option->flag_var = arg;
+	break;
+    }
+
+  if ((diagnostic_t) kind != DK_UNSPECIFIED)
+    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t) kind);
+}
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts.c gcc-mainline/gcc/opts.c
--- gcc-mainline-opt2/gcc/opts.c	2010-06-21 14:40:58.000000000 -0700
+++ gcc-mainline/gcc/opts.c	2010-06-22 15:22:33.000000000 -0700
@@ -372,8 +372,9 @@  bool flag_warn_unused_result = false;
 const char **in_fnames;
 unsigned num_in_fnames;
 
-static int common_handle_option (size_t scode, const char *arg, int value,
-				 unsigned int lang_mask, int kind);
+static bool common_handle_option (size_t scode, const char *arg, int value,
+				  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 *,
@@ -460,112 +461,58 @@  void print_ignored_options (void)
   input_location = saved_loc;
 }
 
+/* Handle an unknown option ARG, returning true if an error should be
+   given.  */
 
-/* Handle option OPT_INDEX, and argument ARG, for the language
-   indicated by LANG_MASK.  VALUE is true, unless no- form of an -f or
-   -W option was given.  KIND is the diagnostic_t if this is a
-   diagnostics option, DK_UNSPECIFIED otherwise.  Returns false if the
-   switch was invalid.  */
-bool
-handle_option (int opt_index, int value, const char *arg,
-		unsigned int lang_mask, int kind)
+static bool
+unknown_option_callback (const char *opt)
 {
-  const struct cl_option *option = &cl_options[opt_index];
-
-  if (option->flag_var)
-    set_option (opt_index, value, arg, kind);
-  
-  if (option->flags & lang_mask)
+  if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
     {
-      if (lang_hooks.handle_option (opt_index, arg, value, kind) == 0)
-	return false;
-#ifdef ENABLE_LTO
-      else
-	lto_register_user_option (opt_index, arg, value, lang_mask);
- #endif
+      /* We don't generate warnings for unknown -Wno-* options unless
+	 we issue diagnostics.  */
+      postpone_unknown_option_warning (opt);
+      return false;
     }
+  else
+    return true;
+}
 
-  if (option->flags & CL_COMMON)
-    {
-      if (common_handle_option (opt_index, arg, value, lang_mask, kind) == 0)
-	return false;
-#ifdef ENABLE_LTO
-      else
-	lto_register_user_option (opt_index, arg, value, CL_COMMON);
-#endif
-    }
+/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
+   has been successfully handled with a handler for mask MASK.  */
 
-  if (option->flags & CL_TARGET)
-    {
-      if (!targetm.handle_option (opt_index, arg, value))
-	return false;
+static void
+post_handling_callback (size_t opt_index ATTRIBUTE_UNUSED,
+			const char *arg ATTRIBUTE_UNUSED,
+			int value ATTRIBUTE_UNUSED,
+			unsigned int mask ATTRIBUTE_UNUSED)
+{
 #ifdef ENABLE_LTO
-      else
-	lto_register_user_option (opt_index, arg, value, CL_TARGET);
+  lto_register_user_option (opt_index, arg, value, mask);
 #endif
-    }
-  return true;
 }
 
-/* Handle the switch DECODED for the language indicated by
-   LANG_MASK.  */
-static void
-read_cmdline_option (struct cl_decoded_option *decoded,
-		     unsigned int lang_mask)
-{
-  const struct cl_option *option;
-  const char *opt;
-
-  if (decoded->opt_index == OPT_SPECIAL_unknown)
-    {
-      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 we issue diagnostics.  */
-	  postpone_unknown_option_warning (opt);
-      else
-	error ("unrecognized command line option %qs", opt);
-      return;
-    }
-
-  option = &cl_options[decoded->opt_index];
-  opt = decoded->orig_option_with_args_text;
+/* Handle a front-end option; arguments and return value as for
+   handle_option.  */
 
-  if (decoded->errors & CL_ERR_DISABLED)
-    {
-      error ("command line option %qs"
-	     " is not supported by this configuration", opt);
-      return;
-    }
-
-  if (decoded->errors & CL_ERR_WRONG_LANG)
-    {
-      complain_wrong_lang (opt, option, lang_mask);
-      return;
-    }
-
-  if (decoded->errors & CL_ERR_MISSING_ARG)
-    {
-      if (option->missing_argument_error)
-	error (option->missing_argument_error, opt);
-      else
-	error ("missing argument to %qs", opt);
-      return;
-    }
-
-  if (decoded->errors & CL_ERR_UINT_ARG)
-    {
-      error ("argument to %qs should be a non-negative integer",
-	     option->opt_text);
-      return;
-    }
+static bool
+lang_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)
+{
+  return lang_hooks.handle_option (opt_index, arg, value, kind, handlers);
+}
 
-  gcc_assert (!decoded->errors);
+/* Handle a back-end option; arguments and return value as for
+   handle_option.  */
 
-  if (!handle_option (decoded->opt_index, decoded->value, decoded->arg,
-		      lang_mask, DK_UNSPECIFIED))
-    error ("unrecognized command line option %qs", opt);
+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)
+{
+  gcc_assert (kind == DK_UNSPECIFIED);
+  return targetm.handle_option (opt_index, arg, value);
 }
 
 /* Handle FILENAME from the command line.  */
@@ -659,11 +606,12 @@  flag_instrument_functions_exclude_p (tre
 
 /* Handle the vector of command line options.  LANG_MASK
    contains has a single bit set representing the current
-   language.  */
+   language.  HANDLERS describes what functions to call for the options.  */
 static void
 read_cmdline_options (struct cl_decoded_option *decoded_options,
 		      unsigned int decoded_options_count,
-		      unsigned int lang_mask)
+		      unsigned int lang_mask,
+		      const struct cl_option_handlers *handlers)
 {
   unsigned int i;
 
@@ -681,7 +629,7 @@  read_cmdline_options (struct cl_decoded_
 	  continue;
 	}
 
-      read_cmdline_option (decoded_options + i, lang_mask);
+      read_cmdline_option (decoded_options + i, lang_mask, handlers);
     }
 }
 
@@ -698,6 +646,7 @@  decode_options (unsigned int argc, const
   static int initial_max_fields_for_field_sensitive;
   static int initial_loop_invariant_max_bbs_in_loop;
   static unsigned int initial_lang_mask;
+  struct cl_option_handlers handlers;
 
   unsigned int i, lang_mask;
   int opt1;
@@ -730,6 +679,17 @@  decode_options (unsigned int argc, const
     /* Perform language-specific options initialization.  */
     lang_hooks.init_options (*decoded_options_count, *decoded_options);
 
+  handlers.unknown_option_callback = unknown_option_callback;
+  handlers.wrong_lang_callback = complain_wrong_lang;
+  handlers.post_handling_callback = post_handling_callback;
+  handlers.num_handlers = 3;
+  handlers.handlers[0].handler = lang_handle_option;
+  handlers.handlers[0].mask = lang_mask;
+  handlers.handlers[1].handler = common_handle_option;
+  handlers.handlers[1].mask = CL_COMMON;
+  handlers.handlers[2].handler = target_handle_option;
+  handlers.handlers[2].mask = CL_TARGET;
+
   /* Scan to see what optimization level has been specified.  That will
      determine the default value of many flags.  */
   for (i = 1; i < *decoded_options_count; i++)
@@ -903,7 +863,7 @@  decode_options (unsigned int argc, const
     }
 
   /* Enable -Werror=coverage-mismatch by default */
-  enable_warning_as_error("coverage-mismatch", 1, lang_mask);
+  enable_warning_as_error ("coverage-mismatch", 1, lang_mask, &handlers);
 
   if (first_time_p)
     {
@@ -931,7 +891,8 @@  decode_options (unsigned int argc, const
   OPTIMIZATION_OPTIONS (optimize, optimize_size);
 #endif
 
-  read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask);
+  read_cmdline_options (*decoded_options, *decoded_options_count, lang_mask,
+			&handlers);
 
   if (dump_base_name && ! IS_ABSOLUTE_PATH (dump_base_name))
     {
@@ -1425,9 +1386,10 @@  print_specific_help (unsigned int includ
    extra handling need to be listed here; if you simply want
    VALUE assigned to a variable, it happens automatically.  */
 
-static int
+static bool
 common_handle_option (size_t scode, const char *arg, int value,
-		      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED)
+		      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
+		      const struct cl_option_handlers *handlers)
 {
   static bool verbose = false;
   enum opt_code code = (enum opt_code) scode;
@@ -1609,7 +1571,7 @@  common_handle_option (size_t scode, cons
       break;
 
     case OPT_Werror_:
-      enable_warning_as_error (arg, value, lang_mask);
+      enable_warning_as_error (arg, value, lang_mask, handlers);
       break;
 
     case OPT_Wlarger_than_:
@@ -1735,7 +1697,7 @@  common_handle_option (size_t scode, cons
 	diagnostic_prefixing_rule (global_dc)
 	  = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
       else
-	return 0;
+	return false;
       break;
 
     case OPT_fdiagnostics_show_option:
@@ -1744,7 +1706,7 @@  common_handle_option (size_t scode, cons
 
     case OPT_fdump_:
       if (!dump_switch_p (arg))
-	return 0;
+	return false;
       break;
 
     case OPT_fexcess_precision_:
@@ -1908,7 +1870,7 @@  common_handle_option (size_t scode, cons
     case OPT_frandom_seed:
       /* The real switch is -fno-random-seed.  */
       if (value)
-	return 0;
+	return false;
       set_random_seed (NULL);
       break;
 
@@ -1926,7 +1888,7 @@  common_handle_option (size_t scode, cons
       fix_sched_param ("verbose", arg);
       break;
 #else
-      return 0;
+      return false;
 #endif
 
     case OPT_fsched_stalled_insns_:
@@ -1973,7 +1935,7 @@  common_handle_option (size_t scode, cons
     case OPT_fstack_limit:
       /* The real switch is -fno-stack-limit.  */
       if (value)
-	return 0;
+	return false;
       stack_limit_rtx = NULL_RTX;
       break;
 
@@ -2140,7 +2102,7 @@  common_handle_option (size_t scode, cons
       break;
     }
 
-  return 1;
+  return true;
 }
 
 /* Handle --param NAME=VALUE.  */
@@ -2355,48 +2317,6 @@  get_option_state (int option, struct cl_
   return true;
 }
 
-/* Set *OPTION according to VALUE and ARG.  */
-
-void
-set_option (int opt_index, int value, const char *arg, int kind)
-{
-  const struct cl_option *option = &cl_options[opt_index];
-
-  if (!option->flag_var)
-    return;
-
-  switch (option->var_type)
-    {
-    case CLVC_BOOLEAN:
-	*(int *) option->flag_var = value;
-	break;
-
-    case CLVC_EQUAL:
-	*(int *) option->flag_var = (value
-				     ? option->var_value
-				     : !option->var_value);
-	break;
-
-    case CLVC_BIT_CLEAR:
-    case CLVC_BIT_SET:
-	if ((value != 0) == (option->var_type == CLVC_BIT_SET))
-	  *(int *) option->flag_var |= option->var_value;
-	else
-	  *(int *) option->flag_var &= ~option->var_value;
-	if (option->flag_var == &target_flags)
-	  target_flags_explicit |= option->var_value;
-	break;
-
-    case CLVC_STRING:
-	*(const char **) option->flag_var = arg;
-	break;
-    }
-
-  if ((diagnostic_t)kind != DK_UNSPECIFIED)
-    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t)kind);
-}
-
-
 /* Callback function, called when -Werror= enables a warning.  */
 
 static void (*warning_as_error_callback) (int) = NULL;
@@ -2414,7 +2334,8 @@  register_warning_as_error_callback (void
    also by legacy Werror-implicit-function-declaration.  */
 
 void
-enable_warning_as_error (const char *arg, int value, unsigned int lang_mask)
+enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
+			 const struct cl_option_handlers *handlers)
 {
   char *new_option;
   int option_index;
@@ -2438,7 +2359,8 @@  enable_warning_as_error (const char *arg
 
 	  /* -Werror=foo implies -Wfoo.  */
 	  if (option->var_type == CLVC_BOOLEAN)
-	    handle_option (option_index, value, arg, lang_mask, (int)kind);
+	    handle_option (option_index, arg, value, lang_mask, (int)kind,
+			   handlers);
 
 	  if (warning_as_error_callback)
 	    warning_as_error_callback (option_index);
diff -rupN --exclude=.svn gcc-mainline-opt2/gcc/opts.h gcc-mainline/gcc/opts.h
--- gcc-mainline-opt2/gcc/opts.h	2010-06-21 15:24:55.000000000 -0700
+++ gcc-mainline/gcc/opts.h	2010-06-22 15:15:44.000000000 -0700
@@ -135,6 +135,47 @@  struct cl_decoded_option
   int errors;
 };
 
+/* Structure describing a single option-handling callback.  */
+
+struct cl_option_handler_func
+{
+  /* The function called to handle the option.  */
+  bool (*handler) (size_t opt_index, const char *arg, int value,
+		   unsigned int lang_mask, int kind,
+		   const struct cl_option_handlers *handlers);
+
+  /* The mask that must have some bit in common with the flags for the
+     option for this particular handler to be used.  */
+  unsigned int mask;
+};
+
+/* Structure describing the callbacks used in handling options.  */
+
+struct cl_option_handlers
+{
+  /* Callback for an unknown option to determine whether to give an
+     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);
+
+  /* Callback to handle, and possibly diagnose, an option for another
+     language.  */
+  void (*wrong_lang_callback) (const char *text,
+			       const struct cl_option *option,
+			       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);
+
+  /* The number of individual handlers.  */
+  size_t num_handlers;
+
+  /* The handlers themselves.  */
+  struct cl_option_handler_func handlers[3];
+};
+
 /* Input file names.  */
 
 extern const char **in_fnames;
@@ -157,10 +198,15 @@  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 (int opt_index, int value, const char *arg,
-		    unsigned int lang_mask, int kind);
+bool handle_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);
 extern void register_warning_as_error_callback (void (*callback) (int));
 extern void enable_warning_as_error (const char *arg, int value,
-				     unsigned int lang_mask);
+				     unsigned int lang_mask,
+				     const struct cl_option_handlers *handlers);
 extern void print_ignored_options (void);
 #endif