OSDN Git Service

gcc:
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 819e26e..c199f6d 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002 Free Software Foundation, Inc.
+   2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -28,6 +28,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "intl.h"
 #include "tree.h"
 #include "tree-inline.h"
@@ -46,6 +48,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "timevar.h"
 #include "c-common.h"
 #include "c-pragma.h"
+#include "cgraph.h"
+#include "hashtab.h"
+#include "libfuncs.h"
+#include "except.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -62,8 +68,7 @@ enum decl_context
 
 tree pending_invalid_xref;
 /* File and line to appear in the eventual error message.  */
-const char *pending_invalid_xref_file;
-int pending_invalid_xref_line;
+location_t pending_invalid_xref_location;
 
 /* While defining an enum type, this is 1 plus the last enumerator
    constant value.  Note that will do not have to save this or `enum_overflow'
@@ -98,8 +103,7 @@ static tree current_function_parm_tags;
 
 /* Similar, for the file and line that the prototype came from if this is
    an old-style definition.  */
-static const char *current_function_prototype_file;
-static int current_function_prototype_line;
+static location_t current_function_prototype_locus;
 
 /* The current statement tree.  */
 
@@ -119,10 +123,9 @@ static GTY(()) tree named_labels;
 
 static GTY(()) tree shadowed_labels;
 
-/* Nonzero when store_parm_decls is called indicates a varargs function.
-   Value not meaningful after store_parm_decls.  */
-
-static int c_function_varargs;
+/* A list of external DECLs that appeared at block scope when there was
+   some other global meaning for that identifier.  */
+static GTY(()) tree truly_local_externals;
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
@@ -161,9 +164,6 @@ static int current_extern_inline;
  * the current one out to the global one.
  */
 
-/* Note that the information in the `names' component of the global contour
-   is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers.  */
-
 struct binding_level GTY(())
   {
     /* A chain of _DECL nodes for all variables, constants, functions,
@@ -179,35 +179,34 @@ struct binding_level GTY(())
      */
     tree tags;
 
-    /* For each level, a list of shadowed outer-level local definitions
+    /* For each level, a list of shadowed outer-level definitions
        to be restored when this level is popped.
        Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
        whose TREE_VALUE is its old definition (a kind of ..._DECL node).  */
     tree shadowed;
 
+    /* For each level, a list of shadowed outer-level tag definitions
+       to be restored when this level is popped.
+       Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+       whose TREE_VALUE is its old definition (a kind of ..._TYPE node).  */
+    tree shadowed_tags;
+
     /* For each level (except not the global one),
        a chain of BLOCK nodes for all the levels
        that were entered and exited one level down.  */
     tree blocks;
 
-    /* The BLOCK node for this level, if one has been preallocated.
-       If 0, the BLOCK is allocated (if needed) when the level is popped.  */
-    tree this_block;
-
     /* The binding level which this one is contained in (inherits from).  */
     struct binding_level *level_chain;
 
-    /* Nonzero for the level that holds the parameters of a function.  */
+    /* Nonzero if we are currently filling this level with parameter
+       declarations.  */
     char parm_flag;
 
-    /* Nonzero if this level "doesn't exist" for tags.  */
-    char tag_transparent;
-
-    /* Nonzero if sublevels of this level "don't exist" for tags.
-       This is set in the parm level of a function definition
-       while reading the function body, so that the outermost block
-       of the function body will be tag-transparent.  */
-    char subblocks_tag_transparent;
+    /* Nonzero if this is the outermost block scope of a function body.
+       This scope contains both the parameters and the local variables
+       declared in the outermost block.  */
+    char function_body;
 
     /* Nonzero means make a BLOCK for this level regardless of all else.  */
     char keep;
@@ -241,12 +240,6 @@ static GTY((deletable (""))) struct binding_level *free_binding_level;
 
 static GTY(()) struct binding_level *global_binding_level;
 
-/* Binding level structures are initialized by copying this one.  */
-
-static struct binding_level clear_binding_level
-  = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
-     NULL};
-
 /* Nonzero means unconditionally make a BLOCK for the next level pushed.  */
 
 static int keep_next_level_flag;
@@ -270,173 +263,31 @@ tree static_ctors, static_dtors;
 
 /* Forward declarations.  */
 
-static struct binding_level * make_binding_level       PARAMS ((void));
-static void pop_binding_level          PARAMS ((struct binding_level **));
-static void clear_limbo_values         PARAMS ((tree));
-static int duplicate_decls             PARAMS ((tree, tree, int));
-static int redeclaration_error_message PARAMS ((tree, tree));
-static void storedecls                 PARAMS ((tree));
-static void storetags                  PARAMS ((tree));
-static tree lookup_tag                 PARAMS ((enum tree_code, tree,
-                                                struct binding_level *, int));
-static tree lookup_tag_reverse         PARAMS ((tree));
-static tree grokdeclarator             PARAMS ((tree, tree, enum decl_context,
-                                                int));
-static tree grokparms                  PARAMS ((tree, int));
-static void layout_array_type          PARAMS ((tree));
-static tree c_make_fname_decl           PARAMS ((tree, int));
-static void c_expand_body               PARAMS ((tree, int, int));
-static void warn_if_shadowing          PARAMS ((tree, tree));
+static struct binding_level *make_binding_level (void);
+static void pop_binding_level (struct binding_level **);
+static int duplicate_decls (tree, tree, int);
+static int redeclaration_error_message (tree, tree);
+static void implicit_decl_warning (tree);
+static void storedecls (tree);
+static void storetags (tree);
+static tree lookup_tag (enum tree_code, tree, int);
+static tree lookup_name_current_level (tree);
+static tree grokdeclarator (tree, tree, enum decl_context, int);
+static tree grokparms (tree, int);
+static void layout_array_type (tree);
+static tree c_make_fname_decl (tree, int);
+static void c_expand_body_1 (tree, int);
+static tree any_external_decl (tree);
+static void record_external_decl (tree);
+static void warn_if_shadowing (tree, tree);
+static void clone_underlying_type (tree);
+static bool flexible_array_type_p (tree);
 \f
-/* C-specific option variables.  */
-
-/* Nonzero means allow type mismatches in conditional expressions;
-   just make their values `void'.  */
-
-int flag_cond_mismatch;
-
-/* Nonzero means don't recognize the keyword `asm'.  */
-
-int flag_no_asm;
-
-/* Nonzero means enable C89 Amendment 1 features.  */
-
-int flag_isoc94 = 0;
-
-/* Nonzero means use the ISO C99 dialect of C.  */
-
-int flag_isoc99 = 0;
-
-/* Nonzero means that we have builtin functions, and main is an int */
-
-int flag_hosted = 1;
-
-/* Nonzero means add default format_arg attributes for functions not
-   in ISO C.  */
-
-int flag_noniso_default_format_attributes = 1;
-
-/* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
-
-int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields = 0;
-
-/* Nonzero means warn about use of implicit int.  */
-
-int warn_implicit_int;
-
-/* Nonzero means warn about usage of long long when `-pedantic'.  */
-
-int warn_long_long = 1;
-
-/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error.  */
-
-int mesg_implicit_function_declaration = -1;
-
-/* Nonzero means give string constants the type `const char *'
-   to get extra warnings from them.  These warnings will be too numerous
-   to be useful, except in thoroughly ANSIfied programs.  */
-
-int flag_const_strings;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
-   from the pointer target type.  */
-
-int warn_cast_qual;
-
-/* Nonzero means warn when casting a function call to a type that does
-   not match the return type (e.g. (float)sqrt() or (anything*)malloc()
-   when there is no previous declaration of sqrt or malloc.  */
-
-int warn_bad_function_cast;
-
-/* Warn about functions which might be candidates for format attributes.  */
-
-int warn_missing_format_attribute;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C.  */
-
-int warn_traditional;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
-   of function pointers.  */
-
-int warn_pointer_arith;
-
-/* Nonzero means warn for non-prototype function decls
-   or non-prototyped defs without previous prototype.  */
-
-int warn_strict_prototypes;
-
-/* Nonzero means warn for any global function def
-   without separate previous prototype decl.  */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn for any global function def
-   without separate previous decl.  */
-
-int warn_missing_declarations;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
-   variable or function.  */
-
-int warn_redundant_decls = 0;
-
-/* Nonzero means warn about extern declarations of objects not at
-   file-scope level and about *all* declarations of functions (whether
-   extern or static) not at file-scope level.  Note that we exclude
-   implicit function declarations.  To get warnings about those, use
-   -Wimplicit.  */
-
-int warn_nested_externs = 0;
-
-/* Warn about a subscript that has type char.  */
-
-int warn_char_subscripts = 0;
-
-/* Warn if a type conversion is done that might have confusing results.  */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested.  */
-
-int warn_parentheses;
-
-/* Warn if initializer is not completely bracketed.  */
-
-int warn_missing_braces;
-
-/* Warn if main is suspicious.  */
-
-int warn_main;
-
-/* Warn about #pragma directives that are not recognised.  */
-
-int warn_unknown_pragmas = 0; /* Tri state variable.  */
-
-/* Warn about comparison of signed and unsigned values.
-   If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified.  */
-
-int warn_sign_compare = -1;
-
-/* Warn about testing equality of floating point numbers.  */
-
-int warn_float_equal = 0;
-
-/* Nonzero means `$' can be in an identifier.  */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
    __attribute__((deprecated)) suppresses warnings of uses of other
    deprecated items.  */
-   
+
 enum deprecated_states {
   DEPRECATED_NORMAL,
   DEPRECATED_SUPPRESS
@@ -444,290 +295,18 @@ enum deprecated_states {
 
 static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
-/* Decode the string P as a language-specific option for C.
-   Return the number of strings consumed.  Should not complain
-   if it does not recognise the option.  */
-
-int
-c_decode_option (argc, argv)
-     int argc ATTRIBUTE_UNUSED;
-     char **argv;
-{
-  int strings_processed;
-  char *p = argv[0];
-
-  static const struct {
-      /* The name of the option.  */
-      const char *option;
-      /* If non-NULL, a flag variable to set to 0 or 1.  If NULL,
-         this means that cpp handles this option.  */
-      int *flag;
-  } warn_options[] = {
-    /* This list is in alphabetical order.  Keep it like that.  */
-    { "bad-function-cast", &warn_bad_function_cast },
-    { "cast-qual", &warn_cast_qual },
-    { "char-subscripts", &warn_char_subscripts },
-    { "comment", NULL },
-    { "comments", NULL },
-    { "conversion", &warn_conversion },
-    { "div-by-zero", &warn_div_by_zero },
-    { "float-equal", &warn_float_equal },
-    { "format-extra-args", &warn_format_extra_args },
-    { "format-zero-length", &warn_format_zero_length },
-    { "format-nonliteral", &warn_format_nonliteral },
-    { "format-security", &warn_format_security },
-    { "format-y2k", &warn_format_y2k },
-    { "implicit-function-declaration", &mesg_implicit_function_declaration },
-    { "implicit-int", &warn_implicit_int },
-    { "import", NULL },
-    { "long-long", &warn_long_long },
-    { "main", &warn_main },
-    { "missing-braces", &warn_missing_braces },
-    { "missing-declarations", &warn_missing_declarations },
-    { "missing-format-attribute", &warn_missing_format_attribute },
-    { "missing-prototypes", &warn_missing_prototypes },
-    { "multichar", &warn_multichar },
-    { "nested-externs", &warn_nested_externs },
-    { "nonnull", &warn_nonnull },
-    { "parentheses", &warn_parentheses },
-    { "pointer-arith", &warn_pointer_arith },
-    { "redundant-decls", &warn_redundant_decls },
-    { "return-type", &warn_return_type },
-    { "sequence-point", &warn_sequence_point },
-    { "sign-compare", &warn_sign_compare },
-    { "strict-prototypes", &warn_strict_prototypes },
-    { "traditional", &warn_traditional },
-    { "trigraphs", NULL },
-    { "undef", NULL },
-    { "write-strings", &flag_const_strings }
-  };
-
-  strings_processed = cpp_handle_option (parse_in, argc, argv);
-
-  if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
-    {
-      flag_hosted = 1;
-      flag_no_builtin = 0;
-    }
-  else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted"))
-    {
-      flag_hosted = 0;
-      flag_no_builtin = 1;
-      /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
-      if (warn_main == 2)
-       warn_main = 0;
-    }
-  else if (!strncmp (p, "-std=", 5))
-    {
-      /* Select the appropriate language standard.  We currently
-        recognize:
-        -std=iso9899:1990      same as -ansi
-        -std=iso9899:199409    ISO C as modified in amend. 1
-        -std=iso9899:1999      ISO C 99
-        -std=c89               same as -std=iso9899:1990
-        -std=c99               same as -std=iso9899:1999
-        -std=gnu89             default, iso9899:1990 + gnu extensions
-        -std=gnu99             iso9899:1999 + gnu extensions
-      */
-      const char *const argstart = &p[5];
-
-      if (!strcmp (argstart, "iso9899:1990")
-         || !strcmp (argstart, "c89"))
-       {
-       iso_1990:
-         flag_isoc94 = 0;
-       iso_1994:
-         flag_writable_strings = 0;
-         flag_no_asm = 1;
-         flag_no_nonansi_builtin = 1;
-         flag_noniso_default_format_attributes = 0;
-         flag_isoc99 = 0;
-         flag_iso = 1;
-       }
-      else if (!strcmp (argstart, "iso9899:199409"))
-       {
-         flag_isoc94 = 1;
-         goto iso_1994;
-       }
-      else if (!strcmp (argstart, "iso9899:199x")
-              || !strcmp (argstart, "iso9899:1999")
-              || !strcmp (argstart, "c9x")
-              || !strcmp (argstart, "c99"))
-       {
-         flag_writable_strings = 0;
-         flag_no_asm = 1;
-         flag_no_nonansi_builtin = 1;
-         flag_noniso_default_format_attributes = 0;
-         flag_isoc99 = 1;
-         flag_isoc94 = 1;
-         flag_iso = 1;
-       }
-      else if (!strcmp (argstart, "gnu89"))
-       {
-         flag_writable_strings = 0;
-         flag_no_asm = 0;
-         flag_no_nonansi_builtin = 0;
-         flag_noniso_default_format_attributes = 1;
-         flag_isoc99 = 0;
-         flag_isoc94 = 0;
-       }
-      else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
-       {
-         flag_writable_strings = 0;
-         flag_no_asm = 0;
-         flag_no_nonansi_builtin = 0;
-         flag_noniso_default_format_attributes = 1;
-         flag_isoc99 = 1;
-         flag_isoc94 = 1;
-       }
-      else if (!strcmp (argstart, "c++98"))
-       ; /* Handled by cpplib.  */
-      else
-       error ("unknown C standard `%s'", argstart);
-    }
-  else if (!strcmp (p, "-fdollars-in-identifiers"))
-    dollars_in_ident = 1;
-  else if (!strcmp (p, "-fno-dollars-in-identifiers"))
-    dollars_in_ident = 0;
-  else if (!strcmp (p, "-fsigned-char"))
-    flag_signed_char = 1;
-  else if (!strcmp (p, "-funsigned-char"))
-    flag_signed_char = 0;
-  else if (!strcmp (p, "-fno-signed-char"))
-    flag_signed_char = 0;
-  else if (!strcmp (p, "-fno-unsigned-char"))
-    flag_signed_char = 1;
-  else if (!strcmp (p, "-fsigned-bitfields")
-          || !strcmp (p, "-fno-unsigned-bitfields"))
-    {
-      flag_signed_bitfields = 1;
-      explicit_flag_signed_bitfields = 1;
-    }
-  else if (!strcmp (p, "-funsigned-bitfields")
-          || !strcmp (p, "-fno-signed-bitfields"))
-    {
-      flag_signed_bitfields = 0;
-      explicit_flag_signed_bitfields = 1;
-    }
-  else if (!strcmp (p, "-fshort-enums"))
-    flag_short_enums = 1;
-  else if (!strcmp (p, "-fno-short-enums"))
-    flag_short_enums = 0;
-  else if (!strcmp (p, "-fshort-wchar"))
-    flag_short_wchar = 1;
-  else if (!strcmp (p, "-fno-short-wchar"))
-    flag_short_wchar = 0;
-  else if (!strcmp (p, "-fcond-mismatch"))
-    flag_cond_mismatch = 1;
-  else if (!strcmp (p, "-fno-cond-mismatch"))
-    flag_cond_mismatch = 0;
-  else if (!strcmp (p, "-fshort-double"))
-    flag_short_double = 1;
-  else if (!strcmp (p, "-fno-short-double"))
-    flag_short_double = 0;
-  else if (!strcmp (p, "-fasm"))
-    flag_no_asm = 0;
-  else if (!strcmp (p, "-fno-asm"))
-    flag_no_asm = 1;
-  else if (!strcmp (p, "-fbuiltin"))
-    flag_no_builtin = 0;
-  else if (!strcmp (p, "-fno-builtin"))
-    flag_no_builtin = 1;
-  else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-")))
-    disable_builtin_function (p + strlen ("-fno-builtin-"));
-  else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
-    ;
-  else if (!strcmp (p, "-ansi"))
-    goto iso_1990;
-  else if (!strcmp (p, "-undef"))
-    flag_undef = 1;
-  else if (!strcmp (p, "-Werror-implicit-function-declaration"))
-    mesg_implicit_function_declaration = 2;
-  else if (!strncmp (p, "-Wformat=", 9))
-    set_Wformat (atoi (p + 9));
-  else if (!strcmp (p, "-Wformat"))
-    set_Wformat (1);
-  else if (!strcmp (p, "-Wno-format"))
-    set_Wformat (0);
-  else if (!strcmp (p, "-Wimplicit"))
-    {
-      warn_implicit_int = 1;
-      if (mesg_implicit_function_declaration != 2)
-       mesg_implicit_function_declaration = 1;
-    }
-  else if (!strcmp (p, "-Wno-implicit"))
-    warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
-  else if (!strcmp (p, "-Wno-main"))
-    warn_main = -1;
-  else if (!strcmp (p, "-Wunknown-pragmas"))
-    /* Set to greater than 1, so that even unknown pragmas in system
-       headers will be warned about.  */
-    warn_unknown_pragmas = 2;
-  else if (!strcmp (p, "-Wno-unknown-pragmas"))
-    warn_unknown_pragmas = 0;
-  else if (!strcmp (p, "-Wall"))
-    {
-      /* We save the value of warn_uninitialized, since if they put
-        -Wuninitialized on the command line, we need to generate a
-        warning about not using it without also specifying -O.  */
-      if (warn_uninitialized != 1)
-       warn_uninitialized = 2;
-      warn_implicit_int = 1;
-      mesg_implicit_function_declaration = 1;
-      warn_return_type = 1;
-      set_Wunused (1);
-      warn_switch = 1;
-      set_Wformat (1);
-      warn_char_subscripts = 1;
-      warn_parentheses = 1;
-      warn_sequence_point = 1;
-      warn_missing_braces = 1;
-      /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
-        it off only if it's not explicit.  */
-      warn_main = 2;
-      /* Only warn about unknown pragmas that are not in system headers.  */
-      warn_unknown_pragmas = 1;
-    }
-  else if (!strcmp (p, "-E"))
-    flag_preprocess_only = 1;
-  else
-    {
-      size_t i;
-      for (i = 0; i < sizeof (warn_options) / sizeof (warn_options[0]); i++)
-       if (strncmp (p, "-W", 2) == 0 
-           && warn_options[i].flag
-           && (strcmp (p+2, warn_options[i].option) == 0
-               || (strncmp (p+2, "no-", 3) == 0
-                   && strcmp (p+5, warn_options[i].option) == 0)))
-         {
-           *(warn_options[i].flag) = strncmp (p+2, "no-", 3) != 0;
-           return 1;
-         }
-      return strings_processed;
-    }
-
-  return 1;
-}
-
 void
-c_print_identifier (file, node, indent)
-     FILE *file;
-     tree node;
-     int indent;
+c_print_identifier (FILE *file, tree node, int indent)
 {
-  print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
-  print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
+  print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4);
+  print_node (file, "tag", IDENTIFIER_TAG_VALUE (node), indent + 4);
   print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
-  print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
-  print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
-  print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
   if (C_IS_RESERVED_WORD (node))
     {
       tree rid = ridpointers[C_RID_CODE (node)];
       indent_to (file, indent + 4);
-      fprintf (file, "rid ");
-      fprintf (file, HOST_PTR_PRINTF, (void *)rid);
-      fprintf (file, " \"%s\"", IDENTIFIER_POINTER (rid));
+      fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
+              (void *) rid, IDENTIFIER_POINTER (rid));
     }
 }
 \f
@@ -735,8 +314,7 @@ c_print_identifier (file, node, indent)
    for a top-level tentative array defn that wasn't complete before.  */
 
 void
-c_finish_incomplete_decl (decl)
-     tree decl;
+c_finish_incomplete_decl (tree decl)
 {
   if (TREE_CODE (decl) == VAR_DECL)
     {
@@ -758,27 +336,30 @@ c_finish_incomplete_decl (decl)
 /* Reuse or create a struct for this binding level.  */
 
 static struct binding_level *
-make_binding_level ()
+make_binding_level (void)
 {
+  struct binding_level *result;
   if (free_binding_level)
     {
-      struct binding_level *result = free_binding_level;
+      result = free_binding_level;
       free_binding_level = result->level_chain;
-      return result;
+      memset (result, 0, sizeof(struct binding_level));
     }
   else
-    return (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
+    result = (struct binding_level *)
+      ggc_alloc_cleared (sizeof (struct binding_level));
+
+  return result;
 }
 
 /* Remove a binding level from a list and add it to the level chain.  */
 
 static void
-pop_binding_level (lp)
-     struct binding_level **lp;
+pop_binding_level (struct binding_level **lp)
 {
   struct binding_level *l = *lp;
   *lp = l->level_chain;
-  
+
   memset (l, 0, sizeof (struct binding_level));
   l->level_chain = free_binding_level;
   free_binding_level = l;
@@ -787,13 +368,13 @@ pop_binding_level (lp)
 /* Nonzero if we are currently in the global binding level.  */
 
 int
-global_bindings_p ()
+global_bindings_p (void)
 {
   return current_binding_level == global_binding_level;
 }
 
 void
-keep_next_level ()
+keep_next_level (void)
 {
   keep_next_level_flag = 1;
 }
@@ -801,14 +382,13 @@ keep_next_level ()
 /* Nonzero if the current level needs to have a BLOCK made.  */
 
 int
-kept_level_p ()
+kept_level_p (void)
 {
   return ((current_binding_level->keep_if_subblocks
           && current_binding_level->blocks != 0)
          || current_binding_level->keep
          || current_binding_level->names != 0
-         || (current_binding_level->tags != 0
-             && !current_binding_level->tag_transparent));
+         || current_binding_level->tags != 0);
 }
 
 /* Identify this binding level as a level of parameters.
@@ -817,8 +397,7 @@ kept_level_p ()
    DEFINITION_FLAG, so we ignore it.  */
 
 void
-declare_parm_level (definition_flag)
-     int definition_flag ATTRIBUTE_UNUSED;
+declare_parm_level (int definition_flag ATTRIBUTE_UNUSED)
 {
   current_binding_level->parm_flag = 1;
 }
@@ -826,62 +405,49 @@ declare_parm_level (definition_flag)
 /* Nonzero if currently making parm declarations.  */
 
 int
-in_parm_level_p ()
+in_parm_level_p (void)
 {
   return current_binding_level->parm_flag;
 }
 
-/* Enter a new binding level.
-   If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
-   not for that of tags.  */
+/* Enter a new binding level.  */
 
 void
-pushlevel (tag_transparent)
-     int tag_transparent;
+pushlevel (int dummy ATTRIBUTE_UNUSED)
 {
-  struct binding_level *newlevel = NULL_BINDING_LEVEL;
-
-  /* If this is the top level of a function,
-     just make sure that NAMED_LABELS is 0.  */
+  /* If this is the top level of a function, make sure that
+     NAMED_LABELS is 0.  */
 
   if (current_binding_level == global_binding_level)
+    named_labels = 0;
+
+  if (keep_next_if_subblocks)
     {
-      named_labels = 0;
+      /* This is the transition from the parameters to the top level
+        of the function body.  These are the same scope
+        (C99 6.2.1p4,6) so we do not push another binding level.
+
+        XXX Note kludge - keep_next_if_subblocks is set only by
+        store_parm_decls, which in turn is called when and only
+        when we are about to encounter the opening curly brace for
+        the function body.  */
+      current_binding_level->parm_flag = 0;
+      current_binding_level->function_body = 1;
+      current_binding_level->keep |= keep_next_level_flag;
+      current_binding_level->keep_if_subblocks = 1;
+
+      keep_next_level_flag = 0;
+      keep_next_if_subblocks = 0;
     }
+  else
+    {
+      struct binding_level *newlevel = make_binding_level ();
 
-  newlevel = make_binding_level ();
-
-  /* Add this level to the front of the chain (stack) of levels that
-     are active.  */
-
-  *newlevel = clear_binding_level;
-  newlevel->tag_transparent
-    = (tag_transparent
-       || (current_binding_level
-          ? current_binding_level->subblocks_tag_transparent
-          : 0));
-  newlevel->level_chain = current_binding_level;
-  current_binding_level = newlevel;
-  newlevel->keep = keep_next_level_flag;
-  keep_next_level_flag = 0;
-  newlevel->keep_if_subblocks = keep_next_if_subblocks;
-  keep_next_if_subblocks = 0;
-}
-
-/* Clear the limbo values of all identifiers defined in BLOCK or a subblock.  */
-
-static void
-clear_limbo_values (block)
-     tree block;
-{
-  tree tem;
-
-  for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem))
-    if (DECL_NAME (tem) != 0)
-      IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0;
-
-  for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem))
-    clear_limbo_values (tem);
+      newlevel->keep              = keep_next_level_flag;
+      newlevel->level_chain       = current_binding_level;
+      current_binding_level = newlevel;
+      keep_next_level_flag = 0;
+    }
 }
 
 /* Exit a binding level.
@@ -900,101 +466,106 @@ clear_limbo_values (block)
    them into the BLOCK.  */
 
 tree
-poplevel (keep, reverse, functionbody)
-     int keep;
-     int reverse;
-     int functionbody;
+poplevel (int keep, int reverse, int functionbody)
 {
   tree link;
-  /* The chain of decls was accumulated in reverse order.
-     Put it into forward order, just for cleanliness.  */
-  tree decls;
+  tree block;
+  tree decl;
+  tree decls = current_binding_level->names;
   tree tags = current_binding_level->tags;
   tree subblocks = current_binding_level->blocks;
-  tree block = 0;
-  tree decl;
-  int block_previously_created;
 
-  keep |= current_binding_level->keep;
+  functionbody |= current_binding_level->function_body;
+  keep |= (current_binding_level->keep || functionbody
+          || (current_binding_level->keep_if_subblocks && subblocks != 0));
 
-  /* This warning is turned off because it causes warnings for
-     declarations like `extern struct foo *x'.  */
-#if 0
-  /* Warn about incomplete structure types in this level.  */
+  /* We used to warn about unused variables in expand_end_bindings,
+     i.e. while generating RTL.  But in function-at-a-time mode we may
+     choose to never expand a function at all (e.g. auto inlining), so
+     we do this explicitly now.  */
+  warn_about_unused_variables (decls);
+
+  /* Clear out the name-meanings declared on this level.
+     Propagate TREE_ADDRESSABLE from nested functions to their
+     containing functions.  */
+  for (link = decls; link; link = TREE_CHAIN (link))
+    {
+      if (DECL_NAME (link) != 0)
+       {
+         if (DECL_EXTERNAL (link))
+           /* External decls stay in the symbol-value slot but are
+              inaccessible.  */
+           C_DECL_INVISIBLE (link) = 1;
+         else
+           IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0;
+       }
+
+      if (TREE_CODE (link) == FUNCTION_DECL
+         && ! TREE_ASM_WRITTEN (link)
+         && DECL_INITIAL (link) != 0
+         && TREE_ADDRESSABLE (link)
+         && DECL_ABSTRACT_ORIGIN (link) != 0
+         && DECL_ABSTRACT_ORIGIN (link) != link)
+       TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (link)) = 1;
+    }
+
+  /* Clear out the tag-meanings declared on this level.  */
   for (link = tags; link; link = TREE_CHAIN (link))
-    if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
-      {
-       tree type = TREE_VALUE (link);
-       tree type_name = TYPE_NAME (type);
-       char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
-                                      ? type_name
-                                      : DECL_NAME (type_name));
-       switch (TREE_CODE (type))
-         {
-         case RECORD_TYPE:
-           error ("`struct %s' incomplete in scope ending here", id);
-           break;
-         case UNION_TYPE:
-           error ("`union %s' incomplete in scope ending here", id);
-           break;
-         case ENUMERAL_TYPE:
-           error ("`enum %s' incomplete in scope ending here", id);
-           break;
-         }
-      }
-#endif /* 0 */
+    if (TREE_PURPOSE (link))
+      IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = 0;
+
+  /* Restore all name-meanings of the outer levels
+     that were shadowed by this level.  */
+
+  for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
+    IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+
+  /* Restore all tag-meanings of the outer levels
+     that were shadowed by this level.  */
+
+  for (link = current_binding_level->shadowed_tags; link;
+       link = TREE_CHAIN (link))
+    IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+
+  /* If this is the top level block of a function, remove all
+     PARM_DECLs from current_binding_level->names; they are already
+     stored in DECL_ARGUMENTS of cfun->decl in proper order, should
+     not be put in BLOCK_VARS, and furthermore reversing them will
+     cause trouble later.  They are all together at the end of the
+     list.  */
+  if (functionbody && decls)
+    {
+      if (TREE_CODE (decls) == PARM_DECL)
+       decls = 0;
+      else
+       {
+         link = decls;
+         while (TREE_CHAIN (link)
+                && TREE_CODE (TREE_CHAIN (link)) != PARM_DECL)
+           link = TREE_CHAIN (link);
+
+         TREE_CHAIN (link) = 0;
+       }
+    }
 
   /* Get the decls in the order they were written.
      Usually current_binding_level->names is in reverse order.
      But parameter decls were previously put in forward order.  */
 
   if (reverse)
-    current_binding_level->names
-      = decls = nreverse (current_binding_level->names);
-  else
-    decls = current_binding_level->names;
-
-  /* Output any nested inline functions within this block
-     if they weren't already output.  */
-
-  for (decl = decls; decl; decl = TREE_CHAIN (decl))
-    if (TREE_CODE (decl) == FUNCTION_DECL
-       && ! TREE_ASM_WRITTEN (decl)
-       && DECL_INITIAL (decl) != 0
-       && TREE_ADDRESSABLE (decl))
-      {
-       /* If this decl was copied from a file-scope decl
-          on account of a block-scope extern decl,
-          propagate TREE_ADDRESSABLE to the file-scope decl.
-
-          DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
-          true, since then the decl goes through save_for_inline_copying.  */
-       if (DECL_ABSTRACT_ORIGIN (decl) != 0
-           && DECL_ABSTRACT_ORIGIN (decl) != decl)
-         TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-      }
-
-  /* We used to warn about unused variables in expand_end_bindings,
-     i.e. while generating RTL.  But in function-at-a-time mode we may
-     choose to never expand a function at all (e.g. auto inlining), so
-     we do this explicitly now.  */
-  warn_about_unused_variables (getdecls ());
+    decls = nreverse (decls);
 
   /* If there were any declarations or structure tags in that level,
      or if this level is a function body,
      create a BLOCK to record them for the life of this function.  */
 
   block = 0;
-  block_previously_created = (current_binding_level->this_block != 0);
-  if (block_previously_created)
-    block = current_binding_level->this_block;
-  else if (keep || functionbody
-          || (current_binding_level->keep_if_subblocks && subblocks != 0))
-    block = make_node (BLOCK);
-  if (block != 0)
+  if (keep)
     {
+      block = make_node (BLOCK);
       BLOCK_VARS (block) = decls;
       BLOCK_SUBBLOCKS (block) = subblocks;
+      TREE_USED (block) = 1;
     }
 
   /* In each subblock, record that this is its superior.  */
@@ -1002,50 +573,31 @@ poplevel (keep, reverse, functionbody)
   for (link = subblocks; link; link = TREE_CHAIN (link))
     BLOCK_SUPERCONTEXT (link) = block;
 
-  /* Clear out the meanings of the local variables of this level.  */
-
-  for (link = decls; link; link = TREE_CHAIN (link))
-    {
-      if (DECL_NAME (link) != 0)
-       {
-         /* If the ident. was used or addressed via a local extern decl,
-            don't forget that fact.  */
-         if (DECL_EXTERNAL (link))
-           {
-             if (TREE_USED (link))
-               TREE_USED (DECL_NAME (link)) = 1;
-             if (TREE_ADDRESSABLE (link))
-               TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
-           }
-         IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
-       }
-    }
+  /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
+     binding contour so that they point to the appropriate construct, i.e.
+     either to the current FUNCTION_DECL node, or else to the BLOCK node
+     we just constructed.
 
-  /* Restore all name-meanings of the outer levels
-     that were shadowed by this level.  */
+     Note that for tagged types whose scope is just the formal parameter
+     list for some function type specification, we can't properly set
+     their TYPE_CONTEXTs here, because we don't have a pointer to the
+     appropriate FUNCTION_TYPE node readily available to us.  For those
+     cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
+     in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
+     node which will represent the "scope" for these "parameter list local"
+     tagged types.  */
 
-  for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
-    IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+  decl = functionbody ? current_function_decl : block;
+  if (decl)
+    for (link = tags; link; link = TREE_CHAIN (link))
+      TYPE_CONTEXT (TREE_VALUE (link)) = decl;
 
-  /* If the level being exited is the top level of a function,
-     check over all the labels, and clear out the current
-     (function local) meanings of their names.  */
+  /* If the level being exited is the top level of a function, check
+     over all the labels, and clear out the current (function local)
+     meanings of their names. Then add them to BLOCK_VARS.  */
 
   if (functionbody)
     {
-      clear_limbo_values (block);
-
-      /* If this is the top level block of a function,
-        the vars are the function's parameters.
-        Don't leave them in the BLOCK because they are
-        found in the FUNCTION_DECL instead.  */
-
-      BLOCK_VARS (block) = 0;
-
-      /* Clear out the definitions of all label names,
-        since their scopes end here,
-        and add them to BLOCK_VARS.  */
-
       for (link = named_labels; link; link = TREE_CHAIN (link))
        {
          tree label = TREE_VALUE (link);
@@ -1054,8 +606,7 @@ poplevel (keep, reverse, functionbody)
            {
              error_with_decl (label, "label `%s' used but not defined");
              /* Avoid crashing later.  */
-             define_label (input_filename, lineno,
-                           DECL_NAME (label));
+             define_label (input_location, DECL_NAME (label));
            }
          else if (warn_unused_label && !TREE_USED (label))
            warning_with_decl (label, "label `%s' defined but not used");
@@ -1076,11 +627,8 @@ poplevel (keep, reverse, functionbody)
   if (functionbody)
     DECL_INITIAL (current_function_decl) = block;
   else if (block)
-    {
-      if (!block_previously_created)
-       current_binding_level->blocks
-         = chainon (current_binding_level->blocks, block);
-    }
+    current_binding_level->blocks
+      = chainon (current_binding_level->blocks, block);
   /* If we did not make a block for the level just exited,
      any blocks made for inner levels
      (since they cannot be recorded as subblocks in that level)
@@ -1090,30 +638,6 @@ poplevel (keep, reverse, functionbody)
     current_binding_level->blocks
       = chainon (current_binding_level->blocks, subblocks);
 
-  /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
-     binding contour so that they point to the appropriate construct, i.e.
-     either to the current FUNCTION_DECL node, or else to the BLOCK node
-     we just constructed.
-
-     Note that for tagged types whose scope is just the formal parameter
-     list for some function type specification, we can't properly set
-     their TYPE_CONTEXTs here, because we don't have a pointer to the
-     appropriate FUNCTION_TYPE node readily available to us.  For those
-     cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
-     in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
-     node which will represent the "scope" for these "parameter list local"
-     tagged types.  */
-
-  if (functionbody)
-    for (link = tags; link; link = TREE_CHAIN (link))
-      TYPE_CONTEXT (TREE_VALUE (link)) = current_function_decl;
-  else if (block)
-    for (link = tags; link; link = TREE_CHAIN (link))
-      TYPE_CONTEXT (TREE_VALUE (link)) = block;
-
-  if (block)
-    TREE_USED (block) = 1;
-
   return block;
 }
 
@@ -1122,30 +646,24 @@ poplevel (keep, reverse, functionbody)
    to handle the BLOCK node inside the BIND_EXPR.  */
 
 void
-insert_block (block)
-     tree block;
+insert_block (tree block)
 {
   TREE_USED (block) = 1;
   current_binding_level->blocks
     = chainon (current_binding_level->blocks, block);
 }
 
-/* Set the BLOCK node for the innermost scope
-   (the one we are currently in).  */
+/* Set the BLOCK node for the innermost scope (the one we are
+   currently in).  The RTL expansion machinery requires us to provide
+   this hook, but it is not useful in function-at-a-time mode.  */
 
 void
-set_block (block)
-     tree block;
+set_block (tree block ATTRIBUTE_UNUSED)
 {
-  current_binding_level->this_block = block;
-  current_binding_level->names = chainon (current_binding_level->names,
-                                         BLOCK_VARS (block));
-  current_binding_level->blocks = chainon (current_binding_level->blocks,
-                                          BLOCK_SUBBLOCKS (block));
 }
 \f
 void
-push_label_level ()
+push_label_level (void)
 {
   struct binding_level *newlevel;
 
@@ -1163,7 +681,7 @@ push_label_level ()
 }
 
 void
-pop_label_level ()
+pop_label_level (void)
 {
   struct binding_level *level = label_level_chain;
   tree link, prev;
@@ -1179,8 +697,7 @@ pop_label_level ()
              error_with_decl (TREE_VALUE (link),
                               "label `%s' used but not defined");
              /* Avoid crashing later.  */
-             define_label (input_filename, lineno,
-                           DECL_NAME (TREE_VALUE (link)));
+             define_label (input_location, DECL_NAME (TREE_VALUE (link)));
            }
          else if (warn_unused_label && !TREE_USED (TREE_VALUE (link)))
            warning_with_decl (TREE_VALUE (link),
@@ -1222,15 +739,9 @@ pop_label_level ()
    In that case, the TYPE_SIZE will be zero.  */
 
 void
-pushtag (name, type)
-     tree name, type;
+pushtag (tree name, tree type)
 {
-  struct binding_level *b;
-
-  /* Find the proper binding level for this type tag.  */
-
-  for (b = current_binding_level; b->tag_transparent; b = b->level_chain)
-    continue;
+  struct binding_level *b = current_binding_level;
 
   if (name)
     {
@@ -1238,6 +749,11 @@ pushtag (name, type)
 
       if (TYPE_NAME (type) == 0)
        TYPE_NAME (type) = name;
+
+      if (IDENTIFIER_TAG_VALUE (name))
+       b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name),
+                                     b->shadowed_tags);
+      IDENTIFIER_TAG_VALUE (name) = type;
     }
 
   b->tags = tree_cons (name, type, b->tags);
@@ -1268,9 +784,7 @@ pushtag (name, type)
    and OLDDECL is in an outer binding level and should thus not be changed.  */
 
 static int
-duplicate_decls (newdecl, olddecl, different_binding_level)
-     tree newdecl, olddecl;
-     int different_binding_level;
+duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
 {
   int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -1328,30 +842,16 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
       if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && (DECL_BUILT_IN (olddecl)
-             || DECL_BUILT_IN_NONANSI (olddecl)))
+         && DECL_BUILT_IN (olddecl))
        {
          /* If you declare a built-in or predefined function name as static,
             the old definition is overridden,
             but optionally warn this was a bad choice of name.  */
          if (!TREE_PUBLIC (newdecl))
            {
-             if (!warn_shadow)
-               ;
-             else if (DECL_BUILT_IN (olddecl))
+             if (warn_shadow)
                warning_with_decl (newdecl, "shadowing built-in function `%s'");
-             else
-               warning_with_decl (newdecl, "shadowing library function `%s'");
            }
-         /* Likewise, if the built-in is not ansi, then programs can
-            override it even globally without an error.  */
-         else if (! DECL_BUILT_IN (olddecl))
-           warning_with_decl (newdecl,
-                              "library function `%s' declared as non-function");
-
-         else if (DECL_BUILT_IN_NONANSI (olddecl))
-           warning_with_decl (newdecl,
-                              "built-in function `%s' declared as non-function");
          else
            warning_with_decl (newdecl,
                               "built-in function `%s' declared as non-function");
@@ -1365,11 +865,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
       return 0;
     }
 
-  /* For real parm decl following a forward decl,
-     return 1 so old decl will be reused.  */
+  /* For real parm decl following a forward decl, return 1 so old decl
+     will be reused.  Only allow this to happen once.  */
   if (types_match && TREE_CODE (newdecl) == PARM_DECL
       && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
-    return 1;
+    {
+      TREE_ASM_WRITTEN (olddecl) = 0;
+      return 1;
+    }
 
   /* The new declaration is the same kind of object as the old one.
      The declarations may partially match.  Print warnings if they don't
@@ -1506,6 +1009,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         we will come back here again.  */
       DECL_IN_SYSTEM_HEADER (newdecl) = 1;
     }
+  /* Permit void foo (...) to match int foo (...) if the latter is the
+     definition and implicit int was used.  See c-torture/compile/920625-2.c.  */
+  else if (!types_match        && new_is_definition
+          && TREE_CODE (olddecl) == FUNCTION_DECL
+          && TREE_CODE (newdecl) == FUNCTION_DECL
+          && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
+          && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
+          && C_FUNCTION_IMPLICIT_INT (newdecl))
+    {
+      pedwarn_with_decl (newdecl, "conflicting types for `%s'");
+      /* Make sure we keep void as the return type.  */
+      TREE_TYPE (newdecl) = newtype = oldtype;
+      C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
+    }
   else if (!types_match
           /* Permit char *foo (int, ...); followed by char *foo ();
              if not pedantic.  */
@@ -1550,6 +1067,30 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                }
            }
        }
+      if (C_DECL_IMPLICIT (olddecl))
+       error_with_decl (olddecl, "previous implicit declaration of `%s'");
+      else
+       error_with_decl (olddecl, "previous declaration of `%s'");
+
+      /* This is safer because the initializer might contain references
+        to variables that were declared between olddecl and newdecl. This
+        will make the initializer invalid for olddecl in case it gets
+        assigned to olddecl below.  */
+      if (TREE_CODE (newdecl) == VAR_DECL)
+       DECL_INITIAL (newdecl) = 0;
+    }
+  /* TLS cannot follow non-TLS declaration.  */
+  else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+          && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
+    {
+      error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration");
+      error_with_decl (olddecl, "previous declaration of `%s'");
+    }
+  /* non-TLS declaration cannot follow TLS declaration.  */
+  else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+          && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
+    {
+      error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration");
       error_with_decl (olddecl, "previous declaration of `%s'");
     }
   else
@@ -1760,11 +1301,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
       COPY_DECL_RTL (olddecl, newdecl);
 
       /* Merge the type qualifiers.  */
-      if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
-         && ! TREE_THIS_VOLATILE (newdecl))
-       TREE_THIS_VOLATILE (write_olddecl) = 0;
-
       if (TREE_READONLY (newdecl))
        TREE_READONLY (write_olddecl) = 1;
 
@@ -1823,6 +1359,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+         TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+         DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+         DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
        }
     }
   /* If cannot merge, then use the new type and qualifiers,
@@ -1878,9 +1418,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         inline, make sure we emit debug info for the inline before we
         throw it away, in case it was inlined into a function that hasn't
         been written out yet.  */
-      if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+      if (new_is_definition && DECL_INITIAL (olddecl))
        {
-         (*debug_hooks->outlining_inline_function) (olddecl);
+         if (TREE_USED (olddecl))
+           (*debug_hooks->outlining_inline_function) (olddecl);
 
          /* The new defn must not be inline.  */
          DECL_INLINE (newdecl) = 0;
@@ -1971,66 +1512,148 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
      Update OLDDECL to be the same.  */
   DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
 
+  /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
+     so that encode_section_info has a chance to look at the new decl
+     flags and attributes.  */
+  if (DECL_RTL_SET_P (olddecl)
+      && (TREE_CODE (olddecl) == FUNCTION_DECL
+         || (TREE_CODE (olddecl) == VAR_DECL
+             && TREE_STATIC (olddecl))))
+    make_decl_rtl (olddecl, NULL);
+
   return 1;
 }
 
+/* Return any external DECL associated with ID, whether or not it is
+   currently in scope.  */
+
+static tree
+any_external_decl (tree id)
+{
+  tree decl = IDENTIFIER_SYMBOL_VALUE (id);
+  tree t;
+
+  if (decl == 0 || TREE_CODE (decl) == ERROR_MARK)
+    return 0;
+  else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl))
+    return decl;
+
+  t = purpose_member (id, truly_local_externals);
+  if (t)
+    return TREE_VALUE (t);
+
+  return 0;
+}
+
+/* Record an external decl DECL.  This only does something if a
+   shadowing decl already exists.  */
+static void
+record_external_decl (tree decl)
+{
+  tree name = DECL_NAME (decl);
+  if (!IDENTIFIER_SYMBOL_VALUE (name))
+    return;
+
+  truly_local_externals = tree_cons (name, decl, truly_local_externals);
+}
+
 /* Check whether decl-node X shadows an existing declaration.
-   OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X,
+   OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X,
    which might be a NULL_TREE.  */
 static void
-warn_if_shadowing (x, oldlocal)
-     tree x, oldlocal;
+warn_if_shadowing (tree x, tree old)
 {
-  tree name;
+  const char *name;
 
-  if (DECL_EXTERNAL (x))
+  /* Nothing to shadow?  */
+  if (old == 0
+      /* Shadow warnings not wanted?  */
+      || !warn_shadow
+      /* No shadow warnings for internally generated vars.  */
+      || DECL_SOURCE_LINE (x) == 0
+      /* No shadow warnings for vars made for inlining.  */
+      || DECL_FROM_INLINE (x)
+      /* Don't warn about the parm names in function declarator
+        within a function declarator.
+        It would be nice to avoid warning in any function
+        declarator in a declaration, as opposed to a definition,
+        but there is no way to tell it's not a definition.  */
+      || (TREE_CODE (x) == PARM_DECL
+         && current_binding_level->level_chain->parm_flag))
     return;
 
-  name = DECL_NAME (x);
+  name = IDENTIFIER_POINTER (DECL_NAME (x));
+
+  if (TREE_CODE (old) == PARM_DECL)
+    shadow_warning (SW_PARAM, name, old);
+  else if (DECL_CONTEXT (old) == 0)
+    shadow_warning (SW_GLOBAL, name, old);
+  else
+    shadow_warning (SW_LOCAL, name, old);
+}
 
-  /* Warn if shadowing an argument at the top level of the body.  */
-  if (oldlocal != 0
-      /* This warning doesn't apply to the parms of a nested fcn.  */
-      && ! current_binding_level->parm_flag
-      /* Check that this is one level down from the parms.  */
-      && current_binding_level->level_chain->parm_flag
-      /* Check that the decl being shadowed
-        comes from the parm level, one level up.  */
-      && chain_member (oldlocal, current_binding_level->level_chain->names))
+
+/* Subroutine of pushdecl.
+
+   X is a TYPE_DECL for a typedef statement.  Create a brand new
+   ..._TYPE node (which will be just a variant of the existing
+   ..._TYPE node with identical properties) and then install X
+   as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
+
+   The whole point here is to end up with a situation where each
+   and every ..._TYPE node the compiler creates will be uniquely
+   associated with AT MOST one node representing a typedef name.
+   This way, even though the compiler substitutes corresponding
+   ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
+   early on, later parts of the compiler can always do the reverse
+   translation and get back the corresponding typedef name.  For
+   example, given:
+
+        typedef struct S MY_TYPE;
+       MY_TYPE object;
+
+   Later parts of the compiler might only know that `object' was of
+   type `struct S' if it were not for code just below.  With this
+   code however, later parts of the compiler see something like:
+
+       struct S' == struct S
+       typedef struct S' MY_TYPE;
+       struct S' object;
+
+    And they can then deduce (from the node for type struct S') that
+    the original object declaration was:
+
+               MY_TYPE object;
+
+    Being able to do this is important for proper support of protoize,
+    and also for generating precise symbolic debugging information
+    which takes full account of the programmer's (typedef) vocabulary.
+
+    Obviously, we don't want to generate a duplicate ..._TYPE node if
+    the TYPE_DECL node that we are now processing really represents a
+    standard built-in type.
+
+    Since all standard types are effectively declared at line zero
+    in the source file, we can easily check to see if we are working
+    on a standard type by checking the current value of lineno.  */
+
+static void
+clone_underlying_type (tree x)
+{
+  if (DECL_SOURCE_LINE (x) == 0)
     {
-      if (TREE_CODE (oldlocal) == PARM_DECL)
-       pedwarn ("declaration of `%s' shadows a parameter",
-                IDENTIFIER_POINTER (name));
-      else
-       pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
-                IDENTIFIER_POINTER (name));
+      if (TYPE_NAME (TREE_TYPE (x)) == 0)
+       TYPE_NAME (TREE_TYPE (x)) = x;
     }
-  /* Maybe warn if shadowing something else.  */
-  else if (warn_shadow
-          /* No shadow warnings for internally generated vars.  */
-          && DECL_SOURCE_LINE (x) != 0
-          /* No shadow warnings for vars made for inlining.  */
-          && ! DECL_FROM_INLINE (x))
+  else if (TREE_TYPE (x) != error_mark_node
+          && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
     {
-      if (TREE_CODE (x) == PARM_DECL
-         && current_binding_level->level_chain->parm_flag)
-       /* Don't warn about the parm names in function declarator
-          within a function declarator.
-          It would be nice to avoid warning in any function
-          declarator in a declaration, as opposed to a definition,
-          but there is no way to tell it's not a definition.  */
-       ;
-      else if (oldlocal)
-       {
-         if (TREE_CODE (oldlocal) == PARM_DECL)
-           shadow_warning ("a parameter", name, oldlocal);
-         else
-           shadow_warning ("a previous local", name, oldlocal);
-       }
-      else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
-              && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-       shadow_warning ("a global declaration", name,
-                       IDENTIFIER_GLOBAL_VALUE (name));
+      tree tt = TREE_TYPE (x);
+      DECL_ORIGINAL_TYPE (x) = tt;
+      tt = build_type_copy (tt);
+      TYPE_NAME (tt) = x;
+      TREE_USED (tt) = TREE_USED (x);
+      TREE_TYPE (x) = tt;
     }
 }
 
@@ -2043,346 +1666,81 @@ warn_if_shadowing (x, oldlocal)
    to agree with what X says.  */
 
 tree
-pushdecl (x)
-     tree x;
+pushdecl (tree x)
 {
-  tree t;
   tree name = DECL_NAME (x);
-  struct binding_level *b = current_binding_level;
+  struct binding_level *scope = current_binding_level;
+
+#ifdef ENABLE_CHECKING
+  if (error_mark_node == 0)
+    /* Called too early.  */
+    abort ();
+#endif
 
   /* Functions need the lang_decl data.  */
   if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
     DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
       ggc_alloc_cleared (sizeof (struct lang_decl));
 
-  DECL_CONTEXT (x) = current_function_decl;
   /* A local extern declaration for a function doesn't constitute nesting.
      A local auto declaration does, since it's a forward decl
      for a nested function coming later.  */
   if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
       && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
     DECL_CONTEXT (x) = 0;
+  else
+    DECL_CONTEXT (x) = current_function_decl;
 
   if (name)
     {
-      int different_binding_level = 0;
+      tree old;
 
       if (warn_nested_externs
+         && scope != global_binding_level
          && DECL_EXTERNAL (x)
-         && b != global_binding_level
-         && x != IDENTIFIER_IMPLICIT_DECL (name)
-         /* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__.  */
          && !DECL_IN_SYSTEM_HEADER (x))
        warning ("nested extern declaration of `%s'",
                 IDENTIFIER_POINTER (name));
 
-      t = lookup_name_current_level (name);
-      if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
-       {
-         t = IDENTIFIER_GLOBAL_VALUE (name);
-         /* Type decls at global scope don't conflict with externs declared
-            inside lexical blocks.  */
-         if (! t || TREE_CODE (t) == TYPE_DECL)
-           /* If there's no visible global declaration, try for an
-               invisible one.  */
-           t = IDENTIFIER_LIMBO_VALUE (name);
-         different_binding_level = 1;
-       }
-      if (t != 0 && t == error_mark_node)
-       /* error_mark_node is 0 for a while during initialization!  */
-       {
-         t = 0;
-         error_with_decl (x, "`%s' used prior to declaration");
-       }
-
-      /* If this decl is `static' and an implicit decl was seen previously,
-        warn.  */
-      if (TREE_PUBLIC (name)
-         /* Don't test for DECL_EXTERNAL, because grokdeclarator
-            sets this for all functions.  */
-         && ! TREE_PUBLIC (x)
-         && (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level)
-         /* We used to warn also for explicit extern followed by static,
-            but sometimes you need to do it that way.  */
-         && IDENTIFIER_IMPLICIT_DECL (name) != 0)
-       {
-         pedwarn ("`%s' was declared implicitly `extern' and later `static'",
-                  IDENTIFIER_POINTER (name));
-         pedwarn_with_file_and_line
-           (DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)),
-            DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)),
-            "previous declaration of `%s'",
-            IDENTIFIER_POINTER (name));
-         TREE_THIS_VOLATILE (name) = 1;
-       }
-
-      if (t != 0 && duplicate_decls (x, t, different_binding_level))
-       {
-         if (TREE_CODE (t) == PARM_DECL)
-           {
-             /* Don't allow more than one "real" duplicate
-                of a forward parm decl.  */
-             TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
-             return t;
-           }
-         return t;
-       }
-
-      /* If we are processing a typedef statement, generate a whole new
-        ..._TYPE node (which will be just an variant of the existing
-        ..._TYPE node with identical properties) and then install the
-        TYPE_DECL node generated to represent the typedef name as the
-        TYPE_NAME of this brand new (duplicate) ..._TYPE node.
-
-        The whole point here is to end up with a situation where each
-        and every ..._TYPE node the compiler creates will be uniquely
-        associated with AT MOST one node representing a typedef name.
-        This way, even though the compiler substitutes corresponding
-        ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
-        early on, later parts of the compiler can always do the reverse
-        translation and get back the corresponding typedef name.  For
-        example, given:
-
-               typedef struct S MY_TYPE;
-               MY_TYPE object;
-
-        Later parts of the compiler might only know that `object' was of
-        type `struct S' if it were not for code just below.  With this
-        code however, later parts of the compiler see something like:
-
-               struct S' == struct S
-               typedef struct S' MY_TYPE;
-               struct S' object;
-
-        And they can then deduce (from the node for type struct S') that
-        the original object declaration was:
-
-               MY_TYPE object;
-
-        Being able to do this is important for proper support of protoize,
-        and also for generating precise symbolic debugging information
-        which takes full account of the programmer's (typedef) vocabulary.
-
-         Obviously, we don't want to generate a duplicate ..._TYPE node if
-        the TYPE_DECL node that we are now processing really represents a
-        standard built-in type.
-
-         Since all standard types are effectively declared at line zero
-         in the source file, we can easily check to see if we are working
-         on a standard type by checking the current value of lineno.  */
-
-      if (TREE_CODE (x) == TYPE_DECL)
+      old = lookup_name_current_level (name);
+      if (old && duplicate_decls (x, old, 0))
+       return old;
+      if (DECL_EXTERNAL (x) || scope == global_binding_level)
        {
-         if (DECL_SOURCE_LINE (x) == 0)
+         /* Find and check against a previous, not-in-scope, external
+            decl for this identifier.  (C99 s???: If two declarations
+            with external linkage, referring to the same object, have
+            incompatible types, the behavior is undefined).  */
+         tree ext = any_external_decl (name);
+         if (ext)
            {
-             if (TYPE_NAME (TREE_TYPE (x)) == 0)
-               TYPE_NAME (TREE_TYPE (x)) = x;
+             if (duplicate_decls (x, ext, scope != global_binding_level))
+               x = copy_node (ext);
            }
-         else if (TREE_TYPE (x) != error_mark_node
-                  && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
-           {
-             tree tt = TREE_TYPE (x);
-             DECL_ORIGINAL_TYPE (x) = tt;
-             tt = build_type_copy (tt);
-             TYPE_NAME (tt) = x;
-             TREE_USED (tt) = TREE_USED (x);
-             TREE_TYPE (x) = tt;
-           }
-       }
-
-      /* Multiple external decls of the same identifier ought to match.
-        We get warnings about inline functions where they are defined.
-        Avoid duplicate warnings where they are used.  */
-      if (TREE_PUBLIC (x)
-         && ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
-       {
-         tree decl;
-
-         if (IDENTIFIER_LIMBO_VALUE (name) != 0)
-           /* Decls in limbo are always extern, so no need to check that.  */
-           decl = IDENTIFIER_LIMBO_VALUE (name);
          else
-           decl = 0;
-
-         if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
-             /* If old decl is built-in, we already warned if we should.  */
-             && !DECL_BUILT_IN (decl))
-           {
-             pedwarn_with_decl (x,
-                                "type mismatch with previous external decl");
-             pedwarn_with_decl (decl, "previous external decl of `%s'");
-           }
-       }
-
-      /* If a function has had an implicit declaration, and then is defined,
-        make sure they are compatible.  */
-
-      if (IDENTIFIER_IMPLICIT_DECL (name) != 0
-         && IDENTIFIER_GLOBAL_VALUE (name) == 0
-         && TREE_CODE (x) == FUNCTION_DECL
-         && ! comptypes (TREE_TYPE (x),
-                         TREE_TYPE (IDENTIFIER_IMPLICIT_DECL (name))))
-       {
-         warning_with_decl (x, "type mismatch with previous implicit declaration");
-         warning_with_decl (IDENTIFIER_IMPLICIT_DECL (name),
-                            "previous implicit declaration of `%s'");
+           record_external_decl (x);
        }
 
-      /* This name is new in its binding level.
-        Install the new declaration and return it.  */
-      if (b == global_binding_level)
+      if (TREE_CODE (x) == TYPE_DECL)
+       clone_underlying_type (x);
+
+      /* If storing a local value, there may already be one
+        (inherited).  If so, record it for restoration when this
+        binding level ends.  Take care not to do this if we are
+        replacing an older decl in the same binding level (i.e.
+        duplicate_decls returned false, above).  */
+      if (scope != global_binding_level
+         && IDENTIFIER_SYMBOL_VALUE (name)
+         && IDENTIFIER_SYMBOL_VALUE (name) != old)
        {
-         /* Install a global value.  */
-
-         /* If the first global decl has external linkage,
-            warn if we later see static one.  */
-         if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
-           TREE_PUBLIC (name) = 1;
-
-         IDENTIFIER_GLOBAL_VALUE (name) = x;
-
-         /* We no longer care about any previous block level declarations.  */
-         IDENTIFIER_LIMBO_VALUE (name) = 0;
-
-         /* Don't forget if the function was used via an implicit decl.  */
-         if (IDENTIFIER_IMPLICIT_DECL (name)
-             && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
-           TREE_USED (x) = 1, TREE_USED (name) = 1;
-
-         /* Don't forget if its address was taken in that way.  */
-         if (IDENTIFIER_IMPLICIT_DECL (name)
-             && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
-           TREE_ADDRESSABLE (x) = 1;
-
-         /* Warn about mismatches against previous implicit decl.  */
-         if (IDENTIFIER_IMPLICIT_DECL (name) != 0
-             /* If this real decl matches the implicit, don't complain.  */
-             && ! (TREE_CODE (x) == FUNCTION_DECL
-                   && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x)))
-                       == integer_type_node)))
-           pedwarn ("`%s' was previously implicitly declared to return `int'",
-                    IDENTIFIER_POINTER (name));
-
-         /* If this decl is `static' and an `extern' was seen previously,
-            that is erroneous.  */
-         if (TREE_PUBLIC (name)
-             && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x))
-           {
-             /* Okay to redeclare an ANSI built-in as static.  */
-             if (t != 0 && DECL_BUILT_IN (t))
-               ;
-             /* Okay to declare a non-ANSI built-in as anything.  */
-             else if (t != 0 && DECL_BUILT_IN_NONANSI (t))
-               ;
-             /* Okay to have global type decl after an earlier extern
-                declaration inside a lexical block.  */
-             else if (TREE_CODE (x) == TYPE_DECL)
-               ;
-             else if (IDENTIFIER_IMPLICIT_DECL (name))
-               {
-                 if (! TREE_THIS_VOLATILE (name))
-                   pedwarn ("`%s' was declared implicitly `extern' and later `static'",
-                            IDENTIFIER_POINTER (name));
-               }
-             else
-               pedwarn ("`%s' was declared `extern' and later `static'",
-                        IDENTIFIER_POINTER (name));
-           }
+         warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name));
+         scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
+                                      scope->shadowed);
        }
-      else
-       {
-         /* Here to install a non-global value.  */
-         tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
-         tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
-
-         IDENTIFIER_LOCAL_VALUE (name) = x;
-
-         /* If this is an extern function declaration, see if we
-            have a global definition or declaration for the function.  */
-         if (oldlocal == 0
-             && oldglobal != 0
-             && TREE_CODE (x) == FUNCTION_DECL
-             && TREE_CODE (oldglobal) == FUNCTION_DECL
-             && DECL_EXTERNAL (x)
-             && ! DECL_DECLARED_INLINE_P (x))
-           {
-             /* We have one.  Their types must agree.  */
-             if (! comptypes (TREE_TYPE (x),
-                              TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name))))
-               pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one");
-             else
-               {
-                 /* Inner extern decl is inline if global one is.
-                    Copy enough to really inline it.  */
-                 if (DECL_DECLARED_INLINE_P (oldglobal))
-                   {
-                     DECL_DECLARED_INLINE_P (x)
-                       = DECL_DECLARED_INLINE_P (oldglobal);
-                     DECL_INLINE (x) = DECL_INLINE (oldglobal);
-                     DECL_INITIAL (x) = (current_function_decl == oldglobal
-                                         ? 0 : DECL_INITIAL (oldglobal));
-                     DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
-                     DECL_NUM_STMTS (x) = DECL_NUM_STMTS (oldglobal);
-                     DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
-                     DECL_RESULT (x) = DECL_RESULT (oldglobal);
-                     TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
-                     DECL_ABSTRACT_ORIGIN (x)
-                       = DECL_ABSTRACT_ORIGIN (oldglobal);
-                   }
-                 /* Inner extern decl is built-in if global one is.  */
-                 if (DECL_BUILT_IN (oldglobal))
-                   {
-                     DECL_BUILT_IN_CLASS (x) = DECL_BUILT_IN_CLASS (oldglobal);
-                     DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
-                   }
-                 /* Keep the arg types from a file-scope fcn defn.  */
-                 if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0
-                     && DECL_INITIAL (oldglobal)
-                     && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0)
-                   TREE_TYPE (x) = TREE_TYPE (oldglobal);
-               }
-           }
 
-#if 0
-         /* This case is probably sometimes the right thing to do.  */
-         /* If we have a local external declaration,
-            then any file-scope declaration should not
-            have been static.  */
-         if (oldlocal == 0 && oldglobal != 0
-             && !TREE_PUBLIC (oldglobal)
-             && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
-           warning ("`%s' locally external but globally static",
-                    IDENTIFIER_POINTER (name));
-#endif
-
-         /* If we have a local external declaration,
-            and no file-scope declaration has yet been seen,
-            then if we later have a file-scope decl it must not be static.  */
-         if (oldlocal == 0
-             && DECL_EXTERNAL (x)
-             && TREE_PUBLIC (x))
-           {
-             if (oldglobal == 0)
-               TREE_PUBLIC (name) = 1;
-
-             /* Save this decl, so that we can do type checking against
-                other decls after it falls out of scope.
-
-                Only save it once.  This prevents temporary decls created in
-                expand_inline_function from being used here, since this
-                will have been set when the inline function was parsed.
-                It also helps give slightly better warnings.  */
-             if (IDENTIFIER_LIMBO_VALUE (name) == 0)
-               IDENTIFIER_LIMBO_VALUE (name) = x;
-           }
-
-         warn_if_shadowing (x, oldlocal);
-
-         /* If storing a local value, there may already be one (inherited).
-            If so, record it for restoration when this binding level ends.  */
-         if (oldlocal != 0)
-           b->shadowed = tree_cons (name, oldlocal, b->shadowed);
-       }
+      /* Install the new declaration in the requested binding level.  */
+      IDENTIFIER_SYMBOL_VALUE (name) = x;
+      C_DECL_INVISIBLE (x) = 0;
 
       /* Keep list of variables in this level with incomplete type.
         If the input is erroneous, we can have error_mark in the type
@@ -2397,84 +1755,133 @@ pushdecl (x)
            element = TREE_TYPE (element);
          if (TREE_CODE (element) == RECORD_TYPE
              || TREE_CODE (element) == UNION_TYPE)
-           b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
+           scope->incomplete_list = tree_cons (NULL_TREE, x,
+                                               scope->incomplete_list);
        }
     }
 
   /* Put decls on list in reverse order.
      We will reverse them later if necessary.  */
-  TREE_CHAIN (x) = b->names;
-  b->names = x;
+  TREE_CHAIN (x) = scope->names;
+  scope->names = x;
 
   return x;
 }
 
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate.  */
-
+/* Record X as belonging to the global scope (C99 "file scope").
+   This is used only internally by the Objective-C front end,
+   and is limited to its needs.  It will hork if there is _any_
+   visible binding for X (not just a global one).  */
 tree
-pushdecl_top_level (x)
-     tree x;
+pushdecl_top_level (tree x)
 {
-  tree t;
-  struct binding_level *b = current_binding_level;
+  tree name, old;
 
-  current_binding_level = global_binding_level;
-  t = pushdecl (x);
-  current_binding_level = b;
-  return t;
+  if (TREE_CODE (x) != VAR_DECL)
+    abort ();
+
+  name = DECL_NAME (x);
+  old = IDENTIFIER_SYMBOL_VALUE (name);
+
+  if (old)
+    {
+      if (DECL_CONTEXT (old))
+       abort ();
+
+      if (!duplicate_decls (x, old, 0))
+       abort ();
+
+      return old;
+    }
+
+  DECL_CONTEXT (x) = 0;
+  IDENTIFIER_SYMBOL_VALUE (name) = x;
+  TREE_CHAIN (x) = global_binding_level->names;
+  global_binding_level->names = x;
+  return x;
 }
-\f
-/* Generate an implicit declaration for identifier FUNCTIONID
-   as a function of type int ().  Print a warning if appropriate.  */
 
+/* Record X as belonging to the outermost scope of the current
+   function.  This is used only internally, by c_make_fname_decl and
+   build_external_ref, and is limited to their needs.  The NAME is
+   provided as a separate argument because build_external_ref wants to
+   use error_mark_node for X.  For VAR_DECLs, duplicate_decls is not
+   called; if there is any preexisting decl for this identifier, it is
+   an ICE.  */
 tree
-implicitly_declare (functionid)
-     tree functionid;
+pushdecl_function_level (tree x, tree name)
 {
-  tree decl;
-  int traditional_warning = 0;
-  /* Only one "implicit declaration" warning per identifier.  */
-  int implicit_warning;
+  struct binding_level *scope;
+
+  scope = current_binding_level;
+  while (scope->function_body == 0)
+    scope = scope->level_chain;
+  if (!scope)
+    abort ();
+
+  if (x == error_mark_node)
+    scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
+                                scope->shadowed);
+  else if (TREE_CODE (x) == VAR_DECL)
+    {
+      if (name != DECL_NAME (x))
+       abort ();
+      if (IDENTIFIER_SYMBOL_VALUE (name))
+       abort ();
 
-  /* We used to reuse an old implicit decl here,
-     but this loses with inline functions because it can clobber
-     the saved decl chains.  */
-#if 0
-  if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
-    decl = IDENTIFIER_IMPLICIT_DECL (functionid);
-  else
-#endif
-    decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
+      DECL_CONTEXT (x) = current_function_decl;
+      TREE_CHAIN (x) = scope->names;
+      scope->names = x;
+    }
 
-  /* Warn of implicit decl following explicit local extern decl.
-     This is probably a program designed for traditional C.  */
-  if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0)
-    traditional_warning = 1;
+  IDENTIFIER_SYMBOL_VALUE (name) = x;
+  return x;
+}
+\f
+/* Generate an implicit declaration for identifier FUNCTIONID as a
+   function of type int ().  */
+
+tree
+implicitly_declare (tree functionid)
+{
+  tree decl = any_external_decl (functionid);
 
-  /* Warn once of an implicit declaration.  */
-  implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0);
+  if (decl && decl != error_mark_node)
+    {
+      /* Implicit declaration of a function already declared
+        (somehow) in a different scope, or as a built-in.
+        If this is the first time this has happened, warn;
+        then recycle the old declaration.  */
+      if (!C_DECL_IMPLICIT (decl))
+       {
+         implicit_decl_warning (DECL_NAME (decl));
+         if (DECL_CONTEXT (decl))
+           warning_with_decl (decl, "previous declaration of `%s'");
+         C_DECL_IMPLICIT (decl) = 1;
+       }
+      /* If this function is global, then it must already be in the
+        global binding level, so there's no need to push it again.  */
+      if (current_binding_level == global_binding_level)
+       return decl;
+      /* If this is a local declaration, make a copy; we can't have
+        the same DECL listed in two different binding levels.  */
+      return pushdecl (copy_node (decl));
+    }
 
+  /* Not seen before.  */
+  decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
-
-  /* Record that we have an implicit decl and this is it.  */
-  IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
+  C_DECL_IMPLICIT (decl) = 1;
+  implicit_decl_warning (functionid);
 
   /* ANSI standard says implicit declarations are in the innermost block.
      So we record the decl in the standard fashion.  */
-  pushdecl (decl);
-
-  /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-  maybe_objc_check_decl (decl);
+  decl = pushdecl (decl);
 
+  /* No need to call objc_check_decl here - it's a function type.  */
   rest_of_decl_compilation (decl, NULL, 0, 0);
 
-  if (implicit_warning)
-    implicit_decl_warning (functionid);
-  else if (warn_traditional && traditional_warning)
-    warning ("function `%s' was previously declared within a block",
-            IDENTIFIER_POINTER (functionid));
-
   /* Write a record describing this implicit function declaration to the
      prototypes file (if requested).  */
 
@@ -2486,9 +1893,8 @@ implicitly_declare (functionid)
   return decl;
 }
 
-void
-implicit_decl_warning (id)
-     tree id;
+static void
+implicit_decl_warning (tree id)
 {
   const char *name = IDENTIFIER_POINTER (id);
   if (mesg_implicit_function_declaration == 2)
@@ -2504,8 +1910,7 @@ implicit_decl_warning (id)
    and 3 if it is a conflicting declaration.  */
 
 static int
-redeclaration_error_message (newdecl, olddecl)
-     tree newdecl, olddecl;
+redeclaration_error_message (tree newdecl, tree olddecl)
 {
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
@@ -2566,8 +1971,7 @@ redeclaration_error_message (newdecl, olddecl)
    This function is called for both label definitions and label references.  */
 
 tree
-lookup_label (id)
-     tree id;
+lookup_label (tree id)
 {
   tree decl = IDENTIFIER_LABEL_VALUE (id);
 
@@ -2597,8 +2001,7 @@ lookup_label (id)
 
   /* Say where one reference is to the label,
      for the sake of the error if it is not defined.  */
-  DECL_SOURCE_LINE (decl) = lineno;
-  DECL_SOURCE_FILE (decl) = input_filename;
+  DECL_SOURCE_LOCATION (decl) = input_location;
 
   IDENTIFIER_LABEL_VALUE (id) = decl;
 
@@ -2616,8 +2019,7 @@ lookup_label (id)
    requires calling declare_nonlocal_label right away.  */
 
 tree
-shadow_label (name)
-     tree name;
+shadow_label (tree name)
 {
   tree decl = IDENTIFIER_LABEL_VALUE (name);
 
@@ -2650,10 +2052,7 @@ shadow_label (name)
    Otherwise return 0.  */
 
 tree
-define_label (filename, line, name)
-     const char *filename;
-     int line;
-     tree name;
+define_label (location_t location, tree name)
 {
   tree decl = lookup_label (name);
 
@@ -2666,14 +2065,12 @@ define_label (filename, line, name)
     }
 
   if (warn_traditional && !in_system_header && lookup_name (name))
-    warning_with_file_and_line (filename, line,
-                               "traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
-                               IDENTIFIER_POINTER (name));
+    warning ("%Htraditional C lacks a separate namespace for labels, "
+             "identifier `%s' conflicts", &location, IDENTIFIER_POINTER (name));
 
   if (DECL_INITIAL (decl) != 0)
     {
-      error_with_file_and_line (filename, line, "duplicate label `%s'",
-                               IDENTIFIER_POINTER (name));
+      error ("%Hduplicate label `%s'", &location, IDENTIFIER_POINTER (name));
       return 0;
     }
   else
@@ -2681,8 +2078,7 @@ define_label (filename, line, name)
       /* Mark label as having been defined.  */
       DECL_INITIAL (decl) = error_mark_node;
       /* Say where in the source.  */
-      DECL_SOURCE_FILE (decl) = filename;
-      DECL_SOURCE_LINE (decl) = line;
+      DECL_SOURCE_LOCATION (decl) = location;
       return decl;
     }
 }
@@ -2693,7 +2089,7 @@ define_label (filename, line, name)
    store the result back using `storedecls' or you will lose.  */
 
 tree
-getdecls ()
+getdecls (void)
 {
   return current_binding_level->names;
 }
@@ -2701,7 +2097,7 @@ getdecls ()
 /* Return the list of type-tags (for structs, etc) of the current level.  */
 
 tree
-gettags ()
+gettags (void)
 {
   return current_binding_level->tags;
 }
@@ -2711,8 +2107,7 @@ gettags ()
    after they are modified in the light of any missing parameters.  */
 
 static void
-storedecls (decls)
-     tree decls;
+storedecls (tree decls)
 {
   current_binding_level->names = decls;
 }
@@ -2720,63 +2115,53 @@ storedecls (decls)
 /* Similarly, store the list of tags of the current level.  */
 
 static void
-storetags (tags)
-     tree tags;
+storetags (tree tags)
 {
   current_binding_level->tags = tags;
 }
 \f
 /* Given NAME, an IDENTIFIER_NODE,
    return the structure (or union or enum) definition for that name.
-   Searches binding levels from BINDING_LEVEL up to the global level.
-   If THISLEVEL_ONLY is nonzero, searches only the specified context
-   (but skips any tag-transparent contexts to find one that is
-   meaningful for tags).
+   If THISLEVEL_ONLY is nonzero, searches only the current_binding_level.
    CODE says which kind of type the caller wants;
    it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
    If the wrong kind of type is found, an error is reported.  */
 
 static tree
-lookup_tag (code, name, binding_level, thislevel_only)
-     enum tree_code code;
-     struct binding_level *binding_level;
-     tree name;
-     int thislevel_only;
+lookup_tag (enum tree_code code, tree name, int thislevel_only)
 {
-  struct binding_level *level;
-  int thislevel = 1;
+  tree tag = IDENTIFIER_TAG_VALUE (name);
+  int thislevel = 0;
 
-  for (level = binding_level; level; level = level->level_chain)
+  if (!tag)
+    return 0;
+
+  /* We only care about whether it's in this level if
+     thislevel_only was set or it might be a type clash.  */
+  if (thislevel_only || TREE_CODE (tag) != code)
     {
-      tree tail;
-      for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
-       {
-         if (TREE_PURPOSE (tail) == name)
-           {
-             if (TREE_CODE (TREE_VALUE (tail)) != code)
-               {
-                 /* Definition isn't the kind we were looking for.  */
-                 pending_invalid_xref = name;
-                 pending_invalid_xref_file = input_filename;
-                 pending_invalid_xref_line = lineno;
-                 /* If in the same binding level as a declaration as a tag
-                    of a different type, this must not be allowed to
-                    shadow that tag, so give the error immediately.
-                    (For example, "struct foo; union foo;" is invalid.)  */
-                 if (thislevel)
-                   pending_xref_error ();
-               }
-             return TREE_VALUE (tail);
-           }
-       }
-      if (! level->tag_transparent)
-       {
-         if (thislevel_only)
-           return NULL_TREE;
-         thislevel = 0;
-       }
+      if (current_binding_level == global_binding_level
+         || purpose_member (name, current_binding_level->tags))
+       thislevel = 1;
     }
-  return NULL_TREE;
+
+  if (thislevel_only && !thislevel)
+    return 0;
+
+  if (TREE_CODE (tag) != code)
+    {
+      /* Definition isn't the kind we were looking for.  */
+      pending_invalid_xref = name;
+      pending_invalid_xref_location = input_location;
+
+      /* If in the same binding level as a declaration as a tag
+        of a different type, this must not be allowed to
+        shadow that tag, so give the error immediately.
+        (For example, "struct foo; union foo;" is invalid.)  */
+      if (thislevel)
+       pending_xref_error ();
+    }
+  return tag;
 }
 
 /* Print an error message now
@@ -2785,36 +2170,15 @@ lookup_tag (code, name, binding_level, thislevel_only)
    when used in the `struct foo;' construct for shadowing.  */
 
 void
-pending_xref_error ()
+pending_xref_error (void)
 {
   if (pending_invalid_xref != 0)
-    error_with_file_and_line (pending_invalid_xref_file,
-                             pending_invalid_xref_line,
-                             "`%s' defined as wrong kind of tag",
-                             IDENTIFIER_POINTER (pending_invalid_xref));
+    error ("%H`%s' defined as wrong kind of tag",
+           &pending_invalid_xref_location,
+           IDENTIFIER_POINTER (pending_invalid_xref));
   pending_invalid_xref = 0;
 }
 
-/* Given a type, find the tag that was defined for it and return the tag name.
-   Otherwise return 0.  */
-
-static tree
-lookup_tag_reverse (type)
-     tree type;
-{
-  struct binding_level *level;
-
-  for (level = current_binding_level; level; level = level->level_chain)
-    {
-      tree tail;
-      for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
-       {
-         if (TREE_VALUE (tail) == type)
-           return TREE_PURPOSE (tail);
-       }
-    }
-  return NULL_TREE;
-}
 \f
 /* Look up NAME in the current binding level and its superiors
    in the namespace of variables, functions and typedefs.
@@ -2822,38 +2186,34 @@ lookup_tag_reverse (type)
    or return 0 if it is undefined.  */
 
 tree
-lookup_name (name)
-     tree name;
+lookup_name (tree name)
 {
-  tree val;
-
-  if (current_binding_level != global_binding_level
-      && IDENTIFIER_LOCAL_VALUE (name))
-    val = IDENTIFIER_LOCAL_VALUE (name);
-  else
-    val = IDENTIFIER_GLOBAL_VALUE (name);
-  return val;
+  tree decl = IDENTIFIER_SYMBOL_VALUE (name);
+  if (decl == 0 || decl == error_mark_node)
+    return decl;
+  if (C_DECL_INVISIBLE (decl))
+    return 0;
+  return decl;
 }
 
-/* Similar to `lookup_name' but look only at current binding level.  */
+/* Similar to `lookup_name' but look only at the current binding level.  */
 
-tree
-lookup_name_current_level (name)
-     tree name;
+static tree
+lookup_name_current_level (tree name)
 {
-  tree t;
+  tree decl = IDENTIFIER_SYMBOL_VALUE (name);
 
-  if (current_binding_level == global_binding_level)
-    return IDENTIFIER_GLOBAL_VALUE (name);
-
-  if (IDENTIFIER_LOCAL_VALUE (name) == 0)
+  if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
     return 0;
 
-  for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
-    if (DECL_NAME (t) == name)
-      break;
+  if (current_binding_level == global_binding_level)
+    return decl;
+
+  /* Scan the current scope for a decl with name NAME.  */
+  if (chain_member (decl, current_binding_level->names))
+    return decl;
 
-  return t;
+  return 0;
 }
 \f
 /* Create the predefined scalar types of C,
@@ -2862,11 +2222,12 @@ lookup_name_current_level (name)
    Make definitions for built-in primitive functions.  */
 
 void
-c_init_decl_processing ()
+c_init_decl_processing (void)
 {
   tree endlink;
   tree ptr_ftype_void, ptr_ftype_ptr;
-
+  location_t save_loc = input_location;
+  
   /* Adds some ggc roots, and reserved words for c-parse.in.  */
   c_parse_init ();
 
@@ -2878,6 +2239,11 @@ c_init_decl_processing ()
   /* Make the binding_level structure for global names.  */
   pushlevel (0);
   global_binding_level = current_binding_level;
+  /* Declarations from c_common_nodes_and_builtins must not be associated
+     with this input file, lest we get differences between using and not
+     using preprocessed headers.  */
+  input_location.file = "<internal>";
+  input_location.line = 0;
 
   build_common_tree_nodes (flag_signed_char);
 
@@ -2905,6 +2271,8 @@ c_init_decl_processing ()
     = build_function_type (ptr_type_node,
                           tree_cons (NULL_TREE, ptr_type_node, endlink));
 
+  input_location = save_loc;
+
   pedantic_lvalues = pedantic;
 
   make_fname_decl = c_make_fname_decl;
@@ -2920,9 +2288,7 @@ c_init_decl_processing ()
    are string merging candidates, which is wrong for C99's __func__.  FIXME.  */
 
 static tree
-c_make_fname_decl (id, type_dep)
-     tree id;
-     int type_dep;
+c_make_fname_decl (tree id, int type_dep)
 {
   const char *name = fname_as_string (type_dep);
   tree decl, type, init;
@@ -2933,19 +2299,20 @@ c_make_fname_decl (id, type_dep)
           build_index_type (size_int (length)));
 
   decl = build_decl (VAR_DECL, id, type);
-  /* We don't push the decl, so have to set its context here.  */
-  DECL_CONTEXT (decl) = current_function_decl;
-  
+
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
-  
+
   init = build_string (length + 1, name);
   TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
 
   TREE_USED (decl) = 1;
-  
+
+  if (current_function_decl)
+    pushdecl_function_level (decl, DECL_NAME (decl));
+
   finish_decl (decl, init, NULL_TREE);
 
   return decl;
@@ -2957,15 +2324,13 @@ c_make_fname_decl (id, type_dep)
    See tree.h for its possible values.
 
    If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
-   the name to be called if we can't opencode the function.  */
+   the name to be called if we can't opencode the function.  If
+   ATTRS is nonzero, use that for the function's attribute list.  */
 
 tree
-builtin_function (name, type, function_code, class, library_name)
-     const char *name;
-     tree type;
-     int function_code;
-     enum built_in_class class;
-     const char *library_name;
+builtin_function (const char *name, tree type, int function_code,
+                 enum built_in_class class, const char *library_name,
+                 tree attrs)
 {
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
@@ -2977,17 +2342,16 @@ builtin_function (name, type, function_code, class, library_name)
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = function_code;
 
-  /* The return builtins leave the current function.  */
-  if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
-    TREE_THIS_VOLATILE (decl) = 1;
-
   /* Warn if a function in the namespace for users
      is used without an occasion to consider it declared.  */
   if (name[0] != '_' || name[1] != '_')
-    C_DECL_ANTICIPATED (decl) = 1;
+    C_DECL_INVISIBLE (decl) = 1;
 
   /* Possibly apply some default attributes to this built-in function.  */
-  decl_attributes (&decl, NULL_TREE, 0);
+  if (attrs)
+    decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
+  else
+    decl_attributes (&decl, NULL_TREE, 0);
 
   return decl;
 }
@@ -2996,8 +2360,7 @@ builtin_function (name, type, function_code, class, library_name)
    attributes.  */
 
 void
-c_insert_default_attributes (decl)
-     tree decl;
+c_insert_default_attributes (tree decl)
 {
   if (!TREE_PUBLIC (decl))
     return;
@@ -3013,16 +2376,15 @@ c_insert_default_attributes (decl)
    Otherwise, it is an error.  */
 
 void
-shadow_tag (declspecs)
-     tree declspecs;
+shadow_tag (tree declspecs)
 {
   shadow_tag_warned (declspecs, 0);
 }
 
 void
-shadow_tag_warned (declspecs, warned)
-     tree declspecs;
-     int warned;
+shadow_tag_warned (tree declspecs, int warned)
+
+
      /* 1 => we have done a pedwarn.  2 => we have done a warning, but
        no pedwarn.  */
 {
@@ -3045,7 +2407,7 @@ shadow_tag_warned (declspecs, warned)
        /* Used to test also that TYPE_SIZE (value) != 0.
           That caused warning for `struct foo;' at top level in the file.  */
        {
-         tree name = lookup_tag_reverse (value);
+         tree name = TYPE_NAME (value);
          tree t;
 
          found_tag++;
@@ -3061,7 +2423,7 @@ shadow_tag_warned (declspecs, warned)
            }
          else
            {
-             t = lookup_tag (code, name, current_binding_level, 1);
+             t = lookup_tag (code, name, 1);
 
              if (t == 0)
                {
@@ -3093,8 +2455,8 @@ shadow_tag_warned (declspecs, warned)
 /* Construct an array declarator.  EXPR is the expression inside [], or
    NULL_TREE.  QUALS are the type qualifiers inside the [] (to be applied
    to the pointer to which a parameter array is converted).  STATIC_P is
-   non-zero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
-   is non-zero is the array is [*], a VLA of unspecified length which is
+   nonzero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
+   is nonzero is the array is [*], a VLA of unspecified length which is
    nevertheless a complete type (not currently implemented by GCC),
    zero otherwise.  The declarator is constructed as an ARRAY_REF
    (to be decoded by grokdeclarator), whose operand 0 is what's on the
@@ -3103,11 +2465,7 @@ shadow_tag_warned (declspecs, warned)
    which has TREE_STATIC set if "static" is used.  */
 
 tree
-build_array_declarator (expr, quals, static_p, vla_unspec_p)
-     tree expr;
-     tree quals;
-     int static_p;
-     int vla_unspec_p;
+build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p)
 {
   tree decl;
   decl = build_nt (ARRAY_REF, NULL_TREE, expr);
@@ -3116,9 +2474,9 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p)
   if (pedantic && !flag_isoc99)
     {
       if (static_p || quals != NULL_TREE)
-       pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+       pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
       if (vla_unspec_p)
-       pedwarn ("ISO C89 does not support `[*]' array declarators");
+       pedwarn ("ISO C90 does not support `[*]' array declarators");
     }
   if (vla_unspec_p)
     warning ("GCC does not yet properly implement `[*]' array declarators");
@@ -3127,16 +2485,13 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p)
 
 /* Set the type of an array declarator.  DECL is the declarator, as
    constructed by build_array_declarator; TYPE is what appears on the left
-   of the [] and goes in operand 0.  ABSTRACT_P is non-zero if it is an
+   of the [] and goes in operand 0.  ABSTRACT_P is nonzero if it is an
    abstract declarator, zero otherwise; this is used to reject static and
    type qualifiers in abstract declarators, where they are not in the
    C99 grammar.  */
 
 tree
-set_array_declarator_type (decl, type, abstract_p)
-     tree decl;
-     tree type;
-     int abstract_p;
+set_array_declarator_type (tree decl, tree type, int abstract_p)
 {
   TREE_OPERAND (decl, 0) = type;
   if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
@@ -3147,8 +2502,7 @@ set_array_declarator_type (decl, type, abstract_p)
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (typename)
-     tree typename;
+groktypename (tree typename)
 {
   tree specs, attrs;
 
@@ -3168,8 +2522,7 @@ groktypename (typename)
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
 
 tree
-groktypename_in_parm_context (typename)
-     tree typename;
+groktypename_in_parm_context (tree typename)
 {
   if (TREE_CODE (typename) != TREE_LIST)
     return typename;
@@ -3194,14 +2547,11 @@ groktypename_in_parm_context (typename)
    grokfield and not through here.  */
 
 tree
-start_decl (declarator, declspecs, initialized, attributes)
-     tree declarator, declspecs;
-     int initialized;
-     tree attributes;
+start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
 {
   tree decl;
   tree tem;
-  
+
   /* An object declared as __attribute__((deprecated)) suppresses
      warnings of uses of other deprecated items.  */
   if (lookup_attribute ("deprecated", attributes))
@@ -3209,7 +2559,7 @@ start_decl (declarator, declspecs, initialized, attributes)
 
   decl = grokdeclarator (declarator, declspecs,
                         NORMAL, initialized);
-  
+
   deprecated_state = DEPRECATED_NORMAL;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
@@ -3223,15 +2573,9 @@ start_decl (declarator, declspecs, initialized, attributes)
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       /* typedef foo = bar  means give foo the same type as bar.
-          We haven't parsed bar yet, so `finish_decl' will fix that up.
-          Any other case of an initialization in a TYPE_DECL is an error.  */
-       if (pedantic || list_length (declspecs) > 1)
-         {
-           error ("typedef `%s' is initialized",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
-           initialized = 0;
-         }
+       error ("typedef `%s' is initialized (use __typeof__ instead)",
+              IDENTIFIER_POINTER (DECL_NAME (decl)));
+       initialized = 0;
        break;
 
       case FUNCTION_DECL:
@@ -3315,7 +2659,7 @@ start_decl (declarator, declspecs, initialized, attributes)
 
      Thread-local variables are never common, since there's no entrenched
      body of code to break, and it allows more efficient variable references
-     in the presense of dynamic linking.  */
+     in the presence of dynamic linking.  */
 
   if (TREE_CODE (decl) == VAR_DECL
       && !initialized
@@ -3367,9 +2711,7 @@ start_decl (declarator, declspecs, initialized, attributes)
    it must be determined now, from the initial value, or it is an error.  */
 
 void
-finish_decl (decl, init, asmspec_tree)
-     tree decl, init;
-     tree asmspec_tree;
+finish_decl (tree decl, tree init, tree asmspec_tree)
 {
   tree type = TREE_TYPE (decl);
   int was_incomplete = (DECL_SIZE (decl) == 0);
@@ -3384,22 +2726,13 @@ finish_decl (decl, init, asmspec_tree)
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
   if (init != 0 && DECL_INITIAL (decl) == 0)
     init = 0;
-  
+
   /* Don't crash if parm is initialized.  */
   if (TREE_CODE (decl) == PARM_DECL)
     init = 0;
 
   if (init)
-    {
-      if (TREE_CODE (decl) != TYPE_DECL)
-       store_init_value (decl, init);
-      else
-       {
-         /* typedef foo = bar; store the type of bar as the type of foo.  */
-         TREE_TYPE (decl) = TREE_TYPE (init);
-         DECL_INITIAL (decl) = init = 0;
-       }
-    }
+    store_init_value (decl, init);
 
   /* Deduce size of array from initialization, if not already known */
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -3485,14 +2818,36 @@ finish_decl (decl, init, asmspec_tree)
        TREE_USED (decl) = 1;
     }
 
-  /* If this is a function and an assembler name is specified, it isn't
-     builtin any more.  Also reset DECL_RTL so we can give it its new
-     name.  */
+  /* If this is a function and an assembler name is specified, reset DECL_RTL
+     so we can give it its new name.  Also, update built_in_decls if it
+     was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
-      DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
+      /* ASMSPEC is given, and not the name of a register.  Mark the
+      name with a star so assemble_name won't munge it.  */
+      char *starred = alloca (strlen (asmspec) + 2);
+      starred[0] = '*';
+      strcpy (starred + 1, asmspec);
+
+      if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+       {
+         tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
+         SET_DECL_RTL (builtin, NULL_RTX);
+         SET_DECL_ASSEMBLER_NAME (builtin, get_identifier (starred));
+#ifdef TARGET_MEM_FUNCTIONS
+         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
+           init_block_move_fn (starred);
+         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
+           init_block_clear_fn (starred);
+#else
+         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY)
+           init_block_move_fn (starred);
+         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO)
+           init_block_clear_fn (starred);
+#endif
+       }
       SET_DECL_RTL (decl, NULL_RTX);
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
+      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (starred));
     }
 
   /* Output the assembler code and/or RTL code for variables and functions,
@@ -3501,8 +2856,9 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
     {
-      /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-      maybe_objc_check_decl (decl);
+      /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+      if (c_dialect_objc ())
+       objc_check_decl (decl);
 
       if (!DECL_CONTEXT (decl))
        {
@@ -3533,7 +2889,7 @@ finish_decl (decl, init, asmspec_tree)
                 ordinary, non-register local variable.  Historically,
                 GCC has accepted -- but ignored -- the ASMSPEC in
                 this case.  */
-             if (TREE_CODE (decl) == VAR_DECL 
+             if (TREE_CODE (decl) == VAR_DECL
                  && !DECL_REGISTER (decl)
                  && !TREE_STATIC (decl))
                warning_with_decl (decl,
@@ -3564,8 +2920,9 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == TYPE_DECL)
     {
-      /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-      maybe_objc_check_decl (decl);
+      /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+      if (c_dialect_objc ())
+       objc_check_decl (decl);
       rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
     }
 
@@ -3574,6 +2931,41 @@ finish_decl (decl, init, asmspec_tree)
      computing them in the following function definition.  */
   if (current_binding_level == global_binding_level)
     get_pending_sizes ();
+
+  /* Install a cleanup (aka destructor) if one was given.  */
+  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+    {
+      tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+      if (attr)
+       {
+         static bool eh_initialized_p;
+
+         tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
+         tree cleanup_decl = lookup_name (cleanup_id);
+         tree cleanup;
+
+         /* Build "cleanup(&decl)" for the destructor.  */
+         cleanup = build_unary_op (ADDR_EXPR, decl, 0);
+         cleanup = build_tree_list (NULL_TREE, cleanup);
+         cleanup = build_function_call (cleanup_decl, cleanup);
+
+         /* Don't warn about decl unused; the cleanup uses it.  */
+         TREE_USED (decl) = 1;
+
+         /* Initialize EH, if we've been told to do so.  */
+         if (flag_exceptions && !eh_initialized_p)
+           {
+             eh_initialized_p = true;
+             eh_personality_libfunc
+               = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+                                   ? "__gcc_personality_sj0"
+                                   : "__gcc_personality_v0");
+             using_eh_for_cleanups ();
+           }
+
+         add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+       }
+    }
 }
 
 /* Given a parsed parameter declaration,
@@ -3582,8 +2974,7 @@ finish_decl (decl, init, asmspec_tree)
    record the given order of parms in `parm_order'.  */
 
 void
-push_parm_decl (parm)
-     tree parm;
+push_parm_decl (tree parm)
 {
   tree decl;
   int old_immediate_size_expand = immediate_size_expand;
@@ -3621,20 +3012,20 @@ push_parm_decl (parm)
    and also at semicolon terminating forward decls.  */
 
 void
-clear_parm_order ()
+clear_parm_order (void)
 {
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+static GTY(()) int compound_literal_number;
+
 /* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
    literal, which may be an incomplete array type completed by the
    initializer; INIT is a CONSTRUCTOR that initializes the compound
    literal.  */
 
 tree
-build_compound_literal (type, init)
-     tree type;
-     tree init;
+build_compound_literal (tree type, tree init)
 {
   /* We do not use start_decl here because we have a type, not a declarator;
      and do not use finish_decl because the decl should be stored inside
@@ -3648,6 +3039,7 @@ build_compound_literal (type, init)
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
+  TREE_READONLY (decl) = TREE_READONLY (type);
   store_init_value (decl, init);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
@@ -3670,12 +3062,18 @@ build_compound_literal (type, init)
   if (TREE_STATIC (decl))
     {
       /* This decl needs a name for the assembler output.  We also need
-        a unique suffix to be added to the name, for which DECL_CONTEXT
-        must be set.  */
-      DECL_NAME (decl) = get_identifier ("__compound_literal");
-      DECL_CONTEXT (decl) = complit;
+        a unique suffix to be added to the name.  */
+      char *name;
+
+      ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+                              compound_literal_number);
+      compound_literal_number++;
+      DECL_NAME (decl) = get_identifier (name);
+      DECL_DEFER_OUTPUT (decl) = 1;
+      DECL_COMDAT (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      pushdecl (decl);
       rest_of_decl_compilation (decl, NULL, 1, 0);
-      DECL_CONTEXT (decl) = NULL_TREE;
     }
 
   return complit;
@@ -3686,10 +3084,7 @@ build_compound_literal (type, init)
    2 if there was no information (in which case assume 1 if DO_DEFAULT).  */
 
 int
-complete_array_type (type, initial_value, do_default)
-     tree type;
-     tree initial_value;
-     int do_default;
+complete_array_type (tree type, tree initial_value, int do_default)
 {
   tree maxindex = NULL_TREE;
   int value = 0;
@@ -3751,6 +3146,39 @@ complete_array_type (type, initial_value, do_default)
   return value;
 }
 \f
+/* Determine whether TYPE is a structure with a flexible array member,
+   or a union containing such a structure (possibly recursively).  */
+
+static bool
+flexible_array_type_p (tree type)
+{
+  tree x;
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+      x = TYPE_FIELDS (type);
+      if (x == NULL_TREE)
+       return false;
+      while (TREE_CHAIN (x) != NULL_TREE)
+       x = TREE_CHAIN (x);
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+         && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+       return true;
+      return false;
+    case UNION_TYPE:
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
+       {
+         if (flexible_array_type_p (TREE_TYPE (x)))
+           return true;
+       }
+      return false;
+    default:
+    return false;
+  }
+}
+\f
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -3781,11 +3209,8 @@ complete_array_type (type, initial_value, do_default)
    and `extern' are interpreted.  */
 
 static tree
-grokdeclarator (declarator, declspecs, decl_context, initialized)
-     tree declspecs;
-     tree declarator;
-     enum decl_context decl_context;
-     int initialized;
+grokdeclarator (tree declarator, tree declspecs,
+               enum decl_context decl_context, int initialized)
 {
   int specbits = 0;
   tree spec;
@@ -3910,12 +3335,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                    {
                      if (pedantic && !flag_isoc99 && ! in_system_header
                          && warn_long_long)
-                       pedwarn ("ISO C89 does not support `long long'");
+                       pedwarn ("ISO C90 does not support `long long'");
                      longlong = 1;
                    }
                }
              else if (specbits & (1 << (int) i))
-               pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+               {
+                 if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
+                   {
+                     if (!flag_isoc99)
+                       pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+                   }
+                 else
+                   error ("duplicate `%s'", IDENTIFIER_POINTER (id));
+               }
 
              /* Diagnose "__thread extern".  Recall that this list
                 is in the reverse order seen in the text.  */
@@ -4048,12 +3481,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else
        {
          ok = 1;
-         if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
+         if (!explicit_int && !defaulted_int && !explicit_char)
            {
-             pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
-                      name);
-             if (flag_pedantic_errors)
-               ok = 0;
+             error ("long, short, signed or unsigned used invalidly for `%s'",
+                    name);
+             ok = 0;
            }
        }
 
@@ -4111,7 +3543,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   if (specbits & 1 << (int) RID_COMPLEX)
     {
       if (pedantic && !flag_isoc99)
-       pedwarn ("ISO C89 does not support complex types");
+       pedwarn ("ISO C90 does not support complex types");
       /* If we just have "complex", it is equivalent to
         "complex double", but if any modifiers at all are specified it is
         the complex form of TYPE.  E.g, "complex short" is
@@ -4347,6 +3779,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              type = error_mark_node;
            }
 
+         if (pedantic && flexible_array_type_p (type))
+           pedwarn ("invalid use of structure with flexible array member");
+
          if (size == error_mark_node)
            type = error_mark_node;
 
@@ -4389,10 +3824,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                  if (!flag_isoc99 && pedantic)
                    {
                      if (TREE_CONSTANT (size))
-                       pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+                       pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
                                 name);
                      else
-                       pedwarn ("ISO C89 forbids variable-size array `%s'",
+                       pedwarn ("ISO C90 forbids variable-size array `%s'",
                                 name);
                    }
                }
@@ -4428,14 +3863,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                    }
 
                  if (size_varies)
-                   itype = variable_size (itype);
+                   {
+                     /* We must be able to distinguish the
+                        SAVE_EXPR_CONTEXT for the variably-sized type
+                        so that we can set it correctly in
+                        set_save_expr_context.  The convention is
+                        that all SAVE_EXPRs that need to be reset
+                        have NULL_TREE for their SAVE_EXPR_CONTEXT.  */
+                     tree cfd = current_function_decl;
+                     if (decl_context == PARM)
+                       current_function_decl = NULL_TREE;
+                     itype = variable_size (itype);
+                     if (decl_context == PARM)
+                       current_function_decl = cfd;
+                   }
                  itype = build_index_type (itype);
                }
            }
          else if (decl_context == FIELD)
            {
              if (pedantic && !flag_isoc99 && !in_system_header)
-               pedwarn ("ISO C89 does not support flexible array members");
+               pedwarn ("ISO C90 does not support flexible array members");
 
              /* ISO C99 Flexible array members are effectively identical
                 to GCC's zero-length array extension.  */
@@ -4522,7 +3970,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            {
              /* Type qualifiers on a function return type are normally
                 permitted by the standard but have no effect, so give a
-                warning at -W.  Qualifiers on a void return type have
+                warning at -Wextra.  Qualifiers on a void return type have
                 meaning as a GNU extension, and are banned on function
                 definitions in ISO C.  FIXME: strictly we shouldn't
                 pedwarn for qualified void return types except on function
@@ -4779,7 +4227,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          }
        else if (type_quals)
          type = c_build_qualified_type (type, type_quals);
-         
+
        type_as_written = type;
 
        decl = build_decl (PARM_DECL, declarator, type);
@@ -4907,6 +4355,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
           needed, and let dwarf2 know that the function is inlinable.  */
        else if (flag_inline_trees == 2 && initialized)
          {
+           if (!DECL_INLINE (decl))
+               DID_INLINE_FUNC (decl) = 1;
            DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 0;
          }
@@ -4931,7 +4381,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          }
        else if (type_quals)
          type = c_build_qualified_type (type, type_quals);
-         
+
+       /* It is invalid to create an `extern' declaration for a
+          variable if there is a global declaration that is
+          `static'.  */
+       if (extern_ref && current_binding_level != global_binding_level)
+         {
+           tree global_decl;
+
+           global_decl = identifier_global_value (declarator);
+           if (global_decl
+               && TREE_CODE (global_decl) == VAR_DECL
+               && !TREE_PUBLIC (global_decl))
+             error ("variable previously declared `static' redeclared "
+                    "`extern'");
+         }
+
        decl = build_decl (VAR_DECL, declarator, type);
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -5009,9 +4474,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
    when FUNCDEF_FLAG is zero.  */
 
 static tree
-grokparms (parms_info, funcdef_flag)
-     tree parms_info;
-     int funcdef_flag;
+grokparms (tree parms_info, int funcdef_flag)
 {
   tree first_parm = TREE_CHAIN (parms_info);
 
@@ -5106,8 +4569,7 @@ grokparms (parms_info, funcdef_flag)
    Zero means the parmlist ended with an ellipsis so don't append `void'.  */
 
 tree
-get_parm_info (void_at_end)
-     int void_at_end;
+get_parm_info (int void_at_end)
 {
   tree decl, t;
   tree types = 0;
@@ -5207,7 +4669,7 @@ get_parm_info (void_at_end)
    defined within.  Do so because these types cannot ever become complete.  */
 
 void
-parmlist_tags_warning ()
+parmlist_tags_warning (void)
 {
   tree elt;
   static int already;
@@ -5253,14 +4715,12 @@ parmlist_tags_warning ()
    Define the tag as a forward-reference if it is not defined.  */
 
 tree
-xref_tag (code, name)
-     enum tree_code code;
-     tree name;
+xref_tag (enum tree_code code, tree name)
 {
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
-  tree ref = lookup_tag (code, name, current_binding_level, 0);
+  tree ref = lookup_tag (code, name, 0);
   /* If this is the right type of tag, return what we found.
      (This reference will be shadowed by shadow_tag later if appropriate.)
      If this is the wrong type of tag, do not return it.  If it was the
@@ -5304,9 +4764,7 @@ xref_tag (code, name)
    CODE says which kind of tag NAME ought to be.  */
 
 tree
-start_struct (code, name)
-     enum tree_code code;
-     tree name;
+start_struct (enum tree_code code, tree name)
 {
   /* If there is already a tag defined at this binding level
      (as a forward reference), just return it.  */
@@ -5314,28 +4772,25 @@ start_struct (code, name)
   tree ref = 0;
 
   if (name != 0)
-    ref = lookup_tag (code, name, current_binding_level, 1);
+    ref = lookup_tag (code, name, 1);
   if (ref && TREE_CODE (ref) == code)
     {
-      C_TYPE_BEING_DEFINED (ref) = 1;
-      TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
         {
          if (code == UNION_TYPE)
-           error ("redefinition of `union %s'",
-                  IDENTIFIER_POINTER (name));
+           error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
           else
-           error ("redefinition of `struct %s'",
-                  IDENTIFIER_POINTER (name));
-       }  
-
-      return ref;
+           error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
+       }
     }
+  else
+    {
+      /* Otherwise create a forward-reference just so the tag is in scope.  */
 
-  /* Otherwise create a forward-reference just so the tag is in scope.  */
+      ref = make_node (code);
+      pushtag (name, ref);
+    }
 
-  ref = make_node (code);
-  pushtag (name, ref);
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
   return ref;
@@ -5350,21 +4805,50 @@ start_struct (code, name)
    are ultimately passed to `build_struct' to make the RECORD_TYPE node.  */
 
 tree
-grokfield (filename, line, declarator, declspecs, width)
-     const char *filename ATTRIBUTE_UNUSED;
-     int line ATTRIBUTE_UNUSED;
-     tree declarator, declspecs, width;
+grokfield (tree declarator, tree declspecs, tree width)
 {
   tree value;
 
   if (declarator == NULL_TREE && width == NULL_TREE)
     {
-      /* This is an unnamed decl.  We only support unnamed
-        structs/unions, so check for other things and refuse them.  */
-      if (TREE_CODE (TREE_VALUE (declspecs)) != RECORD_TYPE
-         && TREE_CODE (TREE_VALUE (declspecs)) != UNION_TYPE)
+      /* This is an unnamed decl.
+
+        If we have something of the form "union { list } ;" then this
+        is the anonymous union extension.  Similarly for struct.
+
+        If this is something of the form "struct foo;", then
+          If MS extensions are enabled, this is handled as an
+            anonymous struct.
+          Otherwise this is a forward declaration of a structure tag.
+
+        If this is something of the form "foo;" and foo is a TYPE_DECL, then
+          If MS extensions are enabled and foo names a structure, then
+            again this is an anonymous struct.
+          Otherwise this is an error.
+
+        Oh what a horrid tangled web we weave.  I wonder if MS consciously
+        took this from Plan 9 or if it was an accident of implementation
+        that took root before someone noticed the bug...  */
+
+      tree type = TREE_VALUE (declspecs);
+
+      if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
+       type = TREE_TYPE (type);
+      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
+       {
+         if (flag_ms_extensions)
+           ; /* ok */
+         else if (flag_iso)
+           goto warn_unnamed_field;
+         else if (TYPE_NAME (type) == NULL)
+           ; /* ok */
+         else
+           goto warn_unnamed_field;
+       }
+      else
        {
-         error ("unnamed fields of type other than struct or union are not allowed");
+       warn_unnamed_field:
+         warning ("declaration does not declare anything");
          return NULL_TREE;
        }
     }
@@ -5374,19 +4858,74 @@ grokfield (filename, line, declarator, declspecs, width)
   finish_decl (value, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
-  maybe_objc_check_decl (value);
+  if (c_dialect_objc ())
+    objc_check_decl (value);
   return value;
 }
 \f
+/* Generate an error for any duplicate field names in FIELDLIST.  Munge
+   the list such that this does not present a problem later.  */
+
+static void
+detect_field_duplicates (tree fieldlist)
+{
+  tree x, y;
+  int timeout = 10;
+
+  /* First, see if there are more than "a few" fields.
+     This is trivially true if there are zero or one fields.  */
+  if (!fieldlist)
+    return;
+  x = TREE_CHAIN (fieldlist);
+  if (!x)
+    return;
+  do {
+    timeout--;
+    x = TREE_CHAIN (x);
+  } while (timeout > 0 && x);
+
+  /* If there were "few" fields, avoid the overhead of allocating
+     a hash table.  Instead just do the nested traversal thing.  */
+  if (timeout > 0)
+    {
+      for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x))
+       if (DECL_NAME (x))
+         {
+           for (y = fieldlist; y != x; y = TREE_CHAIN (y))
+             if (DECL_NAME (y) == DECL_NAME (x))
+               {
+                 error_with_decl (x, "duplicate member `%s'");
+                 DECL_NAME (x) = NULL_TREE;
+               }
+         }
+    }
+  else
+    {
+      htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
+      void **slot;
+
+      for (x = fieldlist; x ; x = TREE_CHAIN (x))
+       if ((y = DECL_NAME (x)) != 0)
+         {
+           slot = htab_find_slot (htab, y, INSERT);
+           if (*slot)
+             {
+               error_with_decl (x, "duplicate member `%s'");
+               DECL_NAME (x) = NULL_TREE;
+             }
+           *slot = y;
+         }
+
+      htab_delete (htab);
+    }
+}
+
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
    ATTRIBUTES are attributes to be applied to the structure.  */
 
 tree
-finish_struct (t, fieldlist, attributes)
-     tree t;
-     tree fieldlist;
-     tree attributes;
+finish_struct (tree t, tree fieldlist, tree attributes)
 {
   tree x;
   int toplevel = global_binding_level == current_binding_level;
@@ -5530,38 +5069,9 @@ finish_struct (t, fieldlist, attributes)
              DECL_SIZE (x) = bitsize_int (width);
              DECL_BIT_FIELD (x) = 1;
              SET_DECL_C_BIT_FIELD (x);
-
-             if (width == 0
-                 && ! (* targetm.ms_bitfield_layout_p) (t))
-               {
-                 /* field size 0 => force desired amount of alignment.  */
-#ifdef EMPTY_FIELD_BOUNDARY
-                 DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
-#endif
-#ifdef PCC_BITFIELD_TYPE_MATTERS
-                 if (PCC_BITFIELD_TYPE_MATTERS)
-                   {
-                     DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
-                                           TYPE_ALIGN (TREE_TYPE (x)));
-                     DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
-                   }
-#endif
-               }
            }
        }
 
-      else if (TREE_TYPE (x) != error_mark_node)
-       {
-         unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
-                                   : TYPE_ALIGN (TREE_TYPE (x)));
-
-         /* Non-bit-fields are aligned for their type, except packed
-            fields which require only BITS_PER_UNIT alignment.  */
-         DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
-         if (! DECL_PACKED (x))
-           DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
-       }
-
       DECL_INITIAL (x) = 0;
 
       /* Detect flexible array member in an invalid context.  */
@@ -5577,35 +5087,16 @@ finish_struct (t, fieldlist, attributes)
          else if (! saw_named_field)
            error_with_decl (x, "flexible array member in otherwise empty struct");
        }
+
+      if (pedantic && TREE_CODE (t) == RECORD_TYPE
+         && flexible_array_type_p (TREE_TYPE (x)))
+       pedwarn_with_decl (x, "invalid use of structure with flexible array member");
+
       if (DECL_NAME (x))
        saw_named_field = 1;
     }
 
-  /* Delete all duplicate fields from the fieldlist */
-  for (x = fieldlist; x && TREE_CHAIN (x);)
-    /* Anonymous fields aren't duplicates.  */
-    if (DECL_NAME (TREE_CHAIN (x)) == 0)
-      x = TREE_CHAIN (x);
-    else
-      {
-       tree y = fieldlist;
-
-       while (1)
-         {
-           if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
-             break;
-           if (y == x)
-             break;
-           y = TREE_CHAIN (y);
-         }
-       if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
-         {
-           error_with_decl (TREE_CHAIN (x), "duplicate member `%s'");
-           TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
-         }
-       else
-         x = TREE_CHAIN (x);
-      }
+  detect_field_duplicates (fieldlist);
 
   /* Now we have the nearly final fieldlist.  Record it,
      then lay out the structure or union (including the fields).  */
@@ -5662,8 +5153,9 @@ finish_struct (t, fieldlist, attributes)
              && TREE_CODE (decl) != TYPE_DECL)
            {
              layout_decl (decl, 0);
-             /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-             maybe_objc_check_decl (decl);
+             /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+             if (c_dialect_objc ())
+               objc_check_decl (decl);
              rest_of_decl_compilation (decl, NULL, toplevel, 0);
              if (! toplevel)
                expand_decl (decl);
@@ -5685,7 +5177,8 @@ finish_struct (t, fieldlist, attributes)
                  if (TREE_CODE (decl) != TYPE_DECL)
                    {
                      layout_decl (decl, 0);
-                     maybe_objc_check_decl (decl);
+                     if (c_dialect_objc ())
+                       objc_check_decl (decl);
                      rest_of_decl_compilation (decl, NULL, toplevel, 0);
                      if (! toplevel)
                        expand_decl (decl);
@@ -5709,8 +5202,7 @@ finish_struct (t, fieldlist, attributes)
 /* Lay out the type T, and its element type, and so on.  */
 
 static void
-layout_array_type (t)
-     tree t;
+layout_array_type (tree t)
 {
   if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
     layout_array_type (TREE_TYPE (t));
@@ -5724,8 +5216,7 @@ layout_array_type (t)
    may be used to declare the individual values as they are read.  */
 
 tree
-start_enum (name)
-     tree name;
+start_enum (tree name)
 {
   tree enumtype = 0;
 
@@ -5734,7 +5225,7 @@ start_enum (name)
      forward reference.  */
 
   if (name != 0)
-    enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
+    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1);
 
   if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
     {
@@ -5770,10 +5261,7 @@ start_enum (name)
    Returns ENUMTYPE.  */
 
 tree
-finish_enum (enumtype, values, attributes)
-     tree enumtype;
-     tree values;
-     tree attributes;
+finish_enum (tree enumtype, tree values, tree attributes)
 {
   tree pair, tem;
   tree minnode = 0, maxnode = 0, enum_value_type;
@@ -5849,11 +5337,6 @@ finish_enum (enumtype, values, attributes)
          tree enu = TREE_PURPOSE (pair);
 
          TREE_TYPE (enu) = enumtype;
-         DECL_SIZE (enu) = TYPE_SIZE (enumtype);
-         DECL_SIZE_UNIT (enu) = TYPE_SIZE_UNIT (enumtype);
-         DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
-         DECL_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype);
-         DECL_MODE (enu) = TYPE_MODE (enumtype);
 
          /* The ISO C Standard mandates enumerators to have type int,
             even though the underlying type of an enum type is
@@ -5903,8 +5386,7 @@ finish_enum (enumtype, values, attributes)
    Assignment of sequential values by default is handled here.  */
 
 tree
-build_enumerator (name, value)
-     tree name, value;
+build_enumerator (tree name, tree value)
 {
   tree decl, type;
 
@@ -5979,8 +5461,7 @@ build_enumerator (name, value)
    yyparse to report a parse error.  */
 
 int
-start_function (declspecs, declarator, attributes)
-     tree declarator, declspecs, attributes;
+start_function (tree declspecs, tree declarator, tree attributes)
 {
   tree decl1, old_decl;
   tree restype;
@@ -5991,7 +5472,6 @@ start_function (declspecs, declarator, attributes)
   current_function_returns_abnormally = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
-  c_function_varargs = 0;
   named_labels = 0;
   shadowed_labels = 0;
 
@@ -6054,31 +5534,19 @@ start_function (declspecs, declarator, attributes)
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
     {
       TREE_TYPE (decl1) = TREE_TYPE (old_decl);
-      current_function_prototype_file = DECL_SOURCE_FILE (old_decl);
-      current_function_prototype_line = DECL_SOURCE_LINE (old_decl);
+      current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
     }
 
-  /* If there is no explicit declaration, look for any out-of-scope implicit
-     declarations.  */
-  if (old_decl == 0)
-    old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1));
-
   /* Optionally warn of old-fashioned def with no previous prototype.  */
   if (warn_strict_prototypes
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
-      && !(old_decl != 0
-          && (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
-              || (DECL_BUILT_IN (old_decl)
-                  && ! C_DECL_ANTICIPATED (old_decl)))))
+      && C_DECL_ISNT_PROTOTYPE (old_decl))
     warning ("function declaration isn't a prototype");
   /* Optionally warn of any global def with no previous prototype.  */
   else if (warn_missing_prototypes
           && TREE_PUBLIC (decl1)
-          && !(old_decl != 0
-               && (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
-                   || (DECL_BUILT_IN (old_decl)
-                       && ! C_DECL_ANTICIPATED (old_decl))))
-          && ! MAIN_NAME_P (DECL_NAME (decl1)))
+          && ! MAIN_NAME_P (DECL_NAME (decl1))
+          && C_DECL_ISNT_PROTOTYPE (old_decl))
     warning_with_decl (decl1, "no previous prototype for `%s'");
   /* Optionally warn of any def with no previous prototype
      if the function has already been used.  */
@@ -6097,7 +5565,7 @@ start_function (declspecs, declarator, attributes)
      if the function has already been used.  */
   else if (warn_missing_declarations
           && old_decl != 0 && TREE_USED (old_decl)
-          && old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)))
+          && C_DECL_IMPLICIT (old_decl))
     warning_with_decl (decl1,
                       "`%s' was used with no declaration before its definition");
 
@@ -6180,7 +5648,6 @@ start_function (declspecs, declarator, attributes)
 
   pushlevel (0);
   declare_parm_level (1);
-  current_binding_level->subblocks_tag_transparent = 1;
 
   make_decl_rtl (current_function_decl, NULL);
 
@@ -6207,18 +5674,8 @@ start_function (declspecs, declarator, attributes)
   immediate_size_expand = old_immediate_size_expand;
 
   start_fname_decls ();
-  
-  return 1;
-}
 
-/* Record that this function is going to be a varargs function.
-   This is called before store_parm_decls, which is too early
-   to call mark_varargs directly.  */
-
-void
-c_mark_varargs ()
-{
-  c_function_varargs = 1;
+  return 1;
 }
 \f
 /* Store the parameter declarations into the current function declaration.
@@ -6229,7 +5686,7 @@ c_mark_varargs ()
    to specify at least the number of arguments.  */
 
 void
-store_parm_decls ()
+store_parm_decls (void)
 {
   tree fndecl = current_function_decl;
   tree parm;
@@ -6255,10 +5712,10 @@ store_parm_decls ()
   /* Nonzero if this definition is written with a prototype.  */
   int prototype = 0;
 
-  int saved_warn_shadow = warn_shadow;
+  bool saved_warn_shadow = warn_shadow;
 
   /* Don't re-emit shadow warnings.  */
-  warn_shadow = 0;
+  warn_shadow = false;
 
   if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
     {
@@ -6283,10 +5740,10 @@ store_parm_decls ()
          for (decl = current_binding_level->names;
               decl; decl = TREE_CHAIN (decl))
            if (DECL_NAME (decl))
-             IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0;
+             IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = 0;
          for (link = current_binding_level->shadowed;
               link; link = TREE_CHAIN (link))
-           IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+           IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
          current_binding_level->names = 0;
          current_binding_level->shadowed = 0;
        }
@@ -6416,8 +5873,7 @@ store_parm_decls ()
              found = build_decl (PARM_DECL, TREE_VALUE (parm),
                                  integer_type_node);
              DECL_ARG_TYPE (found) = TREE_TYPE (found);
-             DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
-             DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
+             DECL_SOURCE_LOCATION (found) = DECL_SOURCE_LOCATION (fndecl);
              if (flag_isoc99)
                pedwarn_with_decl (found, "type of `%s' defaults to `int'");
              else if (extra_warnings)
@@ -6506,9 +5962,8 @@ store_parm_decls ()
                  || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
                {
                  error ("number of arguments doesn't match prototype");
-                 error_with_file_and_line (current_function_prototype_file,
-                                           current_function_prototype_line,
-                                           "prototype declaration");
+                 error ("%Hprototype declaration",
+                         &current_function_prototype_locus);
                  break;
                }
              /* Type for passing arg must be consistent with that
@@ -6537,19 +5992,16 @@ store_parm_decls ()
                        {
                          pedwarn ("promoted argument `%s' doesn't match prototype",
                                   IDENTIFIER_POINTER (DECL_NAME (parm)));
-                         warning_with_file_and_line
-                           (current_function_prototype_file,
-                            current_function_prototype_line,
-                            "prototype declaration");
+                         warning ("%Hprototype declaration",
+                                   &current_function_prototype_locus);
                        }
                    }
                  else
                    {
                      error ("argument `%s' doesn't match prototype",
                             IDENTIFIER_POINTER (DECL_NAME (parm)));
-                     error_with_file_and_line (current_function_prototype_file,
-                                               current_function_prototype_line,
-                                               "prototype declaration");
+                     error ("%Hprototype declaration",
+                             &current_function_prototype_locus);
                    }
                }
            }
@@ -6616,7 +6068,7 @@ store_parm_decls ()
   gen_aux_info_record (fndecl, 1, 0, prototype);
 
   /* Initialize the RTL code for the function.  */
-  init_function_start (fndecl, input_filename, lineno);
+  init_function_start (fndecl);
 
   /* Begin the statement tree for this function.  */
   begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
@@ -6628,7 +6080,7 @@ store_parm_decls ()
     {
       tree t;
 
-      DECL_LANG_SPECIFIC (fndecl)->pending_sizes 
+      DECL_LANG_SPECIFIC (fndecl)->pending_sizes
        = nreverse (get_pending_sizes ());
       for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
           t;
@@ -6659,19 +6111,31 @@ store_parm_decls ()
    CAN_DEFER_P is nonzero if the function may be deferred.  */
 
 void
-finish_function (nested, can_defer_p)
-     int nested;
-     int can_defer_p;
+finish_function (int nested, int can_defer_p)
 {
   tree fndecl = current_function_decl;
 
+  /* When a function declaration is totally empty, e.g.
+        void foo(void) { }
+     (the argument list is irrelevant) the compstmt rule will not
+     bother calling pushlevel/poplevel, which means we get here with
+     the binding_level stack out of sync.  Detect this situation by
+     noticing that the current_binding_level is still as
+     store_parm_decls left it, and do a dummy push/pop to get back to
+     consistency.  Note that the call to pushlevel does not actually
+     push another binding level - see there for details.  */
+  if (current_binding_level->parm_flag && keep_next_if_subblocks)
+    {
+      pushlevel (0);
+      poplevel (1, 0, 1);
+    }
+
 #if 0
   /* This caused &foo to be of type ptr-to-const-function which then
      got a warning when stored in a ptr-to-function variable.  */
   TREE_READONLY (fndecl) = 1;
 #endif
 
-  poplevel (1, 0, 1);
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
   /* Must mark the RESULT_DECL as being in this function.  */
@@ -6699,7 +6163,7 @@ finish_function (nested, can_defer_p)
 #endif
        }
     }
-  
+
   finish_fname_decls ();
 
   /* Tie off the statement tree for this function.  */
@@ -6727,10 +6191,68 @@ finish_function (nested, can_defer_p)
   free_after_compilation (cfun);
   cfun = NULL;
 
+  if (flag_unit_at_a_time && can_defer_p)
+    {
+      cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+      current_function_decl = NULL;
+      return;
+    }
+
   if (! nested)
     {
-      /* Generate RTL for the body of this function.  */
-      c_expand_body (fndecl, nested, can_defer_p);
+      /* Function is parsed.
+        Generate RTL for the body of this function or defer
+        it for later expansion.  */
+      int uninlinable = 1;
+
+      /* There's no reason to do any of the work here if we're only doing
+        semantic analysis; this code just generates RTL.  */
+      if (flag_syntax_only)
+       {
+         current_function_decl = NULL;
+         DECL_SAVED_TREE (fndecl) = NULL_TREE;
+         return;
+       }
+
+      if (flag_inline_trees)
+       {
+         /* First, cache whether the current function is inlinable.  Some
+            predicates depend on cfun and current_function_decl to
+            function completely.  */
+         timevar_push (TV_INTEGRATION);
+         uninlinable = ! tree_inlinable_function_p (fndecl, 0);
+
+         if (can_defer_p
+             /* We defer functions marked inline *even if* the function
+                itself is not inlinable.  This is because we don't yet
+                know if the function will actually be used; we may be
+                able to avoid emitting it entirely.  */
+             && (! uninlinable || DECL_DECLARED_INLINE_P (fndecl))
+             /* Save function tree for inlining.  Should return 0 if the
+                language does not support function deferring or the
+                function could not be deferred.  */
+             && defer_fn (fndecl))
+           {
+             /* Let the back-end know that this function exists.  */
+             (*debug_hooks->deferred_inline_function) (fndecl);
+             timevar_pop (TV_INTEGRATION);
+             current_function_decl = NULL;
+             return;
+           }
+
+         /* Then, inline any functions called in it.  */
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+
+      c_expand_body (fndecl);
+
+      /* Keep the function body if it's needed for inlining or dumping.  */
+      if (uninlinable && !dump_enabled_p (TDI_all))
+       {
+         /* Allow the body of the function to be garbage collected.  */
+         DECL_SAVED_TREE (fndecl) = NULL_TREE;
+       }
 
       /* Let the error reporting routines know that we're outside a
         function.  For a nested function, this value is used in
@@ -6742,60 +6264,50 @@ finish_function (nested, can_defer_p)
 /* Generate the RTL for a deferred function FNDECL.  */
 
 void
-c_expand_deferred_function (fndecl)
-     tree fndecl;
+c_expand_deferred_function (tree fndecl)
 {
   /* DECL_INLINE or DECL_RESULT might got cleared after the inline
      function was deferred, e.g. in duplicate_decls.  */
   if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
     {
-      c_expand_body (fndecl, 0, 0);
+      if (flag_inline_trees)
+       {
+         timevar_push (TV_INTEGRATION);
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+      c_expand_body (fndecl);
       current_function_decl = NULL;
     }
 }
 
-/* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
+/* Called to move the SAVE_EXPRs for parameter declarations in a
+   nested function into the nested function.  DATA is really the
+   nested FUNCTION_DECL.  */
+
+static tree
+set_save_expr_context (tree *tp,
+                      int *walk_subtrees,
+                      void *data)
+{
+  if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
+    SAVE_EXPR_CONTEXT (*tp) = (tree) data;
+  /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
+     circularity.  */
+  else if (DECL_P (*tp))
+    *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
+
+/* Generate the RTL for the body of FNDECL.  If NESTED_P is nonzero,
    then we are already in the process of generating RTL for another
    function.  If can_defer_p is zero, we won't attempt to defer the
    generation of RTL.  */
 
 static void
-c_expand_body (fndecl, nested_p, can_defer_p)
-     tree fndecl;
-     int nested_p, can_defer_p;
+c_expand_body_1 (tree fndecl, int nested_p)
 {
-  int uninlinable = 1;
-
-  /* There's no reason to do any of the work here if we're only doing
-     semantic analysis; this code just generates RTL.  */
-  if (flag_syntax_only)
-    return;
-
-  if (flag_inline_trees)
-    {
-      /* First, cache whether the current function is inlinable.  Some
-         predicates depend on cfun and current_function_decl to
-         function completely.  */
-      timevar_push (TV_INTEGRATION);
-      uninlinable = ! tree_inlinable_function_p (fndecl);
-      
-      if (! uninlinable && can_defer_p
-         /* Save function tree for inlining.  Should return 0 if the
-             language does not support function deferring or the
-             function could not be deferred.  */
-         && defer_fn (fndecl))
-       {
-         /* Let the back-end know that this function exists.  */
-         (*debug_hooks->deferred_inline_function) (fndecl);
-          timevar_pop (TV_INTEGRATION);
-         return;
-       }
-      
-      /* Then, inline any functions called in it.  */
-      optimize_inline_calls (fndecl);
-      timevar_pop (TV_INTEGRATION);
-    }
-
   timevar_push (TV_EXPAND);
 
   if (nested_p)
@@ -6809,8 +6321,8 @@ c_expand_body (fndecl, nested_p, can_defer_p)
 
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
-  input_filename = DECL_SOURCE_FILE (fndecl);
-  init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+  input_location = DECL_SOURCE_LOCATION (fndecl);
+  init_function_start (fndecl);
 
   /* This function is being processed in whole-function mode.  */
   cfun->x_whole_function_mode_p = 1;
@@ -6822,13 +6334,18 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
 
-  /* If this is a varargs function, inform function.c.  */
-  if (c_function_varargs)
-    mark_varargs ();
-
   /* Set up parameters and prepare for return, for the function.  */
   expand_function_start (fndecl, 0);
 
+  /* If the function has a variably modified type, there may be
+     SAVE_EXPRs in the parameter types.  Their context must be set to
+     refer to this function; they cannot be expanded in the containing
+     function.  */
+  if (decl_function_context (fndecl)
+      && variably_modified_type_p (TREE_TYPE (fndecl)))
+    walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
+              NULL);
+
   /* If this function is `main', emit a call to `__main'
      to run global initializers, etc.  */
   if (DECL_NAME (fndecl)
@@ -6838,11 +6355,6 @@ c_expand_body (fndecl, nested_p, can_defer_p)
 
   /* Generate the RTL for this function.  */
   expand_stmt (DECL_SAVED_TREE (fndecl));
-  if (uninlinable)
-    {
-      /* Allow the body of the function to be garbage collected.  */
-      DECL_SAVED_TREE (fndecl) = NULL_TREE;
-    }
 
   /* We hard-wired immediate_size_expand to zero above.
      expand_function_end will decrement this variable.  So, we set the
@@ -6855,7 +6367,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
     (*lang_expand_function_end) ();
 
   /* Generate rtl for function exit.  */
-  expand_function_end (input_filename, lineno, 0);
+  expand_function_end ();
 
   /* If this is a nested function, protect the local variables in the stack
      above us from being collected while we're compiling this function.  */
@@ -6869,7 +6381,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   if (nested_p)
     ggc_pop_context ();
 
-  /* With just -W, complain only if function returns both with
+  /* With just -Wextra, complain only if function returns both with
      and without a value.  */
   if (extra_warnings
       && current_function_returns_value
@@ -6940,11 +6452,19 @@ c_expand_body (fndecl, nested_p, can_defer_p)
     pop_function_context ();
   timevar_pop (TV_EXPAND);
 }
+
+/* Like c_expand_body_1 but only for unnested functions.  */
+
+void
+c_expand_body (tree fndecl)
+{
+  c_expand_body_1 (fndecl, 0);
+}
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  */
 void
-check_for_loop_decls ()
+check_for_loop_decls (void)
 {
   tree t;
 
@@ -6975,7 +6495,7 @@ check_for_loop_decls ()
       if (TREE_PURPOSE (t) != 0)
         {
           enum tree_code code = TREE_CODE (TREE_VALUE (t));
-         
+
           if (code == RECORD_TYPE)
             error ("`struct %s' declared in `for' loop initial declaration",
                    IDENTIFIER_POINTER (TREE_PURPOSE (t)));
@@ -7020,8 +6540,7 @@ struct language_function GTY(())
    used during compilation of a C function.  */
 
 void
-c_push_function_context (f)
-     struct function *f;
+c_push_function_context (struct function *f)
 {
   struct language_function *p;
   p = ((struct language_function *)
@@ -7043,8 +6562,7 @@ c_push_function_context (f)
 /* Restore the variables used during compilation of a C function.  */
 
 void
-c_pop_function_context (f)
-     struct function *f;
+c_pop_function_context (struct function *f)
 {
   struct language_function *p = f->language;
   tree link;
@@ -7082,8 +6600,7 @@ c_pop_function_context (f)
 /* Copy the DECL_LANG_SPECIFIC data associated with DECL.  */
 
 void
-c_dup_lang_specific_decl (decl)
-     tree decl;
+c_dup_lang_specific_decl (tree decl)
 {
   struct lang_decl *ld;
 
@@ -7101,12 +6618,12 @@ c_dup_lang_specific_decl (decl)
    functions are not called from anywhere in the C front end, but as
    these changes continue, that will change.  */
 
-/* Returns non-zero if the current statement is a full expression,
+/* Returns nonzero if the current statement is a full expression,
    i.e. temporaries created during that statement should be destroyed
    at the end of the statement.  */
 
 int
-stmts_are_full_exprs_p ()
+stmts_are_full_exprs_p (void)
 {
   return 0;
 }
@@ -7116,7 +6633,7 @@ stmts_are_full_exprs_p ()
    returned.  */
 
 stmt_tree
-current_stmt_tree ()
+current_stmt_tree (void)
 {
   return &c_stmt_tree;
 }
@@ -7124,7 +6641,7 @@ current_stmt_tree ()
 /* Returns the stack of SCOPE_STMTs for the current function.  */
 
 tree *
-current_scope_stmt_stack ()
+current_scope_stmt_stack (void)
 {
   return &c_scope_stmt_stack;
 }
@@ -7133,8 +6650,7 @@ current_scope_stmt_stack ()
    C.  */
 
 int
-anon_aggr_type_p (node)
-     tree node ATTRIBUTE_UNUSED;
+anon_aggr_type_p (tree node ATTRIBUTE_UNUSED)
 {
   return 0;
 }
@@ -7142,7 +6658,7 @@ anon_aggr_type_p (node)
 /* Dummy function in place of callback used by C++.  */
 
 void
-extract_interface_info ()
+extract_interface_info (void)
 {
 }
 
@@ -7150,7 +6666,7 @@ extract_interface_info ()
    statement tree.  */
 
 tree
-c_begin_compound_stmt ()
+c_begin_compound_stmt (void)
 {
   tree stmt;
 
@@ -7164,8 +6680,7 @@ c_begin_compound_stmt ()
    common code.  */
 
 void
-c_expand_decl_stmt (t)
-     tree t;
+c_expand_decl_stmt (tree t)
 {
   tree decl = DECL_STMT_DECL (t);
 
@@ -7173,27 +6688,32 @@ c_expand_decl_stmt (t)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_CONTEXT (decl) == current_function_decl
       && DECL_SAVED_TREE (decl))
-    c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
+    c_expand_body_1 (decl, 1);
 }
 
-/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
-   the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++.  */
+/* Return the global value of T as a symbol.  */
 
 tree
-identifier_global_value        (t)
-     tree t;
+identifier_global_value        (tree t)
 {
-  return IDENTIFIER_GLOBAL_VALUE (t);
+  tree decl = IDENTIFIER_SYMBOL_VALUE (t);
+  if (decl == 0 || DECL_CONTEXT (decl) == 0)
+    return decl;
+
+  /* Shadowed by something else; find the true global value.  */
+  for (decl = global_binding_level->names; decl; decl = TREE_CHAIN (decl))
+    if (DECL_NAME (decl) == t)
+      return decl;
+
+  /* Only local values for this decl.  */
+  return 0;
 }
 
 /* Record a builtin type for C.  If NAME is non-NULL, it is the name used;
    otherwise the name is found in ridpointers from RID_INDEX.  */
 
 void
-record_builtin_type (rid_index, name, type)
-     enum rid rid_index;
-     const char *name;
-     tree type;
+record_builtin_type (enum rid rid_index, const char *name, tree type)
 {
   tree id;
   if (name == 0)
@@ -7205,7 +6725,7 @@ record_builtin_type (rid_index, name, type)
 
 /* Build the void_list_node (void_type_node having been created).  */
 tree
-build_void_list_node ()
+build_void_list_node (void)
 {
   tree t = build_tree_list (NULL_TREE, void_type_node);
   return t;
@@ -7221,8 +6741,7 @@ build_void_list_node ()
    if attributes are present) and whose type is the modifier list.  */
 
 tree
-make_pointer_declarator (type_quals_attrs, target)
-     tree type_quals_attrs, target;
+make_pointer_declarator (tree type_quals_attrs, tree target)
 {
   tree quals, attrs;
   tree itarget = target;