]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/gcc.c
sh.c: Do not include algorithm.
[thirdparty/gcc.git] / gcc / gcc.c
index 6ef4e8a1b7748173df810b7ed460615c4e5bfa65..653ca8db9f61e1818f5ec6db77fb0e9c5119c218 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,5 +1,5 @@
 /* Compiler driver program that can handle many languages.
-   Copyright (C) 1987-2013 Free Software Foundation, Inc.
+   Copyright (C) 1987-2014 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -105,6 +105,9 @@ static int verbose_only_flag;
 
 static int print_subprocess_help;
 
+/* Linker suffix passed to -fuse-ld=... */
+static const char *use_ld;
+
 /* Whether we should report subprocess execution times to a file.  */
 
 FILE *report_times_to_file = NULL;
@@ -154,6 +157,11 @@ static const char *const spec_version = DEFAULT_TARGET_VERSION;
 /* The target machine.  */
 
 static const char *spec_machine = DEFAULT_TARGET_MACHINE;
+static const char *spec_host_machine = DEFAULT_REAL_TARGET_MACHINE;
+
+/* List of offload targets.  */
+
+static char *offload_targets = NULL;
 
 /* Nonzero if cross-compiling.
    When -b is used, the value comes from the `specs' file.  */
@@ -215,7 +223,7 @@ static inline void process_marked_switches (void);
 static const char *process_brace_body (const char *, const char *, const char *, int, int);
 static const struct spec_function *lookup_spec_function (const char *);
 static const char *eval_spec_function (const char *, const char *);
-static const char *handle_spec_function (const char *);
+static const char *handle_spec_function (const char *, bool *);
 static char *save_string (const char *, int);
 static void set_collect_gcc_options (void);
 static int do_spec_1 (const char *, int, const char *);
@@ -250,9 +258,11 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+static void try_generate_repro (const char **argv);
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
+static const char *sanitize_spec_function (int, const char **);
 static const char *replace_outfile_spec_function (int, const char **);
 static const char *remove_outfile_spec_function (int, const char **);
 static const char *version_compare_spec_function (int, const char **);
@@ -387,7 +397,8 @@ or with constant text in a single argument.
  %2    process CC1PLUS_SPEC as a spec.
  %*    substitute the variable part of a matched option.  (See below.)
        Note that each comma in the substituted string is replaced by
-       a single space.
+       a single space.  A space is appended after the last substition
+       unless there is more text in current sequence.
  %<S    remove all occurrences of -S from the command line.
         Note - this command is position dependent.  % commands in the
         spec string before this one will see -S, % commands in the
@@ -421,7 +432,9 @@ or with constant text in a single argument.
           once, no matter how many such switches appeared.  However,
           if %* appears somewhere in X, then X will be substituted
           once for each matching switch, with the %* replaced by the
-          part of that switch that matched the '*'.
+          part of that switch that matched the '*'.  A space will be
+         appended after the last substition unless there is more
+         text in current sequence.
  %{.S:X}  substitutes X, if processing a file with suffix S.
  %{!.S:X} substitutes X, if NOT processing a file with suffix S.
  %{,S:X}  substitutes X, if processing a file which will use spec S.
@@ -432,6 +445,10 @@ or with constant text in a single argument.
          than the OR.
          If %* appears in X, all of the alternatives must be starred, and
          only the first matching alternative is substituted.
+ %{%:function(args):X}
+         Call function named FUNCTION with args ARGS.  If the function
+         returns non-NULL, then X is substituted, if it returns
+         NULL, it isn't substituted.
  %{S:X;   if S was given to GCC, substitutes X;
    T:Y;   else if T was given to GCC, substitutes Y;
     :D}   else substitutes D.  There can be as many clauses as you need.
@@ -518,45 +535,25 @@ proper position among the other output files.  */
 #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
 #endif
 
-/* mudflap specs */
-#ifndef MFWRAP_SPEC
-/* XXX: valid only for GNU ld */
-/* 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=mmap64 --wrap=munmap --wrap=alloca\
-} %{fmudflapth: --wrap=pthread_create\
-}} %{fmudflap|fmudflapth: --wrap=main}"
-#endif
-#ifndef MFLIB_SPEC
-#define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}"
-#endif
-
 /* When using -fsplit-stack we need to wrap pthread_create, in order
    to initialize the stack guard.  We always use wrapping, rather than
    shared library ordering, and we keep the wrapper function in
    libgcc.  This is not yet a real spec, though it could become one;
    it is currently just stuffed into LINK_SPEC.  FIXME: This wrapping
-   only works with GNU ld and gold.  FIXME: This is incompatible with
-   -fmudflap when linking statically, which wants to do its own
-   wrapping.  */
+   only works with GNU ld and gold.  */
 #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
+#define STATIC_LIBASAN_LIBS \
+  " %{static-libasan:%:include(libsanitizer.spec)%(link_libasan)}"
 #ifdef LIBASAN_EARLY_SPEC
-#define LIBASAN_SPEC ADD_STATIC_LIBASAN_LIBS
+#define LIBASAN_SPEC 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
+                    STATIC_LIBASAN_LIBS
 #else
-#define LIBASAN_SPEC "-lasan" ADD_STATIC_LIBASAN_LIBS
+#define LIBASAN_SPEC "-lasan" STATIC_LIBASAN_LIBS
 #endif
 #endif
 
@@ -565,20 +562,16 @@ proper position among the other output files.  */
 #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
+#define STATIC_LIBTSAN_LIBS \
+  " %{static-libtsan:%:include(libsanitizer.spec)%(link_libtsan)}"
 #ifdef LIBTSAN_EARLY_SPEC
-#define LIBTSAN_SPEC ADD_STATIC_LIBTSAN_LIBS
+#define LIBTSAN_SPEC 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
+                    STATIC_LIBTSAN_LIBS
 #else
-#define LIBTSAN_SPEC "-ltsan" ADD_STATIC_LIBTSAN_LIBS
+#define LIBTSAN_SPEC "-ltsan" STATIC_LIBTSAN_LIBS
 #endif
 #endif
 
@@ -586,6 +579,61 @@ proper position among the other output files.  */
 #define LIBTSAN_EARLY_SPEC ""
 #endif
 
+#ifndef LIBLSAN_SPEC
+#define STATIC_LIBLSAN_LIBS \
+  " %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}"
+#ifdef LIBLSAN_EARLY_SPEC
+#define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBLSAN_SPEC "%{static-liblsan:" LD_STATIC_OPTION \
+                    "} -llsan %{static-liblsan:" LD_DYNAMIC_OPTION "}" \
+                    STATIC_LIBLSAN_LIBS
+#else
+#define LIBLSAN_SPEC "-llsan" STATIC_LIBLSAN_LIBS
+#endif
+#endif
+
+#ifndef LIBLSAN_EARLY_SPEC
+#define LIBLSAN_EARLY_SPEC ""
+#endif
+
+#ifndef LIBUBSAN_SPEC
+#define STATIC_LIBUBSAN_LIBS \
+  " %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}"
+#ifdef HAVE_LD_STATIC_DYNAMIC
+#define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \
+                    "} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \
+                    STATIC_LIBUBSAN_LIBS
+#else
+#define LIBUBSAN_SPEC "-lubsan" STATIC_LIBUBSAN_LIBS
+#endif
+#endif
+
+/* Linker options for compressed debug sections.  */
+#if HAVE_LD_COMPRESS_DEBUG == 0
+/* No linker support.  */
+#define LINK_COMPRESS_DEBUG_SPEC \
+       " %{gz*:%e-gz is not supported in this configuration} "
+#elif HAVE_LD_COMPRESS_DEBUG == 1
+/* GNU style on input, GNU ld options.  Reject, not useful.  */
+#define LINK_COMPRESS_DEBUG_SPEC \
+       " %{gz*:%e-gz is not supported in this configuration} "
+#elif HAVE_LD_COMPRESS_DEBUG == 2
+/* GNU style, GNU gold options.  */
+#define LINK_COMPRESS_DEBUG_SPEC \
+       " %{gz|gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
+       " %{gz=none:"        LD_COMPRESS_DEBUG_OPTION "=none}" \
+       " %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
+#elif HAVE_LD_COMPRESS_DEBUG == 3
+/* ELF gABI style.  */
+#define LINK_COMPRESS_DEBUG_SPEC \
+       " %{gz|gz=zlib:"  LD_COMPRESS_DEBUG_OPTION "=zlib}" \
+       " %{gz=none:"     LD_COMPRESS_DEBUG_OPTION "=none}" \
+       " %{gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
+#else
+#error Unknown value for HAVE_LD_COMPRESS_DEBUG.
+#endif
+
 /* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
    included.  */
 #ifndef LIBGCC_SPEC
@@ -620,6 +668,33 @@ proper position among the other output files.  */
 #define ASM_MAP ""
 #endif
 
+/* Assembler options for compressed debug sections.  */
+#if HAVE_LD_COMPRESS_DEBUG < 2
+/* Reject if the linker cannot write compressed debug sections.  */
+#define ASM_COMPRESS_DEBUG_SPEC \
+       " %{gz*:%e-gz is not supported in this configuration} "
+#else /* HAVE_LD_COMPRESS_DEBUG >= 2 */
+#if HAVE_AS_COMPRESS_DEBUG == 0
+/* No assembler support.  Ignore silently.  */
+#define ASM_COMPRESS_DEBUG_SPEC \
+       " %{gz*:} "
+#elif HAVE_AS_COMPRESS_DEBUG == 1
+/* GNU style, GNU as options.  */
+#define ASM_COMPRESS_DEBUG_SPEC \
+       " %{gz|gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "}" \
+       " %{gz=none:"        AS_NO_COMPRESS_DEBUG_OPTION "}" \
+       " %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
+#elif HAVE_AS_COMPRESS_DEBUG == 2
+/* ELF gABI style.  */
+#define ASM_COMPRESS_DEBUG_SPEC \
+       " %{gz|gz=zlib:"  AS_COMPRESS_DEBUG_OPTION "=zlib}" \
+       " %{gz=none:"     AS_COMPRESS_DEBUG_OPTION "=none}" \
+       " %{gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
+#else
+#error Unknown value for HAVE_AS_COMPRESS_DEBUG.
+#endif
+#endif /* HAVE_LD_COMPRESS_DEBUG >= 2 */
+
 /* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
    to the assembler.  */
 #ifndef ASM_DEBUG_SPEC
@@ -684,7 +759,7 @@ proper position among the other output files.  */
 #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 "!fno-use-linker-plugin:%{!fno-lto"
 #define PLUGIN_COND_CLOSE "}"
 #else
 /* The linker used has limited plugin support, use LTO plugin with explicit
@@ -708,18 +783,30 @@ proper position among the other output files.  */
 /* 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 "}}}"
+%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
+    %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
+    %{%:sanitize(leak):" LIBLSAN_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:%e-fsanitize=address is incompatible with -fsanitize=thread}}\
-    %{fsanitize=thread:" LIBTSAN_SPEC "\
-    %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}}}"
+%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
+    %{static:%ecannot specify -static with -fsanitize=address}}\
+    %{%:sanitize(thread):" LIBTSAN_SPEC "\
+    %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}\
+    %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
+    %{%:sanitize(leak):" LIBLSAN_SPEC "}}}"
+#endif
+
+/*  This is the spec to use, once the code for creating the vtable
+    verification runtime library, libvtv.so, has been created.  Currently
+    the vtable verification runtime functions are in libstdc++, so we use
+    the spec just below this one.  */
+#ifndef VTABLE_VERIFICATION_SPEC
+#define VTABLE_VERIFICATION_SPEC "\
+%{!nostdlib:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\
+    %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}"
 #endif
 
 /* -u* was put back because both BSD and SysV seem to support it.  */
@@ -737,12 +824,13 @@ proper position among the other output files.  */
     %(linker) " \
     LINK_PLUGIN_SPEC \
    "%{flto|flto=*:%<fcompare-debug*} \
-    %{flto} %{flto=*} %l " LINK_PIE_SPEC \
-   "%{fuse-ld=*:-fuse-ld=%*}\
-    %X %{o*} %{e*} %{N} %{n} %{r}\
-    %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
+    %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
+   "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
+   "%X %{o*} %{e*} %{N} %{n} %{r}\
+    %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} " VTABLE_VERIFICATION_SPEC " \
     %{static:} %{L*} %(mfwrap) %(link_libgcc) " SANITIZER_EARLY_SPEC " %o\
     %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+    %{fcilkplus:%:include(libcilkrts.spec)%(link_cilkrts)}\
     %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
     %(mflib) " STACK_SPLIT_SPEC "\
     %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \
@@ -781,8 +869,6 @@ static const char *asm_spec = ASM_SPEC;
 static const char *asm_final_spec = ASM_FINAL_SPEC;
 static const char *link_spec = LINK_SPEC;
 static const char *lib_spec = LIB_SPEC;
-static const char *mfwrap_spec = MFWRAP_SPEC;
-static const char *mflib_spec = MFLIB_SPEC;
 static const char *link_gomp_spec = "";
 static const char *libgcc_spec = LIBGCC_SPEC;
 static const char *endfile_spec = ENDFILE_SPEC;
@@ -823,8 +909,6 @@ static const char *cpp_unique_options =
  %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\
  %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
  %{H} %C %{D*&U*&A*} %{i*} %Z %i\
- %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
- %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
  %{E|M|MM:%W{o*}}";
 
 /* This contains cpp options which are common with cc1_options and are passed
@@ -856,7 +940,6 @@ static const char *cc1_options =
  %{-help=*:--help=%*}\
  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
  %{fsyntax-only:-o %j} %{-param*}\
- %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
  %{coverage:-fprofile-arcs -ftest-coverage}";
 
 static const char *asm_options =
@@ -866,16 +949,17 @@ static const char *asm_options =
    to the assembler equivalents.  */
 "%{v} %{w:-W} %{I*} "
 #endif
+ASM_COMPRESS_DEBUG_SPEC
 "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
 
 static const char *invoke_as =
 #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
-"%{!fwpa:\
+"%{!fwpa*:\
    %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
    %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\
   }";
 #else
-"%{!fwpa:\
+"%{!fwpa*:\
    %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
    %{!S:-o %|.s |\n as %(asm_options) %m.s %A }\
   }";
@@ -903,7 +987,7 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 #define DRIVER_SELF_SPECS ""
 #endif
 
-/* Adding -fopenmp should imply pthreads.  This is particularly important
+/* Linking to libgomp implies pthreads.  This is particularly important
    for targets that use different start files and suchlike.  */
 #ifndef GOMP_SELF_SPECS
 #define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
@@ -914,9 +998,15 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 #define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
 #endif
 
+/* Likewise for -fcilkplus.  */
+#ifndef CILK_SELF_SPECS
+#define CILK_SELF_SPECS "%{fcilkplus: -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, GTM_SELF_SPECS
+  DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS,
+  CILK_SELF_SPECS
 };
 
 #ifndef OPTION_DEFAULT_SPECS
@@ -1211,6 +1301,9 @@ static const char *const standard_startfile_prefix_2
    relative to the driver.  */
 static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
 
+/* A prefix to be used when this is an accelerator compiler.  */
+static const char *const accel_dir_suffix = ACCEL_DIR_SUFFIX;
+
 /* Subdirectory to use for locating libraries.  Set by
    set_multilib_dir based on the compilation options.  */
 
@@ -1270,8 +1363,6 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("endfile",                 &endfile_spec),
   INIT_STATIC_SPEC ("link",                    &link_spec),
   INIT_STATIC_SPEC ("lib",                     &lib_spec),
-  INIT_STATIC_SPEC ("mfwrap",                  &mfwrap_spec),
-  INIT_STATIC_SPEC ("mflib",                   &mflib_spec),
   INIT_STATIC_SPEC ("link_gomp",               &link_gomp_spec),
   INIT_STATIC_SPEC ("libgcc",                  &libgcc_spec),
   INIT_STATIC_SPEC ("startfile",               &startfile_spec),
@@ -1323,6 +1414,7 @@ static const struct spec_function static_spec_functions[] =
   { "getenv",                   getenv_spec_function },
   { "if-exists",               if_exists_spec_function },
   { "if-exists-else",          if_exists_else_spec_function },
+  { "sanitize",                        sanitize_spec_function },
   { "replace-outfile",         replace_outfile_spec_function },
   { "remove-outfile",          remove_outfile_spec_function },
   { "version-compare",         version_compare_spec_function },
@@ -1516,7 +1608,7 @@ init_spec (void)
   /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
   {
     static const char tf[] = "--traditional-format ";
-    obstack_grow (&obstack, tf, sizeof(tf) - 1);
+    obstack_grow (&obstack, tf, sizeof (tf) - 1);
     obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
     asm_spec = XOBFINISH (&obstack, const char *);
   }
@@ -1526,19 +1618,19 @@ init_spec (void)
     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);
+  obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof (LINK_BUILDID_SPEC) - 1);
 # endif
 # 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);
+  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_grow (&obstack, hash_style, sizeof (hash_style) - 1);
+    obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof (LINKER_HASH_STYLE) - 1);
     obstack_1grow (&obstack, ' ');
   }
 # endif
@@ -1604,7 +1696,7 @@ set_spec (const char *name, const char *spec, bool user_p)
 
   /* Free the old spec.  */
   if (old_spec && sl->alloc_p)
-    free (CONST_CAST(char *, old_spec));
+    free (CONST_CAST (char *, old_spec));
 
   sl->user_p = user_p;
   sl->alloc_p = true;
@@ -1618,17 +1710,15 @@ typedef const char *const_char_p; /* For DEF_VEC_P.  */
 
 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).  */
-
-static int have_o_argbuf_index = 0;
-
 /* Were the options -c, -S or -E passed.  */
 static int have_c = 0;
 
 /* Was the option -o passed.  */
 static int have_o = 0;
 
+/* Pointer to output file name passed in with -o. */
+static const char *output_file = 0;
+
 /* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
    temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
    it here.  */
@@ -1678,8 +1768,6 @@ store_arg (const char *arg, int delete_always, int delete_failure)
 {
   argbuf.safe_push (arg);
 
-  if (strcmp (arg, "-o") == 0)
-    have_o_argbuf_index = argbuf.length ();
   if (delete_always || delete_failure)
     {
       const char *p;
@@ -2450,7 +2538,7 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
 #endif
 
 #ifdef DEFAULT_LINKER
-  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
+  if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0)
     return xstrdup (DEFAULT_LINKER);
 #endif
 
@@ -2773,7 +2861,7 @@ execute (void)
            }
        }
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
        free (CONST_CAST (char *, string));
     }
 
@@ -2826,6 +2914,15 @@ execute (void)
        else if (WIFEXITED (status)
                 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
          {
+           /* For ICEs in cc1, cc1obj, cc1plus see if it is
+              reproducible or not.  */
+           const char *p;
+           if (flag_report_bug
+               && WEXITSTATUS (status) == ICE_EXIT_CODE
+               && i == 0
+               && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+               && ! strncmp (p + 1, "cc1", 3))
+             try_generate_repro (commands[0].argv);
            if (WEXITSTATUS (status) > greatest_status)
              greatest_status = WEXITSTATUS (status);
            ret_code = -1;
@@ -2883,6 +2980,9 @@ execute (void)
          }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -3262,6 +3362,100 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
 static const char *spec_lang = 0;
 static int last_language_n_infiles;
 
+/* Parse -foffload option argument.  */
+
+static void
+handle_foffload_option (const char *arg)
+{
+  const char *c, *cur, *n, *next, *end;
+  char *target;
+
+  /* If option argument starts with '-' then no target is specified and we
+     do not need to parse it.  */
+  if (arg[0] == '-')
+    return;
+
+  end = strchr (arg, '=');
+  if (end == NULL)
+    end = strchr (arg, '\0');
+  cur = arg;
+
+  while (cur < end)
+    {
+      next = strchr (cur, ',');
+      if (next == NULL)
+       next = strchr (cur, '\0');
+      next = (next > end) ? end : next;
+
+      target = XNEWVEC (char, next - cur + 1);
+      strncpy (target, cur, next - cur);
+      target[next - cur] = '\0';
+
+      /* If 'disable' is passed to the option, stop parsing the option and clean
+         the list of offload targets.  */
+      if (strcmp (target, "disable") == 0)
+       {
+         free (offload_targets);
+         offload_targets = xstrdup ("");
+         break;
+       }
+
+      /* Check that GCC is configured to support the offload target.  */
+      c = OFFLOAD_TARGETS;
+      while (c)
+       {
+         n = strchr (c, ',');
+         if (n == NULL)
+           n = strchr (c, '\0');
+
+         if (strlen (target) == (size_t) (n - c)
+             && strncmp (target, c, n - c) == 0)
+           break;
+
+         c = *n ? n + 1 : NULL;
+       }
+
+      if (!c)
+       fatal_error ("GCC is not configured to support %s as offload target",
+                    target);
+
+      if (!offload_targets)
+       offload_targets = xstrdup (target);
+      else
+       {
+         /* Check that the target hasn't already presented in the list.  */
+         c = offload_targets;
+         do
+           {
+             n = strchr (c, ':');
+             if (n == NULL)
+               n = strchr (c, '\0');
+
+             if (strlen (target) == (size_t) (n - c)
+                 && strncmp (c, target, n - c) == 0)
+               break;
+
+             c = n + 1;
+           }
+         while (*n);
+
+         /* If duplicate is not found, append the target to the list.  */
+         if (c > n)
+           {
+             offload_targets
+               = XRESIZEVEC (char, offload_targets,
+                             strlen (offload_targets) + strlen (target) + 2);
+             if (strlen (offload_targets) != 0)
+               strcat (offload_targets, ":");
+             strcat (offload_targets, target);
+           }
+       }
+
+      cur = next + 1;
+      XDELETEVEC (target);
+    }
+}
+
 /* Handle a driver option; arguments and return value as for
    handle_option.  */
 
@@ -3366,6 +3560,14 @@ driver_handle_option (struct gcc_options *opts,
       do_save = false;
       break;
 
+    case OPT_fuse_ld_bfd:
+       use_ld = ".bfd";
+       break;
+
+    case OPT_fuse_ld_gold:
+       use_ld = ".gold";
+       break;
+
     case OPT_fcompare_debug_second:
       compare_debug_second = 1;
       break;
@@ -3609,6 +3811,7 @@ driver_handle_option (struct gcc_options *opts,
 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
       arg = convert_filename (arg, ! have_c, 0);
 #endif
+      output_file = arg;
       /* Save the output name in case -save-temps=obj was used.  */
       save_temps_prefix = xstrdup (arg);
       /* On some systems, ld cannot handle "-o" without a space.  So
@@ -3626,6 +3829,14 @@ driver_handle_option (struct gcc_options *opts,
       validated = true;
       break;
 
+    case OPT_fwpa:
+      flag_wpa = "";
+      break;
+
+    case OPT_foffload_:
+      handle_foffload_option (arg);
+      break;
+
     default:
       /* Various driver options need no special processing at this
         point, having been handled in a prescan above or being
@@ -3944,6 +4155,16 @@ process_command (unsigned int decoded_options_count,
                           CL_DRIVER, &handlers, global_dc);
     }
 
+  if (output_file && strcmp (output_file, "-"))
+    {
+      int i;
+      for (i = 0; i < n_infiles; i++)
+       if ((!infiles[i].language || infiles[i].language[0] != '*')
+           && canonical_filename_eq (infiles[i].name, output_file))
+         fatal_error ("input file %qs is the same as output file",
+                      output_file);
+    }
+
   /* If -save-temps=obj and -o name, create the prefix to use for %b.
      Otherwise just make -save-temps=obj the same as -save-temps=cwd.  */
   if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
@@ -4014,15 +4235,15 @@ process_command (unsigned int decoded_options_count,
     }
 
   gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
-  tooldir_prefix2 = concat (tooldir_base_prefix, spec_machine,
+  tooldir_prefix2 = concat (tooldir_base_prefix, spec_host_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_prefix2, NULL);
+             spec_host_machine, dir_separator_str, spec_version,
+             accel_dir_suffix, dir_separator_str, tooldir_prefix2, NULL);
   free (tooldir_prefix2);
 
   add_prefix (&exec_prefixes,
@@ -4806,7 +5027,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                      {
                        saved_suffix
                          = XNEWVEC (char, suffix_length
-                                    + strlen (TARGET_OBJECT_SUFFIX));
+                                    + strlen (TARGET_OBJECT_SUFFIX) + 1);
                        strncpy (saved_suffix, suffix, suffix_length);
                        strcpy (saved_suffix + suffix_length,
                                TARGET_OBJECT_SUFFIX);
@@ -5273,7 +5494,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
            break;
 
          case ':':
-           p = handle_spec_function (p);
+           p = handle_spec_function (p, NULL);
            if (p == 0)
              return -1;
            break;
@@ -5335,7 +5556,17 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              {
                if (soft_matched_part[0])
                  do_spec_1 (soft_matched_part, 1, NULL);
-               do_spec_1 (" ", 0, NULL);
+               /* Only insert a space after the substitution if it is at the
+                  end of the current sequence.  So if:
+
+                    "%{foo=*:bar%*}%{foo=*:one%*two}"
+
+                  matches -foo=hello then it will produce:
+                  
+                    barhello onehellotwo
+               */
+               if (*p == 0 || *p == '}')
+                 do_spec_1 (" ", 0, NULL);
              }
            else
              /* Catch the case where a spec string contains something like
@@ -5442,7 +5673,7 @@ eval_spec_function (const char *func, const char *args)
   const char *save_suffix_subst;
 
   int save_growing_size;
-  void *save_growing_value;
+  void *save_growing_value = NULL;
 
   sf = lookup_spec_function (func);
   if (sf == NULL)
@@ -5509,10 +5740,13 @@ eval_spec_function (const char *func, const char *args)
    ARGS is processed as a spec in a separate context and split into an
    argument vector in the normal fashion.  The function returns a string
    containing a spec which we then process in the caller's context, or
-   NULL if no processing is required.  */
+   NULL if no processing is required.
+
+   If RETVAL_NONNULL is not NULL, then store a bool whether function
+   returned non-NULL.  */
 
 static const char *
-handle_spec_function (const char *p)
+handle_spec_function (const char *p, bool *retval_nonnull)
 {
   char *func, *args;
   const char *endp, *funcval;
@@ -5558,6 +5792,8 @@ handle_spec_function (const char *p)
   funcval = eval_spec_function (func, args);
   if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
     p = NULL;
+  if (retval_nonnull)
+    *retval_nonnull = funcval != NULL;
 
   free (func);
   free (args);
@@ -5696,26 +5932,35 @@ handle_braces (const char *p)
       a_is_negated = false;
       a_is_spectype = false;
 
-      SKIP_WHITE();
+      SKIP_WHITE ();
       if (*p == '!')
        p++, a_is_negated = true;
 
-      SKIP_WHITE();
-      if (*p == '.')
-       p++, a_is_suffix = true;
-      else if (*p == ',')
-       p++, a_is_spectype = true;
-
-      atom = p;
-      while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
-            || *p == ',' || *p == '.' || *p == '@')
-       p++;
-      end_atom = p;
+      SKIP_WHITE ();
+      if (*p == '%' && p[1] == ':')
+       {
+         atom = NULL;
+         end_atom = NULL;
+         p = handle_spec_function (p + 2, &a_matched);
+       }
+      else
+       {
+         if (*p == '.')
+           p++, a_is_suffix = true;
+         else if (*p == ',')
+           p++, a_is_spectype = true;
+
+         atom = p;
+         while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
+                || *p == ',' || *p == '.' || *p == '@')
+           p++;
+         end_atom = p;
 
-      if (*p == '*')
-       p++, a_is_starred = 1;
+         if (*p == '*')
+           p++, a_is_starred = 1;
+       }
 
-      SKIP_WHITE();
+      SKIP_WHITE ();
       switch (*p)
        {
        case '&': case '}':
@@ -5738,7 +5983,7 @@ handle_braces (const char *p)
          if (ordered_set)
            goto invalid;
 
-         if (atom == end_atom)
+         if (atom && atom == end_atom)
            {
              if (!n_way_choice || disj_matched || *p == '|'
                  || a_is_negated || a_is_suffix || a_is_spectype
@@ -5763,7 +6008,9 @@ handle_braces (const char *p)
                 match.  */
              if (!disj_matched && !n_way_matched)
                {
-                 if (a_is_suffix)
+                 if (atom == NULL)
+                   /* a_matched is already set by handle_spec_function.  */;
+                 else if (a_is_suffix)
                    a_matched = input_suffix_matches (atom, end_atom);
                  else if (a_is_spectype)
                    a_matched = input_spec_matches (atom, end_atom);
@@ -6018,13 +6265,13 @@ give_switch (int switchnum, int omit_first_word)
              while (length-- && !IS_DIR_SEPARATOR (arg[length]))
                if (arg[length] == '.')
                  {
-                   (CONST_CAST(char *, arg))[length] = 0;
+                   (CONST_CAST (char *, arg))[length] = 0;
                    dot = 1;
                    break;
                  }
              do_spec_1 (arg, 1, NULL);
              if (dot)
-               (CONST_CAST(char *, arg))[length] = '.';
+               (CONST_CAST (char *, arg))[length] = '.';
              do_spec_1 (suffix_subst, 1, NULL);
            }
          else
@@ -6036,6 +6283,348 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+/* Print GCC configuration (e.g. version, thread model, target,
+   configuration_arguments) to a given FILE.  */
+
+static void
+print_configuration (FILE *file)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (file, "Target: %s\n", spec_machine);
+  fnotice (file, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (file, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (file, "gcc version %s %s\n\n", version_string,
+            pkgversion_string);
+  else
+    fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n",
+            version_string, pkgversion_string, compiler_version);
+
+}
+
+#define RETRY_ICE_ATTEMPTS 3
+
+/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise.  */
+
+static bool
+files_equal_p (char *file1, char *file2)
+{
+  struct stat st1, st2;
+  off_t n, len;
+  int fd1, fd2;
+  const int bufsize = 8192;
+  char *buf = XNEWVEC (char, bufsize);
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+       len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+         || read (fd2, buf + bufsize / 2, len) != (int) len)
+       {
+         goto error;
+       }
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+       goto error;
+    }
+
+  free (buf);
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  free (buf);
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+/* Check that compiler's output doesn't differ across runs.
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing
+   stdout and stderr for each compiler run.  Return true if all of
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent.  */
+
+static bool
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1])
+        || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1]))
+       {
+        fnotice (stderr, "The bug is not reproducible, so it is"
+                 " likely a hardware or OS problem.\n");
+        break;
+       }
+    }
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+
+/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout
+   to OUT_TEMP and stderr to ERR_TEMP.  If APPEND is TRUE, append to OUT_TEMP
+   and ERR_TEMP instead of truncating.  If EMIT_SYSTEM_INFO is TRUE, also write
+   GCC configuration into to ERR_TEMP.  Return ATTEMPT_STATUS_FAIL_TO_RUN if
+   compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and
+   ATTEMPT_STATUS_SUCCESS otherwise.  */
+
+static enum attempt_status
+run_attempt (const char **new_argv, const char *out_temp,
+            const char *err_temp, int emit_system_info, int append)
+{
+
+  if (emit_system_info)
+    {
+      FILE *file_out = fopen (err_temp, "a");
+      print_configuration (file_out);
+      fclose (file_out);
+    }
+
+  int exit_status;
+  const char *errmsg;
+  struct pex_obj *pex;
+  int err;
+  int pex_flags = PEX_USE_PIPES | PEX_LAST;
+  enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  if (append)
+    pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND;
+
+  pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
+  if (!pex)
+    fatal_error ("pex_init failed: %m");
+
+  errmsg = pex_run (pex, pex_flags, new_argv[0],
+                   CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
+                   err_temp, &err);
+  if (errmsg != NULL)
+    {
+      if (err == 0)
+       fatal_error (errmsg);
+      else
+       {
+         errno = err;
+         pfatal_with_name (errmsg);
+       }
+    }
+
+  if (!pex_get_status (pex, 1, &exit_status))
+    goto out;
+
+  switch (WEXITSTATUS (exit_status))
+    {
+      case ICE_EXIT_CODE:
+       status = ATTEMPT_STATUS_ICE;
+       break;
+
+      case SUCCESS_EXIT_CODE:
+       status = ATTEMPT_STATUS_SUCCESS;
+       break;
+
+      default:
+       ;
+    }
+
+out:
+  pex_free (pex);
+  return status;
+}
+
+/* This routine adds preprocessed source code into the given ERR_FILE.
+   To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
+   add information in report file.  RUN_ATTEMPT should return
+   ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report.  */
+
+static void
+do_report_bug (const char **new_argv, const int nargs,
+              char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+              " please attach this to your bugreport.\n", *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+/* Append string STR to file FILE.  */
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+/* Try to reproduce ICE.  If bug is reproducible, generate report .err file
+   containing GCC configuration, backtrace, compiler's command line options
+   and preprocessed source code.  */
+
+static void
+try_generate_repro (const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+       if (out_arg == -1)
+         out_arg = nargs;
+       else
+         return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+       {
+         append = 1;
+         emit_system_info = 1;
+       }
+
+      if (emit_system_info)
+       append_text (temp_stderr_files[attempt], "/*\n");
+
+      status = run_attempt (new_argv, temp_stdout_files[attempt],
+                           temp_stderr_files[attempt], emit_system_info,
+                           append);
+
+      if (emit_system_info)
+       append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+       {
+         fnotice (stderr, "The bug is not reproducible, so it is"
+                  " likely a hardware or OS problem.\n");
+         goto out;
+       }
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append compiler options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (new_argv, nargs,
+                &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+                &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+       unlink (temp_stdout_files[i]);
+       free (temp_stdout_files[i]);
+      }
+}
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6248,49 +6837,134 @@ compare_files (char *cmpfile[])
   return ret;
 }
 
-extern int main (int, char **);
+/* The top-level "main" within the driver would be ~1000 lines long.
+   This class breaks it up into smaller functions and contains some
+   state shared by them.  */
 
-int
-main (int argc, char **argv)
+class driver
 {
-  size_t i;
-  int value;
-  int linker_was_run = 0;
-  int lang_n_infiles = 0;
-  int num_linker_inputs = 0;
+ public:
+  int main (int argc, char **argv);
+
+ private:
+  void set_progname (const char *argv0) const;
+  void expand_at_files (int *argc, char ***argv) const;
+  void decode_argv (int argc, const char **argv);
+  void global_initializations ();
+  void build_multilib_strings () const;
+  void set_up_specs () const;
+  void putenv_COLLECT_GCC (const char *argv0) const;
+  void maybe_putenv_COLLECT_LTO_WRAPPER () const;
+  void maybe_putenv_OFFLOAD_TARGETS () const;
+  void handle_unrecognized_options () const;
+  int maybe_print_and_exit () const;
+  bool prepare_infiles ();
+  void do_spec_on_infiles () const;
+  void maybe_run_linker (const char *argv0) const;
+  void final_actions () const;
+  int get_exit_code () const;
+
+ private:
   char *explicit_link_files;
-  char *specs_file;
-  char *lto_wrapper_file;
-  const char *p;
-  struct user_specs *uptr;
-  char **old_argv = argv;
   struct cl_decoded_option *decoded_options;
   unsigned int decoded_options_count;
+};
+
+/* Implement the top-level "main" within the driver in terms of
+   driver::main.  */
+
+extern int main (int, char **);
+
+int
+main (int argc, char **argv)
+{
+  driver d;
+
+  return d.main (argc, argv);
+}
+
+/* driver::main is implemented as a series of driver:: method calls.  */
+
+int
+driver::main (int argc, char **argv)
+{
+  bool early_exit;
+
+  set_progname (argv[0]);
+  expand_at_files (&argc, &argv);
+  decode_argv (argc, const_cast <const char **> (argv));
+  global_initializations ();
+  build_multilib_strings ();
+  set_up_specs ();
+  putenv_COLLECT_GCC (argv[0]);
+  maybe_putenv_COLLECT_LTO_WRAPPER ();
+  maybe_putenv_OFFLOAD_TARGETS ();
+  handle_unrecognized_options ();
+
+  if (!maybe_print_and_exit ())
+    return 0;
 
-  p = argv[0] + strlen (argv[0]);
-  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+  early_exit = prepare_infiles ();
+  if (early_exit)
+    return get_exit_code ();
+
+  do_spec_on_infiles ();
+  maybe_run_linker (argv[0]);
+  final_actions ();
+  return get_exit_code ();
+}
+
+/* Locate the final component of argv[0] after any leading path, and set
+   the program name accordingly.  */
+
+void
+driver::set_progname (const char *argv0) const
+{
+  const char *p = argv0 + strlen (argv0);
+  while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
     --p;
   progname = p;
 
   xmalloc_set_program_name (progname);
+}
+
+/* Expand any @ files within the command-line args,
+   setting at_file_supplied if any were expanded.  */
+
+void
+driver::expand_at_files (int *argc, char ***argv) const
+{
+  char **old_argv = *argv;
 
-  expandargv (&argc, &argv);
+  expandargv (argc, argv);
 
   /* Determine if any expansions were made.  */
-  if (argv != old_argv)
+  if (*argv != old_argv)
     at_file_supplied = true;
+}
 
+/* Decode the command-line arguments from argc/argv into the
+   decoded_options array.  */
+
+void
+driver::decode_argv (int argc, const char **argv)
+{
   /* 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),
+  decode_cmdline_options_to_array (argc, argv,
                                   CL_DRIVER,
                                   &decoded_options, &decoded_options_count);
+}
+
+/* Perform various initializations and setup.  */
 
+void
+driver::global_initializations ()
+{
   /* Unlock the stdio streams.  */
   unlock_std_streams ();
 
@@ -6332,10 +7006,16 @@ main (int argc, char **argv)
   alloc_args ();
 
   obstack_init (&obstack);
+}
+
+/* Build multilib_select, et. al from the separate lines that make up each
+   multilib selection.  */
 
-  /* Build multilib_select, et. al from the separate lines that make up each
-     multilib selection.  */
+void
+driver::build_multilib_strings () const
+{
   {
+    const char *p;
     const char *const *q = multilib_raw;
     int need_space;
 
@@ -6368,7 +7048,7 @@ main (int argc, char **argv)
     multilib_reuse = XOBFINISH (&multilib_obstack, const char *);
 
     need_space = FALSE;
-    for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
+    for (size_t i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
       {
        if (need_space)
          obstack_1grow (&multilib_obstack, ' ');
@@ -6381,6 +7061,16 @@ main (int argc, char **argv)
     obstack_1grow (&multilib_obstack, 0);
     multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
   }
+}
+
+/* Set up the spec-handling machinery.  */
+
+void
+driver::set_up_specs () const
+{
+  const char *spec_machine_suffix;
+  char *specs_file;
+  size_t i;
 
 #ifdef INIT_ENVIRONMENT
   /* Set up any other necessary machine specific environment variables.  */
@@ -6402,8 +7092,8 @@ main (int argc, char **argv)
 
   /* Read specs from a file if there is one.  */
 
-  machine_suffix = concat (spec_machine, dir_separator_str,
-                          spec_version, dir_separator_str, NULL);
+  machine_suffix = concat (spec_host_machine, dir_separator_str, spec_version,
+                          accel_dir_suffix, dir_separator_str, NULL);
   just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
 
   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
@@ -6413,13 +7103,18 @@ main (int argc, char **argv)
   else
     init_spec ();
 
-  /* We need to check standard_exec_prefix/just_machine_suffix/specs
+#ifdef ACCEL_COMPILER
+  spec_machine_suffix = machine_suffix;
+#else
+  spec_machine_suffix = just_machine_suffix;
+#endif
+
+  /* We need to check standard_exec_prefix/spec_machine_suffix/specs
      for any override of as, ld and libraries.  */
   specs_file = (char *) alloca (strlen (standard_exec_prefix)
-                      + strlen (just_machine_suffix) + sizeof ("specs"));
-
+                      + strlen (spec_machine_suffix) + sizeof ("specs"));
   strcpy (specs_file, standard_exec_prefix);
-  strcat (specs_file, just_machine_suffix);
+  strcat (specs_file, spec_machine_suffix);
   strcat (specs_file, "specs");
   if (access (specs_file, R_OK) == 0)
     read_specs (specs_file, true, false);
@@ -6540,7 +7235,7 @@ main (int argc, char **argv)
 
   /* Process any user specified specs in the order given on the command
      line.  */
-  for (uptr = user_specs_head; uptr; uptr = uptr->next)
+  for (struct user_specs *uptr = user_specs_head; uptr; uptr = uptr->next)
     {
       char *filename = find_a_file (&startfile_prefixes, uptr->filename,
                                    R_OK, true);
@@ -6601,8 +7296,9 @@ main (int argc, char **argv)
 
   /* 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,
-                             spec_version, dir_separator_str, NULL);
+    gcc_exec_prefix = concat (gcc_exec_prefix, spec_host_machine,
+                             dir_separator_str, spec_version,
+                             accel_dir_suffix, dir_separator_str, NULL);
 
   /* Now we have the specs.
      Set the `valid' bits for switches that match anything in any spec.  */
@@ -6612,16 +7308,27 @@ main (int argc, char **argv)
   /* Now that we have the switches and the specs, set
      the subdirectory based on the options.  */
   set_multilib_dir ();
+}
+
+/* Set up to remember the pathname of gcc and any options
+   needed for collect.  We use argv[0] instead of progname because
+   we need the complete pathname.  */
 
-  /* Set up to remember the pathname of gcc and any options
-     needed for collect.  We use argv[0] instead of progname because
-     we need the complete pathname.  */
+void
+driver::putenv_COLLECT_GCC (const char *argv0) const
+{
   obstack_init (&collect_obstack);
   obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
-  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
+  obstack_grow (&collect_obstack, argv0, strlen (argv0) + 1);
   xputenv (XOBFINISH (&collect_obstack, char *));
+}
 
-  /* Set up to remember the pathname of the lto wrapper. */
+/* Set up to remember the pathname of the lto wrapper. */
+
+void
+driver::maybe_putenv_COLLECT_LTO_WRAPPER () const
+{
+  char *lto_wrapper_file;
 
   if (have_c)
     lto_wrapper_file = NULL;
@@ -6640,14 +7347,47 @@ main (int argc, char **argv)
       xputenv (XOBFINISH (&collect_obstack, char *));
     }
 
-  /* Reject switches that no pass was interested in.  */
+}
 
-  for (i = 0; (int) i < n_switches; i++)
+/* Set up to remember the names of offload targets.  */
+
+void
+driver::maybe_putenv_OFFLOAD_TARGETS () const
+{
+  const char *targets = offload_targets;
+
+  /* If no targets specified by -foffload, use all available targets.  */
+  if (!targets)
+    targets = OFFLOAD_TARGETS;
+
+  if (strlen (targets) > 0)
+    {
+      obstack_grow (&collect_obstack, "OFFLOAD_TARGET_NAMES=",
+                   sizeof ("OFFLOAD_TARGET_NAMES=") - 1);
+      obstack_grow (&collect_obstack, targets,
+                   strlen (targets) + 1);
+      xputenv (XOBFINISH (&collect_obstack, char *));
+    }
+
+  free (offload_targets);
+}
+
+/* Reject switches that no pass was interested in.  */
+
+void
+driver::handle_unrecognized_options () const
+{
+  for (size_t i = 0; (int) i < n_switches; i++)
     if (! switches[i].validated)
       error ("unrecognized command line option %<-%s%>", switches[i].part1);
+}
 
-  /* Obey some of the options.  */
+/* Handle the various -print-* options, returning 0 if the driver
+   should exit, or nonzero if the driver should continue.  */
 
+int
+driver::maybe_print_and_exit () const
+{
   if (print_search_dirs)
     {
       printf (_("install: %s%s\n"),
@@ -6668,6 +7408,38 @@ main (int argc, char **argv)
 
   if (print_prog_name)
     {
+      if (use_ld != NULL && ! strcmp (print_prog_name, "ld"))
+       {
+         /* Append USE_LD to to the default linker.  */
+#ifdef DEFAULT_LINKER
+         char *ld;
+# ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+         int len = (sizeof (DEFAULT_LINKER)
+                    - sizeof (HOST_EXECUTABLE_SUFFIX));
+         ld = NULL;
+         if (len > 0)
+           {
+             char *default_linker = xstrdup (DEFAULT_LINKER);
+             /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains
+                HOST_EXECUTABLE_SUFFIX.  */
+             if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX))
+               {
+                 default_linker[len] = '\0';
+                 ld = concat (default_linker, use_ld,
+                              HOST_EXECUTABLE_SUFFIX, NULL);
+               }
+           }
+         if (ld == NULL)
+# endif
+         ld = concat (DEFAULT_LINKER, use_ld, NULL);
+         if (access (ld, X_OK) == 0)
+           {
+             printf ("%s\n", ld);
+             return (0);
+           }
+#endif
+         print_prog_name = concat (print_prog_name, use_ld, NULL);
+       }
       char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
       printf ("%s\n", (newname ? newname : print_prog_name));
       return (0);
@@ -6757,7 +7529,7 @@ main (int argc, char **argv)
     {
       printf (_("%s %s%s\n"), progname, pkgversion_string,
              version_string);
-      printf ("Copyright %s 2013 Free Software Foundation, Inc.\n",
+      printf ("Copyright %s 2014 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"),
@@ -6773,50 +7545,29 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-        but there's no point in doing all this processing just to get
-        thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-        from version string, so truncate version_string at the first space
-        before comparing.  */
-      for (n = 0; version_string[n]; n++)
-       if (version_string[n] == ' ')
-         break;
-
-      if (! strncmp (version_string, compiler_version, n)
-         && compiler_version[n] == 0)
-       fnotice (stderr, "gcc version %s %s\n", version_string,
-                pkgversion_string);
-      else
-       fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-                version_string, pkgversion_string, compiler_version);
-
+      print_configuration (stderr);
       if (n_infiles == 0)
        return (0);
     }
 
+  return 1;
+}
+
+/* Figure out what to do with each input file.
+   Return true if we need to exit early from "main", false otherwise.  */
+
+bool
+driver::prepare_infiles ()
+{
+  size_t i;
+  int lang_n_infiles = 0;
+
   if (n_infiles == added_libraries)
     fatal_error ("no input files");
 
   if (seen_error ())
-    goto out;
+    /* Early exit needed from main.  */
+    return true;
 
   /* Make a place to record the compiler output file names
      that correspond to the input files.  */
@@ -6864,6 +7615,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
   if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
     fatal_error ("cannot specify -o with -c, -S or -E with multiple files");
 
+  /* No early exit needed from main; we can continue.  */
+  return false;
+}
+
+/* Run the spec machinery on each input file.  */
+
+void
+driver::do_spec_on_infiles () const
+{
+  size_t i;
+
   for (i = 0; (int) i < n_infiles; i++)
     {
       int this_file_error = 0;
@@ -6898,6 +7660,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
            }
          else
            {
+             int value;
+
              if (compare_debug)
                {
                  free (debug_check_temp_file[0]);
@@ -6999,6 +7763,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
       if (lang_specific_pre_link ())
        errorcount++;
     }
+}
+
+/* If we have to run the linker, do it now.  */
+
+void
+driver::maybe_run_linker (const char *argv0) const
+{
+  size_t i;
+  int linker_was_run = 0;
+  int num_linker_inputs;
 
   /* Determine if there are any linker input files.  */
   num_linker_inputs = 0;
@@ -7050,7 +7824,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
              linker_plugin_file_spec = convert_white_space (temp_spec);
            }
 #endif
-         lto_gcc_spec = argv[0];
+         lto_gcc_spec = argv0;
        }
 
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
@@ -7065,7 +7839,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                    " to the linker.\n\n"));
          fflush (stdout);
        }
-      value = do_spec (link_command_spec);
+      int value = do_spec (link_command_spec);
       if (value < 0)
        errorcount = 1;
       linker_was_run = (tmp != execution_count);
@@ -7080,7 +7854,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          && !(infiles[i].language && infiles[i].language[0] == '*'))
        warning (0, "%s: linker input file unused because linking not done",
                 outfiles[i]);
+}
 
+/* The end of "main".  */
+
+void
+driver::final_actions () const
+{
   /* Delete some or all of the temporary files we made.  */
 
   if (seen_error ())
@@ -7092,8 +7872,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
       printf (("\nFor bug reporting instructions, please see:\n"));
       printf ("%s\n", bug_report_url);
     }
+}
+
+/* Determine what the exit code of the driver should be.  */
 
- out:
+int
+driver::get_exit_code () const
+{
   return (signal_count != 0 ? 2
          : seen_error () ? (pass_exit_codes ? greatest_status : 1)
          : 0);
@@ -7396,7 +8181,7 @@ used_arg (const char *p, int len)
        {
          const char *r;
 
-         for (q = multilib_options; *q != '\0'; q++)
+         for (q = multilib_options; *q != '\0'; *q && q++)
            {
              while (*q == ' ')
                q++;
@@ -7696,10 +8481,15 @@ set_multilib_dir (void)
                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 (ml_end - q == 1)
+               multilib_os_dir = xstrdup (".");
+             else
+               {
+                 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;
+               }
 
              if (q2 < end && *q2 == ':')
                {
@@ -8060,6 +8850,33 @@ if_exists_else_spec_function (int argc, const char **argv)
   return argv[1];
 }
 
+/* sanitize built-in spec function.
+
+   This returns non-NULL, if sanitizing address, thread or
+   any of the undefined behavior sanitizers.  */
+
+static const char *
+sanitize_spec_function (int argc, const char **argv)
+{
+  if (argc != 1)
+    return NULL;
+
+  if (strcmp (argv[0], "address") == 0)
+    return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL;
+  if (strcmp (argv[0], "kernel-address") == 0)
+    return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL;
+  if (strcmp (argv[0], "thread") == 0)
+    return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
+  if (strcmp (argv[0], "undefined") == 0)
+    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+           && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
+  if (strcmp (argv[0], "leak") == 0)
+    return ((flag_sanitize
+            & (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD))
+           == SANITIZE_LEAK) ? "" : NULL;
+  return NULL;
+}
+
 /* replace-outfile built-in spec function.
 
    This looks for the first argument in the outfiles array's name and
@@ -8318,7 +9135,7 @@ get_random_number (void)
   }
 #endif
 
-  return ret ^ getpid();
+  return ret ^ getpid ();
 }
 
 /* %:compare-debug-dump-opt spec function.  Save the last argument,
@@ -8530,7 +9347,7 @@ replace_extension_spec_func (int argc, const char **argv)
 
   name = xstrdup (argv[0]);
 
-  for (i = strlen(name) - 1; i >= 0; i--)
+  for (i = strlen (name) - 1; i >= 0; i--)
     if (IS_DIR_SEPARATOR (name[i]))
       break;