]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/gcc.c
Use -z ignore instead of --as-needed on Solaris
[thirdparty/gcc.git] / gcc / gcc.c
index ec35ed01f6dcffb3115256a469827a8ae7844eab..27072f007743429a6b8f121408af5d00b182d18e 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,8 +1,5 @@
 /* Compiler driver program that can handle many languages.
-   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2013 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -43,7 +40,9 @@ compilation is specified by a string called a "spec".  */
 #include "diagnostic.h"
 #include "flags.h"
 #include "opts.h"
+#include "params.h"
 #include "vec.h"
+#include "filenames.h"
 
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -188,8 +187,8 @@ static void init_spec (void);
 static void store_arg (const char *, int, int);
 static void insert_wrapper (const char *);
 static char *load_specs (const char *);
-static void read_specs (const char *, int);
-static void set_spec (const char *, const char *);
+static void read_specs (const char *, bool, bool);
+static void set_spec (const char *, const char *, bool);
 static struct compiler *lookup_compiler (const char *, size_t, const char *);
 static char *build_search_list (const struct path_prefix *, const char *,
                                bool, bool);
@@ -225,9 +224,9 @@ static void do_option_spec (const char *, const char *);
 static void do_self_spec (const char *);
 static const char *find_file (const char *);
 static int is_directory (const char *, bool);
-static const char *validate_switches (const char *);
+static const char *validate_switches (const char *, bool);
 static void validate_all_switches (void);
-static inline void validate_switches_from_spec (const char *);
+static inline void validate_switches_from_spec (const char *, bool);
 static void give_switch (int, int);
 static int used_arg (const char *, int);
 static int default_arg (const char *, int);
@@ -265,6 +264,8 @@ static const char *compare_debug_dump_opt_spec_function (int, const char **);
 static const char *compare_debug_self_opt_spec_function (int, const char **);
 static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
 static const char *pass_through_libs_spec_func (int, const char **);
+static const char *replace_extension_spec_func (int, const char **);
+static char *convert_white_space (char *);
 \f
 /* The Specs Language
 
@@ -375,6 +376,7 @@ or with constant text in a single argument.
        If multilib_dir is set, extra entries are generated with it affixed.
  %l     process LINK_SPEC as a spec.
  %L     process LIB_SPEC as a spec.
+ %M     Output multilib_os_dir.
  %G     process LIBGCC_SPEC as a spec.
  %R     Output the concatenation of target_system_root and
         target_sysroot_suffix.
@@ -436,7 +438,6 @@ or with constant text in a single argument.
           This may be combined with '.', '!', ',', '|', and '*' as above.
 
  %(Spec) processes a specification defined in a specs file as *Spec:
- %[Spec] as above, but put __ around -D arguments
 
 The conditional text X in a %{S:X} or similar construct may contain
 other nested % constructs or spaces, or even newlines.  They are
@@ -445,7 +446,7 @@ ignored.  White space may also appear anywhere on the left side of the
 colon in these constructs, except between . or * and the corresponding
 word.
 
-The -O, -f, -m, and -W switches are handled specifically in these
+The -O, -f, -g, -m, and -W switches are handled specifically in these
 constructs.  If another value of -O or the negated form of a -f, -m, or
 -W switch is found later in the command line, the earlier switch
 value is ignored, except with {S*} where S is just one letter; this
@@ -478,7 +479,14 @@ proper position among the other output files.  */
 /* config.h can define ASM_FINAL_SPEC to run a post processor after
    the assembler has run.  */
 #ifndef ASM_FINAL_SPEC
-#define ASM_FINAL_SPEC ""
+#define ASM_FINAL_SPEC \
+  "%{gsplit-dwarf: \n\
+       objcopy --extract-dwo \
+        %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
+        %{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo} \n\
+       objcopy --strip-dwo \
+        %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
+    }"
 #endif
 
 /* config.h can define CPP_SPEC to provide extra args to the C preprocessor
@@ -516,7 +524,7 @@ proper position among the other output files.  */
 /* XXX: should exactly match hooks provided by libmudflap.a */
 #define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
  --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
- --wrap=mmap --wrap=munmap --wrap=alloca\
+ --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca\
 } %{fmudflapth: --wrap=pthread_create\
 }} %{fmudflap|fmudflapth: --wrap=main}"
 #endif
@@ -534,6 +542,50 @@ proper position among the other output files.  */
    wrapping.  */
 #define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
 
+#ifndef LIBASAN_SPEC
+#ifdef STATIC_LIBASAN_LIBS
+#define ADD_STATIC_LIBASAN_LIBS \
+  " %{static-libasan:" STATIC_LIBASAN_LIBS "}"
+#else
+#define ADD_STATIC_LIBASAN_LIBS
+#endif
+#ifdef LIBASAN_EARLY_SPEC
+#define LIBASAN_SPEC ADD_STATIC_LIBASAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBASAN_SPEC "%{static-libasan:" LD_STATIC_OPTION \
+                    "} -lasan %{static-libasan:" LD_DYNAMIC_OPTION "}" \
+                    ADD_STATIC_LIBASAN_LIBS
+#else
+#define LIBASAN_SPEC "-lasan" ADD_STATIC_LIBASAN_LIBS
+#endif
+#endif
+
+#ifndef LIBASAN_EARLY_SPEC
+#define LIBASAN_EARLY_SPEC ""
+#endif
+
+#ifndef LIBTSAN_SPEC
+#ifdef STATIC_LIBTSAN_LIBS
+#define ADD_STATIC_LIBTSAN_LIBS \
+  " %{static-libtsan:" STATIC_LIBTSAN_LIBS "}"
+#else
+#define ADD_STATIC_LIBTSAN_LIBS
+#endif
+#ifdef LIBTSAN_EARLY_SPEC
+#define LIBTSAN_SPEC ADD_STATIC_LIBTSAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \
+                    "} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}" \
+                    ADD_STATIC_LIBTSAN_LIBS
+#else
+#define LIBTSAN_SPEC "-ltsan" ADD_STATIC_LIBTSAN_LIBS
+#endif
+#endif
+
+#ifndef LIBTSAN_EARLY_SPEC
+#define LIBTSAN_EARLY_SPEC ""
+#endif
+
 /* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
    included.  */
 #ifndef LIBGCC_SPEC
@@ -575,7 +627,7 @@ proper position among the other output files.  */
      && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
 #  define ASM_DEBUG_SPEC                                               \
       (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG                           \
-       ? "%{!g0:%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}}" ASM_MAP   \
+       ? "%{!g0:%{gdwarf*:--gdwarf2}%{!gdwarf*:%{g*:--gstabs}}}" ASM_MAP       \
        : "%{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
 # else
 #  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
@@ -621,20 +673,53 @@ proper position among the other output files.  */
 # endif
 #endif
 
-/* Conditional to test whether plugin is used or not.
+/* Conditional to test whether the LTO plugin is used or not.
    FIXME: For slim LTO we will need to enable plugin unconditionally.  This
    still cause problems with PLUGIN_LD != LD and when plugin is built but
    not useable.  For GCC 4.6 we don't support slim LTO and thus we can enable
    plugin only when LTO is enabled.  We still honor explicit
-   -fuse-linker-plugin.  */
-#ifdef HAVE_LTO_PLUGIN
+   -fuse-linker-plugin if the linker used understands -plugin.  */
+
+/* The linker has some plugin support.  */
+#if HAVE_LTO_PLUGIN > 0
+/* The linker used has full plugin support, use LTO plugin by default.  */
+#if HAVE_LTO_PLUGIN == 2
 #define PLUGIN_COND "!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin"
 #define PLUGIN_COND_CLOSE "}"
 #else
+/* The linker used has limited plugin support, use LTO plugin with explicit
+   -fuse-linker-plugin.  */
 #define PLUGIN_COND "fuse-linker-plugin"
 #define PLUGIN_COND_CLOSE ""
 #endif
+#define LINK_PLUGIN_SPEC \
+    "%{"PLUGIN_COND": \
+    -plugin %(linker_plugin_file) \
+    -plugin-opt=%(lto_wrapper) \
+    -plugin-opt=-fresolution=%u.res \
+    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
+    }"PLUGIN_COND_CLOSE
+#else
+/* The linker used doesn't support -plugin, reject -fuse-linker-plugin.  */
+#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
+    %e-fuse-linker-plugin is not supported in this configuration}"
+#endif
 
+/* Linker command line options for -fsanitize= early on the command line.  */
+#ifndef SANITIZER_EARLY_SPEC
+#define SANITIZER_EARLY_SPEC "\
+%{!nostdlib:%{!nodefaultlibs:%{fsanitize=address:" LIBASAN_EARLY_SPEC "} \
+    %{fsanitize=thread:" LIBTSAN_EARLY_SPEC "}}}"
+#endif
+
+/* Linker command line options for -fsanitize= late on the command line.  */
+#ifndef SANITIZER_SPEC
+#define SANITIZER_SPEC "\
+%{!nostdlib:%{!nodefaultlibs:%{fsanitize=address:" LIBASAN_SPEC "\
+    %{static:%ecannot specify -static with -fsanitize=address}}\
+    %{fsanitize=thread:" LIBTSAN_SPEC "\
+    %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}}}"
+#endif
 
 /* -u* was put back because both BSD and SysV seem to support it.  */
 /* %{static:} simply prevents an error message if the target machine
@@ -644,24 +729,22 @@ proper position among the other output files.  */
    directories.  */
 /* We pass any -flto flags on to the linker, which is expected
    to understand them.  In practice, this means it had better be collect2.  */
+/* %{e*} includes -export-dynamic; see comment in common.opt.  */
 #ifndef LINK_COMMAND_SPEC
 #define LINK_COMMAND_SPEC "\
 %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
-    %(linker) \
-    %{"PLUGIN_COND": \
-    -plugin %(linker_plugin_file) \
-    -plugin-opt=%(lto_wrapper) \
-    -plugin-opt=-fresolution=%u.res \
-    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
-    }"PLUGIN_COND_CLOSE" \
-    %{flto|flto=*:%<fcompare-debug*} \
+    %(linker) " \
+    LINK_PLUGIN_SPEC \
+   "%{flto|flto=*:%<fcompare-debug*} \
     %{flto} %{flto=*} %l " LINK_PIE_SPEC \
-   "%X %{o*} %{e*} %{N} %{n} %{r}\
+   "%{fuse-ld=*:-fuse-ld=%*}\
+    %X %{o*} %{e*} %{N} %{n} %{r}\
     %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
-    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
+    %{static:} %{L*} %(mfwrap) %(link_libgcc) " SANITIZER_EARLY_SPEC " %o\
     %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+    %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
     %(mflib) " STACK_SPLIT_SPEC "\
-    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
+    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \
     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
     %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}"
 #endif
@@ -687,7 +770,7 @@ proper position among the other output files.  */
 # define SYSROOT_HEADERS_SUFFIX_SPEC ""
 #endif
 
-static const char *asm_debug;
+static const char *asm_debug = ASM_DEBUG_SPEC;
 static const char *cpp_spec = CPP_SPEC;
 static const char *cc1_spec = CC1_SPEC;
 static const char *cc1plus_spec = CC1PLUS_SPEC;
@@ -713,6 +796,7 @@ static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
 static const char *sysroot_spec = SYSROOT_SPEC;
 static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
 static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
+static const char *self_spec = "";
 
 /* Standard options to cpp, cc1, and as, to reduce duplication in specs.
    There should be no need to override these in target dependent files,
@@ -775,7 +859,7 @@ static const char *cc1_options =
  %{coverage:-fprofile-arcs -ftest-coverage}";
 
 static const char *asm_options =
-"%{--target-help:%:print-asm-header()} "
+"%{-target-help:%:print-asm-header()} "
 #if HAVE_GNU_AS
 /* If GNU AS is used, then convert -w (no warnings), -I, and -v
    to the assembler equivalents.  */
@@ -804,6 +888,7 @@ static const char *multilib_select;
 static const char *multilib_matches;
 static const char *multilib_defaults;
 static const char *multilib_exclusions;
+static const char *multilib_reuse;
 
 /* Check whether a particular argument is a default argument.  */
 
@@ -823,9 +908,14 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 #define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
 #endif
 
+/* Likewise for -fgnu-tm.  */
+#ifndef GTM_SELF_SPECS
+#define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
+#endif
+
 static const char *const driver_self_specs[] = {
   "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
-  DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS
+  DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
 };
 
 #ifndef OPTION_DEFAULT_SPECS
@@ -949,7 +1039,7 @@ static const struct compiler default_compilers[] =
                     %W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0},
   {".i", "@cpp-output", 0, 0, 0},
   {"@cpp-output",
-   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
+   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
   {".s", "@assembler", 0, 0, 0},
   {"@assembler",
    "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
@@ -979,23 +1069,21 @@ static const struct compiler default_compilers[] =
 static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
 
 typedef char *char_p; /* For DEF_VEC_P.  */
-DEF_VEC_P(char_p);
-DEF_VEC_ALLOC_P(char_p,heap);
 
 /* A vector of options to give to the linker.
    These options are accumulated by %x,
    and substituted into the linker command with %X.  */
-static VEC(char_p,heap) *linker_options;
+static vec<char_p> linker_options;
 
 /* A vector of options to give to the assembler.
    These options are accumulated by -Wa,
    and substituted into the assembler command with %Y.  */
-static VEC(char_p,heap) *assembler_options;
+static vec<char_p> assembler_options;
 
 /* A vector of options to give to the preprocessor.
    These options are accumulated by -Wp,
    and substituted into the preprocessor command with %Z.  */
-static VEC(char_p,heap) *preprocessor_options;
+static vec<char_p> preprocessor_options;
 \f
 static char *
 skip_whitespace (char *p)
@@ -1131,10 +1219,15 @@ static const char *multilib_dir;
    set_multilib_dir based on the compilation options.  */
 
 static const char *multilib_os_dir;
+
+/* Subdirectory to use for locating libraries in multiarch conventions.  Set by
+   set_multilib_dir based on the compilation options.  */
+
+static const char *multiarch_dir;
 \f
 /* Structure to keep track of the specs that have been defined so far.
-   These are accessed using %(specname) or %[specname] in a compiler
-   or link spec.  */
+   These are accessed using %(specname) in a compiler or link
+   spec.  */
 
 struct spec_list
 {
@@ -1148,11 +1241,12 @@ struct spec_list
   const char **ptr_spec;       /* pointer to the spec itself.  */
   struct spec_list *next;      /* Next spec in linked list.  */
   int name_len;                        /* length of the name */
-  int alloc_p;                 /* whether string was allocated */
+  bool user_p;                 /* whether string come from file spec.  */
+  bool alloc_p;                        /* whether string was allocated */
 };
 
 #define INIT_STATIC_SPEC(NAME,PTR) \
-{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
+  { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false }
 
 /* List of statically defined specs.  */
 static struct spec_list static_specs[] =
@@ -1188,6 +1282,7 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("multilib_matches",                &multilib_matches),
   INIT_STATIC_SPEC ("multilib_exclusions",     &multilib_exclusions),
   INIT_STATIC_SPEC ("multilib_options",                &multilib_options),
+  INIT_STATIC_SPEC ("multilib_reuse",          &multilib_reuse),
   INIT_STATIC_SPEC ("linker",                  &linker_name_spec),
   INIT_STATIC_SPEC ("linker_plugin_file",      &linker_plugin_file_spec),
   INIT_STATIC_SPEC ("lto_wrapper",             &lto_wrapper_spec),
@@ -1200,6 +1295,7 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("sysroot_spec",             &sysroot_spec),
   INIT_STATIC_SPEC ("sysroot_suffix_spec",     &sysroot_suffix_spec),
   INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",        &sysroot_hdrs_suffix_spec),
+  INIT_STATIC_SPEC ("self_spec",               &self_spec),
 };
 
 #ifdef EXTRA_SPECS             /* additional specs needed */
@@ -1237,6 +1333,7 @@ static const struct spec_function static_spec_functions[] =
   { "compare-debug-self-opt",  compare_debug_self_opt_spec_function },
   { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
   { "pass-through-libs",       pass_through_libs_spec_func },
+  { "replace-extension",       replace_extension_spec_func },
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -1264,7 +1361,8 @@ init_gcc_specs (struct obstack *obstack, const char *shared_name,
                "%{!static:%{!static-libgcc:"
 #if USE_LD_AS_NEEDED
                "%{!shared-libgcc:",
-               static_name, " --as-needed ", shared_name, " --no-as-needed"
+               static_name, " " LD_AS_NEEDED_OPTION " ",
+               shared_name, " " LD_NO_AS_NEEDED_OPTION
                "}"
                "%{shared-libgcc:",
                shared_name, "%{!shared: ", static_name, "}"
@@ -1423,7 +1521,8 @@ init_spec (void)
   }
 #endif
 
-#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC
+#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC || \
+    defined LINKER_HASH_STYLE
 # ifdef LINK_BUILDID_SPEC
   /* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before.  */
   obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof(LINK_BUILDID_SPEC) - 1);
@@ -1431,6 +1530,16 @@ init_spec (void)
 # ifdef LINK_EH_SPEC
   /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
   obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
+# endif
+# ifdef LINKER_HASH_STYLE
+  /* Prepend --hash-style=LINKER_HASH_STYLE to whatever link_spec we had
+     before.  */
+  {
+    static const char hash_style[] = "--hash-style=";
+    obstack_grow (&obstack, hash_style, sizeof(hash_style) - 1);
+    obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof(LINKER_HASH_STYLE) - 1);
+    obstack_1grow (&obstack, ' ');
+  }
 # endif
   obstack_grow0 (&obstack, link_spec, strlen (link_spec));
   link_spec = XOBFINISH (&obstack, const char *);
@@ -1444,7 +1553,7 @@ init_spec (void)
    current spec.  */
 
 static void
-set_spec (const char *name, const char *spec)
+set_spec (const char *name, const char *spec, bool user_p)
 {
   struct spec_list *sl;
   const char *old_spec;
@@ -1496,18 +1605,17 @@ set_spec (const char *name, const char *spec)
   if (old_spec && sl->alloc_p)
     free (CONST_CAST(char *, old_spec));
 
-  sl->alloc_p = 1;
+  sl->user_p = user_p;
+  sl->alloc_p = true;
 }
 \f
 /* Accumulate a command (program name and args), and run it.  */
 
 typedef const char *const_char_p; /* For DEF_VEC_P.  */
-DEF_VEC_P(const_char_p);
-DEF_VEC_ALLOC_P(const_char_p,heap);
 
 /* Vector of pointers to arguments in the current line of specifications.  */
 
-static VEC(const_char_p,heap) *argbuf;
+static vec<const_char_p> argbuf;
 
 /* Position in the argbuf vector containing the name of the output file
    (the value associated with the "-o" flag).  */
@@ -1546,7 +1654,7 @@ static int signal_count;
 static void
 alloc_args (void)
 {
-  argbuf = VEC_alloc (const_char_p, heap, 10);
+  argbuf.create (10);
 }
 
 /* Clear out the vector of arguments (after a command is executed).  */
@@ -1554,7 +1662,7 @@ alloc_args (void)
 static void
 clear_args (void)
 {
-  VEC_truncate (const_char_p, argbuf, 0);
+  argbuf.truncate (0);
 }
 
 /* Add one argument to the vector at the end.
@@ -1567,10 +1675,10 @@ clear_args (void)
 static void
 store_arg (const char *arg, int delete_always, int delete_failure)
 {
-  VEC_safe_push (const_char_p, heap, argbuf, arg);
+  argbuf.safe_push (arg);
 
   if (strcmp (arg, "-o") == 0)
-    have_o_argbuf_index = VEC_length (const_char_p, argbuf);
+    have_o_argbuf_index = argbuf.length ();
   if (delete_always || delete_failure)
     {
       const char *p;
@@ -1652,7 +1760,7 @@ load_specs (const char *filename)
    Anything invalid in the file is a fatal error.  */
 
 static void
-read_specs (const char *filename, int main_p)
+read_specs (const char *filename, bool main_p, bool user_p)
 {
   char *buffer;
   char *p;
@@ -1701,7 +1809,7 @@ read_specs (const char *filename, int main_p)
 
              p[-2] = '\0';
              new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
-             read_specs (new_filename ? new_filename : p1, FALSE);
+             read_specs (new_filename ? new_filename : p1, false, user_p);
              continue;
            }
          else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
@@ -1722,7 +1830,7 @@ read_specs (const char *filename, int main_p)
              p[-2] = '\0';
              new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
              if (new_filename)
-               read_specs (new_filename, FALSE);
+               read_specs (new_filename, false, user_p);
              else if (verbose_flag)
                fnotice (stderr, "could not find specs file %s\n", p1);
              continue;
@@ -1799,7 +1907,7 @@ read_specs (const char *filename, int main_p)
 #endif
                }
 
-             set_spec (p2, *(sl->ptr_spec));
+             set_spec (p2, *(sl->ptr_spec), user_p);
              if (sl->alloc_p)
                free (CONST_CAST (char *, *(sl->ptr_spec)));
 
@@ -1865,7 +1973,7 @@ read_specs (const char *filename, int main_p)
          if (! strcmp (suffix, "*link_command"))
            link_command_spec = spec;
          else
-           set_spec (suffix + 1, spec);
+           set_spec (suffix + 1, spec, user_p);
        }
       else
        {
@@ -1935,7 +2043,7 @@ record_temp_file (const char *filename, int always_delete, int fail_delete)
     {
       struct temp_file *temp;
       for (temp = always_delete_queue; temp; temp = temp->next)
-       if (! strcmp (name, temp->name))
+       if (! filename_cmp (name, temp->name))
          goto already1;
 
       temp = XNEW (struct temp_file);
@@ -1950,8 +2058,11 @@ record_temp_file (const char *filename, int always_delete, int fail_delete)
     {
       struct temp_file *temp;
       for (temp = failure_delete_queue; temp; temp = temp->next)
-       if (! strcmp (name, temp->name))
-         goto already2;
+       if (! filename_cmp (name, temp->name))
+         {
+           free (name);
+           goto already2;
+         }
 
       temp = XNEW (struct temp_file);
       temp->next = failure_delete_queue;
@@ -2044,6 +2155,7 @@ for_each_path (const struct path_prefix *paths,
   struct prefix_list *pl;
   const char *multi_dir = NULL;
   const char *multi_os_dir = NULL;
+  const char *multiarch_suffix = NULL;
   const char *multi_suffix;
   const char *just_multi_suffix;
   char *path = NULL;
@@ -2061,11 +2173,14 @@ for_each_path (const struct path_prefix *paths,
     }
   if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
     multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+  if (multiarch_dir)
+    multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
 
   while (1)
     {
       size_t multi_dir_len = 0;
       size_t multi_os_dir_len = 0;
+      size_t multiarch_len = 0;
       size_t suffix_len;
       size_t just_suffix_len;
       size_t len;
@@ -2074,16 +2189,15 @@ for_each_path (const struct path_prefix *paths,
        multi_dir_len = strlen (multi_dir);
       if (multi_os_dir)
        multi_os_dir_len = strlen (multi_os_dir);
+      if (multiarch_suffix)
+       multiarch_len = strlen (multiarch_suffix);
       suffix_len = strlen (multi_suffix);
       just_suffix_len = strlen (just_multi_suffix);
 
       if (path == NULL)
        {
          len = paths->max_len + extra_space + 1;
-         if (suffix_len > multi_os_dir_len)
-           len += suffix_len;
-         else
-           len += multi_os_dir_len;
+         len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
          path = XNEWVEC (char, len);
        }
 
@@ -2112,6 +2226,16 @@ for_each_path (const struct path_prefix *paths,
                break;
            }
 
+         /* Now try the multiarch path.  */
+         if (!skip_multi_dir
+             && !pl->require_machine_suffix && multiarch_dir)
+           {
+             memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+             ret = callback (path, callback_info);
+             if (ret)
+               break;
+           }
+
          /* Now try the base path.  */
          if (!pl->require_machine_suffix
              && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
@@ -2417,9 +2541,20 @@ add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
 
   if (target_system_root)
     {
+      char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
+      size_t sysroot_len = strlen (target_system_root);
+
+      if (sysroot_len > 0
+         && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
+       sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+
       if (target_sysroot_suffix)
-         prefix = concat (target_sysroot_suffix, prefix, NULL);
-      prefix = concat (target_system_root, prefix, NULL);
+       prefix = concat (sysroot_no_trailing_dir_separator,
+                        target_sysroot_suffix, prefix, NULL);
+      else
+       prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
+
+      free (sysroot_no_trailing_dir_separator);
 
       /* We have to override this because GCC's notion of sysroot
         moves along with GCC.  */
@@ -2457,14 +2592,14 @@ execute (void)
   if (wrapper_string)
     {
       string = find_a_file (&exec_prefixes,
-                           VEC_index (const_char_p, argbuf, 0), X_OK, false);
+                           argbuf[0], X_OK, false);
       if (string)
-       VEC_replace (const_char_p, argbuf, 0, string);
+       argbuf[0] = string;
       insert_wrapper (wrapper_string);
     }
 
   /* Count # of piped commands.  */
-  for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++)
+  for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
     if (strcmp (arg, "|") == 0)
       n_commands++;
 
@@ -2475,10 +2610,10 @@ execute (void)
      and record info about each one.
      Also search for the programs that are to be run.  */
 
-  VEC_safe_push (const_char_p, heap, argbuf, 0);
+  argbuf.safe_push (0);
 
-  commands[0].prog = VEC_index (const_char_p, argbuf, 0); /* first command.  */
-  commands[0].argv = VEC_address (const_char_p, argbuf);
+  commands[0].prog = argbuf[0]; /* first command.  */
+  commands[0].argv = argbuf.address ();
 
   if (!wrapper_string)
     {
@@ -2486,17 +2621,17 @@ execute (void)
       commands[0].argv[0] = (string) ? string : commands[0].argv[0];
     }
 
-  for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++)
+  for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
     if (arg && strcmp (arg, "|") == 0)
       {                                /* each command.  */
 #if defined (__MSDOS__) || defined (OS2) || defined (VMS)
        fatal_error ("-pipe not supported");
 #endif
-       VEC_replace (const_char_p, argbuf, i, 0); /* Termination of
+       argbuf[i] = 0; /* Termination of
                                                     command args.  */
-       commands[n_commands].prog = VEC_index (const_char_p, argbuf, i + 1);
+       commands[n_commands].prog = argbuf[i + 1];
        commands[n_commands].argv
-         = &(VEC_address (const_char_p, argbuf))[i + 1];
+         = &(argbuf.address ())[i + 1];
        string = find_a_file (&exec_prefixes, commands[n_commands].prog,
                              X_OK, false);
        if (string)
@@ -2537,13 +2672,20 @@ execute (void)
                        }
                      fputc ('"', stderr);
                    }
+                 /* If it's empty, print "".  */
+                 else if (!**j)
+                   fprintf (stderr, " \"\"");
                  else
                    fprintf (stderr, " %s", *j);
                }
            }
          else
            for (j = commands[i].argv; *j; j++)
-             fprintf (stderr, " %s", *j);
+             /* If it's empty, print "".  */
+             if (!**j)
+               fprintf (stderr, " \"\"");
+             else
+               fprintf (stderr, " %s", *j);
 
          /* Print a pipe symbol after all but the last command.  */
          if (i + 1 != n_commands)
@@ -2770,8 +2912,9 @@ struct switchstr
   const char *part1;
   const char **args;
   unsigned int live_cond;
-  unsigned char validated;
-  unsigned char ordering;
+  bool known;
+  bool validated;
+  bool ordering;
 };
 
 static struct switchstr *switches;
@@ -2909,7 +3052,7 @@ display_help (void)
   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
   fputs (_("  --help                   Display this information\n"), stdout);
   fputs (_("  --target-help            Display target specific command line options\n"), stdout);
-  fputs (_("  --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
+  fputs (_("  --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
   fputs (_("                           Display specific types of command line options\n"), stdout);
   if (! verbose_flag)
     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
@@ -2921,6 +3064,9 @@ display_help (void)
   fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
   fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
   fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
+  fputs (_("\
+  -print-multiarch         Display the target's normalized GNU triplet, used as\n\
+                           a component in the library path\n"), stdout);
   fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
   fputs (_("\
   -print-multi-lib         Display the mapping between command line options and\n\
@@ -2953,6 +3099,8 @@ display_help (void)
   fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
   fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
   fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
+  fputs (_("  -pie                     Create a position independent executable\n"), stdout);
+  fputs (_("  -shared                  Create a shared library\n"), stdout);
   fputs (_("\
   -x <language>            Specify the language of the following input files\n\
                            Permissible languages include: c c++ assembler none\n\
@@ -2973,20 +3121,19 @@ display_help (void)
 static void
 add_preprocessor_option (const char *option, int len)
 {
-  VEC_safe_push (char_p, heap, preprocessor_options,
-                save_string (option, len));
+  preprocessor_options.safe_push (save_string (option, len));
 }
 
 static void
 add_assembler_option (const char *option, int len)
 {
-  VEC_safe_push (char_p, heap, assembler_options, save_string (option, len));
+  assembler_options.safe_push (save_string (option, len));
 }
 
 static void
 add_linker_option (const char *option, int len)
 {
-  VEC_safe_push (char_p, heap, linker_options, save_string (option, len));
+  linker_options.safe_push (save_string (option, len));
 }
 \f
 /* Allocate space for an input file in infiles.  */
@@ -3035,11 +3182,11 @@ alloc_switch (void)
 }
 
 /* Save an option OPT with N_ARGS arguments in array ARGS, marking it
-   as validated if VALIDATED.  */
+   as validated if VALIDATED and KNOWN if it is an internal switch.  */
 
 static void
 save_switch (const char *opt, size_t n_args, const char *const *args,
-            bool validated)
+            bool validated, bool known)
 {
   alloc_switch ();
   switches[n_switches].part1 = opt + 1;
@@ -3054,21 +3201,38 @@ save_switch (const char *opt, size_t n_args, const char *const *args,
 
   switches[n_switches].live_cond = 0;
   switches[n_switches].validated = validated;
+  switches[n_switches].known = known;
   switches[n_switches].ordering = 0;
   n_switches++;
 }
 
 /* Handle an option DECODED that is unknown to the option-processing
-   machinery, but may be known to specs.  */
+   machinery.  */
 
 static bool
 driver_unknown_option_callback (const struct cl_decoded_option *decoded)
 {
-  save_switch (decoded->canonical_option[0],
-              decoded->canonical_option_num_elements - 1,
-              &decoded->canonical_option[1], false);
-
-  return false;
+  const char *opt = decoded->arg;
+  if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
+      && !(decoded->errors & CL_ERR_NEGATIVE))
+    {
+      /* Leave unknown -Wno-* options for the compiler proper, to be
+        diagnosed only if there are warnings.  */
+      save_switch (decoded->canonical_option[0],
+                  decoded->canonical_option_num_elements - 1,
+                  &decoded->canonical_option[1], false, true);
+      return false;
+    }
+  if (decoded->opt_index == OPT_SPECIAL_unknown)
+    {
+      /* Give it a chance to define it a a spec file.  */
+      save_switch (decoded->canonical_option[0],
+                  decoded->canonical_option_num_elements - 1,
+                  &decoded->canonical_option[1], false, false);
+      return false;
+    }
+  else
+    return true;
 }
 
 /* Handle an option DECODED that is not marked as CL_DRIVER.
@@ -3085,21 +3249,13 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
      options.  */
   const struct cl_option *option = &cl_options[decoded->opt_index];
 
-  if (option->flags & CL_REJECT_DRIVER)
+  if (option->cl_reject_driver)
     error ("unrecognized command line option %qs",
           decoded->orig_option_with_args_text);
   else
-    driver_unknown_option_callback (decoded);
-}
-
-/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
-   has been successfully handled with a handler for mask MASK.  */
-
-static void
-driver_post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
-                              unsigned int mask ATTRIBUTE_UNUSED)
-{
-  /* Nothing to do here.  */
+    save_switch (decoded->canonical_option[0],
+                decoded->canonical_option_num_elements - 1,
+                &decoded->canonical_option[1], false, true);
 }
 
 static const char *spec_lang = 0;
@@ -3185,6 +3341,7 @@ driver_handle_option (struct gcc_options *opts,
       add_linker_option ("--target-help", 13);
       break;
 
+    case OPT__no_sysroot_suffix:
     case OPT_pass_exit_codes:
     case OPT_print_search_dirs:
     case OPT_print_file_name_:
@@ -3193,6 +3350,7 @@ driver_handle_option (struct gcc_options *opts,
     case OPT_print_multi_directory:
     case OPT_print_sysroot:
     case OPT_print_multi_os_directory:
+    case OPT_print_multiarch:
     case OPT_print_sysroot_headers_suffix:
     case OPT_time:
     case OPT_wrapper:
@@ -3234,7 +3392,7 @@ driver_handle_option (struct gcc_options *opts,
     compare_debug_with_arg:
       gcc_assert (decoded->canonical_option_num_elements == 1);
       gcc_assert (arg != NULL);
-      if (arg)
+      if (*arg)
        compare_debug = 1;
       else
        compare_debug = -1;
@@ -3242,7 +3400,7 @@ driver_handle_option (struct gcc_options *opts,
        compare_debug_opt = NULL;
       else
        compare_debug_opt = arg;
-      save_switch (compare_debug_replacement_opt, 0, NULL, validated);
+      save_switch (compare_debug_replacement_opt, 0, NULL, validated, true);
       return true;
 
     case OPT_Wa_:
@@ -3327,7 +3485,12 @@ driver_handle_option (struct gcc_options *opts,
     case OPT_L:
       /* Similarly, canonicalize -L for linkers that may not accept
         separate arguments.  */
-      save_switch (concat ("-L", arg, NULL), 0, NULL, validated);
+      save_switch (concat ("-L", arg, NULL), 0, NULL, validated, true);
+      return true;
+
+    case OPT_F:
+      /* Likewise -F.  */
+      save_switch (concat ("-F", arg, NULL), 0, NULL, validated, true);
       return true;
 
     case OPT_save_temps:
@@ -3370,7 +3533,7 @@ driver_handle_option (struct gcc_options *opts,
          user_specs_head = user;
        user_specs_tail = user;
       }
-      do_save = false;
+      validated = true;
       break;
 
     case OPT__sysroot_:
@@ -3449,7 +3612,7 @@ driver_handle_option (struct gcc_options *opts,
       save_temps_prefix = xstrdup (arg);
       /* On some systems, ld cannot handle "-o" without a space.  So
         split the option from its argument.  */
-      save_switch ("-o", 1, &arg, validated);
+      save_switch ("-o", 1, &arg, validated, true);
       return true;
 
     case OPT_static_libgcc:
@@ -3472,7 +3635,7 @@ driver_handle_option (struct gcc_options *opts,
   if (do_save)
     save_switch (decoded->canonical_option[0],
                 decoded->canonical_option_num_elements - 1,
-                &decoded->canonical_option[1], validated);
+                &decoded->canonical_option[1], validated, true);
   return true;
 }
 
@@ -3483,10 +3646,13 @@ set_option_handlers (struct cl_option_handlers *handlers)
 {
   handlers->unknown_option_callback = driver_unknown_option_callback;
   handlers->wrong_lang_callback = driver_wrong_lang_callback;
-  handlers->post_handling_callback = driver_post_handling_callback;
-  handlers->num_handlers = 1;
+  handlers->num_handlers = 3;
   handlers->handlers[0].handler = driver_handle_option;
   handlers->handlers[0].mask = CL_DRIVER;
+  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;
 }
 
 /* Create the vector `switches' and its contents.
@@ -3498,7 +3664,7 @@ process_command (unsigned int decoded_options_count,
 {
   const char *temp;
   char *temp1;
-  const char *tooldir_prefix;
+  char *tooldir_prefix, *tooldir_prefix2;
   char *(*get_relative_prefix) (const char *, const char *,
                                const char *) = NULL;
   struct cl_option_handlers handlers;
@@ -3593,9 +3759,9 @@ process_command (unsigned int decoded_options_count,
        {
          temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
          if (IS_DIR_SEPARATOR (*temp)
-             && strncmp (temp + 1, "lib", 3) == 0
+             && filename_ncmp (temp + 1, "lib", 3) == 0
              && IS_DIR_SEPARATOR (temp[4])
-             && strncmp (temp + 5, "gcc", 3) == 0)
+             && filename_ncmp (temp + 5, "gcc", 3) == 0)
            len -= sizeof ("/lib/gcc/") - 1;
        }
 
@@ -3762,7 +3928,7 @@ process_command (unsigned int decoded_options_count,
            }
          else
            fname = xstrdup (arg);
+
           if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
            perror_with_name (fname);
           else
@@ -3847,15 +4013,16 @@ process_command (unsigned int decoded_options_count,
     }
 
   gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
-  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
-                          dir_separator_str, NULL);
+  tooldir_prefix2 = concat (tooldir_base_prefix, spec_machine,
+                           dir_separator_str, NULL);
 
   /* Look for tools relative to the location from which the driver is
      running, or, if that is not available, the configured prefix.  */
   tooldir_prefix
     = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
              spec_machine, dir_separator_str,
-             spec_version, dir_separator_str, tooldir_prefix, NULL);
+             spec_version, dir_separator_str, tooldir_prefix2, NULL);
+  free (tooldir_prefix2);
 
   add_prefix (&exec_prefixes,
              concat (tooldir_prefix, "bin", dir_separator_str, NULL),
@@ -3863,6 +4030,7 @@ process_command (unsigned int decoded_options_count,
   add_prefix (&startfile_prefixes,
              concat (tooldir_prefix, "lib", dir_separator_str, NULL),
              "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
+  free (tooldir_prefix);
 
 #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
   /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
@@ -3888,17 +4056,12 @@ process_command (unsigned int decoded_options_count,
   if (n_infiles == last_language_n_infiles && spec_lang != 0)
     warning (0, "%<-x %s%> after last input file has no effect", spec_lang);
 
+  /* Synthesize -fcompare-debug flag from the GCC_COMPARE_DEBUG
+     environment variable.  */
   if (compare_debug == 2 || compare_debug == 3)
     {
-      alloc_switch ();
-      switches[n_switches].part1 = concat ("fcompare-debug=",
-                                          compare_debug_opt,
-                                          NULL);
-      switches[n_switches].args = 0;
-      switches[n_switches].live_cond = 0;
-      switches[n_switches].validated = 0;
-      switches[n_switches].ordering = 0;
-      n_switches++;
+      const char *opt = concat ("-fcompare-debug=", compare_debug_opt, NULL);
+      save_switch (opt, 0, NULL, false, true);
       compare_debug = 1;
     }
 
@@ -4078,7 +4241,7 @@ insert_wrapper (const char *wrapper)
   int i;
   char *buf = xstrdup (wrapper);
   char *p = buf;
-  unsigned int old_length = VEC_length (const_char_p, argbuf);
+  unsigned int old_length = argbuf.length ();
 
   do
     {
@@ -4088,9 +4251,9 @@ insert_wrapper (const char *wrapper)
     }
   while ((p = strchr (p, ',')) != NULL);
 
-  VEC_safe_grow (const_char_p, heap, argbuf, old_length + n);
-  memmove (VEC_address (const_char_p, argbuf) + n,
-          VEC_address (const_char_p, argbuf),
+  argbuf.safe_grow (old_length + n);
+  memmove (argbuf.address () + n,
+          argbuf.address (),
           old_length * sizeof (const_char_p));
 
   i = 0;
@@ -4102,7 +4265,7 @@ insert_wrapper (const char *wrapper)
           *p = 0;
           p++;
         }
-      VEC_replace (const_char_p, argbuf, i, p);
+      argbuf[i] = p;
       i++;
     }
   while ((p = strchr (p, ',')) != NULL);
@@ -4123,13 +4286,13 @@ do_spec (const char *spec)
      If -pipe, this forces out the last command if it ended in `|'.  */
   if (value == 0)
     {
-      if (VEC_length (const_char_p, argbuf) > 0
-         && !strcmp (VEC_last (const_char_p, argbuf), "|"))
-       VEC_pop (const_char_p, argbuf);
+      if (argbuf.length () > 0
+         && !strcmp (argbuf.last (), "|"))
+       argbuf.pop ();
 
       set_collect_gcc_options ();
 
-      if (VEC_length (const_char_p, argbuf) > 0)
+      if (argbuf.length () > 0)
        value = execute ();
     }
 
@@ -4225,7 +4388,7 @@ do_self_spec (const char *spec)
     if ((switches[i].live_cond & SWITCH_IGNORE))
       switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
 
-  if (VEC_length (const_char_p, argbuf) > 0)
+  if (argbuf.length () > 0)
     {
       const char **argbuf_copy;
       struct cl_decoded_option *decoded_options;
@@ -4236,15 +4399,16 @@ do_self_spec (const char *spec)
       /* Create a copy of argbuf with a dummy argv[0] entry for
         decode_cmdline_options_to_array.  */
       argbuf_copy = XNEWVEC (const char *,
-                            VEC_length (const_char_p, argbuf) + 1);
+                            argbuf.length () + 1);
       argbuf_copy[0] = "";
-      memcpy (argbuf_copy + 1, VEC_address (const_char_p, argbuf),
-             VEC_length (const_char_p, argbuf) * sizeof (const char *));
+      memcpy (argbuf_copy + 1, argbuf.address (),
+             argbuf.length () * sizeof (const char *));
 
-      decode_cmdline_options_to_array (VEC_length (const_char_p, argbuf) + 1,
+      decode_cmdline_options_to_array (argbuf.length () + 1,
                                       argbuf_copy,
                                       CL_DRIVER, &decoded_options,
                                       &decoded_options_count);
+      free (argbuf_copy);
 
       set_option_handlers (&handlers);
 
@@ -4271,7 +4435,7 @@ do_self_spec (const char *spec)
              save_switch (decoded_options[j].canonical_option[0],
                           (decoded_options[j].canonical_option_num_elements
                            - 1),
-                          &decoded_options[j].canonical_option[1], false);
+                          &decoded_options[j].canonical_option[1], false, true);
              break;
 
            default:
@@ -4384,12 +4548,12 @@ compile_input_file_p (struct infile *infile)
 /* Process each member of VEC as a spec.  */
 
 static void
-do_specs_vec (VEC(char_p,heap) *vec)
+do_specs_vec (vec<char_p> vec)
 {
   unsigned ix;
   char *opt;
 
-  FOR_EACH_VEC_ELT (char_p, vec, ix, opt)
+  FOR_EACH_VEC_ELT (vec, ix, opt)
     {
       do_spec_1 (opt, 1, NULL);
       /* Make each accumulated option a separate argument.  */
@@ -4417,6 +4581,10 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
   int i;
   int value;
 
+  /* If it's an empty string argument to a switch, keep it as is.  */
+  if (inswitch && !*p)
+    arg_going = 1;
+
   while ((c = *p++))
     /* If substituting a switch, treat all chars like letters.
        Otherwise, NL, SPC, TAB and % are special.  */
@@ -4425,8 +4593,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
       case '\n':
        end_going_arg ();
 
-       if (VEC_length (const_char_p, argbuf) > 0
-           && !strcmp (VEC_last (const_char_p, argbuf), "|"))
+       if (argbuf.length () > 0
+           && !strcmp (argbuf.last (), "|"))
          {
            /* A `|' before the newline means use a pipe here,
               but only if -pipe was specified.
@@ -4437,12 +4605,12 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                break;
              }
            else
-             VEC_pop (const_char_p, argbuf);
+             argbuf.pop ();
          }
 
        set_collect_gcc_options ();
 
-       if (VEC_length (const_char_p, argbuf) > 0)
+       if (argbuf.length () > 0)
          {
            value = execute ();
            if (value)
@@ -4662,8 +4830,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    memcpy (tmp, save_temps_prefix, save_temps_length);
                    memcpy (tmp + save_temps_length, suffix, suffix_length);
                    tmp[save_temps_length + suffix_length] = '\0';
-                   temp_filename = save_string (tmp,
-                                                temp_filename_length + 1);
+                   temp_filename = save_string (tmp, save_temps_length
+                                                     + suffix_length);
                    obstack_grow (&obstack, temp_filename,
                                  temp_filename_length);
                    arg_going = 1;
@@ -4689,7 +4857,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    tmp[basename_length + suffix_length] = '\0';
                    temp_filename = tmp;
 
-                   if (strcmp (temp_filename, gcc_input_filename) != 0)
+                   if (filename_cmp (temp_filename, gcc_input_filename) != 0)
                      {
 #ifndef HOST_LACKS_INODE_NUMBERS
                        struct stat st_temp;
@@ -4715,7 +4883,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                        /* Just compare canonical pathnames.  */
                        char* input_realname = lrealpath (gcc_input_filename);
                        char* temp_realname = lrealpath (temp_filename);
-                       bool files_differ = strcmp (input_realname, temp_realname);
+                       bool files_differ = filename_cmp (input_realname, temp_realname);
                        free (input_realname);
                        free (temp_realname);
                        if (files_differ)
@@ -4765,8 +4933,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    t->filename_length = temp_filename_length;
                  }
 
-               if (saved_suffix)
-                 free (saved_suffix);
+               free (saved_suffix);
 
                obstack_grow (&obstack, t->filename, t->filename_length);
                delete_this_arg = 1;
@@ -4834,6 +5001,15 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                  do_spec_1 (" ", 0, NULL);
                }
 
+             if (multiarch_dir)
+               {
+                 do_spec_1 ("-imultiarch", 1, NULL);
+                 /* Make this a separate argument.  */
+                 do_spec_1 (" ", 0, NULL);
+                 do_spec_1 (multiarch_dir, 1, NULL);
+                 do_spec_1 (" ", 0, NULL);
+               }
+
              if (gcc_exec_prefix)
                {
                  do_spec_1 ("-iprefix", 1, NULL);
@@ -4938,7 +5114,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
          case 'W':
            {
-             unsigned int cur_index = VEC_length (const_char_p, argbuf);
+             unsigned int cur_index = argbuf.length ();
              /* Handle the {...} following the %W.  */
              if (*p != '{')
                fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p);
@@ -4948,8 +5124,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              end_going_arg ();
              /* If any args were output, mark the last one for deletion
                 on failure.  */
-             if (VEC_length (const_char_p, argbuf) != cur_index)
-               record_temp_file (VEC_last (const_char_p, argbuf), 0, 1);
+             if (argbuf.length () != cur_index)
+               record_temp_file (argbuf.last (), 0, 1);
              break;
            }
 
@@ -4969,7 +5145,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              string = save_string (p1 + 1, p - p1 - 2);
 
              /* See if we already recorded this option.  */
-             FOR_EACH_VEC_ELT (char_p, linker_options, ix, opt)
+             FOR_EACH_VEC_ELT (linker_options, ix, opt)
                if (! strcmp (string, opt))
                  {
                    free (string);
@@ -4978,6 +5154,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
              /* This option is new; add it.  */
              add_linker_option (string, strlen (string));
+             free (string);
            }
            break;
 
@@ -5053,6 +5230,14 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              return value;
            break;
 
+         case 'M':
+           if (multilib_os_dir == NULL)
+             obstack_1grow (&obstack, '.');
+           else
+             obstack_grow (&obstack, multilib_os_dir,
+                           strlen (multilib_os_dir));
+           break;
+
          case 'G':
            value = do_spec_1 (libgcc_spec, 0, NULL);
            if (value != 0)
@@ -5133,7 +5318,11 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    && (have_wildcard || switches[i].part1[len] == '\0'))
                  {
                    switches[i].live_cond |= switch_option;
-                   switches[i].validated = 1;
+                   /* User switch be validated from validate_all_switches.
+                      when the definition is seen from the spec file.
+                      If not defined anywhere, will be rejected.  */
+                   if (switches[i].known)
+                     switches[i].validated = true;
                  }
 
              p += len;
@@ -5143,7 +5332,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
          case '*':
            if (soft_matched_part)
              {
-               do_spec_1 (soft_matched_part, 1, NULL);
+               if (soft_matched_part[0])
+                 do_spec_1 (soft_matched_part, 1, NULL);
                do_spec_1 (" ", 0, NULL);
              }
            else
@@ -5155,11 +5345,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
            /* Process a string found as the value of a spec given by name.
               This feature allows individual machine descriptions
-              to add and use their own specs.
-              %[...] modifies -D options the way %P does;
-              %(...) uses the spec unmodified.  */
-         case '[':
-           warning (0, "use of obsolete %%[ operator in specs");
+              to add and use their own specs.  */
          case '(':
            {
              const char *name = p;
@@ -5168,7 +5354,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
              /* The string after the S/P is the name of a spec that is to be
                 processed.  */
-             while (*p && *p != ')' && *p != ']')
+             while (*p && *p != ')')
                p++;
 
              /* See if it's in the list.  */
@@ -5177,63 +5363,20 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                  {
                    name = *(sl->ptr_spec);
 #ifdef DEBUG_SPECS
-                   fnotice (stderr, "Processing spec %c%s%c, which is '%s'\n",
-                           c, sl->name, (c == '(') ? ')' : ']', name);
+                   fnotice (stderr, "Processing spec (%s), which is '%s'\n",
+                            sl->name, name);
 #endif
                    break;
                  }
 
              if (sl)
                {
-                 if (c == '(')
-                   {
-                     value = do_spec_1 (name, 0, NULL);
-                     if (value != 0)
-                       return value;
-                   }
-                 else
-                   {
-                     char *x = (char *) alloca (strlen (name) * 2 + 1);
-                     char *buf = x;
-                     const char *y = name;
-                     int flag = 0;
-
-                     /* Copy all of NAME into BUF, but put __ after
-                        every -D and at the end of each arg.  */
-                     while (1)
-                       {
-                         if (! strncmp (y, "-D", 2))
-                           {
-                             *x++ = '-';
-                             *x++ = 'D';
-                             *x++ = '_';
-                             *x++ = '_';
-                             y += 2;
-                             flag = 1;
-                             continue;
-                           }
-                         else if (flag
-                                  && (*y == ' ' || *y == '\t' || *y == '='
-                                      || *y == '}' || *y == 0))
-                           {
-                             *x++ = '_';
-                             *x++ = '_';
-                             flag = 0;
-                           }
-                         if (*y == 0)
-                           break;
-                         else
-                           *x++ = *y++;
-                       }
-                     *x = 0;
-
-                     value = do_spec_1 (buf, 0, NULL);
-                     if (value != 0)
-                       return value;
-                   }
+                 value = do_spec_1 (name, 0, NULL);
+                 if (value != 0)
+                   return value;
                }
 
-             /* Discard the closing paren or bracket.  */
+             /* Discard the closing paren.  */
              if (*p)
                p++;
            }
@@ -5287,7 +5430,7 @@ eval_spec_function (const char *func, const char *args)
   const char *funcval;
 
   /* Saved spec processing context.  */
-  VEC(const_char_p,heap) *save_argbuf;
+  vec<const_char_p> save_argbuf;
 
   int save_arg_going;
   int save_delete_this_arg;
@@ -5297,6 +5440,8 @@ eval_spec_function (const char *func, const char *args)
   int save_this_is_linker_script;
   const char *save_suffix_subst;
 
+  int save_growing_size;
+  void *save_growing_value;
 
   sf = lookup_spec_function (func);
   if (sf == NULL)
@@ -5313,6 +5458,18 @@ eval_spec_function (const char *func, const char *args)
   save_input_from_pipe = input_from_pipe;
   save_suffix_subst = suffix_subst;
 
+  /* If we have some object growing now, finalize it so the args and function
+     eval proceed from a cleared context.  This is needed to prevent the first
+     constructed arg from mistakenly including the growing value.  We'll push
+     this value back on the obstack once the function evaluation is done, to
+     restore a consistent processing context for our caller.  This is fine as
+     the address of growing objects isn't guaranteed to remain stable until
+     they are finalized, and we expect this situation to be rare enough for
+     the extra copy not to be an issue.  */
+  save_growing_size = obstack_object_size (&obstack);
+  if (save_growing_size > 0)
+    save_growing_value = obstack_finish (&obstack);
+
   /* Create a new spec processing context, and build the function
      arguments.  */
 
@@ -5323,11 +5480,11 @@ eval_spec_function (const char *func, const char *args)
   /* argbuf_index is an index for the next argument to be inserted, and
      so contains the count of the args already inserted.  */
 
-  funcval = (*sf->func) (VEC_length (const_char_p, argbuf),
-                        VEC_address (const_char_p, argbuf));
+  funcval = (*sf->func) (argbuf.length (),
+                        argbuf.address ());
 
   /* Pop the spec processing context.  */
-  VEC_free (const_char_p, heap, argbuf);
+  argbuf.release ();
   argbuf = save_argbuf;
 
   arg_going = save_arg_going;
@@ -5338,6 +5495,9 @@ eval_spec_function (const char *func, const char *args)
   input_from_pipe = save_input_from_pipe;
   suffix_subst = save_suffix_subst;
 
+  if (save_growing_size > 0)
+    obstack_grow (&obstack, save_growing_value, save_growing_size);
+
   return funcval;
 }
 
@@ -5445,6 +5605,21 @@ switch_matches (const char *atom, const char *end_atom, int starred)
        && check_live_switch (i, plen))
       return true;
 
+    /* Check if a switch with separated form matching the atom.
+       We check -D and -U switches. */
+    else if (switches[i].args != 0)
+      {
+       if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
+           && *switches[i].part1 == atom[0])
+         {
+           if (!strncmp (switches[i].args[0], &atom[1], len - 1)
+               && (starred || (switches[i].part1[1] == '\0'
+                               && switches[i].args[0][len - 1] == '\0'))
+               && check_live_switch (i, (starred ? 1 : -1)))
+             return true;
+         }
+      }
+
   return false;
 }
 
@@ -5729,7 +5904,7 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
    on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
    spec, or -1 if either exact match or %* is used.
 
-   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
+   A -O switch is obsoleted by a later -O switch.  A -f, -g, -m, or -W switch
    whose value does not begin with "no-" is obsoleted by the same value
    with the "no-", similarly for a switch with the "no-" prefix.  */
 
@@ -5760,13 +5935,13 @@ check_live_switch (int switchnum, int prefix_length)
       for (i = switchnum + 1; i < n_switches; i++)
        if (switches[i].part1[0] == 'O')
          {
-           switches[switchnum].validated = 1;
+           switches[switchnum].validated = true;
            switches[switchnum].live_cond = SWITCH_FALSE;
            return 0;
          }
       break;
 
-    case 'W':  case 'f':  case 'm':
+    case 'W':  case 'f':  case 'm': case 'g':
       if (! strncmp (name + 1, "no-", 3))
        {
          /* We have Xno-YYY, search for XYYY.  */
@@ -5774,7 +5949,9 @@ check_live_switch (int switchnum, int prefix_length)
            if (switches[i].part1[0] == name[0]
                && ! strcmp (&switches[i].part1[1], &name[4]))
              {
-               switches[switchnum].validated = 1;
+               /* --specs are validated with the validate_switches mechanism.  */
+               if (switches[switchnum].known)
+                 switches[switchnum].validated = true;
                switches[switchnum].live_cond = SWITCH_FALSE;
                return 0;
              }
@@ -5789,7 +5966,9 @@ check_live_switch (int switchnum, int prefix_length)
                && switches[i].part1[3] == '-'
                && !strcmp (&switches[i].part1[4], &name[1]))
              {
-               switches[switchnum].validated = 1;
+               /* --specs are validated with the validate_switches mechanism.  */
+               if (switches[switchnum].known)
+                 switches[switchnum].validated = true;
                switches[switchnum].live_cond = SWITCH_FALSE;
                return 0;
              }
@@ -5853,7 +6032,7 @@ give_switch (int switchnum, int omit_first_word)
     }
 
   do_spec_1 (" ", 0, NULL);
-  switches[switchnum].validated = 1;
+  switches[switchnum].validated = true;
 }
 \f
 /* Search for a file named NAME trying various prefixes including the
@@ -5893,11 +6072,11 @@ is_directory (const char *path1, bool linker)
   if (linker
       && IS_DIR_SEPARATOR (path[0])
       && ((cp - path == 6
-          && strncmp (path + 1, "lib", 3) == 0)
+          && filename_ncmp (path + 1, "lib", 3) == 0)
          || (cp - path == 10
-             && strncmp (path + 1, "usr", 3) == 0
+             && filename_ncmp (path + 1, "usr", 3) == 0
              && IS_DIR_SEPARATOR (path[4])
-             && strncmp (path + 5, "lib", 3) == 0)))
+             && filename_ncmp (path + 5, "lib", 3) == 0)))
     return 0;
 
   return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
@@ -6087,10 +6266,6 @@ main (int argc, char **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.  */
-  asm_debug = ASM_DEBUG_SPEC;
-
   p = argv[0] + strlen (argv[0]);
   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
     --p;
@@ -6104,24 +6279,29 @@ main (int argc, char **argv)
   if (argv != old_argv)
     at_file_supplied = true;
 
-  global_options = global_options_init;
+  /* Register the language-independent parameters.  */
+  global_init_params ();
+  finish_params ();
+
+  init_options_struct (&global_options, &global_options_set);
 
   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.  */
-  GCC_DRIVER_HOST_INITIALIZATION;
-#endif
-
   /* Unlock the stdio streams.  */
   unlock_std_streams ();
 
   gcc_init_libintl ();
 
   diagnostic_initialize (global_dc, 0);
+
+#ifdef GCC_DRIVER_HOST_INITIALIZATION
+  /* Perform host dependent initialization when needed.  */
+  GCC_DRIVER_HOST_INITIALIZATION;
+#endif
+
   if (atexit (delete_temp_files) != 0)
     fatal_error ("atexit failed");
 
@@ -6143,6 +6323,10 @@ main (int argc, char **argv)
   signal (SIGCHLD, SIG_DFL);
 #endif
 
+  /* Parsing and gimplification sometimes need quite large stack.
+     Increase stack size limits if possible.  */
+  stack_limit_increase (64 * 1024 * 1024);
+
   /* Allocate the argument vector.  */
   alloc_args ();
 
@@ -6175,6 +6359,13 @@ main (int argc, char **argv)
     obstack_1grow (&multilib_obstack, 0);
     multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
 
+    q = multilib_reuse_raw;
+    while ((p = *q++) != (char *) 0)
+      obstack_grow (&multilib_obstack, p, strlen (p));
+
+    obstack_1grow (&multilib_obstack, 0);
+    multilib_reuse = XOBFINISH (&multilib_obstack, const char *);
+
     need_space = FALSE;
     for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
       {
@@ -6217,7 +6408,7 @@ main (int argc, char **argv)
   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
   /* Read the specs file unless it is a default one.  */
   if (specs_file != 0 && strcmp (specs_file, "specs"))
-    read_specs (specs_file, TRUE);
+    read_specs (specs_file, true, false);
   else
     init_spec ();
 
@@ -6230,7 +6421,7 @@ main (int argc, char **argv)
   strcat (specs_file, just_machine_suffix);
   strcat (specs_file, "specs");
   if (access (specs_file, R_OK) == 0)
-    read_specs (specs_file, TRUE);
+    read_specs (specs_file, true, false);
 
   /* Process any configure-time defaults specified for the command line
      options, via OPTION_DEFAULT_SPECS.  */
@@ -6244,48 +6435,6 @@ main (int argc, char **argv)
   for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
     do_self_spec (driver_self_specs[i]);
 
-  if (compare_debug)
-    {
-      enum save_temps save;
-
-      if (!compare_debug_second)
-       {
-         n_switches_debug_check[1] = n_switches;
-         n_switches_alloc_debug_check[1] = n_switches_alloc;
-         switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
-                                            n_switches_alloc);
-
-         do_self_spec ("%:compare-debug-self-opt()");
-         n_switches_debug_check[0] = n_switches;
-         n_switches_alloc_debug_check[0] = n_switches_alloc;
-         switches_debug_check[0] = switches;
-
-         n_switches = n_switches_debug_check[1];
-         n_switches_alloc = n_switches_alloc_debug_check[1];
-         switches = switches_debug_check[1];
-       }
-
-      /* Avoid crash when computing %j in this early.  */
-      save = save_temps_flag;
-      save_temps_flag = SAVE_TEMPS_NONE;
-
-      compare_debug = -compare_debug;
-      do_self_spec ("%:compare-debug-self-opt()");
-
-      save_temps_flag = save;
-
-      if (!compare_debug_second)
-       {
-         n_switches_debug_check[1] = n_switches;
-         n_switches_alloc_debug_check[1] = n_switches_alloc;
-         switches_debug_check[1] = switches;
-         compare_debug = -compare_debug;
-         n_switches = n_switches_debug_check[0];
-         n_switches_alloc = n_switches_debug_check[0];
-         switches = switches_debug_check[0];
-       }
-    }
-
   /* If not cross-compiling, look for executables in the standard
      places.  */
   if (*cross_compile == '0')
@@ -6299,12 +6448,13 @@ main (int argc, char **argv)
 
   /* Process sysroot_suffix_spec.  */
   if (*sysroot_suffix_spec != 0
+      && !no_sysroot_suffix
       && do_spec_2 (sysroot_suffix_spec) == 0)
     {
-      if (VEC_length (const_char_p, argbuf) > 1)
+      if (argbuf.length () > 1)
         error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
-      else if (VEC_length (const_char_p, argbuf) == 1)
-        target_sysroot_suffix = xstrdup (VEC_last (const_char_p, argbuf));
+      else if (argbuf.length () == 1)
+        target_sysroot_suffix = xstrdup (argbuf.last ());
     }
 
 #ifdef HAVE_LD_SYSROOT
@@ -6316,18 +6466,19 @@ main (int argc, char **argv)
     {
       obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
       obstack_grow0 (&obstack, link_spec, strlen (link_spec));
-      set_spec ("link", XOBFINISH (&obstack, const char *));
+      set_spec ("link", XOBFINISH (&obstack, const char *), false);
     }
 #endif
 
   /* Process sysroot_hdrs_suffix_spec.  */
   if (*sysroot_hdrs_suffix_spec != 0
+      && !no_sysroot_suffix
       && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
     {
-      if (VEC_length (const_char_p, argbuf) > 1)
+      if (argbuf.length () > 1)
         error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
-      else if (VEC_length (const_char_p, argbuf) == 1)
-        target_sysroot_hdrs_suffix = xstrdup (VEC_last (const_char_p, argbuf));
+      else if (argbuf.length () == 1)
+        target_sysroot_hdrs_suffix = xstrdup (argbuf.last ());
     }
 
   /* Look for startfiles in the standard places.  */
@@ -6337,7 +6488,7 @@ main (int argc, char **argv)
     {
       const char *arg;
       int ndx;
-      FOR_EACH_VEC_ELT (const_char_p, argbuf, ndx, arg)
+      FOR_EACH_VEC_ELT (argbuf, ndx, arg)
        add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS",
                              PREFIX_PRIORITY_LAST, 0, 1);
     }
@@ -6392,9 +6543,61 @@ main (int argc, char **argv)
     {
       char *filename = find_a_file (&startfile_prefixes, uptr->filename,
                                    R_OK, true);
-      read_specs (filename ? filename : uptr->filename, FALSE);
+      read_specs (filename ? filename : uptr->filename, false, true);
     }
 
+  /* Process any user self specs.  */
+  {
+    struct spec_list *sl;
+    for (sl = specs; sl; sl = sl->next)
+      if (sl->name_len == sizeof "self_spec" - 1
+         && !strcmp (sl->name, "self_spec"))
+       do_self_spec (*sl->ptr_spec);
+  }
+
+  if (compare_debug)
+    {
+      enum save_temps save;
+
+      if (!compare_debug_second)
+       {
+         n_switches_debug_check[1] = n_switches;
+         n_switches_alloc_debug_check[1] = n_switches_alloc;
+         switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
+                                            n_switches_alloc);
+
+         do_self_spec ("%:compare-debug-self-opt()");
+         n_switches_debug_check[0] = n_switches;
+         n_switches_alloc_debug_check[0] = n_switches_alloc;
+         switches_debug_check[0] = switches;
+
+         n_switches = n_switches_debug_check[1];
+         n_switches_alloc = n_switches_alloc_debug_check[1];
+         switches = switches_debug_check[1];
+       }
+
+      /* Avoid crash when computing %j in this early.  */
+      save = save_temps_flag;
+      save_temps_flag = SAVE_TEMPS_NONE;
+
+      compare_debug = -compare_debug;
+      do_self_spec ("%:compare-debug-self-opt()");
+
+      save_temps_flag = save;
+
+      if (!compare_debug_second)
+       {
+         n_switches_debug_check[1] = n_switches;
+         n_switches_alloc_debug_check[1] = n_switches_alloc;
+         switches_debug_check[1] = switches;
+         compare_debug = -compare_debug;
+         n_switches = n_switches_debug_check[0];
+         n_switches_alloc = n_switches_debug_check[0];
+         switches = switches_debug_check[0];
+       }
+    }
+
+
   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
   if (gcc_exec_prefix)
     gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
@@ -6419,9 +6622,14 @@ main (int argc, char **argv)
 
   /* Set up to remember the pathname of the lto wrapper. */
 
-  lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
+  if (have_c)
+    lto_wrapper_file = NULL;
+  else
+    lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
+                                   X_OK, false);
   if (lto_wrapper_file)
     {
+      lto_wrapper_file = convert_white_space (lto_wrapper_file);
       lto_wrapper_spec = lto_wrapper_file;
       obstack_init (&collect_obstack);
       obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
@@ -6431,11 +6639,11 @@ main (int argc, char **argv)
       xputenv (XOBFINISH (&collect_obstack, char *));
     }
 
-  /* Warn about any switches that no pass was interested in.  */
+  /* Reject switches that no pass was interested in.  */
 
   for (i = 0; (int) i < n_switches; i++)
     if (! switches[i].validated)
-      error ("unrecognized option %<-%s%>", switches[i].part1);
+      error ("unrecognized command line option %<-%s%>", switches[i].part1);
 
   /* Obey some of the options.  */
 
@@ -6479,6 +6687,15 @@ main (int argc, char **argv)
       return (0);
     }
 
+  if (print_multiarch)
+    {
+      if (multiarch_dir == NULL)
+       printf ("\n");
+      else
+       printf ("%s\n", multiarch_dir);
+      return (0);
+    }
+
   if (print_sysroot)
     {
       if (target_system_root)
@@ -6539,7 +6756,7 @@ main (int argc, char **argv)
     {
       printf (_("%s %s%s\n"), progname, pkgversion_string,
              version_string);
-      printf ("Copyright %s 2011 Free Software Foundation, Inc.\n",
+      printf ("Copyright %s 2013 Free Software Foundation, Inc.\n",
              _("(C)"));
       fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
@@ -6682,12 +6899,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
            {
              if (compare_debug)
                {
-                 if (debug_check_temp_file[0])
-                   free (debug_check_temp_file[0]);
+                 free (debug_check_temp_file[0]);
                  debug_check_temp_file[0] = NULL;
 
-                 if (debug_check_temp_file[1])
-                   free (debug_check_temp_file[1]);
+                 free (debug_check_temp_file[1]);
                  debug_check_temp_file[1] = NULL;
                }
 
@@ -6719,8 +6934,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                    }
 
                  gcc_assert (debug_check_temp_file[1]
-                             && strcmp (debug_check_temp_file[0],
-                                        debug_check_temp_file[1]));
+                             && filename_cmp (debug_check_temp_file[0],
+                                              debug_check_temp_file[1]));
 
                  if (verbose_flag)
                    inform (0, "comparing final insns dumps");
@@ -6731,12 +6946,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
              if (compare_debug)
                {
-                 if (debug_check_temp_file[0])
-                   free (debug_check_temp_file[0]);
+                 free (debug_check_temp_file[0]);
                  debug_check_temp_file[0] = NULL;
 
-                 if (debug_check_temp_file[1])
-                   free (debug_check_temp_file[1]);
+                 free (debug_check_temp_file[1]);
                  debug_check_temp_file[1] = NULL;
                }
            }
@@ -6797,35 +7010,47 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
   if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
     {
       int tmp = execution_count;
-#ifdef HAVE_LTO_PLUGIN
-      const char *fno_use_linker_plugin = "fno-use-linker-plugin";
+
+      if (! have_c)
+       {
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
+         const char *fno_use_linker_plugin = "fno-use-linker-plugin";
 #else
-      const char *fuse_linker_plugin = "fuse-linker-plugin";
+         const char *fuse_linker_plugin = "fuse-linker-plugin";
+#endif
 #endif
 
-      /* We'll use ld if we can't find collect2.  */
-      if (! strcmp (linker_name_spec, "collect2"))
-       {
-         char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
-         if (s == NULL)
-           linker_name_spec = "ld";
-       }
+         /* We'll use ld if we can't find collect2.  */
+         if (! strcmp (linker_name_spec, "collect2"))
+           {
+             char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
+             if (s == NULL)
+               linker_name_spec = "ld";
+           }
 
-#ifdef HAVE_LTO_PLUGIN
-      if (!switch_matches (fno_use_linker_plugin,
-                          fno_use_linker_plugin + strlen (fno_use_linker_plugin), 0))
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
+         if (!switch_matches (fno_use_linker_plugin,
+                              fno_use_linker_plugin
+                              + strlen (fno_use_linker_plugin), 0))
 #else
-      if (switch_matches (fuse_linker_plugin,
-                         fuse_linker_plugin + strlen (fuse_linker_plugin), 0))
+         if (switch_matches (fuse_linker_plugin,
+                             fuse_linker_plugin
+                             + strlen (fuse_linker_plugin), 0))
 #endif
-       {
-         linker_plugin_file_spec = find_a_file (&exec_prefixes,
-                                                LTOPLUGINSONAME, R_OK,
-                                                false);
-         if (!linker_plugin_file_spec)
-           fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
+           {
+             char *temp_spec = find_a_file (&exec_prefixes,
+                                            LTOPLUGINSONAME, R_OK,
+                                            false);
+             if (!temp_spec)
+               fatal_error ("-fuse-linker-plugin, but %s not found",
+                            LTOPLUGINSONAME);
+             linker_plugin_file_spec = convert_white_space (temp_spec);
+           }
+#endif
+         lto_gcc_spec = argv[0];
        }
-      lto_gcc_spec = argv[0];
 
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
         for collect.  */
@@ -6968,14 +7193,14 @@ perror_with_name (const char *name)
 }
 \f
 static inline void
-validate_switches_from_spec (const char *spec)
+validate_switches_from_spec (const char *spec, bool user)
 {
   const char *p = spec;
   char c;
   while ((c = *p++))
     if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
       /* We have a switch spec.  */
-      p = validate_switches (p + 1);
+      p = validate_switches (p + 1, user);
 }
 
 static void
@@ -6985,20 +7210,20 @@ validate_all_switches (void)
   struct spec_list *spec;
 
   for (comp = compilers; comp->spec; comp++)
-    validate_switches_from_spec (comp->spec);
+    validate_switches_from_spec (comp->spec, false);
 
   /* Look through the linked list of specs read from the specs file.  */
   for (spec = specs; spec; spec = spec->next)
-    validate_switches_from_spec (*spec->ptr_spec);
+    validate_switches_from_spec (*spec->ptr_spec, spec->user_p);
 
-  validate_switches_from_spec (link_command_spec);
+  validate_switches_from_spec (link_command_spec, false);
 }
 
 /* Look at the switch-name that comes after START
    and mark as valid all supplied switches that match it.  */
 
 static const char *
-validate_switches (const char *start)
+validate_switches (const char *start, bool user_spec)
 {
   const char *p = start;
   const char *atom;
@@ -7035,8 +7260,9 @@ next_member:
       /* Mark all matching switches as valid.  */
       for (i = 0; i < n_switches; i++)
        if (!strncmp (switches[i].part1, atom, len)
-           && (starred || switches[i].part1[len] == 0))
-         switches[i].validated = 1;
+           && (starred || switches[i].part1[len] == '\0')
+           && (switches[i].known || user_spec))
+             switches[i].validated = true;
     }
 
   if (*p) p++;
@@ -7051,9 +7277,9 @@ next_member:
            {
              p++;
              if (*p == '{' || *p == '<')
-               p = validate_switches (p+1);
+               p = validate_switches (p+1, user_spec);
              else if (p[0] == 'W' && p[1] == '{')
-               p = validate_switches (p+2);
+               p = validate_switches (p+2, user_spec);
            }
          else
            p++;
@@ -7242,7 +7468,9 @@ default_arg (const char *p, int len)
    options are present, then we will ignore this completely. Passing
    that, gcc will consider each multilib_select in turn using the same
    rules for matching the options. If a match is found, that subdirectory
-   will be used.  */
+   will be used.
+   A subdirectory name is optionally followed by a colon and the corresponding
+   multiarch name.  */
 
 static void
 set_multilib_dir (void)
@@ -7353,6 +7581,12 @@ set_multilib_dir (void)
 
   first = 1;
   p = multilib_select;
+
+  /* Append multilib reuse rules if any.  With those rules, we can reuse
+     one multilib for certain different options sets.  */
+  if (strlen (multilib_reuse) > 0)
+    p = concat (p, multilib_reuse, NULL);
+
   while (*p != '\0')
     {
       /* Ignore newlines.  */
@@ -7369,8 +7603,8 @@ set_multilib_dir (void)
          if (*p == '\0')
            {
            invalid_select:
-             fatal_error ("multilib select %qs is invalid",
-                          multilib_select);
+             fatal_error ("multilib select %qs %qs is invalid",
+                          multilib_select, multilib_reuse);
            }
          ++p;
        }
@@ -7454,10 +7688,25 @@ set_multilib_dir (void)
            q++;
          if (q < end)
            {
-             char *new_multilib_os_dir = XNEWVEC (char, end - q);
-             memcpy (new_multilib_os_dir, q + 1, end - q - 1);
-             new_multilib_os_dir[end - q - 1] = '\0';
-             multilib_os_dir = new_multilib_os_dir;
+             const char *q2 = q + 1, *ml_end = end;
+             char *new_multilib_os_dir;
+
+             while (q2 < end && *q2 != ':')
+               q2++;
+             if (*q2 == ':')
+               ml_end = q2;
+             new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+             memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+             new_multilib_os_dir[ml_end - q - 1] = '\0';
+             multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+
+             if (q2 < end && *q2 == ':')
+               {
+                 char *new_multiarch_dir = XNEWVEC (char, end - q2);
+                 memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+                 new_multiarch_dir[end - q2 - 1] = '\0';
+                 multiarch_dir = new_multiarch_dir;
+               }
              break;
            }
        }
@@ -7517,9 +7766,10 @@ print_multilib_info (void)
        }
 
       /* When --disable-multilib was used but target defines
-        MULTILIB_OSDIRNAMES, entries starting with .: are there just
-        to find multilib_os_dir, so skip them from output.  */
-      if (this_path[0] == '.' && this_path[1] == ':')
+        MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
+         with .:: for multiarch configurations) are there just to find
+         multilib_os_dir, so skip them from output.  */
+      if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
        skip = 1;
 
       /* Check for matches with the multilib_exclusions. We don't bother
@@ -7620,7 +7870,7 @@ print_multilib_info (void)
          /* If this is a duplicate, skip it.  */
          skip = (last_path != 0
                  && (unsigned int) (p - this_path) == last_path_len
-                 && ! strncmp (last_path, this_path, last_path_len));
+                 && ! filename_ncmp (last_path, this_path, last_path_len));
 
          last_path = this_path;
          last_path_len = p - this_path;
@@ -7824,7 +8074,7 @@ replace_outfile_spec_function (int argc, const char **argv)
 
   for (i = 0; i < n_infiles; i++)
     {
-      if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
+      if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
        outfiles[i] = xstrdup (argv[1]);
     }
   return NULL;
@@ -7845,7 +8095,7 @@ remove_outfile_spec_function (int argc, const char **argv)
 
   for (i = 0; i < n_infiles; i++)
     {
-      if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
+      if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
         outfiles[i] = NULL;
     }
   return NULL;
@@ -7983,13 +8233,13 @@ include_spec_function (int argc, const char **argv)
     abort ();
 
   file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
-  read_specs (file ? file : argv[0], FALSE);
+  read_specs (file ? file : argv[0], false, false);
 
   return NULL;
 }
 
 /* %:find-file spec function.  This function replaces its argument by
-    the file found thru find_file, that is the -print-file-name gcc
+    the file found through find_file, that is the -print-file-name gcc
     program option. */
 static const char *
 find_file_spec_function (int argc, const char **argv)
@@ -8005,7 +8255,7 @@ find_file_spec_function (int argc, const char **argv)
 
 
 /* %:find-plugindir spec function.  This function replaces its argument
-    by the -iplugindir=<dir> option.  `dir' is found thru find_file, that
+    by the -iplugindir=<dir> option.  `dir' is found through find_file, that
     is the -print-file-name gcc program option. */
 static const char *
 find_plugindir_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
@@ -8033,12 +8283,22 @@ print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-/* Compute a timestamp to initialize flag_random_seed.  */
+/* Get a random number for -frandom-seed */
 
-static unsigned
-get_local_tick (void)
+static unsigned HOST_WIDE_INT
+get_random_number (void)
 {
-  unsigned ret = 0;
+  unsigned HOST_WIDE_INT ret = 0;
+  int fd; 
+
+  fd = open ("/dev/urandom", O_RDONLY); 
+  if (fd >= 0)
+    {
+      read (fd, &ret, sizeof (HOST_WIDE_INT));
+      close (fd);
+      if (ret)
+        return ret;
+    }
 
   /* Get some more or less random data.  */
 #ifdef HAVE_GETTIMEOFDAY
@@ -8057,7 +8317,7 @@ get_local_tick (void)
   }
 #endif
 
-  return ret;
+  return ret ^ getpid();
 }
 
 /* %:compare-debug-dump-opt spec function.  Save the last argument,
@@ -8068,7 +8328,7 @@ static const char *
 compare_debug_dump_opt_spec_function (int arg,
                                      const char **argv ATTRIBUTE_UNUSED)
 {
-  const char *ret;
+  char *ret;
   char *name;
   int which;
   static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
@@ -8079,20 +8339,20 @@ compare_debug_dump_opt_spec_function (int arg,
   do_spec_2 ("%{fdump-final-insns=*:%*}");
   do_spec_1 (" ", 0, NULL);
 
-  if (VEC_length (const_char_p, argbuf) > 0
-      && strcmp (argv[VEC_length (const_char_p, argbuf) - 1], "."))
+  if (argbuf.length () > 0
+      && strcmp (argv[argbuf.length () - 1], "."))
     {
       if (!compare_debug)
        return NULL;
 
-      name = xstrdup (argv[VEC_length (const_char_p, argbuf) - 1]);
+      name = xstrdup (argv[argbuf.length () - 1]);
       ret = NULL;
     }
   else
     {
       const char *ext = NULL;
 
-      if (VEC_length (const_char_p, argbuf) > 0)
+      if (argbuf.length () > 0)
        {
          do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}");
          ext = ".gkd";
@@ -8104,9 +8364,9 @@ compare_debug_dump_opt_spec_function (int arg,
 
       do_spec_1 (" ", 0, NULL);
 
-      gcc_assert (VEC_length (const_char_p, argbuf) > 0);
+      gcc_assert (argbuf.length () > 0);
 
-      name = concat (VEC_last (const_char_p, argbuf), ext, NULL);
+      name = concat (argbuf.last (), ext, NULL);
 
       ret = concat ("-fdump-final-insns=", name, NULL);
     }
@@ -8116,14 +8376,18 @@ compare_debug_dump_opt_spec_function (int arg,
 
   if (!which)
     {
-      unsigned HOST_WIDE_INT value = get_local_tick () ^ getpid ();
+      unsigned HOST_WIDE_INT value = get_random_number ();
 
       sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
     }
 
   if (*random_seed)
-    ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
-                 ret, NULL);
+    {
+      char *tmp = ret;
+      ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
+                   ret, NULL);
+      free (tmp);
+    }
 
   if (which)
     *random_seed = 0;
@@ -8150,9 +8414,9 @@ compare_debug_self_opt_spec_function (int arg,
   do_spec_2 ("%{c|S:%{o*:%*}}");
   do_spec_1 (" ", 0, NULL);
 
-  if (VEC_length (const_char_p, argbuf) > 0)
+  if (argbuf.length () > 0)
     debug_auxbase_opt = concat ("-auxbase-strip ",
-                               VEC_last (const_char_p, argbuf),
+                               argbuf.last (),
                                NULL);
   else
     debug_auxbase_opt = NULL;
@@ -8248,3 +8512,81 @@ pass_through_libs_spec_func (int argc, const char **argv)
     }
   return prepended;
 }
+
+/* %:replace-extension spec function.  Replaces the extension of the
+   first argument with the second argument.  */
+
+const char *
+replace_extension_spec_func (int argc, const char **argv)
+{
+  char *name;
+  char *p;
+  char *result;
+  int i;
+
+  if (argc != 2)
+    fatal_error ("too few arguments to %%:replace-extension");
+
+  name = xstrdup (argv[0]);
+
+  for (i = strlen(name) - 1; i >= 0; i--)
+    if (IS_DIR_SEPARATOR (name[i]))
+      break;
+
+  p = strrchr (name + i + 1, '.');
+  if (p != NULL)
+      *p = '\0';
+
+  result = concat (name, argv[1], NULL);
+
+  free (name);
+  return result;
+}
+
+/* Insert backslash before spaces in ORIG (usually a file path), to 
+   avoid being broken by spec parser.
+
+   This function is needed as do_spec_1 treats white space (' ' and '\t')
+   as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
+   the file name should be treated as a single argument rather than being
+   broken into multiple. Solution is to insert '\\' before the space in a 
+   file name.
+   
+   This function converts and only converts all occurrence of ' ' 
+   to '\\' + ' ' and '\t' to '\\' + '\t'.  For example:
+   "a b"  -> "a\\ b"
+   "a  b" -> "a\\ \\ b"
+   "a\tb" -> "a\\\tb"
+   "a\\ b" -> "a\\\\ b"
+
+   orig: input null-terminating string that was allocated by xalloc. The
+   memory it points to might be freed in this function. Behavior undefined
+   if ORIG wasn't xalloced or was freed already at entry.
+
+   Return: ORIG if no conversion needed. Otherwise a newly allocated string
+   that was converted from ORIG.  */
+
+static char *
+convert_white_space (char *orig)
+{
+  int len, number_of_space = 0;
+
+  for (len = 0; orig[len]; len++)
+    if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
+
+  if (number_of_space)
+    {
+      char *new_spec = (char *) xmalloc (len + number_of_space + 1);
+      int j, k;
+      for (j = 0, k = 0; j <= len; j++, k++)
+       {
+         if (orig[j] == ' ' || orig[j] == '\t')
+           new_spec[k++] = '\\';
+         new_spec[k] = orig[j];
+       }
+      free (orig);
+      return new_spec;
+  }
+  else
+    return orig;
+}