PR c++/68795: fix uninitialized close_paren_loc in cp_parser_postfix_expression
[gcc.git] / gcc / opts.c
index 4cb2cdf4eff3bd68bee6aa97830a2f9b2701ca46..2add158224d97a29c514cad5b3a20ae1b4c1fa17 100644 (file)
@@ -1,5 +1,5 @@
 /* Command line option handling.
-   Copyright (C) 2002-2013 Free Software Foundation, Inc.
+   Copyright (C) 2002-2016 Free Software Foundation, Inc.
    Contributed by Neil Booth.
 
 This file is part of GCC.
@@ -23,14 +23,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "coretypes.h"
 #include "opts.h"
-#include "options.h"
-#include "tm.h" /* For STACK_CHECK_BUILTIN,
-                  STACK_CHECK_STATIC_BUILTIN, DEFAULT_GDB_EXTENSIONS,
-                  DWARF2_DEBUGGING_INFO and DBX_DEBUGGING_INFO.  */
+#include "tm.h"
 #include "flags.h"
 #include "params.h"
 #include "diagnostic.h"
-#include "diagnostic-color.h"
 #include "opts-diagnostic.h"
 #include "insn-attr-common.h"
 #include "common/common-target.h"
@@ -185,7 +181,8 @@ base_of_path (const char *path, const char **base_out)
 }
 
 /* What to print when a switch has no documentation.  */
-static const char undocumented_msg[] = N_("This switch lacks documentation");
+static const char undocumented_msg[] = N_("This option lacks documentation.");
+static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed.");
 
 typedef char *char_p; /* For DEF_VEC_P.  */
 
@@ -269,6 +266,20 @@ add_comma_separated_to_vector (void **pvec, const char *arg)
   *pvec = v;
 }
 
+/* Initialize opts_obstack if not initialized.  */
+
+void
+init_opts_obstack (void)
+{
+  static bool opts_obstack_initialized = false;
+
+  if (!opts_obstack_initialized)
+    {
+      opts_obstack_initialized = true;
+      gcc_obstack_init (&opts_obstack);
+    }
+}
+
 /* Initialize OPTS and OPTS_SET before using them in parsing options.  */
 
 void
@@ -276,7 +287,7 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
 {
   size_t num_params = get_num_compiler_params ();
 
-  gcc_obstack_init (&opts_obstack);
+  init_opts_obstack ();
 
   *opts = global_options_init;
 
@@ -307,6 +318,14 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
   targetm_common.option_init_struct (opts);
 }
 
+/* Release any allocations owned by OPTS.  */
+
+void
+finalize_options_struct (struct gcc_options *opts)
+{
+  XDELETEVEC (opts->x_param_values);
+}
+
 /* If indicated by the optimization level LEVEL (-Os if SIZE is set,
    -Ofast if FAST is set, -Og if DEBUG is set), apply the option DEFAULT_OPT
    to OPTS and OPTS_SET, diagnostic context DC, location LOC, with language
@@ -425,28 +444,29 @@ static const struct default_options default_options_table[] =
   {
     /* -O1 optimizations.  */
     { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
-#ifdef DELAY_SLOTS
+#if DELAY_SLOTS
     { OPT_LEVELS_1_PLUS, OPT_fdelayed_branch, NULL, 1 },
 #endif
     { OPT_LEVELS_1_PLUS, OPT_fguess_branch_probability, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fcprop_registers, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fforward_propagate, NULL, 1 },
-    { OPT_LEVELS_1_PLUS, OPT_fif_conversion, NULL, 1 },
-    { OPT_LEVELS_1_PLUS, OPT_fif_conversion2, NULL, 1 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion, NULL, 1 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fipa_pure_const, NULL, 1 },
     { 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_freorder_blocks, 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 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_ftree_coalesce_vars, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_dce, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
     { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },
-    { OPT_LEVELS_1_PLUS, OPT_ftree_copyrename, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
@@ -454,6 +474,11 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_1_PLUS, OPT_fcombine_stack_adjustments, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_fcompare_elim, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_slsr, NULL, 1 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fbranch_count_reg, NULL, 1 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_pta, NULL, 1 },
+    { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
 
     /* -O2 optimizations.  */
     { OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 },
@@ -475,13 +500,14 @@ static const struct default_options default_options_table[] =
 #endif
     { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 },
-    { OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 },
+    { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_freorder_blocks_algorithm_, NULL,
+      REORDER_BLOCKS_ALGORITHM_STC },
     { OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
-    { OPT_LEVELS_2_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
     { 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_fipa_cp_alignment, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
@@ -493,12 +519,15 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },
     { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
-    { OPT_LEVELS_2_PLUS, OPT_fipa_sem_equality, NULL, 1 },
+    { OPT_LEVELS_2_PLUS, OPT_fipa_icf, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },
+    { OPT_LEVELS_2_PLUS, OPT_fipa_ra, NULL, 1 },
+    { OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 },
 
     /* -O3 optimizations.  */
     { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
     { OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },
+    { OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 },
     /* 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 },
@@ -531,6 +560,7 @@ default_options_optimization (struct gcc_options *opts,
 {
   unsigned int i;
   int opt2;
+  bool openacc_mode = false;
 
   /* Scan to see what optimization level has been specified.  That will
      determine the default value of many flags.  */
@@ -590,6 +620,11 @@ default_options_optimization (struct gcc_options *opts,
          opts->x_optimize_debug = 1;
          break;
 
+       case OPT_fopenacc:
+         if (opt->value)
+           openacc_mode = true;
+         break;
+
        default:
          /* Ignore other options in this prescan.  */
          break;
@@ -604,6 +639,10 @@ default_options_optimization (struct gcc_options *opts,
   /* -O2 param settings.  */
   opt2 = (opts->x_optimize >= 2);
 
+  if (openacc_mode
+      && !opts_set->x_flag_ipa_pta)
+    opts->x_flag_ipa_pta = true;
+
   /* Track fields in field-sensitive alias analysis.  */
   maybe_set_param_value
     (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE,
@@ -616,6 +655,13 @@ default_options_optimization (struct gcc_options *opts,
      opt2 ? default_param_value (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP) : 1000,
      opts->x_param_values, opts_set->x_param_values);
 
+  /* At -Ofast, allow store motion to introduce potential race conditions.  */
+  maybe_set_param_value
+    (PARAM_ALLOW_STORE_DATA_RACES,
+     opts->x_optimize_fast ? 1
+     : default_param_value (PARAM_ALLOW_STORE_DATA_RACES),
+     opts->x_param_values, opts_set->x_param_values);
+
   if (opts->x_optimize_size)
     /* We want to crossjump as much as possible.  */
     maybe_set_param_value (PARAM_MIN_CROSSJUMP_INSNS, 1,
@@ -625,6 +671,12 @@ default_options_optimization (struct gcc_options *opts,
                           default_param_value (PARAM_MIN_CROSSJUMP_INSNS),
                           opts->x_param_values, opts_set->x_param_values);
 
+  /* Restrict the amount of work combine does at -Og while retaining
+     most of its useful transforms.  */
+  if (opts->x_optimize_debug)
+    maybe_set_param_value (PARAM_MAX_COMBINE_INSNS, 2,
+                          opts->x_param_values, opts_set->x_param_values);
+
   /* Allow default optimizations to be specified on a per-machine basis.  */
   maybe_default_options (opts, opts_set,
                         targetm_common.option_optimization_table,
@@ -642,7 +694,9 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 {
   enum unwind_info_type ui_except;
 
-  if (opts->x_dump_base_name && ! IS_ABSOLUTE_PATH (opts->x_dump_base_name))
+  if (opts->x_dump_base_name
+      && ! IS_ABSOLUTE_PATH (opts->x_dump_base_name)
+      && ! opts->x_dump_base_name_prefixed)
     {
       /* First try to make OPTS->X_DUMP_BASE_NAME relative to the
         OPTS->X_DUMP_DIR_NAME directory.  Then try to make
@@ -672,6 +726,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
              opts->x_dump_base_name = new_dump_base_name;
            }
        }
+       opts->x_dump_base_name_prefixed = true;
     }
 
   /* Handle related options for unit-at-a-time, toplevel-reorder, and
@@ -711,6 +766,15 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 
   if (!opts->x_flag_opts_finished)
     {
+      /* We initialize opts->x_flag_pie to -1 so that targets can set a
+        default value.  */
+      if (opts->x_flag_pie == -1)
+       {
+         if (opts->x_flag_pic == 0)
+           opts->x_flag_pie = DEFAULT_FLAG_PIE;
+         else
+           opts->x_flag_pie = 0;
+       }
       if (opts->x_flag_pie)
        opts->x_flag_pic = opts->x_flag_pie;
       if (opts->x_flag_pic && !opts->x_flag_pie)
@@ -718,6 +782,11 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
       opts->x_flag_opts_finished = true;
     }
 
+  /* We initialize opts->x_flag_stack_protect to -1 so that targets
+     can set a default value.  */
+  if (opts->x_flag_stack_protect == -1)
+    opts->x_flag_stack_protect = DEFAULT_FLAG_SSP;
+
   if (opts->x_optimize == 0)
     {
       /* Inlining does not work if not optimizing,
@@ -780,6 +849,16 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
       opts->x_flag_reorder_blocks = 1;
     }
 
+  /* Disable -freorder-blocks-and-partition when -fprofile-use is not in
+     effect. Function splitting was not actually being performed in that case,
+     as probably_never_executed_bb_p does not distinguish any basic blocks as
+     being cold vs hot when there is no profile data. Leaving it enabled,
+     however, causes the assembly code generator to create (empty) cold
+     sections and labels, leading to unnecessary size overhead.  */
+  if (opts->x_flag_reorder_blocks_and_partition
+      && !opts_set->x_flag_profile_use)
+    opts->x_flag_reorder_blocks_and_partition = 0;
+
   if (opts->x_flag_reorder_blocks_and_partition
       && !opts_set->x_flag_reorder_functions)
     opts->x_flag_reorder_functions = 1;
@@ -819,14 +898,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
          opts->x_flag_fat_lto_objects = 1;
        }
     }
-  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_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
      default value if they choose based on other options.  */
@@ -860,9 +931,46 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
     maybe_set_param_value (PARAM_MAX_STORES_TO_SINK, 0,
                            opts->x_param_values, opts_set->x_param_values);
 
-  /* The -gsplit-dwarf option requires -gpubnames.  */
+  /* The -gsplit-dwarf option requires -ggnu-pubnames.  */
   if (opts->x_dwarf_split_debug_info)
-    opts->x_debug_generate_pub_sections = 1;
+    opts->x_debug_generate_pub_sections = 2;
+
+  /* Userspace and kernel ASan conflict with each other.  */
+
+  if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+      && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
+    error_at (loc,
+             "-fsanitize=address is incompatible with "
+             "-fsanitize=kernel-address");
+
+  /* And with TSan.  */
+
+  if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
+      && (opts->x_flag_sanitize & SANITIZE_THREAD))
+    error_at (loc,
+             "-fsanitize=address and -fsanitize=kernel-address "
+             "are incompatible with -fsanitize=thread");
+
+  /* Error recovery is not allowed for LSan and TSan.  */
+
+  if (opts->x_flag_sanitize_recover & SANITIZE_THREAD)
+    error_at (loc, "-fsanitize-recover=thread is not supported");
+
+  if (opts->x_flag_sanitize_recover & SANITIZE_LEAK)
+    error_at (loc, "-fsanitize-recover=leak is not supported");
+
+  /* When instrumenting the pointers, we don't want to remove
+     the null pointer checks.  */
+  if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
+                               | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
+    opts->x_flag_delete_null_pointer_checks = 0;
+
+  /* Aggressive compiler optimizations may cause false negatives.  */
+  if (opts->x_flag_sanitize)
+    {
+      opts->x_flag_aggressive_loop_optimizations = 0;
+      opts->x_flag_strict_overflow = 0;
+    }
 }
 
 #define LEFT_COLUMN    27
@@ -927,6 +1035,7 @@ print_filtered_help (unsigned int include_flags,
   const char *help;
   bool found = false;
   bool displayed = false;
+  char new_help[256];
 
   if (include_flags == CL_PARAMS)
     {
@@ -945,6 +1054,15 @@ print_filtered_help (unsigned int include_flags,
          /* Get the translation.  */
          help = _(help);
 
+         if (!opts->x_quiet_flag)
+           {
+             snprintf (new_help, sizeof (new_help),
+                       _("default %d minimum %d maximum %d"),
+                       compiler_params[i].default_value,
+                       compiler_params[i].min_value,
+                       compiler_params[i].max_value);
+             help = new_help;
+           }
          wrap_help (help, param, strlen (param), columns);
        }
       putchar ('\n');
@@ -959,7 +1077,6 @@ print_filtered_help (unsigned int include_flags,
 
   for (i = 0; i < cl_options_count; i++)
     {
-      char new_help[128];
       const struct cl_option *option = cl_options + i;
       unsigned int len;
       const char *opt;
@@ -994,9 +1111,48 @@ print_filtered_help (unsigned int include_flags,
        {
          if (exclude_flags & CL_UNDOCUMENTED)
            continue;
+
          help = undocumented_msg;
        }
 
+      if (option->alias_target < N_OPTS
+         && cl_options [option->alias_target].help)
+       {
+         if (help == undocumented_msg)
+           {
+             /* For undocumented options that are aliases for other options
+                that are documented, point the reader to the other option in
+                preference of the former.  */
+             snprintf (new_help, sizeof new_help,
+                       _("Same as %s.  Use the latter option instead."),
+                       cl_options [option->alias_target].opt_text);
+           }
+         else
+           {
+             /* For documented options with aliases, mention the aliased
+                option's name for reference.  */
+             snprintf (new_help, sizeof new_help,
+                       _("%s  Same as %s."),
+                       help, cl_options [option->alias_target].opt_text);
+           }
+
+         help = new_help;
+       }
+
+      if (option->warn_message)
+       {
+         /* Mention that the use of the option will trigger a warning.  */
+         if (help == new_help)
+           snprintf (new_help + strlen (new_help),
+                     sizeof new_help - strlen (new_help),
+                     "  %s", _(use_diagnosed_msg));
+         else
+           snprintf (new_help, sizeof new_help,
+                     "%s  %s", help, _(use_diagnosed_msg));
+
+         help = new_help;
+       }
+
       /* Get the translation.  */
       help = _(help);
 
@@ -1036,7 +1192,7 @@ print_filtered_help (unsigned int include_flags,
                      if (* (const char **) flag_var != NULL)
                        snprintf (new_help + strlen (new_help),
                                  sizeof (new_help) - strlen (new_help),
-                                 * (const char **) flag_var);
+                                 "%s", * (const char **) flag_var);
                    }
                  else if (option->var_type == CLVC_ENUM)
                    {
@@ -1050,7 +1206,7 @@ print_filtered_help (unsigned int include_flags,
                        arg = _("[default]");
                      snprintf (new_help + strlen (new_help),
                                sizeof (new_help) - strlen (new_help),
-                               arg);
+                               "%s", arg);
                    }
                  else
                    sprintf (new_help + strlen (new_help),
@@ -1086,7 +1242,7 @@ print_filtered_help (unsigned int include_flags,
             options supported by a specific front end.  */
          for (i = 0; (1U << i) < CL_LANG_ALL; i ++)
            if ((1U << i) & langs)
-             printf (_(" None found.  Use --help=%s to show *all* the options supported by the %s front-end\n"),
+             printf (_(" None found.  Use --help=%s to show *all* the options supported by the %s front-end.\n"),
                      lang_names[i], lang_names[i]);
        }
 
@@ -1161,18 +1317,8 @@ print_specific_help (unsigned int include_flags,
      the desired maximum width of the output.  */
   if (opts->x_help_columns == 0)
     {
-      const char *p;
-
-      p = getenv ("COLUMNS");
-      if (p != NULL)
-       {
-         int value = atoi (p);
-
-         if (value > 0)
-           opts->x_help_columns = value;
-       }
-
-      if (opts->x_help_columns == 0)
+      opts->x_help_columns = get_terminal_width ();
+      if (opts->x_help_columns == INT_MAX)
        /* Use a reasonable default.  */
        opts->x_help_columns = 80;
     }
@@ -1244,6 +1390,53 @@ print_specific_help (unsigned int include_flags,
                       opts->x_help_columns, opts, lang_mask);
 }
 
+/* Enable FDO-related flags.  */
+
+static void
+enable_fdo_optimizations (struct gcc_options *opts,
+                         struct gcc_options *opts_set,
+                         int value)
+{
+  if (!opts_set->x_flag_branch_probabilities)
+    opts->x_flag_branch_probabilities = value;
+  if (!opts_set->x_flag_profile_values)
+    opts->x_flag_profile_values = value;
+  if (!opts_set->x_flag_unroll_loops)
+    opts->x_flag_unroll_loops = value;
+  if (!opts_set->x_flag_peel_loops)
+    opts->x_flag_peel_loops = value;
+  if (!opts_set->x_flag_tracer)
+    opts->x_flag_tracer = value;
+  if (!opts_set->x_flag_value_profile_transformations)
+    opts->x_flag_value_profile_transformations = value;
+  if (!opts_set->x_flag_inline_functions)
+    opts->x_flag_inline_functions = value;
+  if (!opts_set->x_flag_ipa_cp)
+    opts->x_flag_ipa_cp = value;
+  if (!opts_set->x_flag_ipa_cp_clone
+      && value && opts->x_flag_ipa_cp)
+    opts->x_flag_ipa_cp_clone = value;
+  if (!opts_set->x_flag_ipa_cp_alignment
+      && value && opts->x_flag_ipa_cp)
+    opts->x_flag_ipa_cp_alignment = value;
+  if (!opts_set->x_flag_predictive_commoning)
+    opts->x_flag_predictive_commoning = value;
+  if (!opts_set->x_flag_unswitch_loops)
+    opts->x_flag_unswitch_loops = value;
+  if (!opts_set->x_flag_gcse_after_reload)
+    opts->x_flag_gcse_after_reload = value;
+  if (!opts_set->x_flag_tree_loop_vectorize
+      && !opts_set->x_flag_tree_vectorize)
+    opts->x_flag_tree_loop_vectorize = value;
+  if (!opts_set->x_flag_tree_slp_vectorize
+      && !opts_set->x_flag_tree_vectorize)
+    opts->x_flag_tree_slp_vectorize = value;
+  if (!opts_set->x_flag_vect_cost_model)
+    opts->x_flag_vect_cost_model = VECT_COST_MODEL_DYNAMIC;
+  if (!opts_set->x_flag_tree_loop_distribute_patterns)
+    opts->x_flag_tree_loop_distribute_patterns = value;
+}
+
 /* Handle target- and language-independent options.  Return zero to
    generate an "unknown option" message.  Only options that need
    extra handling need to be listed here; if you simply want
@@ -1278,7 +1471,7 @@ common_handle_option (struct gcc_options *opts,
        unsigned int i;
 
        if (lang_mask == CL_DRIVER)
-         break;;
+         break;
 
        undoc_mask = ((opts->x_verbose_flag | opts->x_extra_warnings)
                      ? 0
@@ -1437,8 +1630,12 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fsanitize_:
+    case OPT_fsanitize_recover_:
       {
        const char *p = arg;
+       unsigned int *flag
+         = code == OPT_fsanitize_ ? &opts->x_flag_sanitize
+         : &opts->x_flag_sanitize_recover;
        while (*p != 0)
          {
            static const struct
@@ -1448,7 +1645,10 @@ common_handle_option (struct gcc_options *opts,
              size_t len;
            } spec[] =
            {
-             { "address", SANITIZE_ADDRESS, sizeof "address" - 1 },
+             { "address", SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS,
+               sizeof "address" - 1 },
+             { "kernel-address", SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS,
+               sizeof "kernel-address" - 1 },
              { "thread", SANITIZE_THREAD, sizeof "thread" - 1 },
              { "leak", SANITIZE_LEAK, sizeof "leak" - 1 },
              { "shift", SANITIZE_SHIFT, sizeof "shift" - 1 },
@@ -1462,6 +1662,25 @@ common_handle_option (struct gcc_options *opts,
              { "null", SANITIZE_NULL, sizeof "null" - 1 },
              { "signed-integer-overflow", SANITIZE_SI_OVERFLOW,
                sizeof "signed-integer-overflow" -1 },
+             { "bool", SANITIZE_BOOL, sizeof "bool" - 1 },
+             { "enum", SANITIZE_ENUM, sizeof "enum" - 1 },
+             { "float-divide-by-zero", SANITIZE_FLOAT_DIVIDE,
+               sizeof "float-divide-by-zero" - 1 },
+             { "float-cast-overflow", SANITIZE_FLOAT_CAST,
+               sizeof "float-cast-overflow" - 1 },
+             { "bounds", SANITIZE_BOUNDS, sizeof "bounds" - 1 },
+             { "bounds-strict", SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT,
+               sizeof "bounds-strict" - 1 },
+             { "alignment", SANITIZE_ALIGNMENT, sizeof "alignment" - 1 },
+             { "nonnull-attribute", SANITIZE_NONNULL_ATTRIBUTE,
+               sizeof "nonnull-attribute" - 1 },
+             { "returns-nonnull-attribute",
+               SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
+               sizeof "returns-nonnull-attribute" - 1 },
+             { "object-size", SANITIZE_OBJECT_SIZE,
+               sizeof "object-size" - 1 },
+             { "vptr", SANITIZE_VPTR, sizeof "vptr" - 1 },
+             { "all", ~0, sizeof "all" - 1 },
              { NULL, 0, 0 }
            };
            const char *comma;
@@ -1485,31 +1704,69 @@ common_handle_option (struct gcc_options *opts,
                  && memcmp (p, spec[i].name, len) == 0)
                {
                  /* Handle both -fsanitize and -fno-sanitize cases.  */
-                 if (value)
-                   flag_sanitize |= spec[i].flag;
+                 if (value && spec[i].flag == ~0U)
+                   {
+                     if (code == OPT_fsanitize_)
+                       error_at (loc, "-fsanitize=all option is not valid");
+                     else
+                       *flag |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD
+                                  | SANITIZE_LEAK);
+                   }
+                 else if (value)
+                   *flag |= spec[i].flag;
                  else
-                   flag_sanitize &= ~spec[i].flag;
+                   *flag &= ~spec[i].flag;
                  found = true;
                  break;
                }
 
            if (! found)
-             warning_at (loc, 0,
-                         "unrecognized argument to -fsanitize= option: %q.*s",
-                         (int) len, p);
+             error_at (loc,
+                       "unrecognized argument to -fsanitize%s= option: %q.*s",
+                       code == OPT_fsanitize_ ? "" : "-recover", (int) len, p);
 
            if (comma == NULL)
              break;
            p = comma + 1;
          }
 
-       /* When instrumenting the pointers, we don't want to remove
-          the null pointer checks.  */
-       if (flag_sanitize & SANITIZE_NULL)
-         opts->x_flag_delete_null_pointer_checks = 0;
+       if (code != OPT_fsanitize_)
+         break;
+
+       /* Kernel ASan implies normal ASan but does not yet support
+          all features.  */
+       if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+         {
+           maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
+                                  opts->x_param_values,
+                                  opts_set->x_param_values);
+           maybe_set_param_value (PARAM_ASAN_GLOBALS, 0,
+                                  opts->x_param_values,
+                                  opts_set->x_param_values);
+           maybe_set_param_value (PARAM_ASAN_STACK, 0,
+                                  opts->x_param_values,
+                                  opts_set->x_param_values);
+           maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
+                                  opts->x_param_values,
+                                  opts_set->x_param_values);
+         }
+
        break;
       }
 
+    case OPT_fasan_shadow_offset_:
+      /* Deferred.  */
+      break;
+
+    case OPT_fsanitize_recover:
+      if (value)
+       opts->x_flag_sanitize_recover
+         |= SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT;
+      else
+       opts->x_flag_sanitize_recover
+         &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT);
+      break;
+
     case OPT_O:
     case OPT_Os:
     case OPT_Ofast:
@@ -1587,8 +1844,12 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fdbg_cnt_:
+      /* Deferred.  */
+      break;
+
     case OPT_fdbg_cnt_list:
       /* Deferred.  */
+      opts->x_exit_after_options = true;
       break;
 
     case OPT_fdebug_prefix_map_:
@@ -1604,8 +1865,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fdiagnostics_color_:
-      pp_show_color (dc->printer)
-       = colorize_init ((diagnostic_color_rule_t) value);
+      diagnostic_color_init (dc, value);
       break;
 
     case OPT_fdiagnostics_show_option:
@@ -1655,6 +1915,17 @@ common_handle_option (struct gcc_options *opts,
       /* Deferred.  */
       break;
 
+    case OPT_foffload_:
+      /* Deferred.  */
+      break;
+
+#ifndef ACCEL_COMPILER
+    case OPT_foffload_abi_:
+      error_at (loc, "-foffload-abi option can be specified only for "
+               "offload compiler");
+      break;
+#endif
+
     case OPT_fpack_struct_:
       if (value <= 0 || (value & (value - 1)) || value > 16)
        error_at (loc,
@@ -1675,48 +1946,30 @@ common_handle_option (struct gcc_options *opts,
       value = true;
       /* No break here - do -fprofile-use processing. */
     case OPT_fprofile_use:
-      if (!opts_set->x_flag_branch_probabilities)
-       opts->x_flag_branch_probabilities = value;
-      if (!opts_set->x_flag_profile_values)
-       opts->x_flag_profile_values = value;
-      if (!opts_set->x_flag_unroll_loops)
-       opts->x_flag_unroll_loops = value;
-      if (!opts_set->x_flag_peel_loops)
-       opts->x_flag_peel_loops = value;
-      if (!opts_set->x_flag_tracer)
-       opts->x_flag_tracer = value;
-      if (!opts_set->x_flag_value_profile_transformations)
-       opts->x_flag_value_profile_transformations = value;
-      if (!opts_set->x_flag_inline_functions)
-       opts->x_flag_inline_functions = value;
-      if (!opts_set->x_flag_ipa_cp)
-       opts->x_flag_ipa_cp = value;
-      if (!opts_set->x_flag_ipa_cp_clone
-         && value && opts->x_flag_ipa_cp)
-       opts->x_flag_ipa_cp_clone = value;
-      if (!opts_set->x_flag_predictive_commoning)
-       opts->x_flag_predictive_commoning = value;
-      if (!opts_set->x_flag_unswitch_loops)
-       opts->x_flag_unswitch_loops = value;
-      if (!opts_set->x_flag_gcse_after_reload)
-       opts->x_flag_gcse_after_reload = value;
-      if (!opts_set->x_flag_tree_loop_vectorize
-          && !opts_set->x_flag_tree_vectorize)
-       opts->x_flag_tree_loop_vectorize = value;
-      if (!opts_set->x_flag_tree_slp_vectorize
-          && !opts_set->x_flag_tree_vectorize)
-       opts->x_flag_tree_slp_vectorize = value;
-      if (!opts_set->x_flag_vect_cost_model)
-       opts->x_flag_vect_cost_model = VECT_COST_MODEL_DYNAMIC;
-      if (!opts_set->x_flag_tree_loop_distribute_patterns)
-       opts->x_flag_tree_loop_distribute_patterns = value;
-      /* Indirect call profiling should do all useful transformations
-        speculative devirtualization does.  */
+      enable_fdo_optimizations (opts, opts_set, value);
+      if (!opts_set->x_flag_profile_reorder_functions)
+         opts->x_flag_profile_reorder_functions = value;
+       /* Indirect call profiling should do all useful transformations
+          speculative devirtualization does.  */
       if (!opts_set->x_flag_devirtualize_speculatively
          && opts->x_flag_value_profile_transformations)
        opts->x_flag_devirtualize_speculatively = false;
       break;
 
+    case OPT_fauto_profile_:
+      opts->x_auto_profile_file = xstrdup (arg);
+      opts->x_flag_auto_profile = true;
+      value = true;
+      /* No break here - do -fauto-profile processing. */
+    case OPT_fauto_profile:
+      enable_fdo_optimizations (opts, opts_set, value);
+      if (!opts_set->x_flag_profile_correction)
+       opts->x_flag_profile_correction = value;
+      maybe_set_param_value (
+       PARAM_EARLY_INLINER_MAX_ITERATIONS, 10,
+       opts->x_param_values, opts_set->x_param_values);
+      break;
+
     case OPT_fprofile_generate_:
       opts->x_profile_data_prefix = xstrdup (arg);
       value = true;
@@ -1731,7 +1984,7 @@ common_handle_option (struct gcc_options *opts,
       /* 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)
+      if (!opts_set->x_flag_ipa_reference)
         opts->x_flag_ipa_reference = false;
       break;
 
@@ -1790,7 +2043,7 @@ common_handle_option (struct gcc_options *opts,
                             ? STATIC_BUILTIN_STACK_CHECK
                             : GENERIC_STACK_CHECK;
       else
-       warning_at (loc, 0, "unknown stack check parameter \"%s\"", arg);
+       warning_at (loc, 0, "unknown stack check parameter %qs", arg);
       break;
 
     case OPT_fstack_limit:
@@ -1811,13 +2064,8 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_g:
-      /* -g by itself should force -g2.  */
-      if (*arg == '\0')
-       set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "2", opts, opts_set,
-                        loc);
-      else
-       set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
-                        loc);
+      set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
+                       loc);
       break;
 
     case OPT_gcoff:
@@ -1837,7 +2085,7 @@ common_handle_option (struct gcc_options *opts,
       
       /* FALLTHRU */
     case OPT_gdwarf_:
-      if (value < 2 || value > 4)
+      if (value < 2 || value > 5)
        error_at (loc, "dwarf version %d is not supported", value);
       else
        opts->x_dwarf_version = value;
@@ -1869,9 +2117,14 @@ common_handle_option (struct gcc_options *opts,
                       loc);
       break;
 
+    case OPT_gz:
+    case OPT_gz_:
+      /* Handled completely via specs.  */
+      break;
+
     case OPT_pedantic_errors:
       dc->pedantic_errors = 1;
-      control_warning_option (OPT_Wpedantic, DK_ERROR, value,
+      control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
                              loc, lang_mask,
                              handlers, opts, opts_set,
                               dc);
@@ -1905,6 +2158,11 @@ common_handle_option (struct gcc_options *opts,
        opts->x_flag_wrapv = 0;
       break;
 
+    case OPT_fipa_icf:
+      opts->x_flag_ipa_icf_functions = value;
+      opts->x_flag_ipa_icf_variables = value;
+      break;
+
     default:
       /* If the flag was handled in a standard way, assume the lack of
         processing here is intentional.  */
@@ -1932,14 +2190,21 @@ handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
              arg);
   else
     {
-      value = integral_argument (equal + 1);
-      if (value == -1)
-       error_at (loc, "invalid --param value %qs", equal + 1);
+      *equal = '\0';
+
+      enum compiler_param index;
+      if (!find_param (arg, &index))
+       error_at (loc, "invalid --param name %qs", arg);
       else
        {
-         *equal = '\0';
-         set_param_value (arg, value,
-                          opts->x_param_values, opts_set->x_param_values);
+         if (!param_string_value_p (index, equal + 1, &value))
+           value = integral_argument (equal + 1);
+
+         if (value == -1)
+           error_at (loc, "invalid --param value %qs", equal + 1);
+         else
+           set_param_value (arg, value,
+                            opts->x_param_values, opts_set->x_param_values);
        }
     }
 
@@ -2044,7 +2309,7 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
 
          if (extended == 2)
            {
-#ifdef DWARF2_DEBUGGING_INFO
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
              opts->x_write_symbols = DWARF2_DEBUG;
 #elif defined DBX_DEBUGGING_INFO
              opts->x_write_symbols = DBX_DEBUG;
@@ -2061,25 +2326,27 @@ 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_at (loc, "debug format \"%s\" conflicts with prior selection",
+       error_at (loc, "debug format %qs 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.  */
+  /* A debug flag without a level defaults to level 2.
+     If off or at level 1, set it to level 2, but if already
+     at level 3, don't lower it.  */ 
   if (*arg == '\0')
     {
-      if (!opts->x_debug_info_level)
+      if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
        opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
     }
   else
     {
       int argval = integral_argument (arg);
       if (argval == -1)
-       error_at (loc, "unrecognised debug output level \"%s\"", arg);
+       error_at (loc, "unrecognised debug output level %qs", arg);
       else if (argval > 3)
-       error_at (loc, "debug output level %s is too high", arg);
+       error_at (loc, "debug output level %qs is too high", arg);
       else
        opts->x_debug_info_level = (enum debug_info_levels) argval;
     }
@@ -2099,10 +2366,11 @@ setup_core_dumping (diagnostic_context *dc)
   {
     struct rlimit rlim;
     if (getrlimit (RLIMIT_CORE, &rlim) != 0)
-      fatal_error ("getting core file size maximum limit: %m");
+      fatal_error (input_location, "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");
+      fatal_error (input_location,
+                  "setting core file size limit to maximum: %m");
   }
 #endif
   diagnostic_abort_on_error (dc);
@@ -2172,14 +2440,18 @@ enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
   strcpy (new_option + 1, arg);
   option_index = find_opt (new_option, lang_mask);
   if (option_index == OPT_SPECIAL_unknown)
-    {
-      error_at (loc, "-Werror=%s: no option -%s", arg, new_option);
-    }
+    error_at (loc, "-Werror=%s: no option -%s", arg, new_option);
+  else if (!(cl_options[option_index].flags & CL_WARNING))
+    error_at (loc, "-Werror=%s: -%s is not an option that controls warnings",
+             arg, new_option);
   else
     {
       const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+      const char *arg = NULL;
 
-      control_warning_option (option_index, (int) kind, value,
+      if (cl_options[option_index].flags & CL_JOINED)
+       arg = new_option + cl_options[option_index].opt_len;
+      control_warning_option (option_index, (int) kind, arg, value,
                              loc, lang_mask,
                              handlers, opts, opts_set, dc);
     }
@@ -2209,14 +2481,10 @@ option_name (diagnostic_context *context, int option_index,
        return xstrdup (cl_options[option_index].opt_text);
     }
   /* A warning without option classified as an error.  */
-  else if (orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
-          || diag_kind == DK_WARNING)
-    {
-      if (context->warning_as_error_requested)
-       return xstrdup (cl_options[OPT_Werror].opt_text);
-      else
-       return xstrdup (_("enabled by default"));
-    }
+  else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
+           || diag_kind == DK_WARNING)
+          && context->warning_as_error_requested)
+    return xstrdup (cl_options[OPT_Werror].opt_text);
   else
     return NULL;
 }