diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/Makefile.in gcc-mainline/gcc/Makefile.in
--- gcc-mainline-opt3/gcc/Makefile.in	2010-06-22 15:24:00.000000000 -0700
+++ gcc-mainline/gcc/Makefile.in	2010-06-23 08:44:22.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 $(DIAGNOSTIC_H)
+   coretypes.h intl.h $(DIAGNOSTIC_H) $(TM_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-opt3/gcc/ada/gcc-interface/misc.c gcc-mainline/gcc/ada/gcc-interface/misc.c
--- gcc-mainline-opt3/gcc/ada/gcc-interface/misc.c	2010-06-22 16:02:04.000000000 -0700
+++ gcc-mainline/gcc/ada/gcc-interface/misc.c	2010-06-23 07:46:46.000000000 -0700
@@ -303,8 +303,13 @@ gnat_init_options (unsigned int decoded_
   save_argc = 0;
   for (i = 0; i < decoded_options_count; i++)
     {
+      if (decoded_options[i].errors
+	  || decoded_options[i].opt_index == OPT_SPECIAL_unknown)
+	continue;
+      gcc_assert (decoded_options[i].canonical_option_num_elements >= 1
+		  && decoded_options[i].canonical_option_num_elements <= 2);
       save_argv[save_argc++] = decoded_options[i].canonical_option[0];
-      if (decoded_options[i].canonical_option[1] != NULL)
+      if (decoded_options[i].canonical_option_num_elements >= 2)
 	save_argv[save_argc++] = decoded_options[i].canonical_option[1];
     }
   save_argv[save_argc] = NULL;
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/config/darwin-driver.c gcc-mainline/gcc/config/darwin-driver.c
--- gcc-mainline-opt3/gcc/config/darwin-driver.c	2010-06-04 06:35:13.000000000 -0700
+++ gcc-mainline/gcc/config/darwin-driver.c	2010-06-23 08:24:32.000000000 -0700
@@ -27,14 +27,6 @@ along with GCC; see the file COPYING3.  
 #include <sys/sysctl.h>
 #include "xregex.h"
 
-#ifndef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
-#endif
-
-#ifndef WORD_SWITCH_TAKES_ARG
-#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
-#endif
-
 /* When running on a Darwin system and using that system's headers and
    libraries, default the -mmacosx-version-min flag to be the version
    of the system on which the compiler is running.  */
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/cppspec.c gcc-mainline/gcc/cppspec.c
--- gcc-mainline-opt3/gcc/cppspec.c	2010-06-04 06:40:58.000000000 -0700
+++ gcc-mainline/gcc/cppspec.c	2010-06-23 08:24:05.000000000 -0700
@@ -30,14 +30,6 @@ along with GCC; see the file COPYING3.  
    assume the user knows what they're doing.  If no explicit input is
    mentioned, it will read stdin.  */
 
-#ifndef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
-#endif
-
-#ifndef WORD_SWITCH_TAKES_ARG
-#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
-#endif
-
 /* Suffixes for known sorts of input files.  Note that we do not list
    files which are normally considered to have been preprocessed already,
    since the user's expectation is that `cpp' always preprocesses.  */
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/defaults.h gcc-mainline/gcc/defaults.h
--- gcc-mainline-opt3/gcc/defaults.h	2010-06-11 02:16:45.000000000 -0700
+++ gcc-mainline/gcc/defaults.h	2010-06-23 08:24:12.000000000 -0700
@@ -32,6 +32,38 @@ see the files COPYING3 and COPYING.RUNTI
 #define GET_ENVIRONMENT(VALUE, NAME) do { (VALUE) = getenv (NAME); } while (0)
 #endif
 
+/* This defines which switch letters take arguments.  */
+
+#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+  ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
+   || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
+   || (CHAR) == 'I' || (CHAR) == 'J' || (CHAR) == 'm' \
+   || (CHAR) == 'x' || (CHAR) == 'L' || (CHAR) == 'A' \
+   || (CHAR) == 'B' )
+
+/* This defines which multi-letter switches take arguments.  */
+
+#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)		\
+ (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")	\
+  || !strcmp (STR, "Tbss") || !strcmp (STR, "include")	\
+  || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
+  || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
+  || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
+  || !strcmp (STR, "iquote") || !strcmp (STR, "isystem") \
+  || !strcmp (STR, "isysroot") \
+  || !strcmp (STR, "-param") || !strcmp (STR, "specs") \
+  || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ") \
+  || !strcmp (STR, "fintrinsic-modules-path") \
+  || !strcmp (STR, "dumpbase") || !strcmp (STR, "dumpdir"))
+
+#ifndef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG (CHAR)
+#endif
+
+#ifndef WORD_SWITCH_TAKES_ARG
+#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
+#endif
+
 /* Store in OUTPUT a string (made with alloca) containing an
    assembler-name for a local static variable or function named NAME.
    LABELNO is an integer which is different for each call.  */
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/fortran/gfortranspec.c gcc-mainline/gcc/fortran/gfortranspec.c
--- gcc-mainline-opt3/gcc/fortran/gfortranspec.c	2010-06-16 09:07:30.000000000 -0700
+++ gcc-mainline/gcc/fortran/gfortranspec.c	2010-06-23 08:25:11.000000000 -0700
@@ -113,22 +113,6 @@ static void append_arg (const char *);
 static int g77_newargc;
 static const char **g77_newargv;
 
-/* --- This comes from gcc.c (2.8.1) verbatim: */
-
-/* This defines which switch letters take arguments.  */
-
-#ifndef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
-#endif
-
-/* This defines which multi-letter switches take arguments.  */
-
-#ifndef WORD_SWITCH_TAKES_ARG
-#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
-#endif
-
-/* --- End of verbatim.  */
-
 /* Assumes text[0] == '-'.  Returns number of argv items that belong to
    (and follow) this one, an option id for options important to the
    caller, and a pointer to the first char of the arg, if embedded (else
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/gcc.c gcc-mainline/gcc/gcc.c
--- gcc-mainline-opt3/gcc/gcc.c	2010-06-07 02:48:58.000000000 -0700
+++ gcc-mainline/gcc/gcc.c	2010-06-23 08:22:19.000000000 -0700
@@ -975,13 +975,6 @@ struct user_specs
 
 static struct user_specs *user_specs_head, *user_specs_tail;
 
-#ifndef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
-#endif
-
-#ifndef WORD_SWITCH_TAKES_ARG
-#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
-#endif
 
 #ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
 /* This defines which switches stop a full compilation.  */
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/gcc.h gcc-mainline/gcc/gcc.h
--- gcc-mainline-opt3/gcc/gcc.h	2010-05-28 12:31:35.000000000 -0700
+++ gcc-mainline/gcc/gcc.h	2010-06-23 08:21:07.000000000 -0700
@@ -32,31 +32,6 @@ struct spec_function
   const char *(*func) (int, const char **);
 };
 
-/* This defines which switch letters take arguments.  */
-
-#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
-  ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
-   || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
-   || (CHAR) == 'I' || (CHAR) == 'J' || (CHAR) == 'm' \
-   || (CHAR) == 'x' || (CHAR) == 'L' || (CHAR) == 'A' \
-   || (CHAR) == 'B' )
-
-/* This defines which multi-letter switches take arguments.  */
-
-#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)		\
- (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")	\
-  || !strcmp (STR, "Tbss") || !strcmp (STR, "include")	\
-  || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
-  || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
-  || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
-  || !strcmp (STR, "iquote") || !strcmp (STR, "isystem") \
-  || !strcmp (STR, "isysroot") \
-  || !strcmp (STR, "-param") || !strcmp (STR, "specs") \
-  || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ") \
-  || !strcmp (STR, "fintrinsic-modules-path") \
-  || !strcmp (STR, "dumpbase") || !strcmp (STR, "dumpdir"))
-
-
 /* These are exported by gcc.c.  */
 extern int do_spec (const char *);
 extern void record_temp_file (const char *, int, int);
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/opts-common.c gcc-mainline/gcc/opts-common.c
--- gcc-mainline-opt3/gcc/opts-common.c	2010-06-22 15:23:48.000000000 -0700
+++ gcc-mainline/gcc/opts-common.c	2010-06-23 11:44:40.000000000 -0700
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  
 #include "opts.h"
 #include "options.h"
 #include "diagnostic.h"
+#include "tm.h" /* For SWITCH_TAKES_ARG and WORD_SWITCH_TAKES_ARG.  */
 
 /* Perform a binary search to find which option the command-line INPUT
    matches.  Returns its index in the option array, and
@@ -138,7 +139,9 @@ decode_cmdline_option (const char **argv
   const char *opt, *arg = 0;
   char *dup = 0;
   int value = 1;
-  unsigned int result = 1;
+  unsigned int result = 1, i;
+  size_t total_len;
+  char *p;
   const struct cl_option *option;
   int errors = 0;
 
@@ -242,22 +245,54 @@ decode_cmdline_option (const char **argv
   decoded->arg = arg;
   decoded->value = value;
   decoded->errors = errors;
-  switch (result)
+
+  if (opt_index == OPT_SPECIAL_unknown)
     {
-    case 1:
-      decoded->orig_option_with_args_text = argv[0];
-      decoded->canonical_option[0] = argv[0];
-      decoded->canonical_option[1] = NULL;
-      break;
-    case 2:
-      decoded->orig_option_with_args_text = concat (argv[0], " ",
-						    argv[1], NULL);
-      decoded->canonical_option[0] = argv[0];
-      decoded->canonical_option[1] = argv[1];
-      break;
-    default:
-      gcc_unreachable ();
+      /* Skip the correct number of arguments for options handled
+	 through specs.  */
+      const char *popt = argv[0] + 1;
+      int c = *popt;
+
+      gcc_assert (result == 1);
+      if (SWITCH_TAKES_ARG (c) > (popt[1] != 0))
+	result += SWITCH_TAKES_ARG (c) - (popt[1] != 0);
+      else if (WORD_SWITCH_TAKES_ARG (popt))
+	result += WORD_SWITCH_TAKES_ARG (popt);
+      if (result > 1)
+	for (i = 1; i < result; i++)
+	  if (argv[i] == NULL)
+	    {
+	      result = i;
+	      break;
+	    }
     }
+
+  gcc_assert (result >= 1 && result <= ARRAY_SIZE (decoded->canonical_option));
+  decoded->canonical_option_num_elements = result;
+  total_len = 0;
+  for (i = 0; i < ARRAY_SIZE (decoded->canonical_option); i++)
+    {
+      if (i < result)
+	{
+	  decoded->canonical_option[i] = argv[i];
+	  total_len += strlen (argv[i]) + 1;
+	}
+      else
+	decoded->canonical_option[i] = NULL;
+    }
+  decoded->orig_option_with_args_text = p = XNEWVEC (char, total_len);
+  for (i = 0; i < result; i++)
+    {
+      size_t len = strlen (argv[i]);
+
+      memcpy (p, argv[i], len);
+      p += len;
+      if (i == result - 1)
+	*p++ = 0;
+      else
+	*p++ = ' ';
+    }
+
   return result;
 }
 
@@ -284,8 +319,11 @@ decode_cmdline_options_to_array (unsigne
   opt_array[0].opt_index = OPT_SPECIAL_program_name;
   opt_array[0].arg = argv[0];
   opt_array[0].orig_option_with_args_text = argv[0];
+  opt_array[0].canonical_option_num_elements = 1;
   opt_array[0].canonical_option[0] = argv[0];
   opt_array[0].canonical_option[1] = NULL;
+  opt_array[0].canonical_option[2] = NULL;
+  opt_array[0].canonical_option[3] = NULL;
   opt_array[0].value = 1;
   opt_array[0].errors = 0;
   num_decoded_options = 1;
@@ -300,8 +338,11 @@ decode_cmdline_options_to_array (unsigne
 	  opt_array[num_decoded_options].opt_index = OPT_SPECIAL_input_file;
 	  opt_array[num_decoded_options].arg = opt;
 	  opt_array[num_decoded_options].orig_option_with_args_text = opt;
+	  opt_array[num_decoded_options].canonical_option_num_elements = 1;
 	  opt_array[num_decoded_options].canonical_option[0] = opt;
 	  opt_array[num_decoded_options].canonical_option[1] = NULL;
+	  opt_array[num_decoded_options].canonical_option[2] = NULL;
+	  opt_array[num_decoded_options].canonical_option[3] = NULL;
 	  opt_array[num_decoded_options].value = 1;
 	  opt_array[num_decoded_options].errors = 0;
 	  num_decoded_options++;
diff -rupN --exclude=.svn gcc-mainline-opt3/gcc/opts.h gcc-mainline/gcc/opts.h
--- gcc-mainline-opt3/gcc/opts.h	2010-06-22 15:15:44.000000000 -0700
+++ gcc-mainline/gcc/opts.h	2010-06-23 07:30:21.000000000 -0700
@@ -121,10 +121,12 @@ struct cl_decoded_option
   /* The canonical form of the option and its argument, for when it is
      necessary to reconstruct argv elements (in particular, for
      processing specs and passing options to subprocesses from the
-     driver).  The first element of this array is non-NULL; the second
-     is NULL if the canonical form uses only one argv element,
-     non-NULL otherwise.  */
-  const char *canonical_option[2];
+     driver).  */
+  const char *canonical_option[4];
+
+  /* The number of elements in the canonical form of the option and
+     arguments; always at least 1.  */
+  size_t canonical_option_num_elements;
 
   /* For a boolean option, 1 for the true case and 0 for the "no-"
      case.  For an unsigned integer option, the value of the
