OSDN Git Service

PR c++/10549
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 1ab120a..e16c2b6 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"
@@ -37,7 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "expr.h"
 #include "c-tree.h"
-#include "c-lex.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "tm_p.h"
@@ -46,6 +47,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "debug.h"
 #include "timevar.h"
 #include "c-common.h"
+#include "c-pragma.h"
+#include "cgraph.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -103,26 +106,25 @@ static int current_function_prototype_line;
 
 /* The current statement tree.  */
 
-static struct stmt_tree_s c_stmt_tree;
+static GTY(()) struct stmt_tree_s c_stmt_tree;
 
 /* The current scope statement stack.  */
 
-static tree c_scope_stmt_stack;
+static GTY(()) tree c_scope_stmt_stack;
 
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
    that have names.  Here so we can clear out their names' definitions
    at the end of the function.  */
 
-static tree named_labels;
+static GTY(()) tree named_labels;
 
 /* A list of LABEL_DECLs from outer contexts that are currently shadowed.  */
 
-static tree shadowed_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,10 +163,7 @@ 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
+struct binding_level GTY(())
   {
     /* A chain of _DECL nodes for all variables, constants, functions,
        and typedef types.  These are in the reverse of the order supplied.
@@ -179,35 +178,34 @@ struct binding_level
      */
     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;
@@ -215,9 +213,9 @@ struct binding_level
     /* Nonzero means make a BLOCK if this level has any subblocks.  */
     char keep_if_subblocks;
 
-    /* Number of decls in `names' that have incomplete
-       structure or union types.  */
-    int n_incomplete;
+    /* List of decls in `names' that have incomplete structure or
+       union types.  */
+    tree incomplete_list;
 
     /* A list of decls giving the (reversed) specified order of parms,
        not including any forward-decls in the parmlist.
@@ -229,23 +227,17 @@ struct binding_level
 
 /* The binding level currently in effect.  */
 
-static struct binding_level *current_binding_level;
+static GTY(()) struct binding_level *current_binding_level;
 
 /* A chain of binding_level structures awaiting reuse.  */
 
-static struct binding_level *free_binding_level;
+static GTY((deletable (""))) struct binding_level *free_binding_level;
 
 /* The outermost binding level, for names of file scope.
    This is created when the compiler is started and exists
    through the entire run.  */
 
-static 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, 0,
-     NULL};
+static GTY(()) struct binding_level *global_binding_level;
 
 /* Nonzero means unconditionally make a BLOCK for the next level pushed.  */
 
@@ -262,7 +254,7 @@ static int keep_next_if_subblocks;
    saved values of named_labels and shadowed_labels for
    a label binding level outside the current one.  */
 
-static struct binding_level *label_level_chain;
+static GTY(()) struct binding_level *label_level_chain;
 
 /* Functions called automatically at the beginning and end of execution.  */
 
@@ -270,180 +262,27 @@ tree static_ctors, static_dtors;
 
 /* Forward declarations.  */
 
-static struct binding_level * make_binding_level       PARAMS ((void));
-static void mark_binding_level         PARAMS ((void *));
-static void clear_limbo_values         PARAMS ((tree));
+static struct binding_level *make_binding_level                PARAMS ((void));
+static void pop_binding_level          PARAMS ((struct binding_level **));
 static int duplicate_decls             PARAMS ((tree, tree, int));
 static int redeclaration_error_message PARAMS ((tree, tree));
+static void implicit_decl_warning       PARAMS ((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 lookup_tag                 PARAMS ((enum tree_code, tree, int));
+static tree lookup_name_current_level  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 c_expand_body_1             PARAMS ((tree, int));
+static tree any_external_decl          PARAMS ((tree));
+static void record_external_decl       PARAMS ((tree));
 static void warn_if_shadowing          PARAMS ((tree, tree));
+static void clone_underlying_type      PARAMS ((tree));
+static bool flexible_array_type_p      PARAMS ((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 do some things the same way PCC does.  */
-
-int flag_traditional;
-
-/* 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 allow single precision math even if we're generally
-   being traditional.  */
-int flag_allow_single_precision = 0;
-
-/* 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 warn about use of multicharacter literals.  */
-
-int warn_multichar = 1;
-
-/* 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
@@ -456,369 +295,15 @@ 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];
-
-  strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
-
-  if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
-    {
-      warning ("-traditional is deprecated and may be removed");
-      flag_traditional = 1;
-      flag_writable_strings = 1;
-    }
-  else if (!strcmp (p, "-fallow-single-precision"))
-    flag_allow_single_precision = 1;
-  else 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 (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
-    {
-      flag_traditional = 0;
-      flag_writable_strings = 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_traditional = 0;
-         flag_writable_strings = 0;
-         flag_no_asm = 1;
-         flag_no_nonansi_builtin = 1;
-         flag_noniso_default_format_attributes = 0;
-         flag_isoc99 = 0;
-       }
-      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_traditional = 0;
-         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;
-       }
-      else if (!strcmp (argstart, "gnu89"))
-       {
-         flag_traditional = 0;
-         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_traditional = 0;
-         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
-       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, "-Werror-implicit-function-declaration"))
-    mesg_implicit_function_declaration = 2;
-  else if (!strcmp (p, "-Wimplicit-function-declaration"))
-    mesg_implicit_function_declaration = 1;
-  else if (!strcmp (p, "-Wno-implicit-function-declaration"))
-    mesg_implicit_function_declaration = 0;
-  else if (!strcmp (p, "-Wimplicit-int"))
-    warn_implicit_int = 1;
-  else if (!strcmp (p, "-Wno-implicit-int"))
-    warn_implicit_int = 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, "-Wlong-long"))
-    warn_long_long = 1;
-  else if (!strcmp (p, "-Wno-long-long"))
-    warn_long_long = 0;
-  else if (!strcmp (p, "-Wwrite-strings"))
-    flag_const_strings = 1;
-  else if (!strcmp (p, "-Wno-write-strings"))
-    flag_const_strings = 0;
-  else if (!strcmp (p, "-Wcast-qual"))
-    warn_cast_qual = 1;
-  else if (!strcmp (p, "-Wno-cast-qual"))
-    warn_cast_qual = 0;
-  else if (!strcmp (p, "-Wbad-function-cast"))
-    warn_bad_function_cast = 1;
-  else if (!strcmp (p, "-Wno-bad-function-cast"))
-    warn_bad_function_cast = 0;
-  else if (!strcmp (p, "-Wno-missing-noreturn"))
-    warn_missing_noreturn = 0;
-  else if (!strcmp (p, "-Wmissing-format-attribute"))
-    warn_missing_format_attribute = 1;
-  else if (!strcmp (p, "-Wno-missing-format-attribute"))
-    warn_missing_format_attribute = 0;
-  else if (!strcmp (p, "-Wpointer-arith"))
-    warn_pointer_arith = 1;
-  else if (!strcmp (p, "-Wno-pointer-arith"))
-    warn_pointer_arith = 0;
-  else if (!strcmp (p, "-Wstrict-prototypes"))
-    warn_strict_prototypes = 1;
-  else if (!strcmp (p, "-Wno-strict-prototypes"))
-    warn_strict_prototypes = 0;
-  else if (!strcmp (p, "-Wmissing-prototypes"))
-    warn_missing_prototypes = 1;
-  else if (!strcmp (p, "-Wno-missing-prototypes"))
-    warn_missing_prototypes = 0;
-  else if (!strcmp (p, "-Wmissing-declarations"))
-    warn_missing_declarations = 1;
-  else if (!strcmp (p, "-Wno-missing-declarations"))
-    warn_missing_declarations = 0;
-  else if (!strcmp (p, "-Wredundant-decls"))
-    warn_redundant_decls = 1;
-  else if (!strcmp (p, "-Wno-redundant-decls"))
-    warn_redundant_decls = 0;
-  else if (!strcmp (p, "-Wnested-externs"))
-    warn_nested_externs = 1;
-  else if (!strcmp (p, "-Wno-nested-externs"))
-    warn_nested_externs = 0;
-  else if (!strcmp (p, "-Wtraditional"))
-    warn_traditional = 1;
-  else if (!strcmp (p, "-Wno-traditional"))
-    warn_traditional = 0;
-  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, "-Wformat-y2k"))
-    warn_format_y2k = 1;
-  else if (!strcmp (p, "-Wno-format-y2k"))
-    warn_format_y2k = 0;
-  else if (!strcmp (p, "-Wformat-extra-args"))
-    warn_format_extra_args = 1;
-  else if (!strcmp (p, "-Wno-format-extra-args"))
-    warn_format_extra_args = 0;
-  else if (!strcmp (p, "-Wformat-nonliteral"))
-    warn_format_nonliteral = 1;
-  else if (!strcmp (p, "-Wno-format-nonliteral"))
-    warn_format_nonliteral = 0;
-  else if (!strcmp (p, "-Wformat-security"))
-    warn_format_security = 1;
-  else if (!strcmp (p, "-Wno-format-security"))
-    warn_format_security = 0;
-  else if (!strcmp (p, "-Wchar-subscripts"))
-    warn_char_subscripts = 1;
-  else if (!strcmp (p, "-Wno-char-subscripts"))
-    warn_char_subscripts = 0;
-  else if (!strcmp (p, "-Wconversion"))
-    warn_conversion = 1;
-  else if (!strcmp (p, "-Wno-conversion"))
-    warn_conversion = 0;
-  else if (!strcmp (p, "-Wparentheses"))
-    warn_parentheses = 1;
-  else if (!strcmp (p, "-Wno-parentheses"))
-    warn_parentheses = 0;
-  else if (!strcmp (p, "-Wreturn-type"))
-    warn_return_type = 1;
-  else if (!strcmp (p, "-Wno-return-type"))
-    warn_return_type = 0;
-  else if (!strcmp (p, "-Wsequence-point"))
-    warn_sequence_point = 1;
-  else if (!strcmp (p, "-Wno-sequence-point"))
-    warn_sequence_point = 0;
-  else if (!strcmp (p, "-Wcomment"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-comment"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wcomments"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-comments"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wtrigraphs"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-trigraphs"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wundef"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-undef"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wimport"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wno-import"))
-    ; /* cpp handles this one.  */
-  else if (!strcmp (p, "-Wmissing-braces"))
-    warn_missing_braces = 1;
-  else if (!strcmp (p, "-Wno-missing-braces"))
-    warn_missing_braces = 0;
-  else if (!strcmp (p, "-Wmain"))
-    warn_main = 1;
-  else if (!strcmp (p, "-Wno-main"))
-    warn_main = -1;
-  else if (!strcmp (p, "-Wsign-compare"))
-    warn_sign_compare = 1;
-  else if (!strcmp (p, "-Wno-sign-compare"))
-    warn_sign_compare = 0;
-  else if (!strcmp (p, "-Wfloat-equal"))
-    warn_float_equal = 1;
-  else if (!strcmp (p, "-Wno-float-equal"))
-    warn_float_equal = 0;
-  else if (!strcmp (p, "-Wmultichar"))
-    warn_multichar = 1;
-  else if (!strcmp (p, "-Wno-multichar"))
-    warn_multichar = 0;
-  else if (!strcmp (p, "-Wdiv-by-zero"))
-    warn_div_by_zero = 1;
-  else if (!strcmp (p, "-Wno-div-by-zero"))
-    warn_div_by_zero = 0;
-  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
-    return strings_processed;
-
-  return 1;
-}
-
 void
 c_print_identifier (file, node, indent)
      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)];
@@ -833,7 +318,7 @@ c_print_identifier (file, node, indent)
    for a top-level tentative array defn that wasn't complete before.  */
 
 void
-finish_incomplete_decl (decl)
+c_finish_incomplete_decl (decl)
      tree decl;
 {
   if (TREE_CODE (decl) == VAR_DECL)
@@ -853,13 +338,37 @@ finish_incomplete_decl (decl)
     }
 }
 \f
-/* Create a new `struct binding_level'.  */
+/* Reuse or create a struct for this binding level.  */
 
 static struct binding_level *
 make_binding_level ()
 {
-  /* NOSTRICT */
-  return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+  struct binding_level *result;
+  if (free_binding_level)
+    {
+      result = free_binding_level;
+      free_binding_level = result->level_chain;
+      memset (result, 0, sizeof(struct binding_level));
+    }
+  else
+    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;
+{
+  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;
 }
 
 /* Nonzero if we are currently in the global binding level.  */
@@ -885,8 +394,7 @@ kept_level_p ()
           && 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.
@@ -909,67 +417,45 @@ in_parm_level_p ()
   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 (dummy)
+     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.
 
-  /* Reuse or create a struct for this 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;
 
-  if (free_binding_level)
-    {
-      newlevel = free_binding_level;
-      free_binding_level = free_binding_level->level_chain;
+      keep_next_level_flag = 0;
+      keep_next_if_subblocks = 0;
     }
   else
     {
-      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.  */
+      struct binding_level *newlevel = make_binding_level ();
 
-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.
@@ -994,95 +480,103 @@ poplevel (keep, reverse, functionbody)
      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.  */
@@ -1090,50 +584,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);
@@ -1158,23 +633,14 @@ poplevel (keep, reverse, functionbody)
 
   /* Pop the current level, and free the structure for reuse.  */
 
-  {
-    struct binding_level *level = current_binding_level;
-    current_binding_level = current_binding_level->level_chain;
-
-    level->level_chain = free_binding_level;
-    free_binding_level = level;
-  }
+  pop_binding_level (&current_binding_level);
 
   /* Dispose of the block that we just made inside some higher level.  */
   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)
@@ -1184,30 +650,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;
 }
 
@@ -1224,18 +666,14 @@ insert_block (block)
     = 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;
+     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
@@ -1243,17 +681,7 @@ push_label_level ()
 {
   struct binding_level *newlevel;
 
-  /* Reuse or create a struct for this binding level.  */
-
-  if (free_binding_level)
-    {
-      newlevel = free_binding_level;
-      free_binding_level = free_binding_level->level_chain;
-    }
-  else
-    {
-      newlevel = make_binding_level ();
-    }
+  newlevel = make_binding_level ();
 
   /* Add this level to the front of the chain (stack) of label levels.  */
 
@@ -1315,9 +743,7 @@ pop_label_level ()
   shadowed_labels = level->shadowed;
 
   /* Pop the current level, and free the structure for reuse.  */
-  label_level_chain = label_level_chain->level_chain;
-  level->level_chain = free_binding_level;
-  free_binding_level = level;
+  pop_binding_level (&label_level_chain);
 }
 \f
 /* Push a definition or a declaration of struct, union or enum tag "name".
@@ -1331,12 +757,7 @@ void
 pushtag (name, type)
      tree name, 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)
     {
@@ -1344,6 +765,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);
@@ -1434,30 +860,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");
@@ -1471,25 +883,21 @@ 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
      match enough.  Ultimately, copy most of the information from the new
      decl to the old one, and keep using the old one.  */
 
-  if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
-      && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl
-      && DECL_INITIAL (olddecl) == 0)
-    /* If -traditional, avoid error for redeclaring fcn
-       after implicit decl.  */
-    ;
-  else if (TREE_CODE (olddecl) == FUNCTION_DECL
-          && DECL_BUILT_IN (olddecl))
+  if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
     {
       /* A function declaration for a built-in function.  */
       if (!TREE_PUBLIC (newdecl))
@@ -1619,6 +1027,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.  */
@@ -1656,13 +1078,37 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                  break;
                }
 
-             if (simple_type_promotes_to (type) != NULL_TREE)
+             if (c_type_promotes_to (type) != type)
                {
                  error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
                  break;
                }
            }
        }
+      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
@@ -1690,6 +1136,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                             && current_binding_level == global_binding_level)
                            ? "`%s' previously defined here"
                            : "`%s' previously declared here"));
+         return 0;
        }
       else if (TREE_CODE (newdecl) == TYPE_DECL
                && (DECL_IN_SYSTEM_HEADER (olddecl)
@@ -1737,12 +1184,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                }
              /* Type for passing arg must be consistent
                 with that declared for the arg.  */
-             if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))
-                 /* If -traditional, allow `unsigned int' instead of `int'
-                    in the prototype.  */
-                 && (! (flag_traditional
-                        && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
-                        && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
+             if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
                {
                  error_with_decl (newdecl,
                                   "prototype for `%s' follows and argument %d doesn't match",
@@ -1877,11 +1319,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;
 
@@ -1940,6 +1377,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,
@@ -1953,7 +1394,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     }
 
   /* Merge the storage class information.  */
-  DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+  merge_weak (newdecl, olddecl);
+
   /* For functions, static overrides non-static.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -1994,9 +1436,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;
@@ -2090,63 +1533,137 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   return 1;
 }
 
+/* Return any external DECL associated with ID, whether or not it is
+   currently in scope.  */
+static tree
+any_external_decl (id)
+     tree id;
+{
+  tree decl = IDENTIFIER_SYMBOL_VALUE (id);
+  tree t;
+
+  if (decl && 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 (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 (x, old)
+     tree x, 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);
+}
+
+
+/* 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;
 
-  /* 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))
+    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 (x)
+     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;
     }
 }
 
@@ -2162,387 +1679,81 @@ tree
 pushdecl (x)
      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);
-      /* Don't type check externs here when -traditional.  This is so that
-        code with conflicting declarations inside blocks will get warnings
-        not errors.  X11 for instance depends on this.  */
-      if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
-       {
-         t = lookup_name (name);
-         /* Type decls at global scope don't conflict with externs declared
-            inside lexical blocks.  */
-         if (t && TREE_CODE (t) == TYPE_DECL)
-           t = 0;
-         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.  But don't complain if -traditional,
-        since traditional compilers don't complain.  */
-      if (! flag_traditional && 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))
+      old = lookup_name_current_level (name);
+      if (old && duplicate_decls (x, old, 0))
+       return old;
+      if (DECL_EXTERNAL (x) || scope == global_binding_level)
        {
-         if (TREE_CODE (t) == PARM_DECL)
+         /* 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)
            {
-             /* Don't allow more than one "real" duplicate
-                of a forward parm decl.  */
-             TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
-             return t;
+             if (duplicate_decls (x, ext, scope != global_binding_level))
+               x = copy_node (ext);
            }
-         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)
-       {
-         if (DECL_SOURCE_LINE (x) == 0)
-           {
-             if (TYPE_NAME (TREE_TYPE (x)) == 0)
-               TYPE_NAME (TREE_TYPE (x)) = x;
-           }
-         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.
-        Check against both global declarations (when traditional) and out of
-        scope (limbo) block level declarations.
-
-        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 (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0
-             && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
-                 || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
-           decl = IDENTIFIER_GLOBAL_VALUE (name);
-         else 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);
        }
-
-      /* In PCC-compatibility mode, extern decls of vars with no current decl
-        take effect at top level no matter where they are.  */
-      if (flag_traditional && DECL_EXTERNAL (x)
-         && lookup_name (name) == 0)
-       {
-         tree type = TREE_TYPE (x);
-
-         /* But don't do this if the type contains temporary nodes.  */
-         while (type)
-           {
-             if (type == error_mark_node)
-               break;
-             if (TYPE_CONTEXT (type))
-               {
-                 warning_with_decl (x, "type of external `%s' is not global");
-                 /* By exiting the loop early, we leave TYPE nonzero,
-                    and thus prevent globalization of the decl.  */
-                 break;
-               }
-             else if (TREE_CODE (type) == FUNCTION_TYPE
-                      && TYPE_ARG_TYPES (type) != 0)
-               /* The types might not be truly local,
-                  but the list of arg types certainly is temporary.
-                  Since prototypes are nontraditional,
-                  ok not to do the traditional thing.  */
-               break;
-             type = TREE_TYPE (type);
-           }
-
-         if (type == 0)
-           b = global_binding_level;
-       }
-
-      /* 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 count of variables in this level with incomplete type.
+      /* Keep list of variables in this level with incomplete type.
         If the input is erroneous, we can have error_mark in the type
         slot (e.g. "f(void a, ...)") - that doesn't count as an
         incomplete type.  */
@@ -2555,85 +1766,137 @@ pushdecl (x)
            element = TREE_TYPE (element);
          if (TREE_CODE (element) == RECORD_TYPE
              || TREE_CODE (element) == UNION_TYPE)
-           ++b->n_incomplete;
+           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;
 {
-  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;
+}
+
+/* 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
+pushdecl_function_level (x, name)
+     tree x;
+     tree name;
+{
+  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 ();
+
+      DECL_CONTEXT (x) = current_function_decl;
+      TREE_CHAIN (x) = scope->names;
+      scope->names = x;
+    }
+
+  IDENTIFIER_SYMBOL_VALUE (name) = x;
+  return x;
 }
 \f
-/* Generate an implicit declaration for identifier FUNCTIONID
-   as a function of type int ().  Print a warning if appropriate.  */
+/* Generate an implicit declaration for identifier FUNCTIONID as a
+   function of type int ().  */
 
 tree
 implicitly_declare (functionid)
      tree functionid;
 {
-  tree decl;
-  int traditional_warning = 0;
-  /* Only one "implicit declaration" warning per identifier.  */
-  int implicit_warning;
+  tree decl = any_external_decl (functionid);
 
-  /* 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);
-
-  /* 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;
-
-  /* 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.
-     If flag_traditional is set, pushdecl does it top-level.  */
-  pushdecl (decl);
-
-  /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-  maybe_objc_check_decl (decl);
+     So we record the decl in the standard fashion.  */
+  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).  */
 
@@ -2645,7 +1908,7 @@ implicitly_declare (functionid)
   return decl;
 }
 
-void
+static void
 implicit_decl_warning (id)
      tree id;
 {
@@ -2668,17 +1931,8 @@ redeclaration_error_message (newdecl, olddecl)
 {
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
-      if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl))
-       return 0;
-      /* pushdecl creates distinct types for TYPE_DECLs by calling
-        build_type_copy, so the above comparison generally fails.  We do
-        another test against the TYPE_MAIN_VARIANT of the olddecl, which
-        is equivalent to what this code used to do before the build_type_copy
-        call.  The variant type distinction should not matter for traditional
-        code, because it doesn't have type qualifiers.  */
-      if (flag_traditional
-         && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
-       return 0;
+      /* Do not complain about type redeclarations where at least one
+        declaration was in a system header.  */
       if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
        return 0;
       return 1;
@@ -2896,55 +2150,50 @@ storetags (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)
+lookup_tag (code, name, thislevel_only)
      enum tree_code code;
-     struct binding_level *binding_level;
      tree name;
      int thislevel_only;
 {
-  struct binding_level *level;
-  int thislevel = 1;
+  tree tag = IDENTIFIER_TAG_VALUE (name);
+  int thislevel = 0;
+
+  if (!tag)
+    return 0;
 
-  for (level = binding_level; level; level = level->level_chain)
+  /* 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_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 tag;
 }
 
 /* Print an error message now
@@ -2963,26 +2212,6 @@ pending_xref_error ()
   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.
@@ -2993,56 +2222,35 @@ tree
 lookup_name (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
+static tree
 lookup_name_current_level (name)
      tree name;
 {
-  tree t;
-
-  if (current_binding_level == global_binding_level)
-    return IDENTIFIER_GLOBAL_VALUE (name);
+  tree decl = IDENTIFIER_SYMBOL_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;
-
-  return t;
-}
-\f
-/* Mark ARG for GC.  */
+  if (current_binding_level == global_binding_level)
+    return decl;
 
-static void
-mark_binding_level (arg)
-     void *arg;
-{
-  struct binding_level *level = *(struct binding_level **) arg;
+  /* Scan the current scope for a decl with name NAME.  */
+  if (chain_member (decl, current_binding_level->names))
+    return decl;
 
-  for (; level != 0; level = level->level_chain)
-    {
-      ggc_mark_tree (level->names);
-      ggc_mark_tree (level->tags);
-      ggc_mark_tree (level->shadowed);
-      ggc_mark_tree (level->blocks);
-      ggc_mark_tree (level->this_block);
-      ggc_mark_tree (level->parm_order);
-    }
+  return 0;
 }
-
+\f
 /* Create the predefined scalar types of C,
    and some nodes representing standard constants (0, 1, (void *) 0).
    Initialize the global binding level.
@@ -3074,8 +2282,7 @@ c_init_decl_processing ()
   boolean_true_node = integer_one_node;
   boolean_false_node = integer_zero_node;
 
-  /* With GCC, C99's _Bool is always of size 1.  */
-  c_bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
+  c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
   TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
   TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
@@ -3093,75 +2300,10 @@ c_init_decl_processing ()
     = build_function_type (ptr_type_node,
                           tree_cons (NULL_TREE, ptr_type_node, endlink));
 
-  /* Types which are common to the fortran compiler and libf2c.  When
-     changing these, you also need to be concerned with f/com.h.  */
-
-  if (TYPE_PRECISION (float_type_node)
-      == TYPE_PRECISION (long_integer_type_node))
-    {
-      g77_integer_type_node = long_integer_type_node;
-      g77_uinteger_type_node = long_unsigned_type_node;
-    }
-  else if (TYPE_PRECISION (float_type_node)
-          == TYPE_PRECISION (integer_type_node))
-    {
-      g77_integer_type_node = integer_type_node;
-      g77_uinteger_type_node = unsigned_type_node;
-    }
-  else
-    g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
-
-  if (g77_integer_type_node != NULL_TREE)
-    {
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
-                           g77_integer_type_node));
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
-                           g77_uinteger_type_node));
-    }
-
-  if (TYPE_PRECISION (float_type_node) * 2
-      == TYPE_PRECISION (long_integer_type_node))
-    {
-      g77_longint_type_node = long_integer_type_node;
-      g77_ulongint_type_node = long_unsigned_type_node;
-    }
-  else if (TYPE_PRECISION (float_type_node) * 2
-          == TYPE_PRECISION (long_long_integer_type_node))
-    {
-      g77_longint_type_node = long_long_integer_type_node;
-      g77_ulongint_type_node = long_long_unsigned_type_node;
-    }
-  else
-    g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
-
-  if (g77_longint_type_node != NULL_TREE)
-    {
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
-                           g77_longint_type_node));
-      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
-                           g77_ulongint_type_node));
-    }
-
   pedantic_lvalues = pedantic;
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
-
-  incomplete_decl_finalize_hook = finish_incomplete_decl;
-
-  /* Record our roots.  */
-
-  ggc_add_tree_root (c_global_trees, CTI_MAX);
-  ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
-  ggc_add_tree_root (&c_scope_stmt_stack, 1);
-  ggc_add_tree_root (&named_labels, 1);
-  ggc_add_tree_root (&shadowed_labels, 1);
-  ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
-               mark_binding_level);
-  ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
-               mark_binding_level);
-  ggc_add_tree_root (&static_ctors, 1);
-  ggc_add_tree_root (&static_dtors, 1);
 }
 
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -3186,8 +2328,6 @@ 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;
@@ -3198,7 +2338,10 @@ c_make_fname_decl (id, type_dep)
   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;
@@ -3210,24 +2353,21 @@ 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)
+builtin_function (name, type, function_code, class, library_name, attrs)
      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;
   TREE_PUBLIC (decl) = 1;
-  /* If -traditional, permit redefining a builtin function any way you like.
-     (Though really, if the program redefines these functions,
-     it probably won't work right unless compiled with -fno-builtin.)  */
-  if (flag_traditional && name[0] != '_')
-    DECL_BUILT_IN_NONANSI (decl) = 1;
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
   make_decl_rtl (decl, NULL);
@@ -3235,17 +2375,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;
 }
@@ -3254,7 +2393,7 @@ builtin_function (name, type, function_code, class, library_name)
    attributes.  */
 
 void
-insert_default_attributes (decl)
+c_insert_default_attributes (decl)
      tree decl;
 {
   if (!TREE_PUBLIC (decl))
@@ -3303,7 +2442,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++;
@@ -3319,7 +2458,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)
                {
@@ -3351,8 +2490,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
@@ -3374,9 +2513,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");
@@ -3385,7 +2524,7 @@ 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.  */
@@ -3481,15 +2620,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:
@@ -3567,14 +2700,28 @@ start_decl (declarator, declspecs, initialized, attributes)
   /* ANSI specifies that a tentative definition which is not merged with
      a non-tentative definition behaves exactly like a definition with an
      initializer equal to zero.  (Section 3.7.2)
-     -fno-common gives strict ANSI behavior.  Usually you don't want it.
-     This matters only for variables with external linkage.  */
-  if (! flag_no_common || ! TREE_PUBLIC (decl))
+
+     -fno-common gives strict ANSI behavior, though this tends to break
+     a large body of code that grew up without this rule.
+
+     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 presence of dynamic linking.  */
+
+  if (TREE_CODE (decl) == VAR_DECL
+      && !initialized
+      && TREE_PUBLIC (decl)
+      && !DECL_THREAD_LOCAL (decl)
+      && !flag_no_common)
     DECL_COMMON (decl) = 1;
 
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   decl_attributes (&decl, attributes, 0);
 
+  /* If #pragma weak was used, mark the decl weak now.  */
+  if (current_binding_level == global_binding_level)
+    maybe_apply_pragma_weak (decl);
+
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
@@ -3620,6 +2767,8 @@ finish_decl (decl, init, asmspec_tree)
   const char *asmspec = 0;
 
   /* If a name was specified, get the string.  */
+  if (current_binding_level == global_binding_level)
+    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
@@ -3632,16 +2781,7 @@ finish_decl (decl, init, asmspec_tree)
     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
@@ -3727,12 +2867,28 @@ 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;
+      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 (asmspec));
+#ifdef TARGET_MEM_FUNCTIONS
+         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
+           init_block_move_fn (asmspec);
+         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
+           init_block_clear_fn (asmspec);
+#else
+         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY)
+           init_block_move_fn (asmspec);
+         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO)
+           init_block_clear_fn (asmspec);
+#endif
+       }
       SET_DECL_RTL (decl, NULL_RTX);
       SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
     }
@@ -3743,8 +2899,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 (flag_objc)
+       objc_check_decl (decl);
 
       if (!DECL_CONTEXT (decl))
        {
@@ -3806,8 +2963,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 (flag_objc)
+       objc_check_decl (decl);
       rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
     }
 
@@ -3818,17 +2976,6 @@ finish_decl (decl, init, asmspec_tree)
     get_pending_sizes ();
 }
 
-/* If DECL has a cleanup, build and return that cleanup here.
-   This is a callback called by expand_expr.  */
-
-tree
-maybe_build_cleanup (decl)
-     tree decl ATTRIBUTE_UNUSED;
-{
-  /* There are no cleanups in C.  */
-  return NULL_TREE;
-}
-
 /* Given a parsed parameter declaration,
    decode it into a PARM_DECL and push that on the current binding level.
    Also, for the sake of forward parm decls,
@@ -3879,6 +3026,8 @@ clear_parm_order ()
   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
@@ -3901,6 +3050,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))
@@ -3923,12 +3073,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;
@@ -4004,6 +3160,40 @@ 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 (type)
+     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.
@@ -4155,7 +3345,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          enum rid i = C_RID_CODE (id);
          if ((int) i <= (int) RID_LAST_MODIFIER)
            {
-             if (i == RID_LONG && (specbits & (1 << (int) i)))
+             if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
                {
                  if (longlong)
                    error ("`long long long' is too long for GCC");
@@ -4163,12 +3353,33 @@ 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.  */
+             if (i == RID_THREAD
+                 && (specbits & (1 << (int) RID_EXTERN
+                                 | 1 << (int) RID_STATIC)))
+               {
+                 if (specbits & 1 << (int) RID_EXTERN)
+                   error ("`__thread' before `extern'");
+                 else
+                   error ("`__thread' before `static'");
+               }
+
              specbits |= 1 << (int) i;
              goto found;
            }
@@ -4288,12 +3499,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;
            }
        }
 
@@ -4316,9 +3526,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
   if (specbits & 1 << (int) RID_UNSIGNED
-      /* Traditionally, all bitfields are unsigned.  */
-      || (bitfield && flag_traditional
-         && (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
       || (bitfield && ! flag_signed_bitfields
          && (explicit_int || defaulted_int || explicit_char
              /* A typedef for plain `int' without `signed'
@@ -4337,7 +3544,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (type == char_type_node)
        type = unsigned_char_type_node;
       else if (typedef_decl)
-       type = unsigned_type (type);
+       type = c_common_unsigned_type (type);
       else
        type = unsigned_type_node;
     }
@@ -4354,7 +3561,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
@@ -4421,6 +3628,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (specbits & 1 << (int) RID_REGISTER) nclasses++;
     if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
 
+    /* "static __thread" and "extern __thread" are allowed.  */
+    if ((specbits & (1 << (int) RID_THREAD
+                    | 1 << (int) RID_STATIC
+                    | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
+      nclasses++;
+
     /* Warn about storage classes that are invalid for certain
        kinds of declarations (parameters, typenames, etc.).  */
 
@@ -4430,7 +3643,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             && (specbits
                 & ((1 << (int) RID_REGISTER)
                    | (1 << (int) RID_AUTO)
-                   | (1 << (int) RID_TYPEDEF))))
+                   | (1 << (int) RID_TYPEDEF)
+                   | (1 << (int) RID_THREAD))))
       {
        if (specbits & 1 << (int) RID_AUTO
            && (pedantic || current_binding_level == global_binding_level))
@@ -4439,8 +3653,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          error ("function definition declared `register'");
        if (specbits & 1 << (int) RID_TYPEDEF)
          error ("function definition declared `typedef'");
+       if (specbits & 1 << (int) RID_THREAD)
+         error ("function definition declared `__thread'");
        specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
-                     | (1 << (int) RID_AUTO));
+                     | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
       }
     else if (decl_context != NORMAL && nclasses > 0)
       {
@@ -4463,7 +3679,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              }
            specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
                          | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
-                         | (1 << (int) RID_EXTERN));
+                         | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
          }
       }
     else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
@@ -4474,12 +3690,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        else
          error ("`%s' has both `extern' and initializer", name);
       }
-    else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag
-            && current_binding_level != global_binding_level)
-      error ("nested function `%s' declared `extern'", name);
-    else if (current_binding_level == global_binding_level
-            && specbits & (1 << (int) RID_AUTO))
-      error ("top-level declaration of `%s' specifies `auto'", name);
+    else if (current_binding_level == global_binding_level)
+      {
+       if (specbits & 1 << (int) RID_AUTO)
+         error ("top-level declaration of `%s' specifies `auto'", name);
+      }
+    else
+      {
+       if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
+         error ("nested function `%s' declared `extern'", name);
+       else if ((specbits & (1 << (int) RID_THREAD
+                              | 1 << (int) RID_EXTERN
+                              | 1 << (int) RID_STATIC))
+                == (1 << (int) RID_THREAD))
+         {
+           error ("function-scope `%s' implicitly auto and declared `__thread'",
+                  name);
+           specbits &= ~(1 << (int) RID_THREAD);
+         }
+      }
   }
 
   /* Now figure out the structure of the declarator proper.
@@ -4547,7 +3776,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          tree itype = NULL_TREE;
          tree size = TREE_OPERAND (declarator, 1);
          /* The index is a signed object `sizetype' bits wide.  */
-         tree index_type = signed_type (sizetype);
+         tree index_type = c_common_signed_type (sizetype);
 
          array_ptr_quals = TREE_TYPE (declarator);
          array_parm_static = TREE_STATIC (declarator);
@@ -4568,6 +3797,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;
 
@@ -4607,13 +3839,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                     even if it is (eg) a const variable with known value.  */
                  size_varies = 1;
 
-                 if (pedantic)
+                 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);
                    }
                }
@@ -4649,18 +3881,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)
            {
-             /* ??? Need to check somewhere that this is a structure
-                and not a union, that this field is last, and that
-                this structure has at least one other named member.  */
-
              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.  */
@@ -4732,13 +3973,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              type = integer_type_node;
            }
 
-#ifndef TRADITIONAL_RETURN_FLOAT
-         /* Traditionally, declaring return type float means double.  */
-
-         if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
-           type = double_type_node;
-#endif /* TRADITIONAL_RETURN_FLOAT */
-
          /* Construct the function type and go to the next
             inner layer of declarator.  */
 
@@ -4754,7 +3988,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
@@ -5026,11 +4260,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        if (type == error_mark_node)
          promoted_type = type;
        else
-         {
-           promoted_type = simple_type_promotes_to (type);
-           if (! promoted_type)
-             promoted_type = type;
-         }
+         promoted_type = c_type_promotes_to (type);
 
        DECL_ARG_TYPE (decl) = promoted_type;
        DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
@@ -5082,6 +4312,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn ("invalid storage class for function `%s'", name);
        if (specbits & (1 << (int) RID_REGISTER))
          error ("invalid storage class for function `%s'", name);
+       if (specbits & (1 << (int) RID_THREAD))
+         error ("invalid storage class for function `%s'", name);
        /* Function declaration not at top level.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
@@ -5141,6 +4373,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;
          }
@@ -5165,7 +4399,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;
@@ -5174,22 +4423,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn_with_decl (decl, "variable `%s' declared `inline'");
 
        DECL_EXTERNAL (decl) = extern_ref;
+
        /* At top level, the presence of a `static' or `register' storage
           class specifier, or the absence of all storage class specifiers
           makes this declaration a definition (perhaps tentative).  Also,
           the absence of both `static' and `register' makes it public.  */
        if (current_binding_level == global_binding_level)
          {
-           TREE_PUBLIC (decl)
-             = !(specbits
-                 & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)));
-           TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
+           TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
+                                              | (1 << (int) RID_REGISTER)));
+           TREE_STATIC (decl) = !extern_ref;
          }
        /* Not at top level, only `static' makes a static definition.  */
        else
          {
            TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
-           TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
+           TREE_PUBLIC (decl) = extern_ref;
+         }
+
+       if (specbits & 1 << (int) RID_THREAD)
+         {
+           if (targetm.have_tls)
+             DECL_THREAD_LOCAL (decl) = 1;
+           else
+             /* A mere warning is sure to result in improper semantics
+                at runtime.  Don't bother to allow this to compile.  */
+             error ("thread-local storage not supported for this target");
          }
       }
 
@@ -5206,7 +4465,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        Otherwise, the fact that those components are volatile
        will be ignored, and would even crash the compiler.  */
     if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
-      mark_addressable (decl);
+      c_mark_addressable (decl);
 
     decl_attributes (&decl, returned_attrs, 0);
 
@@ -5484,7 +4743,7 @@ xref_tag (code, 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
@@ -5538,28 +4797,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));
+           error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
        }  
-
-      return ref;
     }
+  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;
@@ -5583,12 +4839,44 @@ grokfield (filename, line, declarator, declspecs, width)
 
   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;
        }
     }
@@ -5598,7 +4886,8 @@ grokfield (filename, line, declarator, declspecs, width)
   finish_decl (value, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
-  maybe_objc_check_decl (value);
+  if (flag_objc)
+    objc_check_decl (value);
   return value;
 }
 \f
@@ -5631,7 +4920,7 @@ finish_struct (t, fieldlist, attributes)
        if (pedantic)
          pedwarn ("%s defined inside parms",
                   TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
-       else if (! flag_traditional)
+       else
          warning ("%s defined inside parms",
                   TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
       }
@@ -5754,38 +5043,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.  */
@@ -5801,6 +5061,11 @@ 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;
     }
@@ -5874,22 +5139,29 @@ finish_struct (t, fieldlist, attributes)
   /* If this structure or union completes the type of any previous
      variable declaration, lay it out and output its rtl.  */
 
-  if (current_binding_level->n_incomplete != 0)
+  if (current_binding_level->incomplete_list != NULL_TREE)
     {
-      tree decl;
-      for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
-       {
+      tree prev = NULL_TREE;
+
+      for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
+        {
+         tree decl = TREE_VALUE (x);
+
          if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
              && 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 (flag_objc)
+               objc_check_decl (decl);
              rest_of_decl_compilation (decl, NULL, toplevel, 0);
              if (! toplevel)
                expand_decl (decl);
-             if (--current_binding_level->n_incomplete == 0)
-               break;
+             /* Unlink X from the incomplete list.  */
+             if (prev)
+               TREE_CHAIN (prev) = TREE_CHAIN (x);
+             else
+               current_binding_level->incomplete_list = TREE_CHAIN (x);
            }
          else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
                   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
@@ -5903,13 +5175,17 @@ finish_struct (t, fieldlist, attributes)
                  if (TREE_CODE (decl) != TYPE_DECL)
                    {
                      layout_decl (decl, 0);
-                     maybe_objc_check_decl (decl);
+                     if (flag_objc)
+                       objc_check_decl (decl);
                      rest_of_decl_compilation (decl, NULL, toplevel, 0);
                      if (! toplevel)
                        expand_decl (decl);
                    }
-                 if (--current_binding_level->n_incomplete == 0)
-                   break;
+                 /* Unlink X from the incomplete list.  */
+                 if (prev)
+                   TREE_CHAIN (prev) = TREE_CHAIN (x);
+                 else
+                   current_binding_level->incomplete_list = TREE_CHAIN (x);
                }
            }
        }
@@ -5949,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)
     {
@@ -6026,7 +5302,7 @@ finish_enum (enumtype, values, attributes)
                   min_precision (maxnode, unsign));
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
-      tree narrowest = type_for_size (precision, unsign);
+      tree narrowest = c_common_type_for_size (precision, unsign);
       if (narrowest == 0)
        {
          warning ("enumeration values exceed range of largest integer");
@@ -6039,7 +5315,7 @@ finish_enum (enumtype, values, attributes)
     precision = TYPE_PRECISION (integer_type_node);
 
   if (precision == TYPE_PRECISION (integer_type_node))
-    enum_value_type = type_for_size (precision, 0);
+    enum_value_type = c_common_type_for_size (precision, 0);
   else
     enum_value_type = enumtype;
 
@@ -6064,11 +5340,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
@@ -6167,11 +5438,11 @@ build_enumerator (name, value)
   /* Now create a declaration for the enum value name.  */
 
   type = TREE_TYPE (value);
-  type = type_for_size (MAX (TYPE_PRECISION (type),
-                            TYPE_PRECISION (integer_type_node)),
-                       ((flag_traditional
-                         || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
-                        && TREE_UNSIGNED (type)));
+  type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+                                     TYPE_PRECISION (integer_type_node)),
+                                (TYPE_PRECISION (type)
+                                 >= TYPE_PRECISION (integer_type_node)
+                                 && TREE_UNSIGNED (type)));
 
   decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = convert (type, value);
@@ -6206,7 +5477,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;
 
@@ -6225,6 +5495,10 @@ start_function (declspecs, declarator, attributes)
 
   decl_attributes (&decl1, attributes, 0);
 
+  /* If #pragma weak was used, mark the decl weak now.  */
+  if (current_binding_level == global_binding_level)
+    maybe_apply_pragma_weak (decl1);
+
   if (DECL_DECLARED_INLINE_P (decl1)
       && DECL_UNINLINABLE (decl1)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
@@ -6269,27 +5543,16 @@ start_function (declspecs, declarator, attributes)
       current_function_prototype_line = DECL_SOURCE_LINE (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.  */
@@ -6308,7 +5571,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");
 
@@ -6391,7 +5654,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);
 
@@ -6399,12 +5661,10 @@ start_function (declspecs, declarator, attributes)
   /* Promote the value to int before returning it.  */
   if (c_promoting_integer_type_p (restype))
     {
-      /* It retains unsignedness if traditional
-        or if not really getting wider.  */
+      /* It retains unsignedness if not really getting wider.  */
       if (TREE_UNSIGNED (restype)
-         && (flag_traditional
-             || (TYPE_PRECISION (restype)
-                 == TYPE_PRECISION (integer_type_node))))
+         && (TYPE_PRECISION (restype)
+                 == TYPE_PRECISION (integer_type_node)))
        restype = unsigned_type_node;
       else
        restype = integer_type_node;
@@ -6423,16 +5683,6 @@ start_function (declspecs, declarator, attributes)
   
   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;
-}
 \f
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
@@ -6496,10 +5746,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;
        }
@@ -6623,15 +5873,6 @@ store_parm_decls ()
              layout_decl (found, 0);
            }
 
-         /* Traditionally, a parm declared float is actually a double.  */
-         if (found && flag_traditional
-             && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
-           {
-             TREE_TYPE (found) = double_type_node;
-             DECL_ARG_TYPE (found) = double_type_node;
-             layout_decl (found, 0);
-           }
-
          /* If no declaration found, default to int.  */
          if (!found)
            {
@@ -6765,11 +6006,7 @@ store_parm_decls ()
                             "prototype declaration");
                        }
                    }
-                 /* If -traditional, allow `int' argument to match
-                    `unsigned' prototype.  */
-                 else if (! (flag_traditional
-                             && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node
-                             && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))
+                 else
                    {
                      error ("argument `%s' doesn't match prototype",
                             IDENTIFIER_POINTER (DECL_NAME (parm)));
@@ -6881,32 +6118,43 @@ store_parm_decls ()
 
    This is called after parsing the body of the function definition.
 
-   NESTED is nonzero if the function being finished is nested in another.  */
+   NESTED is nonzero if the function being finished is nested in another.
+   CAN_DEFER_P is nonzero if the function may be deferred.  */
 
 void
-finish_function (nested)
+finish_function (nested, can_defer_p)
      int nested;
+     int can_defer_p;
 {
   tree fndecl = current_function_decl;
 
-/*  TREE_READONLY (fndecl) = 1;
-    This caused &foo to be of type ptr-to-const-function
-    which then got a warning when stored in a ptr-to-function variable.  */
+  /* 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.  */
 
   DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
 
-  /* Obey `register' declarations if `setjmp' is called in this fn.  */
-  if (flag_traditional && current_function_calls_setjmp)
-    {
-      setjmp_protect (DECL_INITIAL (fndecl));
-      setjmp_protect_args ();
-    }
-
   if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
@@ -6935,7 +6183,8 @@ finish_function (nested)
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
   /* Complain if there's just no return statement.  */
-  if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
+  if (warn_return_type
+      && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
       && !current_function_returns_value && !current_function_returns_null
       /* Don't complain if we abort.  */
       && !current_function_returns_abnormally
@@ -6943,9 +6192,9 @@ finish_function (nested)
       && !MAIN_NAME_P (DECL_NAME (fndecl))
       /* Or if they didn't actually specify a return type.  */
       && !C_FUNCTION_IMPLICIT_INT (fndecl)
-      /* If we have -Wreturn-type, let flow complain.  Unless we're an
+      /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
         inline function, as we might never be compiled separately.  */
-      && (!warn_return_type || DECL_INLINE (fndecl)))
+      && DECL_INLINE (fndecl))
     warning ("no return statement in function returning non-void");
 
   /* Clear out memory we no longer need.  */
@@ -6955,13 +6204,72 @@ finish_function (nested)
   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, 1);
+      /* 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
-        pop_c_function_context and then reset via pop_function_context.  */
+        c_pop_function_context and then reset via pop_function_context.  */
       current_function_decl = NULL;
     }
 }
@@ -6976,53 +6284,46 @@ c_expand_deferred_function (fndecl)
      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)
+c_expand_body_1 (fndecl, nested_p)
      tree fndecl;
-     int nested_p, can_defer_p;
+     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)
@@ -7038,6 +6339,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
   current_function_decl = fndecl;
   input_filename = DECL_SOURCE_FILE (fndecl);
   init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+  lineno = DECL_SOURCE_LINE (fndecl);
 
   /* This function is being processed in whole-function mode.  */
   cfun->x_whole_function_mode_p = 1;
@@ -7049,13 +6351,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)
@@ -7065,11 +6372,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
@@ -7096,7 +6398,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
@@ -7136,7 +6438,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
       /* Stop pointing to the local nodes about to be freed.
         But DECL_INITIAL must remain nonzero so we know this
         was an actual function definition.
-        For a nested function, this is done in pop_c_function_context.
+        For a nested function, this is done in c_pop_function_context.
         If rest_of_compilation set this to 0, leave it 0.  */
       if (DECL_INITIAL (fndecl) != 0)
        DECL_INITIAL (fndecl) = error_mark_node;
@@ -7167,6 +6469,15 @@ 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 (fndecl)
+     tree fndecl;
+{
+  c_expand_body_1 (fndecl, 0);
+}
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  */
@@ -7230,9 +6541,9 @@ check_for_loop_decls ()
    that keep track of the progress of compilation of the current function.
    Used for nested functions.  */
 
-struct c_language_function
+struct language_function GTY(())
 {
-  struct language_function base;
+  struct c_language_function base;
   tree named_labels;
   tree shadowed_labels;
   int returns_value;
@@ -7247,13 +6558,13 @@ struct c_language_function
    used during compilation of a C function.  */
 
 void
-push_c_function_context (f)
+c_push_function_context (f)
      struct function *f;
 {
-  struct c_language_function *p;
-  p = ((struct c_language_function *)
-       xmalloc (sizeof (struct c_language_function)));
-  f->language = (struct language_function *) p;
+  struct language_function *p;
+  p = ((struct language_function *)
+       ggc_alloc (sizeof (struct language_function)));
+  f->language = p;
 
   p->base.x_stmt_tree = c_stmt_tree;
   p->base.x_scope_stmt_stack = c_scope_stmt_stack;
@@ -7270,11 +6581,10 @@ push_c_function_context (f)
 /* Restore the variables used during compilation of a C function.  */
 
 void
-pop_c_function_context (f)
+c_pop_function_context (f)
      struct function *f;
 {
-  struct c_language_function *p
-    = (struct c_language_function *) f->language;
+  struct language_function *p = f->language;
   tree link;
 
   /* Bring back all the labels that were shadowed.  */
@@ -7304,32 +6614,13 @@ pop_c_function_context (f)
   current_extern_inline = p->extern_inline;
   current_binding_level = p->binding_level;
 
-  free (p);
-  f->language = 0;
-}
-
-/* Mark the language specific parts of F for GC.  */
-
-void
-mark_c_function_context (f)
-     struct function *f;
-{
-  struct c_language_function *p
-    = (struct c_language_function *) f->language;
-
-  if (p == 0)
-    return;
-
-  mark_c_language_function (&p->base);
-  ggc_mark_tree (p->shadowed_labels);
-  ggc_mark_tree (p->named_labels);
-  mark_binding_level (&p->binding_level);
+  f->language = NULL;
 }
 
-/* Copy the DECL_LANG_SPECIFIC data associated with NODE.  */
+/* Copy the DECL_LANG_SPECIFIC data associated with DECL.  */
 
 void
-copy_lang_decl (decl)
+c_dup_lang_specific_decl (decl)
      tree decl;
 {
   struct lang_decl *ld;
@@ -7343,38 +6634,12 @@ copy_lang_decl (decl)
   DECL_LANG_SPECIFIC (decl) = ld;
 }
 
-/* Mark the language specific bits in T for GC.  */
-
-void
-lang_mark_tree (t)
-     tree t;
-{
-  if (TREE_CODE (t) == IDENTIFIER_NODE)
-    {
-      struct lang_identifier *i = (struct lang_identifier *) t;
-      ggc_mark_tree (i->global_value);
-      ggc_mark_tree (i->local_value);
-      ggc_mark_tree (i->label_value);
-      ggc_mark_tree (i->implicit_decl);
-      ggc_mark_tree (i->error_locus);
-      ggc_mark_tree (i->limbo_value);
-    }
-  else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
-    ggc_mark (TYPE_LANG_SPECIFIC (t));
-  else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
-    {
-      ggc_mark (DECL_LANG_SPECIFIC (t));
-      c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
-      ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
-    }
-}
-
 /* The functions below are required for functionality of doing
    function at once processing in the C front end. Currently these
    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.  */
 
@@ -7446,17 +6711,26 @@ 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;
 {
-  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;
@@ -7483,3 +6757,26 @@ build_void_list_node ()
   tree t = build_tree_list (NULL_TREE, void_type_node);
   return t;
 }
+
+/* Return something to represent absolute declarators containing a *.
+   TARGET is the absolute declarator that the * contains.
+   TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
+   to apply to the pointer type, represented as identifiers, possible mixed
+   with attributes.
+
+   We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
+   if attributes are present) and whose type is the modifier list.  */
+
+tree
+make_pointer_declarator (type_quals_attrs, target)
+     tree type_quals_attrs, target;
+{
+  tree quals, attrs;
+  tree itarget = target;
+  split_specs_attrs (type_quals_attrs, &quals, &attrs);
+  if (attrs != NULL_TREE)
+    itarget = tree_cons (attrs, target, NULL_TREE);
+  return build1 (INDIRECT_REF, quals, itarget);
+}
+
+#include "gt-c-decl.h"