OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / toplev.c
index 550574f..fab180d 100644 (file)
@@ -1,6 +1,7 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,8 +17,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
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This is the top level of cc1/c++.
    It parses command args, opens files, invokes the various passes
@@ -145,7 +146,7 @@ location_t unknown_location = { NULL, 0 };
 
 /* Used to enable -fvar-tracking, -fweb and -frename-registers according
    to optimize and default_debug_hooks in process_options ().  */
-#define AUTODETECT_FLAG_VAR_TRACKING 2
+#define AUTODETECT_VALUE 2
 
 /* Current position in real source file.  */
 
@@ -289,6 +290,14 @@ const char *aux_info_file_name;
 
 int flag_shlib;
 
+/* Generate code for GNU or NeXT Objective-C runtime environment.  */
+
+#ifdef NEXT_OBJC_RUNTIME
+int flag_next_runtime = 1;
+#else
+int flag_next_runtime = 0;
+#endif
+
 /* Set to the default thread-local storage (tls) model to use.  */
 
 enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
@@ -326,9 +335,9 @@ rtx stack_limit_rtx;
 int flag_renumber_insns = 1;
 
 /* Nonzero if we should track variables.  When
-   flag_var_tracking == AUTODETECT_FLAG_VAR_TRACKING it will be set according
+   flag_var_tracking == AUTODETECT_VALUE it will be set according
    to optimize, debug_info_level and debug_hooks in process_options ().  */
-int flag_var_tracking = AUTODETECT_FLAG_VAR_TRACKING;
+int flag_var_tracking = AUTODETECT_VALUE;
 
 /* True if the user has tagged the function with the 'section'
    attribute.  */
@@ -374,35 +383,6 @@ static const param_info lang_independent_params[] = {
   { NULL, 0, 0, 0, NULL }
 };
 
-#ifdef TARGET_SWITCHES
-/* Here is a table, controlled by the tm.h file, listing each -m switch
-   and which bits in `target_switches' it should set or clear.
-   If VALUE is positive, it is bits to set.
-   If VALUE is negative, -VALUE is bits to clear.
-   (The sign bit is not used so there is no confusion.)  */
-
-static const struct
-{
-  const char *const name;
-  const int value;
-  const char *const description;
-}
-target_switches[] = TARGET_SWITCHES;
-#endif
-
-/* This table is similar, but allows the switch to have a value.  */
-
-#ifdef TARGET_OPTIONS
-static const struct
-{
-  const char *const prefix;
-  const char **const variable;
-  const char *const description;
-  const char *const value;
-}
-target_options[] = TARGET_OPTIONS;
-#endif
-
 /* Output files for assembler code (real compiler output)
    and debugging dumps.  */
 
@@ -463,9 +443,9 @@ announce_function (tree decl)
   if (!quiet_flag)
     {
       if (rtl_dump_and_exit)
-       verbatim ("%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
+       fprintf (stderr, "%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
       else
-       verbatim (" %s", lang_hooks.decl_printable_name (decl, 2));
+       fprintf (stderr, " %s", lang_hooks.decl_printable_name (decl, 2));
       fflush (stderr);
       pp_needs_newline (global_dc->printer) = true;
       diagnostic_set_last_function (global_dc);
@@ -537,6 +517,12 @@ read_integral_parameter (const char *p, const char *pname, const int  defval)
   return atoi (p);
 }
 
+/* When compiling with a recent enough GCC, we use the GNU C "extern inline"
+   for floor_log2 and exact_log2; see toplev.h.  That construct, however,
+   conflicts with the ISO C++ One Definition Rule.   */
+
+#if GCC_VERSION < 3004 || !defined (__cplusplus)
+
 /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
    If X is 0, return -1.  */
 
@@ -587,6 +573,8 @@ exact_log2 (unsigned HOST_WIDE_INT x)
 #endif
 }
 
+#endif /*  GCC_VERSION < 3004 || !defined (__cplusplus)  */
+
 /* Handler for fatal signals, such as SIGSEGV.  These are transformed
    into ICE messages, which is much more user friendly.  In case the
    error printer crashes, reset the signal to prevent infinite recursion.  */
@@ -706,183 +694,196 @@ output_file_directive (FILE *asm_file, const char *input_name)
 #endif
 }
 
+/* A subroutine of wrapup_global_declarations.  We've come to the end of
+   the compilation unit.  All deferred variables should be undeferred,
+   and all incomplete decls should be finalized.  */
+
+void
+wrapup_global_declaration_1 (tree decl)
+{
+  /* We're not deferring this any longer.  Assignment is conditional to
+     avoid needlessly dirtying PCH pages.  */
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS)
+      && DECL_DEFER_OUTPUT (decl) != 0)
+    DECL_DEFER_OUTPUT (decl) = 0;
+
+  if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
+    lang_hooks.finish_incomplete_decl (decl);
+}
+
+/* A subroutine of wrapup_global_declarations.  Decide whether or not DECL
+   needs to be output.  Return true if it is output.  */
+
+bool
+wrapup_global_declaration_2 (tree decl)
+{
+  if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
+    return false;
+
+  /* Don't write out static consts, unless we still need them.
+
+     We also keep static consts if not optimizing (for debugging),
+     unless the user specified -fno-keep-static-consts.
+     ??? They might be better written into the debug information.
+     This is possible when using DWARF.
+
+     A language processor that wants static constants to be always
+     written out (even if it is not used) is responsible for
+     calling rest_of_decl_compilation itself.  E.g. the C front-end
+     calls rest_of_decl_compilation from finish_decl.
+     One motivation for this is that is conventional in some
+     environments to write things like:
+     static const char rcsid[] = "... version string ...";
+     intending to force the string to be in the executable.
+
+     A language processor that would prefer to have unneeded
+     static constants "optimized away" would just defer writing
+     them out until here.  E.g. C++ does this, because static
+     constants are often defined in header files.
+
+     ??? A tempting alternative (for both C and C++) would be
+     to force a constant to be written if and only if it is
+     defined in a main file, as opposed to an include file.  */
+
+  if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+    {
+      struct cgraph_varpool_node *node;
+      bool needed = true;
+      node = cgraph_varpool_node (decl);
+
+      if (node->finalized)
+       needed = false;
+      else if (node->alias)
+       needed = false;
+      else if (!cgraph_global_info_ready
+              && (TREE_USED (decl)
+                  || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
+       /* needed */;
+      else if (node->needed)
+       /* needed */;
+      else if (DECL_COMDAT (decl))
+       needed = false;
+      else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
+              && (optimize || !flag_keep_static_consts
+                  || DECL_ARTIFICIAL (decl)))
+       needed = false;
+
+      if (needed)
+       {
+         rest_of_decl_compilation (decl, 1, 1);
+         return true;
+       }
+    }
+
+  return false;
+}
+
 /* Do any final processing required for the declarations in VEC, of
    which there are LEN.  We write out inline functions and variables
    that have been deferred until this point, but which are required.
    Returns nonzero if anything was put out.  */
 
-int
+bool
 wrapup_global_declarations (tree *vec, int len)
 {
-  tree decl;
+  bool reconsider, output_something = false;
   int i;
-  int reconsider;
-  int output_something = 0;
 
   for (i = 0; i < len; i++)
-    {
-      decl = vec[i];
-
-      /* We're not deferring this any longer.  Assignment is
-        conditional to avoid needlessly dirtying PCH pages.  */
-      if (DECL_DEFER_OUTPUT (decl) != 0)
-       DECL_DEFER_OUTPUT (decl) = 0;
-
-      if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
-       lang_hooks.finish_incomplete_decl (decl);
-    }
+    wrapup_global_declaration_1 (vec[i]);
 
   /* Now emit any global variables or functions that we have been
      putting off.  We need to loop in case one of the things emitted
      here references another one which comes earlier in the list.  */
   do
     {
-      reconsider = 0;
+      reconsider = false;
       for (i = 0; i < len; i++)
-       {
-         decl = vec[i];
-
-         if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
-           continue;
-
-         /* Don't write out static consts, unless we still need them.
-
-            We also keep static consts if not optimizing (for debugging),
-            unless the user specified -fno-keep-static-consts.
-            ??? They might be better written into the debug information.
-            This is possible when using DWARF.
-
-            A language processor that wants static constants to be always
-            written out (even if it is not used) is responsible for
-            calling rest_of_decl_compilation itself.  E.g. the C front-end
-            calls rest_of_decl_compilation from finish_decl.
-            One motivation for this is that is conventional in some
-            environments to write things like:
-            static const char rcsid[] = "... version string ...";
-            intending to force the string to be in the executable.
-
-            A language processor that would prefer to have unneeded
-            static constants "optimized away" would just defer writing
-            them out until here.  E.g. C++ does this, because static
-            constants are often defined in header files.
-
-            ??? A tempting alternative (for both C and C++) would be
-            to force a constant to be written if and only if it is
-            defined in a main file, as opposed to an include file.  */
-
-         if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
-           {
-             struct cgraph_varpool_node *node;
-             bool needed = 1;
-             node = cgraph_varpool_node (decl);
-
-             if (node->finalized)
-               needed = 0;
-             else if (node->alias)
-               needed = 0;
-             else if (!cgraph_global_info_ready
-                      && (TREE_USED (decl)
-                          || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
-               /* needed */;
-             else if (node->needed)
-               /* needed */;
-             else if (DECL_COMDAT (decl))
-               needed = 0;
-             else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
-                      && (optimize || !flag_keep_static_consts
-                          || DECL_ARTIFICIAL (decl)))
-               needed = 0;
-
-             if (needed)
-               {
-                 reconsider = 1;
-                 rest_of_decl_compilation (decl, 1, 1);
-               }
-           }
-       }
-
+       reconsider |= wrapup_global_declaration_2 (vec[i]);
       if (reconsider)
-       output_something = 1;
+       output_something = true;
     }
   while (reconsider);
 
   return output_something;
 }
 
+/* A subroutine of check_global_declarations.  Issue appropriate warnings
+   for the global declaration DECL.  */
+
+void
+check_global_declaration_1 (tree decl)
+{
+  /* Warn about any function declared static but not defined.  We don't
+     warn about variables, because many programs have static variables
+     that exist only to get some text into the object file.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_INITIAL (decl) == 0
+      && DECL_EXTERNAL (decl)
+      && ! DECL_ARTIFICIAL (decl)
+      && ! TREE_NO_WARNING (decl)
+      && ! TREE_PUBLIC (decl)
+      && (warn_unused_function
+         || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+    {
+      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+       pedwarn ("%q+F used but never defined", decl);
+      else
+       warning (0, "%q+F declared %<static%> but never defined", decl);
+      /* This symbol is effectively an "extern" declaration now.  */
+      TREE_PUBLIC (decl) = 1;
+      assemble_external (decl);
+    }
+
+  /* Warn about static fns or vars defined but not used.  */
+  if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL)
+       /* We don't warn about "static const" variables because the
+         "rcs_id" idiom uses that construction.  */
+       || (warn_unused_variable
+          && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
+      && ! DECL_IN_SYSTEM_HEADER (decl)
+      && ! TREE_USED (decl)
+      /* The TREE_USED bit for file-scope decls is kept in the identifier,
+        to handle multiple external decls in different scopes.  */
+      && ! (DECL_NAME (decl) && TREE_USED (DECL_NAME (decl)))
+      && ! DECL_EXTERNAL (decl)
+      && ! TREE_PUBLIC (decl)
+      /* A volatile variable might be used in some non-obvious way.  */
+      && ! TREE_THIS_VOLATILE (decl)
+      /* Global register variables must be declared to reserve them.  */
+      && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+      /* Otherwise, ask the language.  */
+      && lang_hooks.decls.warn_unused_global (decl))
+    warning (0, "%q+D defined but not used", decl);
+}
+
 /* Issue appropriate warnings for the global declarations in VEC (of
-   which there are LEN).  Output debugging information for them.  */
+   which there are LEN).  */
 
 void
 check_global_declarations (tree *vec, int len)
 {
-  tree decl;
   int i;
 
   for (i = 0; i < len; i++)
-    {
-      decl = vec[i];
-
-      /* Do not emit debug information about variables that are in
-        static storage, but not defined.  */
-      if (TREE_CODE (decl) == VAR_DECL
-         && TREE_STATIC (decl)
-         && !TREE_ASM_WRITTEN (decl))
-       DECL_IGNORED_P (decl) = 1;
-      /* Warn about any function
-        declared static but not defined.
-        We don't warn about variables,
-        because many programs have static variables
-        that exist only to get some text into the object file.  */
-      if (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_INITIAL (decl) == 0
-         && DECL_EXTERNAL (decl)
-         && ! DECL_ARTIFICIAL (decl)
-         && ! TREE_NO_WARNING (decl)
-         && ! TREE_PUBLIC (decl)
-         && (warn_unused_function
-             || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
-       {
-         if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
-           pedwarn ("%J%qF used but never defined", decl, decl);
-         else
-           warning (0, "%J%qF declared %<static%> but never defined",
-                    decl, decl);
-         /* This symbol is effectively an "extern" declaration now.  */
-         TREE_PUBLIC (decl) = 1;
-         assemble_external (decl);
-       }
+    check_global_declaration_1 (vec[i]);
+}
 
-      /* Warn about static fns or vars defined but not used.  */
-      if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL)
-          /* We don't warn about "static const" variables because the
-             "rcs_id" idiom uses that construction.  */
-          || (warn_unused_variable
-              && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
-         && ! DECL_IN_SYSTEM_HEADER (decl)
-         && ! TREE_USED (decl)
-         /* The TREE_USED bit for file-scope decls is kept in the identifier,
-            to handle multiple external decls in different scopes.  */
-         && ! TREE_USED (DECL_NAME (decl))
-         && ! DECL_EXTERNAL (decl)
-         && ! TREE_PUBLIC (decl)
-         /* A volatile variable might be used in some non-obvious way.  */
-         && ! TREE_THIS_VOLATILE (decl)
-         /* Global register variables must be declared to reserve them.  */
-         && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
-         /* Otherwise, ask the language.  */
-         && lang_hooks.decls.warn_unused_global (decl))
-       warning (0, "%J%qD defined but not used", decl, decl);
-
-      /* Avoid confusing the debug information machinery when there are
-        errors.  */
-      if (errorcount == 0 && sorrycount == 0)
-       {
-         timevar_push (TV_SYMOUT);
-         (*debug_hooks->global_decl) (decl);
-         timevar_pop (TV_SYMOUT);
-       }
-    }
+/* Emit debugging information for all global declarations in VEC.  */
+
+void
+emit_debug_global_declarations (tree *vec, int len)
+{
+  int i;
+
+  /* Avoid confusing the debug information machinery when there are errors.  */
+  if (errorcount != 0 || sorrycount != 0)
+    return;
+
+  timevar_push (TV_SYMOUT);
+  for (i = 0; i < len; i++)
+    debug_hooks->global_decl (vec[i]);
+  timevar_pop (TV_SYMOUT);
 }
 
 /* Warn about a use of an identifier which was marked deprecated.  */
@@ -895,7 +896,8 @@ warn_deprecated_use (tree node)
   if (DECL_P (node))
     {
       expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));
-      warning (0, "%qs is deprecated (declared at %s:%d)",
+      warning (OPT_Wdeprecated_declarations,
+              "%qs is deprecated (declared at %s:%d)",
               IDENTIFIER_POINTER (DECL_NAME (node)),
               xloc.file, xloc.line);
     }
@@ -918,18 +920,20 @@ warn_deprecated_use (tree node)
          expanded_location xloc
            = expand_location (DECL_SOURCE_LOCATION (decl));
          if (what)
-           warning (0, "%qs is deprecated (declared at %s:%d)", what,
-                      xloc.file, xloc.line);
+           warning (OPT_Wdeprecated_declarations,
+                    "%qs is deprecated (declared at %s:%d)", what,
+                    xloc.file, xloc.line);
          else
-           warning (0, "type is deprecated (declared at %s:%d)",
+           warning (OPT_Wdeprecated_declarations,
+                    "type is deprecated (declared at %s:%d)",
                     xloc.file, xloc.line);
        }
       else
        {
          if (what)
-           warning (0, "%qs is deprecated", what);
+           warning (OPT_Wdeprecated_declarations, "%qs is deprecated", what);
          else
-           warning (0, "type is deprecated");
+           warning (OPT_Wdeprecated_declarations, "type is deprecated");
        }
     }
 }
@@ -947,7 +951,7 @@ push_srcloc (const char *file, int line)
 {
   struct file_stack *fs;
 
-  fs = xmalloc (sizeof (struct file_stack));
+  fs = XNEW (struct file_stack);
   fs->location = input_location;
   fs->next = input_file_stack;
 #ifdef USE_MAPPED_LOCATION
@@ -1018,6 +1022,8 @@ compile_file (void)
   if (flag_mudflap)
     mudflap_finish_file ();
 
+  output_object_blocks ();
+
   /* Write out any pending weak symbol declarations.  */
 
   weak_finish ();
@@ -1025,7 +1031,7 @@ compile_file (void)
   /* Do dbx symbols.  */
   timevar_push (TV_SYMOUT);
 
-#ifdef DWARF2_UNWIND_INFO
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
   if (dwarf2out_do_frame ())
     dwarf2out_frame_finish ();
 #endif
@@ -1057,92 +1063,6 @@ compile_file (void)
   targetm.asm_out.file_end ();
 }
 
-/* Display help for target options.  */
-void
-display_target_options (void)
-{
-  int undoc;
-#if defined (TARGET_SWITCHES) || defined (TARGET_OPTIONS)
-  int i;
-#endif
-  unsigned int cli;
-  static bool displayed = false;
-
-  /* Avoid double printing for --help --target-help.  */
-  if (displayed)
-    return;
-
-  displayed = true;
-
-  for (cli = 0; cli < cl_options_count; cli++)
-    if ((cl_options[cli].flags & (CL_TARGET | CL_UNDOCUMENTED)) == CL_TARGET)
-      break;
-
-  if (cli < cl_options_count
-#ifdef TARGET_SWITCHES
-      || ARRAY_SIZE (target_switches) > 1
-#endif
-#ifdef TARGET_OPTIONS
-      || ARRAY_SIZE (target_options) > 1
-#endif
-      )
-    {
-      int doc = cli < cl_options_count;
-
-      undoc = 0;
-
-      printf (_("\nTarget specific options:\n"));
-
-#ifdef TARGET_SWITCHES
-      for (i = ARRAY_SIZE (target_switches); i--;)
-       {
-         const char *option      = target_switches[i].name;
-         const char *description = target_switches[i].description;
-
-         if (option == NULL || *option == 0)
-           continue;
-         else if (description == NULL)
-           {
-             undoc = 1;
-
-             if (extra_warnings)
-               printf (_("  -m%-23s [undocumented]\n"), option);
-           }
-         else if (*description != 0)
-           doc += printf ("  -m%-23s %s\n", option, _(description));
-       }
-#endif
-
-#ifdef TARGET_OPTIONS
-      for (i = ARRAY_SIZE (target_options); i--;)
-       {
-         const char *option      = target_options[i].prefix;
-         const char *description = target_options[i].description;
-
-         if (option == NULL || *option == 0)
-           continue;
-         else if (description == NULL)
-           {
-             undoc = 1;
-
-             if (extra_warnings)
-               printf (_("  -m%-23s [undocumented]\n"), option);
-           }
-         else if (*description != 0)
-           doc += printf ("  -m%-23s %s\n", option, _(description));
-       }
-#endif
-      print_filtered_help (CL_TARGET);
-      if (undoc)
-       {
-         if (doc)
-           printf (_("\nThere are undocumented target specific options as well.\n"));
-         else
-           printf (_("  They exist, but they are not documented.\n"));
-       }
-    }
-}
-
 /* Parse a -d... command line switch.  */
 
 void
@@ -1193,64 +1113,6 @@ const char *const debug_type_names[] =
   "none", "stabs", "coff", "dwarf-2", "xcoff", "vms"
 };
 
-/* Decode -m switches.  */
-/* Decode the switch -mNAME.  */
-
-void
-set_target_switch (const char *name)
-{
-#if defined (TARGET_SWITCHES) || defined (TARGET_OPTIONS)
-  size_t j;
-#endif
-  int valid_target_option = 0;
-
-#ifdef TARGET_SWITCHES
-  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
-    if (!strcmp (target_switches[j].name, name))
-      {
-       if (target_switches[j].value < 0)
-         target_flags &= ~-target_switches[j].value;
-       else
-         target_flags |= target_switches[j].value;
-       if (name[0] != 0)
-         {
-           if (target_switches[j].value < 0)
-             target_flags_explicit |= -target_switches[j].value;
-           else
-             target_flags_explicit |= target_switches[j].value;
-         }
-       valid_target_option = 1;
-      }
-#endif
-
-#ifdef TARGET_OPTIONS
-  if (!valid_target_option)
-    for (j = 0; j < ARRAY_SIZE (target_options); j++)
-      {
-       int len = strlen (target_options[j].prefix);
-       if (target_options[j].value)
-         {
-           if (!strcmp (target_options[j].prefix, name))
-             {
-               *target_options[j].variable = target_options[j].value;
-               valid_target_option = 1;
-             }
-         }
-       else
-         {
-           if (!strncmp (target_options[j].prefix, name, len))
-             {
-               *target_options[j].variable = name + len;
-               valid_target_option = 1;
-             }
-         }
-      }
-#endif
-
-  if (name[0] != 0 && !valid_target_option)
-    error ("invalid option %qs", name);
-}
-
 /* Print version information to FILE.
    Each line begins with INDENT (for the case where FILE is the
    assembler output file).  */
@@ -1258,19 +1120,25 @@ set_target_switch (const char *name)
 void
 print_version (FILE *file, const char *indent)
 {
-#ifndef __VERSION__
-#define __VERSION__ "[?]"
-#endif
-  fnotice (file,
+  static const char fmt1[] =
 #ifdef __GNUC__
-          "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
+    N_("%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n")
 #else
-          "%s%s%s version %s (%s) compiled by CC.\n"
+    N_("%s%s%s version %s (%s) compiled by CC.\n")
+#endif
+    ;
+  static const char fmt2[] =
+    N_("%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n");
+#ifndef __VERSION__
+#define __VERSION__ "[?]"
 #endif
-          , indent, *indent != 0 ? " " : "",
+  fprintf (file,
+          file == stderr ? _(fmt1) : fmt1,
+          indent, *indent != 0 ? " " : "",
           lang_hooks.name, version_string, TARGET_NAME,
           indent, __VERSION__);
-  fnotice (file, "%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n",
+  fprintf (file,
+          file == stderr ? _(fmt2) : fmt2,
           indent, *indent != 0 ? " " : "",
           PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
 }
@@ -1359,31 +1227,6 @@ print_switch_values (FILE *file, int pos, int max,
       pos = print_single_switch (file, pos, max, indent, sep, term,
                                 "", cl_options[j].opt_text);
 
-  /* Print target specific options.  */
-
-#ifdef TARGET_SWITCHES
-  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
-    if (target_switches[j].name[0] != '\0'
-       && target_switches[j].value > 0
-       && ((target_switches[j].value & target_flags)
-           == target_switches[j].value))
-      {
-       pos = print_single_switch (file, pos, max, indent, sep, term,
-                                  "-m", target_switches[j].name);
-      }
-#endif
-
-#ifdef TARGET_OPTIONS
-  for (j = 0; j < ARRAY_SIZE (target_options); j++)
-    if (*target_options[j].variable != NULL)
-      {
-       char prefix[256];
-       sprintf (prefix, "-m%s", target_options[j].prefix);
-       pos = print_single_switch (file, pos, max, indent, sep, term,
-                                  prefix, *target_options[j].variable);
-      }
-#endif
-
   fprintf (file, "%s", term);
 }
 
@@ -1401,7 +1244,7 @@ init_asm_output (const char *name)
       if (asm_file_name == 0)
        {
          int len = strlen (dump_base_name);
-         char *dumpname = xmalloc (len + 6);
+         char *dumpname = XNEWVEC (char, len + 6);
          memcpy (dumpname, dump_base_name, len + 1);
          strip_off_ending (dumpname, len);
          strcat (dumpname, ".s");
@@ -1460,38 +1303,23 @@ default_get_pch_validity (size_t *len)
   size_t i;
   char *result, *r;
 
-  *len = sizeof (target_flags) + 2;
-#ifdef TARGET_OPTIONS
-  for (i = 0; i < ARRAY_SIZE (target_options); i++)
-    {
-      *len += 1;
-      if (*target_options[i].variable)
-       *len += strlen (*target_options[i].variable);
-    }
-#endif
+  *len = 2;
+  if (targetm.check_pch_target_flags)
+    *len += sizeof (target_flags);
   for (i = 0; i < cl_options_count; i++)
     if (option_affects_pch_p (i, &state))
       *len += state.size;
 
-  result = r = xmalloc (*len);
+  result = r = XNEWVEC (char, *len);
   r[0] = flag_pic;
   r[1] = flag_pie;
   r += 2;
-  memcpy (r, &target_flags, sizeof (target_flags));
-  r += sizeof (target_flags);
-
-#ifdef TARGET_OPTIONS
-  for (i = 0; i < ARRAY_SIZE (target_options); i++)
+  if (targetm.check_pch_target_flags)
     {
-      const char *str = *target_options[i].variable;
-      size_t l;
-      if (! str)
-       str = "";
-      l = strlen (str) + 1;
-      memcpy (r, str, l);
-      r += l;
+      memcpy (r, &target_flags, sizeof (target_flags));
+      r += sizeof (target_flags);
     }
-#endif
+
   for (i = 0; i < cl_options_count; i++)
     if (option_affects_pch_p (i, &state))
       {
@@ -1502,6 +1330,20 @@ default_get_pch_validity (size_t *len)
   return result;
 }
 
+/* Return a message which says that a PCH file was created with a different
+   setting of OPTION.  */
+
+static const char *
+pch_option_mismatch (const char *option)
+{
+  char *r;
+
+  asprintf (&r, _("created and used with differing settings of '%s'"), option);
+  if (r == NULL)
+    return _("out of memory");
+  return r;
+}
+
 /* Default version of pch_valid_p.  */
 
 const char *
@@ -1509,9 +1351,7 @@ default_pch_valid_p (const void *data_p, size_t len)
 {
   struct cl_option_state state;
   const char *data = (const char *)data_p;
-  const char *flag_that_differs = NULL;
   size_t i;
-  int tf;
 
   /* -fpic and -fpie also usually make a PCH invalid.  */
   if (data[0] != flag_pic)
@@ -1521,86 +1361,43 @@ default_pch_valid_p (const void *data_p, size_t len)
   data += 2;
 
   /* Check target_flags.  */
-  memcpy (&tf, data, sizeof (target_flags));
   if (targetm.check_pch_target_flags)
     {
-      const char *r = targetm.check_pch_target_flags (tf);
+      int tf;
+      const char *r;
+
+      memcpy (&tf, data, sizeof (target_flags));
+      data += sizeof (target_flags);
+      len -= sizeof (target_flags);
+      r = targetm.check_pch_target_flags (tf);
       if (r != NULL)
        return r;
     }
-#ifdef TARGET_SWITCHES
-  else if (tf != target_flags)
-    {
-      for (i = 0; i < ARRAY_SIZE (target_switches); i++)
-       {
-         int bits;
-
-         bits = target_switches[i].value;
-         if (bits < 0)
-           bits = -bits;
-         if ((target_flags & bits) != (tf & bits))
-           {
-             flag_that_differs = target_switches[i].name;
-             goto make_message;
-           }
-       }
-      gcc_unreachable ();
-    }
-#endif
-  data += sizeof (target_flags);
-  len -= sizeof (target_flags);
-
-  /* Check string options.  */
-#ifdef TARGET_OPTIONS
-  for (i = 0; i < ARRAY_SIZE (target_options); i++)
-    {
-      const char *str = *target_options[i].variable;
-      size_t l;
-      if (! str)
-       str = "";
-      l = strlen (str) + 1;
-      if (len < l || memcmp (data, str, l) != 0)
-       {
-         flag_that_differs = target_options[i].prefix;
-         goto make_message;
-       }
-      data += l;
-      len -= l;
-    }
-#endif
 
   for (i = 0; i < cl_options_count; i++)
     if (option_affects_pch_p (i, &state))
       {
        if (memcmp (data, state.data, state.size) != 0)
-         {
-           flag_that_differs = cl_options[i].opt_text + 2;
-           goto make_message;
-         }
+         return pch_option_mismatch (cl_options[i].opt_text);
        data += state.size;
        len -= state.size;
       }
 
   return NULL;
-
- make_message:
-  {
-    char *r;
-    asprintf (&r, _("created and used with differing settings of '-m%s'"),
-                 flag_that_differs);
-    if (r == NULL)
-      return _("out of memory");
-    return r;
-  }
 }
 
 /* Default tree printer.   Handles declarations only.  */
 static bool
-default_tree_printer (pretty_printer * pp, text_info *text)
+default_tree_printer (pretty_printer * pp, text_info *text, const char *spec,
+                     int precision, bool wide, bool set_locus, bool hash)
 {
   tree t;
 
-  switch (*text->format_spec)
+  /* FUTURE: %+x should set the locus.  */
+  if (precision != 0 || wide || hash)
+    return false;
+
+  switch (*spec)
     {
     case 'D':
       t = va_arg (*text->args_ptr, tree);
@@ -1617,6 +1414,9 @@ default_tree_printer (pretty_printer * pp, text_info *text)
       return false;
     }
 
+  if (set_locus && text->locus)
+    *text->locus = DECL_SOURCE_LOCATION (t);
+
   if (DECL_P (t))
     {
       const char *n = DECL_NAME (t)
@@ -1697,13 +1497,31 @@ general_init (const char *argv0)
 
   /* This must be done after add_params but before argument processing.  */
   init_ggc_heuristics();
-  init_tree_optimization_passes ();
+  init_optimization_passes ();
+}
+
+/* Return true if the current target supports -fsection-anchors.  */
+
+static bool
+target_supports_section_anchors_p (void)
+{
+  if (targetm.min_anchor_offset == 0 && targetm.max_anchor_offset == 0)
+    return false;
+
+  if (targetm.asm_out.output_anchor == NULL)
+    return false;
+
+  return true;
 }
 
 /* Process the options that have been parsed.  */
 static void
 process_options (void)
 {
+  /* Just in case lang_hooks.post_options ends up calling a debug_hook.
+     This can happen with incorrect pre-processed input. */
+  debug_hooks = &do_nothing_debug_hooks;
+
   /* Allow the front end to perform consistency checks and do further
      initialization based on the command line options.  This hook also
      sets the original filename if appropriate (e.g. foo.i -> foo.c)
@@ -1718,6 +1536,13 @@ process_options (void)
   OVERRIDE_OPTIONS;
 #endif
 
+  if (flag_section_anchors && !target_supports_section_anchors_p ())
+    {
+      warning (OPT_fsection_anchors,
+              "this target does not support %qs", "-fsection-anchors");
+      flag_section_anchors = 0;
+    }
+
   if (flag_short_enums == 2)
     flag_short_enums = targetm.default_short_enums ();
 
@@ -1756,22 +1581,15 @@ process_options (void)
   if (flag_unroll_all_loops)
     flag_unroll_loops = 1;
 
-  /* The loop unrolling code assumes that cse will be run after loop.  */
-  if (flag_unroll_loops || flag_peel_loops)
-    flag_rerun_cse_after_loop = 1;
+  /* The loop unrolling code assumes that cse will be run after loop.
+     web and rename-registers also help when run after loop unrolling.  */
 
-  /* If explicitly asked to run new loop optimizer, switch off the old
-     one.  */
-  if (flag_loop_optimize2)
-    flag_loop_optimize = 0;
-
-  /* Enable new loop optimizer pass if any of its optimizations is called.  */
-  if (flag_move_loop_invariants
-      || flag_unswitch_loops
-      || flag_peel_loops
-      || flag_unroll_loops
-      || flag_branch_on_count_reg)
-    flag_loop_optimize2 = 1;
+  if (flag_rerun_cse_after_loop == AUTODETECT_VALUE)
+    flag_rerun_cse_after_loop = flag_unroll_loops || flag_peel_loops;
+  if (flag_web == AUTODETECT_VALUE)
+    flag_web = flag_unroll_loops || flag_peel_loops;
+  if (flag_rename_registers == AUTODETECT_VALUE)
+    flag_rename_registers = flag_unroll_loops || flag_peel_loops;
 
   if (flag_non_call_exceptions)
     flag_asynchronous_unwind_tables = 1;
@@ -1783,20 +1601,12 @@ process_options (void)
   if (flag_unit_at_a_time && ! lang_hooks.callgraph.expand_function)
     flag_unit_at_a_time = 0;
 
+  if (!flag_unit_at_a_time)
+    flag_section_anchors = 0;
+
   if (flag_value_profile_transformations)
     flag_profile_values = 1;
 
-  /* Speculative prefetching implies the value profiling.  We also switch off
-     the prefetching in the loop optimizer, so that we do not emit double
-     prefetches.  TODO -- we should teach these two to cooperate; the loop
-     based prefetching may sometimes do a better job, especially in connection
-     with reuse analysis.  */
-  if (flag_speculative_prefetching)
-    {
-      flag_profile_values = 1;
-      flag_prefetch_loop_arrays = 0;
-    }
-
   /* Warn about options that are not supported on this machine.  */
 #ifndef INSN_SCHEDULING
   if (flag_schedule_insns || flag_schedule_insns_after_reload)
@@ -1868,7 +1678,6 @@ process_options (void)
     default_debug_hooks = &vmsdbg_debug_hooks;
 #endif
 
-  debug_hooks = &do_nothing_debug_hooks;
   if (write_symbols == NO_DEBUG)
     ;
 #if defined(DBX_DEBUGGING_INFO)
@@ -1913,11 +1722,11 @@ process_options (void)
       flag_var_tracking = 0;
     }
 
-  if (flag_rename_registers == AUTODETECT_FLAG_VAR_TRACKING)
+  if (flag_rename_registers == AUTODETECT_VALUE)
     flag_rename_registers = default_debug_hooks->var_location
                            != do_nothing_debug_hooks.var_location;
 
-  if (flag_var_tracking == AUTODETECT_FLAG_VAR_TRACKING)
+  if (flag_var_tracking == AUTODETECT_VALUE)
     flag_var_tracking = optimize >= 1;
 
   /* If auxiliary info generation is desired, open the output file.
@@ -1956,24 +1765,12 @@ process_options (void)
       warning (0, "-fprefetch-loop-arrays not supported for this target");
       flag_prefetch_loop_arrays = 0;
     }
-  if (flag_speculative_prefetching)
-    {
-      if (flag_speculative_prefetching_set)
-       warning (0, "-fspeculative-prefetching not supported for this target");
-      flag_speculative_prefetching = 0;
-    }
 #else
   if (flag_prefetch_loop_arrays && !HAVE_prefetch)
     {
       warning (0, "-fprefetch-loop-arrays not supported for this target (try -march switches)");
       flag_prefetch_loop_arrays = 0;
     }
-  if (flag_speculative_prefetching && !HAVE_prefetch)
-    {
-      if (flag_speculative_prefetching_set)
-       warning (0, "-fspeculative-prefetching not supported for this target (try -march switches)");
-      flag_speculative_prefetching = 0;
-    }
 #endif
 
   /* This combination of options isn't handled for i386 targets and doesn't
@@ -1996,6 +1793,28 @@ process_options (void)
   /* With -fcx-limited-range, we do cheap and quick complex arithmetic.  */
   if (flag_cx_limited_range)
     flag_complex_method = 0;
+
+  /* Targets must be able to place spill slots at lower addresses.  If the
+     target already uses a soft frame pointer, the transition is trivial.  */
+  if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
+    {
+      warning (0, "-fstack-protector not supported for this target");
+      flag_stack_protect = 0;
+    }
+  if (!flag_stack_protect)
+    warn_stack_protect = 0;
+
+  /* ??? Unwind info is not correct around the CFG unless either a frame
+     pointer is present or A_O_A is set.  Fixing this requires rewriting
+     unwind info generation to be aware of the CFG and propagating states
+     around edges.  */
+  if (flag_unwind_tables && !ACCUMULATE_OUTGOING_ARGS
+      && flag_omit_frame_pointer)
+    {
+      warning (0, "unwind tables currently requires a frame pointer "
+              "for correctness");
+      flag_omit_frame_pointer = 0;
+    }
 }
 
 /* Initialize the compiler back end.  */
@@ -2014,9 +1833,7 @@ backend_init (void)
   init_regs ();
   init_fake_stack_mems ();
   init_alias_once ();
-  init_loop ();
   init_reload ();
-  init_function_once ();
   init_varasm_once ();
 
   /* The following initialization functions need to generate rtl, so
@@ -2064,7 +1881,7 @@ lang_dependent_init (const char *name)
      predefined types.  */
   timevar_push (TV_SYMOUT);
 
-#ifdef DWARF2_UNWIND_INFO
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
   if (dwarf2out_do_frame ())
     dwarf2out_frame_init ();
 #endif