OSDN Git Service

PR target/54029
[pf3gnuchains/gcc-fork.git] / gcc / opts.c
index a088bc5..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.
 
@@ -21,35 +21,25 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "config.h"
 #include "system.h"
-
-#include <signal.h>
-
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
 #include "intl.h"
 #include "coretypes.h"
-#include "tm.h" /* Needed by rtl.h and used for DWARF2_DEBUGGING_INFO
-                  and DBX_DEBUGGING_INFO.  */
-#include "tree.h" /* For vect_set_verbosity_level.  */
-#include "rtl.h" /* Needed by insn-attr.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" /* For set_random_seed and enable_rtl_dump_file.  */
 #include "params.h"
 #include "diagnostic.h"
 #include "opts-diagnostic.h"
-#include "insn-attr.h"         /* For INSN_SCHEDULING and DELAY_SLOTS.  */
-#include "target.h"
-#include "dbgcnt.h"
-#include "debug.h"
+#include "insn-attr-common.h"
+#include "common/common-target.h"
 
-/* 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;
+/* Indexed by enum debug_info_type.  */
+const char *const debug_type_names[] =
+{
+  "none", "stabs", "coff", "dwarf-2", "xcoff", "vms"
+};
 
 /* Parse the -femit-struct-debug-detailed option value
    and set the flag variables. */
@@ -59,7 +49,8 @@ int flag_compare_debug;
    ? ((string += sizeof prefix - 1), 1) : 0)
 
 void
-set_struct_debug_option (struct gcc_options *opts, const char *spec)
+set_struct_debug_option (struct gcc_options *opts, location_t loc,
+                        const char *spec)
 {
   /* various labels for comparison */
   static const char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:";
@@ -96,8 +87,10 @@ set_struct_debug_option (struct gcc_options *opts, 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)
@@ -124,23 +117,39 @@ set_struct_debug_option (struct gcc_options *opts, const char *spec)
     }
 
   if (*spec == ',')
-    set_struct_debug_option (opts, 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);
+       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 ("%<-femit-struct-debug-detailed=dir:...%> must allow at least"
-               " as much as %<-femit-struct-debug-detailed=ind:...%>");
+       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
@@ -194,12 +203,15 @@ DEF_VEC_P(char_p);
 DEF_VEC_ALLOC_P(char_p,heap);
 
 static void handle_param (struct gcc_options *opts,
-                         struct gcc_options *opts_set, const char *carg);
+                         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, struct gcc_options *opts,
-                            struct gcc_options *opts_set);
+                            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);
+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,
@@ -218,21 +230,13 @@ 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);
+  return targetm_common.handle_option (opts, opts_set, decoded, loc);
 }
 
 /* Add comma-separated strings to a char_p vector.  */
@@ -290,26 +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);
+  targetm_common.option_init_struct (opts);
 }
 
 /* If indicated by the optimization level LEVEL (-Os if SIZE is set,
@@ -388,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,
@@ -435,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 },
@@ -449,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 },
@@ -478,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 },
@@ -490,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 },
@@ -515,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.  */
@@ -529,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;
@@ -553,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:
@@ -571,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);
@@ -599,23 +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);
+                        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.  */
 void
-finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
+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
@@ -626,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;
 
@@ -651,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;
@@ -667,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))
     {
@@ -677,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.  */
@@ -705,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;
@@ -722,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;
@@ -738,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,
@@ -770,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)
     {
@@ -787,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
@@ -805,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
@@ -869,11 +898,11 @@ print_filtered_help (unsigned int include_flags,
                     unsigned int exclude_flags,
                     unsigned int any_flags,
                     unsigned int columns,
-                    struct gcc_options *opts)
+                    struct gcc_options *opts,
+                    unsigned int lang_mask)
 {
   unsigned int i;
   const char *help;
-  static char *printed = NULL;
   bool found = false;
   bool displayed = false;
 
@@ -900,8 +929,11 @@ 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++)
     {
@@ -930,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)
@@ -963,7 +995,7 @@ 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, opts);
 
@@ -984,6 +1016,20 @@ 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);
@@ -998,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)
@@ -1023,48 +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.  The current option state is in
-   OPTS.  */
+   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,
-                    struct gcc_options *opts)
+                    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.  */
@@ -1130,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, opts);
+  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
@@ -1152,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:
@@ -1169,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, opts);
+           (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, opts);
+       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, opts);
+           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, opts);
-      opts->x_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_:
@@ -1206,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}]
@@ -1290,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;
@@ -1308,12 +1401,16 @@ common_handle_option (struct gcc_options *opts,
          }
 
        if (include_flags)
-         print_specific_help (include_flags, exclude_flags, 0, opts);
+         print_specific_help (include_flags, exclude_flags, 0, opts,
+                              lang_mask);
        opts->x_exit_after_options = true;
        break;
       }
 
     case OPT__version:
+      if (lang_mask == CL_DRIVER)
+       break;
+
       opts->x_exit_after_options = true;
       break;
 
@@ -1323,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;
@@ -1342,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;
@@ -1370,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_:
@@ -1378,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:
@@ -1412,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;
@@ -1468,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_:
@@ -1527,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;
@@ -1579,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:
@@ -1608,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);
-      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);
+    case OPT_fstack_usage:
+      opts->x_flag_stack_usage = value;
+      opts->x_flag_stack_usage_info = value != 0;
       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, opts, opts_set);
+      set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
+                      loc);
       break;
 
     case OPT_gcoff:
-      set_debug_level (SDB_DEBUG, false, arg, opts, opts_set);
+      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, opts_set);
+       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, opts, opts_set);
+      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, opts, opts_set);
+      set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set,
+                      loc);
       break;
 
     case OPT_gvms:
-      set_debug_level (VMS_DEBUG, false, arg, opts, opts_set);
+      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, opts, opts_set);
+      set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg, opts, opts_set,
+                      loc);
       break;
 
     case OPT_pedantic_errors:
@@ -1685,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:
@@ -1700,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.  */
@@ -1713,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;
@@ -1721,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';
@@ -1759,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;
     }
 }
 
@@ -1776,10 +1829,14 @@ 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 in OPTS are set as if -ffast-math.  */
@@ -1807,11 +1864,12 @@ fast_math_flags_struct_set_p (struct cl_optimization *opt)
 
 /* Handle a debug output -g switch for options OPTS
    (OPTS_SET->x_write_symbols storing whether a debug type was passed
-   explicitly).  EXTENDED is true or false to support extended output
-   (2 is special and means "-ggdb" was given).  */
+   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,
-                struct gcc_options *opts, struct gcc_options *opts_set)
+                struct gcc_options *opts, struct gcc_options *opts_set,
+                location_t loc)
 {
   opts->x_use_gnu_debug_info_extensions = extended;
 
@@ -1831,7 +1889,7 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
            }
 
          if (opts->x_write_symbols == NO_DEBUG)
-           warning (0, "target system does not support debug output");
+           warning_at (loc, 0, "target system does not support debug output");
        }
     }
   else
@@ -1840,8 +1898,8 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
       if (opts_set->x_write_symbols != NO_DEBUG
          && opts->x_write_symbols != NO_DEBUG
          && type != opts->x_write_symbols)
-       error ("debug format \"%s\" conflicts with prior selection",
-              debug_type_names[type]);
+       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;
     }
@@ -1856,19 +1914,20 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
     {
       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
        opts->x_debug_info_level = (enum debug_info_levels) argval;
     }
 }
 
-/* Arrange to dump core on error.  (The regular error message is still
-   printed first, except in the case of abort ().)  */
+/* Arrange to dump core on error for diagnostic context DC.  (The
+   regular error message is still printed first, except in the case of
+   abort ().)  */
 
 static void
-setup_core_dumping (void)
+setup_core_dumping (diagnostic_context *dc)
 {
 #ifdef SIGABRT
   signal (SIGABRT, SIG_DFL);
@@ -1883,13 +1942,15 @@ setup_core_dumping (void)
       fatal_error ("setting core file size limit to maximum: %m");
   }
 #endif
-  diagnostic_abort_on_error (global_dc);
+  diagnostic_abort_on_error (dc);
 }
 
-/* Parse a -d<ARG> command line switch.  */
+/* Parse a -d<ARG> command line switch for OPTS, location LOC,
+   diagnostic context DC.  */
 
 static void
-decode_d_option (const char *arg)
+decode_d_option (const char *arg, struct gcc_options *opts,
+                location_t loc, diagnostic_context *dc)
 {
   int c;
 
@@ -1897,20 +1958,20 @@ decode_d_option (const char *arg)
     switch (c = *arg++)
       {
       case 'A':
-       flag_debug_asm = 1;
+       opts->x_flag_debug_asm = 1;
        break;
       case 'p':
-       flag_print_asm_name = 1;
+       opts->x_flag_print_asm_name = 1;
        break;
       case 'P':
-       flag_dump_rtl_in_asm = 1;
-       flag_print_asm_name = 1;
+       opts->x_flag_dump_rtl_in_asm = 1;
+       opts->x_flag_print_asm_name = 1;
        break;
       case 'v':
-       graph_dump_format = vcg;
+       opts->x_graph_dump_format = vcg;
        break;
       case 'x':
-       rtl_dump_and_exit = 1;
+       opts->x_rtl_dump_and_exit = 1;
        break;
       case 'D':        /* These are handled by the preprocessor.  */
       case 'I':
@@ -1919,14 +1980,14 @@ decode_d_option (const char *arg)
       case 'U':
        break;
       case 'H':
-       setup_core_dumping ();
+       setup_core_dumping (dc);
        break;
       case 'a':
-       enable_rtl_dump_file ();
+       opts->x_flag_dump_all_passed = true;
        break;
 
       default:
-         warning (0, "unrecognized gcc debugging option: %c", c);
+         warning_at (loc, 0, "unrecognized gcc debugging option: %c", c);
        break;
       }
 }
@@ -1952,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
     {
@@ -1961,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);
 }