OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / opts.c
index ad3d6fc..6532b56 100644 (file)
@@ -1,5 +1,5 @@
 /* Command line option handling.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Neil Booth.
 
@@ -23,88 +23,24 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "intl.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "expr.h"
-#include "langhooks.h"
+#include "tm.h" /* For STACK_CHECK_BUILTIN,
+                  STACK_CHECK_STATIC_BUILTIN, DEFAULT_GDB_EXTENSIONS,
+                  DWARF2_DEBUGGING_INFO and DBX_DEBUGGING_INFO.  */
 #include "opts.h"
 #include "options.h"
 #include "flags.h"
-#include "toplev.h"
 #include "params.h"
 #include "diagnostic.h"
 #include "opts-diagnostic.h"
-#include "insn-attr.h"         /* For INSN_SCHEDULING.  */
-#include "target.h"
-#include "dbgcnt.h"
-#include "debug.h"
-#include "except.h"
-#include "lto-streamer.h"
-
-/* True if we should exit after parsing options.  */
-bool exit_after_options;
-
-/* Type(s) of debugging information we are producing (if any).  See
-   flags.h for the definitions of the different possible types of
-   debugging information.  */
-enum debug_info_type write_symbols = NO_DEBUG;
-
-/* Level of debugging information we are producing.  See flags.h for
-   the definitions of the different possible levels.  */
-enum debug_info_level debug_info_level = DINFO_LEVEL_NONE;
-
-/* A major contribution to object and executable size is debug
-   information size.  A major contribution to debug information size
-   is struct descriptions replicated in several object files. The
-   following flags attempt to reduce this information.  The basic
-   idea is to not emit struct debugging information in the current
-   compilation unit when that information will be generated by
-   another compilation unit.
-
-   Debug information for a struct defined in the current source
-   file should be generated in the object file.  Likewise the
-   debug information for a struct defined in a header should be
-   generated in the object file of the corresponding source file.
-   Both of these case are handled when the base name of the file of
-   the struct definition matches the base name of the source file
-   of the current compilation unit.  This matching emits minimal
-   struct debugging information.
-
-   The base file name matching rule above will fail to emit debug
-   information for structs defined in system headers.  So a second
-   category of files includes system headers in addition to files
-   with matching bases.
-
-   The remaining types of files are library headers and application
-   headers.  We cannot currently distinguish these two types.  */
-
-enum debug_struct_file
+#include "insn-attr-common.h"
+#include "common/common-target.h"
+
+/* Indexed by enum debug_info_type.  */
+const char *const debug_type_names[] =
 {
-  DINFO_STRUCT_FILE_NONE,   /* Debug no structs. */
-  DINFO_STRUCT_FILE_BASE,   /* Debug structs defined in files with the
-                               same base name as the compilation unit. */
-  DINFO_STRUCT_FILE_SYS,    /* Also debug structs defined in system
-                               header files.  */
-  DINFO_STRUCT_FILE_ANY     /* Debug structs defined in all files. */
+  "none", "stabs", "coff", "dwarf-2", "xcoff", "vms"
 };
 
-/* Generic structs (e.g. templates not explicitly specialized)
-   may not have a compilation unit associated with them, and so
-   may need to be treated differently from ordinary structs.
-
-   Structs only handled by reference (indirectly), will also usually
-   not need as much debugging information.  */
-
-static enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS]
-  = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY };
-static enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS]
-  = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY };
-
-/* Run the second compilation of -fcompare-debug.  Not defined using
-   Var in common.opt because this is used in Ada code and so must be
-   an actual variable not a macro.  */
-int flag_compare_debug;
-
 /* Parse the -femit-struct-debug-detailed option value
    and set the flag variables. */
 
@@ -113,13 +49,14 @@ int flag_compare_debug;
    ? ((string += sizeof prefix - 1), 1) : 0)
 
 void
-set_struct_debug_option (const char *spec)
+set_struct_debug_option (struct gcc_options *opts, location_t loc,
+                        const char *spec)
 {
   /* various labels for comparison */
-  static char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:";
-  static char ord_lbl[] = "ord:", gen_lbl[] = "gen:";
-  static char none_lbl[] = "none", any_lbl[] = "any";
-  static char base_lbl[] = "base", sys_lbl[] = "sys";
+  static const char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:";
+  static const char ord_lbl[] = "ord:", gen_lbl[] = "gen:";
+  static const char none_lbl[] = "none", any_lbl[] = "any";
+  static const char base_lbl[] = "base", sys_lbl[] = "sys";
 
   enum debug_struct_file files = DINFO_STRUCT_FILE_ANY;
   /* Default is to apply to as much as possible. */
@@ -150,54 +87,91 @@ set_struct_debug_option (const char *spec)
   else if (MATCH (base_lbl, spec))
     files = DINFO_STRUCT_FILE_BASE;
   else
-    error ("argument %qs to %<-femit-struct-debug-detailed%> not recognized",
-           spec);
+    error_at (loc,
+             "argument %qs to %<-femit-struct-debug-detailed%> "
+             "not recognized",
+             spec);
 
   /* Effect the specification. */
   if (usage == DINFO_USAGE_NUM_ENUMS)
     {
       if (ord)
         {
-          debug_struct_ordinary[DINFO_USAGE_DFN] = files;
-          debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files;
-          debug_struct_ordinary[DINFO_USAGE_IND_USE] = files;
+          opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files;
+          opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files;
+          opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files;
         }
       if (gen)
         {
-          debug_struct_generic[DINFO_USAGE_DFN] = files;
-          debug_struct_generic[DINFO_USAGE_DIR_USE] = files;
-          debug_struct_generic[DINFO_USAGE_IND_USE] = files;
+          opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files;
+          opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files;
+          opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files;
         }
     }
   else
     {
       if (ord)
-        debug_struct_ordinary[usage] = files;
+        opts->x_debug_struct_ordinary[usage] = files;
       if (gen)
-        debug_struct_generic[usage] = files;
+        opts->x_debug_struct_generic[usage] = files;
     }
 
   if (*spec == ',')
-    set_struct_debug_option (spec+1);
+    set_struct_debug_option (opts, loc, spec+1);
   else
     {
       /* No more -femit-struct-debug-detailed specifications.
          Do final checks. */
       if (*spec != '\0')
-       error ("argument %qs to %<-femit-struct-debug-detailed%> unknown",
-               spec);
-      if (debug_struct_ordinary[DINFO_USAGE_DIR_USE]
-               < debug_struct_ordinary[DINFO_USAGE_IND_USE]
-         || debug_struct_generic[DINFO_USAGE_DIR_USE]
-               < debug_struct_generic[DINFO_USAGE_IND_USE])
-       error ("%<-femit-struct-debug-detailed=dir:...%> must allow at least"
-               " as much as %<-femit-struct-debug-detailed=ind:...%>");
+       error_at (loc,
+                 "argument %qs to %<-femit-struct-debug-detailed%> unknown",
+                 spec);
+      if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE]
+               < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE]
+         || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE]
+               < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE])
+       error_at (loc,
+                 "%<-femit-struct-debug-detailed=dir:...%> must allow "
+                 "at least as much as "
+                 "%<-femit-struct-debug-detailed=ind:...%>");
+    }
+}
+
+/* Handle -ftree-vectorizer-verbose=VAL for options OPTS.  */
+
+static void
+vect_set_verbosity_level (struct gcc_options *opts, int val)
+{
+   if (val < MAX_VERBOSITY_LEVEL)
+     opts->x_user_vect_verbosity_level = (enum vect_verbosity_levels) val;
+   else
+     opts->x_user_vect_verbosity_level
+      = (enum vect_verbosity_levels) (MAX_VERBOSITY_LEVEL - 1);
+}
+
+
+/* Strip off a legitimate source ending from the input string NAME of
+   length LEN.  Rather than having to know the names used by all of
+   our front ends, we strip off an ending of a period followed by
+   up to five characters.  (Java uses ".class".)  */
+
+void
+strip_off_ending (char *name, int len)
+{
+  int i;
+  for (i = 2; i < 6 && len > i; i++)
+    {
+      if (name[len - i] == '.')
+       {
+         name[len - i] = '\0';
+         break;
+       }
     }
 }
 
 /* Find the base name of a path, stripping off both directories and
    a single final extension. */
-static int
+int
 base_of_path (const char *path, const char **base_out)
 {
   const char *base = path;
@@ -221,138 +195,23 @@ base_of_path (const char *path, const char **base_out)
   return dot - base;
 }
 
-/* Match the base name of a file to the base name of a compilation unit. */
-
-static const char *main_input_basename;
-static int main_input_baselength;
-
-static int
-matches_main_base (const char *path)
-{
-  /* Cache the last query. */
-  static const char *last_path = NULL;
-  static int last_match = 0;
-  if (path != last_path)
-    {
-      const char *base;
-      int length = base_of_path (path, &base);
-      last_path = path;
-      last_match = (length == main_input_baselength
-                    && memcmp (base, main_input_basename, length) == 0);
-    }
-  return last_match;
-}
-
-#ifdef DEBUG_DEBUG_STRUCT
-
-static int
-dump_struct_debug (tree type, enum debug_info_usage usage,
-                  enum debug_struct_file criterion, int generic,
-                  int matches, int result)
-{
-  /* Find the type name. */
-  tree type_decl = TYPE_STUB_DECL (type);
-  tree t = type_decl;
-  const char *name = 0;
-  if (TREE_CODE (t) == TYPE_DECL)
-    t = DECL_NAME (t);
-  if (t)
-    name = IDENTIFIER_POINTER (t);
-
-  fprintf (stderr, "   struct %d %s %s %s %s %d %p %s\n",
-          criterion,
-           DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr",
-           matches ? "bas" : "hdr",
-           generic ? "gen" : "ord",
-           usage == DINFO_USAGE_DFN ? ";" :
-             usage == DINFO_USAGE_DIR_USE ? "." : "*",
-           result,
-           (void*) type_decl, name);
-  return result;
-}
-#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \
-  dump_struct_debug (type, usage, criterion, generic, matches, result)
-
-#else
-
-#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \
-  (result)
-
-#endif
-
-
-bool
-should_emit_struct_debug (tree type, enum debug_info_usage usage)
-{
-  enum debug_struct_file criterion;
-  tree type_decl;
-  bool generic = lang_hooks.types.generic_p (type);
-
-  if (generic)
-    criterion = debug_struct_generic[usage];
-  else
-    criterion = debug_struct_ordinary[usage];
-
-  if (criterion == DINFO_STRUCT_FILE_NONE)
-    return DUMP_GSTRUCT (type, usage, criterion, generic, false, false);
-  if (criterion == DINFO_STRUCT_FILE_ANY)
-    return DUMP_GSTRUCT (type, usage, criterion, generic, false, true);
-
-  type_decl = TYPE_STUB_DECL (type);
-
-  if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl))
-    return DUMP_GSTRUCT (type, usage, criterion, generic, false, true);
-
-  if (matches_main_base (DECL_SOURCE_FILE (type_decl)))
-    return DUMP_GSTRUCT (type, usage, criterion, generic, true, true);
-  return DUMP_GSTRUCT (type, usage, criterion, generic, false, false);
-}
-
-/* Nonzero means use GNU-only extensions in the generated symbolic
-   debugging information.  Currently, this only has an effect when
-   write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG.  */
-bool use_gnu_debug_info_extensions;
-
-/* Global visibility options.  */
-struct visibility_flags visibility_options;
-
 /* What to print when a switch has no documentation.  */
 static const char undocumented_msg[] = N_("This switch lacks documentation");
 
-/* Functions excluded from profiling.  */
-
 typedef char *char_p; /* For DEF_VEC_P.  */
 DEF_VEC_P(char_p);
 DEF_VEC_ALLOC_P(char_p,heap);
 
-static VEC(char_p,heap) *flag_instrument_functions_exclude_functions;
-static VEC(char_p,heap) *flag_instrument_functions_exclude_files;
-
-typedef const char *const_char_p; /* For DEF_VEC_P.  */
-DEF_VEC_P(const_char_p);
-DEF_VEC_ALLOC_P(const_char_p,heap);
-
-static VEC(const_char_p,heap) *ignored_options;
-
-/* Input file names.  */
-const char **in_fnames;
-unsigned num_in_fnames;
-
-static bool common_handle_option (struct gcc_options *opts,
-                                 struct gcc_options *opts_set,
-                                 const struct cl_decoded_option *decoded,
-                                 unsigned int lang_mask, int kind,
-                                 location_t loc,
-                                 const struct cl_option_handlers *handlers,
-                                 diagnostic_context *dc);
 static void handle_param (struct gcc_options *opts,
-                         struct gcc_options *opts_set, const char *carg);
-static char *write_langs (unsigned int lang_mask);
-static void complain_wrong_lang (const struct cl_decoded_option *,
-                                unsigned int lang_mask);
+                         struct gcc_options *opts_set, location_t loc,
+                         const char *carg);
 static void set_debug_level (enum debug_info_type type, int extended,
-                            const char *arg);
+                            const char *arg, struct gcc_options *opts,
+                            struct gcc_options *opts_set,
+                            location_t loc);
 static void set_fast_math_flags (struct gcc_options *opts, int set);
+static void decode_d_option (const char *arg, struct gcc_options *opts,
+                            location_t loc, diagnostic_context *dc);
 static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
                                                 int set);
 static void enable_warning_as_error (const char *arg, int value,
@@ -363,194 +222,33 @@ static void enable_warning_as_error (const char *arg, int value,
                                     location_t loc,
                                     diagnostic_context *dc);
 
-/* Return a malloced slash-separated list of languages in MASK.  */
-static char *
-write_langs (unsigned int mask)
-{
-  unsigned int n = 0, len = 0;
-  const char *lang_name;
-  char *result;
-
-  for (n = 0; (lang_name = lang_names[n]) != 0; n++)
-    if (mask & (1U << n))
-      len += strlen (lang_name) + 1;
-
-  result = XNEWVEC (char, len);
-  len = 0;
-  for (n = 0; (lang_name = lang_names[n]) != 0; n++)
-    if (mask & (1U << n))
-      {
-       if (len)
-         result[len++] = '/';
-       strcpy (result + len, lang_name);
-       len += strlen (lang_name);
-      }
-
-  result[len] = 0;
-
-  return result;
-}
-
-/* Complain that switch DECODED does not apply to this front end (mask
-   LANG_MASK).  */
-static void
-complain_wrong_lang (const struct cl_decoded_option *decoded,
-                    unsigned int lang_mask)
-{
-  const struct cl_option *option = &cl_options[decoded->opt_index];
-  const char *text = decoded->orig_option_with_args_text;
-  char *ok_langs = NULL, *bad_lang = NULL;
-  unsigned int opt_flags = option->flags;
-
-  if (!lang_hooks.complain_wrong_lang_p (option))
-    return;
-
-  opt_flags &= ((1U << cl_lang_count) - 1) | CL_DRIVER;
-  if (opt_flags != CL_DRIVER)
-    ok_langs = write_langs (opt_flags);
-  if (lang_mask != CL_DRIVER)
-    bad_lang = write_langs (lang_mask);
-
-  if (opt_flags == CL_DRIVER)
-    error ("command line option %qs is valid for the driver but not for %s",
-          text, bad_lang);
-  else if (lang_mask == CL_DRIVER)
-    gcc_unreachable ();
-  else
-    /* Eventually this should become a hard error IMO.  */
-    warning (0, "command line option %qs is valid for %s but not for %s",
-            text, ok_langs, bad_lang);
-
-  free (ok_langs);
-  free (bad_lang);
-}
-
-/* Buffer the unknown option described by the string OPT.  Currently,
-   we only complain about unknown -Wno-* options if they may have
-   prevented a diagnostic. Otherwise, we just ignore them.
-   Note that if we do complain, it is only as a warning, not an error;
-   passing the compiler an unrecognised -Wno-* option should never
-   change whether the compilation succeeds or fails.  */
-
-static void postpone_unknown_option_warning(const char *opt)
-{
-  VEC_safe_push (const_char_p, heap, ignored_options, opt);
-}
-
-/* Produce a warning for each option previously buffered.  */
-
-void print_ignored_options (void)
-{
-  location_t saved_loc = input_location;
-
-  input_location = 0;
-
-  while (!VEC_empty (const_char_p, ignored_options))
-    {
-      const char *opt;
-      opt = VEC_pop (const_char_p, ignored_options);
-      warning (0, "unrecognized command line option \"%s\"", opt);
-    }
-
-  input_location = saved_loc;
-}
-
-/* Handle an unknown option DECODED, returning true if an error should be
-   given.  */
-
-static bool
-unknown_option_callback (const struct cl_decoded_option *decoded)
-{
-  const char *opt = decoded->arg;
-
-  if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
-      && !(decoded->errors & CL_ERR_NEGATIVE))
-    {
-      /* We don't generate warnings for unknown -Wno-* options unless
-        we issue diagnostics.  */
-      postpone_unknown_option_warning (opt);
-      return false;
-    }
-  else
-    return true;
-}
-
-/* Note that an option DECODED has been successfully handled with a
-   handler for mask MASK.  */
-
-static void
-post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
-                       unsigned int mask ATTRIBUTE_UNUSED)
-{
-#ifdef ENABLE_LTO
-  lto_register_user_option (decoded->opt_index, decoded->arg,
-                           decoded->value, mask);
-#endif
-}
-
-/* Handle a front-end option; arguments and return value as for
-   handle_option.  */
-
-static bool
-lang_handle_option (struct gcc_options *opts,
-                   struct gcc_options *opts_set,
-                   const struct cl_decoded_option *decoded,
-                   unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
-                   location_t loc,
-                   const struct cl_option_handlers *handlers,
-                   diagnostic_context *dc)
-{
-  gcc_assert (opts == &global_options);
-  gcc_assert (opts_set == &global_options_set);
-  gcc_assert (dc == global_dc);
-  gcc_assert (decoded->canonical_option_num_elements <= 2);
-  return lang_hooks.handle_option (decoded->opt_index, decoded->arg,
-                                  decoded->value, kind, loc, handlers);
-}
-
 /* Handle a back-end option; arguments and return value as for
    handle_option.  */
 
-static bool
+bool
 target_handle_option (struct gcc_options *opts,
                      struct gcc_options *opts_set,
                      const struct cl_decoded_option *decoded,
                      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
-                     location_t loc ATTRIBUTE_UNUSED,
+                     location_t loc,
                      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
                      diagnostic_context *dc)
 {
-  gcc_assert (opts == &global_options);
-  gcc_assert (opts_set == &global_options_set);
   gcc_assert (dc == global_dc);
-  gcc_assert (decoded->canonical_option_num_elements <= 2);
   gcc_assert (kind == DK_UNSPECIFIED);
-  /* Although the location is not passed down to
-     targetm.handle_option, do not make assertions about its value;
-     options may come from optimize attributes and having the correct
-     location in the handler is not generally important.  */
-  return targetm.handle_option (decoded->opt_index, decoded->arg,
-                               decoded->value);
-}
-
-/* Handle FILENAME from the command line.  */
-static void
-add_input_filename (const char *filename)
-{
-  num_in_fnames++;
-  in_fnames = XRESIZEVEC (const char *, in_fnames, num_in_fnames);
-  in_fnames[num_in_fnames - 1] = filename;
+  return targetm_common.handle_option (opts, opts_set, decoded, loc);
 }
 
 /* Add comma-separated strings to a char_p vector.  */
 
 static void
-add_comma_separated_to_vector (VEC(char_p,heap) **pvec, const char* arg)
+add_comma_separated_to_vector (void **pvec, const char *arg)
 {
   char *tmp;
   char *r;
   char *w;
   char *token_start;
+  VEC(char_p,heap) *vec = (VEC(char_p,heap) *) *pvec;
 
   /* We never free this string.  */
   tmp = xstrdup (arg);
@@ -565,7 +263,7 @@ add_comma_separated_to_vector (VEC(char_p,heap) **pvec, const char* arg)
        {
          *w++ = '\0';
          ++r;
-         VEC_safe_push (char_p, heap, *pvec, token_start);
+         VEC_safe_push (char_p, heap, vec, token_start);
          token_start = w;
        }
       if (*r == '\\' && r[1] == ',')
@@ -577,96 +275,9 @@ add_comma_separated_to_vector (VEC(char_p,heap) **pvec, const char* arg)
        *w++ = *r++;
     }
   if (*token_start != '\0')
-    VEC_safe_push (char_p, heap, *pvec, token_start);
-}
-
-/* Return whether we should exclude FNDECL from instrumentation.  */
-
-bool
-flag_instrument_functions_exclude_p (tree fndecl)
-{
-  if (VEC_length (char_p, flag_instrument_functions_exclude_functions) > 0)
-    {
-      const char *name;
-      int i;
-      char *s;
-
-      name = lang_hooks.decl_printable_name (fndecl, 0);
-      FOR_EACH_VEC_ELT (char_p, flag_instrument_functions_exclude_functions,
-                       i, s)
-       if (strstr (name, s) != NULL)
-         return true;
-    }
-
-  if (VEC_length (char_p, flag_instrument_functions_exclude_files) > 0)
-    {
-      const char *name;
-      int i;
-      char *s;
-
-      name = DECL_SOURCE_FILE (fndecl);
-      FOR_EACH_VEC_ELT (char_p, flag_instrument_functions_exclude_files, i, s)
-       if (strstr (name, s) != NULL)
-         return true;
-    }
-
-  return false;
-}
-
-
-/* Handle the vector of command line options (located at LOC), storing
-   the results of processing DECODED_OPTIONS and DECODED_OPTIONS_COUNT
-   in OPTS and OPTS_SET and using DC for diagnostic state.  LANG_MASK
-   contains has a single bit set representing the current language.
-   HANDLERS describes what functions to call for the options.  */
-static void
-read_cmdline_options (struct gcc_options *opts, struct gcc_options *opts_set,
-                     struct cl_decoded_option *decoded_options,
-                     unsigned int decoded_options_count,
-                     location_t loc,
-                     unsigned int lang_mask,
-                     const struct cl_option_handlers *handlers,
-                     diagnostic_context *dc)
-{
-  unsigned int i;
-
-  for (i = 1; i < decoded_options_count; i++)
-    {
-      if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
-       {
-         /* Input files should only ever appear on the main command
-            line.  */
-         gcc_assert (opts == &global_options);
-         gcc_assert (opts_set == &global_options_set);
-
-         if (main_input_filename == NULL)
-           {
-             main_input_filename = decoded_options[i].arg;
-             main_input_baselength
-               = base_of_path (main_input_filename, &main_input_basename);
-           }
-         add_input_filename (decoded_options[i].arg);
-         continue;
-       }
-
-      read_cmdline_option (opts, opts_set,
-                          decoded_options + i, loc, lang_mask, handlers,
-                          dc);
-    }
-}
-
-/* Language mask determined at initialization.  */
-static unsigned int initial_lang_mask;
-
-/* Initialize global options-related settings at start-up.  */
-
-void
-init_options_once (void)
-{
-  /* Perform language-specific options initialization.  */
-  initial_lang_mask = lang_hooks.option_lang_mask ();
+    VEC_safe_push (char_p, heap, vec, token_start);
 
-  lang_hooks.initialize_diagnostics (global_dc);
+  *pvec = vec;
 }
 
 /* Initialize OPTS and OPTS_SET before using them in parsing options.  */
@@ -683,41 +294,21 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
   opts_set->x_param_values = XCNEWVEC (int, num_params);
   init_param_values (opts->x_param_values);
 
-  /* Use priority coloring if cover classes is not defined for the
-     target.  */
-  if (targetm.ira_cover_classes == NULL)
-    opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
-
   /* Initialize whether `char' is signed.  */
   opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
   /* Set this to a special "uninitialized" value.  The actual default
      is set after target options have been processed.  */
   opts->x_flag_short_enums = 2;
 
-  /* Initialize target_flags before targetm.target_option.optimization
+  /* Initialize target_flags before default_options_optimization
      so the latter can modify it.  */
-  opts->x_target_flags = targetm.default_target_flags;
+  opts->x_target_flags = targetm_common.default_target_flags;
 
   /* Some targets have ABI-specified unwind tables.  */
-  opts->x_flag_unwind_tables = targetm.unwind_tables_default;
+  opts->x_flag_unwind_tables = targetm_common.unwind_tables_default;
 
   /* Some targets have other target-specific initialization.  */
-  targetm.target_option.init_struct (opts);
-}
-
-/* Decode command-line options to an array, like
-   decode_cmdline_options_to_array and with the same arguments but
-   using the default lang_mask.  */
-
-void
-decode_cmdline_options_to_array_default_mask (unsigned int argc,
-                                             const char **argv, 
-                                             struct cl_decoded_option **decoded_options,
-                                             unsigned int *decoded_options_count)
-{
-  decode_cmdline_options_to_array (argc, argv,
-                                  initial_lang_mask | CL_COMMON | CL_TARGET,
-                                  decoded_options, decoded_options_count);
+  targetm_common.option_init_struct (opts);
 }
 
 /* If indicated by the optimization level LEVEL (-Os if SIZE is set,
@@ -796,7 +387,7 @@ maybe_default_option (struct gcc_options *opts,
                             lang_mask, DK_UNSPECIFIED, loc,
                             handlers, dc);
   else if (default_opt->arg == NULL
-          && !(option->flags & CL_REJECT_NEGATIVE))
+          && !option->cl_reject_negative)
     handle_generated_option (opts, opts_set, default_opt->opt_index,
                             default_opt->arg, !default_opt->value,
                             lang_mask, DK_UNSPECIFIED, loc,
@@ -843,6 +434,7 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_bit_ccp, NULL, 1 },
@@ -857,6 +449,7 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fcombine_stack_adjustments, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_fcompare_elim, NULL, 1 },
 
     /* -O2 optimizations.  */
     { OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 },
@@ -886,11 +479,14 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },
+    { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_falign_loops, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_falign_jumps, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_falign_labels, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },
+    { OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
+    { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
 
     /* -O3 optimizations.  */
     { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
@@ -898,6 +494,7 @@ static const struct default_options default_options_table[] =
     /* Inlining of functions reducing size is a good idea with -Os
        regardless of them being declared inline.  */
     { OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_finline_functions_called_once, NULL, 1 },
     { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
     { OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
     { OPT_LEVELS_3_PLUS, OPT_ftree_vectorize, NULL, 1 },
@@ -911,7 +508,7 @@ static const struct default_options default_options_table[] =
 
 /* Default the options in OPTS and OPTS_SET based on the optimization
    settings in DECODED_OPTIONS and DECODED_OPTIONS_COUNT.  */
-static void
+void
 default_options_optimization (struct gcc_options *opts,
                              struct gcc_options *opts_set,
                              struct cl_decoded_option *decoded_options,
@@ -923,7 +520,6 @@ default_options_optimization (struct gcc_options *opts,
 {
   unsigned int i;
   int opt2;
-  int ofast = 0;
 
   /* Scan to see what optimization level has been specified.  That will
      determine the default value of many flags.  */
@@ -937,21 +533,22 @@ default_options_optimization (struct gcc_options *opts,
            {
              opts->x_optimize = 1;
              opts->x_optimize_size = 0;
-             ofast = 0;
+             opts->x_optimize_fast = 0;
            }
          else
            {
              const int optimize_val = integral_argument (opt->arg);
              if (optimize_val == -1)
-               error ("argument to %qs should be a non-negative integer",
-                      "-O");
+               error_at (loc,
+                         "argument to %qs should be a non-negative integer",
+                         "-O");
              else
                {
                  opts->x_optimize = optimize_val;
                  if ((unsigned int) opts->x_optimize > 255)
                    opts->x_optimize = 255;
                  opts->x_optimize_size = 0;
-                 ofast = 0;
+                 opts->x_optimize_fast = 0;
                }
            }
          break;
@@ -961,14 +558,14 @@ default_options_optimization (struct gcc_options *opts,
 
          /* Optimizing for size forces optimize to be 2.  */
          opts->x_optimize = 2;
-         ofast = 0;
+         opts->x_optimize_fast = 0;
          break;
 
        case OPT_Ofast:
          /* -Ofast only adds flags to -O3.  */
          opts->x_optimize_size = 0;
          opts->x_optimize = 3;
-         ofast = 1;
+         opts->x_optimize_fast = 1;
          break;
 
        default:
@@ -979,7 +576,7 @@ default_options_optimization (struct gcc_options *opts,
 
   maybe_default_options (opts, opts_set, default_options_table,
                         opts->x_optimize, opts->x_optimize_size,
-                        ofast, lang_mask, handlers, loc, dc);
+                        opts->x_optimize_fast, lang_mask, handlers, loc, dc);
 
   /* -O2 param settings.  */
   opt2 = (opts->x_optimize >= 2);
@@ -1007,82 +604,20 @@ default_options_optimization (struct gcc_options *opts,
 
   /* Allow default optimizations to be specified on a per-machine basis.  */
   maybe_default_options (opts, opts_set,
-                        targetm.target_option.optimization_table,
+                        targetm_common.option_optimization_table,
                         opts->x_optimize, opts->x_optimize_size,
-                        ofast, lang_mask, handlers, loc, dc);
-}
-
-static void finish_options (struct gcc_options *, struct gcc_options *);
-
-/* Set *HANDLERS to the default set of option handlers for use in the
-   compilers proper (not the driver).  */
-void
-set_default_handlers (struct cl_option_handlers *handlers)
-{
-  handlers->unknown_option_callback = unknown_option_callback;
-  handlers->wrong_lang_callback = complain_wrong_lang;
-  handlers->post_handling_callback = post_handling_callback;
-  handlers->num_handlers = 3;
-  handlers->handlers[0].handler = lang_handle_option;
-  handlers->handlers[0].mask = initial_lang_mask;
-  handlers->handlers[1].handler = common_handle_option;
-  handlers->handlers[1].mask = CL_COMMON;
-  handlers->handlers[2].handler = target_handle_option;
-  handlers->handlers[2].mask = CL_TARGET;
-}
-
-/* Parse command line options and set default flag values.  Do minimal
-   options processing.  The decoded options are in *DECODED_OPTIONS
-   and *DECODED_OPTIONS_COUNT; settings go in OPTS, OPTS_SET and DC;
-   the options are located at LOC.  */
-void
-decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
-               struct cl_decoded_option *decoded_options,
-               unsigned int decoded_options_count,
-               location_t loc, diagnostic_context *dc)
-{
-  struct cl_option_handlers handlers;
-
-  unsigned int lang_mask;
-
-  lang_mask = initial_lang_mask;
-
-  set_default_handlers (&handlers);
-
-  /* Enable -Werror=coverage-mismatch by default.  */
-  control_warning_option (OPT_Wcoverage_mismatch, (int) DK_ERROR, true,
-                         loc, lang_mask,
-                         &handlers, opts, opts_set, dc);
-
-  default_options_optimization (opts, opts_set,
-                               decoded_options, decoded_options_count,
-                               loc, lang_mask, &handlers, dc);
-
-#ifdef ENABLE_LTO
-  /* Clear any options currently held for LTO.  */
-  lto_clear_user_options ();
-#endif
-
-  read_cmdline_options (opts, opts_set,
-                       decoded_options, decoded_options_count,
-                       loc, lang_mask,
-                       &handlers, dc);
-
-  finish_options (opts, opts_set);
+                        opts->x_optimize_fast, lang_mask, handlers, loc, dc);
 }
 
-/* After all options have been read into OPTS and OPTS_SET, finalize
-   settings of those options and diagnose incompatible
+/* After all options at LOC have been read into OPTS and OPTS_SET,
+   finalize settings of those options and diagnose incompatible
    combinations.  */
-static void
-finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
+void
+finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
+               location_t loc)
 {
-  static bool first_time_p = true;
   enum unwind_info_type ui_except;
 
-  gcc_assert (opts == &global_options);
-  gcc_assert (opts_set = &global_options_set);
-
   if (opts->x_dump_base_name && ! IS_ABSOLUTE_PATH (opts->x_dump_base_name))
     {
       /* First try to make OPTS->X_DUMP_BASE_NAME relative to the
@@ -1093,7 +628,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
       if (opts->x_dump_dir_name)
        opts->x_dump_base_name = concat (opts->x_dump_dir_name,
                                         opts->x_dump_base_name, NULL);
-      else if (opts->x_aux_base_name)
+      else if (opts->x_aux_base_name
+              && strcmp (opts->x_aux_base_name, HOST_BIT_BUCKET) != 0)
        {
          const char *aux_base;
 
@@ -1118,15 +654,18 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
   if (!opts->x_flag_unit_at_a_time)
     {
       if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
-       error ("section anchors must be disabled when unit-at-a-time "
-              "is disabled");
+       error_at (loc, "section anchors must be disabled when unit-at-a-time "
+                 "is disabled");
       opts->x_flag_section_anchors = 0;
       if (opts->x_flag_toplevel_reorder == 1)
-       error ("toplevel reorder must be disabled when unit-at-a-time "
-              "is disabled");
+       error_at (loc, "toplevel reorder must be disabled when unit-at-a-time "
+                 "is disabled");
       opts->x_flag_toplevel_reorder = 0;
     }
 
+  if (opts->x_flag_tm && opts->x_flag_non_call_exceptions)
+    sorry ("transactional memory is not supported with non-call exceptions");
+
   /* -Wmissing-noreturn is alias for -Wsuggest-attribute=noreturn.  */
   if (opts->x_warn_missing_noreturn)
     opts->x_warn_suggest_attribute_noreturn = true;
@@ -1134,7 +673,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
   /* Unless the user has asked for section anchors, we disable toplevel
      reordering at -O0 to disable transformations that might be surprising
      to end users and to get -fno-toplevel-reorder tested.  */
-  if (!optimize
+  if (!opts->x_optimize
       && opts->x_flag_toplevel_reorder == 2
       && !(opts->x_flag_section_anchors && opts_set->x_flag_section_anchors))
     {
@@ -1144,21 +683,21 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
   if (!opts->x_flag_toplevel_reorder)
     {
       if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
-       error ("section anchors must be disabled when toplevel reorder"
-              " is disabled");
+       error_at (loc, "section anchors must be disabled when toplevel reorder"
+                 " is disabled");
       opts->x_flag_section_anchors = 0;
     }
 
-  if (first_time_p)
+  if (!opts->x_flag_opts_finished)
     {
       if (opts->x_flag_pie)
        opts->x_flag_pic = opts->x_flag_pie;
       if (opts->x_flag_pic && !opts->x_flag_pie)
        opts->x_flag_shlib = 1;
-      first_time_p = false;
+      opts->x_flag_opts_finished = true;
     }
 
-  if (optimize == 0)
+  if (opts->x_optimize == 0)
     {
       /* Inlining does not work if not optimizing,
         so force it not to be done.  */
@@ -1172,13 +711,13 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
      generating unwind info.  If opts->x_flag_exceptions is turned on
      we need to turn off the partitioning optimization.  */
 
-  ui_except = targetm.except_unwind_info ();
+  ui_except = targetm_common.except_unwind_info (opts);
 
   if (opts->x_flag_exceptions
       && opts->x_flag_reorder_blocks_and_partition
       && (ui_except == UI_SJLJ || ui_except == UI_TARGET))
     {
-      inform (input_location,
+      inform (loc,
              "-freorder-blocks-and-partition does not work "
              "with exceptions on this architecture");
       opts->x_flag_reorder_blocks_and_partition = 0;
@@ -1189,11 +728,11 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
      optimization.  */
 
   if (opts->x_flag_unwind_tables
-      && !targetm.unwind_tables_default
+      && !targetm_common.unwind_tables_default
       && opts->x_flag_reorder_blocks_and_partition
       && (ui_except == UI_SJLJ || ui_except == UI_TARGET))
     {
-      inform (input_location,
+      inform (loc,
              "-freorder-blocks-and-partition does not support "
              "unwind info on this architecture");
       opts->x_flag_reorder_blocks_and_partition = 0;
@@ -1205,31 +744,27 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
      support named sections.  */
 
   if (opts->x_flag_reorder_blocks_and_partition
-      && (!targetm.have_named_sections
+      && (!targetm_common.have_named_sections
          || (opts->x_flag_unwind_tables
-             && targetm.unwind_tables_default
+             && targetm_common.unwind_tables_default
              && (ui_except == UI_SJLJ || ui_except == UI_TARGET))))
     {
-      inform (input_location,
+      inform (loc,
              "-freorder-blocks-and-partition does not work "
              "on this architecture");
       opts->x_flag_reorder_blocks_and_partition = 0;
       opts->x_flag_reorder_blocks = 1;
     }
 
+  if (opts->x_flag_reorder_blocks_and_partition
+      && !opts_set->x_flag_reorder_functions)
+    opts->x_flag_reorder_functions = 1;
+
   /* Pipelining of outer loops is only possible when general pipelining
      capabilities are requested.  */
   if (!opts->x_flag_sel_sched_pipelining)
     opts->x_flag_sel_sched_pipelining_outer_loops = 0;
 
-  if (!targetm.ira_cover_classes
-      && opts->x_flag_ira_algorithm == IRA_ALGORITHM_CB)
-    {
-      inform (input_location,
-             "-fira-algorithm=CB does not work on this architecture");
-      opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
-    }
-
   if (opts->x_flag_conserve_stack)
     {
       maybe_set_param_value (PARAM_LARGE_STACK_FRAME, 100,
@@ -1237,12 +772,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
       maybe_set_param_value (PARAM_STACK_FRAME_GROWTH, 40,
                             opts->x_param_values, opts_set->x_param_values);
     }
-  if (opts->x_flag_wpa || opts->x_flag_ltrans)
-    {
-      /* These passes are not WHOPR compatible yet.  */
-      opts->x_flag_ipa_pta = 0;
-      opts->x_flag_ipa_struct_reorg = 0;
-    }
 
   if (opts->x_flag_lto)
     {
@@ -1254,16 +783,18 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
         errors later.  */
       opts->x_flag_whole_program = 0;
 #else
-      error ("LTO support has not been enabled in this configuration");
+      error_at (loc, "LTO support has not been enabled in this configuration");
 #endif
-    }
+      if (!opts->x_flag_fat_lto_objects && !HAVE_LTO_PLUGIN)
+        error_at (loc, "-fno-fat-lto-objects are supported only with linker plugin.");
+}
   if ((opts->x_flag_lto_partition_balanced != 0) + (opts->x_flag_lto_partition_1to1 != 0)
        + (opts->x_flag_lto_partition_none != 0) >= 1)
     {
       if ((opts->x_flag_lto_partition_balanced != 0)
           + (opts->x_flag_lto_partition_1to1 != 0)
           + (opts->x_flag_lto_partition_none != 0) > 1)
-       error ("only one -flto-partition value can be specified");
+       error_at (loc, "only one -flto-partition value can be specified");
     }
 
   /* We initialize opts->x_flag_split_stack to -1 so that targets can set a
@@ -1272,13 +803,44 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
     opts->x_flag_split_stack = 0;
   else if (opts->x_flag_split_stack)
     {
-      if (!targetm.supports_split_stack (true))
+      if (!targetm_common.supports_split_stack (true, opts))
        {
-         error ("%<-fsplit-stack%> is not supported by "
-                "this compiler configuration");
+         error_at (loc, "%<-fsplit-stack%> is not supported by "
+                   "this compiler configuration");
          opts->x_flag_split_stack = 0;
        }
     }
+
+  /* Set PARAM_MAX_STORES_TO_SINK to 0 if either vectorization or if-conversion
+     is disabled.  */
+  if (!opts->x_flag_tree_vectorize || !opts->x_flag_tree_loop_if_convert)
+    maybe_set_param_value (PARAM_MAX_STORES_TO_SINK, 0,
+                           opts->x_param_values, opts_set->x_param_values);
+
+  /* This replaces set_Wunused.  */
+  if (opts->x_warn_unused_function == -1)
+    opts->x_warn_unused_function = opts->x_warn_unused;
+  if (opts->x_warn_unused_label == -1)
+    opts->x_warn_unused_label = opts->x_warn_unused;
+  /* Wunused-parameter is enabled if both -Wunused -Wextra are enabled.  */
+  if (opts->x_warn_unused_parameter == -1)
+    opts->x_warn_unused_parameter = (opts->x_warn_unused
+                                    && opts->x_extra_warnings);
+  if (opts->x_warn_unused_variable == -1)
+    opts->x_warn_unused_variable = opts->x_warn_unused;
+  /* Wunused-but-set-parameter is enabled if both -Wunused -Wextra are
+     enabled.  */
+  if (opts->x_warn_unused_but_set_parameter == -1)
+    opts->x_warn_unused_but_set_parameter = (opts->x_warn_unused
+                                            && opts->x_extra_warnings);
+  if (opts->x_warn_unused_but_set_variable == -1)
+    opts->x_warn_unused_but_set_variable = opts->x_warn_unused;
+  if (opts->x_warn_unused_value == -1)
+    opts->x_warn_unused_value = opts->x_warn_unused;
+
+  /* This replaces set_Wextra.  */
+  if (opts->x_warn_uninitialized == -1)
+    opts->x_warn_uninitialized = opts->x_extra_warnings;
 }
 
 #define LEFT_COLUMN    27
@@ -1335,11 +897,12 @@ static void
 print_filtered_help (unsigned int include_flags,
                     unsigned int exclude_flags,
                     unsigned int any_flags,
-                    unsigned int columns)
+                    unsigned int columns,
+                    struct gcc_options *opts,
+                    unsigned int lang_mask)
 {
   unsigned int i;
   const char *help;
-  static char *printed = NULL;
   bool found = false;
   bool displayed = false;
 
@@ -1366,12 +929,15 @@ print_filtered_help (unsigned int include_flags,
       return;
     }
 
-  if (!printed)
-    printed = XCNEWVAR (char, cl_options_count);
+  if (!opts->x_help_printed)
+    opts->x_help_printed = XCNEWVAR (char, cl_options_count);
+
+  if (!opts->x_help_enum_printed)
+    opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
 
   for (i = 0; i < cl_options_count; i++)
     {
-      static char new_help[128];
+      char new_help[128];
       const struct cl_option *option = cl_options + i;
       unsigned int len;
       const char *opt;
@@ -1396,10 +962,10 @@ print_filtered_help (unsigned int include_flags,
 
       found = true;
       /* Skip switches that have already been printed.  */
-      if (printed[i])
+      if (opts->x_help_printed[i])
        continue;
 
-      printed[i] = true;
+      opts->x_help_printed[i] = true;
 
       help = option->help;
       if (help == NULL)
@@ -1429,9 +995,9 @@ print_filtered_help (unsigned int include_flags,
 
       /* With the -Q option enabled we change the descriptive text associated
         with an option to be an indication of its current setting.  */
-      if (!quiet_flag)
+      if (!opts->x_quiet_flag)
        {
-         void *flag_var = option_flag_var (i, &global_options);
+         void *flag_var = option_flag_var (i, opts);
 
          if (len < (LEFT_COLUMN + 2))
            strcpy (new_help, "\t\t");
@@ -1450,12 +1016,26 @@ print_filtered_help (unsigned int include_flags,
                                  sizeof (new_help) - strlen (new_help),
                                  * (const char **) flag_var);
                    }
+                 else if (option->var_type == CLVC_ENUM)
+                   {
+                     const struct cl_enum *e = &cl_enums[option->var_enum];
+                     int value;
+                     const char *arg = NULL;
+
+                     value = e->get (flag_var);
+                     enum_value_to_arg (e->values, &arg, value, lang_mask);
+                     if (arg == NULL)
+                       arg = _("[default]");
+                     snprintf (new_help + strlen (new_help),
+                               sizeof (new_help) - strlen (new_help),
+                               arg);
+                   }
                  else
                    sprintf (new_help + strlen (new_help),
                             "%#x", * (int *) flag_var);
                }
              else
-               strcat (new_help, option_enabled (i, &global_options)
+               strcat (new_help, option_enabled (i, opts)
                        ? _("[enabled]") : _("[disabled]"));
            }
 
@@ -1464,6 +1044,10 @@ print_filtered_help (unsigned int include_flags,
 
       wrap_help (help, opt, len, columns);
       displayed = true;
+
+      if (option->var_type == CLVC_ENUM
+         && opts->x_help_enum_printed[option->var_enum] != 2)
+       opts->x_help_enum_printed[option->var_enum] = 1;
     }
 
   if (! found)
@@ -1489,46 +1073,86 @@ print_filtered_help (unsigned int include_flags,
     printf (_(" All options with the desired characteristics have already been displayed\n"));
 
   putchar ('\n');
+
+  /* Print details of enumerated option arguments, if those
+     enumerations have help text headings provided.  If no help text
+     is provided, presume that the possible values are listed in the
+     help text for the relevant options.  */
+  for (i = 0; i < cl_enums_count; i++)
+    {
+      unsigned int j, pos;
+
+      if (opts->x_help_enum_printed[i] != 1)
+       continue;
+      if (cl_enums[i].help == NULL)
+       continue;
+      printf ("  %s\n    ", _(cl_enums[i].help));
+      pos = 4;
+      for (j = 0; cl_enums[i].values[j].arg != NULL; j++)
+       {
+         unsigned int len = strlen (cl_enums[i].values[j].arg);
+
+         if (pos > 4 && pos + 1 + len <= columns)
+           {
+             printf (" %s", cl_enums[i].values[j].arg);
+             pos += 1 + len;
+           }
+         else
+           {
+             if (pos > 4)
+               {
+                 printf ("\n    ");
+                 pos = 4;
+               }
+             printf ("%s", cl_enums[i].values[j].arg);
+             pos += len;
+           }
+       }
+      printf ("\n\n");
+      opts->x_help_enum_printed[i] = 2;
+    }
 }
 
 /* Display help for a specified type of option.
    The options must have ALL of the INCLUDE_FLAGS set
    ANY of the flags in the ANY_FLAGS set
-   and NONE of the EXCLUDE_FLAGS set.  */
+   and NONE of the EXCLUDE_FLAGS set.  The current option state is in
+   OPTS; LANG_MASK is used for interpreting enumerated option state.  */
 static void
 print_specific_help (unsigned int include_flags,
                     unsigned int exclude_flags,
-                    unsigned int any_flags)
+                    unsigned int any_flags,
+                    struct gcc_options *opts,
+                    unsigned int lang_mask)
 {
   unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
   const char * description = NULL;
   const char * descrip_extra = "";
   size_t i;
   unsigned int flag;
-  static unsigned int columns = 0;
 
   /* Sanity check: Make sure that we do not have more
      languages than we have bits available to enumerate them.  */
-  gcc_assert ((1U << cl_lang_count) < CL_MIN_OPTION_CLASS);
+  gcc_assert ((1U << cl_lang_count) <= CL_MIN_OPTION_CLASS);
 
   /* If we have not done so already, obtain
      the desired maximum width of the output.  */
-  if (columns == 0)
+  if (opts->x_help_columns == 0)
     {
       const char *p;
 
-      GET_ENVIRONMENT (p, "COLUMNS");
+      p = getenv ("COLUMNS");
       if (p != NULL)
        {
          int value = atoi (p);
 
          if (value > 0)
-           columns = value;
+           opts->x_help_columns = value;
        }
 
-      if (columns == 0)
+      if (opts->x_help_columns == 0)
        /* Use a reasonable default.  */
-       columns = 80;
+       opts->x_help_columns = 80;
     }
 
   /* Decide upon the title for the options that we are going to display.  */
@@ -1594,7 +1218,8 @@ print_specific_help (unsigned int include_flags,
     }
 
   printf ("%s%s:\n", description, descrip_extra);
-  print_filtered_help (include_flags, exclude_flags, any_flags, columns);
+  print_filtered_help (include_flags, exclude_flags, any_flags,
+                      opts->x_help_columns, opts, lang_mask);
 }
 
 /* Handle target- and language-independent options.  Return zero to
@@ -1602,7 +1227,7 @@ print_specific_help (unsigned int include_flags,
    extra handling need to be listed here; if you simply want
    DECODED->value assigned to a variable, it happens automatically.  */
 
-static bool
+bool
 common_handle_option (struct gcc_options *opts,
                      struct gcc_options *opts_set,
                      const struct cl_decoded_option *decoded,
@@ -1616,15 +1241,12 @@ common_handle_option (struct gcc_options *opts,
   int value = decoded->value;
   enum opt_code code = (enum opt_code) scode;
 
-  gcc_assert (opts == &global_options);
-  gcc_assert (opts_set == &global_options_set);
-  gcc_assert (dc == global_dc);
   gcc_assert (decoded->canonical_option_num_elements <= 2);
 
   switch (code)
     {
     case OPT__param:
-      handle_param (opts, opts_set, arg);
+      handle_param (opts, opts_set, loc, arg);
       break;
 
     case OPT__help:
@@ -1633,30 +1255,33 @@ common_handle_option (struct gcc_options *opts,
        unsigned int undoc_mask;
        unsigned int i;
 
+       if (lang_mask == CL_DRIVER)
+         break;;
+
        undoc_mask = ((opts->x_verbose_flag | opts->x_extra_warnings)
                      ? 0
                      : CL_UNDOCUMENTED);
        /* First display any single language specific options.  */
        for (i = 0; i < cl_lang_count; i++)
          print_specific_help
-           (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0);
+           (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts,
+            lang_mask);
        /* Next display any multi language specific options.  */
-       print_specific_help (0, undoc_mask, all_langs_mask);
+       print_specific_help (0, undoc_mask, all_langs_mask, opts, lang_mask);
        /* Then display any remaining, non-language options.  */
        for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1)
          if (i != CL_DRIVER)
-           print_specific_help (i, undoc_mask, 0);
-       exit_after_options = true;
+           print_specific_help (i, undoc_mask, 0, opts, lang_mask);
+       opts->x_exit_after_options = true;
        break;
       }
 
     case OPT__target_help:
-      print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0);
-      exit_after_options = true;
+      if (lang_mask == CL_DRIVER)
+       break;
 
-      /* Allow the target a chance to give the user some additional information.  */
-      if (targetm.help)
-       targetm.help ();
+      print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts, lang_mask);
+      opts->x_exit_after_options = true;
       break;
 
     case OPT__help_:
@@ -1670,6 +1295,9 @@ common_handle_option (struct gcc_options *opts,
           --help=target,^undocumented  */
        unsigned int exclude_flags = 0;
 
+       if (lang_mask == CL_DRIVER)
+         break;
+
        /* Walk along the argument string, parsing each word in turn.
           The format is:
           arg = [^]{word}[,{arg}]
@@ -1677,7 +1305,7 @@ common_handle_option (struct gcc_options *opts,
                   params|common|<language>}  */
        while (* a != 0)
          {
-           static struct
+           static const struct
            {
              const char * string;
              unsigned int flag;
@@ -1754,17 +1382,18 @@ common_handle_option (struct gcc_options *opts,
                    if (strncasecmp (a, "c", len) == 0)
                      * pflags |= lang_flag;
                    else
-                     fnotice (stderr,
-                              "warning: --help argument %.*s is ambiguous, please be more specific\n",
-                              len, a);
+                     warning_at (loc, 0,
+                                 "--help argument %q.*s is ambiguous, "
+                                 "please be more specific",
+                                 len, a);
                  }
              }
            else if (lang_flag != 0)
              * pflags |= lang_flag;
            else
-             fnotice (stderr,
-                      "warning: unrecognized argument to --help= option: %.*s\n",
-                      len, a);
+             warning_at (loc, 0,
+                         "unrecognized argument to --help= option: %q.*s",
+                         len, a);
 
            if (comma == NULL)
              break;
@@ -1772,13 +1401,17 @@ common_handle_option (struct gcc_options *opts,
          }
 
        if (include_flags)
-         print_specific_help (include_flags, exclude_flags, 0);
-       exit_after_options = true;
+         print_specific_help (include_flags, exclude_flags, 0, opts,
+                              lang_mask);
+       opts->x_exit_after_options = true;
        break;
       }
 
     case OPT__version:
-      exit_after_options = true;
+      if (lang_mask == CL_DRIVER)
+       break;
+
+      opts->x_exit_after_options = true;
       break;
 
     case OPT_O:
@@ -1787,7 +1420,14 @@ common_handle_option (struct gcc_options *opts,
       /* Currently handled in a prescan.  */
       break;
 
+    case OPT_Werror:
+      dc->warning_as_error_requested = value;
+      break;
+
     case OPT_Werror_:
+      if (lang_mask == CL_DRIVER)
+       break;
+
       enable_warning_as_error (arg, value, lang_mask, handlers,
                               opts, opts_set, loc, dc);
       break;
@@ -1806,6 +1446,11 @@ common_handle_option (struct gcc_options *opts,
       opts->x_warn_frame_larger_than = value != -1;
       break;
 
+    case OPT_Wstack_usage_:
+      opts->x_warn_stack_usage = value;
+      opts->x_flag_stack_usage_info = value != -1;
+      break;
+
     case OPT_Wstrict_aliasing:
       set_Wstrict_aliasing (opts, value);
       break;
@@ -1834,7 +1479,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_d:
-      decode_d_option (arg);
+      decode_d_option (arg, opts, loc, dc);
       break;
 
     case OPT_fcall_used_:
@@ -1842,30 +1487,17 @@ common_handle_option (struct gcc_options *opts,
       /* Deferred.  */
       break;
 
-    case OPT_fcompare_debug_second:
-      flag_compare_debug = value;
-      break;
-
     case OPT_fdbg_cnt_:
-      dbg_cnt_process_opt (arg);
-      break;
-
     case OPT_fdbg_cnt_list:
-      dbg_cnt_list_all_counters ();
+      /* Deferred.  */
       break;
 
     case OPT_fdebug_prefix_map_:
-      add_debug_prefix_map (arg);
+      /* Deferred.  */
       break;
 
     case OPT_fdiagnostics_show_location_:
-      if (!strcmp (arg, "once"))
-       diagnostic_prefixing_rule (dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
-      else if (!strcmp (arg, "every-line"))
-       diagnostic_prefixing_rule (dc)
-         = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-      else
-       return false;
+      diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
       break;
 
     case OPT_fdiagnostics_show_option:
@@ -1876,27 +1508,6 @@ common_handle_option (struct gcc_options *opts,
       /* Deferred.  */
       break;
 
-    case OPT_ffp_contract_:
-      if (!strcmp (arg, "on"))
-       /* Not implemented, fall back to conservative FP_CONTRACT_OFF.  */
-       opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
-      else if (!strcmp (arg, "off"))
-       opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
-      else if (!strcmp (arg, "fast"))
-       opts->x_flag_fp_contract_mode = FP_CONTRACT_FAST;
-      else
-       error ("unknown floating point contraction style \"%s\"", arg);
-      break;
-
-    case OPT_fexcess_precision_:
-      if (!strcmp (arg, "fast"))
-       opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
-      else if (!strcmp (arg, "standard"))
-       opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
-      else
-       error ("unknown excess precision style \"%s\"", arg);
-      break;
-
     case OPT_ffast_math:
       set_fast_math_flags (opts, value);
       break;
@@ -1918,12 +1529,12 @@ common_handle_option (struct gcc_options *opts,
 
     case OPT_finstrument_functions_exclude_function_list_:
       add_comma_separated_to_vector
-       (&flag_instrument_functions_exclude_functions, arg);
+       (&opts->x_flag_instrument_functions_exclude_functions, arg);
       break;
 
     case OPT_finstrument_functions_exclude_file_list_:
       add_comma_separated_to_vector
-       (&flag_instrument_functions_exclude_files, arg);
+       (&opts->x_flag_instrument_functions_exclude_files, arg);
       break;
 
     case OPT_fmessage_length_:
@@ -1932,12 +1543,11 @@ common_handle_option (struct gcc_options *opts,
 
     case OPT_fpack_struct_:
       if (value <= 0 || (value & (value - 1)) || value > 16)
-       error ("structure alignment must be a small power of two, not %d", value);
+       error_at (loc,
+                 "structure alignment must be a small power of two, not %d",
+                 value);
       else
-       {
-         initial_max_fld_align = value;
-         maximum_field_alignment = value * BITS_PER_UNIT;
-       }
+       opts->x_initial_max_fld_align = value;
       break;
 
     case OPT_fplugin_:
@@ -1945,12 +1555,8 @@ common_handle_option (struct gcc_options *opts,
       /* Deferred.  */
       break;
 
-    case OPT_fprofile_dir_:
-      profile_data_prefix = xstrdup (arg);
-      break;
-
     case OPT_fprofile_use_:
-      profile_data_prefix = xstrdup (arg);
+      opts->x_profile_data_prefix = xstrdup (arg);
       opts->x_flag_profile_use = true;
       value = true;
       /* No break here - do -fprofile-use processing. */
@@ -1983,7 +1589,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fprofile_generate_:
-      profile_data_prefix = xstrdup (arg);
+      opts->x_profile_data_prefix = xstrdup (arg);
       value = true;
       /* No break here - do -fprofile-generate processing. */
     case OPT_fprofile_generate:
@@ -1995,41 +1601,31 @@ common_handle_option (struct gcc_options *opts,
        opts->x_flag_value_profile_transformations = value;
       if (!opts_set->x_flag_inline_functions)
        opts->x_flag_inline_functions = value;
+      /* FIXME: Instrumentation we insert makes ipa-reference bitmaps
+        quadratic.  Disable the pass until better memory representation
+        is done.  */
+      if (!opts_set->x_flag_ipa_reference && opts->x_in_lto_p)
+        opts->x_flag_ipa_reference = false;
       break;
 
     case OPT_fshow_column:
       dc->show_column = value;
       break;
 
-    case OPT_fvisibility_:
-      {
-        if (!strcmp(arg, "default"))
-          opts->x_default_visibility = VISIBILITY_DEFAULT;
-        else if (!strcmp(arg, "internal"))
-          opts->x_default_visibility = VISIBILITY_INTERNAL;
-        else if (!strcmp(arg, "hidden"))
-          opts->x_default_visibility = VISIBILITY_HIDDEN;
-        else if (!strcmp(arg, "protected"))
-          opts->x_default_visibility = VISIBILITY_PROTECTED;
-        else
-          error ("unrecognized visibility value \"%s\"", arg);
-      }
-      break;
-
     case OPT_frandom_seed:
       /* The real switch is -fno-random-seed.  */
       if (value)
        return false;
-      set_random_seed (NULL);
+      /* Deferred.  */
       break;
 
     case OPT_frandom_seed_:
-      set_random_seed (arg);
+      /* Deferred.  */
       break;
 
     case OPT_fsched_verbose_:
 #ifdef INSN_SCHEDULING
-      fix_sched_param ("verbose", arg);
+      /* Handled with Var in common.opt.  */
       break;
 #else
       return false;
@@ -2047,21 +1643,21 @@ common_handle_option (struct gcc_options *opts,
 
     case OPT_fstack_check_:
       if (!strcmp (arg, "no"))
-       flag_stack_check = NO_STACK_CHECK;
+       opts->x_flag_stack_check = NO_STACK_CHECK;
       else if (!strcmp (arg, "generic"))
        /* This is the old stack checking method.  */
-       flag_stack_check = STACK_CHECK_BUILTIN
+       opts->x_flag_stack_check = STACK_CHECK_BUILTIN
                           ? FULL_BUILTIN_STACK_CHECK
                           : GENERIC_STACK_CHECK;
       else if (!strcmp (arg, "specific"))
        /* This is the new stack checking method.  */
-       flag_stack_check = STACK_CHECK_BUILTIN
+       opts->x_flag_stack_check = STACK_CHECK_BUILTIN
                           ? FULL_BUILTIN_STACK_CHECK
                           : STACK_CHECK_STATIC_BUILTIN
                             ? STATIC_BUILTIN_STACK_CHECK
                             : GENERIC_STACK_CHECK;
       else
-       warning (0, "unknown stack check parameter \"%s\"", arg);
+       warning_at (loc, 0, "unknown stack check parameter \"%s\"", arg);
       break;
 
     case OPT_fstack_limit:
@@ -2076,75 +1672,50 @@ common_handle_option (struct gcc_options *opts,
       /* Deferred.  */
       break;
 
-    case OPT_ftree_vectorizer_verbose_:
-      vect_set_verbosity_level (arg);
-      break;
-
-    case OPT_ftls_model_:
-      if (!strcmp (arg, "global-dynamic"))
-       opts->x_flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
-      else if (!strcmp (arg, "local-dynamic"))
-       opts->x_flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
-      else if (!strcmp (arg, "initial-exec"))
-       opts->x_flag_tls_default = TLS_MODEL_INITIAL_EXEC;
-      else if (!strcmp (arg, "local-exec"))
-       opts->x_flag_tls_default = TLS_MODEL_LOCAL_EXEC;
-      else
-       warning (0, "unknown tls-model \"%s\"", arg);
+    case OPT_fstack_usage:
+      opts->x_flag_stack_usage = value;
+      opts->x_flag_stack_usage_info = value != 0;
       break;
 
-    case OPT_fira_algorithm_:
-      if (!strcmp (arg, "CB"))
-       opts->x_flag_ira_algorithm = IRA_ALGORITHM_CB;
-      else if (!strcmp (arg, "priority"))
-       opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
-      else
-       warning (0, "unknown ira algorithm \"%s\"", arg);
-      break;
-
-    case OPT_fira_region_:
-      if (!strcmp (arg, "one"))
-       opts->x_flag_ira_region = IRA_REGION_ONE;
-      else if (!strcmp (arg, "all"))
-       opts->x_flag_ira_region = IRA_REGION_ALL;
-      else if (!strcmp (arg, "mixed"))
-       opts->x_flag_ira_region = IRA_REGION_MIXED;
-      else
-       warning (0, "unknown ira region \"%s\"", arg);
+    case OPT_ftree_vectorizer_verbose_:
+      vect_set_verbosity_level (opts, value);
       break;
 
     case OPT_g:
-      set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg);
+      set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
+                      loc);
       break;
 
     case OPT_gcoff:
-      set_debug_level (SDB_DEBUG, false, arg);
+      set_debug_level (SDB_DEBUG, false, arg, opts, opts_set, loc);
       break;
 
     case OPT_gdwarf_:
       if (value < 2 || value > 4)
-       error ("dwarf version %d is not supported", value);
+       error_at (loc, "dwarf version %d is not supported", value);
       else
-       dwarf_version = value;
-      set_debug_level (DWARF2_DEBUG, false, "");
+       opts->x_dwarf_version = value;
+      set_debug_level (DWARF2_DEBUG, false, "", opts, opts_set, loc);
       break;
 
     case OPT_ggdb:
-      set_debug_level (NO_DEBUG, 2, arg);
+      set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc);
       break;
 
     case OPT_gstabs:
     case OPT_gstabs_:
-      set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg);
+      set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set,
+                      loc);
       break;
 
     case OPT_gvms:
-      set_debug_level (VMS_DEBUG, false, arg);
+      set_debug_level (VMS_DEBUG, false, arg, opts, opts_set, loc);
       break;
 
     case OPT_gxcoff:
     case OPT_gxcoff_:
-      set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg);
+      set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg, opts, opts_set,
+                      loc);
       break;
 
     case OPT_pedantic_errors:
@@ -2153,7 +1724,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_flto:
-      opts->x_flag_lto = "";
+      opts->x_flag_lto = value ? "" : NULL;
       break;
 
     case OPT_w:
@@ -2168,6 +1739,11 @@ common_handle_option (struct gcc_options *opts,
       /* No-op. Used by the driver and passed to us because it starts with f.*/
       break;
 
+    case OPT_Wuninitialized:
+      /* Also turn on maybe uninitialized warning.  */
+      opts->x_warn_maybe_uninitialized = value;
+      break;
+
     default:
       /* If the flag was handled in a standard way, assume the lack of
         processing here is intentional.  */
@@ -2181,7 +1757,7 @@ common_handle_option (struct gcc_options *opts,
 /* Handle --param NAME=VALUE.  */
 static void
 handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
-             const char *carg)
+             location_t loc, const char *carg)
 {
   char *equal, *arg;
   int value;
@@ -2189,12 +1765,13 @@ handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
   arg = xstrdup (carg);
   equal = strchr (arg, '=');
   if (!equal)
-    error ("%s: --param arguments should be of the form NAME=VALUE", arg);
+    error_at (loc, "%s: --param arguments should be of the form NAME=VALUE",
+             arg);
   else
     {
       value = integral_argument (equal + 1);
       if (value == -1)
-       error ("invalid --param value %qs", equal + 1);
+       error_at (loc, "invalid --param value %qs", equal + 1);
       else
        {
          *equal = '\0';
@@ -2227,15 +1804,23 @@ set_Wstrict_aliasing (struct gcc_options *opts, int onoff)
 static void
 set_fast_math_flags (struct gcc_options *opts, int set)
 {
-  opts->x_flag_unsafe_math_optimizations = set;
-  set_unsafe_math_optimizations_flags (opts, set);
-  opts->x_flag_finite_math_only = set;
-  opts->x_flag_errno_math = !set;
+  if (!opts->frontend_set_flag_unsafe_math_optimizations)
+    {
+      opts->x_flag_unsafe_math_optimizations = set;
+      set_unsafe_math_optimizations_flags (opts, set);
+    }
+  if (!opts->frontend_set_flag_finite_math_only)
+    opts->x_flag_finite_math_only = set;
+  if (!opts->frontend_set_flag_errno_math)
+    opts->x_flag_errno_math = !set;
   if (set)
     {
-      opts->x_flag_signaling_nans = 0;
-      opts->x_flag_rounding_math = 0;
-      opts->x_flag_cx_limited_range = 1;
+      if (!opts->frontend_set_flag_signaling_nans)
+       opts->x_flag_signaling_nans = 0;
+      if (!opts->frontend_set_flag_rounding_math)
+       opts->x_flag_rounding_math = 0;
+      if (!opts->frontend_set_flag_cx_limited_range)
+       opts->x_flag_cx_limited_range = 1;
     }
 }
 
@@ -2244,21 +1829,25 @@ set_fast_math_flags (struct gcc_options *opts, int set)
 static void
 set_unsafe_math_optimizations_flags (struct gcc_options *opts, int set)
 {
-  opts->x_flag_trapping_math = !set;
-  opts->x_flag_signed_zeros = !set;
-  opts->x_flag_associative_math = set;
-  opts->x_flag_reciprocal_math = set;
+  if (!opts->frontend_set_flag_trapping_math)
+    opts->x_flag_trapping_math = !set;
+  if (!opts->frontend_set_flag_signed_zeros)
+    opts->x_flag_signed_zeros = !set;
+  if (!opts->frontend_set_flag_associative_math)
+    opts->x_flag_associative_math = set;
+  if (!opts->frontend_set_flag_reciprocal_math)
+    opts->x_flag_reciprocal_math = set;
 }
 
-/* Return true iff flags are set as if -ffast-math.  */
+/* Return true iff flags in OPTS are set as if -ffast-math.  */
 bool
-fast_math_flags_set_p (void)
+fast_math_flags_set_p (const struct gcc_options *opts)
 {
-  return (!flag_trapping_math
-         && flag_unsafe_math_optimizations
-         && flag_finite_math_only
-         && !flag_signed_zeros
-         && !flag_errno_math);
+  return (!opts->x_flag_trapping_math
+         && opts->x_flag_unsafe_math_optimizations
+         && opts->x_flag_finite_math_only
+         && !opts->x_flag_signed_zeros
+         && !opts->x_flag_errno_math);
 }
 
 /* Return true iff flags are set as if -ffast-math but using the flags stored
@@ -2273,132 +1862,134 @@ fast_math_flags_struct_set_p (struct cl_optimization *opt)
          && !opt->x_flag_errno_math);
 }
 
-/* Handle a debug output -g switch.  EXTENDED is true or false to support
+/* Handle a debug output -g switch for options OPTS
+   (OPTS_SET->x_write_symbols storing whether a debug type was passed
+   explicitly), location LOC.  EXTENDED is true or false to support
    extended output (2 is special and means "-ggdb" was given).  */
 static void
-set_debug_level (enum debug_info_type type, int extended, const char *arg)
+set_debug_level (enum debug_info_type type, int extended, const char *arg,
+                struct gcc_options *opts, struct gcc_options *opts_set,
+                location_t loc)
 {
-  static bool type_explicit;
-
-  use_gnu_debug_info_extensions = extended;
+  opts->x_use_gnu_debug_info_extensions = extended;
 
   if (type == NO_DEBUG)
     {
-      if (write_symbols == NO_DEBUG)
+      if (opts->x_write_symbols == NO_DEBUG)
        {
-         write_symbols = PREFERRED_DEBUGGING_TYPE;
+         opts->x_write_symbols = PREFERRED_DEBUGGING_TYPE;
 
          if (extended == 2)
            {
 #ifdef DWARF2_DEBUGGING_INFO
-             write_symbols = DWARF2_DEBUG;
+             opts->x_write_symbols = DWARF2_DEBUG;
 #elif defined DBX_DEBUGGING_INFO
-             write_symbols = DBX_DEBUG;
+             opts->x_write_symbols = DBX_DEBUG;
 #endif
            }
 
-         if (write_symbols == NO_DEBUG)
-           warning (0, "target system does not support debug output");
+         if (opts->x_write_symbols == NO_DEBUG)
+           warning_at (loc, 0, "target system does not support debug output");
        }
     }
   else
     {
       /* Does it conflict with an already selected type?  */
-      if (type_explicit && write_symbols != NO_DEBUG && type != write_symbols)
-       error ("debug format \"%s\" conflicts with prior selection",
-              debug_type_names[type]);
-      write_symbols = type;
-      type_explicit = true;
+      if (opts_set->x_write_symbols != NO_DEBUG
+         && opts->x_write_symbols != NO_DEBUG
+         && type != opts->x_write_symbols)
+       error_at (loc, "debug format \"%s\" conflicts with prior selection",
+                 debug_type_names[type]);
+      opts->x_write_symbols = type;
+      opts_set->x_write_symbols = type;
     }
 
   /* A debug flag without a level defaults to level 2.  */
   if (*arg == '\0')
     {
-      if (!debug_info_level)
-       debug_info_level = DINFO_LEVEL_NORMAL;
+      if (!opts->x_debug_info_level)
+       opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
     }
   else
     {
       int argval = integral_argument (arg);
       if (argval == -1)
-       error ("unrecognised debug output level \"%s\"", arg);
+       error_at (loc, "unrecognised debug output level \"%s\"", arg);
       else if (argval > 3)
-       error ("debug output level %s is too high", arg);
+       error_at (loc, "debug output level %s is too high", arg);
       else
-       debug_info_level = (enum debug_info_level) argval;
+       opts->x_debug_info_level = (enum debug_info_levels) argval;
     }
 }
 
-/* Return 1 if option OPT_IDX is enabled in OPTS, 0 if it is disabled,
-   or -1 if it isn't a simple on-off switch.  */
+/* Arrange to dump core on error for diagnostic context DC.  (The
+   regular error message is still printed first, except in the case of
+   abort ().)  */
 
-int
-option_enabled (int opt_idx, void *opts)
+static void
+setup_core_dumping (diagnostic_context *dc)
 {
-  const struct cl_option *option = &(cl_options[opt_idx]);
-  struct gcc_options *optsg = (struct gcc_options *) opts;
-  void *flag_var = option_flag_var (opt_idx, optsg);
-
-  if (flag_var)
-    switch (option->var_type)
-      {
-      case CLVC_BOOLEAN:
-       return *(int *) flag_var != 0;
-
-      case CLVC_EQUAL:
-       return *(int *) flag_var == option->var_value;
-
-      case CLVC_BIT_CLEAR:
-       return (*(int *) flag_var & option->var_value) == 0;
-
-      case CLVC_BIT_SET:
-       return (*(int *) flag_var & option->var_value) != 0;
-
-      case CLVC_STRING:
-      case CLVC_DEFER:
-       break;
-      }
-  return -1;
+#ifdef SIGABRT
+  signal (SIGABRT, SIG_DFL);
+#endif
+#if defined(HAVE_SETRLIMIT)
+  {
+    struct rlimit rlim;
+    if (getrlimit (RLIMIT_CORE, &rlim) != 0)
+      fatal_error ("getting core file size maximum limit: %m");
+    rlim.rlim_cur = rlim.rlim_max;
+    if (setrlimit (RLIMIT_CORE, &rlim) != 0)
+      fatal_error ("setting core file size limit to maximum: %m");
+  }
+#endif
+  diagnostic_abort_on_error (dc);
 }
 
-/* Fill STATE with the current state of option OPTION in OPTS.  Return
-   true if there is some state to store.  */
+/* Parse a -d<ARG> command line switch for OPTS, location LOC,
+   diagnostic context DC.  */
 
-bool
-get_option_state (struct gcc_options *opts, int option,
-                 struct cl_option_state *state)
+static void
+decode_d_option (const char *arg, struct gcc_options *opts,
+                location_t loc, diagnostic_context *dc)
 {
-  void *flag_var = option_flag_var (option, opts);
-
-  if (flag_var == 0)
-    return false;
+  int c;
 
-  switch (cl_options[option].var_type)
-    {
-    case CLVC_BOOLEAN:
-    case CLVC_EQUAL:
-      state->data = flag_var;
-      state->size = sizeof (int);
-      break;
-
-    case CLVC_BIT_CLEAR:
-    case CLVC_BIT_SET:
-      state->ch = option_enabled (option, opts);
-      state->data = &state->ch;
-      state->size = 1;
-      break;
-
-    case CLVC_STRING:
-      state->data = *(const char **) flag_var;
-      if (state->data == 0)
-       state->data = "";
-      state->size = strlen ((const char *) state->data) + 1;
-      break;
+  while (*arg)
+    switch (c = *arg++)
+      {
+      case 'A':
+       opts->x_flag_debug_asm = 1;
+       break;
+      case 'p':
+       opts->x_flag_print_asm_name = 1;
+       break;
+      case 'P':
+       opts->x_flag_dump_rtl_in_asm = 1;
+       opts->x_flag_print_asm_name = 1;
+       break;
+      case 'v':
+       opts->x_graph_dump_format = vcg;
+       break;
+      case 'x':
+       opts->x_rtl_dump_and_exit = 1;
+       break;
+      case 'D':        /* These are handled by the preprocessor.  */
+      case 'I':
+      case 'M':
+      case 'N':
+      case 'U':
+       break;
+      case 'H':
+       setup_core_dumping (dc);
+       break;
+      case 'a':
+       opts->x_flag_dump_all_passed = true;
+       break;
 
-    case CLVC_DEFER:
-      return false;
-    }
-  return true;
+      default:
+         warning_at (loc, 0, "unrecognized gcc debugging option: %c", c);
+       break;
+      }
 }
 
 /* Enable (or disable if VALUE is 0) a warning option ARG (language
@@ -2422,7 +2013,7 @@ enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
   option_index = find_opt (new_option, lang_mask);
   if (option_index == OPT_SPECIAL_unknown)
     {
-      error ("-Werror=%s: no option -%s", arg, new_option);
+      error_at (loc, "-Werror=%s: no option -%s", arg, new_option);
     }
   else
     {
@@ -2431,6 +2022,9 @@ enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
       control_warning_option (option_index, (int) kind, value,
                              loc, lang_mask,
                              handlers, opts, opts_set, dc);
+      if (option_index == OPT_Wuninitialized)
+        enable_warning_as_error ("maybe-uninitialized", value, lang_mask,
+                                handlers, opts, opts_set, loc, dc);
     }
   free (new_option);
 }