Patchwork Make prune_options work with decoded options

login
register
mail settings
Submitter Joseph S. Myers
Date Sept. 11, 2010, 12:15 p.m.
Message ID <Pine.LNX.4.64.1009111215060.9335@digraph.polyomino.org.uk>
Download mbox | patch
Permalink /patch/64511/
State New
Headers show

Comments

Joseph S. Myers - Sept. 11, 2010, 12:15 p.m.
This patch, based on a tree with
<http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00669.html> (pending
review) applied, makes prune_options work with decoded options and
moves it into decode_cmdline_options_to_array, so ensuring that both
the driver and the core compilers decode options as the next step in
argv processing after calling expandargv and so that they decode
the sequence of options in the same way (subject to any differences
arising from different lang_mask values).  This also means that
prune_options will now automatically work properly with option
aliases.

prune_options should only be needed in the driver, for specs
processing; option handlers are meant to handle successive mutually
overriding options properly, so that prune_options is only needed for
specs.  But if any corner case arises where prune_options affects how
the core compiler interprets options, consistency between the driver
and the core compiler seems desirable.  (Option handlers still need to
handle overriding options rather than relying on the previous pruning,
in order to work properly with the attributes that cause options to be
processed for particular functions.)

The main complication in making the driver start using decoded options
as early as it should is GCC_DRIVER_HOST_INITIALIZATION.  This is a
macro with rather poorly defined semantics.  Documented as a host
macro, it is in fact defined both as a host macro (for DJGPP) and as a
target macro (for Cygwin, Xtensa bare-metal and Darwin native).  This
would cause conflicts if a cross compiler is built from DJGPP to
Cygwin or Xtensa bare-metal.  The macro does not take parameters;
instead, it uses the caller's local variables, such as argc and argv.
The definition in xtensa/elf.h should probably not be there (I see no
good reason for xtensa-elf to have different directory search logic
from all other *-elf targets).  This patch fixes the affected
definitions of GCC_DRIVER_HOST_INITIALIZATION, those for Cygwin and
Darwin, to work with decoded options.  Yet another relic of -b and -V
handling, in darwin_default_min_version, is removed.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Tested
building xgcc for a cross to i686-cygwin and for a native Darwin
compiler (build = x86_64-unknown-linux-gnu, host = target =
i686-darwin) as a sanity check on those changes.  OK to commit?

2010-09-11  Joseph Myers  <joseph@codesourcery.com>

	* opts-common.c (prune_options): Make static.  Work with decoded
	options.
	(decode_cmdline_options_to_array): Call prune_options.  Don't
	resize option array here.
	* opts.h (prune_options): Remove prototype.
	* gcc.c (process_command): Take decoded options; don't call
	decode_cmdline_options_to_array here.  Use decoded options for
	argv[0].
	(main): Call decode_cmdline_options_to_array here instead of
	prune_options.  Update call to process_command.
	* config/darwin-driver.c: Include opts.h.
	(darwin_default_min_version): Work with decoded options.  Don't
	handle -b or -V here.
	* config/darwin.h (darwin_default_min_version): Update prototype.
	(GCC_DRIVER_HOST_INITIALIZATION): Update call to
	darwin_default_min_version.
	* config/i386/cygwin.h (mingw_scan): Update prototype.
	(GCC_DRIVER_HOST_INITIALIZATION): Update call to mingw_scan.
	* config/i386/cygwin1.c: Include opts.h.
	(mingw_scan): Work with decoded options.
	* config/i386/t-cygwin (cygwin1.o): Update dependencies.
	* config/t-darwin (darwin-driver.o): Update dependencies.
Richard Guenther - Sept. 11, 2010, 12:29 p.m.
On Sat, Sep 11, 2010 at 2:15 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> This patch, based on a tree with
> <http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00669.html> (pending
> review) applied, makes prune_options work with decoded options and
> moves it into decode_cmdline_options_to_array, so ensuring that both
> the driver and the core compilers decode options as the next step in
> argv processing after calling expandargv and so that they decode
> the sequence of options in the same way (subject to any differences
> arising from different lang_mask values).  This also means that
> prune_options will now automatically work properly with option
> aliases.
>
> prune_options should only be needed in the driver, for specs
> processing; option handlers are meant to handle successive mutually
> overriding options properly, so that prune_options is only needed for
> specs.  But if any corner case arises where prune_options affects how
> the core compiler interprets options, consistency between the driver
> and the core compiler seems desirable.  (Option handlers still need to
> handle overriding options rather than relying on the previous pruning,
> in order to work properly with the attributes that cause options to be
> processed for particular functions.)
>
> The main complication in making the driver start using decoded options
> as early as it should is GCC_DRIVER_HOST_INITIALIZATION.  This is a
> macro with rather poorly defined semantics.  Documented as a host
> macro, it is in fact defined both as a host macro (for DJGPP) and as a
> target macro (for Cygwin, Xtensa bare-metal and Darwin native).  This
> would cause conflicts if a cross compiler is built from DJGPP to
> Cygwin or Xtensa bare-metal.  The macro does not take parameters;
> instead, it uses the caller's local variables, such as argc and argv.
> The definition in xtensa/elf.h should probably not be there (I see no
> good reason for xtensa-elf to have different directory search logic
> from all other *-elf targets).  This patch fixes the affected
> definitions of GCC_DRIVER_HOST_INITIALIZATION, those for Cygwin and
> Darwin, to work with decoded options.  Yet another relic of -b and -V
> handling, in darwin_default_min_version, is removed.
>
> Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Tested
> building xgcc for a cross to i686-cygwin and for a native Darwin
> compiler (build = x86_64-unknown-linux-gnu, host = target =
> i686-darwin) as a sanity check on those changes.  OK to commit?

Ok.

Thanks,
Richard.

> 2010-09-11  Joseph Myers  <joseph@codesourcery.com>
>
>        * opts-common.c (prune_options): Make static.  Work with decoded
>        options.
>        (decode_cmdline_options_to_array): Call prune_options.  Don't
>        resize option array here.
>        * opts.h (prune_options): Remove prototype.
>        * gcc.c (process_command): Take decoded options; don't call
>        decode_cmdline_options_to_array here.  Use decoded options for
>        argv[0].
>        (main): Call decode_cmdline_options_to_array here instead of
>        prune_options.  Update call to process_command.
>        * config/darwin-driver.c: Include opts.h.
>        (darwin_default_min_version): Work with decoded options.  Don't
>        handle -b or -V here.
>        * config/darwin.h (darwin_default_min_version): Update prototype.
>        (GCC_DRIVER_HOST_INITIALIZATION): Update call to
>        darwin_default_min_version.
>        * config/i386/cygwin.h (mingw_scan): Update prototype.
>        (GCC_DRIVER_HOST_INITIALIZATION): Update call to mingw_scan.
>        * config/i386/cygwin1.c: Include opts.h.
>        (mingw_scan): Work with decoded options.
>        * config/i386/t-cygwin (cygwin1.o): Update dependencies.
>        * config/t-darwin (darwin-driver.o): Update dependencies.
>
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/darwin-driver.c gcc-mainline/gcc/config/darwin-driver.c
> --- gcc-mainline-0trans/gcc/config/darwin-driver.c      2010-07-27 16:46:56.000000000 -0700
> +++ gcc-mainline/gcc/config/darwin-driver.c     2010-09-10 17:35:03.000000000 -0700
> @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.
>  #include "coretypes.h"
>  #include "tm.h"
>  #include "gcc.h"
> +#include "opts.h"
>  #include <sys/sysctl.h>
>  #include "xregex.h"
>
> @@ -32,11 +33,12 @@ along with GCC; see the file COPYING3.
>    of the system on which the compiler is running.  */
>
>  void
> -darwin_default_min_version (int * argc_p, char *** argv_p)
> +darwin_default_min_version (unsigned int *decoded_options_count,
> +                           struct cl_decoded_option **decoded_options)
>  {
> -  const int argc = *argc_p;
> -  char ** const argv = *argv_p;
> -  int i;
> +  const unsigned int argc = *decoded_options_count;
> +  struct cl_decoded_option *const argv = *decoded_options;
> +  unsigned int i;
>   char osversion[32];
>   size_t osversion_len = sizeof (osversion) - 1;
>   static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE };
> @@ -44,34 +46,17 @@ darwin_default_min_version (int * argc_p
>   char * version_pend;
>   int major_vers;
>   char minor_vers[6];
> -  static char new_flag[sizeof ("-mmacosx-version-min=10.0.0") + 6];
> +  static char new_flag[sizeof ("10.0.0") + 6];
>
>   /* If the command-line is empty, just return.  */
>   if (argc <= 1)
>     return;
> -  /* Don't do this if the user has specified -b or -V at the start
> -     of the command-line.  */
> -  if (argv[1][0] == '-'
> -      && (argv[1][1] == 'V' ||
> -         ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
> -    return;
>
>   /* Don't do this if the user specified -mmacosx-version-min= or
>      -mno-macosx-version-min.  */
>   for (i = 1; i < argc; i++)
> -    if (argv[i][0] == '-')
> -      {
> -       const char * const p = argv[i];
> -       if (strncmp (p, "-mno-macosx-version-min", 23) == 0
> -           || strncmp (p, "-mmacosx-version-min", 20) == 0)
> -         return;
> -
> -       /* It doesn't count if it's an argument to a different switch.  */
> -       if (p[0] == '-'
> -           && ((SWITCH_TAKES_ARG (p[1]) > (p[2] != 0))
> -               || WORD_SWITCH_TAKES_ARG (p + 1)))
> -         i++;
> -      }
> +    if (argv[i].opt_index == OPT_mmacosx_version_min_)
> +      return;
>
>   /* Retrieve the deployment target from the environment and insert
>      it as a flag.  */
> @@ -84,12 +69,14 @@ darwin_default_min_version (int * argc_p
>           to ignore the environment variable, as if it was never set.  */
>        && macosx_deployment_target[0])
>       {
> -       ++*argc_p;
> -       *argv_p = XNEWVEC (char *, *argc_p);
> -       (*argv_p)[0] = argv[0];
> -       (*argv_p)[1] = concat ("-mmacosx-version-min=",
> -                              macosx_deployment_target, NULL);
> -       memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *));
> +       ++*decoded_options_count;
> +       *decoded_options = XNEWVEC (struct cl_decoded_option,
> +                                   *decoded_options_count);
> +       (*decoded_options)[0] = argv[0];
> +       generate_option (OPT_mmacosx_version_min_, macosx_deployment_target,
> +                        1, CL_DRIVER, &(*decoded_options)[1]);
> +       memcpy (*decoded_options + 2, argv + 1,
> +               (argc - 1) * sizeof (struct cl_decoded_option *));
>        return;
>       }
>   }
> @@ -128,17 +115,20 @@ darwin_default_min_version (int * argc_p
>   if (major_vers - 4 <= 4)
>     /* On 10.4 and earlier, the old linker is used which does not
>        support three-component system versions.  */
> -    sprintf (new_flag, "-mmacosx-version-min=10.%d", major_vers - 4);
> +    sprintf (new_flag, "10.%d", major_vers - 4);
>   else
> -    sprintf (new_flag, "-mmacosx-version-min=10.%d.%s", major_vers - 4,
> +    sprintf (new_flag, "10.%d.%s", major_vers - 4,
>             minor_vers);
>
>   /* Add the new flag.  */
> -  ++*argc_p;
> -  *argv_p = XNEWVEC (char *, *argc_p);
> -  (*argv_p)[0] = argv[0];
> -  (*argv_p)[1] = new_flag;
> -  memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *));
> +  ++*decoded_options_count;
> +  *decoded_options = XNEWVEC (struct cl_decoded_option,
> +                             *decoded_options_count);
> +  (*decoded_options)[0] = argv[0];
> +  generate_option (OPT_mmacosx_version_min_, new_flag,
> +                  1, CL_DRIVER, &(*decoded_options)[1]);
> +  memcpy (*decoded_options + 2, argv + 1,
> +         (argc - 1) * sizeof (struct cl_decoded_option *));
>   return;
>
>  parse_failed:
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/darwin.h gcc-mainline/gcc/config/darwin.h
> --- gcc-mainline-0trans/gcc/config/darwin.h     2010-08-22 05:22:04.000000000 -0700
> +++ gcc-mainline/gcc/config/darwin.h    2010-09-10 13:45:48.000000000 -0700
> @@ -1059,9 +1059,10 @@ extern int flag_apple_kext;
>  #define TARGET_HAS_TARGETCM 1
>
>  #ifndef CROSS_DIRECTORY_STRUCTURE
> -extern void darwin_default_min_version (int * argc, char *** argv);
> +extern void darwin_default_min_version (unsigned int *decoded_options_count,
> +                                       struct cl_decoded_option **decoded_options);
>  #define GCC_DRIVER_HOST_INITIALIZATION \
> -  darwin_default_min_version (&argc, &argv)
> +  darwin_default_min_version (&decoded_options_count, &decoded_options)
>  #endif /* CROSS_DIRECTORY_STRUCTURE */
>
>  /* The Apple assembler and linker do not support constructor priorities.  */
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/i386/cygwin.h gcc-mainline/gcc/config/i386/cygwin.h
> --- gcc-mainline-0trans/gcc/config/i386/cygwin.h        2010-09-02 04:45:25.000000000 -0700
> +++ gcc-mainline/gcc/config/i386/cygwin.h       2010-09-10 17:03:22.000000000 -0700
> @@ -252,12 +252,13 @@ char *cvt_to_mingw[] =
>  #undef GEN_CVT_ARRAY
>  #endif /*GEN_CVT_ARRAY*/
>
> -void mingw_scan (int, const char * const *, const char **);
> +void mingw_scan (unsigned int, const struct cl_decoded_option *,
> +                const char **);
>  #if 1
>  #define GCC_DRIVER_HOST_INITIALIZATION \
>  do \
>  { \
> -  mingw_scan(argc, (const char * const *) argv, &spec_machine); \
> +  mingw_scan (decoded_options_count, decoded_options, &spec_machine);  \
>   } \
>  while (0)
>  #else
> @@ -277,7 +278,7 @@ do \
>   add_prefix (&startfile_prefixes,\
>              concat (standard_startfile_prefix, "w32api", NULL),\
>              "GCC", PREFIX_PRIORITY_LAST, 0, NULL);\
> -  mingw_scan(argc, (const char * const *) argv, &spec_machine); \
> +  mingw_scan (decoded_options_count, decoded_options, &spec_machine);  \
>   } \
>  while (0)
>  #endif
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/i386/cygwin1.c gcc-mainline/gcc/config/i386/cygwin1.c
> --- gcc-mainline-0trans/gcc/config/i386/cygwin1.c       2009-03-28 00:38:15.000000000 -0700
> +++ gcc-mainline/gcc/config/i386/cygwin1.c      2010-09-10 17:03:32.000000000 -0700
> @@ -22,32 +22,42 @@ along with GCC; see the file COPYING3.
>  #include "system.h"
>  #include "coretypes.h"
>  #include "tm.h"
> +#include "opts.h"
>  #include <string.h>
>
>  void
> -mingw_scan (int argc ATTRIBUTE_UNUSED,
> -            const char *const *argv,
> +mingw_scan (unsigned int decoded_options_count,
> +           const struct cl_decoded_option *decoded_options,
>             const char **spec_machine)
>  {
> +  unsigned int i;
>   putenv (xstrdup ("GCC_CYGWIN_MINGW=0"));
>
> -  while (*++argv)
> -    if (strcmp (*argv, "-mno-win32") == 0)
> -      putenv (xstrdup ("GCC_CYGWIN_WIN32=0"));
> -    else if (strcmp (*argv, "-mwin32") == 0)
> -      putenv (xstrdup ("GCC_CYGWIN_WIN32=1"));
> -    else if (strcmp (*argv, "-mno-cygwin") == 0)
> +  for (i = 1; i < decoded_options_count; i++)
> +    switch (decoded_options[i].opt_index)
>       {
> -       char *p = strstr (*spec_machine, "-cygwin");
> -       if (p)
> +      case OPT_mwin32:
> +       if (decoded_options[i].value == 0)
> +         putenv (xstrdup ("GCC_CYGWIN_WIN32=0"));
> +       else
> +         putenv (xstrdup ("GCC_CYGWIN_WIN32=1"));
> +       break;
> +
> +      case OPT_mcygwin:
> +       if (decoded_options[i].value == 0)
>          {
> -           int len = p - *spec_machine;
> -           char *s = XNEWVEC (char, strlen (*spec_machine) + 3);
> -           memcpy (s, *spec_machine, len);
> -           strcpy (s + len, "-mingw32");
> -           *spec_machine = s;
> +           char *p = strstr (*spec_machine, "-cygwin");
> +           if (p)
> +             {
> +               int len = p - *spec_machine;
> +               char *s = XNEWVEC (char, strlen (*spec_machine) + 3);
> +               memcpy (s, *spec_machine, len);
> +               strcpy (s + len, "-mingw32");
> +               *spec_machine = s;
> +             }
> +           putenv (xstrdup ("GCC_CYGWIN_MINGW=1"));
>          }
> -       putenv (xstrdup ("GCC_CYGWIN_MINGW=1"));
> +       break;
>       }
>   return;
>  }
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/i386/t-cygwin gcc-mainline/gcc/config/i386/t-cygwin
> --- gcc-mainline-0trans/gcc/config/i386/t-cygwin        2010-09-02 04:45:25.000000000 -0700
> +++ gcc-mainline/gcc/config/i386/t-cygwin       2010-09-10 17:04:44.000000000 -0700
> @@ -1,4 +1,4 @@
> -# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009
> +# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010
>  # Free Software Foundation, Inc.
>  #
>  # This file is part of GCC.
> @@ -24,7 +24,7 @@ LIBGCC2_INCLUDES += -I$(srcdir)/../winsu
>        -I$(srcdir)/../winsup/cygwin/include
>
>  cygwin1.o: $(srcdir)/config/i386/cygwin1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
> -  $(TM_H) $(TM_P_H)
> +  $(TM_H) $(TM_P_H) opts.h
>        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
>        $(srcdir)/config/i386/cygwin1.c
>
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/t-darwin gcc-mainline/gcc/config/t-darwin
> --- gcc-mainline-0trans/gcc/config/t-darwin     2010-06-07 02:48:58.000000000 -0700
> +++ gcc-mainline/gcc/config/t-darwin    2010-09-10 17:04:34.000000000 -0700
> @@ -36,7 +36,7 @@ darwin-f.o: $(srcdir)/config/darwin-f.c
>          $(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES)
>
>  darwin-driver.o: $(srcdir)/config/darwin-driver.c \
> -  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
> +  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) opts.h
>        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
>          $(srcdir)/config/darwin-driver.c
>
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/gcc.c gcc-mainline/gcc/gcc.c
> --- gcc-mainline-0trans/gcc/gcc.c       2010-09-08 03:32:16.000000000 -0700
> +++ gcc-mainline/gcc/gcc.c      2010-09-10 14:12:13.000000000 -0700
> @@ -261,7 +261,7 @@ static void display_help (void);
>  static void add_preprocessor_option (const char *, int);
>  static void add_assembler_option (const char *, int);
>  static void add_linker_option (const char *, int);
> -static void process_command (int, const char **);
> +static void process_command (unsigned int, struct cl_decoded_option *);
>  static int execute (void);
>  static void alloc_args (void);
>  static void clear_args (void);
> @@ -3516,7 +3516,8 @@ driver_handle_option (const struct cl_de
>    Store its length in `n_switches'.  */
>
>  static void
> -process_command (int argc, const char **argv)
> +process_command (unsigned int decoded_options_count,
> +                struct cl_decoded_option *decoded_options)
>  {
>   const char *temp;
>   char *temp1;
> @@ -3524,8 +3525,7 @@ process_command (int argc, const char **
>   char *(*get_relative_prefix) (const char *, const char *,
>                                const char *) = NULL;
>   struct cl_option_handlers handlers;
> -  struct cl_decoded_option *decoded_options;
> -  unsigned int decoded_options_count, j;
> +  unsigned int j;
>
>   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
>
> @@ -3546,9 +3546,6 @@ process_command (int argc, const char **
>        }
>     }
>
> -  decode_cmdline_options_to_array (argc, argv, CL_DRIVER,
> -                                  &decoded_options, &decoded_options_count);
> -
>   /* Handle any -no-canonical-prefixes flag early, to assign the function
>      that builds relative prefixes.  This function creates default search
>      paths that are needed later in normal option handling.  */
> @@ -3565,17 +3562,18 @@ process_command (int argc, const char **
>     get_relative_prefix = make_relative_prefix;
>
>   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
> -     see if we can create it from the pathname specified in argv[0].  */
> +     see if we can create it from the pathname specified in
> +     decoded_options[0].arg.  */
>
>   gcc_libexec_prefix = standard_libexec_prefix;
>  #ifndef VMS
>   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
>   if (!gcc_exec_prefix)
>     {
> -      gcc_exec_prefix = get_relative_prefix (argv[0],
> +      gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
>                                             standard_bindir_prefix,
>                                             standard_exec_prefix);
> -      gcc_libexec_prefix = get_relative_prefix (argv[0],
> +      gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg,
>                                             standard_bindir_prefix,
>                                             standard_libexec_prefix);
>       if (gcc_exec_prefix)
> @@ -3602,7 +3600,8 @@ process_command (int argc, const char **
>  #endif
>   /* From this point onward, gcc_exec_prefix is non-null if the toolchain
>      is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
> -     or an automatically created GCC_EXEC_PREFIX from argv[0].  */
> +     or an automatically created GCC_EXEC_PREFIX from
> +     decoded_options[0].arg.  */
>
>   /* Do language-specific adjustment/addition of flags.  */
>   lang_specific_driver (&decoded_options, &decoded_options_count,
> @@ -3898,7 +3897,7 @@ process_command (int argc, const char **
>      ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
>   if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
>     {
> -      char *tmp_prefix = get_relative_prefix (argv[0],
> +      char *tmp_prefix = get_relative_prefix (decoded_options[0].arg,
>                                              standard_bindir_prefix,
>                                              target_system_root);
>       if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
> @@ -6109,6 +6108,8 @@ main (int argc, char **argv)
>   const char *p;
>   struct user_specs *uptr;
>   char **old_argv = argv;
> +  struct cl_decoded_option *decoded_options;
> +  unsigned int decoded_options_count;
>
>   /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
>      on ?: in file-scope variable initializations.  */
> @@ -6127,7 +6128,10 @@ main (int argc, char **argv)
>   if (argv != old_argv)
>     at_file_supplied = true;
>
> -  prune_options (&argc, &argv);
> +  decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **,
> +                                                     argv),
> +                                  CL_DRIVER,
> +                                  &decoded_options, &decoded_options_count);
>
>  #ifdef GCC_DRIVER_HOST_INITIALIZATION
>   /* Perform host dependent initialization when needed.  */
> @@ -6217,7 +6221,7 @@ main (int argc, char **argv)
>      Make a table of specified input files (infiles, n_infiles).
>      Decode switches that are handled locally.  */
>
> -  process_command (argc, CONST_CAST2 (const char **, char **, argv));
> +  process_command (decoded_options_count, decoded_options);
>
>   /* Initialize the vector of specs to just the default.
>      This means one element containing 0s, as a terminator.  */
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/opts-common.c gcc-mainline/gcc/opts-common.c
> --- gcc-mainline-0trans/gcc/opts-common.c       2010-09-08 06:56:29.000000000 -0700
> +++ gcc-mainline/gcc/opts-common.c      2010-09-10 14:47:56.000000000 -0700
> @@ -27,6 +27,8 @@ along with GCC; see the file COPYING3.
>  #include "tm.h" /* For SWITCH_TAKES_ARG, WORD_SWITCH_TAKES_ARG and
>                   TARGET_OPTION_TRANSLATE_TABLE.  */
>
> +static void prune_options (struct cl_decoded_option **, unsigned int *);
> +
>  /* Perform a binary search to find which option the command-line INPUT
>    matches.  Returns its index in the option array, and
>    OPT_SPECIAL_unknown on failure.
> @@ -698,10 +700,9 @@ decode_cmdline_options_to_array (unsigne
>
>   if (argv_copied)
>     free (argv);
> -  opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array,
> -                         num_decoded_options);
>   *decoded_options = opt_array;
>   *decoded_options_count = num_decoded_options;
> +  prune_options (decoded_options, decoded_options_count);
>  }
>
>  /* Return true if NEXT_OPT_IDX cancels OPT_IDX.  Return false if the
> @@ -724,119 +725,77 @@ cancel_option (int opt_idx, int next_opt
>
>  /* Filter out options canceled by the ones after them.  */
>
> -void
> -prune_options (int *argcp, char ***argvp)
> +static void
> +prune_options (struct cl_decoded_option **decoded_options,
> +              unsigned int *decoded_options_count)
>  {
> -  int argc = *argcp;
> -  int *options = XNEWVEC (int, argc);
> -  /* We will only return this replacement argv if we remove at least
> -     one argument, so it does not need to be size (argc + 1) to
> -     make room for the terminating NULL because we will always have
> -     freed up at least one slot when we end up using it at all.  */
> -  char **argv = XNEWVEC (char *, argc);
> -  int i, arg_count, need_prune = 0;
> +  unsigned int old_decoded_options_count = *decoded_options_count;
> +  struct cl_decoded_option *old_decoded_options = *decoded_options;
> +  unsigned int new_decoded_options_count;
> +  struct cl_decoded_option *new_decoded_options
> +    = XNEWVEC (struct cl_decoded_option, old_decoded_options_count);
> +  unsigned int i;
>   const struct cl_option *option;
> -  size_t opt_index;
>
> -  /* Scan all arguments.  */
> -  for (i = 1; i < argc; i++)
> +  /* Remove arguments which are negated by others after them.  */
> +  new_decoded_options_count = 0;
> +  for (i = 0; i < old_decoded_options_count; i++)
>     {
> -      int value = 1;
> -      const char *opt = (*argvp) [i];
> +      unsigned int j, opt_idx, next_opt_idx;
>
> -      opt_index = find_opt (opt + 1, -1);
> -      if (opt_index == OPT_SPECIAL_unknown
> -         && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
> -         && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
> -       {
> -         char *dup;
> -
> -         /* Drop the "no-" from negative switches.  */
> -         size_t len = strlen (opt) - 3;
> -
> -         dup = XNEWVEC (char, len + 1);
> -         dup[0] = '-';
> -         dup[1] = opt[1];
> -         memcpy (dup + 2, opt + 5, len - 2 + 1);
> -         opt = dup;
> -         value = 0;
> -         opt_index = find_opt (opt + 1, -1);
> -         free (dup);
> -       }
> +      if (old_decoded_options[i].errors & ~CL_ERR_WRONG_LANG)
> +       goto keep;
>
> -      if (opt_index == OPT_SPECIAL_unknown)
> +      opt_idx = old_decoded_options[i].opt_index;
> +      switch (opt_idx)
>        {
> -cont:
> -         options [i] = 0;
> -         continue;
> -       }
> -
> -      option = &cl_options[opt_index];
> -      if (option->neg_index < 0)
> -       goto cont;
> -
> -      /* Skip joined switches.  */
> -      if ((option->flags & CL_JOINED))
> -       goto cont;
> -
> -      /* Reject negative form of switches that don't take negatives as
> -        unrecognized.  */
> -      if (!value && (option->flags & CL_REJECT_NEGATIVE))
> -       goto cont;
> -
> -      options [i] = (int) opt_index;
> -      need_prune |= options [i];
> -    }
> +       case OPT_SPECIAL_unknown:
> +       case OPT_SPECIAL_ignore:
> +       case OPT_SPECIAL_program_name:
> +       case OPT_SPECIAL_input_file:
> +         goto keep;
> +
> +       default:
> +         gcc_assert (opt_idx < cl_options_count);
> +         option = &cl_options[opt_idx];
> +         if (option->neg_index < 0)
> +           goto keep;
> +
> +         /* Skip joined switches.  */
> +         if ((option->flags & CL_JOINED))
> +           goto keep;
>
> -  if (!need_prune)
> -    goto done;
> -
> -  /* Remove arguments which are negated by others after them.  */
> -  argv [0] = (*argvp) [0];
> -  arg_count = 1;
> -  for (i = 1; i < argc; i++)
> -    {
> -      int j, opt_idx;
> -
> -      opt_idx = options [i];
> -      if (opt_idx)
> -       {
> -         int next_opt_idx;
> -         for (j = i + 1; j < argc; j++)
> +         for (j = i + 1; j < old_decoded_options_count; j++)
>            {
> -             next_opt_idx = options [j];
> -             if (next_opt_idx
> -                 && cancel_option (opt_idx, next_opt_idx,
> -                                   next_opt_idx))
> +             if (old_decoded_options[j].errors & ~CL_ERR_WRONG_LANG)
> +               continue;
> +             next_opt_idx = old_decoded_options[j].opt_index;
> +             if (next_opt_idx >= cl_options_count)
> +               continue;
> +             if (cl_options[next_opt_idx].neg_index < 0)
> +               continue;
> +             if ((cl_options[next_opt_idx].flags & CL_JOINED))
> +                 continue;
> +             if (cancel_option (opt_idx, next_opt_idx, next_opt_idx))
>                break;
>            }
> -       }
> -      else
> -       goto keep;
> -
> -      if (j == argc)
> -       {
> +         if (j == old_decoded_options_count)
> +           {
>  keep:
> -         argv [arg_count] = (*argvp) [i];
> -         arg_count++;
> +             new_decoded_options[new_decoded_options_count]
> +               = old_decoded_options[i];
> +             new_decoded_options_count++;
> +           }
> +         break;
>        }
>     }
>
> -  if (arg_count != argc)
> -    {
> -      *argcp = arg_count;
> -      *argvp = argv;
> -      /* Add NULL-termination.  Guaranteed not to overflow because
> -        arg_count here can only be less than argc.  */
> -      argv[arg_count] = 0;
> -    }
> -  else
> -    {
> -done:
> -      free (argv);
> -    }
> -
> -  free (options);
> +  free (old_decoded_options);
> +  new_decoded_options = XRESIZEVEC (struct cl_decoded_option,
> +                                   new_decoded_options,
> +                                   new_decoded_options_count);
> +  *decoded_options = new_decoded_options;
> +  *decoded_options_count = new_decoded_options_count;
>  }
>
>  /* Handle option DECODED for the language indicated by LANG_MASK,
> diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/opts.h gcc-mainline/gcc/opts.h
> --- gcc-mainline-0trans/gcc/opts.h      2010-09-03 08:51:25.000000000 -0700
> +++ gcc-mainline/gcc/opts.h     2010-09-10 12:56:10.000000000 -0700
> @@ -206,7 +206,6 @@ extern void decode_cmdline_options_to_ar
>                                             unsigned int lang_mask,
>                                             struct cl_decoded_option **decoded_options,
>                                             unsigned int *decoded_options_count);
> -extern void prune_options (int *argcp, char ***argvp);
>  extern void decode_options (unsigned int argc, const char **argv,
>                            struct cl_decoded_option **decoded_options,
>                            unsigned int *decoded_options_count);
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>
Dave Korn - Sept. 11, 2010, 1:26 p.m.
On 11/09/2010 13:15, Joseph S. Myers wrote:

> The main complication in making the driver start using decoded options
> as early as it should is GCC_DRIVER_HOST_INITIALIZATION.  This is a
> macro with rather poorly defined semantics.  Documented as a host
> macro, it is in fact defined both as a host macro (for DJGPP) and as a
> target macro (for Cygwin, Xtensa bare-metal and Darwin native).  This
> would cause conflicts if a cross compiler is built from DJGPP to
> Cygwin or Xtensa bare-metal.  [ ... ]  This patch fixes the affected
> definitions of GCC_DRIVER_HOST_INITIALIZATION, those for Cygwin and
> Darwin, to work with decoded options.  [ ... ]

  Oh.  Sorry, Joseph, I hope you didn't spend too much time and sweat fixing
up that Cygwin stuff; it's all deprecated and I'm planning to chop the whole
lot out before 4.7.0 goes out; I wish I could have saved you the trouble.
(Just to be clear, I don't in any way object to this patch; in the long run
it's not going to matter from a Cygwin POV.)

    cheers,
      DaveK

Patch

diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/darwin-driver.c gcc-mainline/gcc/config/darwin-driver.c
--- gcc-mainline-0trans/gcc/config/darwin-driver.c	2010-07-27 16:46:56.000000000 -0700
+++ gcc-mainline/gcc/config/darwin-driver.c	2010-09-10 17:35:03.000000000 -0700
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.  
 #include "coretypes.h"
 #include "tm.h"
 #include "gcc.h"
+#include "opts.h"
 #include <sys/sysctl.h>
 #include "xregex.h"
 
@@ -32,11 +33,12 @@  along with GCC; see the file COPYING3.  
    of the system on which the compiler is running.  */
 
 void
-darwin_default_min_version (int * argc_p, char *** argv_p)
+darwin_default_min_version (unsigned int *decoded_options_count,
+			    struct cl_decoded_option **decoded_options)
 {
-  const int argc = *argc_p;
-  char ** const argv = *argv_p;
-  int i;
+  const unsigned int argc = *decoded_options_count;
+  struct cl_decoded_option *const argv = *decoded_options;
+  unsigned int i;
   char osversion[32];
   size_t osversion_len = sizeof (osversion) - 1;
   static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE };
@@ -44,34 +46,17 @@  darwin_default_min_version (int * argc_p
   char * version_pend;
   int major_vers;
   char minor_vers[6];
-  static char new_flag[sizeof ("-mmacosx-version-min=10.0.0") + 6];
+  static char new_flag[sizeof ("10.0.0") + 6];
 
   /* If the command-line is empty, just return.  */
   if (argc <= 1)
     return;
-  /* Don't do this if the user has specified -b or -V at the start
-     of the command-line.  */
-  if (argv[1][0] == '-'
-      && (argv[1][1] == 'V' ||
-	  ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
-    return;
   
   /* Don't do this if the user specified -mmacosx-version-min= or
      -mno-macosx-version-min.  */
   for (i = 1; i < argc; i++)
-    if (argv[i][0] == '-')
-      {
-	const char * const p = argv[i];
-	if (strncmp (p, "-mno-macosx-version-min", 23) == 0
-	    || strncmp (p, "-mmacosx-version-min", 20) == 0)
-	  return;
-	
-	/* It doesn't count if it's an argument to a different switch.  */
-	if (p[0] == '-'
-	    && ((SWITCH_TAKES_ARG (p[1]) > (p[2] != 0))
-		|| WORD_SWITCH_TAKES_ARG (p + 1)))
-	  i++;
-      }
+    if (argv[i].opt_index == OPT_mmacosx_version_min_)
+      return;
 
   /* Retrieve the deployment target from the environment and insert
      it as a flag.  */
@@ -84,12 +69,14 @@  darwin_default_min_version (int * argc_p
 	   to ignore the environment variable, as if it was never set.  */
 	&& macosx_deployment_target[0])
       {
-	++*argc_p;
-	*argv_p = XNEWVEC (char *, *argc_p);
-	(*argv_p)[0] = argv[0];
-	(*argv_p)[1] = concat ("-mmacosx-version-min=",
-			       macosx_deployment_target, NULL);
-	memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *));
+	++*decoded_options_count;
+	*decoded_options = XNEWVEC (struct cl_decoded_option,
+				    *decoded_options_count);
+	(*decoded_options)[0] = argv[0];
+	generate_option (OPT_mmacosx_version_min_, macosx_deployment_target,
+			 1, CL_DRIVER, &(*decoded_options)[1]);
+	memcpy (*decoded_options + 2, argv + 1,
+		(argc - 1) * sizeof (struct cl_decoded_option *));
 	return;
       }
   }
@@ -128,17 +115,20 @@  darwin_default_min_version (int * argc_p
   if (major_vers - 4 <= 4)
     /* On 10.4 and earlier, the old linker is used which does not
        support three-component system versions.  */
-    sprintf (new_flag, "-mmacosx-version-min=10.%d", major_vers - 4);
+    sprintf (new_flag, "10.%d", major_vers - 4);
   else
-    sprintf (new_flag, "-mmacosx-version-min=10.%d.%s", major_vers - 4,
+    sprintf (new_flag, "10.%d.%s", major_vers - 4,
 	     minor_vers);
 
   /* Add the new flag.  */
-  ++*argc_p;
-  *argv_p = XNEWVEC (char *, *argc_p);
-  (*argv_p)[0] = argv[0];
-  (*argv_p)[1] = new_flag;
-  memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *));
+  ++*decoded_options_count;
+  *decoded_options = XNEWVEC (struct cl_decoded_option,
+			      *decoded_options_count);
+  (*decoded_options)[0] = argv[0];
+  generate_option (OPT_mmacosx_version_min_, new_flag,
+		   1, CL_DRIVER, &(*decoded_options)[1]);
+  memcpy (*decoded_options + 2, argv + 1,
+	  (argc - 1) * sizeof (struct cl_decoded_option *));
   return;
   
  parse_failed:
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/darwin.h gcc-mainline/gcc/config/darwin.h
--- gcc-mainline-0trans/gcc/config/darwin.h	2010-08-22 05:22:04.000000000 -0700
+++ gcc-mainline/gcc/config/darwin.h	2010-09-10 13:45:48.000000000 -0700
@@ -1059,9 +1059,10 @@  extern int flag_apple_kext;
 #define TARGET_HAS_TARGETCM 1
 
 #ifndef CROSS_DIRECTORY_STRUCTURE
-extern void darwin_default_min_version (int * argc, char *** argv);
+extern void darwin_default_min_version (unsigned int *decoded_options_count,
+					struct cl_decoded_option **decoded_options);
 #define GCC_DRIVER_HOST_INITIALIZATION \
-  darwin_default_min_version (&argc, &argv)
+  darwin_default_min_version (&decoded_options_count, &decoded_options)
 #endif /* CROSS_DIRECTORY_STRUCTURE */
 
 /* The Apple assembler and linker do not support constructor priorities.  */
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/i386/cygwin.h gcc-mainline/gcc/config/i386/cygwin.h
--- gcc-mainline-0trans/gcc/config/i386/cygwin.h	2010-09-02 04:45:25.000000000 -0700
+++ gcc-mainline/gcc/config/i386/cygwin.h	2010-09-10 17:03:22.000000000 -0700
@@ -252,12 +252,13 @@  char *cvt_to_mingw[] =
 #undef GEN_CVT_ARRAY
 #endif /*GEN_CVT_ARRAY*/
 
-void mingw_scan (int, const char * const *, const char **);
+void mingw_scan (unsigned int, const struct cl_decoded_option *,
+		 const char **);
 #if 1
 #define GCC_DRIVER_HOST_INITIALIZATION \
 do \
 { \
-  mingw_scan(argc, (const char * const *) argv, &spec_machine); \
+  mingw_scan (decoded_options_count, decoded_options, &spec_machine);	\
   } \
 while (0)
 #else
@@ -277,7 +278,7 @@  do \
   add_prefix (&startfile_prefixes,\
 	      concat (standard_startfile_prefix, "w32api", NULL),\
 	      "GCC", PREFIX_PRIORITY_LAST, 0, NULL);\
-  mingw_scan(argc, (const char * const *) argv, &spec_machine); \
+  mingw_scan (decoded_options_count, decoded_options, &spec_machine);	\
   } \
 while (0)
 #endif
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/i386/cygwin1.c gcc-mainline/gcc/config/i386/cygwin1.c
--- gcc-mainline-0trans/gcc/config/i386/cygwin1.c	2009-03-28 00:38:15.000000000 -0700
+++ gcc-mainline/gcc/config/i386/cygwin1.c	2010-09-10 17:03:32.000000000 -0700
@@ -22,32 +22,42 @@  along with GCC; see the file COPYING3.  
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "opts.h"
 #include <string.h>
 
 void
-mingw_scan (int argc ATTRIBUTE_UNUSED,
-            const char *const *argv,
+mingw_scan (unsigned int decoded_options_count,
+	    const struct cl_decoded_option *decoded_options,
             const char **spec_machine)
 {
+  unsigned int i;
   putenv (xstrdup ("GCC_CYGWIN_MINGW=0"));
  
-  while (*++argv)
-    if (strcmp (*argv, "-mno-win32") == 0)
-      putenv (xstrdup ("GCC_CYGWIN_WIN32=0"));
-    else if (strcmp (*argv, "-mwin32") == 0)
-      putenv (xstrdup ("GCC_CYGWIN_WIN32=1"));
-    else if (strcmp (*argv, "-mno-cygwin") == 0)
+  for (i = 1; i < decoded_options_count; i++)
+    switch (decoded_options[i].opt_index)
       {
-	char *p = strstr (*spec_machine, "-cygwin");
-	if (p)
+      case OPT_mwin32:
+	if (decoded_options[i].value == 0)
+	  putenv (xstrdup ("GCC_CYGWIN_WIN32=0"));
+	else
+	  putenv (xstrdup ("GCC_CYGWIN_WIN32=1"));
+	break;
+
+      case OPT_mcygwin:
+	if (decoded_options[i].value == 0)
 	  {
-	    int len = p - *spec_machine;
-	    char *s = XNEWVEC (char, strlen (*spec_machine) + 3);
-	    memcpy (s, *spec_machine, len);
-	    strcpy (s + len, "-mingw32");
-	    *spec_machine = s;
+	    char *p = strstr (*spec_machine, "-cygwin");
+	    if (p)
+	      {
+		int len = p - *spec_machine;
+		char *s = XNEWVEC (char, strlen (*spec_machine) + 3);
+		memcpy (s, *spec_machine, len);
+		strcpy (s + len, "-mingw32");
+		*spec_machine = s;
+	      }
+	    putenv (xstrdup ("GCC_CYGWIN_MINGW=1"));
 	  }
-	putenv (xstrdup ("GCC_CYGWIN_MINGW=1"));
+	break;
       }
   return;
 }
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/i386/t-cygwin gcc-mainline/gcc/config/i386/t-cygwin
--- gcc-mainline-0trans/gcc/config/i386/t-cygwin	2010-09-02 04:45:25.000000000 -0700
+++ gcc-mainline/gcc/config/i386/t-cygwin	2010-09-10 17:04:44.000000000 -0700
@@ -1,4 +1,4 @@ 
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009
+# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010
 # Free Software Foundation, Inc.
 #
 # This file is part of GCC.
@@ -24,7 +24,7 @@  LIBGCC2_INCLUDES += -I$(srcdir)/../winsu
 	-I$(srcdir)/../winsup/cygwin/include
 
 cygwin1.o: $(srcdir)/config/i386/cygwin1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-  $(TM_H) $(TM_P_H)
+  $(TM_H) $(TM_P_H) opts.h
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	$(srcdir)/config/i386/cygwin1.c
 
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/config/t-darwin gcc-mainline/gcc/config/t-darwin
--- gcc-mainline-0trans/gcc/config/t-darwin	2010-06-07 02:48:58.000000000 -0700
+++ gcc-mainline/gcc/config/t-darwin	2010-09-10 17:04:34.000000000 -0700
@@ -36,7 +36,7 @@  darwin-f.o: $(srcdir)/config/darwin-f.c 
 	  $(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES)
 
 darwin-driver.o: $(srcdir)/config/darwin-driver.c \
-  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) opts.h
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	  $(srcdir)/config/darwin-driver.c
 
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/gcc.c gcc-mainline/gcc/gcc.c
--- gcc-mainline-0trans/gcc/gcc.c	2010-09-08 03:32:16.000000000 -0700
+++ gcc-mainline/gcc/gcc.c	2010-09-10 14:12:13.000000000 -0700
@@ -261,7 +261,7 @@  static void display_help (void);
 static void add_preprocessor_option (const char *, int);
 static void add_assembler_option (const char *, int);
 static void add_linker_option (const char *, int);
-static void process_command (int, const char **);
+static void process_command (unsigned int, struct cl_decoded_option *);
 static int execute (void);
 static void alloc_args (void);
 static void clear_args (void);
@@ -3516,7 +3516,8 @@  driver_handle_option (const struct cl_de
    Store its length in `n_switches'.  */
 
 static void
-process_command (int argc, const char **argv)
+process_command (unsigned int decoded_options_count,
+		 struct cl_decoded_option *decoded_options)
 {
   const char *temp;
   char *temp1;
@@ -3524,8 +3525,7 @@  process_command (int argc, const char **
   char *(*get_relative_prefix) (const char *, const char *,
 				const char *) = NULL;
   struct cl_option_handlers handlers;
-  struct cl_decoded_option *decoded_options;
-  unsigned int decoded_options_count, j;
+  unsigned int j;
 
   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
 
@@ -3546,9 +3546,6 @@  process_command (int argc, const char **
 	}
     }
 
-  decode_cmdline_options_to_array (argc, argv, CL_DRIVER,
-				   &decoded_options, &decoded_options_count);
-
   /* Handle any -no-canonical-prefixes flag early, to assign the function
      that builds relative prefixes.  This function creates default search
      paths that are needed later in normal option handling.  */
@@ -3565,17 +3562,18 @@  process_command (int argc, const char **
     get_relative_prefix = make_relative_prefix;
 
   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
-     see if we can create it from the pathname specified in argv[0].  */
+     see if we can create it from the pathname specified in
+     decoded_options[0].arg.  */
 
   gcc_libexec_prefix = standard_libexec_prefix;
 #ifndef VMS
   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
   if (!gcc_exec_prefix)
     {
-      gcc_exec_prefix = get_relative_prefix (argv[0],
+      gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
 					     standard_bindir_prefix,
 					     standard_exec_prefix);
-      gcc_libexec_prefix = get_relative_prefix (argv[0],
+      gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg,
 					     standard_bindir_prefix,
 					     standard_libexec_prefix);
       if (gcc_exec_prefix)
@@ -3602,7 +3600,8 @@  process_command (int argc, const char **
 #endif
   /* From this point onward, gcc_exec_prefix is non-null if the toolchain
      is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
-     or an automatically created GCC_EXEC_PREFIX from argv[0].  */
+     or an automatically created GCC_EXEC_PREFIX from
+     decoded_options[0].arg.  */
 
   /* Do language-specific adjustment/addition of flags.  */
   lang_specific_driver (&decoded_options, &decoded_options_count,
@@ -3898,7 +3897,7 @@  process_command (int argc, const char **
      ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
   if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
     {
-      char *tmp_prefix = get_relative_prefix (argv[0],
+      char *tmp_prefix = get_relative_prefix (decoded_options[0].arg,
 					      standard_bindir_prefix,
 					      target_system_root);
       if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
@@ -6109,6 +6108,8 @@  main (int argc, char **argv)
   const char *p;
   struct user_specs *uptr;
   char **old_argv = argv;
+  struct cl_decoded_option *decoded_options;
+  unsigned int decoded_options_count;
 
   /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
      on ?: in file-scope variable initializations.  */
@@ -6127,7 +6128,10 @@  main (int argc, char **argv)
   if (argv != old_argv)
     at_file_supplied = true;
 
-  prune_options (&argc, &argv);
+  decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **,
+						      argv),
+				   CL_DRIVER,
+				   &decoded_options, &decoded_options_count);
 
 #ifdef GCC_DRIVER_HOST_INITIALIZATION
   /* Perform host dependent initialization when needed.  */
@@ -6217,7 +6221,7 @@  main (int argc, char **argv)
      Make a table of specified input files (infiles, n_infiles).
      Decode switches that are handled locally.  */
 
-  process_command (argc, CONST_CAST2 (const char **, char **, argv));
+  process_command (decoded_options_count, decoded_options);
 
   /* Initialize the vector of specs to just the default.
      This means one element containing 0s, as a terminator.  */
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/opts-common.c gcc-mainline/gcc/opts-common.c
--- gcc-mainline-0trans/gcc/opts-common.c	2010-09-08 06:56:29.000000000 -0700
+++ gcc-mainline/gcc/opts-common.c	2010-09-10 14:47:56.000000000 -0700
@@ -27,6 +27,8 @@  along with GCC; see the file COPYING3.  
 #include "tm.h" /* For SWITCH_TAKES_ARG, WORD_SWITCH_TAKES_ARG and
 		   TARGET_OPTION_TRANSLATE_TABLE.  */
 
+static void prune_options (struct cl_decoded_option **, unsigned int *);
+
 /* Perform a binary search to find which option the command-line INPUT
    matches.  Returns its index in the option array, and
    OPT_SPECIAL_unknown on failure.
@@ -698,10 +700,9 @@  decode_cmdline_options_to_array (unsigne
 
   if (argv_copied)
     free (argv);
-  opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array,
-			  num_decoded_options);
   *decoded_options = opt_array;
   *decoded_options_count = num_decoded_options;
+  prune_options (decoded_options, decoded_options_count);
 }
 
 /* Return true if NEXT_OPT_IDX cancels OPT_IDX.  Return false if the
@@ -724,119 +725,77 @@  cancel_option (int opt_idx, int next_opt
 
 /* Filter out options canceled by the ones after them.  */
 
-void
-prune_options (int *argcp, char ***argvp)
+static void
+prune_options (struct cl_decoded_option **decoded_options,
+	       unsigned int *decoded_options_count)
 {
-  int argc = *argcp;
-  int *options = XNEWVEC (int, argc);
-  /* We will only return this replacement argv if we remove at least
-     one argument, so it does not need to be size (argc + 1) to
-     make room for the terminating NULL because we will always have
-     freed up at least one slot when we end up using it at all.  */
-  char **argv = XNEWVEC (char *, argc);
-  int i, arg_count, need_prune = 0;
+  unsigned int old_decoded_options_count = *decoded_options_count;
+  struct cl_decoded_option *old_decoded_options = *decoded_options;
+  unsigned int new_decoded_options_count;
+  struct cl_decoded_option *new_decoded_options
+    = XNEWVEC (struct cl_decoded_option, old_decoded_options_count);
+  unsigned int i;
   const struct cl_option *option;
-  size_t opt_index;
 
-  /* Scan all arguments.  */
-  for (i = 1; i < argc; i++)
+  /* Remove arguments which are negated by others after them.  */
+  new_decoded_options_count = 0;
+  for (i = 0; i < old_decoded_options_count; i++)
     {
-      int value = 1;
-      const char *opt = (*argvp) [i];
+      unsigned int j, opt_idx, next_opt_idx;
 
-      opt_index = find_opt (opt + 1, -1);
-      if (opt_index == OPT_SPECIAL_unknown
-	  && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
-	  && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
-	{
-	  char *dup;
-
-	  /* Drop the "no-" from negative switches.  */
-	  size_t len = strlen (opt) - 3;
-
-	  dup = XNEWVEC (char, len + 1);
-	  dup[0] = '-';
-	  dup[1] = opt[1];
-	  memcpy (dup + 2, opt + 5, len - 2 + 1);
-	  opt = dup;
-	  value = 0;
-	  opt_index = find_opt (opt + 1, -1);
-	  free (dup);
-	}
+      if (old_decoded_options[i].errors & ~CL_ERR_WRONG_LANG)
+	goto keep;
 
-      if (opt_index == OPT_SPECIAL_unknown)
+      opt_idx = old_decoded_options[i].opt_index;
+      switch (opt_idx)
 	{
-cont:
-	  options [i] = 0;
-	  continue;
-	}
-
-      option = &cl_options[opt_index];
-      if (option->neg_index < 0)
-	goto cont;
-
-      /* Skip joined switches.  */
-      if ((option->flags & CL_JOINED))
-	goto cont;
-
-      /* Reject negative form of switches that don't take negatives as
-	 unrecognized.  */
-      if (!value && (option->flags & CL_REJECT_NEGATIVE))
-	goto cont;
-
-      options [i] = (int) opt_index;
-      need_prune |= options [i];
-    }
+	case OPT_SPECIAL_unknown:
+	case OPT_SPECIAL_ignore:
+	case OPT_SPECIAL_program_name:
+	case OPT_SPECIAL_input_file:
+	  goto keep;
+
+	default:
+	  gcc_assert (opt_idx < cl_options_count);
+	  option = &cl_options[opt_idx];
+	  if (option->neg_index < 0)
+	    goto keep;
+
+	  /* Skip joined switches.  */
+	  if ((option->flags & CL_JOINED))
+	    goto keep;
 
-  if (!need_prune)
-    goto done;
-
-  /* Remove arguments which are negated by others after them.  */
-  argv [0] = (*argvp) [0];
-  arg_count = 1;
-  for (i = 1; i < argc; i++)
-    {
-      int j, opt_idx;
-
-      opt_idx = options [i];
-      if (opt_idx)
-	{
-	  int next_opt_idx;
-	  for (j = i + 1; j < argc; j++)
+	  for (j = i + 1; j < old_decoded_options_count; j++)
 	    {
-	      next_opt_idx = options [j];
-	      if (next_opt_idx
-		  && cancel_option (opt_idx, next_opt_idx,
-				    next_opt_idx))
+	      if (old_decoded_options[j].errors & ~CL_ERR_WRONG_LANG)
+		continue;
+	      next_opt_idx = old_decoded_options[j].opt_index;
+	      if (next_opt_idx >= cl_options_count)
+		continue;
+	      if (cl_options[next_opt_idx].neg_index < 0)
+		continue;
+	      if ((cl_options[next_opt_idx].flags & CL_JOINED))
+		  continue;
+	      if (cancel_option (opt_idx, next_opt_idx, next_opt_idx))
 		break;
 	    }
-	}
-      else
-	goto keep;
-
-      if (j == argc)
-	{
+	  if (j == old_decoded_options_count)
+	    {
 keep:
-	  argv [arg_count] = (*argvp) [i];
-	  arg_count++;
+	      new_decoded_options[new_decoded_options_count]
+		= old_decoded_options[i];
+	      new_decoded_options_count++;
+	    }
+	  break;
 	}
     }
 
-  if (arg_count != argc)
-    {
-      *argcp = arg_count;
-      *argvp = argv;
-      /* Add NULL-termination.  Guaranteed not to overflow because
-	 arg_count here can only be less than argc.  */
-      argv[arg_count] = 0;
-    }
-  else
-    {
-done:
-      free (argv);
-    }
-
-  free (options);
+  free (old_decoded_options);
+  new_decoded_options = XRESIZEVEC (struct cl_decoded_option,
+				    new_decoded_options,
+				    new_decoded_options_count);
+  *decoded_options = new_decoded_options;
+  *decoded_options_count = new_decoded_options_count;
 }
 
 /* Handle option DECODED for the language indicated by LANG_MASK,
diff -rupN --exclude=.svn gcc-mainline-0trans/gcc/opts.h gcc-mainline/gcc/opts.h
--- gcc-mainline-0trans/gcc/opts.h	2010-09-03 08:51:25.000000000 -0700
+++ gcc-mainline/gcc/opts.h	2010-09-10 12:56:10.000000000 -0700
@@ -206,7 +206,6 @@  extern void decode_cmdline_options_to_ar
 					     unsigned int lang_mask,
 					     struct cl_decoded_option **decoded_options,
 					     unsigned int *decoded_options_count);
-extern void prune_options (int *argcp, char ***argvp);
 extern void decode_options (unsigned int argc, const char **argv,
 			    struct cl_decoded_option **decoded_options,
 			    unsigned int *decoded_options_count);