OSDN Git Service

* common.opt (user_vect_verbosity_level): New Variable entry.
[pf3gnuchains/gcc-fork.git] / gcc / opts.c
index 085bc25..fb6e6dc 100644 (file)
@@ -21,89 +21,26 @@ 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"
-#include "tree.h"
-#include "rtl.h"
-#include "expr.h"
-#include "ggc.h"
-#include "output.h"
-#include "langhooks.h"
+#include "tm.h" /* Needed by rtl.h and used for DWARF2_DEBUGGING_INFO
+                  and DBX_DEBUGGING_INFO.  */
+#include "rtl.h" /* Needed by insn-attr.h.  */
 #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 "insn-attr.h"         /* For INSN_SCHEDULING and DELAY_SLOTS.  */
 #include "target.h"
-#include "tree-pass.h"
-#include "dbgcnt.h"
-#include "debug.h"
-#include "plugin.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
-{
-  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. */
-};
-
-/* 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
@@ -118,13 +55,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. */
@@ -155,54 +93,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;
@@ -226,292 +201,42 @@ 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,
-                                 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);
-
-/* 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,
-                   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, handlers);
-}
+static void enable_warning_as_error (const char *arg, int value,
+                                    unsigned int lang_mask,
+                                    const struct cl_option_handlers *handlers,
+                                    struct gcc_options *opts,
+                                    struct gcc_options *opts_set,
+                                    location_t loc,
+                                    diagnostic_context *dc);
 
 /* 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,
                      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
                      diagnostic_context *dc)
 {
@@ -520,28 +245,24 @@ target_handle_option (struct gcc_options *opts,
   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;
-}
-
 /* 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);
@@ -556,7 +277,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] == ',')
@@ -568,95 +289,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);
-}
+    VEC_safe_push (char_p, heap, vec, 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, 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,
-                     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, 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 ();
-
-  lang_hooks.initialize_diagnostics (global_dc);
+  *pvec = vec;
 }
 
 /* Initialize OPTS and OPTS_SET before using them in parsing options.  */
@@ -695,25 +330,10 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
   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);
-}
-
 /* If indicated by the optimization level LEVEL (-Os if SIZE is set,
    -Ofast if FAST is set), apply the option DEFAULT_OPT to OPTS and
-   OPTS_SET, diagnostic context DC, with language mask LANG_MASK and
-   option handlers HANDLERS.  */
+   OPTS_SET, diagnostic context DC, location LOC, with language mask
+   LANG_MASK and option handlers HANDLERS.  */
 
 static void
 maybe_default_option (struct gcc_options *opts,
@@ -722,6 +342,7 @@ maybe_default_option (struct gcc_options *opts,
                      int level, bool size, bool fast,
                      unsigned int lang_mask,
                      const struct cl_option_handlers *handlers,
+                     location_t loc,
                      diagnostic_context *dc)
 {
   const struct cl_option *option = &cl_options[default_opt->opt_index];
@@ -782,18 +403,20 @@ maybe_default_option (struct gcc_options *opts,
   if (enabled)
     handle_generated_option (opts, opts_set, default_opt->opt_index,
                             default_opt->arg, default_opt->value,
-                            lang_mask, DK_UNSPECIFIED, handlers, dc);
+                            lang_mask, DK_UNSPECIFIED, loc,
+                            handlers, dc);
   else if (default_opt->arg == NULL
           && !(option->flags & CL_REJECT_NEGATIVE))
     handle_generated_option (opts, opts_set, default_opt->opt_index,
                             default_opt->arg, !default_opt->value,
-                            lang_mask, DK_UNSPECIFIED, handlers, dc);
+                            lang_mask, DK_UNSPECIFIED, loc,
+                            handlers, dc);
 }
 
 /* As indicated by the optimization level LEVEL (-Os if SIZE is set,
    -Ofast if FAST is set), apply the options in array DEFAULT_OPTS to
-   OPTS and OPTS_SET, diagnostic context DC, with language mask
-   LANG_MASK and option handlers HANDLERS.  */
+   OPTS and OPTS_SET, diagnostic context DC, location LOC, with
+   language mask LANG_MASK and option handlers HANDLERS.  */
 
 static void
 maybe_default_options (struct gcc_options *opts,
@@ -802,13 +425,14 @@ maybe_default_options (struct gcc_options *opts,
                       int level, bool size, bool fast,
                       unsigned int lang_mask,
                       const struct cl_option_handlers *handlers,
+                      location_t loc,
                       diagnostic_context *dc)
 {
   size_t i;
 
   for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++)
     maybe_default_option (opts, opts_set, &default_opts[i],
-                         level, size, fast, lang_mask, handlers, dc);
+                         level, size, fast, lang_mask, handlers, loc, dc);
 }
 
 /* Table of options enabled by default at different levels.  */
@@ -897,11 +521,12 @@ 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,
                              unsigned int decoded_options_count,
+                             location_t loc,
                              unsigned int lang_mask,
                              const struct cl_option_handlers *handlers,
                              diagnostic_context *dc)
@@ -928,8 +553,9 @@ default_options_optimization (struct gcc_options *opts,
            {
              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;
@@ -964,7 +590,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, dc);
+                        ofast, lang_mask, handlers, loc, dc);
 
   /* -O2 param settings.  */
   opt2 = (opts->x_optimize >= 2);
@@ -994,66 +620,21 @@ default_options_optimization (struct gcc_options *opts,
   maybe_default_options (opts, opts_set,
                         targetm.target_option.optimization_table,
                         opts->x_optimize, opts->x_optimize_size,
-                        ofast, lang_mask, handlers, dc);
+                        ofast, lang_mask, handlers, loc, dc);
 }
 
-static void finish_options (struct gcc_options *, struct gcc_options *);
-
-/* 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.  */
-void
-decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
-               struct cl_decoded_option *decoded_options,
-               unsigned int decoded_options_count,
-               diagnostic_context *dc)
-{
-  struct cl_option_handlers handlers;
-
-  unsigned int lang_mask;
-
-  lang_mask = initial_lang_mask;
-
-  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 = 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;
-
-  /* Enable -Werror=coverage-mismatch by default */
-  enable_warning_as_error ("coverage-mismatch", 1, lang_mask, &handlers,
-                          dc);
-
-  default_options_optimization (opts, opts_set,
-                               decoded_options, decoded_options_count,
-                               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, lang_mask,
-                       &handlers, dc);
-
-  finish_options (opts, opts_set);
-}
-
-/* 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;
 
+  /* These assertions are because of the use of target hooks that
+     still access global data rather than being passed an options
+     structure pointer.  */
   gcc_assert (opts == &global_options);
   gcc_assert (opts_set = &global_options_set);
 
@@ -1092,12 +673,12 @@ 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;
     }
 
@@ -1108,7 +689,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))
     {
@@ -1118,21 +699,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 = false;
     }
 
-  if (optimize == 0)
+  if (opts->x_optimize == 0)
     {
       /* Inlining does not work if not optimizing,
         so force it not to be done.  */
@@ -1152,7 +733,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
       && 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;
@@ -1167,7 +748,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
       && 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;
@@ -1184,7 +765,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
              && targetm.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;
@@ -1199,7 +780,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
   if (!targetm.ira_cover_classes
       && opts->x_flag_ira_algorithm == IRA_ALGORITHM_CB)
     {
-      inform (input_location,
+      inform (loc,
              "-fira-algorithm=CB does not work on this architecture");
       opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
     }
@@ -1228,7 +809,7 @@ 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_lto_partition_balanced != 0) + (opts->x_flag_lto_partition_1to1 != 0)
@@ -1237,9 +818,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
       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");
-      if (!opts->x_flag_lto && !opts->x_flag_wpa && !opts->x_flag_ltrans)
-       error ("-flto-partition has no effect without -flto");
+       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
@@ -1250,8 +829,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set)
     {
       if (!targetm.supports_split_stack (true))
        {
-         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;
        }
     }
@@ -1311,11 +890,11 @@ 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 i;
   const char *help;
-  static char *printed = NULL;
   bool found = false;
   bool displayed = false;
 
@@ -1342,12 +921,12 @@ 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);
 
   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;
@@ -1372,10 +951,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)
@@ -1407,14 +986,15 @@ print_filtered_help (unsigned int include_flags,
         with an option to be an indication of its current setting.  */
       if (!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");
          else
            strcpy (new_help, "\t");
 
-         if (flag_var != NULL)
+         if (flag_var != NULL
+             && option->var_type != CLVC_DEFER)
            {
              if (option->flags & CL_JOINED)
                {
@@ -1430,7 +1010,7 @@ print_filtered_help (unsigned int include_flags,
                             "%#x", * (int *) flag_var);
                }
              else
-               strcat (new_help, option_enabled (i, &global_options)
+               strcat (new_help, option_enabled (i, opts)
                        ? _("[enabled]") : _("[disabled]"));
            }
 
@@ -1469,18 +1049,19 @@ print_filtered_help (unsigned int include_flags,
 /* 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.  */
 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 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.  */
@@ -1488,7 +1069,7 @@ print_specific_help (unsigned int include_flags,
 
   /* 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;
 
@@ -1498,12 +1079,12 @@ print_specific_help (unsigned int include_flags,
          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.  */
@@ -1569,7 +1150,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);
 }
 
 /* Handle target- and language-independent options.  Return zero to
@@ -1577,11 +1159,12 @@ 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,
                      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
+                     location_t loc,
                      const struct cl_option_handlers *handlers,
                      diagnostic_context *dc)
 {
@@ -1598,7 +1181,7 @@ common_handle_option (struct gcc_options *opts,
   switch (code)
     {
     case OPT__param:
-      handle_param (opts, opts_set, arg);
+      handle_param (opts, opts_set, loc, arg);
       break;
 
     case OPT__help:
@@ -1613,20 +1196,20 @@ common_handle_option (struct gcc_options *opts,
        /* 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);
        /* 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);
        /* 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);
+       opts->x_exit_after_options = true;
        break;
       }
 
     case OPT__target_help:
-      print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0);
-      exit_after_options = true;
+      print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts);
+      opts->x_exit_after_options = true;
 
       /* Allow the target a chance to give the user some additional information.  */
       if (targetm.help)
@@ -1651,7 +1234,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;
@@ -1728,17 +1311,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;
@@ -1746,13 +1330,13 @@ 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);
+       opts->x_exit_after_options = true;
        break;
       }
 
     case OPT__version:
-      exit_after_options = true;
+      opts->x_exit_after_options = true;
       break;
 
     case OPT_O:
@@ -1762,7 +1346,8 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_Werror_:
-      enable_warning_as_error (arg, value, lang_mask, handlers, dc);
+      enable_warning_as_error (arg, value, lang_mask, handlers,
+                              opts, opts_set, loc, dc);
       break;
 
     case OPT_Wlarger_than_:
@@ -1807,15 +1392,12 @@ 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_:
-      fix_register (arg, 0, 1);
-      break;
-
     case OPT_fcall_saved_:
-      fix_register (arg, 0, 0);
+      /* Deferred.  */
       break;
 
     case OPT_fcompare_debug_second:
@@ -1823,15 +1405,12 @@ common_handle_option (struct gcc_options *opts,
       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_:
@@ -1849,8 +1428,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fdump_:
-      if (!dump_switch_p (arg))
-       return false;
+      /* Deferred.  */
       break;
 
     case OPT_ffp_contract_:
@@ -1862,7 +1440,7 @@ common_handle_option (struct gcc_options *opts,
       else if (!strcmp (arg, "fast"))
        opts->x_flag_fp_contract_mode = FP_CONTRACT_FAST;
       else
-       error ("unknown floating point contraction style \"%s\"", arg);
+       error_at (loc, "unknown floating point contraction style \"%s\"", arg);
       break;
 
     case OPT_fexcess_precision_:
@@ -1871,7 +1449,7 @@ common_handle_option (struct gcc_options *opts,
       else if (!strcmp (arg, "standard"))
        opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
       else
-       error ("unknown excess precision style \"%s\"", arg);
+       error_at (loc, "unknown excess precision style \"%s\"", arg);
       break;
 
     case OPT_ffast_math:
@@ -1883,7 +1461,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_ffixed_:
-      fix_register (arg, 1, 1);
+      /* Deferred.  */
       break;
 
     case OPT_finline_limit_:
@@ -1895,12 +1473,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_:
@@ -1909,36 +1487,20 @@ 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_:
-#ifdef ENABLE_PLUGIN
-      add_new_plugin (arg);
-#else
-      error ("plugin support is disabled; configure with --enable-plugin");
-#endif
-      break;
-
     case OPT_fplugin_arg_:
-#ifdef ENABLE_PLUGIN
-      parse_plugin_arg_opt (arg);
-#else
-      error ("plugin support is disabled; configure with --enable-plugin");
-#endif
-      break;
-
-    case OPT_fprofile_dir_:
-      profile_data_prefix = xstrdup (arg);
+      /* Deferred.  */
       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. */
@@ -1971,7 +1533,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:
@@ -2000,7 +1562,7 @@ common_handle_option (struct gcc_options *opts,
         else if (!strcmp(arg, "protected"))
           opts->x_default_visibility = VISIBILITY_PROTECTED;
         else
-          error ("unrecognized visibility value \"%s\"", arg);
+          error_at (loc, "unrecognized visibility value \"%s\"", arg);
       }
       break;
 
@@ -2008,16 +1570,16 @@ common_handle_option (struct gcc_options *opts,
       /* 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;
@@ -2049,32 +1611,23 @@ common_handle_option (struct gcc_options *opts,
                             ? 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:
       /* The real switch is -fno-stack-limit.  */
       if (value)
        return false;
-      stack_limit_rtx = NULL_RTX;
+      /* Deferred.  */
       break;
 
     case OPT_fstack_limit_register_:
-      {
-       int reg = decode_reg_name (arg);
-       if (reg < 0)
-         error ("unrecognized register name \"%s\"", arg);
-       else
-         stack_limit_rtx = gen_rtx_REG (Pmode, reg);
-      }
-      break;
-
     case OPT_fstack_limit_symbol_:
-      stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg));
+      /* Deferred.  */
       break;
 
     case OPT_ftree_vectorizer_verbose_:
-      vect_set_verbosity_level (arg);
+      vect_set_verbosity_level (opts, value);
       break;
 
     case OPT_ftls_model_:
@@ -2087,7 +1640,7 @@ common_handle_option (struct gcc_options *opts,
       else if (!strcmp (arg, "local-exec"))
        opts->x_flag_tls_default = TLS_MODEL_LOCAL_EXEC;
       else
-       warning (0, "unknown tls-model \"%s\"", arg);
+       warning_at (loc, 0, "unknown tls-model \"%s\"", arg);
       break;
 
     case OPT_fira_algorithm_:
@@ -2096,7 +1649,7 @@ common_handle_option (struct gcc_options *opts,
       else if (!strcmp (arg, "priority"))
        opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
       else
-       warning (0, "unknown ira algorithm \"%s\"", arg);
+       warning_at (loc, 0, "unknown ira algorithm \"%s\"", arg);
       break;
 
     case OPT_fira_region_:
@@ -2107,41 +1660,44 @@ common_handle_option (struct gcc_options *opts,
       else if (!strcmp (arg, "mixed"))
        opts->x_flag_ira_region = IRA_REGION_MIXED;
       else
-       warning (0, "unknown ira region \"%s\"", arg);
+       warning_at (loc, 0, "unknown ira region \"%s\"", arg);
       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, "");
+      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:
@@ -2157,6 +1713,10 @@ common_handle_option (struct gcc_options *opts,
       dc->dc_inhibit_warnings = true;
       break;
 
+    case OPT_fmax_errors_:
+      dc->max_errors = value;
+      break;
+
     case OPT_fuse_linker_plugin:
       /* No-op. Used by the driver and passed to us because it starts with f.*/
       break;
@@ -2174,7 +1734,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;
@@ -2182,12 +1742,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';
@@ -2243,15 +1804,15 @@ set_unsafe_math_optimizations_flags (struct gcc_options *opts, int set)
   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
@@ -2266,139 +1827,147 @@ 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:
-       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);
+  int c;
 
-  if (flag_var == 0)
-    return false;
-
-  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;
+  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_STRING:
-      state->data = *(const char **) flag_var;
-      if (state->data == 0)
-       state->data = "";
-      state->size = strlen ((const char *) state->data) + 1;
-      break;
-    }
-  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
-   mask LANG_MASK, option handlers HANDLERS) as an error for
-   diagnostic context DC (possibly NULL).  This is used by
-   -Werror=.  */
+   mask LANG_MASK, option handlers HANDLERS) as an error for option
+   structures OPTS and OPTS_SET, diagnostic context DC (possibly
+   NULL), location LOC.  This is used by -Werror=.  */
 
-void
+static void
 enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
                         const struct cl_option_handlers *handlers,
-                        diagnostic_context *dc)
+                        struct gcc_options *opts,
+                        struct gcc_options *opts_set,
+                        location_t loc, diagnostic_context *dc)
 {
   char *new_option;
   int option_index;
@@ -2409,31 +1978,15 @@ 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
     {
-      const struct cl_option *option = &cl_options[option_index];
       const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
 
-      if (option->alias_target != N_OPTS)
-       option_index = option->alias_target;
-      if (option_index == OPT_SPECIAL_ignore)
-       return;
-      if (dc)
-       diagnostic_classify_diagnostic (dc, option_index, kind,
-                                       UNKNOWN_LOCATION);
-      if (kind == DK_ERROR)
-       {
-         const struct cl_option * const option = cl_options + option_index;
-
-         /* -Werror=foo implies -Wfoo.  */
-         if (option->var_type == CLVC_BOOLEAN)
-           handle_generated_option (&global_options, &global_options_set,
-                                    option_index, NULL, value, lang_mask,
-                                    (int)kind, handlers,
-                                    dc);
-       }
+      control_warning_option (option_index, (int) kind, value,
+                             loc, lang_mask,
+                             handlers, opts, opts_set, dc);
     }
   free (new_option);
 }