OSDN Git Service

PR rtl-optimization/21299
[pf3gnuchains/gcc-fork.git] / gcc / opts.c
index 5a4873c..01ec30d 100644 (file)
@@ -1,5 +1,5 @@
 /* Command line option handling.
 /* Command line option handling.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    Contributed by Neil Booth.
 
 This file is part of GCC.
    Contributed by Neil Booth.
 
 This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm_p.h"              /* For OPTIMIZATION_OPTIONS.  */
 #include "insn-attr.h"         /* For INSN_SCHEDULING.  */
 #include "target.h"
 #include "tm_p.h"              /* For OPTIMIZATION_OPTIONS.  */
 #include "insn-attr.h"         /* For INSN_SCHEDULING.  */
 #include "target.h"
+#include "tree-pass.h"
 
 /* Value of the -G xx switch, and whether it was passed or not.  */
 unsigned HOST_WIDE_INT g_switch_value;
 
 /* Value of the -G xx switch, and whether it was passed or not.  */
 unsigned HOST_WIDE_INT g_switch_value;
@@ -76,6 +77,17 @@ enum debug_info_level debug_info_level = DINFO_LEVEL_NONE;
    write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG.  */
 bool use_gnu_debug_info_extensions;
 
    write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG.  */
 bool use_gnu_debug_info_extensions;
 
+/* The default visibility for all symbols (unless overridden) */
+enum symbol_visibility default_visibility = VISIBILITY_DEFAULT;
+
+/* Disable unit-at-a-time for frontends that might be still broken in this
+   respect.  */
+  
+bool no_unit_at_a_time_default;
+
+/* Global visibility options.  */
+struct visibility_flags visibility_options;
+
 /* Columns of --help display.  */
 static unsigned int columns = 80;
 
 /* Columns of --help display.  */
 static unsigned int columns = 80;
 
@@ -93,8 +105,8 @@ static bool flag_peel_loops_set, flag_branch_probabilities_set;
 const char **in_fnames;
 unsigned num_in_fnames;
 
 const char **in_fnames;
 unsigned num_in_fnames;
 
-static size_t find_opt (const char *, int);
-static int common_handle_option (size_t scode, const char *arg, int value);
+static int common_handle_option (size_t scode, const char *arg, int value,
+                                unsigned int lang_mask);
 static void handle_param (const char *);
 static void set_Wextra (int);
 static unsigned int handle_option (const char **argv, unsigned int lang_mask);
 static void handle_param (const char *);
 static void set_Wextra (int);
 static unsigned int handle_option (const char **argv, unsigned int lang_mask);
@@ -103,97 +115,14 @@ static void complain_wrong_lang (const char *, const struct cl_option *,
                                 unsigned int lang_mask);
 static void handle_options (unsigned int, const char **, unsigned int);
 static void wrap_help (const char *help, const char *item, unsigned int);
                                 unsigned int lang_mask);
 static void handle_options (unsigned int, const char **, unsigned int);
 static void wrap_help (const char *help, const char *item, unsigned int);
+static void print_target_help (void);
 static void print_help (void);
 static void print_param_help (void);
 static void print_help (void);
 static void print_param_help (void);
-static void print_filtered_help (unsigned int flag);
+static void print_filtered_help (unsigned int);
 static unsigned int print_switch (const char *text, unsigned int indent);
 static void set_debug_level (enum debug_info_type type, int extended,
                             const char *arg);
 
 static unsigned int print_switch (const char *text, unsigned int indent);
 static void set_debug_level (enum debug_info_type type, int extended,
                             const char *arg);
 
-/* Perform a binary search to find which option the command-line INPUT
-   matches.  Returns its index in the option array, and N_OPTS
-   (cl_options_count) on failure.
-
-   This routine is quite subtle.  A normal binary search is not good
-   enough because some options can be suffixed with an argument, and
-   multiple sub-matches can occur, e.g. input of "-pedantic" matching
-   the initial substring of "-pedantic-errors".
-
-   A more complicated example is -gstabs.  It should match "-g" with
-   an argument of "stabs".  Suppose, however, that the number and list
-   of switches are such that the binary search tests "-gen-decls"
-   before having tested "-g".  This doesn't match, and as "-gen-decls"
-   is less than "-gstabs", it will become the lower bound of the
-   binary search range, and "-g" will never be seen.  To resolve this
-   issue, opts.sh makes "-gen-decls" point, via the back_chain member,
-   to "-g" so that failed searches that end between "-gen-decls" and
-   the lexicographically subsequent switch know to go back and see if
-   "-g" causes a match (which it does in this example).
-
-   This search is done in such a way that the longest match for the
-   front end in question wins.  If there is no match for the current
-   front end, the longest match for a different front end is returned
-   (or N_OPTS if none) and the caller emits an error message.  */
-static size_t
-find_opt (const char *input, int lang_mask)
-{
-  size_t mn, mx, md, opt_len;
-  size_t match_wrong_lang;
-  int comp;
-
-  mn = 0;
-  mx = cl_options_count;
-
-  /* Find mn such this lexicographical inequality holds:
-     cl_options[mn] <= input < cl_options[mn + 1].  */
-  while (mx - mn > 1)
-    {
-      md = (mn + mx) / 2;
-      opt_len = cl_options[md].opt_len;
-      comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
-
-      if (comp < 0)
-       mx = md;
-      else
-       mn = md;
-    }
-
-  /* This is the switch that is the best match but for a different
-     front end, or cl_options_count if there is no match at all.  */
-  match_wrong_lang = cl_options_count;
-
-  /* Backtrace the chain of possible matches, returning the longest
-     one, if any, that fits best.  With current GCC switches, this
-     loop executes at most twice.  */
-  do
-    {
-      const struct cl_option *opt = &cl_options[mn];
-
-      /* Is this switch a prefix of the input?  */
-      if (!strncmp (input, opt->opt_text + 1, opt->opt_len))
-       {
-         /* If language is OK, and the match is exact or the switch
-            takes a joined argument, return it.  */
-         if ((opt->flags & lang_mask)
-             && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
-           return mn;
-
-         /* If we haven't remembered a prior match, remember this
-            one.  Any prior match is necessarily better.  */
-         if (match_wrong_lang == cl_options_count)
-           match_wrong_lang = mn;
-       }
-
-      /* Try the next possibility.  This is cl_options_count if there
-        are no more.  */
-      mn = opt->back_chain;
-    }
-  while (mn != cl_options_count);
-
-  /* Return the best wrong match, or cl_options_count if none.  */
-  return match_wrong_lang;
-}
-
 /* If ARG is a non-negative integer made up solely of digits, return its
    value, otherwise return -1.  */
 static int
 /* If ARG is a non-negative integer made up solely of digits, return its
    value, otherwise return -1.  */
 static int
@@ -222,7 +151,7 @@ write_langs (unsigned int mask)
     if (mask & (1U << n))
       len += strlen (lang_name) + 1;
 
     if (mask & (1U << n))
       len += strlen (lang_name) + 1;
 
-  result = xmalloc (len);
+  result = XNEWVEC (char, len);
   len = 0;
   for (n = 0; (lang_name = lang_names[n]) != 0; n++)
     if (mask & (1U << n))
   len = 0;
   for (n = 0; (lang_name = lang_names[n]) != 0; n++)
     if (mask & (1U << n))
@@ -249,7 +178,7 @@ complain_wrong_lang (const char *text, const struct cl_option *option,
   bad_lang = write_langs (lang_mask);
 
   /* Eventually this should become a hard error IMO.  */
   bad_lang = write_langs (lang_mask);
 
   /* Eventually this should become a hard error IMO.  */
-  warning ("command line option \"%s\" is valid for %s but not for %s",
+  warning (0, "command line option \"%s\" is valid for %s but not for %s",
           text, ok_langs, bad_lang);
 
   free (ok_langs);
           text, ok_langs, bad_lang);
 
   free (ok_langs);
@@ -270,21 +199,23 @@ handle_option (const char **argv, unsigned int lang_mask)
 
   opt = argv[0];
 
 
   opt = argv[0];
 
-  /* Drop the "no-" from negative switches.  */
-  if ((opt[1] == 'W' || opt[1] == 'f')
+  opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET);
+  if (opt_index == cl_options_count
+      && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
       && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
     {
       && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
     {
+      /* Drop the "no-" from negative switches.  */
       size_t len = strlen (opt) - 3;
 
       size_t len = strlen (opt) - 3;
 
-      dup = xmalloc (len + 1);
+      dup = XNEWVEC (char, len + 1);
       dup[0] = '-';
       dup[1] = opt[1];
       memcpy (dup + 2, opt + 5, len - 2 + 1);
       opt = dup;
       value = 0;
       dup[0] = '-';
       dup[1] = opt[1];
       memcpy (dup + 2, opt + 5, len - 2 + 1);
       opt = dup;
       value = 0;
+      opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET);
     }
 
     }
 
-  opt_index = find_opt (opt + 1, lang_mask | CL_COMMON);
   if (opt_index == cl_options_count)
     goto done;
 
   if (opt_index == cl_options_count)
     goto done;
 
@@ -298,6 +229,14 @@ handle_option (const char **argv, unsigned int lang_mask)
   /* We've recognized this switch.  */
   result = 1;
 
   /* We've recognized this switch.  */
   result = 1;
 
+  /* Check to see if the option is disabled for this configuration.  */
+  if (option->flags & CL_DISABLED)
+    {
+      error ("command line option %qs"
+            " is not supported by this configuration", opt);
+      goto done;
+    }
+
   /* Sort out any argument the switch takes.  */
   if (option->flags & CL_JOINED)
     {
   /* Sort out any argument the switch takes.  */
   if (option->flags & CL_JOINED)
     {
@@ -328,7 +267,7 @@ handle_option (const char **argv, unsigned int lang_mask)
 
   /* Now we've swallowed any potential argument, complain if this
      is a switch for a different front end.  */
 
   /* Now we've swallowed any potential argument, complain if this
      is a switch for a different front end.  */
-  if (!(option->flags & (lang_mask | CL_COMMON)))
+  if (!(option->flags & (lang_mask | CL_COMMON | CL_TARGET)))
     {
       complain_wrong_lang (argv[0], option, lang_mask);
       goto done;
     {
       complain_wrong_lang (argv[0], option, lang_mask);
       goto done;
@@ -354,24 +293,43 @@ handle_option (const char **argv, unsigned int lang_mask)
     }
 
   if (option->flag_var)
     }
 
   if (option->flag_var)
-    {
-      if (option->has_set_value)
-       {
-         if (value)
-           *option->flag_var = option->set_value;
-         else
-           *option->flag_var = !option->set_value;
-       }
-      else
-       *option->flag_var = value;
-    }
+    switch (option->var_type)
+      {
+      case CLVC_BOOLEAN:
+       *(int *) option->flag_var = value;
+       break;
+
+      case CLVC_EQUAL:
+       *(int *) option->flag_var = (value
+                                    ? option->var_value
+                                    : !option->var_value);
+       break;
+
+      case CLVC_BIT_CLEAR:
+      case CLVC_BIT_SET:
+       if ((value != 0) == (option->var_type == CLVC_BIT_SET))
+         *(int *) option->flag_var |= option->var_value;
+       else
+         *(int *) option->flag_var &= ~option->var_value;
+       if (option->flag_var == &target_flags)
+         target_flags_explicit |= option->var_value;
+       break;
+
+      case CLVC_STRING:
+       *(const char **) option->flag_var = arg;
+       break;
+      }
   
   if (option->flags & lang_mask)
     if (lang_hooks.handle_option (opt_index, arg, value) == 0)
       result = 0;
 
   if (result && (option->flags & CL_COMMON))
   
   if (option->flags & lang_mask)
     if (lang_hooks.handle_option (opt_index, arg, value) == 0)
       result = 0;
 
   if (result && (option->flags & CL_COMMON))
-    if (common_handle_option (opt_index, arg, value) == 0)
+    if (common_handle_option (opt_index, arg, value, lang_mask) == 0)
+      result = 0;
+
+  if (result && (option->flags & CL_TARGET))
+    if (!targetm.handle_option (opt_index, arg, value))
       result = 0;
 
  done:
       result = 0;
 
  done:
@@ -380,6 +338,15 @@ handle_option (const char **argv, unsigned int lang_mask)
   return result;
 }
 
   return result;
 }
 
+/* Handle FILENAME from the command line.  */
+static void
+add_input_filename (const char *filename)
+{
+  num_in_fnames++;
+  in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
+  in_fnames[num_in_fnames - 1] = filename;
+}
+
 /* Decode and handle the vector of command line options.  LANG_MASK
    contains has a single bit set representing the current
    language.  */
 /* Decode and handle the vector of command line options.  LANG_MASK
    contains has a single bit set representing the current
    language.  */
@@ -412,15 +379,6 @@ handle_options (unsigned int argc, const char **argv, unsigned int lang_mask)
     }
 }
 
     }
 }
 
-/* Handle FILENAME from the command line.  */
-void
-add_input_filename (const char *filename)
-{
-  num_in_fnames++;
-  in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
-  in_fnames[num_in_fnames - 1] = filename;
-}
-
 /* Parse command line options and set default flag values.  Do minimal
    options processing.  */
 void
 /* Parse command line options and set default flag values.  Do minimal
    options processing.  */
 void
@@ -474,7 +432,6 @@ decode_options (unsigned int argc, const char **argv)
   if (optimize >= 1)
     {
       flag_defer_pop = 1;
   if (optimize >= 1)
     {
       flag_defer_pop = 1;
-      flag_thread_jumps = 1;
 #ifdef DELAY_SLOTS
       flag_delayed_branch = 1;
 #endif
 #ifdef DELAY_SLOTS
       flag_delayed_branch = 1;
 #endif
@@ -483,19 +440,24 @@ decode_options (unsigned int argc, const char **argv)
 #endif
       flag_guess_branch_prob = 1;
       flag_cprop_registers = 1;
 #endif
       flag_guess_branch_prob = 1;
       flag_cprop_registers = 1;
-      flag_loop_optimize = 1;
       flag_if_conversion = 1;
       flag_if_conversion2 = 1;
       flag_if_conversion = 1;
       flag_if_conversion2 = 1;
+      flag_ipa_pure_const = 1;
+      flag_ipa_reference = 1;
       flag_tree_ccp = 1;
       flag_tree_dce = 1;
       flag_tree_dom = 1;
       flag_tree_dse = 1;
       flag_tree_ccp = 1;
       flag_tree_dce = 1;
       flag_tree_dom = 1;
       flag_tree_dse = 1;
-      flag_tree_pre = 1;
       flag_tree_ter = 1;
       flag_tree_live_range_split = 1;
       flag_tree_sra = 1;
       flag_tree_copyrename = 1;
       flag_tree_fre = 1;
       flag_tree_ter = 1;
       flag_tree_live_range_split = 1;
       flag_tree_sra = 1;
       flag_tree_copyrename = 1;
       flag_tree_fre = 1;
+      flag_tree_copy_prop = 1;
+      flag_tree_sink = 1;
+      flag_tree_salias = 1;
+      if (!no_unit_at_a_time_default)
+        flag_unit_at_a_time = 1;
 
       if (!optimize_size)
        {
 
       if (!optimize_size)
        {
@@ -509,17 +471,16 @@ decode_options (unsigned int argc, const char **argv)
 
   if (optimize >= 2)
     {
 
   if (optimize >= 2)
     {
+      flag_thread_jumps = 1;
       flag_crossjumping = 1;
       flag_optimize_sibling_calls = 1;
       flag_cse_follow_jumps = 1;
       flag_cse_skip_blocks = 1;
       flag_gcse = 1;
       flag_expensive_optimizations = 1;
       flag_crossjumping = 1;
       flag_optimize_sibling_calls = 1;
       flag_cse_follow_jumps = 1;
       flag_cse_skip_blocks = 1;
       flag_gcse = 1;
       flag_expensive_optimizations = 1;
-      flag_strength_reduce = 1;
+      flag_ipa_type_escape = 1;
       flag_rerun_cse_after_loop = 1;
       flag_rerun_cse_after_loop = 1;
-      flag_rerun_loop_opt = 1;
       flag_caller_saves = 1;
       flag_caller_saves = 1;
-      flag_force_mem = 1;
       flag_peephole2 = 1;
 #ifdef INSN_SCHEDULING
       flag_schedule_insns = 1;
       flag_peephole2 = 1;
 #ifdef INSN_SCHEDULING
       flag_schedule_insns = 1;
@@ -530,7 +491,15 @@ decode_options (unsigned int argc, const char **argv)
       flag_delete_null_pointer_checks = 1;
       flag_reorder_blocks = 1;
       flag_reorder_functions = 1;
       flag_delete_null_pointer_checks = 1;
       flag_reorder_blocks = 1;
       flag_reorder_functions = 1;
-      flag_unit_at_a_time = 1;
+      flag_tree_store_ccp = 1;
+      flag_tree_store_copy_prop = 1;
+      flag_tree_vrp = 1;
+
+      if (!optimize_size)
+       {
+          /* PRE tends to generate bigger code.  */
+          flag_tree_pre = 1;
+       }
     }
 
   if (optimize >= 3)
     }
 
   if (optimize >= 3)
@@ -563,8 +532,10 @@ decode_options (unsigned int argc, const char **argv)
       /* Inlining of very small functions usually reduces total size.  */
       set_param_value ("max-inline-insns-single", 5);
       set_param_value ("max-inline-insns-auto", 5);
       /* Inlining of very small functions usually reduces total size.  */
       set_param_value ("max-inline-insns-single", 5);
       set_param_value ("max-inline-insns-auto", 5);
-      set_param_value ("max-inline-insns-rtl", 10);
       flag_inline_functions = 1;
       flag_inline_functions = 1;
+
+      /* We want to crossjump as much as possible.  */
+      set_param_value ("min-crossjump-insns", 1);
     }
 
   /* Initialize whether `char' is signed.  */
     }
 
   /* Initialize whether `char' is signed.  */
@@ -575,14 +546,10 @@ decode_options (unsigned int argc, const char **argv)
 
   /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
      modify it.  */
 
   /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
      modify it.  */
-  target_flags = 0;
-  set_target_switch ("");
+  target_flags = targetm.default_target_flags;
 
 
-  /* Unwind tables are always present in an ABI-conformant IA-64
-     object file, so the default should be ON.  */
-#ifdef IA64_UNWIND_INFO
-  flag_unwind_tables = IA64_UNWIND_INFO;
-#endif
+  /* Some tagets have ABI-specified unwind tables.  */
+  flag_unwind_tables = targetm.unwind_tables_default;
 
 #ifdef OPTIMIZATION_OPTIONS
   /* Allow default optimizations to be specified on a per-machine basis.  */
 
 #ifdef OPTIMIZATION_OPTIONS
   /* Allow default optimizations to be specified on a per-machine basis.  */
@@ -617,7 +584,8 @@ decode_options (unsigned int argc, const char **argv)
         this to `2' if -Wall is used, so we can avoid giving out
         lots of errors for people who don't realize what -Wall does.  */
       if (warn_uninitialized == 1)
         this to `2' if -Wall is used, so we can avoid giving out
         lots of errors for people who don't realize what -Wall does.  */
       if (warn_uninitialized == 1)
-       warning ("-Wuninitialized is not supported without -O");
+       warning (OPT_Wuninitialized,
+                "-Wuninitialized is not supported without -O");
     }
 
   if (flag_really_no_inline == 2)
     }
 
   if (flag_really_no_inline == 2)
@@ -625,16 +593,42 @@ decode_options (unsigned int argc, const char **argv)
 
   /* The optimization to partition hot and cold basic blocks into separate
      sections of the .o and executable files does not work (currently)
 
   /* The optimization to partition hot and cold basic blocks into separate
      sections of the .o and executable files does not work (currently)
-     with exception handling.  If flag_exceptions is turned on we need to
+     with exception handling.  This is because there is no support for
+     generating unwind info.  If flag_exceptions is turned on we need to
      turn off the partitioning optimization.  */
 
   if (flag_exceptions && flag_reorder_blocks_and_partition)
     {
      turn off the partitioning optimization.  */
 
   if (flag_exceptions && flag_reorder_blocks_and_partition)
     {
-      warning 
+      inform 
            ("-freorder-blocks-and-partition does not work with exceptions");
       flag_reorder_blocks_and_partition = 0;
       flag_reorder_blocks = 1;
     }
            ("-freorder-blocks-and-partition does not work with exceptions");
       flag_reorder_blocks_and_partition = 0;
       flag_reorder_blocks = 1;
     }
+
+  /* If user requested unwind info, then turn off the partitioning
+     optimization.  */
+
+  if (flag_unwind_tables && ! targetm.unwind_tables_default
+      && flag_reorder_blocks_and_partition)
+    {
+      inform ("-freorder-blocks-and-partition does not support unwind info");
+      flag_reorder_blocks_and_partition = 0;
+      flag_reorder_blocks = 1;
+    }
+
+  /* If the target requested unwind info, then turn off the partitioning
+     optimization with a different message.  Likewise, if the target does not
+     support named sections.  */
+
+  if (flag_reorder_blocks_and_partition
+      && (!targetm.have_named_sections
+         || (flag_unwind_tables && targetm.unwind_tables_default)))
+    {
+      inform 
+       ("-freorder-blocks-and-partition does not work on this architecture");
+      flag_reorder_blocks_and_partition = 0;
+      flag_reorder_blocks = 1;
+    }
 }
 
 /* Handle target- and language-independent options.  Return zero to
 }
 
 /* Handle target- and language-independent options.  Return zero to
@@ -643,7 +637,8 @@ decode_options (unsigned int argc, const char **argv)
    VALUE assigned to a variable, it happens automatically.  */
 
 static int
    VALUE assigned to a variable, it happens automatically.  */
 
 static int
-common_handle_option (size_t scode, const char *arg, int value)
+common_handle_option (size_t scode, const char *arg, int value,
+                     unsigned int lang_mask)
 {
   enum opt_code code = (enum opt_code) scode;
 
 {
   enum opt_code code = (enum opt_code) scode;
 
@@ -659,7 +654,7 @@ common_handle_option (size_t scode, const char *arg, int value)
       break;
 
     case OPT__target_help:
       break;
 
     case OPT__target_help:
-      display_target_options ();
+      print_target_help ();
       exit_after_options = true;
       break;
 
       exit_after_options = true;
       break;
 
@@ -683,6 +678,33 @@ common_handle_option (size_t scode, const char *arg, int value)
       set_Wextra (value);
       break;
 
       set_Wextra (value);
       break;
 
+    case OPT_Werror_:
+      {
+       char *new_option;
+       int option_index;
+       new_option = XNEWVEC (char, strlen (arg) + 2);
+       new_option[0] = 'W';
+       strcpy (new_option+1, arg);
+       option_index = find_opt (new_option, lang_mask);
+       if (option_index == N_OPTS)
+         {
+           error ("-Werror-%s: No option -%s", arg, new_option);
+         }
+       else
+         {
+           int kind = value ? DK_ERROR : DK_WARNING;
+           diagnostic_classify_diagnostic (global_dc, option_index, kind);
+
+           /* -Werror=foo implies -Wfoo.  */
+           if (cl_options[option_index].var_type == CLVC_BOOLEAN
+               && cl_options[option_index].flag_var
+               && kind == DK_ERROR)
+             *(int *) cl_options[option_index].flag_var = 1;
+           free (new_option);
+         }
+      }
+      break;
+
     case OPT_Wextra:
       set_Wextra (value);
       break;
     case OPT_Wextra:
       set_Wextra (value);
       break;
@@ -766,6 +788,10 @@ common_handle_option (size_t scode, const char *arg, int value)
        return 0;
       break;
 
        return 0;
       break;
 
+    case OPT_fdiagnostics_show_option:
+      global_dc->show_option_requested = true;
+      break;
+
     case OPT_fdump_:
       if (!dump_switch_p (arg))
        return 0;
     case OPT_fdump_:
       if (!dump_switch_p (arg))
        return 0;
@@ -783,13 +809,22 @@ common_handle_option (size_t scode, const char *arg, int value)
     case OPT_finline_limit_eq:
       set_param_value ("max-inline-insns-single", value / 2);
       set_param_value ("max-inline-insns-auto", value / 2);
     case OPT_finline_limit_eq:
       set_param_value ("max-inline-insns-single", value / 2);
       set_param_value ("max-inline-insns-auto", value / 2);
-      set_param_value ("max-inline-insns-rtl", value);
       break;
 
     case OPT_fmessage_length_:
       pp_set_line_maximum_length (global_dc->printer, value);
       break;
 
       break;
 
     case OPT_fmessage_length_:
       pp_set_line_maximum_length (global_dc->printer, value);
       break;
 
+    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);
+      else
+       {
+         initial_max_fld_align = value;
+         maximum_field_alignment = value * BITS_PER_UNIT;
+       }
+      break;
+
     case OPT_fpeel_loops:
       flag_peel_loops_set = true;
       break;
     case OPT_fpeel_loops:
       flag_peel_loops_set = true;
       break;
@@ -826,8 +861,23 @@ common_handle_option (size_t scode, const char *arg, int value)
       flag_profile_values_set = true;
       break;
 
       flag_profile_values_set = true;
       break;
 
+    case OPT_fvisibility_:
+      {
+        if (!strcmp(arg, "default"))
+          default_visibility = VISIBILITY_DEFAULT;
+        else if (!strcmp(arg, "internal"))
+          default_visibility = VISIBILITY_INTERNAL;
+        else if (!strcmp(arg, "hidden"))
+          default_visibility = VISIBILITY_HIDDEN;
+        else if (!strcmp(arg, "protected"))
+          default_visibility = VISIBILITY_PROTECTED;
+        else
+          error ("unrecognized visibility value \"%s\"", arg);
+      }
+      break;
+
     case OPT_fvpt:
     case OPT_fvpt:
-      flag_value_profile_transformations_set = value;
+      flag_value_profile_transformations_set = true;
       break;
 
     case OPT_frandom_seed:
       break;
 
     case OPT_frandom_seed:
@@ -880,6 +930,10 @@ common_handle_option (size_t scode, const char *arg, int value)
       stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg));
       break;
 
       stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg));
       break;
 
+    case OPT_ftree_vectorizer_verbose_:
+      vect_set_verbosity_level (arg);
+      break;
+
     case OPT_ftls_model_:
       if (!strcmp (arg, "global-dynamic"))
        flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
     case OPT_ftls_model_:
       if (!strcmp (arg, "global-dynamic"))
        flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
@@ -890,29 +944,13 @@ common_handle_option (size_t scode, const char *arg, int value)
       else if (!strcmp (arg, "local-exec"))
        flag_tls_default = TLS_MODEL_LOCAL_EXEC;
       else
       else if (!strcmp (arg, "local-exec"))
        flag_tls_default = TLS_MODEL_LOCAL_EXEC;
       else
-       warning ("unknown tls-model \"%s\"", arg);
+       warning (0, "unknown tls-model \"%s\"", arg);
       break;
 
     case OPT_ftracer:
       flag_tracer_set = true;
       break;
 
       break;
 
     case OPT_ftracer:
       flag_tracer_set = true;
       break;
 
-    case OPT_ftree_points_to_:
-      if (!strcmp (arg, "andersen"))
-#ifdef HAVE_BANSHEE
-        flag_tree_points_to = PTA_ANDERSEN;
-#else
-        warning ("Andersen's PTA not available - libbanshee not compiled.");
-#endif
-      else if (!strcmp (arg, "none"))
-       flag_tree_points_to = PTA_NONE;
-      else
-       {
-         warning ("`%s`: unknown points-to analysis algorithm", arg);
-         return 0;
-       }
-      break;
-
     case OPT_funroll_loops:
       flag_unroll_loops_set = true;
       break;
     case OPT_funroll_loops:
       flag_unroll_loops_set = true;
       break;
@@ -947,10 +985,6 @@ common_handle_option (size_t scode, const char *arg, int value)
       set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg);
       break;
 
       set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg);
       break;
 
-    case OPT_m:
-      set_target_switch (arg);
-      break;
-
     case OPT_o:
       asm_file_name = arg;
       break;
     case OPT_o:
       asm_file_name = arg;
       break;
@@ -959,13 +993,21 @@ common_handle_option (size_t scode, const char *arg, int value)
       flag_pedantic_errors = pedantic = 1;
       break;
 
       flag_pedantic_errors = pedantic = 1;
       break;
 
+    case OPT_fforce_mem:
+      warning (0, "-f[no-]force-mem is nop and option will be removed in 4.2");
+      break;
+
+    case OPT_floop_optimize:
+    case OPT_frerun_loop_opt:
+    case OPT_fstrength_reduce:
+      /* These are no-ops, preserved for backward compatibility.  */
+      break;
+
     default:
       /* If the flag was handled in a standard way, assume the lack of
         processing here is intentional.  */
     default:
       /* If the flag was handled in a standard way, assume the lack of
         processing here is intentional.  */
-      if (cl_options[scode].flag_var)
-       break;
-
-      abort ();
+      gcc_assert (cl_options[scode].flag_var);
+      break;
     }
 
   return 1;
     }
 
   return 1;
@@ -986,7 +1028,7 @@ handle_param (const char *carg)
     {
       value = integral_argument (equal + 1);
       if (value == -1)
     {
       value = integral_argument (equal + 1);
       if (value == -1)
-       error ("invalid --param value `%s'", equal + 1);
+       error ("invalid --param value %qs", equal + 1);
       else
        {
          *equal = '\0';
       else
        {
          *equal = '\0';
@@ -1044,6 +1086,7 @@ set_fast_math_flags (int set)
     {
       flag_signaling_nans = 0;
       flag_rounding_math = 0;
     {
       flag_signaling_nans = 0;
       flag_rounding_math = 0;
+      flag_cx_limited_range = 1;
     }
 }
 
     }
 }
 
@@ -1082,7 +1125,7 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg)
            }
 
          if (write_symbols == NO_DEBUG)
            }
 
          if (write_symbols == NO_DEBUG)
-           warning ("target system does not support debug output");
+           warning (0, "target system does not support debug output");
        }
     }
   else
        }
     }
   else
@@ -1111,6 +1154,27 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg)
     }
 }
 
     }
 }
 
+/* Display help for target options.  */
+static void
+print_target_help (void)
+{
+  unsigned int i;
+  static bool displayed = false;
+
+  /* Avoid double printing for --help --target-help.  */
+  if (displayed)
+    return;
+
+  displayed = true;
+  for (i = 0; i < cl_options_count; i++)
+    if ((cl_options[i].flags & (CL_TARGET | CL_UNDOCUMENTED)) == CL_TARGET)
+      {
+       printf (_("\nTarget specific options:\n"));
+       print_filtered_help (CL_TARGET);
+       break;
+      }
+}
+
 /* Output --help text.  */
 static void
 print_help (void)
 /* Output --help text.  */
 static void
 print_help (void)
@@ -1137,8 +1201,7 @@ print_help (void)
              lang_names[i]);
       print_filtered_help (1U << i);
     }
              lang_names[i]);
       print_filtered_help (1U << i);
     }
-
-  display_target_options ();
+  print_target_help ();
 }
 
 /* Print the help for --param.  */
 }
 
 /* Print the help for --param.  */
@@ -1175,7 +1238,7 @@ print_filtered_help (unsigned int flag)
   const char *help, *opt, *tab;
   static char *printed;
 
   const char *help, *opt, *tab;
   static char *printed;
 
-  if (flag == CL_COMMON)
+  if (flag == CL_COMMON || flag == CL_TARGET)
     {
       filter = flag;
       if (!printed)
     {
       filter = flag;
       if (!printed)
@@ -1322,3 +1385,65 @@ wrap_help (const char *help, const char *item, unsigned int item_width)
     }
   while (remaining);
 }
     }
   while (remaining);
 }
+
+/* Return 1 if OPTION is enabled, 0 if it is disabled, or -1 if it isn't
+   a simple on-off switch.  */
+
+int
+option_enabled (int opt_idx)
+{
+  const struct cl_option *option = &(cl_options[opt_idx]);
+  if (option->flag_var)
+    switch (option->var_type)
+      {
+      case CLVC_BOOLEAN:
+       return *(int *) option->flag_var != 0;
+
+      case CLVC_EQUAL:
+       return *(int *) option->flag_var == option->var_value;
+
+      case CLVC_BIT_CLEAR:
+       return (*(int *) option->flag_var & option->var_value) == 0;
+
+      case CLVC_BIT_SET:
+       return (*(int *) option->flag_var & option->var_value) != 0;
+
+      case CLVC_STRING:
+       break;
+      }
+  return -1;
+}
+
+/* Fill STATE with the current state of option OPTION.  Return true if
+   there is some state to store.  */
+
+bool
+get_option_state (int option, struct cl_option_state *state)
+{
+  if (cl_options[option].flag_var == 0)
+    return false;
+
+  switch (cl_options[option].var_type)
+    {
+    case CLVC_BOOLEAN:
+    case CLVC_EQUAL:
+      state->data = cl_options[option].flag_var;
+      state->size = sizeof (int);
+      break;
+
+    case CLVC_BIT_CLEAR:
+    case CLVC_BIT_SET:
+      state->ch = option_enabled (option);
+      state->data = &state->ch;
+      state->size = 1;
+      break;
+
+    case CLVC_STRING:
+      state->data = *(const char **) cl_options[option].flag_var;
+      if (state->data == 0)
+       state->data = "";
+      state->size = strlen (state->data) + 1;
+      break;
+    }
+  return true;
+}