OSDN Git Service

* Makefile.am (gfor_helper_src): Split selected_kind.f90.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 0f76b88..7ef352e 100644 (file)
@@ -49,6 +49,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "timevar.h"
 #include "c-common.h"
 #include "c-pragma.h"
 #include "timevar.h"
 #include "c-common.h"
 #include "c-pragma.h"
+#include "langhooks.h"
+#include "tree-mudflap.h"
+#include "tree-gimple.h"
+#include "diagnostic.h"
+#include "tree-dump.h"
 #include "cgraph.h"
 #include "hashtab.h"
 #include "libfuncs.h"
 #include "cgraph.h"
 #include "hashtab.h"
 #include "libfuncs.h"
@@ -66,11 +71,14 @@ enum decl_context
 \f
 /* Nonzero if we have seen an invalid cross reference
    to a struct, union, or enum, but not yet printed the message.  */
 \f
 /* Nonzero if we have seen an invalid cross reference
    to a struct, union, or enum, but not yet printed the message.  */
-
 tree pending_invalid_xref;
 tree pending_invalid_xref;
+
 /* File and line to appear in the eventual error message.  */
 location_t pending_invalid_xref_location;
 
 /* File and line to appear in the eventual error message.  */
 location_t pending_invalid_xref_location;
 
+/* True means we've initialized exception handling.  */
+bool c_eh_initialized_p;
+
 /* While defining an enum type, this is 1 plus the last enumerator
    constant value.  Note that will do not have to save this or `enum_overflow'
    around nested function definition since such a definition could only
 /* While defining an enum type, this is 1 plus the last enumerator
    constant value.  Note that will do not have to save this or `enum_overflow'
    around nested function definition since such a definition could only
@@ -83,64 +91,40 @@ static tree enum_next_value;
 
 static int enum_overflow;
 
 
 static int enum_overflow;
 
-/* Parsing a function declarator leaves a list of parameter names
-   or a chain of parameter decls here.  */
-
-static tree last_function_parms;
-
-/* ... and a chain of structure and enum types declared in the
-   parmlist here.  */
-
-static tree last_function_parm_tags;
-
-/* ... and a chain of all non-parameter declarations (such as
-   CONST_DECLs from enumerations) here.  */
-
-static tree last_function_parm_others;
-
-/* After parsing the declarator that starts a function definition,
-   `start_function' puts the list of parameter names or chain of decls here
-   for `store_parm_decls' to find.  */
-
-static tree current_function_parms;
+/* These #defines are for clarity in working with the information block
+   returned by get_parm_info.  */
+#define ARG_INFO_PARMS(args)  TREE_PURPOSE(args)
+#define ARG_INFO_TAGS(args)   TREE_VALUE(args)
+#define ARG_INFO_TYPES(args)  TREE_CHAIN(args)
+#define ARG_INFO_OTHERS(args) TREE_TYPE(args)
 
 
-/* Similar, for last_function_parm_tags.  */
+/* The file and line that the prototype came from if this is an
+   old-style definition; used for diagnostics in
+   store_parm_decls_oldstyle.  */
 
 
-static tree current_function_parm_tags;
-
-/* And for last_function_parm_others.  */
+static location_t current_function_prototype_locus;
 
 
-static tree current_function_parm_others;
+/* The argument information structure for the function currently being
+   defined.  */
 
 
-/* Similar, for the file and line that the prototype came from if this is
-   an old-style definition.  */
-
-static location_t current_function_prototype_locus;
+static GTY(()) tree current_function_arg_info;
 
 /* The current statement tree.  */
 
 static GTY(()) struct stmt_tree_s c_stmt_tree;
 
 
 /* The current statement tree.  */
 
 static GTY(()) struct stmt_tree_s c_stmt_tree;
 
-/* The current scope statement stack.  */
-
-static GTY(()) tree c_scope_stmt_stack;
-
 /* State saving variables.  */
 /* State saving variables.  */
-int c_in_iteration_stmt;
-int c_in_case_stmt;
-
-/* 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;
-
-/* All the builtins; this is a subset of the entries of global_scope.  */
+tree c_break_label;
+tree c_cont_label;
 
 
-static GTY(()) tree first_builtin_decl;
-static GTY(()) tree last_builtin_decl;
+/* Linked list of TRANSLATION_UNIT_DECLS for the translation units
+   included in this invocation.  Note that the current translation
+   unit is not included in this list.  */
 
 
-/* A DECL for the current file-scope context.  */
+static GTY(()) tree all_translation_units;
 
 
-static GTY(()) tree current_file_decl;
+/* A list of decls to be made automatically visible in each file scope.  */
+static GTY(()) tree visible_builtins;
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
@@ -165,10 +149,110 @@ static int warn_about_return_type;
 /* Nonzero when starting a function declared `extern inline'.  */
 
 static int current_extern_inline;
 /* Nonzero when starting a function declared `extern inline'.  */
 
 static int current_extern_inline;
+
+/* True means global_bindings_p should return false even if the scope stack
+   says we are in file scope.  */
+bool c_override_global_bindings_to_false;
+
 \f
 \f
-/* Each c_scope structure describes the complete contents of one scope.
-   Three scopes are distinguished specially: the innermost or current
-   scope, the innermost function scope, and the outermost or file scope.
+/* Each c_binding structure describes one binding of an identifier to
+   a decl.  All the decls in a scope - irrespective of namespace - are
+   chained together by the ->prev field, which (as the name implies)
+   runs in reverse order.  All the decls in a given namespace bound to
+   a given identifier are chained by the ->shadowed field, which runs
+   from inner to outer scopes.
+
+   The ->decl field usually points to a DECL node, but there are two
+   exceptions.  In the namespace of type tags, the bound entity is a
+   RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node.  If an undeclared
+   identifier is encountered, it is bound to error_mark_node to
+   suppress further errors about that identifier in the current
+   function.
+
+   The ->type field stores the type of the declaration in this scope;
+   if NULL, the type is the type of the ->decl field.  This is only of
+   relevance for objects with external or internal linkage which may
+   be redeclared in inner scopes, forming composite types that only
+   persist for the duration of those scopes.  In the external scope,
+   this stores the composite of all the types declared for this
+   object, visible or not.  The ->inner_comp field (used only at file
+   scope) stores whether an incomplete array type at file scope was
+   completed at an inner scope to an array size other than 1.
+
+   The depth field is copied from the scope structure that holds this
+   decl.  It is used to preserve the proper ordering of the ->shadowed
+   field (see bind()) and also for a handful of special-case checks.
+   Finally, the invisible bit is true for a decl which should be
+   ignored for purposes of normal name lookup, and the nested bit is
+   true for a decl that's been bound a second time in an inner scope;
+   in all such cases, the binding in the outer scope will have its
+   invisible bit true.  */
+
+struct c_binding GTY((chain_next ("%h.prev")))
+{
+  tree decl;                   /* the decl bound */
+  tree type;                   /* the type in this scope */
+  tree id;                     /* the identifier it's bound to */
+  struct c_binding *prev;      /* the previous decl in this scope */
+  struct c_binding *shadowed;  /* the innermost decl shadowed by this one */
+  unsigned int depth : 28;      /* depth of this scope */
+  BOOL_BITFIELD invisible : 1;  /* normal lookup should ignore this binding */
+  BOOL_BITFIELD nested : 1;     /* do not set DECL_CONTEXT when popping */
+  BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
+  /* one free bit */
+};
+#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
+#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
+#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
+#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
+
+#define I_SYMBOL_BINDING(node) \
+  (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->symbol_binding)
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+#define I_TAG_BINDING(node) \
+  (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->tag_binding)
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+#define I_LABEL_BINDING(node) \
+  (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->label_binding)
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
+/* Each C symbol points to three linked lists of c_binding structures.
+   These describe the values of the identifier in the three different
+   namespaces defined by the language.  */
+
+struct lang_identifier GTY(())
+{
+  struct c_common_identifier common_id;
+  struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
+  struct c_binding *tag_binding;    /* struct/union/enum tags */
+  struct c_binding *label_binding;  /* labels */
+};
+
+/* Validate c-lang.c's assumptions.  */
+extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
+[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
+
+/* The resulting tree type.  */
+
+union lang_tree_node
+  GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+{
+  union tree_node GTY ((tag ("0"),
+                       desc ("tree_node_structure (&%h)")))
+    generic;
+  struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
+/* Each c_scope structure describes the complete contents of one
+   scope.  Four scopes are distinguished specially: the innermost or
+   current scope, the innermost function scope, the file scope (always
+   the second to outermost) and the outermost or external scope.
 
    Most declarations are recorded in the current scope.
 
 
    Most declarations are recorded in the current scope.
 
@@ -178,20 +262,39 @@ static int current_extern_inline;
    hence the 'innermost' qualifier.)  Explicitly declared labels
    (using the __label__ extension) appear in the current scope.
 
    hence the 'innermost' qualifier.)  Explicitly declared labels
    (using the __label__ extension) appear in the current scope.
 
-   Being in the global scope (current_scope == global_scope) causes
+   Being in the file scope (current_scope == file_scope) causes
    special behavior in several places below.  Also, under some
    conditions the Objective-C front end records declarations in the
    special behavior in several places below.  Also, under some
    conditions the Objective-C front end records declarations in the
-   global scope even though that isn't the current scope.
+   file scope even though that isn't the current scope.
 
 
-   The order of the names, parms, and blocks lists matters, and they
-   are frequently appended to.  To avoid having to walk all the way to
-   the end of the list on each insertion, or reverse the lists later,
-   we maintain a pointer to the last list entry for each of the lists.
+   All declarations with external linkage are recorded in the external
+   scope, even if they aren't visible there; this models the fact that
+   such declarations are visible to the entire program, and (with a
+   bit of cleverness, see pushdecl) allows diagnosis of some violations
+   of C99 6.2.2p7 and 6.2.7p2:
 
 
-   The order of the tags, shadowed, and shadowed_tags
-   lists does not matter, so we just prepend to these lists.  */
+     If, within the same translation unit, the same identifier appears
+     with both internal and external linkage, the behavior is
+     undefined.
 
 
-struct c_scope GTY(())
+     All declarations that refer to the same object or function shall
+     have compatible type; otherwise, the behavior is undefined.
+
+   Initially only the built-in declarations, which describe compiler
+   intrinsic functions plus a subset of the standard library, are in
+   this scope.
+
+   The order of the blocks list matters, and it is frequently appended
+   to.  To avoid having to walk all the way to the end of the list on
+   each insertion, or reverse the list later, we maintain a pointer to
+   the last list entry.  (FIXME: It should be feasible to use a reversed
+   list here.)
+
+   The bindings list is strictly in reverse order of declarations;
+   pop_scope relies on this.  */
+
+
+struct c_scope GTY((chain_next ("%h.outer")))
 {
   /* The scope containing this one.  */
   struct c_scope *outer;
 {
   /* The scope containing this one.  */
   struct c_scope *outer;
@@ -199,35 +302,18 @@ struct c_scope GTY(())
   /* The next outermost function scope.  */
   struct c_scope *outer_function;
 
   /* The next outermost function scope.  */
   struct c_scope *outer_function;
 
-  /* All variables, constants, functions, labels, and typedef names.  */
-  tree names;
-  tree names_last;
-
-  /* All parameter declarations.  Used only in the outermost scope of
-     a function.  */
-  tree parms;
-  tree parms_last;
-
-  /* All structure, union, and enum type tags.  */
-  tree tags;
-
-  /* For each scope, a list of shadowed outer-scope definitions
-     to be restored when this scope 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 scope, a list of shadowed outer-scope tag definitions
-     to be restored when this scope 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;
+  /* All bindings in this scope.  */
+  struct c_binding *bindings;
 
   /* For each scope (except the global one), a chain of BLOCK nodes
      for all the scopes that were entered and exited one level down.  */
   tree blocks;
   tree blocks_last;
 
 
   /* For each scope (except the global one), a chain of BLOCK nodes
      for all the scopes that were entered and exited one level down.  */
   tree blocks;
   tree blocks_last;
 
+  /* The depth of this scope.  Used to keep the ->shadowed chain of
+     bindings sorted innermost to outermost.  */
+  unsigned int depth : 28;
+
   /* True if we are currently filling this scope with parameter
      declarations.  */
   BOOL_BITFIELD parm_flag : 1;
   /* True if we are currently filling this scope with parameter
      declarations.  */
   BOOL_BITFIELD parm_flag : 1;
@@ -251,20 +337,28 @@ struct c_scope GTY(())
 
 static GTY(()) struct c_scope *current_scope;
 
 
 static GTY(()) struct c_scope *current_scope;
 
-/* A chain of c_scope structures awaiting reuse.  */
-
-static GTY((deletable (""))) struct c_scope *scope_freelist;
-
 /* The innermost function scope.  Ordinary (not explicitly declared)
    labels, bindings to error_mark_node, and the lazily-created
    bindings of __func__ and its friends get this scope.  */
 
 static GTY(()) struct c_scope *current_function_scope;
 
 /* The innermost function scope.  Ordinary (not explicitly declared)
    labels, bindings to error_mark_node, and the lazily-created
    bindings of __func__ and its friends get this scope.  */
 
 static GTY(()) struct c_scope *current_function_scope;
 
-/* The outermost scope, corresponding to the C "file scope".  This is
-   created when the compiler is started and exists through the entire run.  */
+/* The C file scope.  This is reset for each input translation unit.  */
+
+static GTY(()) struct c_scope *file_scope;
+
+/* The outermost scope.  This is used for all declarations with
+   external linkage, and only these, hence the name.  */
+
+static GTY(()) struct c_scope *external_scope;
+
+/* A chain of c_scope structures awaiting reuse.  */
+
+static GTY((deletable)) struct c_scope *scope_freelist;
 
 
-static GTY(()) struct c_scope *global_scope;
+/* A chain of c_binding structures awaiting reuse.  */
+
+static GTY((deletable)) struct c_binding *binding_freelist;
 
 /* Append VAR to LIST in scope SCOPE.  */
 #define SCOPE_LIST_APPEND(scope, list, decl) do {      \
 
 /* Append VAR to LIST in scope SCOPE.  */
 #define SCOPE_LIST_APPEND(scope, list, decl) do {      \
@@ -292,7 +386,7 @@ static GTY(()) struct c_scope *global_scope;
 
 static bool keep_next_level_flag;
 
 
 static bool keep_next_level_flag;
 
-/* True means the next call to pushlevel will be the outermost scope
+/* True means the next call to push_scope will be the outermost scope
    of a function body, so do not push a new scope, merely cease
    expecting parameter decls.  */
 
    of a function body, so do not push a new scope, merely cease
    expecting parameter decls.  */
 
@@ -300,32 +394,15 @@ static bool next_is_function_body;
 
 /* Functions called automatically at the beginning and end of execution.  */
 
 
 /* Functions called automatically at the beginning and end of execution.  */
 
-tree static_ctors, static_dtors;
+static GTY(()) tree static_ctors;
+static GTY(()) tree static_dtors;
 
 /* Forward declarations.  */
 
 /* Forward declarations.  */
-
-static struct c_scope *make_scope (void);
-static void pop_scope (void);
-static tree make_label (tree, location_t);
-static void bind_label (tree, tree, struct c_scope *);
-static void implicit_decl_warning (tree);
-static tree lookup_tag (enum tree_code, tree, int);
-static tree lookup_name_current_level (tree);
-static tree grokdeclarator (tree, tree, enum decl_context, int, tree *);
-static tree grokparms (tree, int);
-static void layout_array_type (tree);
-static void store_parm_decls_newstyle (void);
-static void store_parm_decls_oldstyle (void);
+static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (tree, int);
 static tree c_make_fname_decl (tree, int);
-static void c_expand_body_1 (tree, int);
-static tree any_external_decl (tree);
-static void record_external_decl (tree);
-static void warn_if_shadowing (tree, tree);
-static void check_bitfield_type_and_width (tree *, tree *, const char *);
-static void clone_underlying_type (tree);
-static bool flexible_array_type_p (tree);
-static hashval_t link_hash_hash        (const void *);
-static int link_hash_eq (const void *, const void *);
+static tree grokdeclarator (tree, tree, enum decl_context, bool, tree *);
+static tree grokparms (tree, bool);
+static void layout_array_type (tree);
 \f
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
 \f
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
@@ -342,9 +419,9 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 void
 c_print_identifier (FILE *file, tree node, int indent)
 {
 void
 c_print_identifier (FILE *file, tree node, int indent)
 {
-  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, "symbol", I_SYMBOL_DECL (node), indent + 4);
+  print_node (file, "tag", I_TAG_DECL (node), indent + 4);
+  print_node (file, "label", I_LABEL_DECL (node), indent + 4);
   if (C_IS_RESERVED_WORD (node))
     {
       tree rid = ridpointers[C_RID_CODE (node)];
   if (C_IS_RESERVED_WORD (node))
     {
       tree rid = ridpointers[C_RID_CODE (node)];
@@ -353,6 +430,82 @@ c_print_identifier (FILE *file, tree node, int indent)
               (void *) rid, IDENTIFIER_POINTER (rid));
     }
 }
               (void *) rid, IDENTIFIER_POINTER (rid));
     }
 }
+
+/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
+   which may be any of several kinds of DECL or TYPE or error_mark_node,
+   in the scope SCOPE.  */
+static void
+bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
+{
+  struct c_binding *b, **here;
+
+  if (binding_freelist)
+    {
+      b = binding_freelist;
+      binding_freelist = b->prev;
+    }
+  else
+    b = GGC_NEW (struct c_binding);
+
+  b->shadowed = 0;
+  b->decl = decl;
+  b->id = name;
+  b->depth = scope->depth;
+  b->invisible = invisible;
+  b->nested = nested;
+  b->inner_comp = 0;
+
+  b->type = 0;
+
+  b->prev = scope->bindings;
+  scope->bindings = b;
+
+  if (!name)
+    return;
+
+  switch (TREE_CODE (decl))
+    {
+    case LABEL_DECL:     here = &I_LABEL_BINDING (name);   break;
+    case ENUMERAL_TYPE:
+    case UNION_TYPE:
+    case RECORD_TYPE:    here = &I_TAG_BINDING (name);     break;
+    case VAR_DECL:
+    case FUNCTION_DECL:
+    case TYPE_DECL:
+    case CONST_DECL:
+    case PARM_DECL:
+    case ERROR_MARK:     here = &I_SYMBOL_BINDING (name);  break;
+
+    default:
+      abort ();
+    }
+
+  /* Locate the appropriate place in the chain of shadowed decls
+     to insert this binding.  Normally, scope == current_scope and
+     this does nothing.  */
+  while (*here && (*here)->depth > scope->depth)
+    here = &(*here)->shadowed;
+
+  b->shadowed = *here;
+  *here = b;
+}
+
+/* Clear the binding structure B, stick it on the binding_freelist,
+   and return the former value of b->prev.  This is used by pop_scope
+   and get_parm_info to iterate destructively over all the bindings
+   from a given scope.  */
+static struct c_binding *
+free_binding_and_advance (struct c_binding *b)
+{
+  struct c_binding *prev = b->prev;
+
+  memset (b, 0, sizeof (struct c_binding));
+  b->prev = binding_freelist;
+  binding_freelist = b;
+
+  return prev;
+}
+
 \f
 /* Hook called at end of compilation to assume 1 elt
    for a file-scope tentative array defn that wasn't complete before.  */
 \f
 /* Hook called at end of compilation to assume 1 elt
    for a file-scope tentative array defn that wasn't complete before.  */
@@ -377,40 +530,6 @@ c_finish_incomplete_decl (tree decl)
     }
 }
 \f
     }
 }
 \f
-/* Reuse or create a struct for this scope.  */
-
-static struct c_scope *
-make_scope (void)
-{
-  struct c_scope *result;
-  if (scope_freelist)
-    {
-      result = scope_freelist;
-      scope_freelist = result->outer;
-    }
-  else
-    result = ggc_alloc_cleared (sizeof (struct c_scope));
-
-  return result;
-}
-
-/* Remove the topmost scope from the stack and add it to the
-   free list, updating current_function_scope if necessary.  */
-
-static void
-pop_scope (void)
-{
-  struct c_scope *scope = current_scope;
-
-  current_scope = scope->outer;
-  if (scope->function_body)
-    current_function_scope = scope->outer_function;
-
-  memset (scope, 0, sizeof (struct c_scope));
-  scope->outer = scope_freelist;
-  scope_freelist = scope;
-}
-
 /* The Objective-C front-end often needs to determine the current scope.  */
 
 void *
 /* The Objective-C front-end often needs to determine the current scope.  */
 
 void *
@@ -426,30 +545,35 @@ void
 objc_mark_locals_volatile (void *enclosing_blk)
 {
   struct c_scope *scope;
 objc_mark_locals_volatile (void *enclosing_blk)
 {
   struct c_scope *scope;
+  struct c_binding *b;
 
   for (scope = current_scope;
        scope && scope != enclosing_blk;
        scope = scope->outer)
     {
 
   for (scope = current_scope;
        scope && scope != enclosing_blk;
        scope = scope->outer)
     {
-      tree decl;
-
-      for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
+      for (b = scope->bindings; b; b = b->prev)
        {
        {
-         DECL_REGISTER (decl) = 0;
-         TREE_THIS_VOLATILE (decl) = 1;
+         if (TREE_CODE (b->decl) == VAR_DECL
+             || TREE_CODE (b->decl) == PARM_DECL)
+           {
+             C_DECL_REGISTER (b->decl) = 0;
+             DECL_REGISTER (b->decl) = 0;
+             TREE_THIS_VOLATILE (b->decl) = 1;
+           }
        }
        }
+
       /* Do not climb up past the current function.  */
       if (scope->function_body)
        break;
     }
 }
 
       /* Do not climb up past the current function.  */
       if (scope->function_body)
        break;
     }
 }
 
-/* Nonzero if we are currently in the global scope.  */
+/* Nonzero if we are currently in file scope.  */
 
 int
 global_bindings_p (void)
 {
 
 int
 global_bindings_p (void)
 {
-  return current_scope == global_scope;
+  return current_scope == file_scope && !c_override_global_bindings_to_false;
 }
 
 void
 }
 
 void
@@ -466,19 +590,8 @@ declare_parm_level (void)
   current_scope->parm_flag = true;
 }
 
   current_scope->parm_flag = true;
 }
 
-/* Nonzero if currently making parm declarations.  */
-
-int
-in_parm_level_p (void)
-{
-  return current_scope->parm_flag;
-}
-
-/* Enter a new scope.  The dummy parameter is for signature
-   compatibility with lang_hooks.decls.pushlevel.  */
-
 void
 void
-pushlevel (int dummy ATTRIBUTE_UNUSED)
+push_scope (void)
 {
   if (next_is_function_body)
     {
 {
   if (next_is_function_body)
     {
@@ -503,49 +616,56 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
     }
   else
     {
     }
   else
     {
-      struct c_scope *scope = make_scope ();
+      struct c_scope *scope;
+      if (scope_freelist)
+       {
+         scope = scope_freelist;
+         scope_freelist = scope->outer;
+       }
+      else
+       scope = GGC_CNEW (struct c_scope);
 
       scope->keep          = keep_next_level_flag;
       scope->outer         = current_scope;
 
       scope->keep          = keep_next_level_flag;
       scope->outer         = current_scope;
+      scope->depth        = current_scope ? (current_scope->depth + 1) : 0;
+
+      /* Check for scope depth overflow.  Unlikely (2^28 == 268,435,456) but
+        possible.  */
+      if (current_scope && scope->depth == 0)
+       {
+         scope->depth--;
+         sorry ("GCC supports only %u nested scopes\n", scope->depth);
+       }
+
       current_scope        = scope;
       keep_next_level_flag = false;
     }
 }
 
       current_scope        = scope;
       keep_next_level_flag = false;
     }
 }
 
-/* Exit a scope.  Restore the state of the identifier-decl mappings
-   that were in effect when this scope was entered.
-
-   If KEEP is KEEP_YES (1), this scope had explicit declarations, so
-   create a BLOCK node to record its declarations and subblocks for
-   debugging output.  If KEEP is KEEP_MAYBE, do so only if the names
-   or tags lists are nonempty.
-
-   The second parameter is ignored; it is present only for
-   signature compatibility with lang_hooks.decls.poplevel.
+/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT.  */
 
 
-   If FUNCTIONBODY is nonzero, this level is the body of a function,
-   even if current_scope->function_body is not set.  This is used
-   by language-independent code that generates synthetic functions,
-   and cannot set current_scope->function_body.
+static void
+set_type_context (tree type, tree context)
+{
+  for (type = TYPE_MAIN_VARIANT (type); type;
+       type = TYPE_NEXT_VARIANT (type))
+    TYPE_CONTEXT (type) = context;
+}
 
 
-   FIXME: Eliminate the need for all arguments.  */
+/* Exit a scope.  Restore the state of the identifier-decl mappings
+   that were in effect when this scope was entered.  Return a BLOCK
+   node containing all the DECLs in this scope that are of interest
+   to debug info generation.  */
 
 tree
 
 tree
-poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
+pop_scope (void)
 {
   struct c_scope *scope = current_scope;
 {
   struct c_scope *scope = current_scope;
-  tree block;
-  tree decl;
-  tree p;
-
-  /* The following line does not use |= due to a bug in HP's C compiler.  */
-  scope->function_body = scope->function_body | functionbody;
+  tree block, context, p;
+  struct c_binding *b;
 
 
-  if (keep == KEEP_MAYBE)
-    keep = (scope->names || scope->tags);
-
-  keep |= scope->keep;
-  keep |= scope->function_body;
+  bool functionbody = scope->function_body;
+  bool keep = functionbody || scope->keep || scope->bindings;
 
   /* If appropriate, create a BLOCK to record the decls for the life
      of this function.  */
 
   /* If appropriate, create a BLOCK to record the decls for the life
      of this function.  */
@@ -553,28 +673,49 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
   if (keep)
     {
       block = make_node (BLOCK);
   if (keep)
     {
       block = make_node (BLOCK);
-      BLOCK_VARS (block) = scope->names;
       BLOCK_SUBBLOCKS (block) = scope->blocks;
       TREE_USED (block) = 1;
       BLOCK_SUBBLOCKS (block) = scope->blocks;
       TREE_USED (block) = 1;
-    }
 
 
-  /* In each subblock, record that this is its superior.  */
-  for (p = scope->blocks; p; p = TREE_CHAIN (p))
-    BLOCK_SUPERCONTEXT (p) = block;
+      /* In each subblock, record that this is its superior.  */
+      for (p = scope->blocks; p; p = TREE_CHAIN (p))
+       BLOCK_SUPERCONTEXT (p) = block;
 
 
-  /* Clear out the variable bindings in this scope.
+      BLOCK_VARS (block) = 0;
+    }
 
 
-     Propagate TREE_ADDRESSABLE from nested functions to their
-     containing functions.
+  /* The TYPE_CONTEXTs for all of the tagged types belonging to this
+     scope must be set 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.
 
 
-     Issue warnings for unused variables and labels, and errors for
-     undefined labels, if there are any.  */
+     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 (scope->function_body)
+    context = current_function_decl;
+  else if (scope == file_scope)
+    {
+      tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
+      TREE_CHAIN (file_decl) = all_translation_units;
+      all_translation_units = file_decl;
+      context = file_decl;
+    }
+  else
+    context = block;
 
 
-  for (p = scope->names; p; p = TREE_CHAIN (p))
+  /* Clear all bindings in this scope.  */
+  for (b = scope->bindings; b; b = free_binding_and_advance (b))
     {
     {
+      p = b->decl;
       switch (TREE_CODE (p))
        {
        case LABEL_DECL:
       switch (TREE_CODE (p))
        {
        case LABEL_DECL:
+         /* Warnings for unused labels, errors for undefined labels.  */
          if (TREE_USED (p) && !DECL_INITIAL (p))
            {
              error ("%Jlabel `%D' used but not defined", p, p);
          if (TREE_USED (p) && !DECL_INITIAL (p))
            {
              error ("%Jlabel `%D' used but not defined", p, p);
@@ -587,94 +728,118 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
              else
                warning ("%Jlabel `%D' declared but not defined", p, p);
            }
              else
                warning ("%Jlabel `%D' declared but not defined", p, p);
            }
+         /* Labels go in BLOCK_VARS.  */
+         TREE_CHAIN (p) = BLOCK_VARS (block);
+         BLOCK_VARS (block) = p;
 
 
-         IDENTIFIER_LABEL_VALUE (DECL_NAME (p)) = 0;
-         break;
+#ifdef ENABLE_CHECKING
+         if (I_LABEL_BINDING (b->id) != b) abort ();
+#endif
+         I_LABEL_BINDING (b->id) = b->shadowed;
+         break;
+
+       case ENUMERAL_TYPE:
+       case UNION_TYPE:
+       case RECORD_TYPE:
+         set_type_context (p, context);
+
+         /* Types may not have tag-names, in which case the type
+            appears in the bindings list with b->id NULL.  */
+         if (b->id)
+           {
+#ifdef ENABLE_CHECKING
+             if (I_TAG_BINDING (b->id) != b) abort ();
+#endif
+             I_TAG_BINDING (b->id) = b->shadowed;
+           }
+         break;
 
        case FUNCTION_DECL:
 
        case FUNCTION_DECL:
+         /* Propagate TREE_ADDRESSABLE from nested functions to their
+            containing functions.  */
          if (! TREE_ASM_WRITTEN (p)
              && DECL_INITIAL (p) != 0
              && TREE_ADDRESSABLE (p)
              && DECL_ABSTRACT_ORIGIN (p) != 0
              && DECL_ABSTRACT_ORIGIN (p) != p)
            TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
          if (! TREE_ASM_WRITTEN (p)
              && DECL_INITIAL (p) != 0
              && TREE_ADDRESSABLE (p)
              && DECL_ABSTRACT_ORIGIN (p) != 0
              && DECL_ABSTRACT_ORIGIN (p) != p)
            TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
-         goto normal;
+         goto common_symbol;
 
        case VAR_DECL:
 
        case VAR_DECL:
-         /* Keep this in sync with stmt.c:warn_about_unused_variables.
-            No warnings when the global scope is popped because the
-            global scope isn't popped for the last translation unit,
-            so the warnings are done in c_write_global_declaration.  */
-         if (warn_unused_variable && scope != global_scope
+         /* Warnings for unused variables.  */
+         if (warn_unused_variable
              && !TREE_USED (p)
              && !DECL_IN_SYSTEM_HEADER (p)
              && DECL_NAME (p)
              && !TREE_USED (p)
              && !DECL_IN_SYSTEM_HEADER (p)
              && DECL_NAME (p)
-             && !DECL_ARTIFICIAL (p))
+             && !DECL_ARTIFICIAL (p)
+             && (scope != file_scope
+                 || (TREE_STATIC (p) && !TREE_PUBLIC (p)
+                     && !TREE_THIS_VOLATILE (p)))
+             && scope != external_scope)
            warning ("%Junused variable `%D'", p, p);
            warning ("%Junused variable `%D'", p, p);
-         /* fall through */
 
 
-       default:
-       normal:
-         if (DECL_NAME (p))
+         if (b->inner_comp)
            {
            {
-             if (DECL_EXTERNAL (p) && scope != global_scope)
-               /* External decls stay in the symbol-value slot but are
-                  inaccessible.  */
-               C_DECL_INVISIBLE (p) = 1;
-             else
-               IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
+             error ("%Jtype of array %qD completed incompatibly with"
+                    " implicit initialization", p, p);
            }
            }
-         break;
-       }
-    }
-
-  /* Clear out the parameter bindings in this scope, if any.
-     Unused-parameter warnings are handled by function.c.  */
-  for (p = scope->parms; p; p = TREE_CHAIN (p))
-    if (DECL_NAME (p))
-      IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
 
 
-  /* Clear out the tag-meanings declared in this scope.
-
-     Set the TYPE_CONTEXTs for all of the tagged types belonging to
-     this scope 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.
+         /* Fall through.  */
+       case TYPE_DECL:
+       case CONST_DECL:
+       common_symbol:
+         /* All of these go in BLOCK_VARS, but only if this is the
+            binding in the home scope.  */
+         if (!b->nested)
+           {
+             TREE_CHAIN (p) = BLOCK_VARS (block);
+             BLOCK_VARS (block) = p;
+           }
+         /* If this is the file scope, and we are processing more
+            than one translation unit in this compilation, set
+            DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
+            This makes same_translation_unit_p work, and causes
+            static declarations to be given disambiguating suffixes.  */
+         if (scope == file_scope && num_in_fnames > 1)
+           {
+             DECL_CONTEXT (p) = context;
+             if (TREE_CODE (p) == TYPE_DECL)
+               set_type_context (TREE_TYPE (p), context);
+           }
 
 
-     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.  */
+         /* Fall through.  */
+         /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
+            already been put there by store_parm_decls.  Unused-
+            parameter warnings are handled by function.c.
+            error_mark_node obviously does not go in BLOCK_VARS and
+            does not get unused-variable warnings.  */
+       case PARM_DECL:
+       case ERROR_MARK:
+         /* It is possible for a decl not to have a name.  We get
+            here with b->id NULL in this case.  */
+         if (b->id)
+           {
+#ifdef ENABLE_CHECKING
+             if (I_SYMBOL_BINDING (b->id) != b) abort ();
+#endif
+             I_SYMBOL_BINDING (b->id) = b->shadowed;
+             if (b->shadowed && b->shadowed->type)
+               TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
+           }
+         break;
 
 
-  decl = scope->function_body ? current_function_decl : block;
-  for (p = scope->tags; p; p = TREE_CHAIN (p))
-    {
-      if (TREE_PURPOSE (p))
-       IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0;
-      if (decl)
-       TYPE_CONTEXT (TREE_VALUE (p)) = decl;
+       default:
+         abort ();
+       }
     }
 
     }
 
-  /* Restore all name- and label-meanings from outer scopes that were
-     shadowed by this scope.  */
-  for (p = scope->shadowed; p; p = TREE_CHAIN (p))
-    if (TREE_VALUE (p) && TREE_CODE (TREE_VALUE (p)) == LABEL_DECL)
-      IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
-    else
-      IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
-
-  /* Restore all tag-meanings from outer scopes that were shadowed by
-     this scope.  */
-  for (p = scope->shadowed_tags; p; p = TREE_CHAIN (p))
-    IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
 
   /* Dispose of the block that we just made inside some higher level.  */
 
   /* Dispose of the block that we just made inside some higher level.  */
-  if (scope->function_body && current_function_decl)
-    DECL_INITIAL (current_function_decl) = block;
+  if ((scope->function_body || scope == file_scope) && context)
+    {
+      DECL_INITIAL (context) = block;
+      BLOCK_SUPERCONTEXT (block) = context;
+    }
   else if (scope->outer)
     {
       if (block)
   else if (scope->outer)
     {
       if (block)
@@ -687,11 +852,62 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
     }
 
   /* Pop the current scope, and free the structure for reuse.  */
     }
 
   /* Pop the current scope, and free the structure for reuse.  */
-  pop_scope ();
+  current_scope = scope->outer;
+  if (scope->function_body)
+    current_function_scope = scope->outer_function;
+
+  memset (scope, 0, sizeof (struct c_scope));
+  scope->outer = scope_freelist;
+  scope_freelist = scope;
 
   return block;
 }
 
 
   return block;
 }
 
+void
+push_file_scope (void)
+{
+  tree decl;
+
+  if (file_scope)
+    return;
+
+  push_scope ();
+  file_scope = current_scope;
+
+  start_fname_decls ();
+
+  for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
+    bind (DECL_NAME (decl), decl, file_scope,
+         /*invisible=*/false, /*nested=*/true);
+}
+
+void
+pop_file_scope (void)
+{
+  /* In case there were missing closebraces, get us back to the global
+     binding level.  */
+  while (current_scope != file_scope)
+    pop_scope ();
+
+  /* __FUNCTION__ is defined at file scope ("").  This
+     call may not be necessary as my tests indicate it
+     still works without it.  */
+  finish_fname_decls ();
+
+  /* This is the point to write out a PCH if we're doing that.
+     In that case we do not want to do anything else.  */
+  if (pch_file)
+    {
+      c_common_write_pch ();
+      return;
+    }
+
+  /* Pop off the file scope and close this translation unit.  */
+  pop_scope ();
+  file_scope = 0;
+  cgraph_finalize_compilation_unit ();
+}
+
 /* Insert BLOCK at the end of the list of subblocks of the current
    scope.  This is used when a BIND_EXPR is expanded, to handle the
    BLOCK node inside the BIND_EXPR.  */
 /* Insert BLOCK at the end of the list of subblocks of the current
    scope.  This is used when a BIND_EXPR is expanded, to handle the
    BLOCK node inside the BIND_EXPR.  */
@@ -702,15 +918,6 @@ insert_block (tree block)
   TREE_USED (block) = 1;
   SCOPE_LIST_APPEND (current_scope, blocks, block);
 }
   TREE_USED (block) = 1;
   SCOPE_LIST_APPEND (current_scope, blocks, block);
 }
-
-/* 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 (tree block ATTRIBUTE_UNUSED)
-{
-}
 \f
 /* Push a definition or a declaration of struct, union or enum tag "name".
    "type" should be the type node.
 \f
 /* Push a definition or a declaration of struct, union or enum tag "name".
    "type" should be the type node.
@@ -719,24 +926,13 @@ set_block (tree block ATTRIBUTE_UNUSED)
    Note that the definition may really be just a forward reference.
    In that case, the TYPE_SIZE will be zero.  */
 
    Note that the definition may really be just a forward reference.
    In that case, the TYPE_SIZE will be zero.  */
 
-void
+static void
 pushtag (tree name, tree type)
 {
 pushtag (tree name, tree type)
 {
-  struct c_scope *b = current_scope;
-
   /* Record the identifier as the type's name if it has none.  */
   /* Record the identifier as the type's name if it has none.  */
-  if (name)
-    {
-      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);
+  if (name && !TYPE_NAME (type))
+    TYPE_NAME (type) = name;
+  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
 
   /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
      tagged type we just added to the current scope.  This fake
 
   /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
      tagged type we just added to the current scope.  This fake
@@ -748,7 +944,7 @@ pushtag (tree name, tree type)
   TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
 
   /* An approximation for now, so we can tell this is a function-scope tag.
   TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
 
   /* An approximation for now, so we can tell this is a function-scope tag.
-     This will be updated in poplevel.  */
+     This will be updated in pop_scope.  */
   TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
 }
 \f
   TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
 }
 \f
@@ -802,7 +998,7 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
   tree t;
 
   if (TREE_CODE (olddecl) != FUNCTION_DECL
   tree t;
 
   if (TREE_CODE (olddecl) != FUNCTION_DECL
-      || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), COMPARE_STRICT)
+      || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
       || !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
           ||
           (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
       || !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
           ||
           (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
@@ -874,7 +1070,7 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
 
       /* Type for passing arg must be consistent with that declared
         for the arg.  */
 
       /* Type for passing arg must be consistent with that declared
         for the arg.  */
-      else if (! comptypes (oldargtype, newargtype, COMPARE_STRICT))
+      else if (! comptypes (oldargtype, newargtype))
        {
          error ("%Jprototype for '%D' declares arg %d with incompatible type",
                 newdecl, newdecl, i);
        {
          error ("%Jprototype for '%D' declares arg %d with incompatible type",
                 newdecl, newdecl, i);
@@ -939,8 +1135,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
      unless OLDDECL is a builtin.  OLDDECL will be discarded in any case.  */
   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
      unless OLDDECL is a builtin.  OLDDECL will be discarded in any case.  */
   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
-      if (TREE_CODE (olddecl) != FUNCTION_DECL
-          || !DECL_BUILT_IN (olddecl) || !C_DECL_INVISIBLE (olddecl))
+      if (!(TREE_CODE (olddecl) == FUNCTION_DECL
+           && DECL_BUILT_IN (olddecl)
+           && !C_DECL_DECLARED_BUILTIN (olddecl)))
        {
          error ("%J'%D' redeclared as different kind of symbol",
                 newdecl, newdecl);
        {
          error ("%J'%D' redeclared as different kind of symbol",
                 newdecl, newdecl);
@@ -950,21 +1147,21 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        warning ("%Jbuilt-in function '%D' declared as non-function",
                 newdecl, newdecl);
       else if (warn_shadow)
        warning ("%Jbuilt-in function '%D' declared as non-function",
                 newdecl, newdecl);
       else if (warn_shadow)
-       warning ("%Jshadowing built-in function '%D'",
+       warning ("%Jdeclaration of '%D' shadows a built-in function",
                 newdecl, newdecl);
       return false;
     }
 
                 newdecl, newdecl);
       return false;
     }
 
-  if (!comptypes (oldtype, newtype, COMPARE_STRICT))
+  if (!comptypes (oldtype, newtype))
     {
       if (TREE_CODE (olddecl) == FUNCTION_DECL
     {
       if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && DECL_BUILT_IN (olddecl) && C_DECL_INVISIBLE (olddecl))
+         && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
        {
          /* Accept harmless mismatch in function types.
             This is for the ffs and fprintf builtins.  */
          tree trytype = match_builtin_function_types (newtype, oldtype);
 
        {
          /* Accept harmless mismatch in function types.
             This is for the ffs and fprintf builtins.  */
          tree trytype = match_builtin_function_types (newtype, oldtype);
 
-         if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
+         if (trytype && comptypes (newtype, trytype))
            *oldtypep = oldtype = trytype;
          else
            {
            *oldtypep = oldtype = trytype;
          else
            {
@@ -977,7 +1174,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
            }
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
            }
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
-              && DECL_SOURCE_LINE (olddecl) == 0)
+              && DECL_IS_BUILTIN (olddecl))
        {
          /* A conflicting function declaration for a predeclared
             function that isn't actually built in.  Objective C uses
        {
          /* A conflicting function declaration for a predeclared
             function that isn't actually built in.  Objective C uses
@@ -1003,7 +1200,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        }
       else
        {
        }
       else
        {
-         error ("%Jconflicting types for '%D'", newdecl, newdecl);
+         if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
+           error ("%J conflicting type qualifiers for '%D'", newdecl, newdecl);
+         else
+           error ("%Jconflicting types for '%D'", newdecl, newdecl);
          diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
          locate_old_decl (olddecl, error);
          return false;
          diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
          locate_old_decl (olddecl, error);
          return false;
@@ -1016,8 +1216,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
       if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
       if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
-       return true;  /* allow OLDDECL to continue in use */
-      
+       return true;  /* Allow OLDDECL to continue in use.  */
+
       error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
       locate_old_decl (olddecl, error);
       return false;
       error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
       locate_old_decl (olddecl, error);
       return false;
@@ -1036,24 +1236,26 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
         can't validate the argument list) the built-in definition is
         overridden, but optionally warn this was a bad choice of name.  */
       if (DECL_BUILT_IN (olddecl)
         can't validate the argument list) the built-in definition is
         overridden, but optionally warn this was a bad choice of name.  */
       if (DECL_BUILT_IN (olddecl)
-         && C_DECL_INVISIBLE (olddecl)
+         && !C_DECL_DECLARED_BUILTIN (olddecl)
          && (!TREE_PUBLIC (newdecl)
              || (DECL_INITIAL (newdecl)
                  && !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
        {
          if (warn_shadow)
          && (!TREE_PUBLIC (newdecl)
              || (DECL_INITIAL (newdecl)
                  && !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
        {
          if (warn_shadow)
-           warning ("%Jshadowing built-in function '%D'", newdecl, newdecl);
+           warning ("%Jdeclaration of '%D' shadows a built-in function",
+                    newdecl, newdecl);
          /* Discard the old built-in function.  */
          return false;
        }
          /* Discard the old built-in function.  */
          return false;
        }
-      
+
       if (DECL_INITIAL (newdecl))
        {
          if (DECL_INITIAL (olddecl)
              && !(DECL_DECLARED_INLINE_P (olddecl)
                   && DECL_EXTERNAL (olddecl)
                   && !(DECL_DECLARED_INLINE_P (newdecl)
       if (DECL_INITIAL (newdecl))
        {
          if (DECL_INITIAL (olddecl)
              && !(DECL_DECLARED_INLINE_P (olddecl)
                   && DECL_EXTERNAL (olddecl)
                   && !(DECL_DECLARED_INLINE_P (newdecl)
-                       && DECL_EXTERNAL (newdecl))))
+                       && DECL_EXTERNAL (newdecl)
+                       && same_translation_unit_p (olddecl, newdecl))))
            {
              error ("%Jredefinition of '%D'", newdecl, newdecl);
              locate_old_decl (olddecl, error);
            {
              error ("%Jredefinition of '%D'", newdecl, newdecl);
              locate_old_decl (olddecl, error);
@@ -1070,33 +1272,47 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          locate_old_decl (olddecl, error);
          return false;
        }
          locate_old_decl (olddecl, error);
          return false;
        }
-      /* Mismatched non-static and static is considered poor style.
-         We only diagnose static then non-static if -Wtraditional,
-        because it is the most convenient way to get some effects
-        (see e.g.  what unwind-dw2-fde-glibc.c does to the definition
-        of _Unwind_Find_FDE in unwind-dw2-fde.c).  Revisit?  */
+      /* A non-static declaration (even an "extern") followed by a
+        static declaration is undefined behavior per C99 6.2.2p3-5,7.
+        The same is true for a static forward declaration at block
+        scope followed by a non-static declaration/definition at file
+        scope.  Static followed by non-static at the same scope is
+        not undefined behavior, and is the most convenient way to get
+        some effects (see e.g.  what unwind-dw2-fde-glibc.c does to
+        the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but
+        we do diagnose it if -Wtraditional. */
       if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
        {
       if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
        {
-         /* A static function declaration for a predeclared function
-            that isn't actually built in, silently overrides the
-            default.  Objective C uses these.  See also above.
-            FIXME: Make Objective C use normal builtins.  */
-         if (TREE_CODE (olddecl) == FUNCTION_DECL
-             && DECL_SOURCE_LINE (olddecl) == 0)
-           return false;
-         else
+         /* Two exceptions to the rule.  If olddecl is an extern
+            inline, or a predeclared function that isn't actually
+            built in, newdecl silently overrides olddecl.  The latter
+            occur only in Objective C; see also above.  (FIXME: Make
+            Objective C use normal builtins.)  */
+         if (!DECL_IS_BUILTIN (olddecl)
+             && !(DECL_EXTERNAL (olddecl)
+                  && DECL_DECLARED_INLINE_P (olddecl)))
            {
            {
-             warning ("%Jstatic declaration of '%D' follows "
-                      "non-static declaration", newdecl, newdecl);
-             warned = true;
+             error ("%Jstatic declaration of '%D' follows "
+                    "non-static declaration", newdecl, newdecl);
+             locate_old_decl (olddecl, error);
            }
            }
+         return false;
        }
        }
-      else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)
-              && warn_traditional)
+      else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl))
        {
        {
-         warning ("%Jnon-static declaration of '%D' follows "
-                  "static declaration", newdecl, newdecl);
-         warned = true;
+         if (DECL_CONTEXT (olddecl))
+           {
+             error ("%Jnon-static declaration of '%D' follows "
+                    "static declaration", newdecl, newdecl);
+             locate_old_decl (olddecl, error);
+             return false;
+           }
+         else if (warn_traditional)
+           {
+             warning ("%Jnon-static declaration of '%D' follows "
+                      "static declaration", newdecl, newdecl);
+             warned = true;
+           }
        }
     }
   else if (TREE_CODE (newdecl) == VAR_DECL)
        }
     }
   else if (TREE_CODE (newdecl) == VAR_DECL)
@@ -1124,13 +1340,34 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          return false;
        }
 
          return false;
        }
 
-      /* Objects declared at file scope: if at least one is 'extern',
-        it's fine (6.2.2p4); otherwise the linkage must agree (6.2.2p7).  */
-      if (DECL_FILE_SCOPE_P (newdecl))
+      /* Objects declared at file scope: if the first declaration had
+        external linkage (even if it was an external reference) the
+        second must have external linkage as well, or the behavior is
+        undefined.  If the first declaration had internal linkage, then
+        the second must too, or else be an external reference (in which
+        case the composite declaration still has internal linkage).
+        As for function declarations, we warn about the static-then-
+        extern case only for -Wtraditional.  See generally 6.2.2p3-5,7.  */
+      if (DECL_FILE_SCOPE_P (newdecl)
+         && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
        {
        {
-         if (!DECL_EXTERNAL (newdecl)
-             && !DECL_EXTERNAL (olddecl)
-             && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
+         if (DECL_EXTERNAL (newdecl))
+           {
+             if (!DECL_FILE_SCOPE_P (olddecl))
+               {
+                 error ("%Jextern declaration of %qD follows "
+                        "declaration with no linkage", newdecl, newdecl);
+                 locate_old_decl (olddecl, error);
+                 return false;
+               }
+             else if (warn_traditional)
+               {
+                 warning ("%Jnon-static declaration of '%D' follows "
+                          "static declaration", newdecl, newdecl);
+                 warned = true;
+               }
+           }
+         else
            {
              if (TREE_PUBLIC (newdecl))
                error ("%Jnon-static declaration of '%D' follows "
            {
              if (TREE_PUBLIC (newdecl))
                error ("%Jnon-static declaration of '%D' follows "
@@ -1145,28 +1382,33 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        }
       /* Two objects with the same name declared at the same block
         scope must both be external references (6.7p3).  */
        }
       /* Two objects with the same name declared at the same block
         scope must both be external references (6.7p3).  */
-      else if (DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)
-              && (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl)))
+      else if (!DECL_FILE_SCOPE_P (newdecl))
        {
          if (DECL_EXTERNAL (newdecl))
        {
          if (DECL_EXTERNAL (newdecl))
-           error ("%Jextern declaration of '%D' follows "
-                  "declaration with no linkage", newdecl, newdecl);
+           {
+             /* Extern with initializer at block scope, which will
+                already have received an error.  */
+           }
          else if (DECL_EXTERNAL (olddecl))
          else if (DECL_EXTERNAL (olddecl))
-           error ("%Jdeclaration of '%D' with no linkage follows "
-                  "extern declaration", newdecl, newdecl);
+           {
+             error ("%Jdeclaration of '%D' with no linkage follows "
+                    "extern declaration", newdecl, newdecl);
+             locate_old_decl (olddecl, error);
+           }
          else
          else
-           error ("%Jredeclaration of '%D' with no linkage",
-                  newdecl, newdecl);
+           {
+             error ("%Jredeclaration of '%D' with no linkage",
+                    newdecl, newdecl);
+             locate_old_decl (olddecl, error);
+           }
 
 
-         locate_old_decl (olddecl, error);
          return false;
        }
     }
 
   /* warnings */
          return false;
        }
     }
 
   /* warnings */
-  /* All decls must agree on a non-default visibility.  */
-  if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
-      && DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT
+  /* All decls must agree on a visibility.  */
+  if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
       && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
     {
       warning ("%Jredeclaration of '%D' with different visibility "
       && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
     {
       warning ("%Jredeclaration of '%D' with different visibility "
@@ -1194,8 +1436,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
       /* Inline declaration after use or definition.
         ??? Should we still warn about this now we have unit-at-a-time
 
       /* Inline declaration after use or definition.
         ??? Should we still warn about this now we have unit-at-a-time
-        mode and can get it right?  */
-      if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl))
+        mode and can get it right?
+        Definitely don't complain if the decls are in different translation
+        units.  */
+      if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
+         && same_translation_unit_p (olddecl, newdecl))
        {
          if (TREE_USED (olddecl))
            {
        {
          if (TREE_USED (olddecl))
            {
@@ -1211,28 +1456,23 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
            }
        }
     }
            }
        }
     }
-  else /* VAR_DECL */
+  else /* PARM_DECL, VAR_DECL */
     {
     {
-      /* These bits are only type qualifiers when applied to objects.  */
-      if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
-       {
-         if (TREE_THIS_VOLATILE (newdecl))
-           pedwarn ("%Jvolatile declaration of '%D' follows "
-                    "non-volatile declaration", newdecl, newdecl);
-         else
-           pedwarn ("%Jnon-volatile declaration of '%D' follows "
-                    "volatile declaration", newdecl, newdecl);
-         pedwarned = true;
-       }
-      if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl))
+      /* Redeclaration of a parameter is a constraint violation (this is
+        not explicitly stated, but follows from C99 6.7p3 [no more than
+        one declaration of the same identifier with no linkage in the
+        same scope, except type tags] and 6.2.2p6 [parameters have no
+        linkage]).  We must check for a forward parameter declaration,
+        indicated by TREE_ASM_WRITTEN on the old declaration - this is
+        an extension, the mandatory diagnostic for which is handled by
+        mark_forward_parm_decls.  */
+
+      if (TREE_CODE (newdecl) == PARM_DECL
+         && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
        {
        {
-         if (TREE_READONLY (newdecl))
-           pedwarn ("%Jconst declaration of '%D' follows "
-                    "non-const declaration", newdecl, newdecl);
-         else
-           pedwarn ("%Jnon-const declaration of '%D' follows "
-                    "const declaration", newdecl, newdecl);
-         pedwarned = true;
+         error ("%Jredefinition of parameter '%D'", newdecl, newdecl);
+         locate_old_decl (olddecl, error);
+         return false;
        }
     }
 
        }
     }
 
@@ -1241,10 +1481,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       && warn_redundant_decls
       /* Don't warn about a function declaration followed by a
         definition.  */
       && warn_redundant_decls
       /* Don't warn about a function declaration followed by a
         definition.  */
-    && !(TREE_CODE (newdecl) == FUNCTION_DECL
-        && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
-    /* Don't warn about an extern followed by a definition.  */
-    && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl)))
+      && !(TREE_CODE (newdecl) == FUNCTION_DECL
+          && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
+      /* Don't warn about redundant redeclarations of builtins. */
+      && !(TREE_CODE (newdecl) == FUNCTION_DECL
+          && !DECL_BUILT_IN (newdecl)
+          && DECL_BUILT_IN (olddecl)
+          && !C_DECL_DECLARED_BUILTIN (olddecl))
+      /* Don't warn about an extern followed by a definition.  */
+      && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
+      /* Don't warn about forward parameter decls.  */
+      && !(TREE_CODE (newdecl) == PARM_DECL
+          && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)))
     {
       warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl);
       warned = true;
     {
       warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl);
       warned = true;
@@ -1268,22 +1516,35 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
                           && DECL_INITIAL (newdecl) != 0);
 
   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
                           && DECL_INITIAL (newdecl) != 0);
 
-  /* For real parm decl following a forward decl, return 1 so old decl
-     will be reused.  Only allow this to happen once.  */
+  /* For real parm decl following a forward decl, rechain the old decl
+     in its new location and clear TREE_ASM_WRITTEN (it's not a
+     forward decl anymore).  */
   if (TREE_CODE (newdecl) == PARM_DECL
       && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
     {
   if (TREE_CODE (newdecl) == PARM_DECL
       && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
     {
+      struct c_binding *b, **here;
+
+      for (here = &current_scope->bindings; *here; here = &(*here)->prev)
+       if ((*here)->decl == olddecl)
+         goto found;
+      abort ();
+
+    found:
+      b = *here;
+      *here = b->prev;
+      b->prev = current_scope->bindings;
+      current_scope->bindings = b;
+
       TREE_ASM_WRITTEN (olddecl) = 0;
       TREE_ASM_WRITTEN (olddecl) = 0;
-      return;
     }
 
   DECL_ATTRIBUTES (newdecl)
     }
 
   DECL_ATTRIBUTES (newdecl)
-    = (*targetm.merge_decl_attributes) (olddecl, newdecl);
+    = targetm.merge_decl_attributes (olddecl, newdecl);
 
   /* Merge the data types specified in the two decls.  */
   TREE_TYPE (newdecl)
     = TREE_TYPE (olddecl)
 
   /* Merge the data types specified in the two decls.  */
   TREE_TYPE (newdecl)
     = TREE_TYPE (olddecl)
-    = common_type (newtype, oldtype);
+    = composite_type (newtype, oldtype);
 
   /* Lay the type out, unless already done.  */
   if (oldtype != TREE_TYPE (newdecl))
 
   /* Lay the type out, unless already done.  */
   if (oldtype != TREE_TYPE (newdecl))
@@ -1348,9 +1609,12 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
      Currently, it can only be defined in the prototype.  */
   COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
 
      Currently, it can only be defined in the prototype.  */
   COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
 
-  /* If either declaration has a nondefault visibility, use it.  */
-  if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
-    DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+  /* Use visibility of whichever declaration had it specified */
+  if (DECL_VISIBILITY_SPECIFIED (olddecl))
+    {
+      DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+      DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+    }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -1431,9 +1695,11 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
 
       if (DECL_BUILT_IN (olddecl))
        {
 
       if (DECL_BUILT_IN (olddecl))
        {
-         /* If redeclaring a builtin function, it stays built in.  */
+         /* If redeclaring a builtin function, it stays built in.
+            But it gets tagged as having been declared.  */
          DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
          DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
          DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
          DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+         C_DECL_DECLARED_BUILTIN (newdecl) = 1;
        }
 
       /* Also preserve various other info from the definition.  */
        }
 
       /* Also preserve various other info from the definition.  */
@@ -1465,14 +1731,16 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
     }
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
     }
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
-     But preserve OLDDECL's DECL_UID.  */
+     But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
   {
     unsigned olddecl_uid = DECL_UID (olddecl);
   {
     unsigned olddecl_uid = DECL_UID (olddecl);
+    tree olddecl_context = DECL_CONTEXT (olddecl);
 
     memcpy ((char *) olddecl + sizeof (struct tree_common),
            (char *) newdecl + sizeof (struct tree_common),
            sizeof (struct tree_decl) - sizeof (struct tree_common));
     DECL_UID (olddecl) = olddecl_uid;
 
     memcpy ((char *) olddecl + sizeof (struct tree_common),
            (char *) newdecl + sizeof (struct tree_common),
            sizeof (struct tree_decl) - sizeof (struct tree_common));
     DECL_UID (olddecl) = olddecl_uid;
+    DECL_CONTEXT (olddecl) = olddecl_context;
   }
 
   /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
   }
 
   /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
@@ -1482,7 +1750,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       && (TREE_CODE (olddecl) == FUNCTION_DECL
          || (TREE_CODE (olddecl) == VAR_DECL
              && TREE_STATIC (olddecl))))
       && (TREE_CODE (olddecl) == FUNCTION_DECL
          || (TREE_CODE (olddecl) == VAR_DECL
              && TREE_STATIC (olddecl))))
-    make_decl_rtl (olddecl, NULL);
+    make_decl_rtl (olddecl);
 }
 
 /* Handle when a new declaration NEWDECL has the same name as an old
 }
 
 /* Handle when a new declaration NEWDECL has the same name as an old
@@ -1490,84 +1758,67 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
    if appropriate.
 
    If safely possible, alter OLDDECL to look like NEWDECL, and return
    if appropriate.
 
    If safely possible, alter OLDDECL to look like NEWDECL, and return
-   true.  Otherwise, return false.  */
-
-static bool
-duplicate_decls (tree newdecl, tree olddecl)
-{
-  tree newtype, oldtype;
-
-  if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
-    return false;
-
-  merge_decls (newdecl, olddecl, newtype, oldtype);
-  return true;
-}
-  
-\f
-/* Return any external DECL associated with ID, whether or not it is
-   currently in scope.  */
-
-static tree
-any_external_decl (tree id)
-{
-  tree decl = IDENTIFIER_SYMBOL_VALUE (id);
-  tree t;
-
-  if (decl == 0 || TREE_CODE (decl) == ERROR_MARK)
-    return 0;
-  else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl))
-    return decl;
-
-  t = purpose_member (id, truly_local_externals);
-  if (t)
-    return TREE_VALUE (t);
-
-  return 0;
-}
+   true.  Otherwise, return false.  */
 
 
-/* Record an external decl DECL.  This only does something if a
-   shadowing decl already exists.  */
-static void
-record_external_decl (tree decl)
+static bool
+duplicate_decls (tree newdecl, tree olddecl)
 {
 {
-  tree name = DECL_NAME (decl);
-  if (!IDENTIFIER_SYMBOL_VALUE (name))
-    return;
+  tree newtype = NULL, oldtype = NULL;
+
+  if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
+    return false;
 
 
-  truly_local_externals = tree_cons (name, decl, truly_local_externals);
+  merge_decls (newdecl, olddecl, newtype, oldtype);
+  return true;
 }
 
 }
 
-/* Check whether decl-node X shadows an existing declaration.
-   OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X,
-   which might be a NULL_TREE.  */
+\f
+/* Check whether decl-node NEW_DECL shadows an existing declaration.  */
 static void
 static void
-warn_if_shadowing (tree x, tree old)
+warn_if_shadowing (tree new_decl)
 {
 {
-  /* Nothing to shadow?  */
-  if (old == 0
-      /* Shadow warnings not wanted?  */
-      || !warn_shadow
+  struct c_binding *b;
+
+  /* Shadow warnings wanted?  */
+  if (!warn_shadow
       /* No shadow warnings for internally generated vars.  */
       /* No shadow warnings for internally generated vars.  */
-      || DECL_SOURCE_LINE (x) == 0
+      || DECL_IS_BUILTIN (new_decl)
       /* No shadow warnings for vars made for inlining.  */
       /* No shadow warnings for vars made for inlining.  */
-      || DECL_FROM_INLINE (x)
+      || DECL_FROM_INLINE (new_decl)
       /* Don't warn about the parm names in function declarator
       /* 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_scope->outer->parm_flag))
+        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 at this point.  */
+      || (TREE_CODE (new_decl) == PARM_DECL && current_scope->outer->parm_flag))
     return;
 
     return;
 
-  if (TREE_CODE (old) == PARM_DECL)
-    warning ("%Jdeclaration of '%D' shadows a parameter", x, x);
-  else if (DECL_FILE_SCOPE_P (old))
-    warning ("%Jdeclaration of '%D' shadows a global declaration", x, x);
-  else
-    warning ("%Jdeclaration of '%D' shadows a previous local", x, x);
+  /* Is anything being shadowed?  Invisible decls do not count.  */
+  for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
+    if (b->decl && b->decl != new_decl && !b->invisible)
+      {
+       tree old_decl = b->decl;
+
+       if (TREE_CODE (old_decl) == PARM_DECL)
+         warning ("%Jdeclaration of '%D' shadows a parameter",
+                  new_decl, new_decl);
+       else if (DECL_FILE_SCOPE_P (old_decl))
+         warning ("%Jdeclaration of '%D' shadows a global declaration",
+                  new_decl, new_decl);
+       else if (TREE_CODE (old_decl) == FUNCTION_DECL
+                && DECL_BUILT_IN (old_decl))
+         warning ("%Jdeclaration of '%D' shadows a built-in function",
+                  new_decl, new_decl);
+       else
+         warning ("%Jdeclaration of '%D' shadows a previous local",
+                  new_decl, new_decl);
+
+       if (TREE_CODE (old_decl) != FUNCTION_DECL
+           || ! DECL_BUILT_IN (old_decl))
+         warning ("%Jshadowed declaration is here", old_decl);
 
 
-  warning ("%Jshadowed declaration is here", old);
+       break;
+      }
 }
 
 
 }
 
 
@@ -1618,7 +1869,7 @@ warn_if_shadowing (tree x, tree old)
 static void
 clone_underlying_type (tree x)
 {
 static void
 clone_underlying_type (tree x)
 {
-  if (DECL_SOURCE_LINE (x) == 0)
+  if (DECL_IS_BUILTIN (x))
     {
       if (TYPE_NAME (TREE_TYPE (x)) == 0)
        TYPE_NAME (TREE_TYPE (x)) = x;
     {
       if (TYPE_NAME (TREE_TYPE (x)) == 0)
        TYPE_NAME (TREE_TYPE (x)) = x;
@@ -1628,7 +1879,7 @@ clone_underlying_type (tree x)
     {
       tree tt = TREE_TYPE (x);
       DECL_ORIGINAL_TYPE (x) = tt;
     {
       tree tt = TREE_TYPE (x);
       DECL_ORIGINAL_TYPE (x) = tt;
-      tt = build_type_copy (tt);
+      tt = build_variant_type_copy (tt);
       TYPE_NAME (tt) = x;
       TREE_USED (tt) = TREE_USED (x);
       TREE_TYPE (x) = tt;
       TYPE_NAME (tt) = x;
       TREE_USED (tt) = TREE_USED (x);
       TREE_TYPE (x) = tt;
@@ -1648,132 +1899,221 @@ pushdecl (tree x)
 {
   tree name = DECL_NAME (x);
   struct c_scope *scope = current_scope;
 {
   tree name = DECL_NAME (x);
   struct c_scope *scope = current_scope;
-
-#ifdef ENABLE_CHECKING
-  if (error_mark_node == 0)
-    /* Called too early.  */
-    abort ();
-#endif
+  struct c_binding *b;
+  bool nested = false;
 
   /* Functions need the lang_decl data.  */
   if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
 
   /* Functions need the lang_decl data.  */
   if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
-    DECL_LANG_SPECIFIC (x) = ggc_alloc_cleared (sizeof (struct lang_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 (current_function_decl == NULL
-      || ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
-         && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)))
-    DECL_CONTEXT (x) = current_file_decl;
-  else
+    DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
+
+  /* Must set DECL_CONTEXT for everything not at file scope or
+     DECL_FILE_SCOPE_P won't work.  Local externs don't count
+     unless they have initializers (which generate code).  */
+  if (current_function_decl
+      && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL)
+         || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
     DECL_CONTEXT (x) = current_function_decl;
 
     DECL_CONTEXT (x) = current_function_decl;
 
-  if (name)
+  /* Anonymous decls are just inserted in the scope.  */
+  if (!name)
     {
     {
-      tree old;
+      bind (name, x, scope, /*invisible=*/false, /*nested=*/false);
+      return x;
+    }
 
 
+  /* First, see if there is another declaration with the same name in
+     the current scope.  If there is, duplicate_decls may do all the
+     work for us.  If duplicate_decls returns false, that indicates
+     two incompatible decls in the same scope; we are to silently
+     replace the old one (duplicate_decls has issued all appropriate
+     diagnostics).  In particular, we should not consider possible
+     duplicates in the external scope, or shadowing.  */
+  b = I_SYMBOL_BINDING (name);
+  if (b && B_IN_SCOPE (b, scope))
+    {
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+         && COMPLETE_TYPE_P (TREE_TYPE (x)))
+       b->inner_comp = false;
+      if (duplicate_decls (x, b->decl))
+       return b->decl;
+      else
+       goto skip_external_and_shadow_checks;
+    }
+
+  /* All declarations with external linkage, and all external
+     references, go in the external scope, no matter what scope is
+     current.  However, the binding in that scope is ignored for
+     purposes of normal name lookup.  A separate binding structure is
+     created in the requested scope; this governs the normal
+     visibility of the symbol.
+
+     The binding in the externals scope is used exclusively for
+     detecting duplicate declarations of the same object, no matter
+     what scope they are in; this is what we do here.  (C99 6.2.7p2:
+     All declarations that refer to the same object or function shall
+     have compatible type; otherwise, the behavior is undefined.)  */
+  if (DECL_EXTERNAL (x) || scope == file_scope)
+    {
+      tree type = TREE_TYPE (x);
+      tree vistype = 0;
+      tree visdecl = 0;
+      bool type_saved = false;
+      if (b && !B_IN_EXTERNAL_SCOPE (b)
+         && (TREE_CODE (b->decl) == FUNCTION_DECL
+             || TREE_CODE (b->decl) == VAR_DECL)
+         && DECL_FILE_SCOPE_P (b->decl))
+       {
+         visdecl = b->decl;
+         vistype = TREE_TYPE (visdecl);
+       }
       if (warn_nested_externs
       if (warn_nested_externs
-         && scope != global_scope
-         && DECL_EXTERNAL (x)
+         && scope != file_scope
          && !DECL_IN_SYSTEM_HEADER (x))
          && !DECL_IN_SYSTEM_HEADER (x))
-       warning ("nested extern declaration of `%s'",
-                IDENTIFIER_POINTER (name));
+       warning ("nested extern declaration of '%D'", x);
 
 
-      old = lookup_name_current_level (name);
-      if (old && duplicate_decls (x, old))
+      while (b && !B_IN_EXTERNAL_SCOPE (b))
        {
        {
-         /* For PARM_DECLs, old may be a forward declaration.
-            If so, we want to remove it from its old location
-            (in the variables chain) and rechain it in the
-            location given by the new declaration.  */
-         if (TREE_CODE (x) == PARM_DECL)
+         /* If this decl might be modified, save its type.  This is
+            done here rather than when the decl is first bound
+            because the type may change after first binding, through
+            being completed or through attributes being added.  If we
+            encounter multiple such decls, only the first should have
+            its type saved; the others will already have had their
+            proper types saved and the types will not have changed as
+            their scopes will not have been re-entered.  */
+         if (DECL_FILE_SCOPE_P (b->decl) && !type_saved)
            {
            {
-             tree *p;
-             for (p = &scope->names; *p; p = &TREE_CHAIN (*p))
-               if (*p == old)
-                 {
-                   *p = TREE_CHAIN (old);
-                   SCOPE_LIST_APPEND (scope, parms, old);
-                   break;
-                 }
+             b->type = TREE_TYPE (b->decl);
+             type_saved = true;
+           }
+         if (B_IN_FILE_SCOPE (b)
+             && TREE_CODE (b->decl) == VAR_DECL
+             && TREE_STATIC (b->decl)
+             && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
+             && !TYPE_DOMAIN (TREE_TYPE (b->decl))
+             && TREE_CODE (type) == ARRAY_TYPE
+             && TYPE_DOMAIN (type)
+             && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+             && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+           {
+             /* Array type completed in inner scope, which should be
+                diagnosed if the completion does not have size 1 and
+                it does not get completed in the file scope.  */
+             b->inner_comp = true;
            }
            }
-         return old;
+         b = b->shadowed;
+       }
+
+      /* If a matching external declaration has been found, set its
+        type to the composite of all the types of that declaration.
+        After the consistency checks, it will be reset to the
+        composite of the visible types only.  */
+      if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+         && b->type)
+       TREE_TYPE (b->decl) = b->type;
+
+      /* The point of the same_translation_unit_p check here is,
+        we want to detect a duplicate decl for a construct like
+        foo() { extern bar(); } ... static bar();  but not if
+        they are in different translation units.  In any case,
+        the static does not go in the externals scope.  */
+      if (b
+         && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+         && duplicate_decls (x, b->decl))
+       {
+         tree thistype;
+         thistype = (vistype ? composite_type (vistype, type) : type);
+         b->type = TREE_TYPE (b->decl);
+         if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
+           thistype
+             = build_type_attribute_variant (thistype,
+                                             TYPE_ATTRIBUTES (b->type));
+         TREE_TYPE (b->decl) = thistype;
+         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+         return b->decl;
        }
        }
-      if (DECL_EXTERNAL (x) || scope == global_scope)
+      else if (TREE_PUBLIC (x))
        {
        {
-         /* Find and check against a previous, not-in-scope, external
-            decl for this identifier.  (C99 6.2.7p2: All declarations
-            that refer to the same object or function shall have
-            compatible type; otherwise, the behavior is undefined.)  */
-         tree ext = any_external_decl (name);
-         if (ext)
+         if (visdecl && !b && duplicate_decls (x, visdecl))
            {
            {
-             if (duplicate_decls (x, ext))
-               x = copy_node (ext);
+             /* An external declaration at block scope referring to a
+                visible entity with internal linkage.  The composite
+                type will already be correct for this scope, so we
+                just need to fall through to make the declaration in
+                this scope.  */
+             nested = true;
            }
          else
            }
          else
-           record_external_decl (x);
+           {
+             bind (name, x, external_scope, /*invisible=*/true,
+                   /*nested=*/false);
+             nested = true;
+           }
        }
        }
+    }
+  /* Similarly, a declaration of a function with static linkage at
+     block scope must be checked against any existing declaration
+     of that function at file scope.  */
+  else if (TREE_CODE (x) == FUNCTION_DECL && scope != file_scope
+          && !TREE_PUBLIC (x) && !DECL_INITIAL (x))
+    {
+      if (warn_nested_externs && !DECL_IN_SYSTEM_HEADER (x))
+       warning ("nested static declaration of '%D'", x);
 
 
-      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
-        scope ends.  Take care not to do this if we are replacing an
-        older decl in the same scope (i.e.  duplicate_decls returned
-        false, above).  */
-      if (scope != global_scope
-         && IDENTIFIER_SYMBOL_VALUE (name)
-         && IDENTIFIER_SYMBOL_VALUE (name) != old)
+      while (b && !B_IN_FILE_SCOPE (b))
+       b = b->shadowed;
+
+      if (b && same_translation_unit_p (x, b->decl)
+         && duplicate_decls (x, b->decl))
        {
        {
-         warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name));
-         scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
-                                      scope->shadowed);
+         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+         return b->decl;
        }
        }
-
-      /* Install the new declaration in the requested scope.  */
-      IDENTIFIER_SYMBOL_VALUE (name) = x;
-      C_DECL_INVISIBLE (x) = 0;
-
-      /* If x's type is incomplete because it's based on a
-        structure or union which has not yet been fully declared,
-        attach it to that structure or union type, so we can go
-        back and complete the variable declaration later, if the
-        structure or union gets fully declared.
-
-        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.  */
-      if (TREE_TYPE (x) != error_mark_node
-         && !COMPLETE_TYPE_P (TREE_TYPE (x)))
+      else
        {
        {
-         tree element = TREE_TYPE (x);
-
-         while (TREE_CODE (element) == ARRAY_TYPE)
-           element = TREE_TYPE (element);
-         element = TYPE_MAIN_VARIANT (element);
-
-         if ((TREE_CODE (element) == RECORD_TYPE
-              || TREE_CODE (element) == UNION_TYPE)
-             && (TREE_CODE (x) != TYPE_DECL
-                 || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
-             && !COMPLETE_TYPE_P (element))
-           C_TYPE_INCOMPLETE_VARS (element)
-             = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
+         bind (name, x, file_scope, /*invisible=*/true, /*nested=*/false);
+         nested = true;
        }
     }
 
        }
     }
 
-  if (TREE_CODE (x) == PARM_DECL)
-    SCOPE_LIST_APPEND (scope, parms, x);
-  else
-    SCOPE_LIST_APPEND (scope, names, x);
+  warn_if_shadowing (x);
+
+ skip_external_and_shadow_checks:
+  if (TREE_CODE (x) == TYPE_DECL)
+    clone_underlying_type (x);
+
+  bind (name, x, scope, /*invisible=*/false, nested);
+
+  /* If x's type is incomplete because it's based on a
+     structure or union which has not yet been fully declared,
+     attach it to that structure or union type, so we can go
+     back and complete the variable declaration later, if the
+     structure or union gets fully declared.
+
+     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.  */
+  if (TREE_TYPE (x) != error_mark_node
+      && !COMPLETE_TYPE_P (TREE_TYPE (x)))
+    {
+      tree element = TREE_TYPE (x);
+
+      while (TREE_CODE (element) == ARRAY_TYPE)
+       element = TREE_TYPE (element);
+      element = TYPE_MAIN_VARIANT (element);
 
 
+      if ((TREE_CODE (element) == RECORD_TYPE
+          || TREE_CODE (element) == UNION_TYPE)
+         && (TREE_CODE (x) != TYPE_DECL
+             || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
+         && !COMPLETE_TYPE_P (element))
+       C_TYPE_INCOMPLETE_VARS (element)
+         = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
+    }
   return x;
 }
 
   return x;
 }
 
-/* Record X as belonging to the global scope (C99 "file scope").
+/* Record X as belonging to file scope.
    This is used only internally by the Objective-C front end,
    and is limited to its needs.  duplicate_decls is not called;
    if there is any preexisting decl for this identifier, it is an ICE.  */
    This is used only internally by the Objective-C front end,
    and is limited to its needs.  duplicate_decls is not called;
    if there is any preexisting decl for this identifier, it is an ICE.  */
@@ -1782,50 +2122,115 @@ tree
 pushdecl_top_level (tree x)
 {
   tree name;
 pushdecl_top_level (tree x)
 {
   tree name;
+  bool nested = false;
 
   if (TREE_CODE (x) != VAR_DECL)
     abort ();
 
   name = DECL_NAME (x);
 
 
   if (TREE_CODE (x) != VAR_DECL)
     abort ();
 
   name = DECL_NAME (x);
 
-  if (IDENTIFIER_SYMBOL_VALUE (name))
+  if (I_SYMBOL_BINDING (name))
     abort ();
 
     abort ();
 
-  DECL_CONTEXT (x) = current_file_decl;
-  IDENTIFIER_SYMBOL_VALUE (name) = x;
+  if (TREE_PUBLIC (x))
+    {
+      bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
+      nested = true;
+    }
+  if (file_scope)
+    bind (name, x, file_scope, /*invisible=*/false, nested);
 
 
-  SCOPE_LIST_APPEND (global_scope, names, x);
   return x;
 }
 \f
   return x;
 }
 \f
+static void
+implicit_decl_warning (tree id, tree olddecl)
+{
+  void (*diag) (const char *, ...);
+  switch (mesg_implicit_function_declaration)
+    {
+    case 0: return;
+    case 1: diag = warning; break;
+    case 2: diag = error;   break;
+    default: abort ();
+    }
+
+  diag (N_("implicit declaration of function '%E'"), id);
+  if (olddecl)
+    locate_old_decl (olddecl, diag);
+}
+
 /* Generate an implicit declaration for identifier FUNCTIONID as a
    function of type int ().  */
 
 tree
 implicitly_declare (tree functionid)
 {
 /* Generate an implicit declaration for identifier FUNCTIONID as a
    function of type int ().  */
 
 tree
 implicitly_declare (tree functionid)
 {
-  tree decl = any_external_decl (functionid);
+  struct c_binding *b;
+  tree decl = 0;
+  for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
+    {
+      if (B_IN_SCOPE (b, external_scope))
+       {
+         decl = b->decl;
+         break;
+       }
+    }
 
   if (decl)
     {
 
   if (decl)
     {
-      /* 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))
+      /* FIXME: Objective-C has weird not-really-builtin functions
+        which are supposed to be visible automatically.  They wind up
+        in the external scope because they're pushed before the file
+        scope gets created.  Catch this here and rebind them into the
+        file scope.  */
+      if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
+       {
+         bind (functionid, decl, file_scope,
+               /*invisible=*/false, /*nested=*/true);
+         return decl;
+       }
+      else
        {
        {
-         implicit_decl_warning (DECL_NAME (decl));
-         if (! DECL_FILE_SCOPE_P (decl))
-           warning ("%Jprevious declaration of '%D'", decl, decl);
-         C_DECL_IMPLICIT (decl) = 1;
+         tree newtype = default_function_type;
+         if (b->type)
+           TREE_TYPE (decl) = b->type;
+         /* 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 but with the new type.  */
+         if (!C_DECL_IMPLICIT (decl))
+           {
+             implicit_decl_warning (functionid, decl);
+             C_DECL_IMPLICIT (decl) = 1;
+           }
+         if (DECL_BUILT_IN (decl))
+           {
+             newtype = build_type_attribute_variant (newtype,
+                                                     TYPE_ATTRIBUTES
+                                                     (TREE_TYPE (decl)));
+             if (!comptypes (newtype, TREE_TYPE (decl)))
+               {
+                 warning ("incompatible implicit declaration of built-in"
+                          " function %qD", decl);
+                 newtype = TREE_TYPE (decl);
+               }
+           }
+         else
+           {
+             if (!comptypes (newtype, TREE_TYPE (decl)))
+               {
+                 error ("incompatible implicit declaration of function %qD",
+                        decl);
+                 locate_old_decl (decl, error);
+               }
+           }
+         b->type = TREE_TYPE (decl);
+         TREE_TYPE (decl) = newtype;
+         bind (functionid, decl, current_scope,
+               /*invisible=*/false, /*nested=*/true);
+         return decl;
        }
        }
-      /* If this function is global, then it must already be in the
-        global scope, so there's no need to push it again.  */
-      if (current_scope == global_scope)
-       return decl;
-      /* If this is a local declaration, make a copy; we can't have
-        the same DECL listed in two different scopes.  */
-      return pushdecl (copy_node (decl));
     }
 
   /* Not seen before.  */
     }
 
   /* Not seen before.  */
@@ -1833,14 +2238,14 @@ implicitly_declare (tree functionid)
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
   C_DECL_IMPLICIT (decl) = 1;
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
   C_DECL_IMPLICIT (decl) = 1;
-  implicit_decl_warning (functionid);
+  implicit_decl_warning (functionid, 0);
 
   /* C89 says implicit declarations are in the innermost block.
      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.  */
 
   /* C89 says implicit declarations are in the innermost block.
      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);
+  rest_of_decl_compilation (decl, 0, 0);
 
   /* Write a record describing this implicit function declaration
      to the prototypes file (if requested).  */
 
   /* Write a record describing this implicit function declaration
      to the prototypes file (if requested).  */
@@ -1852,16 +2257,6 @@ implicitly_declare (tree functionid)
   return decl;
 }
 
   return decl;
 }
 
-static void
-implicit_decl_warning (tree id)
-{
-  const char *name = IDENTIFIER_POINTER (id);
-  if (mesg_implicit_function_declaration == 2)
-    error ("implicit declaration of function `%s'", name);
-  else if (mesg_implicit_function_declaration == 1)
-    warning ("implicit declaration of function `%s'", name);
-}
-
 /* Issue an error message for a reference to an undeclared variable
    ID, including a reference to a builtin outside of function-call
    context.  Establish a binding of the identifier to error_mark_node
 /* Issue an error message for a reference to an undeclared variable
    ID, including a reference to a builtin outside of function-call
    context.  Establish a binding of the identifier to error_mark_node
@@ -1875,14 +2270,12 @@ undeclared_variable (tree id)
 
   if (current_function_decl == 0)
     {
 
   if (current_function_decl == 0)
     {
-      error ("`%s' undeclared here (not in a function)",
-            IDENTIFIER_POINTER (id));
+      error ("'%E' undeclared here (not in a function)", id);
       scope = current_scope;
     }
   else
     {
       scope = current_scope;
     }
   else
     {
-      error ("`%s' undeclared (first use in this function)",
-            IDENTIFIER_POINTER (id));
+      error ("'%E' undeclared (first use in this function)", id);
 
       if (! already)
        {
 
       if (! already)
        {
@@ -1891,12 +2284,11 @@ undeclared_variable (tree id)
          already = true;
        }
 
          already = true;
        }
 
-      scope = current_function_scope;
+      /* If we are parsing old-style parameter decls, current_function_decl
+         will be nonnull but current_function_scope will be null.  */
+      scope = current_function_scope ? current_function_scope : current_scope;
     }
     }
-
-  scope->shadowed = tree_cons (id, IDENTIFIER_SYMBOL_VALUE (id),
-                              scope->shadowed);
-  IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
+  bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
 }
 \f
 /* Subroutine of lookup_label, declare_label, define_label: construct a
 }
 \f
 /* Subroutine of lookup_label, declare_label, define_label: construct a
@@ -1914,20 +2306,6 @@ make_label (tree name, location_t location)
   return label;
 }
 
   return label;
 }
 
-/* Another subroutine of lookup_label, declare_label, define_label:
-   set up the binding of name to LABEL_DECL in the given SCOPE.  */
-
-static void
-bind_label (tree name, tree label, struct c_scope *scope)
-{
-  if (IDENTIFIER_LABEL_VALUE (name))
-    scope->shadowed = tree_cons (name, IDENTIFIER_LABEL_VALUE (name),
-                                scope->shadowed);
-  IDENTIFIER_LABEL_VALUE (name) = label;
-
-  SCOPE_LIST_APPEND (scope, names, label);
-}
-
 /* Get the LABEL_DECL corresponding to identifier NAME as a label.
    Create one if none exists so far for the current function.
    This is called when a label is used in a goto expression or
 /* Get the LABEL_DECL corresponding to identifier NAME as a label.
    Create one if none exists so far for the current function.
    This is called when a label is used in a goto expression or
@@ -1948,7 +2326,7 @@ lookup_label (tree name)
   /* Use a label already defined or ref'd with this name, but not if
      it is inherited from a containing function and wasn't declared
      using __label__.  */
   /* Use a label already defined or ref'd with this name, but not if
      it is inherited from a containing function and wasn't declared
      using __label__.  */
-  label = IDENTIFIER_LABEL_VALUE (name);
+  label = I_LABEL_DECL (name);
   if (label && (DECL_CONTEXT (label) == current_function_decl
                || C_DECLARED_LABEL_FLAG (label)))
     {
   if (label && (DECL_CONTEXT (label) == current_function_decl
                || C_DECLARED_LABEL_FLAG (label)))
     {
@@ -1964,7 +2342,8 @@ lookup_label (tree name)
   label = make_label (name, input_location);
 
   /* Ordinary labels go in the current function scope.  */
   label = make_label (name, input_location);
 
   /* Ordinary labels go in the current function scope.  */
-  bind_label (name, label, current_function_scope);
+  bind (name, label, current_function_scope,
+       /*invisible=*/false, /*nested=*/false);
   return label;
 }
 
   return label;
 }
 
@@ -1972,33 +2351,29 @@ lookup_label (tree name)
    any that may be inherited from containing functions or containing
    scopes.  This is called for __label__ declarations.  */
 
    any that may be inherited from containing functions or containing
    scopes.  This is called for __label__ declarations.  */
 
-/* Note that valid use, if the label being shadowed comes from another
-   scope in the same function, requires calling declare_nonlocal_label
-   right away.  (Is this still true?  -zw 2003-07-17)  */
-
 tree
 declare_label (tree name)
 {
 tree
 declare_label (tree name)
 {
-  tree label = IDENTIFIER_LABEL_VALUE (name);
-  tree dup;
+  struct c_binding *b = I_LABEL_BINDING (name);
+  tree label;
 
   /* Check to make sure that the label hasn't already been declared
      at this scope */
 
   /* Check to make sure that the label hasn't already been declared
      at this scope */
-  for (dup = current_scope->names; dup; dup = TREE_CHAIN (dup))
-    if (dup == label)
-      {
-       error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
-       error ("%Jthis is a previous declaration", dup);
+  if (b && B_IN_CURRENT_SCOPE (b))
+    {
+      error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
+      locate_old_decl (b->decl, error);
 
 
-       /* Just use the previous declaration.  */
-       return dup;
-      }
+      /* Just use the previous declaration.  */
+      return b->decl;
+    }
 
   label = make_label (name, input_location);
   C_DECLARED_LABEL_FLAG (label) = 1;
 
   /* Declared labels go in the current scope.  */
 
   label = make_label (name, input_location);
   C_DECLARED_LABEL_FLAG (label) = 1;
 
   /* Declared labels go in the current scope.  */
-  bind_label (name, label, current_scope);
+  bind (name, label, current_scope,
+       /*invisible=*/false, /*nested=*/false);
   return label;
 }
 
   return label;
 }
 
@@ -2009,13 +2384,11 @@ declare_label (tree name)
 tree
 define_label (location_t location, tree name)
 {
 tree
 define_label (location_t location, tree name)
 {
-  tree label;
-
   /* Find any preexisting label with this name.  It is an error
      if that label has already been defined in this function, or
      if there is a containing function with a declared label with
      the same name.  */
   /* Find any preexisting label with this name.  It is an error
      if that label has already been defined in this function, or
      if there is a containing function with a declared label with
      the same name.  */
-  label = IDENTIFIER_LABEL_VALUE (name);
+  tree label = I_LABEL_DECL (name);
 
   if (label
       && ((DECL_CONTEXT (label) == current_function_decl
 
   if (label
       && ((DECL_CONTEXT (label) == current_function_decl
@@ -2024,10 +2397,7 @@ define_label (location_t location, tree name)
              && C_DECLARED_LABEL_FLAG (label))))
     {
       error ("%Hduplicate label `%D'", &location, label);
              && C_DECLARED_LABEL_FLAG (label))))
     {
       error ("%Hduplicate label `%D'", &location, label);
-      if (DECL_INITIAL (label))
-       error ("%J`%D' previously defined here", label, label);
-      else
-       error ("%J`%D' previously declared here", label, label);
+      locate_old_decl (label, error);
       return 0;
     }
   else if (label && DECL_CONTEXT (label) == current_function_decl)
       return 0;
     }
   else if (label && DECL_CONTEXT (label) == current_function_decl)
@@ -2043,7 +2413,8 @@ define_label (location_t location, tree name)
       label = make_label (name, location);
 
       /* Ordinary labels go in the current function scope.  */
       label = make_label (name, location);
 
       /* Ordinary labels go in the current function scope.  */
-      bind_label (name, label, current_function_scope);
+      bind (name, label, current_function_scope,
+           /*invisible=*/false, /*nested=*/false);
     }
 
   if (warn_traditional && !in_system_header && lookup_name (name))
     }
 
   if (warn_traditional && !in_system_header && lookup_name (name))
@@ -2056,16 +2427,6 @@ define_label (location_t location, tree name)
   return label;
 }
 \f
   return label;
 }
 \f
-/* Return the list of declarations of the current scope.
-   This hook is optional and not implemented for C.  */
-
-tree
-getdecls (void)
-{
-  return 0;
-}
-
-\f
 /* Given NAME, an IDENTIFIER_NODE,
    return the structure (or union or enum) definition for that name.
    If THISLEVEL_ONLY is nonzero, searches only the current_scope.
 /* Given NAME, an IDENTIFIER_NODE,
    return the structure (or union or enum) definition for that name.
    If THISLEVEL_ONLY is nonzero, searches only the current_scope.
@@ -2076,25 +2437,29 @@ getdecls (void)
 static tree
 lookup_tag (enum tree_code code, tree name, int thislevel_only)
 {
 static tree
 lookup_tag (enum tree_code code, tree name, int thislevel_only)
 {
-  tree tag = IDENTIFIER_TAG_VALUE (name);
+  struct c_binding *b = I_TAG_BINDING (name);
   int thislevel = 0;
 
   int thislevel = 0;
 
-  if (!tag)
+  if (!b || !b->decl)
     return 0;
 
   /* We only care about whether it's in this level if
      thislevel_only was set or it might be a type clash.  */
     return 0;
 
   /* We only care about whether it's in this level if
      thislevel_only was set or it might be a type clash.  */
-  if (thislevel_only || TREE_CODE (tag) != code)
-    {
-      if (current_scope == global_scope
-         || purpose_member (name, current_scope->tags))
+  if (thislevel_only || TREE_CODE (b->decl) != code)
+    {
+      /* For our purposes, a tag in the external scope is the same as
+        a tag in the file scope.  (Primarily relevant to Objective-C
+        and its builtin structure tags, which get pushed before the
+        file scope is created.)  */
+      if (B_IN_CURRENT_SCOPE (b)
+         || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
        thislevel = 1;
     }
 
   if (thislevel_only && !thislevel)
     return 0;
 
        thislevel = 1;
     }
 
   if (thislevel_only && !thislevel)
     return 0;
 
-  if (TREE_CODE (tag) != code)
+  if (TREE_CODE (b->decl) != code)
     {
       /* Definition isn't the kind we were looking for.  */
       pending_invalid_xref = name;
     {
       /* Definition isn't the kind we were looking for.  */
       pending_invalid_xref = name;
@@ -2107,7 +2472,7 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only)
       if (thislevel)
        pending_xref_error ();
     }
       if (thislevel)
        pending_xref_error ();
     }
-  return tag;
+  return b->decl;
 }
 
 /* Print an error message now
 }
 
 /* Print an error message now
@@ -2134,36 +2499,22 @@ pending_xref_error (void)
 tree
 lookup_name (tree name)
 {
 tree
 lookup_name (tree name)
 {
-  tree decl = IDENTIFIER_SYMBOL_VALUE (name);
-  if (decl == 0 || decl == error_mark_node)
-    return decl;
-  if (C_DECL_INVISIBLE (decl))
-    return 0;
-  return decl;
+  struct c_binding *b = I_SYMBOL_BINDING (name);
+  if (b && !b->invisible)
+    return b->decl;
+  return 0;
 }
 
 }
 
-/* Similar to `lookup_name' but look only at the current scope.  */
+/* Similar to `lookup_name' but look only at the indicated scope.  */
 
 static tree
 
 static tree
-lookup_name_current_level (tree name)
+lookup_name_in_scope (tree name, struct c_scope *scope)
 {
 {
-  tree decl = IDENTIFIER_SYMBOL_VALUE (name);
-
-  if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
-    return 0;
-
-  if (current_scope == global_scope)
-    return decl;
-
-  /* Scan the current scope for a decl with name NAME.
-     For PARM_DECLs, we have to look at both ->parms and ->names, since
-     forward parameter declarations wind up on the ->names list.  */
-  if (TREE_CODE (decl) == PARM_DECL
-      && chain_member (decl, current_scope->parms))
-    return decl;
-  if (chain_member (decl, current_scope->names))
-    return decl;
+  struct c_binding *b;
 
 
+  for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
+    if (B_IN_SCOPE (b, scope))
+      return b->decl;
   return 0;
 }
 \f
   return 0;
 }
 \f
@@ -2184,20 +2535,21 @@ c_init_decl_processing (void)
 
   current_function_decl = 0;
 
 
   current_function_decl = 0;
 
-  /* Make the c_scope structure for global names.  */
-  pushlevel (0);
-  global_scope = current_scope;
+  /* Make the externals scope.  */
+  push_scope ();
+  external_scope = current_scope;
 
   /* Declarations from c_common_nodes_and_builtins must not be associated
      with this input file, lest we get differences between using and not
      using preprocessed headers.  */
 
   /* Declarations from c_common_nodes_and_builtins must not be associated
      with this input file, lest we get differences between using and not
      using preprocessed headers.  */
-  input_location.file = "<internal>";
+#ifdef USE_MAPPED_LOCATION
+  input_location = BUILTINS_LOCATION;
+#else
+  input_location.file = "<built-in>";
   input_location.line = 0;
   input_location.line = 0;
+#endif
 
 
-  /* Make the DECL for the toplevel file scope.  */
-  current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
-
-  build_common_tree_nodes (flag_signed_char);
+  build_common_tree_nodes (flag_signed_char, false);
 
   c_common_nodes_and_builtins ();
 
 
   c_common_nodes_and_builtins ();
 
@@ -2222,9 +2574,6 @@ c_init_decl_processing (void)
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
-
-  first_builtin_decl = global_scope->names;
-  last_builtin_decl = global_scope->names_last;
 }
 
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
 }
 
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -2252,6 +2601,7 @@ c_make_fname_decl (tree id, int type_dep)
   DECL_ARTIFICIAL (decl) = 1;
 
   init = build_string (length + 1, name);
   DECL_ARTIFICIAL (decl) = 1;
 
   init = build_string (length + 1, name);
+  free ((char *) name);
   TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
 
   TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
 
@@ -2260,8 +2610,8 @@ c_make_fname_decl (tree id, int type_dep)
   if (current_function_decl)
     {
       DECL_CONTEXT (decl) = current_function_decl;
   if (current_function_decl)
     {
       DECL_CONTEXT (decl) = current_function_decl;
-      IDENTIFIER_SYMBOL_VALUE (id) = decl;
-      SCOPE_LIST_APPEND (current_function_scope, names, decl);
+      bind (id, decl, current_function_scope,
+           /*invisible=*/false, /*nested=*/false);
     }
 
   finish_decl (decl, init, NULL_TREE);
     }
 
   finish_decl (decl, init, NULL_TREE);
@@ -2280,23 +2630,32 @@ c_make_fname_decl (tree id, int type_dep)
 
 tree
 builtin_function (const char *name, tree type, int function_code,
 
 tree
 builtin_function (const char *name, tree type, int function_code,
-                 enum built_in_class class, const char *library_name,
+                 enum built_in_class cl, const char *library_name,
                  tree attrs)
 {
                  tree attrs)
 {
-  tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
-  DECL_EXTERNAL (decl) = 1;
+  tree id = get_identifier (name);
+  tree decl = build_decl (FUNCTION_DECL, id, type);
   TREE_PUBLIC (decl) = 1;
   TREE_PUBLIC (decl) = 1;
+  DECL_EXTERNAL (decl) = 1;
+  DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
+  DECL_BUILT_IN_CLASS (decl) = cl;
+  DECL_FUNCTION_CODE (decl) = function_code;
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
-  make_decl_rtl (decl, NULL);
-  pushdecl (decl);
-  DECL_BUILT_IN_CLASS (decl) = class;
-  DECL_FUNCTION_CODE (decl) = function_code;
 
 
-  /* 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_INVISIBLE (decl) = 1;
+  /* Should never be called on a symbol with a preexisting meaning.  */
+  if (I_SYMBOL_BINDING (id))
+    abort ();
+
+  bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
+
+  /* Builtins in the implementation namespace are made visible without
+     needing to be explicitly declared.  See push_file_scope.  */
+  if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+    {
+      TREE_CHAIN (decl) = visible_builtins;
+      visible_builtins = decl;
+    }
 
   /* Possibly apply some default attributes to this built-in function.  */
   if (attrs)
 
   /* Possibly apply some default attributes to this built-in function.  */
   if (attrs)
@@ -2321,12 +2680,10 @@ shadow_tag (tree declspecs)
   shadow_tag_warned (declspecs, 0);
 }
 
   shadow_tag_warned (declspecs, 0);
 }
 
+/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
+   but no pedwarn.  */
 void
 shadow_tag_warned (tree declspecs, int warned)
 void
 shadow_tag_warned (tree declspecs, int warned)
-
-
-     /* 1 => we have done a pedwarn.  2 => we have done a warning, but
-       no pedwarn.  */
 {
   int found_tag = 0;
   tree link;
 {
   int found_tag = 0;
   tree link;
@@ -2395,20 +2752,21 @@ shadow_tag_warned (tree declspecs, int 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
 /* 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
-   nonzero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
-   is nonzero is the array is [*], a VLA of unspecified length which is
+   true if "static" is inside the [], false otherwise.  VLA_UNSPEC_P
+   is true if the array is [*], a VLA of unspecified length which is
    nevertheless a complete type (not currently implemented by GCC),
    nevertheless a complete type (not currently implemented by GCC),
-   zero otherwise.  The declarator is constructed as an ARRAY_REF
+   false otherwise.  The declarator is constructed as an ARRAY_REF
    (to be decoded by grokdeclarator), whose operand 0 is what's on the
    (to be decoded by grokdeclarator), whose operand 0 is what's on the
-   left of the [] (filled by in set_array_declarator_type) and operand 1
+   left of the [] (filled by in set_array_declarator_inner) and operand 1
    is the expression inside; whose TREE_TYPE is the type qualifiers and
    which has TREE_STATIC set if "static" is used.  */
 
 tree
    is the expression inside; whose TREE_TYPE is the type qualifiers and
    which has TREE_STATIC set if "static" is used.  */
 
 tree
-build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p)
+build_array_declarator (tree expr, tree quals, bool static_p,
+                       bool vla_unspec_p)
 {
   tree decl;
 {
   tree decl;
-  decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+  decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
   TREE_TYPE (decl) = quals;
   TREE_STATIC (decl) = (static_p ? 1 : 0);
   if (pedantic && !flag_isoc99)
   TREE_TYPE (decl) = quals;
   TREE_STATIC (decl) = (static_p ? 1 : 0);
   if (pedantic && !flag_isoc99)
@@ -2425,13 +2783,13 @@ build_array_declarator (tree expr, tree quals, int static_p, int 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
 
 /* 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 nonzero if it is an
-   abstract declarator, zero otherwise; this is used to reject static and
+   of the [] and goes in operand 0.  ABSTRACT_P is true if it is an
+   abstract declarator, false otherwise; this is used to reject static and
    type qualifiers in abstract declarators, where they are not in the
    C99 grammar.  */
 
 tree
    type qualifiers in abstract declarators, where they are not in the
    C99 grammar.  */
 
 tree
-set_array_declarator_type (tree decl, tree type, int abstract_p)
+set_array_declarator_inner (tree decl, tree type, bool abstract_p)
 {
   TREE_OPERAND (decl, 0) = type;
   if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
 {
   TREE_OPERAND (decl, 0) = type;
   if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
@@ -2442,34 +2800,34 @@ set_array_declarator_type (tree decl, tree type, int abstract_p)
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (tree typename)
+groktypename (tree type_name)
 {
   tree specs, attrs;
 
 {
   tree specs, attrs;
 
-  if (TREE_CODE (typename) != TREE_LIST)
-    return typename;
+  if (TREE_CODE (type_name) != TREE_LIST)
+    return type_name;
 
 
-  split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+  split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
 
 
-  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0,
+  type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
                             NULL);
 
   /* Apply attributes.  */
                             NULL);
 
   /* Apply attributes.  */
-  decl_attributes (&typename, attrs, 0);
+  decl_attributes (&type_name, attrs, 0);
 
 
-  return typename;
+  return type_name;
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
 
 tree
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
 
 tree
-groktypename_in_parm_context (tree typename)
+groktypename_in_parm_context (tree type_name)
 {
 {
-  if (TREE_CODE (typename) != TREE_LIST)
-    return typename;
-  return grokdeclarator (TREE_VALUE (typename),
-                        TREE_PURPOSE (typename),
-                        PARM, 0, NULL);
+  if (TREE_CODE (type_name) != TREE_LIST)
+    return type_name;
+  return grokdeclarator (TREE_VALUE (type_name),
+                        TREE_PURPOSE (type_name),
+                        PARM, false, NULL);
 }
 
 /* Decode a declarator in an ordinary declaration or data definition.
 }
 
 /* Decode a declarator in an ordinary declaration or data definition.
@@ -2488,7 +2846,7 @@ groktypename_in_parm_context (tree typename)
    grokfield and not through here.  */
 
 tree
    grokfield and not through here.  */
 
 tree
-start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
+start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
 {
   tree decl;
   tree tem;
 {
   tree decl;
   tree tem;
@@ -2510,34 +2868,31 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
-       tell `finish_decl' to ignore the initializer once it is parsed.  */
+       tell 'finish_decl' to ignore the initializer once it is parsed.  */
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       error ("typedef `%s' is initialized (use __typeof__ instead)",
-              IDENTIFIER_POINTER (DECL_NAME (decl)));
+       error ("typedef '%D' is initialized (use __typeof__ instead)", decl);
        initialized = 0;
        break;
 
       case FUNCTION_DECL:
        initialized = 0;
        break;
 
       case FUNCTION_DECL:
-       error ("function `%s' is initialized like a variable",
-              IDENTIFIER_POINTER (DECL_NAME (decl)));
+       error ("function '%D' is initialized like a variable", decl);
        initialized = 0;
        break;
 
       case PARM_DECL:
        /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE.  */
        initialized = 0;
        break;
 
       case PARM_DECL:
        /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE.  */
-       error ("parameter `%s' is initialized",
-              IDENTIFIER_POINTER (DECL_NAME (decl)));
+       error ("parameter '%D' is initialized", decl);
        initialized = 0;
        break;
 
       default:
        initialized = 0;
        break;
 
       default:
-       /* Don't allow initializations for incomplete types
-          except for arrays which might be completed by the initialization.  */
+       /* Don't allow initializations for incomplete types except for
+          arrays which might be completed by the initialization.  */
 
 
-       /* This can happen if the array size is an undefined macro.  We already
-          gave a warning, so we don't need another one.  */
+       /* This can happen if the array size is an undefined macro.
+          We already gave a warning, so we don't need another one.  */
        if (TREE_TYPE (decl) == error_mark_node)
          initialized = 0;
        else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
        if (TREE_TYPE (decl) == error_mark_node)
          initialized = 0;
        else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
@@ -2553,27 +2908,24 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
          }
        else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
          {
          }
        else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
          {
-           error ("variable `%s' has initializer but incomplete type",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
+           error ("variable '%D' has initializer but incomplete type", decl);
            initialized = 0;
          }
        else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          {
            initialized = 0;
          }
        else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          {
-           error ("elements of array `%s' have incomplete type",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
+           error ("elements of array '%D' have incomplete type", decl);
            initialized = 0;
          }
       }
 
   if (initialized)
     {
            initialized = 0;
          }
       }
 
   if (initialized)
     {
-      DECL_EXTERNAL (decl) = 0;
-      if (current_scope == global_scope)
+      if (current_scope == file_scope)
        TREE_STATIC (decl) = 1;
 
        TREE_STATIC (decl) = 1;
 
-      /* Tell `pushdecl' this is an initialized decl
+      /* Tell 'pushdecl' this is an initialized decl
         even though we don't yet have the initializer expression.
         even though we don't yet have the initializer expression.
-        Also tell `finish_decl' it may store the real initializer.  */
+        Also tell 'finish_decl' it may store the real initializer.  */
       DECL_INITIAL (decl) = error_mark_node;
     }
 
       DECL_INITIAL (decl) = error_mark_node;
     }
 
@@ -2617,7 +2969,7 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
          for (; args; args = TREE_CHAIN (args))
            {
              tree type = TREE_TYPE (args);
          for (; args; args = TREE_CHAIN (args))
            {
              tree type = TREE_TYPE (args);
-             if (INTEGRAL_TYPE_P (type)
+             if (type && INTEGRAL_TYPE_P (type)
                  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
                DECL_ARG_TYPE (args) = integer_type_node;
            }
                  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
                DECL_ARG_TYPE (args) = integer_type_node;
            }
@@ -2634,20 +2986,8 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
 
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
 
-  /* For a local variable, define the RTL now.  */
-  if (current_scope != global_scope
-      /* But not if this is a duplicate decl
-        and we preserved the rtl from the previous one
-        (which may or may not happen).  */
-      && !DECL_RTL_SET_P (tem)
-      && DECL_FILE_SCOPE_P (tem))
-    {
-      if (TREE_TYPE (tem) != error_mark_node
-         && (COMPLETE_TYPE_P (TREE_TYPE (tem))
-             || (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
-                 && DECL_INITIAL (tem) != 0)))
-       expand_decl (tem);
-    }
+  if (initialized)
+    DECL_EXTERNAL (tem) = 0;
 
   return tem;
 }
 
   return tem;
 }
@@ -2665,7 +3005,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
   const char *asmspec = 0;
 
   /* If a name was specified, get the string.  */
   const char *asmspec = 0;
 
   /* If a name was specified, get the string.  */
-  if (current_scope == global_scope)
+  if (current_scope == file_scope)
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -2682,8 +3022,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
     store_init_value (decl, init);
 
   if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
     store_init_value (decl, init);
 
   if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
-                   || TREE_CODE (decl) == FUNCTION_DECL
-                   || TREE_CODE (decl) == FIELD_DECL))
+                           || TREE_CODE (decl) == FUNCTION_DECL
+                           || TREE_CODE (decl) == FIELD_DECL))
     objc_check_decl (decl);
 
   /* Deduce size of array from initialization, if not already known.  */
     objc_check_decl (decl);
 
   /* Deduce size of array from initialization, if not already known.  */
@@ -2724,7 +3064,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
         in the array, because we start counting at zero.  Therefore,
         warn only if the value is less than zero.  */
       else if (pedantic && TYPE_DOMAIN (type) != 0
         in the array, because we start counting at zero.  Therefore,
         warn only if the value is less than zero.  */
       else if (pedantic && TYPE_DOMAIN (type) != 0
-             && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+              && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
        error ("%Jzero or negative size array '%D'", decl, decl);
 
       layout_decl (decl, 0);
        error ("%Jzero or negative size array '%D'", decl, decl);
 
       layout_decl (decl, 0);
@@ -2740,22 +3080,20 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
          /* Don't give an error if we already gave one earlier.  */
          && TREE_TYPE (decl) != error_mark_node
          && (TREE_STATIC (decl)
          /* Don't give an error if we already gave one earlier.  */
          && TREE_TYPE (decl) != error_mark_node
          && (TREE_STATIC (decl)
-             ?
-               /* A static variable with an incomplete type
-                  is an error if it is initialized.
-                  Also if it is not file scope.
-                  Otherwise, let it through, but if it is not `extern'
-                  then it may cause an error message later.  */
-               (DECL_INITIAL (decl) != 0
+             /* A static variable with an incomplete type
+                is an error if it is initialized.
+                Also if it is not file scope.
+                Otherwise, let it through, but if it is not `extern'
+                then it may cause an error message later.  */
+             ? (DECL_INITIAL (decl) != 0
                 || !DECL_FILE_SCOPE_P (decl))
                 || !DECL_FILE_SCOPE_P (decl))
-             :
-               /* An automatic variable with an incomplete type
-                  is an error.  */
-               !DECL_EXTERNAL (decl)))
-       {
-         error ("%Jstorage size of '%D' isn't known", decl, decl);
-         TREE_TYPE (decl) = error_mark_node;
-       }
+             /* An automatic variable with an incomplete type
+                is an error.  */
+             : !DECL_EXTERNAL (decl)))
+        {
+          error ("%Jstorage size of '%D' isn't known", decl, decl);
+          TREE_TYPE (decl) = error_mark_node;
+        }
 
       if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
          && DECL_SIZE (decl) != 0)
 
       if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
          && DECL_SIZE (decl) != 0)
@@ -2775,37 +3113,28 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
      was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
      was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
-      /* ASMSPEC is given, and not the name of a register.  Mark the
-      name with a star so assemble_name won't munge it.  */
-      char *starred = alloca (strlen (asmspec) + 2);
-      starred[0] = '*';
-      strcpy (starred + 1, asmspec);
-
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
        {
          tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
        {
          tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
-         SET_DECL_RTL (builtin, NULL_RTX);
-         SET_DECL_ASSEMBLER_NAME (builtin, get_identifier (starred));
-#ifdef TARGET_MEM_FUNCTIONS
-         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
-           init_block_move_fn (starred);
-         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
-           init_block_clear_fn (starred);
-#else
-         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY)
-           init_block_move_fn (starred);
-         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO)
-           init_block_clear_fn (starred);
-#endif
-       }
-      SET_DECL_RTL (decl, NULL_RTX);
-      change_decl_assembler_name (decl, get_identifier (starred));
+         set_user_assembler_name (builtin, asmspec);
+          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);
+        }
+      set_user_assembler_name (decl, asmspec);
     }
 
   /* If #pragma weak was used, mark the decl weak now.  */
     }
 
   /* If #pragma weak was used, mark the decl weak now.  */
-  if (current_scope == global_scope)
+  if (current_scope == file_scope)
     maybe_apply_pragma_weak (decl);
 
     maybe_apply_pragma_weak (decl);
 
+  /* If this is a variable definition, determine its ELF visibility.  */
+  if (TREE_CODE (decl) == VAR_DECL 
+      && TREE_STATIC (decl) 
+      && !DECL_EXTERNAL (decl))
+    c_determine_visibility (decl);
+
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
      If not, it will get done when the type is completed.  */
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
      If not, it will get done when the type is completed.  */
@@ -2816,6 +3145,25 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
       if (c_dialect_objc ())
        objc_check_decl (decl);
 
       if (c_dialect_objc ())
        objc_check_decl (decl);
 
+      if (asmspec) 
+       {
+         /* If this is not a static variable, issue a warning.
+            It doesn't make any sense to give an ASMSPEC for an
+            ordinary, non-register local variable.  Historically,
+            GCC has accepted -- but ignored -- the ASMSPEC in
+            this case.  */
+         if (! DECL_FILE_SCOPE_P (decl)
+             && TREE_CODE (decl) == VAR_DECL
+             && !C_DECL_REGISTER (decl)
+             && !TREE_STATIC (decl))
+           warning ("%Jignoring asm-specifier for non-static local "
+                    "variable '%D'", decl, decl);
+         else if (C_DECL_REGISTER (decl))
+           change_decl_assembler_name (decl, get_identifier (asmspec));
+         else
+           set_user_assembler_name (decl, asmspec);
+       }
+      
       if (DECL_FILE_SCOPE_P (decl))
        {
          if (DECL_INITIAL (decl) == NULL_TREE
       if (DECL_FILE_SCOPE_P (decl))
        {
          if (DECL_INITIAL (decl) == NULL_TREE
@@ -2824,37 +3172,44 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
               when a tentative file-scope definition is seen.
               But at end of compilation, do output code for them.  */
            DECL_DEFER_OUTPUT (decl) = 1;
               when a tentative file-scope definition is seen.
               But at end of compilation, do output code for them.  */
            DECL_DEFER_OUTPUT (decl) = 1;
-         rest_of_decl_compilation (decl, asmspec, true, 0);
+         rest_of_decl_compilation (decl, true, 0);
        }
       else
        {
        }
       else
        {
-         /* This is a local variable.  If there is an ASMSPEC, the
-            user has requested that we handle it specially.  */
-         if (asmspec)
+         /* In conjunction with an ASMSPEC, the `register'
+            keyword indicates that we should place the variable
+            in a particular register.  */
+         if (asmspec && C_DECL_REGISTER (decl))
            {
            {
-             /* In conjunction with an ASMSPEC, the `register'
-                keyword indicates that we should place the variable
-                in a particular register.  */
-             if (DECL_REGISTER (decl))
-               DECL_C_HARD_REGISTER (decl) = 1;
-
-             /* If this is not a static variable, issue a warning.
-                It doesn't make any sense to give an ASMSPEC for an
-                ordinary, non-register local variable.  Historically,
-                GCC has accepted -- but ignored -- the ASMSPEC in
-                this case.  */
-             if (TREE_CODE (decl) == VAR_DECL
-                 && !DECL_REGISTER (decl)
-                 && !TREE_STATIC (decl))
-               warning ("%Jignoring asm-specifier for non-static local "
-                         "variable '%D'", decl, decl);
-             else
-               change_decl_assembler_name (decl, get_identifier (asmspec));
+             DECL_HARD_REGISTER (decl) = 1;
+             /* This cannot be done for a structure with volatile
+                fields, on which DECL_REGISTER will have been
+                reset.  */
+             if (!DECL_REGISTER (decl))
+               error ("cannot put object with volatile field into register");
            }
 
          if (TREE_CODE (decl) != FUNCTION_DECL)
            }
 
          if (TREE_CODE (decl) != FUNCTION_DECL)
-           add_decl_stmt (decl);
+           {
+             /* If we're building a variable sized type, and we might be
+                reachable other than via the top of the current binding
+                level, then create a new BIND_EXPR so that we deallocate
+                the object at the right time.  */
+             /* Note that DECL_SIZE can be null due to errors.  */
+             if (DECL_SIZE (decl)
+                 && !TREE_CONSTANT (DECL_SIZE (decl))
+                 && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
+               {
+                 tree bind;
+                 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+                 TREE_SIDE_EFFECTS (bind) = 1;
+                 add_stmt (bind);
+                 BIND_EXPR_BODY (bind) = push_stmt_list ();
+               }
+             add_stmt (build_stmt (DECL_EXPR, decl));
+           }
        }
        }
+  
 
       if (!DECL_FILE_SCOPE_P (decl))
        {
 
       if (!DECL_FILE_SCOPE_P (decl))
        {
@@ -2874,15 +3229,21 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
 
   /* If this was marked 'used', be sure it will be output.  */
   if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
 
   /* If this was marked 'used', be sure it will be output.  */
   if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
-    mark_referenced (DECL_ASSEMBLER_NAME (decl));
+    mark_decl_referenced (decl);
 
   if (TREE_CODE (decl) == TYPE_DECL)
 
   if (TREE_CODE (decl) == TYPE_DECL)
-    rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+    {
+      if (!DECL_FILE_SCOPE_P (decl)
+         && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+       add_stmt (build_stmt (DECL_EXPR, decl));
+
+      rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
+    }
 
   /* At the end of a declaration, throw away any variable type sizes
      of types defined inside that declaration.  There is no use
      computing them in the following function definition.  */
 
   /* At the end of a declaration, throw away any variable type sizes
      of types defined inside that declaration.  There is no use
      computing them in the following function definition.  */
-  if (current_scope == global_scope)
+  if (current_scope == file_scope)
     get_pending_sizes ();
 
   /* Install a cleanup (aka destructor) if one was given.  */
     get_pending_sizes ();
 
   /* Install a cleanup (aka destructor) if one was given.  */
@@ -2891,8 +3252,6 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
       tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
       if (attr)
        {
       tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
       if (attr)
        {
-         static bool eh_initialized_p;
-
          tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
          tree cleanup_decl = lookup_name (cleanup_id);
          tree cleanup;
          tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
          tree cleanup_decl = lookup_name (cleanup_id);
          tree cleanup;
@@ -2904,11 +3263,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
 
          /* Don't warn about decl unused; the cleanup uses it.  */
          TREE_USED (decl) = 1;
 
          /* Don't warn about decl unused; the cleanup uses it.  */
          TREE_USED (decl) = 1;
+         TREE_USED (cleanup_decl) = 1;
 
          /* Initialize EH, if we've been told to do so.  */
 
          /* Initialize EH, if we've been told to do so.  */
-         if (flag_exceptions && !eh_initialized_p)
+         if (flag_exceptions && !c_eh_initialized_p)
            {
            {
-             eh_initialized_p = true;
+             c_eh_initialized_p = true;
              eh_personality_libfunc
                = init_one_libfunc (USING_SJLJ_EXCEPTIONS
                                    ? "__gcc_personality_sj0"
              eh_personality_libfunc
                = init_one_libfunc (USING_SJLJ_EXCEPTIONS
                                    ? "__gcc_personality_sj0"
@@ -2916,11 +3276,25 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
              using_eh_for_cleanups ();
            }
 
              using_eh_for_cleanups ();
            }
 
-         add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+         push_cleanup (decl, cleanup, false);
        }
     }
 }
 
        }
     }
 }
 
+/* Given a parsed parameter declaration, decode it into a PARM_DECL.  */
+
+tree
+grokparm (tree parm)
+{
+  tree decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
+                             TREE_PURPOSE (TREE_PURPOSE (parm)),
+                             PARM, false, NULL);
+
+  decl_attributes (&decl, TREE_VALUE (parm), 0);
+
+  return decl;
+}
+
 /* Given a parsed parameter declaration, decode it into a PARM_DECL
    and push that on the current scope.  */
 
 /* Given a parsed parameter declaration, decode it into a PARM_DECL
    and push that on the current scope.  */
 
@@ -2929,31 +3303,23 @@ push_parm_decl (tree parm)
 {
   tree decl;
 
 {
   tree decl;
 
-  /* Don't attempt to expand sizes while parsing this decl.
-     (We can get here with i_s_e 1 somehow from Objective-C.)  */
-  int save_immediate_size_expand = immediate_size_expand;
-  immediate_size_expand = 0;
-
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
                         TREE_PURPOSE (TREE_PURPOSE (parm)),
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
                         TREE_PURPOSE (TREE_PURPOSE (parm)),
-                        PARM, 0, NULL);
+                        PARM, false, NULL);
   decl_attributes (&decl, TREE_VALUE (parm), 0);
 
   decl = pushdecl (decl);
 
   finish_decl (decl, NULL_TREE, NULL_TREE);
   decl_attributes (&decl, TREE_VALUE (parm), 0);
 
   decl = pushdecl (decl);
 
   finish_decl (decl, NULL_TREE, NULL_TREE);
-
-  immediate_size_expand = save_immediate_size_expand;
 }
 
 }
 
-/* Mark all the parameter declarations to date as forward decls,
-   shift them to the variables list, and reset the parameters list.
+/* Mark all the parameter declarations to date as forward decls.
    Also diagnose use of this extension.  */
 
 void
 mark_forward_parm_decls (void)
 {
    Also diagnose use of this extension.  */
 
 void
 mark_forward_parm_decls (void)
 {
-  tree parm;
+  struct c_binding *b;
 
   if (pedantic && !current_scope->warned_forward_parm_decls)
     {
 
   if (pedantic && !current_scope->warned_forward_parm_decls)
     {
@@ -2961,12 +3327,9 @@ mark_forward_parm_decls (void)
       current_scope->warned_forward_parm_decls = true;
     }
 
       current_scope->warned_forward_parm_decls = true;
     }
 
-  for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
-    TREE_ASM_WRITTEN (parm) = 1;
-
-  SCOPE_LIST_CONCAT (current_scope, names, current_scope, parms);
-  current_scope->parms = 0;
-  current_scope->parms_last = 0;
+  for (b = current_scope->bindings; b; b = b->prev)
+    if (TREE_CODE (b->decl) == PARM_DECL)
+      TREE_ASM_WRITTEN (b->decl) = 1;
 }
 \f
 static GTY(()) int compound_literal_number;
 }
 \f
 static GTY(()) int compound_literal_number;
@@ -2981,17 +3344,17 @@ build_compound_literal (tree type, tree init)
 {
   /* We do not use start_decl here because we have a type, not a declarator;
      and do not use finish_decl because the decl should be stored inside
 {
   /* We do not use start_decl here because we have a type, not a declarator;
      and do not use finish_decl because the decl should be stored inside
-     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT.  */
+     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR.  */
   tree decl = build_decl (VAR_DECL, NULL_TREE, type);
   tree complit;
   tree stmt;
   DECL_EXTERNAL (decl) = 0;
   TREE_PUBLIC (decl) = 0;
   tree decl = build_decl (VAR_DECL, NULL_TREE, type);
   tree complit;
   tree stmt;
   DECL_EXTERNAL (decl) = 0;
   TREE_PUBLIC (decl) = 0;
-  TREE_STATIC (decl) = (current_scope == global_scope);
+  TREE_STATIC (decl) = (current_scope == file_scope);
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
-  TREE_READONLY (decl) = TREE_READONLY (type);
+  TREE_READONLY (decl) = TYPE_READONLY (type);
   store_init_value (decl, init);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
   store_init_value (decl, init);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
@@ -3005,7 +3368,7 @@ build_compound_literal (tree type, tree init)
   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
     return error_mark_node;
 
   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
     return error_mark_node;
 
-  stmt = build_stmt (DECL_STMT, decl);
+  stmt = build_stmt (DECL_EXPR, decl);
   complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
   TREE_SIDE_EFFECTS (complit) = 1;
 
   complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
   TREE_SIDE_EFFECTS (complit) = 1;
 
@@ -3025,7 +3388,7 @@ build_compound_literal (tree type, tree init)
       DECL_COMDAT (decl) = 1;
       DECL_ARTIFICIAL (decl) = 1;
       pushdecl (decl);
       DECL_COMDAT (decl) = 1;
       DECL_ARTIFICIAL (decl) = 1;
       pushdecl (decl);
-      rest_of_decl_compilation (decl, NULL, 1, 0);
+      rest_of_decl_compilation (decl, 1, 0);
     }
 
   return complit;
     }
 
   return complit;
@@ -3049,22 +3412,22 @@ complete_array_type (tree type, tree initial_value, int do_default)
        {
          int eltsize
            = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
        {
          int eltsize
            = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
-         maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
-                                  / eltsize) - 1, 0);
+         maxindex = build_int_cst (NULL_TREE,
+                                   (TREE_STRING_LENGTH (initial_value)
+                                    / eltsize) - 1);
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
          tree elts = CONSTRUCTOR_ELTS (initial_value);
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
          tree elts = CONSTRUCTOR_ELTS (initial_value);
-         maxindex = build_int_2 (-1, -1);
+         maxindex = build_int_cst (NULL_TREE, -1);
          for (; elts; elts = TREE_CHAIN (elts))
            {
              if (TREE_PURPOSE (elts))
                maxindex = TREE_PURPOSE (elts);
              else
          for (; elts; elts = TREE_CHAIN (elts))
            {
              if (TREE_PURPOSE (elts))
                maxindex = TREE_PURPOSE (elts);
              else
-               maxindex = fold (build (PLUS_EXPR, integer_type_node,
-                                       maxindex, integer_one_node));
+               maxindex = fold (build2 (PLUS_EXPR, integer_type_node,
+                                        maxindex, integer_one_node));
            }
            }
-         maxindex = copy_node (maxindex);
        }
       else
        {
        }
       else
        {
@@ -3073,14 +3436,14 @@ complete_array_type (tree type, tree initial_value, int do_default)
            value = 1;
 
          /* Prevent further error messages.  */
            value = 1;
 
          /* Prevent further error messages.  */
-         maxindex = build_int_2 (0, 0);
+         maxindex = build_int_cst (NULL_TREE, 0);
        }
     }
 
   if (!maxindex)
     {
       if (do_default)
        }
     }
 
   if (!maxindex)
     {
       if (do_default)
-       maxindex = build_int_2 (0, 0);
+       maxindex = build_int_cst (NULL_TREE, 0);
       value = 2;
     }
 
       value = 2;
     }
 
@@ -3088,7 +3451,7 @@ complete_array_type (tree type, tree initial_value, int do_default)
     {
       TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (!TREE_TYPE (maxindex))
     {
       TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (!TREE_TYPE (maxindex))
-       TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+       abort ();
     }
 
   /* Lay out the type now that we can get the real answer.  */
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -3191,15 +3554,19 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
     {
       error ("width of `%s' exceeds its type", name);
       w = max_width;
     {
       error ("width of `%s' exceeds its type", name);
       w = max_width;
-      *width = build_int_2 (w, 0);
+      *width = build_int_cst (NULL_TREE, w);
     }
   else
     w = tree_low_cst (*width, 1);
 
     }
   else
     w = tree_low_cst (*width, 1);
 
-  if (TREE_CODE (*type) == ENUMERAL_TYPE
-      && (w < min_precision (TYPE_MIN_VALUE (*type), TREE_UNSIGNED (*type))
-         || w < min_precision (TYPE_MAX_VALUE (*type), TREE_UNSIGNED (*type))))
-    warning ("`%s' is narrower than values of its type", name);
+  if (TREE_CODE (*type) == ENUMERAL_TYPE)
+    {
+      struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
+      if (!lt
+          || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+         || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+       warning ("`%s' is narrower than values of its type", name);
+    }
 }
 \f
 /* Given declspecs and a declarator,
 }
 \f
 /* Given declspecs and a declarator,
@@ -3221,7 +3588,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
      TYPENAME if for a typename (in a cast or sizeof).
       Don't make a DECL node; just return the ..._TYPE node.
      FIELD for a struct or union field; make a FIELD_DECL.
      TYPENAME if for a typename (in a cast or sizeof).
       Don't make a DECL node; just return the ..._TYPE node.
      FIELD for a struct or union field; make a FIELD_DECL.
-   INITIALIZED is 1 if the decl has an initializer.
+   INITIALIZED is true if the decl has an initializer.
    WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
    representing the width of the bit-field.
 
    WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
    representing the width of the bit-field.
 
@@ -3234,7 +3601,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
 
 static tree
 grokdeclarator (tree declarator, tree declspecs,
 
 static tree
 grokdeclarator (tree declarator, tree declspecs,
-               enum decl_context decl_context, int initialized, tree *width)
+               enum decl_context decl_context, bool initialized, tree *width)
 {
   int specbits = 0;
   tree spec;
 {
   int specbits = 0;
   tree spec;
@@ -3260,6 +3627,7 @@ grokdeclarator (tree declarator, tree declspecs,
   tree returned_attrs = NULL_TREE;
   bool bitfield = width != NULL;
   tree element_type;
   tree returned_attrs = NULL_TREE;
   bool bitfield = width != NULL;
   tree element_type;
+  tree arg_info = NULL_TREE;
 
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
 
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
@@ -3306,8 +3674,7 @@ grokdeclarator (tree declarator, tree declspecs,
   /* If this looks like a function definition, make it one,
      even if it occurs where parms are expected.
      Then store_parm_decls will reject it and not use it as a parm.  */
   /* If this looks like a function definition, make it one,
      even if it occurs where parms are expected.
      Then store_parm_decls will reject it and not use it as a parm.  */
-  if (decl_context == NORMAL && !funcdef_flag
-      && current_scope->parm_flag)
+  if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
     decl_context = PARM;
 
   /* Look through the decl specs and record which ones appear.
     decl_context = PARM;
 
   /* Look through the decl specs and record which ones appear.
@@ -3362,7 +3729,7 @@ grokdeclarator (tree declarator, tree declspecs,
                {
                  if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
                    {
                {
                  if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
                    {
-                     if (!flag_isoc99)
+                     if (pedantic && !flag_isoc99)
                        pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
                    }
                  else
                        pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
                    }
                  else
@@ -3403,11 +3770,11 @@ grokdeclarator (tree declarator, tree declspecs,
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
        {
          tree t = lookup_name (id);
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
        {
          tree t = lookup_name (id);
-         if (TREE_TYPE (t) == error_mark_node)
-           ;
-         else if (!t || TREE_CODE (t) != TYPE_DECL)
+          if (!t || TREE_CODE (t) != TYPE_DECL)
            error ("`%s' fails to be a typedef or built in type",
                   IDENTIFIER_POINTER (id));
            error ("`%s' fails to be a typedef or built in type",
                   IDENTIFIER_POINTER (id));
+          else if (TREE_TYPE (t) == error_mark_node)
+           ;
          else
            {
              type = TREE_TYPE (t);
          else
            {
              type = TREE_TYPE (t);
@@ -3619,12 +3986,15 @@ grokdeclarator (tree declarator, tree declspecs,
   volatilep
     = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type);
   inlinep = !! (specbits & (1 << (int) RID_INLINE));
   volatilep
     = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type);
   inlinep = !! (specbits & (1 << (int) RID_INLINE));
-  if (constp > 1 && ! flag_isoc99)
-    pedwarn ("duplicate `const'");
-  if (restrictp > 1 && ! flag_isoc99)
-    pedwarn ("duplicate `restrict'");
-  if (volatilep > 1 && ! flag_isoc99)
-    pedwarn ("duplicate `volatile'");
+  if (pedantic && !flag_isoc99)
+    {
+      if (constp > 1)
+       pedwarn ("duplicate `const'");
+      if (restrictp > 1)
+       pedwarn ("duplicate `restrict'");
+      if (volatilep > 1)
+       pedwarn ("duplicate `volatile'");
+    }
   if (! flag_gen_aux_info && (TYPE_QUALS (type)))
     type = TYPE_MAIN_VARIANT (type);
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
   if (! flag_gen_aux_info && (TYPE_QUALS (type)))
     type = TYPE_MAIN_VARIANT (type);
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
@@ -3661,7 +4031,7 @@ grokdeclarator (tree declarator, tree declspecs,
                    | (1 << (int) RID_THREAD))))
       {
        if (specbits & 1 << (int) RID_AUTO
                    | (1 << (int) RID_THREAD))))
       {
        if (specbits & 1 << (int) RID_AUTO
-           && (pedantic || current_scope == global_scope))
+           && (pedantic || current_scope == file_scope))
          pedwarn ("function definition declared `auto'");
        if (specbits & 1 << (int) RID_REGISTER)
          error ("function definition declared `register'");
          pedwarn ("function definition declared `auto'");
        if (specbits & 1 << (int) RID_REGISTER)
          error ("function definition declared `register'");
@@ -3699,12 +4069,12 @@ grokdeclarator (tree declarator, tree declspecs,
     else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
       {
        /* `extern' with initialization is invalid if not at file scope.  */
     else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
       {
        /* `extern' with initialization is invalid if not at file scope.  */
-       if (current_scope == global_scope)
+       if (current_scope == file_scope)
          warning ("`%s' initialized and declared `extern'", name);
        else
          error ("`%s' has both `extern' and initializer", name);
       }
          warning ("`%s' initialized and declared `extern'", name);
        else
          error ("`%s' has both `extern' and initializer", name);
       }
-    else if (current_scope == global_scope)
+    else if (current_scope == file_scope)
       {
        if (specbits & 1 << (int) RID_AUTO)
          error ("file-scope declaration of `%s' specifies `auto'", name);
       {
        if (specbits & 1 << (int) RID_AUTO)
          error ("file-scope declaration of `%s' specifies `auto'", name);
@@ -3811,7 +4181,7 @@ grokdeclarator (tree declarator, tree declspecs,
              type = error_mark_node;
            }
 
              type = error_mark_node;
            }
 
-         if (pedantic && flexible_array_type_p (type))
+         if (pedantic && !in_system_header && flexible_array_type_p (type))
            pedwarn ("invalid use of structure with flexible array member");
 
          if (size == error_mark_node)
            pedwarn ("invalid use of structure with flexible array member");
 
          if (size == error_mark_node)
@@ -3877,9 +4247,9 @@ grokdeclarator (tree declarator, tree declspecs,
                     Do the calculation in index_type, so that if it is
                     a variable the computations will be done in the
                     proper mode.  */
                     Do the calculation in index_type, so that if it is
                     a variable the computations will be done in the
                     proper mode.  */
-                 itype = fold (build (MINUS_EXPR, index_type,
-                                      convert (index_type, size),
-                                      convert (index_type, size_one_node)));
+                 itype = fold (build2 (MINUS_EXPR, index_type,
+                                       convert (index_type, size),
+                                       convert (index_type, size_one_node)));
 
                  /* If that overflowed, the array is too big.
                     ??? While a size of INT_MAX+1 technically shouldn't
 
                  /* If that overflowed, the array is too big.
                     ??? While a size of INT_MAX+1 technically shouldn't
@@ -3895,20 +4265,7 @@ grokdeclarator (tree declarator, tree declspecs,
                    }
 
                  if (size_varies)
                    }
 
                  if (size_varies)
-                   {
-                     /* 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 = variable_size (itype);
                  itype = build_index_type (itype);
                }
            }
                  itype = build_index_type (itype);
                }
            }
@@ -3947,6 +4304,11 @@ grokdeclarator (tree declarator, tree declspecs,
              TYPE_SIZE (type) = bitsize_zero_node;
              TYPE_SIZE_UNIT (type) = size_zero_node;
            }
              TYPE_SIZE (type) = bitsize_zero_node;
              TYPE_SIZE_UNIT (type) = size_zero_node;
            }
+         else if (declarator && TREE_CODE (declarator) == INDIRECT_REF)
+           /* We can never complete an array type which is the target of a
+              pointer, so go ahead and lay it out.  */
+           layout_type (type);
+
          if (decl_context != PARM
              && (array_ptr_quals != NULL_TREE || array_parm_static))
            {
          if (decl_context != PARM
              && (array_ptr_quals != NULL_TREE || array_parm_static))
            {
@@ -3957,7 +4319,17 @@ grokdeclarator (tree declarator, tree declspecs,
        }
       else if (TREE_CODE (declarator) == CALL_EXPR)
        {
        }
       else if (TREE_CODE (declarator) == CALL_EXPR)
        {
+         /* Say it's a definition only for the declarator closest to
+            the identifier, apart possibly from some attributes.  */
+         bool really_funcdef = false;
          tree arg_types;
          tree arg_types;
+         if (funcdef_flag)
+           {
+             tree t = TREE_OPERAND (declarator, 0);
+             while (TREE_CODE (t) == TREE_LIST)
+               t = TREE_VALUE (t);
+             really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE);
+           }
 
          /* Declaring a function type.
             Make sure we have a valid type for the function to return.  */
 
          /* Declaring a function type.
             Make sure we have a valid type for the function to return.  */
@@ -3981,32 +4353,22 @@ grokdeclarator (tree declarator, tree declspecs,
 
          /* Construct the function type and go to the next
             inner layer of declarator.  */
 
          /* Construct the function type and go to the next
             inner layer of declarator.  */
+         arg_info = TREE_OPERAND (declarator, 1);
+         arg_types = grokparms (arg_info, really_funcdef);
 
 
-         arg_types = grokparms (TREE_OPERAND (declarator, 1),
-                                funcdef_flag
-                                /* Say it's a definition
-                                   only for the CALL_EXPR
-                                   closest to the identifier.  */
-                                && TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
          /* Type qualifiers before the return type of the function
             qualify the return type, not the function type.  */
          if (type_quals)
            {
          /* Type qualifiers before the return type of the function
             qualify the return type, not the function type.  */
          if (type_quals)
            {
-             /* Type qualifiers on a function return type are normally
-                permitted by the standard but have no effect, so give a
-                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
-                definitions, but not doing so could lead to the undesirable
-                state of a "volatile void" function return type not being
-                warned about, and a use of the function being compiled
-                with GNU semantics, with no diagnostics under -pedantic.  */
-             if (VOID_TYPE_P (type) && pedantic && !in_system_header)
-               pedwarn ("ISO C forbids qualified void function return type");
-             else if (extra_warnings
-                      && !(VOID_TYPE_P (type)
-                           && type_quals == TYPE_QUAL_VOLATILE))
+             /* Type qualifiers on a function return type are
+                normally permitted by the standard but have no
+                effect, so give a warning at -Wreturn-type.
+                Qualifiers on a void return type are banned on
+                function definitions in ISO C; GCC used to used them
+                for noreturn functions.  */
+             if (VOID_TYPE_P (type) && really_funcdef)
+               pedwarn ("function definition has qualified void return type");
+             else if (warn_return_type)
                warning ("type qualifiers ignored on function return type");
 
              type = c_build_qualified_type (type, type_quals);
                warning ("type qualifiers ignored on function return type");
 
              type = c_build_qualified_type (type, type_quals);
@@ -4023,7 +4385,7 @@ grokdeclarator (tree declarator, tree declspecs,
          {
            tree link;
 
          {
            tree link;
 
-           for (link = last_function_parm_tags;
+           for (link = ARG_INFO_TAGS (arg_info);
                 link;
                 link = TREE_CHAIN (link))
              TYPE_CONTEXT (TREE_VALUE (link)) = type;
                 link;
                 link = TREE_CHAIN (link))
              TYPE_CONTEXT (TREE_VALUE (link)) = type;
@@ -4077,12 +4439,15 @@ grokdeclarator (tree declarator, tree declspecs,
 
              if (erred)
                error ("invalid type modifier within pointer declarator");
 
              if (erred)
                error ("invalid type modifier within pointer declarator");
-             if (constp > 1 && ! flag_isoc99)
-               pedwarn ("duplicate `const'");
-             if (volatilep > 1 && ! flag_isoc99)
-               pedwarn ("duplicate `volatile'");
-             if (restrictp > 1 && ! flag_isoc99)
-               pedwarn ("duplicate `restrict'");
+             if (pedantic && !flag_isoc99)
+               {
+                 if (constp > 1)
+                   pedwarn ("duplicate `const'");
+                 if (volatilep > 1)
+                   pedwarn ("duplicate `volatile'");
+                 if (restrictp > 1)
+                   pedwarn ("duplicate `restrict'");
+               }
 
              type_quals = ((constp ? TYPE_QUAL_CONST : 0)
                            | (restrictp ? TYPE_QUAL_RESTRICT : 0)
 
              type_quals = ((constp ? TYPE_QUAL_CONST : 0)
                            | (restrictp ? TYPE_QUAL_RESTRICT : 0)
@@ -4170,7 +4535,7 @@ grokdeclarator (tree declarator, tree declspecs,
   if (VOID_TYPE_P (type) && decl_context != PARM
       && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
            && ((specbits & (1 << (int) RID_EXTERN))
   if (VOID_TYPE_P (type) && decl_context != PARM
       && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
            && ((specbits & (1 << (int) RID_EXTERN))
-               || (current_scope == global_scope
+               || (current_scope == file_scope
                    && !(specbits
                         & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
     {
                    && !(specbits
                         & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
     {
@@ -4299,16 +4664,8 @@ grokdeclarator (tree declarator, tree declspecs,
       }
     else if (TREE_CODE (type) == FUNCTION_TYPE)
       {
       }
     else if (TREE_CODE (type) == FUNCTION_TYPE)
       {
-       /* Every function declaration is "external"
-          except for those which are inside a function body
-          in which `auto' is used.
-          That is a case not specified by ANSI C,
-          and we use it for forward declarations for nested functions.  */
-       int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
-                         || current_scope == global_scope);
-
        if (specbits & (1 << (int) RID_AUTO)
        if (specbits & (1 << (int) RID_AUTO)
-           && (pedantic || current_scope == global_scope))
+           && (pedantic || current_scope == file_scope))
          pedwarn ("invalid storage class for function `%s'", name);
        if (specbits & (1 << (int) RID_REGISTER))
          error ("invalid storage class for function `%s'", name);
          pedwarn ("invalid storage class for function `%s'", name);
        if (specbits & (1 << (int) RID_REGISTER))
          error ("invalid storage class for function `%s'", name);
@@ -4317,7 +4674,7 @@ grokdeclarator (tree declarator, tree declspecs,
        /* Function declaration not at file scope.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
        /* Function declaration not at file scope.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
-       if (current_scope != global_scope
+       if (current_scope != file_scope
            && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
            && pedantic)
          pedwarn ("invalid storage class for function `%s'", name);
            && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
            && pedantic)
          pedwarn ("invalid storage class for function `%s'", name);
@@ -4326,23 +4683,36 @@ grokdeclarator (tree declarator, tree declspecs,
        decl = build_decl_attribute_variant (decl, decl_attr);
 
        DECL_LANG_SPECIFIC (decl)
        decl = build_decl_attribute_variant (decl, decl_attr);
 
        DECL_LANG_SPECIFIC (decl)
-         = ggc_alloc_cleared (sizeof (struct lang_decl));
+         = GGC_CNEW (struct lang_decl);
 
        if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ISO C forbids qualified function types");
 
 
        if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ISO C forbids qualified function types");
 
-       /* GNU C interprets a `volatile void' return type to indicate
+       /* GNU C interprets a volatile-qualified function type to indicate
           that the function does not return.  */
        if ((type_quals & TYPE_QUAL_VOLATILE)
            && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          warning ("`noreturn' function returns non-void value");
 
           that the function does not return.  */
        if ((type_quals & TYPE_QUAL_VOLATILE)
            && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          warning ("`noreturn' function returns non-void value");
 
-       if (extern_ref)
+       /* Every function declaration is an external reference
+          (DECL_EXTERNAL) except for those which are not at file
+          scope and are explicitly declared "auto".  This is
+          forbidden by standard C (C99 6.7.1p5) and is interpreted by
+          GCC to signify a forward declaration of a nested function.  */
+       if ((specbits & (1 << RID_AUTO)) && current_scope != file_scope)
+         DECL_EXTERNAL (decl) = 0;
+       else
          DECL_EXTERNAL (decl) = 1;
          DECL_EXTERNAL (decl) = 1;
+
        /* Record absence of global scope for `static' or `auto'.  */
        TREE_PUBLIC (decl)
          = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
 
        /* Record absence of global scope for `static' or `auto'.  */
        TREE_PUBLIC (decl)
          = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
 
+       /* For a function definition, record the argument information
+          block where store_parm_decls will look for it.  */
+       if (funcdef_flag)
+         current_function_arg_info = arg_info;
+
        if (defaulted_int)
          C_FUNCTION_IMPLICIT_INT (decl) = 1;
 
        if (defaulted_int)
          C_FUNCTION_IMPLICIT_INT (decl) = 1;
 
@@ -4392,19 +4762,23 @@ grokdeclarator (tree declarator, tree declspecs,
        else if (type_quals)
          type = c_build_qualified_type (type, type_quals);
 
        else if (type_quals)
          type = c_build_qualified_type (type, type_quals);
 
-       /* It is invalid to create an `extern' declaration for a
+       /* C99 6.2.2p7: It is invalid (compile-time undefined
+          behavior) to create an 'extern' declaration for a
           variable if there is a global declaration that is
           variable if there is a global declaration that is
-          `static'.  */
-       if (extern_ref && current_scope != global_scope)
+          'static' and the global declaration is not visible.
+          (If the static declaration _is_ currently visible,
+          the 'extern' declaration is taken to refer to that decl.) */
+       if (extern_ref && current_scope != file_scope)
          {
          {
-           tree global_decl;
+           tree global_decl  = identifier_global_value (declarator);
+           tree visible_decl = lookup_name (declarator);
 
 
-           global_decl = identifier_global_value (declarator);
            if (global_decl
            if (global_decl
+               && global_decl != visible_decl
                && TREE_CODE (global_decl) == VAR_DECL
                && !TREE_PUBLIC (global_decl))
                && TREE_CODE (global_decl) == VAR_DECL
                && !TREE_PUBLIC (global_decl))
-             error ("variable previously declared `static' redeclared "
-                    "`extern'");
+             error ("variable previously declared 'static' redeclared "
+                    "'extern'");
          }
 
        decl = build_decl (VAR_DECL, declarator, type);
          }
 
        decl = build_decl (VAR_DECL, declarator, type);
@@ -4414,13 +4788,16 @@ grokdeclarator (tree declarator, tree declspecs,
        if (inlinep)
          pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
 
        if (inlinep)
          pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
 
-       DECL_EXTERNAL (decl) = extern_ref;
+       /* At file scope, an initialized extern declaration may follow
+          a static declaration.  In that case, DECL_EXTERNAL will be
+          reset later in start_decl.  */
+       DECL_EXTERNAL (decl) = !!(specbits & (1 << (int) RID_EXTERN));
 
        /* At file scope, 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.  */
 
        /* At file scope, 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_scope == global_scope)
+       if (current_scope == file_scope)
          {
            TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
                                               | (1 << (int) RID_REGISTER)));
          {
            TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
                                               | (1 << (int) RID_REGISTER)));
@@ -4448,7 +4825,10 @@ grokdeclarator (tree declarator, tree declspecs,
        and in case doing stupid register allocation.  */
 
     if (specbits & (1 << (int) RID_REGISTER))
        and in case doing stupid register allocation.  */
 
     if (specbits & (1 << (int) RID_REGISTER))
-      DECL_REGISTER (decl) = 1;
+      {
+       C_DECL_REGISTER (decl) = 1;
+       DECL_REGISTER (decl) = 1;
+      }
 
     /* Record constancy and volatility.  */
     c_apply_type_quals_to_decl (type_quals, decl);
 
     /* Record constancy and volatility.  */
     c_apply_type_quals_to_decl (type_quals, decl);
@@ -4457,7 +4837,16 @@ grokdeclarator (tree declarator, tree declspecs,
        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)))
        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)))
-      c_mark_addressable (decl);
+      {
+       /* It is not an error for a structure with volatile fields to
+          be declared register, but reset DECL_REGISTER since it
+          cannot actually go in a register.  */
+       int was_reg = C_DECL_REGISTER (decl);
+       C_DECL_REGISTER (decl) = 0;
+       DECL_REGISTER (decl) = 0;
+       c_mark_addressable (decl);
+       C_DECL_REGISTER (decl) = was_reg;
+      }
 
 #ifdef ENABLE_CHECKING
   /* This is the earliest point at which we might know the assembler
 
 #ifdef ENABLE_CHECKING
   /* This is the earliest point at which we might know the assembler
@@ -4480,203 +4869,270 @@ grokdeclarator (tree declarator, tree declspecs,
    of calls is different.  The last call to `grokparms' is always the one
    that contains the formal parameter names of a function definition.
 
    of calls is different.  The last call to `grokparms' is always the one
    that contains the formal parameter names of a function definition.
 
-   Store in `last_function_parms' a chain of the decls of parms.
-   Also store in `last_function_parm_tags' a chain of the struct, union,
-   and enum tags declared among the parms.
-
    Return a list of arg types to use in the FUNCTION_TYPE for this function.
 
    Return a list of arg types to use in the FUNCTION_TYPE for this function.
 
-   FUNCDEF_FLAG is nonzero for a function definition, 0 for
+   FUNCDEF_FLAG is true for a function definition, false for
    a mere declaration.  A nonempty identifier-list gets an error message
    a mere declaration.  A nonempty identifier-list gets an error message
-   when FUNCDEF_FLAG is zero.  */
+   when FUNCDEF_FLAG is false.  */
 
 static tree
 
 static tree
-grokparms (tree parms_info, int funcdef_flag)
+grokparms (tree arg_info, bool funcdef_flag)
 {
 {
-  tree first_parm = TREE_CHAIN (parms_info);
+  tree arg_types = ARG_INFO_TYPES (arg_info);
 
 
-  last_function_parms = TREE_PURPOSE (parms_info);
-  last_function_parm_tags = TREE_VALUE (parms_info);
-  last_function_parm_others = TREE_TYPE (parms_info);
-
-  if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag
+  if (warn_strict_prototypes && arg_types == 0 && !funcdef_flag
       && !in_system_header)
     warning ("function declaration isn't a prototype");
 
       && !in_system_header)
     warning ("function declaration isn't a prototype");
 
-  if (first_parm != 0
-      && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE)
+  if (arg_types == error_mark_node)
+    return 0;  /* don't set TYPE_ARG_TYPES in this case */
+
+  else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
     {
       if (! funcdef_flag)
        pedwarn ("parameter names (without types) in function declaration");
 
     {
       if (! funcdef_flag)
        pedwarn ("parameter names (without types) in function declaration");
 
-      last_function_parms = first_parm;
+      ARG_INFO_PARMS (arg_info) = ARG_INFO_TYPES (arg_info);
+      ARG_INFO_TYPES (arg_info) = 0;
       return 0;
     }
   else
     {
       return 0;
     }
   else
     {
-      tree parm;
-      tree typelt;
-      /* If the arg types are incomplete in a declaration,
-        they must include undefined tags.
-        These tags can never be defined in the scope of the declaration,
-        so the types can never be completed,
-        and no call can be compiled successfully.  */
+      tree parm, type, typelt;
+      unsigned int parmno;
 
 
-      for (parm = last_function_parms, typelt = first_parm;
+      /* If the arg types are incomplete in a declaration, they must
+        include undefined tags.  These tags can never be defined in
+        the scope of the declaration, so the types can never be
+        completed, and no call can be compiled successfully.  */
+
+      for (parm = ARG_INFO_PARMS (arg_info), typelt = arg_types, parmno = 1;
           parm;
           parm;
-          parm = TREE_CHAIN (parm))
-       /* Skip over any enumeration constants declared here.  */
-       if (TREE_CODE (parm) == PARM_DECL)
-         {
-           /* Barf if the parameter itself has an incomplete type.  */
-           tree type = TREE_VALUE (typelt);
-           if (type == error_mark_node)
-             continue;
-           if (!COMPLETE_TYPE_P (type))
-             {
-               if (funcdef_flag && DECL_NAME (parm) != 0)
-                 error ("parameter `%s' has incomplete type",
-                        IDENTIFIER_POINTER (DECL_NAME (parm)));
-               else
-                 warning ("parameter has incomplete type");
-               if (funcdef_flag)
-                 {
-                   TREE_VALUE (typelt) = error_mark_node;
-                   TREE_TYPE (parm) = error_mark_node;
-                 }
-             }
-           typelt = TREE_CHAIN (typelt);
-         }
+          parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+       {
+         type = TREE_VALUE (typelt);
+         if (type == error_mark_node)
+           continue;
+
+         if (!COMPLETE_TYPE_P (type))
+           {
+             if (funcdef_flag)
+               {
+                 if (DECL_NAME (parm))
+                   error ("%Jparameter %u ('%D') has incomplete type",
+                          parm, parmno, parm);
+                 else
+                   error ("%Jparameter %u has incomplete type",
+                          parm, parmno);
 
 
-      return first_parm;
+                 TREE_VALUE (typelt) = error_mark_node;
+                 TREE_TYPE (parm) = error_mark_node;
+               }
+             else
+               {
+                 if (DECL_NAME (parm))
+                   warning ("%Jparameter %u ('%D') has incomplete type",
+                            parm, parmno, parm);
+                 else
+                   warning ("%Jparameter %u has incomplete type",
+                            parm, parmno);
+               }
+           }
+       }
+      return arg_types;
     }
 }
 
     }
 }
 
-/* Return a tree_list node with info on a parameter list just parsed.
-   The TREE_PURPOSE is a list of decls of those parms.
-   The TREE_VALUE is a list of structure, union and enum tags defined.
-   The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE.
-   The TREE_TYPE is a list of non-parameter decls which appeared with the
-   parameters.
-   This tree_list node is later fed to `grokparms'.
+/* Take apart the current scope and return a tree_list node with info
+   on a parameter list just parsed.  This tree_list node should be
+   examined using the ARG_INFO_* macros, defined above:
+
+     ARG_INFO_PARMS:  a list of parameter decls.
+     ARG_INFO_TAGS:   a list of structure, union and enum tags defined.
+     ARG_INFO_TYPES:  a list of argument types to go in the FUNCTION_TYPE.
+     ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration
+                      constants) defined with the parameters.
+
+   This tree_list node is later fed to 'grokparms' and 'store_parm_decls'.
 
 
-   VOID_AT_END nonzero means append `void' to the end of the type-list.
-   Zero means the parmlist ended with an ellipsis so don't append `void'.  */
+   ELLIPSIS being true means the argument list ended in '...' so don't
+   append a sentinel (void_list_node) to the end of the type-list.  */
 
 tree
 
 tree
-get_parm_info (int void_at_end)
+get_parm_info (bool ellipsis)
 {
 {
-  tree decl, type, list;
-  tree types = 0;
-  tree *last_type = &types;
-  tree tags = current_scope->tags;
-  tree parms = current_scope->parms;
-  tree others = current_scope->names;
+  struct c_binding *b = current_scope->bindings;
+  tree arg_info = make_node (TREE_LIST);
+  tree parms    = 0;
+  tree tags     = 0;
+  tree types    = 0;
+  tree others   = 0;
+
   static bool explained_incomplete_types = false;
   bool gave_void_only_once_err = false;
 
   static bool explained_incomplete_types = false;
   bool gave_void_only_once_err = false;
 
-  /* Just "void" (and no ellipsis) is special.  There are really no parms.
-     But if the "void" is qualified (by "const" or "volatile"), or has a
-     storage class specifier ("register"), then the behavior is undefined;
-     issue an error.  Typedefs for "void" are OK (see DR#157).  */
-  if (void_at_end && parms != 0
-      && TREE_CHAIN (parms) == 0
-      && VOID_TYPE_P (TREE_TYPE (parms))
-      && !DECL_NAME (parms))
+  /* The bindings in this scope must not get put into a block.
+     We will take care of deleting the binding nodes.  */
+  current_scope->bindings = 0;
+
+  /* This function is only called if there was *something* on the
+     parameter list.  */
+#ifdef ENABLE_CHECKING
+  if (b == 0)
+    abort ();
+#endif
+
+  /* A parameter list consisting solely of 'void' indicates that the
+     function takes no arguments.  But if the 'void' is qualified
+     (by 'const' or 'volatile'), or has a storage class specifier
+     ('register'), then the behavior is undefined; issue an error.
+     Typedefs for 'void' are OK (see DR#157).  */
+  if (b->prev == 0                         /* one binding */
+      && TREE_CODE (b->decl) == PARM_DECL   /* which is a parameter */
+      && !DECL_NAME (b->decl)               /* anonymous */
+      && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
     {
     {
-      if (TREE_THIS_VOLATILE (parms)
-         || TREE_READONLY (parms)
-         || DECL_REGISTER (parms))
-       error ("\"void\" as only parameter may not be qualified");
+      if (TREE_THIS_VOLATILE (b->decl)
+         || TREE_READONLY (b->decl)
+         || C_DECL_REGISTER (b->decl))
+       error ("'void' as only parameter may not be qualified");
 
 
-      return tree_cons (0, 0, tree_cons (0, void_type_node, 0));
+      /* There cannot be an ellipsis.  */
+      if (ellipsis)
+       error ("'void' must be the only parameter");
+
+      ARG_INFO_TYPES (arg_info) = void_list_node;
+      return arg_info;
     }
 
     }
 
-  /* Sanity check all of the parameter declarations.  */
-  for (decl = parms; decl; decl = TREE_CHAIN (decl))
-    {
-      if (TREE_CODE (decl) != PARM_DECL)
-       abort ();
-      if (TREE_ASM_WRITTEN (decl))
-       abort ();
+  if (!ellipsis)
+    types = void_list_node;
 
 
-      /* Since there is a prototype, args are passed in their
-        declared types.  The back end may override this.  */
-      type = TREE_TYPE (decl);
-      DECL_ARG_TYPE (decl) = type;
+  /* Break up the bindings list into parms, tags, types, and others;
+     apply sanity checks; purge the name-to-decl bindings.  */
+  while (b)
+    {
+      tree decl = b->decl;
+      tree type = TREE_TYPE (decl);
+      const char *keyword;
 
 
-      /* Check for (..., void, ...) and issue an error.  */
-      if (VOID_TYPE_P (type) && !DECL_NAME (decl) && !gave_void_only_once_err)
+      switch (TREE_CODE (decl))
        {
        {
-         error ("\"void\" must be the only parameter");
-         gave_void_only_once_err = true;
-       }
+       case PARM_DECL:
+         if (b->id)
+           {
+#ifdef ENABLE_CHECKING
+             if (I_SYMBOL_BINDING (b->id) != b) abort ();
+#endif
+             I_SYMBOL_BINDING (b->id) = b->shadowed;
+           }
 
 
-      type = build_tree_list (0, type);
-      *last_type = type;
-      last_type = &TREE_CHAIN (type);
-    }
+         /* Check for forward decls that never got their actual decl.  */
+         if (TREE_ASM_WRITTEN (decl))
+           error ("%Jparameter '%D' has just a forward declaration",
+                  decl, decl);
+         /* Check for (..., void, ...) and issue an error.  */
+         else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
+           {
+             if (!gave_void_only_once_err)
+               {
+                 error ("'void' must be the only parameter");
+                 gave_void_only_once_err = true;
+               }
+           }
+         else
+           {
+             /* Valid parameter, add it to the list.  */
+             TREE_CHAIN (decl) = parms;
+             parms = decl;
+
+             /* Since there is a prototype, args are passed in their
+                declared types.  The back end may override this later.  */
+             DECL_ARG_TYPE (decl) = type;
+             types = tree_cons (0, type, types);
+           }
+         break;
 
 
-  /* Check the list of non-parameter decls for any forward parm decls
-     that never got real decls.  */
-  for (decl = others; decl; decl = TREE_CHAIN (decl))
-    if (TREE_CODE (decl) == PARM_DECL)
-      {
-       if (!TREE_ASM_WRITTEN (decl))
-         abort ();
+       case ENUMERAL_TYPE: keyword = "enum"; goto tag;
+       case UNION_TYPE:    keyword = "union"; goto tag;
+       case RECORD_TYPE:   keyword = "struct"; goto tag;
+       tag:
+         /* Types may not have tag-names, in which case the type
+            appears in the bindings list with b->id NULL.  */
+         if (b->id)
+           {
+#ifdef ENABLE_CHECKING
+             if (I_TAG_BINDING (b->id) != b) abort ();
+#endif
+             I_TAG_BINDING (b->id) = b->shadowed;
+           }
 
 
-         error ("%Jparameter \"%D\" has just a forward declaration",
-                decl, decl);
-      }
+         /* Warn about any struct, union or enum tags defined in a
+            parameter list.  The scope of such types is limited to
+            the parameter list, which is rarely if ever desirable
+            (it's impossible to call such a function with type-
+            correct arguments).  An anonymous union parm type is
+            meaningful as a GNU extension, so don't warn for that.  */
+         if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
+           {
+             if (b->id)
+               /* The %s will be one of 'struct', 'union', or 'enum'.  */
+               warning ("'%s %E' declared inside parameter list",
+                        keyword, b->id);
+             else
+               /* The %s will be one of 'struct', 'union', or 'enum'.  */
+               warning ("anonymous %s declared inside parameter list",
+                        keyword);
 
 
-  /* Warn about any struct, union or enum tags defined within this
-     list.  The scope of such types is limited to this declaration,
-     which is rarely if ever desirable (it's impossible to call such
-     a function with type-correct arguments).  */
-  for (decl = tags; decl; decl = TREE_CHAIN (decl))
-    {
-      enum tree_code code = TREE_CODE (TREE_VALUE (decl));
-      const char *keyword;
-      /* An anonymous union parm type is meaningful as a GNU extension.
-        So don't warn for that.  */
-      if (code == UNION_TYPE && TREE_PURPOSE (decl) == 0 && !pedantic)
-       continue;
+             if (! explained_incomplete_types)
+               {
+                 warning ("its scope is only this definition or declaration,"
+                          " which is probably not what you want");
+                 explained_incomplete_types = true;
+               }
+           }
 
 
-      /* The keyword should not be translated.  */
-      switch (code)
-       {
-       case RECORD_TYPE:   keyword = "struct"; break;
-       case UNION_TYPE:    keyword = "union";  break;
-       case ENUMERAL_TYPE: keyword = "enum";   break;
-       default: abort ();
-       }
+         tags = tree_cons (b->id, decl, tags);
+         break;
 
 
-      if (TREE_PURPOSE (decl))
-       /* The first %s will be one of 'struct', 'union', or 'enum'.  */
-       warning ("\"%s %s\" declared inside parameter list",
-                keyword, IDENTIFIER_POINTER (TREE_PURPOSE (decl)));
-      else
-       /* The %s will be one of 'struct', 'union', or 'enum'.  */
-       warning ("anonymous %s declared inside parameter list", keyword);
+       case CONST_DECL:
+       case TYPE_DECL:
+         /* CONST_DECLs appear here when we have an embedded enum,
+            and TYPE_DECLs appear here when we have an embedded struct
+            or union.  No warnings for this - we already warned about the
+            type itself.  */
+         TREE_CHAIN (decl) = others;
+         others = decl;
+         /* fall through */
 
 
-      if (! explained_incomplete_types)
-       {
-         warning ("its scope is only this definition or declaration,"
-                  " which is probably not what you want");
-         explained_incomplete_types = true;
-       }
-    }
+       case ERROR_MARK:
+         /* error_mark_node appears here when we have an undeclared
+            variable.  Just throw it away.  */
+         if (b->id)
+           {
+#ifdef ENABLE_CHECKING
+             if (I_SYMBOL_BINDING (b->id) != b) abort ();
+#endif
+             I_SYMBOL_BINDING (b->id) = b->shadowed;
+           }
+         break;
 
 
+         /* Other things that might be encountered.  */
+       case LABEL_DECL:
+       case FUNCTION_DECL:
+       case VAR_DECL:
+       default:
+         abort ();
+       }
 
 
-  if (void_at_end)
-    {
-      type = build_tree_list (0, void_type_node);
-      *last_type = type;
+      b = free_binding_and_advance (b);
     }
 
     }
 
-  list = tree_cons (parms, tags, types);
-  TREE_TYPE (list) = others;
-  return list;
+  ARG_INFO_PARMS  (arg_info) = parms;
+  ARG_INFO_TAGS   (arg_info) = tags;
+  ARG_INFO_TYPES  (arg_info) = types;
+  ARG_INFO_OTHERS (arg_info) = others;
+  return arg_info;
 }
 \f
 /* Get the struct, enum or union (CODE says which) with tag NAME.
 }
 \f
 /* Get the struct, enum or union (CODE says which) with tag NAME.
@@ -4716,7 +5172,7 @@ xref_tag (enum tree_code code, tree name)
       TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
       TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
       TYPE_USER_ALIGN (ref) = 0;
       TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
       TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
       TYPE_USER_ALIGN (ref) = 0;
-      TREE_UNSIGNED (ref) = 1;
+      TYPE_UNSIGNED (ref) = 1;
       TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
       TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
       TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
       TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
       TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
       TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
@@ -4821,7 +5277,7 @@ grokfield (tree declarator, tree declspecs, tree width)
        }
     }
 
        }
     }
 
-  value = grokdeclarator (declarator, declspecs, FIELD, 0,
+  value = grokdeclarator (declarator, declspecs, FIELD, false,
                          width ? &width : NULL);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
                          width ? &width : NULL);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
@@ -4895,7 +5351,7 @@ tree
 finish_struct (tree t, tree fieldlist, tree attributes)
 {
   tree x;
 finish_struct (tree t, tree fieldlist, tree attributes)
 {
   tree x;
-  int toplevel = global_scope == current_scope;
+  bool toplevel = file_scope == current_scope;
   int saw_named_field;
 
   /* If this type was previously laid out as a forward reference,
   int saw_named_field;
 
   /* If this type was previously laid out as a forward reference,
@@ -4905,19 +5361,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
 
   decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
 
   decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
-  /* Nameless union parm types are useful as GCC extension.  */
-  if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
-    /* Otherwise, warn about any struct or union def. in parmlist.  */
-    if (in_parm_level_p ())
-      {
-       if (pedantic)
-         pedwarn ("%s defined inside parms",
-                  TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
-       else
-         warning ("%s defined inside parms",
-                  TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
-      }
-
   if (pedantic)
     {
       for (x = fieldlist; x; x = TREE_CHAIN (x))
   if (pedantic)
     {
       for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -4931,9 +5374,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
-     Also process specified field sizes,m which is found in the DECL_INITIAL.
-     Store 0 there, except for ": 0" fields (so we can find them
-     and delete them, below).  */
+     Also process specified field sizes, found in the DECL_INITIAL,
+     storing 0 there after the type has been changed to precision equal
+     to its width, rather than the precision of the specified standard
+     type.  (Correct layout requires the original type to have been preserved
+     until now.)  */
 
   saw_named_field = 0;
   for (x = fieldlist; x; x = TREE_CHAIN (x))
 
   saw_named_field = 0;
   for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -4977,8 +5422,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          SET_DECL_C_BIT_FIELD (x);
        }
 
          SET_DECL_C_BIT_FIELD (x);
        }
 
-      DECL_INITIAL (x) = 0;
-
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@@ -4986,14 +5429,23 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
        {
          if (TREE_CODE (t) == UNION_TYPE)
          && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
        {
          if (TREE_CODE (t) == UNION_TYPE)
-           error ("%Jflexible array member in union", x);
+           {
+             error ("%Jflexible array member in union", x);
+             TREE_TYPE (x) = error_mark_node;
+           }
          else if (TREE_CHAIN (x) != NULL_TREE)
          else if (TREE_CHAIN (x) != NULL_TREE)
-           error ("%Jflexible array member not at end of struct", x);
+           {
+             error ("%Jflexible array member not at end of struct", x);
+             TREE_TYPE (x) = error_mark_node;
+           }
          else if (! saw_named_field)
          else if (! saw_named_field)
-           error ("%Jflexible array member in otherwise empty struct", x);
+           {
+             error ("%Jflexible array member in otherwise empty struct", x);
+             TREE_TYPE (x) = error_mark_node;
+           }
        }
 
        }
 
-      if (pedantic && TREE_CODE (t) == RECORD_TYPE
+      if (pedantic && !in_system_header && TREE_CODE (t) == RECORD_TYPE
          && flexible_array_type_p (TREE_TYPE (x)))
        pedwarn ("%Jinvalid use of structure with flexible array member", x);
 
          && flexible_array_type_p (TREE_TYPE (x)))
        pedwarn ("%Jinvalid use of structure with flexible array member", x);
 
@@ -5010,12 +5462,21 @@ finish_struct (tree t, tree fieldlist, tree attributes)
 
   layout_type (t);
 
 
   layout_type (t);
 
-  /* Delete all zero-width bit-fields from the fieldlist.  */
+  /* Give bit-fields their proper types.  */
   {
     tree *fieldlistp = &fieldlist;
     while (*fieldlistp)
   {
     tree *fieldlistp = &fieldlist;
     while (*fieldlistp)
-      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
-       *fieldlistp = TREE_CHAIN (*fieldlistp);
+      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
+         && TREE_TYPE (*fieldlistp) != error_mark_node)
+       {
+         unsigned HOST_WIDE_INT width
+           = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+         tree type = TREE_TYPE (*fieldlistp);
+         if (width != TYPE_PRECISION (type))
+           TREE_TYPE (*fieldlistp)
+             = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+         DECL_INITIAL (*fieldlistp) = 0;
+       }
       else
        fieldlistp = &TREE_CHAIN (*fieldlistp);
   }
       else
        fieldlistp = &TREE_CHAIN (*fieldlistp);
   }
@@ -5050,8 +5511,9 @@ finish_struct (tree t, tree fieldlist, tree attributes)
           ensure that this lives as long as the rest of the struct decl.
           All decls in an inline function need to be saved.  */
 
           ensure that this lives as long as the rest of the struct decl.
           All decls in an inline function need to be saved.  */
 
-        space = ggc_alloc (sizeof (struct lang_type));
-        space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+        space = GGC_CNEW (struct lang_type);
+        space2 = GGC_NEWVAR (struct sorted_fields_type,
+                            sizeof (struct sorted_fields_type) + len * sizeof (tree));
 
         len = 0;
        space->s = space2;
 
         len = 0;
        space->s = space2;
@@ -5107,7 +5569,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          layout_decl (decl, 0);
          if (c_dialect_objc ())
            objc_check_decl (decl);
          layout_decl (decl, 0);
          if (c_dialect_objc ())
            objc_check_decl (decl);
-         rest_of_decl_compilation (decl, NULL, toplevel, 0);
+         rest_of_decl_compilation (decl, toplevel, 0);
          if (! toplevel)
            expand_decl (decl);
        }
          if (! toplevel)
            expand_decl (decl);
        }
@@ -5185,12 +5647,10 @@ tree
 finish_enum (tree enumtype, tree values, tree attributes)
 {
   tree pair, tem;
 finish_enum (tree enumtype, tree values, tree attributes)
 {
   tree pair, tem;
-  tree minnode = 0, maxnode = 0, enum_value_type;
+  tree minnode = 0, maxnode = 0;
   int precision, unsign;
   int precision, unsign;
-  int toplevel = (global_scope == current_scope);
-
-  if (in_parm_level_p ())
-    warning ("enum defined inside parms");
+  bool toplevel = (file_scope == current_scope);
+  struct lang_type *lt;
 
   decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
 
   decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
@@ -5220,27 +5680,20 @@ finish_enum (tree enumtype, tree values, tree attributes)
                   min_precision (maxnode, unsign));
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
                   min_precision (maxnode, unsign));
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
-      tree narrowest = c_common_type_for_size (precision, unsign);
-      if (narrowest == 0)
+      tem = c_common_type_for_size (precision, unsign);
+      if (tem == NULL)
        {
          warning ("enumeration values exceed range of largest integer");
        {
          warning ("enumeration values exceed range of largest integer");
-         narrowest = long_long_integer_type_node;
+         tem = long_long_integer_type_node;
        }
        }
-
-      precision = TYPE_PRECISION (narrowest);
     }
   else
     }
   else
-    precision = TYPE_PRECISION (integer_type_node);
-
-  if (precision == TYPE_PRECISION (integer_type_node))
-    enum_value_type = c_common_type_for_size (precision, 0);
-  else
-    enum_value_type = enumtype;
+    tem = unsign ? unsigned_type_node : integer_type_node;
 
 
-  TYPE_MIN_VALUE (enumtype) = minnode;
-  TYPE_MAX_VALUE (enumtype) = maxnode;
-  TYPE_PRECISION (enumtype) = precision;
-  TREE_UNSIGNED (enumtype) = unsign;
+  TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
+  TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
+  TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+  TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
   TYPE_SIZE (enumtype) = 0;
   layout_type (enumtype);
 
   TYPE_SIZE (enumtype) = 0;
   layout_type (enumtype);
 
@@ -5256,6 +5709,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
       for (pair = values; pair; pair = TREE_CHAIN (pair))
        {
          tree enu = TREE_PURPOSE (pair);
       for (pair = values; pair; pair = TREE_CHAIN (pair))
        {
          tree enu = TREE_PURPOSE (pair);
+         tree ini = DECL_INITIAL (enu);
 
          TREE_TYPE (enu) = enumtype;
 
 
          TREE_TYPE (enu) = enumtype;
 
@@ -5266,18 +5720,27 @@ finish_enum (tree enumtype, tree values, tree attributes)
             when comparing integers with enumerators that fit in the
             int range.  When -pedantic is given, build_enumerator()
             would have already taken care of those that don't fit.  */
             when comparing integers with enumerators that fit in the
             int range.  When -pedantic is given, build_enumerator()
             would have already taken care of those that don't fit.  */
-         if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
-           DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+         if (int_fits_type_p (ini, integer_type_node))
+           tem = integer_type_node;
          else
          else
-           DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+           tem = enumtype;
+         ini = convert (tem, ini);
 
 
+         DECL_INITIAL (enu) = ini;
          TREE_PURPOSE (pair) = DECL_NAME (enu);
          TREE_PURPOSE (pair) = DECL_NAME (enu);
-         TREE_VALUE (pair) = DECL_INITIAL (enu);
+         TREE_VALUE (pair) = ini;
        }
 
       TYPE_VALUES (enumtype) = values;
     }
 
        }
 
       TYPE_VALUES (enumtype) = values;
     }
 
+  /* Record the min/max values so that we can warn about bit-field
+     enumerations that are too small for the values.  */
+  lt = GGC_CNEW (struct lang_type);
+  lt->enum_min = minnode;
+  lt->enum_max = maxnode;
+  TYPE_LANG_SPECIFIC (enumtype) = lt;
+
   /* Fix up all variant types of this enum type.  */
   for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
     {
   /* Fix up all variant types of this enum type.  */
   for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
     {
@@ -5292,7 +5755,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
       TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
       TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
-      TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+      TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
+      TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
     }
 
   /* Finish debugging output for this type.  */
     }
 
   /* Finish debugging output for this type.  */
@@ -5319,16 +5783,19 @@ build_enumerator (tree name, tree value)
 
   if (value != 0)
     {
 
   if (value != 0)
     {
-      if (TREE_CODE (value) == INTEGER_CST)
+      /* Don't issue more errors for error_mark_node (i.e. an
+        undeclared identifier) - just ignore the value expression.  */
+      if (value == error_mark_node)
+       value = 0;
+      else if (TREE_CODE (value) != INTEGER_CST)
        {
        {
-         value = default_conversion (value);
-         constant_expression_warning (value);
+         error ("enumerator value for '%E' is not an integer constant", name);
+         value = 0;
        }
       else
        {
        }
       else
        {
-         error ("enumerator value for `%s' not integer constant",
-                IDENTIFIER_POINTER (name));
-         value = 0;
+         value = default_conversion (value);
+         constant_expression_warning (value);
        }
     }
 
        }
     }
 
@@ -5345,6 +5812,8 @@ build_enumerator (tree name, tree value)
   if (pedantic && ! int_fits_type_p (value, integer_type_node))
     {
       pedwarn ("ISO C restricts enumerator values to range of `int'");
   if (pedantic && ! int_fits_type_p (value, integer_type_node))
     {
       pedwarn ("ISO C restricts enumerator values to range of `int'");
+      /* XXX This causes -pedantic to change the meaning of the program.
+        Remove?  -zw 2004-03-15  */
       value = convert (integer_type_node, value);
     }
 
       value = convert (integer_type_node, value);
     }
 
@@ -5359,7 +5828,7 @@ build_enumerator (tree name, tree value)
                                      TYPE_PRECISION (integer_type_node)),
                                 (TYPE_PRECISION (type)
                                  >= TYPE_PRECISION (integer_type_node)
                                      TYPE_PRECISION (integer_type_node)),
                                 (TYPE_PRECISION (type)
                                  >= TYPE_PRECISION (integer_type_node)
-                                 && TREE_UNSIGNED (type)));
+                                 && TYPE_UNSIGNED (type)));
 
   decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = convert (type, value);
 
   decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = convert (type, value);
@@ -5385,29 +5854,26 @@ int
 start_function (tree declspecs, tree declarator, tree attributes)
 {
   tree decl1, old_decl;
 start_function (tree declspecs, tree declarator, tree attributes)
 {
   tree decl1, old_decl;
-  tree restype;
-  int old_immediate_size_expand = immediate_size_expand;
+  tree restype, resdecl;
 
   current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
   current_function_returns_abnormally = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
 
   current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
   current_function_returns_abnormally = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
-  c_in_iteration_stmt = 0;
-  c_in_case_stmt = 0;
+  c_switch_stack = NULL;
 
 
-  /* Don't expand any sizes in the return type of the function.  */
-  immediate_size_expand = 0;
+  /* Indicate no valid break/continue context by setting these variables
+     to some non-null, non-label value.  We'll notice and emit the proper
+     error message in c_finish_bc_stmt.  */
+  c_break_label = c_cont_label = size_zero_node;
 
 
-  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
+  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL);
 
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == 0)
 
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == 0)
-    {
-      immediate_size_expand = old_immediate_size_expand;
-      return 0;
-    }
+    return 0;
 
   decl_attributes (&decl1, attributes, 0);
 
 
   decl_attributes (&decl1, attributes, 0);
 
@@ -5430,27 +5896,22 @@ start_function (tree declspecs, tree declarator, tree attributes)
   if (warn_about_return_type)
     pedwarn_c99 ("return type defaults to `int'");
 
   if (warn_about_return_type)
     pedwarn_c99 ("return type defaults to `int'");
 
-  /* Save the parm names or decls from this function's declarator
-     where store_parm_decls will find them.  */
-  current_function_parms = last_function_parms;
-  current_function_parm_tags = last_function_parm_tags;
-  current_function_parm_others = last_function_parm_others;
-
   /* Make the init_value nonzero so pushdecl knows this is not tentative.
   /* Make the init_value nonzero so pushdecl knows this is not tentative.
-     error_mark_node is replaced below (in poplevel) with the BLOCK.  */
+     error_mark_node is replaced below (in pop_scope) with the BLOCK.  */
   DECL_INITIAL (decl1) = error_mark_node;
 
   /* If this definition isn't a prototype and we had a prototype declaration
      before, copy the arg type info from that prototype.
      But not if what we had before was a builtin function.  */
   DECL_INITIAL (decl1) = error_mark_node;
 
   /* If this definition isn't a prototype and we had a prototype declaration
      before, copy the arg type info from that prototype.
      But not if what we had before was a builtin function.  */
-  old_decl = lookup_name_current_level (DECL_NAME (decl1));
+  old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
   if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
       && !DECL_BUILT_IN (old_decl)
   if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
       && !DECL_BUILT_IN (old_decl)
-      && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
-         == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl))))
+      && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+                   TREE_TYPE (TREE_TYPE (old_decl)))
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
     {
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
     {
-      TREE_TYPE (decl1) = TREE_TYPE (old_decl);
+      TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
+                                         TREE_TYPE (decl1));
       current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
     }
 
       current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
     }
 
@@ -5508,7 +5969,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
 #endif
 
   /* If #pragma weak was used, mark the decl weak now.  */
 #endif
 
   /* If #pragma weak was used, mark the decl weak now.  */
-  if (current_scope == global_scope)
+  if (current_scope == file_scope)
     maybe_apply_pragma_weak (decl1);
 
   /* Warn for unlikely, improbable, or stupid declarations of `main'.  */
     maybe_apply_pragma_weak (decl1);
 
   /* Warn for unlikely, improbable, or stupid declarations of `main'.  */
@@ -5574,32 +6035,26 @@ start_function (tree declspecs, tree declarator, tree attributes)
 
   current_function_decl = pushdecl (decl1);
 
 
   current_function_decl = pushdecl (decl1);
 
-  pushlevel (0);
+  push_scope ();
   declare_parm_level ();
 
   declare_parm_level ();
 
-  make_decl_rtl (current_function_decl, NULL);
-
   restype = TREE_TYPE (TREE_TYPE (current_function_decl));
   /* Promote the value to int before returning it.  */
   if (c_promoting_integer_type_p (restype))
     {
       /* It retains unsignedness if not really getting wider.  */
   restype = TREE_TYPE (TREE_TYPE (current_function_decl));
   /* Promote the value to int before returning it.  */
   if (c_promoting_integer_type_p (restype))
     {
       /* It retains unsignedness if not really getting wider.  */
-      if (TREE_UNSIGNED (restype)
+      if (TYPE_UNSIGNED (restype)
          && (TYPE_PRECISION (restype)
                  == TYPE_PRECISION (integer_type_node)))
        restype = unsigned_type_node;
       else
        restype = integer_type_node;
     }
          && (TYPE_PRECISION (restype)
                  == TYPE_PRECISION (integer_type_node)))
        restype = unsigned_type_node;
       else
        restype = integer_type_node;
     }
-  DECL_RESULT (current_function_decl)
-    = build_decl (RESULT_DECL, NULL_TREE, restype);
-
-  /* If this fcn was already referenced via a block-scope `extern' decl
-     (or an implicit decl), propagate certain information about the usage.  */
-  if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
-    TREE_ADDRESSABLE (current_function_decl) = 1;
 
 
-  immediate_size_expand = old_immediate_size_expand;
+  resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+  DECL_ARTIFICIAL (resdecl) = 1;
+  DECL_IGNORED_P (resdecl) = 1;
+  DECL_RESULT (current_function_decl) = resdecl;
 
   start_fname_decls ();
 
 
   start_fname_decls ();
 
@@ -5611,99 +6066,83 @@ start_function (tree declspecs, tree declarator, tree attributes)
    need only record them as in effect and complain if any redundant
    old-style parm decls were written.  */
 static void
    need only record them as in effect and complain if any redundant
    old-style parm decls were written.  */
 static void
-store_parm_decls_newstyle (void)
+store_parm_decls_newstyle (tree fndecl, tree arg_info)
 {
 {
-  tree decl, last;
-  tree fndecl = current_function_decl;
-  tree parms = current_function_parms;
-  tree tags = current_function_parm_tags;
-  tree others = current_function_parm_others;
+  tree decl;
+  tree parms  = ARG_INFO_PARMS  (arg_info);
+  tree tags   = ARG_INFO_TAGS   (arg_info);
+  tree others = ARG_INFO_OTHERS (arg_info);
 
 
-  if (current_scope->parms || current_scope->names || current_scope->tags)
+  if (current_scope->bindings)
     {
       error ("%Jold-style parameter declarations in prototyped "
             "function definition", fndecl);
 
       /* Get rid of the old-style declarations.  */
     {
       error ("%Jold-style parameter declarations in prototyped "
             "function definition", fndecl);
 
       /* Get rid of the old-style declarations.  */
-      poplevel (0, 0, 0);
-      pushlevel (0);
-    }
+      pop_scope ();
+      push_scope ();
+    }
+  /* Don't issue this warning for nested functions, and don't issue this
+     warning if we got here because ARG_INFO_TYPES was error_mark_node
+     (this happens when a function definition has just an ellipsis in
+     its parameter list).  */
+  else if (warn_traditional && !in_system_header && !current_function_scope
+          && ARG_INFO_TYPES (arg_info) != error_mark_node)
+    warning ("%Jtraditional C rejects ISO C style function definitions",
+            fndecl);
 
   /* Now make all the parameter declarations visible in the function body.
      We can bypass most of the grunt work of pushdecl.  */
 
   /* Now make all the parameter declarations visible in the function body.
      We can bypass most of the grunt work of pushdecl.  */
-  for (last = 0, decl = parms; decl; last = decl, decl = TREE_CHAIN (decl))
+  for (decl = parms; decl; decl = TREE_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
     {
       DECL_CONTEXT (decl) = current_function_decl;
-      if (DECL_NAME (decl) == 0)
-       error ("%Jparameter name omitted", decl);
+      if (DECL_NAME (decl))
+       bind (DECL_NAME (decl), decl, current_scope,
+             /*invisible=*/false, /*nested=*/false);
       else
       else
-       {
-         if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
-           current_scope->shadowed
-             = tree_cons (DECL_NAME (decl),
-                          IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
-                          current_scope->shadowed);
-         IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
-       }
+       error ("%Jparameter name omitted", decl);
     }
     }
-  current_scope->parms = parms;
-  current_scope->parms_last = last;
 
   /* Record the parameter list in the function declaration.  */
   DECL_ARGUMENTS (fndecl) = parms;
 
   /* Now make all the ancillary declarations visible, likewise.  */
 
   /* Record the parameter list in the function declaration.  */
   DECL_ARGUMENTS (fndecl) = parms;
 
   /* Now make all the ancillary declarations visible, likewise.  */
-  for (last = 0, decl = others; decl; last = decl, decl = TREE_CHAIN (decl))
+  for (decl = others; decl; decl = TREE_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
     {
       DECL_CONTEXT (decl) = current_function_decl;
-      if (DECL_NAME (decl)
-         && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
-       {
-         if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
-           current_scope->shadowed
-             = tree_cons (DECL_NAME (decl),
-                          IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
-                          current_scope->shadowed);
-         IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
-       }
+      if (DECL_NAME (decl))
+       bind (DECL_NAME (decl), decl, current_scope,
+             /*invisible=*/false, /*nested=*/false);
     }
     }
-  current_scope->names = others;
-  current_scope->names_last = last;
 
   /* And all the tag declarations.  */
   for (decl = tags; decl; decl = TREE_CHAIN (decl))
     if (TREE_PURPOSE (decl))
 
   /* And all the tag declarations.  */
   for (decl = tags; decl; decl = TREE_CHAIN (decl))
     if (TREE_PURPOSE (decl))
-      {
-       if (IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)))
-         current_scope->shadowed_tags
-           = tree_cons (TREE_PURPOSE (decl),
-                        IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (decl)),
-                        current_scope->shadowed_tags);
-       IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)) = TREE_VALUE (decl);
-      }
-  current_scope->tags = tags;
+      bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
+           /*invisible=*/false, /*nested=*/false);
 }
 
 /* Subroutine of store_parm_decls which handles old-style function
    definitions (separate parameter list and declarations).  */
 
 static void
 }
 
 /* Subroutine of store_parm_decls which handles old-style function
    definitions (separate parameter list and declarations).  */
 
 static void
-store_parm_decls_oldstyle (void)
+store_parm_decls_oldstyle (tree fndecl, tree arg_info)
 {
 {
+  struct c_binding *b;
   tree parm, decl, last;
   tree parm, decl, last;
-  tree fndecl = current_function_decl;
-
-  /* This is the identifier list from the function declarator.  */
-  tree parmids = current_function_parms;
+  tree parmids = ARG_INFO_PARMS (arg_info);
 
   /* We use DECL_WEAK as a flag to show which parameters have been
      seen already, since it is not used on PARM_DECL.  */
 #ifdef ENABLE_CHECKING
 
   /* We use DECL_WEAK as a flag to show which parameters have been
      seen already, since it is not used on PARM_DECL.  */
 #ifdef ENABLE_CHECKING
-  for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
-    if (DECL_WEAK (parm))
+  for (b = current_scope->bindings; b; b = b->prev)
+    if (TREE_CODE (b->decl) == PARM_DECL && DECL_WEAK (b->decl))
       abort ();
 #endif
 
       abort ();
 #endif
 
+  if (warn_old_style_definition && !in_system_header)
+    warning ("%Jold-style function definition", fndecl);
+
   /* Match each formal parameter name with its declaration.  Save each
      decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
   for (parm = parmids; parm; parm = TREE_CHAIN (parm))
   /* Match each formal parameter name with its declaration.  Save each
      decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
   for (parm = parmids; parm; parm = TREE_CHAIN (parm))
@@ -5715,17 +6154,18 @@ store_parm_decls_oldstyle (void)
          continue;
        }
 
          continue;
        }
 
-      decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
-      if (decl && DECL_CONTEXT (decl) == fndecl)
+      b = I_SYMBOL_BINDING (TREE_VALUE (parm));
+      if (b && B_IN_CURRENT_SCOPE (b))
        {
        {
+         decl = b->decl;
          /* If we got something other than a PARM_DECL it is an error.  */
          if (TREE_CODE (decl) != PARM_DECL)
          /* If we got something other than a PARM_DECL it is an error.  */
          if (TREE_CODE (decl) != PARM_DECL)
-           error ("%J\"%D\" declared as a non-parameter", decl, decl);
+           error ("%J'%D' declared as a non-parameter", decl, decl);
          /* If the declaration is already marked, we have a duplicate
             name.  Complain and ignore the duplicate.  */
          else if (DECL_WEAK (decl))
            {
          /* If the declaration is already marked, we have a duplicate
             name.  Complain and ignore the duplicate.  */
          else if (DECL_WEAK (decl))
            {
-             error ("%Jmultiple parameters named \"%D\"", decl, decl);
+             error ("%Jmultiple parameters named '%D'", decl, decl);
              TREE_PURPOSE (parm) = 0;
              continue;
            }
              TREE_PURPOSE (parm) = 0;
              continue;
            }
@@ -5733,7 +6173,7 @@ store_parm_decls_oldstyle (void)
             an int.  */
          else if (VOID_TYPE_P (TREE_TYPE (decl)))
            {
             an int.  */
          else if (VOID_TYPE_P (TREE_TYPE (decl)))
            {
-             error ("%Jparameter \"%D\" declared void", decl, decl);
+             error ("%Jparameter '%D' declared with void type", decl, decl);
              TREE_TYPE (decl) = integer_type_node;
              DECL_ARG_TYPE (decl) = integer_type_node;
              layout_decl (decl, 0);
              TREE_TYPE (decl) = integer_type_node;
              DECL_ARG_TYPE (decl) = integer_type_node;
              layout_decl (decl, 0);
@@ -5748,9 +6188,9 @@ store_parm_decls_oldstyle (void)
          pushdecl (decl);
 
          if (flag_isoc99)
          pushdecl (decl);
 
          if (flag_isoc99)
-           pedwarn ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
+           pedwarn ("%Jtype of '%D' defaults to 'int'", decl, decl);
          else if (extra_warnings)
          else if (extra_warnings)
-           warning ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
+           warning ("%Jtype of '%D' defaults to 'int'", decl, decl);
        }
 
       TREE_PURPOSE (parm) = decl;
        }
 
       TREE_PURPOSE (parm) = decl;
@@ -5760,17 +6200,21 @@ store_parm_decls_oldstyle (void)
   /* Now examine the parms chain for incomplete declarations
      and declarations with no corresponding names.  */
 
   /* Now examine the parms chain for incomplete declarations
      and declarations with no corresponding names.  */
 
-  for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
+  for (b = current_scope->bindings; b; b = b->prev)
     {
     {
+      parm = b->decl;
+      if (TREE_CODE (parm) != PARM_DECL)
+       continue;
+
       if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
       if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
-         error ("%Jparameter \"%D\" has incomplete type", parm, parm);
+         error ("%Jparameter '%D' has incomplete type", parm, parm);
          TREE_TYPE (parm) = error_mark_node;
        }
 
       if (! DECL_WEAK (parm))
        {
          TREE_TYPE (parm) = error_mark_node;
        }
 
       if (! DECL_WEAK (parm))
        {
-         error ("%Jdeclaration for parameter \"%D\" but no such parameter",
+         error ("%Jdeclaration for parameter '%D' but no such parameter",
                 parm, parm);
 
          /* Pretend the parameter was not missing.
                 parm, parm);
 
          /* Pretend the parameter was not missing.
@@ -5792,7 +6236,6 @@ store_parm_decls_oldstyle (void)
     {
       last = TREE_PURPOSE (parm);
       DECL_ARGUMENTS (fndecl) = last;
     {
       last = TREE_PURPOSE (parm);
       DECL_ARGUMENTS (fndecl) = last;
-      current_scope->parms = last;
       DECL_WEAK (last) = 0;
 
       for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
       DECL_WEAK (last) = 0;
 
       for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
@@ -5802,7 +6245,6 @@ store_parm_decls_oldstyle (void)
            last = TREE_PURPOSE (parm);
            DECL_WEAK (last) = 0;
          }
            last = TREE_PURPOSE (parm);
            DECL_WEAK (last) = 0;
          }
-      current_scope->parms_last = last;
       TREE_CHAIN (last) = 0;
     }
 
       TREE_CHAIN (last) = 0;
     }
 
@@ -5831,8 +6273,7 @@ store_parm_decls_oldstyle (void)
             declared for the arg.  ISO C says we take the unqualified
             type for parameters declared with qualified type.  */
          if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
             declared for the arg.  ISO C says we take the unqualified
             type for parameters declared with qualified type.  */
          if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
-                          TYPE_MAIN_VARIANT (TREE_VALUE (type)),
-                          COMPARE_STRICT))
+                          TYPE_MAIN_VARIANT (TREE_VALUE (type))))
            {
              if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
                  == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
            {
              if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
                  == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -5852,7 +6293,7 @@ store_parm_decls_oldstyle (void)
 
                  if (pedantic)
                    {
 
                  if (pedantic)
                    {
-                     pedwarn ("promoted argument \"%D\" "
+                     pedwarn ("promoted argument '%D' "
                               "doesn't match prototype", parm);
                      pedwarn ("%Hprototype declaration",
                               &current_function_prototype_locus);
                               "doesn't match prototype", parm);
                      pedwarn ("%Hprototype declaration",
                               &current_function_prototype_locus);
@@ -5860,7 +6301,7 @@ store_parm_decls_oldstyle (void)
                }
              else
                {
                }
              else
                {
-                 error ("argument \"%D\" doesn't match prototype", parm);
+                 error ("argument '%D' doesn't match prototype", parm);
                  error ("%Hprototype declaration",
                         &current_function_prototype_locus);
                }
                  error ("%Hprototype declaration",
                         &current_function_prototype_locus);
                }
@@ -5898,7 +6339,7 @@ store_parm_decls_oldstyle (void)
         will be a variant of the main variant of the original function
         type.  */
 
         will be a variant of the main variant of the original function
         type.  */
 
-      TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
+      TREE_TYPE (fndecl) = build_variant_type_copy (TREE_TYPE (fndecl));
 
       TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
     }
 
       TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
     }
@@ -5915,60 +6356,81 @@ void
 store_parm_decls (void)
 {
   tree fndecl = current_function_decl;
 store_parm_decls (void)
 {
   tree fndecl = current_function_decl;
+  bool proto;
 
 
-  /* The function containing FNDECL, if any.  */
-  tree context = decl_function_context (fndecl);
+  /* The argument information block for FNDECL.  */
+  tree arg_info = current_function_arg_info;
+  current_function_arg_info = 0;
 
 
-  /* True if this definition is written with a prototype.  */
-  bool prototype = (current_function_parms
-                   && TREE_CODE (current_function_parms) != TREE_LIST);
+  /* True if this definition is written with a prototype.  Note:
+     despite C99 6.7.5.3p14, we can *not* treat an empty argument
+     list in a function definition as equivalent to (void) -- an
+     empty argument list specifies the function has no parameters,
+     but only (void) sets up a prototype for future calls.  */
+  proto = ARG_INFO_TYPES (arg_info) != 0;
 
 
-  if (prototype)
-    store_parm_decls_newstyle ();
+  if (proto)
+    store_parm_decls_newstyle (fndecl, arg_info);
   else
   else
-    store_parm_decls_oldstyle ();
+    store_parm_decls_oldstyle (fndecl, arg_info);
 
 
-  /* The next call to pushlevel will be a function body.  */
+  /* The next call to push_scope will be a function body.  */
 
   next_is_function_body = true;
 
   /* Write a record describing this function definition to the prototypes
      file (if requested).  */
 
 
   next_is_function_body = true;
 
   /* Write a record describing this function definition to the prototypes
      file (if requested).  */
 
-  gen_aux_info_record (fndecl, 1, 0, prototype);
+  gen_aux_info_record (fndecl, 1, 0, proto);
 
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl);
 
   /* Begin the statement tree for this function.  */
 
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl);
 
   /* Begin the statement tree for this function.  */
-  begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
+  DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
 
-  /* If this is a nested function, save away the sizes of any
-     variable-size types so that we can expand them when generating
-     RTL.  */
-  if (context)
-    {
-      tree t;
-
-      DECL_LANG_SPECIFIC (fndecl)->pending_sizes
-       = nreverse (get_pending_sizes ());
-      for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
-          t;
-          t = TREE_CHAIN (t))
-       SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
-    }
-
-  /* This function is being processed in whole-function mode.  */
-  cfun->x_whole_function_mode_p = 1;
+  /* ??? Insert the contents of the pending sizes list into the function
+     to be evaluated.  This just changes mis-behaviour until assign_parms
+     phase ordering problems are resolved.  */
+  {
+    tree t;
+    for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
+      add_stmt (TREE_VALUE (t));
+  }
 
   /* Even though we're inside a function body, we still don't want to
      call expand_expr to calculate the size of a variable-sized array.
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
 
   /* Even though we're inside a function body, we still don't want to
      call expand_expr to calculate the size of a variable-sized array.
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
-  immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
 }
 \f
   cfun->x_dont_save_pending_sizes_p = 1;
 }
 \f
+/* Give FNDECL and all its nested functions to cgraph for compilation.  */
+
+static void
+c_finalize (tree fndecl)
+{
+  struct cgraph_node *cgn;
+
+  /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
+  c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+
+  /* ??? Objc emits functions after finalizing the compilation unit.
+     This should be cleaned up later and this conditional removed.  */
+  if (cgraph_global_info_ready)
+    {
+      c_expand_body (fndecl);
+      return;
+    }
+
+  /* Finalize all nested functions now.  */
+  cgn = cgraph_node (fndecl);
+  for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
+    c_finalize (cgn->decl);
+
+  cgraph_finalize_function (fndecl, false);
+}
+
 /* Finish up a function declaration and compile that function
    all the way to assembler language output.  The free the storage
    for the function definition.
 /* Finish up a function declaration and compile that function
    all the way to assembler language output.  The free the storage
    for the function definition.
@@ -5980,22 +6442,6 @@ finish_function (void)
 {
   tree fndecl = current_function_decl;
 
 {
   tree fndecl = current_function_decl;
 
-  /* When a function declaration is totally empty, e.g.
-        void foo(void) { }
-     (the argument list is irrelevant) the compstmt rule will not
-     bother calling pushlevel/poplevel, which means we get here with
-     the scope stack out of sync.  Detect this situation by noticing
-     that current_scope 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
-     scope - see there for details.  */
-
-  if (current_scope->parm_flag && next_is_function_body)
-    {
-      pushlevel (0);
-      poplevel (0, 0, 0);
-    }
-
   if (TREE_CODE (fndecl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
     {
   if (TREE_CODE (fndecl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
     {
@@ -6029,20 +6475,15 @@ finish_function (void)
        }
       else
        {
        }
       else
        {
-#ifdef DEFAULT_MAIN_RETURN
-         /* Make it so that `main' always returns success by default.  */
-         DEFAULT_MAIN_RETURN;
-#else
          if (flag_isoc99)
          if (flag_isoc99)
-           c_expand_return (integer_zero_node);
-#endif
+           c_finish_return (integer_zero_node);
        }
     }
 
        }
     }
 
-  finish_fname_decls ();
-
   /* Tie off the statement tree for this function.  */
   /* Tie off the statement tree for this function.  */
-  finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+  DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+  finish_fname_decls ();
 
   /* Complain if there's just no return statement.  */
   if (warn_return_type
 
   /* Complain if there's just no return statement.  */
   if (warn_return_type
@@ -6066,90 +6507,70 @@ finish_function (void)
       && current_function_returns_null)
     warning ("this function may return with or without a value");
 
       && current_function_returns_null)
     warning ("this function may return with or without a value");
 
-  /* We're leaving the context of this function, so zap cfun.
-     It's still in DECL_STRUCT_FUNCTION , and we'll restore it in
-     tree_rest_of_compilation.  */
-  cfun = NULL;
-
-  /* ??? Objc emits functions after finalizing the compilation unit.
-     This should be cleaned up later and this conditional removed.  */
-  if (!cgraph_global_info_ready)
-    cgraph_finalize_function (fndecl, false);
-  else
-    c_expand_body (fndecl);
-  current_function_decl = NULL;
-}
-
-/* Generate the RTL for a deferred function FNDECL.  */
-
-void
-c_expand_deferred_function (tree fndecl)
-{
-  /* DECL_INLINE or DECL_RESULT might got cleared after the inline
-     function was deferred, e.g. in duplicate_decls.  */
-  if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
-    {
-      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 nonzero,
-   then we are already in the process of generating RTL for another
-   function.  */
+  /* Store the end of the function, so that we get good line number
+     info for the epilogue.  */
+  cfun->function_end_locus = input_location;
 
 
-static void
-c_expand_body_1 (tree fndecl, int nested_p)
-{
-  if (nested_p)
-    {
-      /* Make sure that we will evaluate variable-sized types involved
-        in our function's type.  */
-      expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
+  /* If we don't have ctors/dtors sections, and this is a static
+     constructor or destructor, it must be recorded now.  */
+  if (DECL_STATIC_CONSTRUCTOR (fndecl)
+      && !targetm.have_ctors_dtors)
+    static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+  if (DECL_STATIC_DESTRUCTOR (fndecl)
+      && !targetm.have_ctors_dtors)
+    static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
 
 
-      /* Squirrel away our current state.  */
-      push_function_context ();
-    }
-    
-  tree_rest_of_compilation (fndecl, nested_p);
+  /* Finalize the ELF visibility for the function.  */
+  c_determine_visibility (fndecl);
 
 
-  if (nested_p)
-    /* Return to the enclosing function.  */
-    pop_function_context ();
+  /* Genericize before inlining.  Delay genericizing nested functions
+     until their parent function is genericized.  Since finalizing
+     requires GENERIC, delay that as well.  */
 
 
-  if (DECL_STATIC_CONSTRUCTOR (fndecl))
+  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
     {
     {
-      if (targetm.have_ctors_dtors)
-       (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
-                                        DEFAULT_INIT_PRIORITY);
+      if (!decl_function_context (fndecl))
+        {
+          c_genericize (fndecl);
+         lower_nested_functions (fndecl);
+          c_finalize (fndecl);
+        }
       else
       else
-       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+        {
+          /* Register this function with cgraph just far enough to get it
+            added to our parent's nested function list.  Handy, since the
+            C front end doesn't have such a list.  */
+          (void) cgraph_node (fndecl);
+        }
     }
 
     }
 
-  if (DECL_STATIC_DESTRUCTOR (fndecl))
-    {
-      if (targetm.have_ctors_dtors)
-       (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
-                                       DEFAULT_INIT_PRIORITY);
-      else
-       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-    }
+  /* We're leaving the context of this function, so zap cfun.
+     It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
+     tree_rest_of_compilation.  */
+  cfun = NULL;
+  current_function_decl = NULL;
 }
 
 }
 
-/* Like c_expand_body_1 but only for unnested functions.  */
+/* Generate the RTL for the body of FNDECL.  */
 
 void
 c_expand_body (tree fndecl)
 {
 
 
 void
 c_expand_body (tree fndecl)
 {
 
-  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
-    c_expand_body_1 (fndecl, 0);
+  if (!DECL_INITIAL (fndecl)
+      || DECL_INITIAL (fndecl) == error_mark_node)
+    return;
+
+  tree_rest_of_compilation (fndecl, false);
+
+  if (DECL_STATIC_CONSTRUCTOR (fndecl)
+      && targetm.have_ctors_dtors)
+    targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
+                                 DEFAULT_INIT_PRIORITY);
+  if (DECL_STATIC_DESTRUCTOR (fndecl)
+      && targetm.have_ctors_dtors)
+    targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
+                                DEFAULT_INIT_PRIORITY);
 }
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
 }
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
@@ -6157,7 +6578,7 @@ c_expand_body (tree fndecl)
 void
 check_for_loop_decls (void)
 {
 void
 check_for_loop_decls (void)
 {
-  tree t;
+  struct c_binding *b;
 
   if (!flag_isoc99)
     {
 
   if (!flag_isoc99)
     {
@@ -6181,35 +6602,38 @@ check_for_loop_decls (void)
      interpretation, to avoid creating an extension which later causes
      problems.  */
 
      interpretation, to avoid creating an extension which later causes
      problems.  */
 
-  for (t = current_scope->tags; t; t = TREE_CHAIN (t))
+  for (b = current_scope->bindings; b; b = b->prev)
     {
     {
-      if (TREE_PURPOSE (t) != 0)
-        {
-          enum tree_code code = TREE_CODE (TREE_VALUE (t));
-
-          if (code == RECORD_TYPE)
-            error ("'struct %s' declared in 'for' loop initial declaration",
-                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-          else if (code == UNION_TYPE)
-            error ("'union %s' declared in 'for' loop initial declaration",
-                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-          else
-            error ("'enum %s' declared in 'for' loop initial declaration",
-                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-        }
-    }
+      tree id = b->id;
+      tree decl = b->decl;
 
 
-  for (t = current_scope->names; t; t = TREE_CHAIN (t))
-    {
-      if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
-       error ("%Jdeclaration of non-variable '%D' in 'for' loop "
-               "initial declaration", t, t);
-      else if (TREE_STATIC (t))
-       error ("%Jdeclaration of static variable '%D' in 'for' loop "
-              "initial declaration", t, t);
-      else if (DECL_EXTERNAL (t))
-       error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
-               "initial declaration", t, t);
+      if (!id)
+       continue;
+
+      switch (TREE_CODE (decl))
+       {
+       case VAR_DECL:
+         if (TREE_STATIC (decl))
+           error ("%Jdeclaration of static variable '%D' in 'for' loop "
+                  "initial declaration", decl, decl);
+         else if (DECL_EXTERNAL (decl))
+           error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
+                  "initial declaration", decl, decl);
+         break;
+
+       case RECORD_TYPE:
+         error ("'struct %E' declared in 'for' loop initial declaration", id);
+         break;
+       case UNION_TYPE:
+         error ("'union %E' declared in 'for' loop initial declaration", id);
+         break;
+       case ENUMERAL_TYPE:
+         error ("'enum %E' declared in 'for' loop initial declaration", id);
+         break;
+       default:
+         error ("%Jdeclaration of non-variable '%D' in 'for' loop "
+                "initial declaration", decl, decl);
+       }
     }
 }
 \f
     }
 }
 \f
@@ -6220,13 +6644,14 @@ void
 c_push_function_context (struct function *f)
 {
   struct language_function *p;
 c_push_function_context (struct function *f)
 {
   struct language_function *p;
-  p = ggc_alloc (sizeof (struct language_function));
+  p = GGC_NEW (struct language_function);
   f->language = p;
 
   p->base.x_stmt_tree = c_stmt_tree;
   f->language = p;
 
   p->base.x_stmt_tree = c_stmt_tree;
-  p->base.x_scope_stmt_stack = c_scope_stmt_stack;
-  p->x_in_iteration_stmt = c_in_iteration_stmt;
-  p->x_in_case_stmt = c_in_case_stmt;
+  p->x_break_label = c_break_label;
+  p->x_cont_label = c_cont_label;
+  p->x_switch_stack = c_switch_stack;
+  p->arg_info = current_function_arg_info;
   p->returns_value = current_function_returns_value;
   p->returns_null = current_function_returns_null;
   p->returns_abnormally = current_function_returns_abnormally;
   p->returns_value = current_function_returns_value;
   p->returns_null = current_function_returns_null;
   p->returns_abnormally = current_function_returns_abnormally;
@@ -6252,9 +6677,10 @@ c_pop_function_context (struct function *f)
     }
 
   c_stmt_tree = p->base.x_stmt_tree;
     }
 
   c_stmt_tree = p->base.x_stmt_tree;
-  c_scope_stmt_stack = p->base.x_scope_stmt_stack;
-  c_in_iteration_stmt = p->x_in_iteration_stmt;
-  c_in_case_stmt = p->x_in_case_stmt;
+  c_break_label = p->x_break_label;
+  c_cont_label = p->x_cont_label;
+  c_switch_stack = p->x_switch_stack;
+  current_function_arg_info = p->arg_info;
   current_function_returns_value = p->returns_value;
   current_function_returns_null = p->returns_null;
   current_function_returns_abnormally = p->returns_abnormally;
   current_function_returns_value = p->returns_value;
   current_function_returns_null = p->returns_null;
   current_function_returns_abnormally = p->returns_abnormally;
@@ -6274,7 +6700,7 @@ c_dup_lang_specific_decl (tree decl)
   if (!DECL_LANG_SPECIFIC (decl))
     return;
 
   if (!DECL_LANG_SPECIFIC (decl))
     return;
 
-  ld = ggc_alloc (sizeof (struct lang_decl));
+  ld = GGC_NEW (struct lang_decl);
   memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
   DECL_LANG_SPECIFIC (decl) = ld;
 }
   memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
   DECL_LANG_SPECIFIC (decl) = ld;
 }
@@ -6304,19 +6730,11 @@ current_stmt_tree (void)
   return &c_stmt_tree;
 }
 
   return &c_stmt_tree;
 }
 
-/* Returns the stack of SCOPE_STMTs for the current function.  */
-
-tree *
-current_scope_stmt_stack (void)
-{
-  return &c_scope_stmt_stack;
-}
-
 /* Nonzero if TYPE is an anonymous union or struct type.  Always 0 in
    C.  */
 
 int
 /* Nonzero if TYPE is an anonymous union or struct type.  Always 0 in
    C.  */
 
 int
-anon_aggr_type_p (tree node ATTRIBUTE_UNUSED)
+anon_aggr_type_p (tree ARG_UNUSED (node))
 {
   return 0;
 }
 {
   return 0;
 }
@@ -6328,50 +6746,17 @@ extract_interface_info (void)
 {
 }
 
 {
 }
 
-/* Return a new COMPOUND_STMT, after adding it to the current
-   statement tree.  */
-
-tree
-c_begin_compound_stmt (void)
-{
-  tree stmt;
-
-  /* Create the COMPOUND_STMT.  */
-  stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
-
-  return stmt;
-}
-
-/* Expand T (a DECL_STMT) if it declares an entity not handled by the
-   common code.  */
-
-void
-c_expand_decl_stmt (tree t)
-{
-  tree decl = DECL_STMT_DECL (t);
-
-  /* Expand nested functions.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_CONTEXT (decl) == current_function_decl
-      && DECL_SAVED_TREE (decl))
-    c_expand_body_1 (decl, 1);
-}
-
 /* Return the global value of T as a symbol.  */
 
 tree
 identifier_global_value        (tree t)
 {
 /* Return the global value of T as a symbol.  */
 
 tree
 identifier_global_value        (tree t)
 {
-  tree decl = IDENTIFIER_SYMBOL_VALUE (t);
-  if (decl == 0 || DECL_FILE_SCOPE_P (decl))
-    return decl;
+  struct c_binding *b;
 
 
-  /* Shadowed by something else; find the true global value.  */
-  for (decl = global_scope->names; decl; decl = TREE_CHAIN (decl))
-    if (DECL_NAME (decl) == t)
-      return decl;
+  for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed)
+    if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b))
+      return b->decl;
 
 
-  /* Only local values for this decl.  */
   return 0;
 }
 
   return 0;
 }
 
@@ -6381,15 +6766,15 @@ identifier_global_value (tree t)
 void
 record_builtin_type (enum rid rid_index, const char *name, tree type)
 {
 void
 record_builtin_type (enum rid rid_index, const char *name, tree type)
 {
-  tree id;
-  tree tdecl;
+  tree id, decl;
   if (name == 0)
     id = ridpointers[(int) rid_index];
   else
     id = get_identifier (name);
   if (name == 0)
     id = ridpointers[(int) rid_index];
   else
     id = get_identifier (name);
-  tdecl = build_decl (TYPE_DECL, id, type);
-  pushdecl (tdecl);
-  debug_hooks->type_decl (tdecl, 0);
+  decl = build_decl (TYPE_DECL, id, type);
+  pushdecl (decl);
+  if (debug_hooks->type_decl)
+    debug_hooks->type_decl (decl, false);
 }
 
 /* Build the void_list_node (void_type_node having been created).  */
 }
 
 /* Build the void_list_node (void_type_node having been created).  */
@@ -6400,6 +6785,34 @@ build_void_list_node (void)
   return t;
 }
 
   return t;
 }
 
+/* Return a structure for a parameter with the given SPECS, ATTRS and
+   DECLARATOR.  */
+
+tree
+build_c_parm (tree specs, tree attrs, tree declarator)
+{
+  return build_tree_list (build_tree_list (specs, declarator), attrs);
+}
+
+/* Return a declarator with nested attributes.  TARGET is the inner
+   declarator to which these attributes apply.  ATTRS are the
+   attributes.  */
+
+tree
+build_attrs_declarator (tree attrs, tree target)
+{
+  return tree_cons (attrs, target, NULL_TREE);
+}
+
+/* Return a declarator for a function with arguments specified by ARGS
+   and return type specified by TARGET.  */
+
+tree
+build_function_declarator (tree args, tree target)
+{
+  return build_nt (CALL_EXPR, target, args, NULL_TREE);
+}
+
 /* 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
 /* 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
@@ -6416,198 +6829,88 @@ make_pointer_declarator (tree type_quals_attrs, tree target)
   tree itarget = target;
   split_specs_attrs (type_quals_attrs, &quals, &attrs);
   if (attrs != NULL_TREE)
   tree itarget = target;
   split_specs_attrs (type_quals_attrs, &quals, &attrs);
   if (attrs != NULL_TREE)
-    itarget = tree_cons (attrs, target, NULL_TREE);
+    itarget = build_attrs_declarator (attrs, target);
   return build1 (INDIRECT_REF, quals, itarget);
 }
 
   return build1 (INDIRECT_REF, quals, itarget);
 }
 
-/* A wrapper around lhd_set_decl_assembler_name that gives static
-   variables their C names if they are at file scope and only one
-   translation unit is being compiled, for backwards compatibility
-   with certain bizarre assembler hacks (like crtstuff.c).  */
-
-void
-c_static_assembler_name (tree decl)
+/* Synthesize a function which calls all the global ctors or global
+   dtors in this file.  This is only used for targets which do not
+   support .ctors/.dtors sections.  FIXME: Migrate into cgraph.  */
+static void
+build_cdtor (int method_type, tree cdtors)
 {
 {
-  if (num_in_fnames == 1
-      && !TREE_PUBLIC (decl) && DECL_CONTEXT (decl)
-      && TREE_CODE (DECL_CONTEXT (decl)) == TRANSLATION_UNIT_DECL)
-    SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
-  else
-    lhd_set_decl_assembler_name (decl);
-}
+  tree body = 0;
 
 
-/* Hash and equality functions for link_hash_table: key off
-   DECL_ASSEMBLER_NAME.  */
+  if (!cdtors)
+    return;
 
 
-static hashval_t
-link_hash_hash (const void *x_p)
-{
-  tree x = (tree)x_p;
-  return (hashval_t) (long)DECL_ASSEMBLER_NAME (x);
-}
+  for (; cdtors; cdtors = TREE_CHAIN (cdtors))
+    append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0),
+                             &body);
 
 
-static int
-link_hash_eq (const void *x1_p, const void *x2_p)
-{
-  tree x1 = (tree)x1_p;
-  tree x2 = (tree)x2_p;
-  return DECL_ASSEMBLER_NAME (x1) == DECL_ASSEMBLER_NAME (x2);
+  cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
 }
 
 }
 
-/* Propagate information between definitions and uses between multiple
-   translation units in TU_LIST based on linkage rules.  */
-
-void
-merge_translation_unit_decls (void)
+/* Perform final processing on one file scope's declarations (or the
+   external scope's declarations), GLOBALS.  */
+static void
+c_write_global_declarations_1 (tree globals)
 {
 {
-  const tree tu_list = current_file_decl;
-  tree tu;
+  size_t len = list_length (globals);
+  tree *vec = XNEWVEC (tree, len);
+  size_t i;
   tree decl;
   tree decl;
-  htab_t link_hash_table;
-  tree block;
-
-  /* Create the BLOCK that poplevel would have created, but don't
-     actually call poplevel since that's expensive.  */
-  block = make_node (BLOCK);
-  BLOCK_VARS (block) = current_scope->names;
-  TREE_USED (block) = 1;
-  DECL_INITIAL (current_file_decl) = block;
-
-  /* If only one translation unit seen, no copying necessary.  */
-  if (TREE_CHAIN (tu_list) == NULL_TREE)
-    return;
-
-  link_hash_table = htab_create (1021, link_hash_hash, link_hash_eq, NULL);
-
-  /* Enter any actual definitions into the hash table.  */
-  for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
-    for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
-      if (TREE_PUBLIC (decl) && ! DECL_EXTERNAL (decl))
-       {
-         PTR *slot;
-         slot = htab_find_slot (link_hash_table, decl, INSERT);
-
-         /* If we've already got a definition, work out which one is
-            the real one, put it into the hash table, and make the
-            other one DECL_EXTERNAL.  This is important to avoid
-            putting out two definitions of the same symbol in the
-            assembly output.  */
-         if (*slot != NULL)
-           {
-             tree old_decl = (tree) *slot;
-
-             /* If this is weak or common or whatever, suppress it
-                in favor of the other definition.  */
-             if (DECL_WEAK (decl))
-               DECL_EXTERNAL (decl) = 1;
-             else if (DECL_WEAK (old_decl) && ! DECL_WEAK (decl))
-               DECL_EXTERNAL (old_decl) = 1;
-             else if (DECL_COMMON (decl) || DECL_ONE_ONLY (decl))
-               DECL_EXTERNAL (decl) = 1;
-             else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl))
-               DECL_EXTERNAL (old_decl) = 1;
-
-             if (DECL_EXTERNAL (decl))
-               {
-                 DECL_INITIAL (decl) = NULL_TREE;
-                 DECL_COMMON (decl) = 0;
-                 DECL_ONE_ONLY (decl) = 0;
-                 DECL_WEAK (decl) = 0;
-               }
-             else if (DECL_EXTERNAL (old_decl))
-               {
-                 DECL_INITIAL (old_decl) = NULL_TREE;
-                 DECL_COMMON (old_decl) = 0;
-                 DECL_ONE_ONLY (old_decl) = 0;
-                 DECL_WEAK (old_decl) = 0;
-                 *slot = decl;
-               }
-             else
-               {
-                 error ("%Jredefinition of global '%D'", decl, decl);
-                 error ("%J'%D' previously defined here", old_decl, old_decl);
-               }
-           }
-         else
-           *slot = decl;
-       }
 
 
-  /* Now insert the desired information from all the definitions
-     into any plain declarations.  */
-  for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
-    for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
-      if (TREE_PUBLIC (decl) && DECL_EXTERNAL (decl))
-       {
-         tree global_decl;
-         global_decl = htab_find (link_hash_table, decl);
-
-         if (! global_decl)
-           continue;
+  /* Process the decls in the order they were written.  */
+  for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+    vec[i] = decl;
 
 
-         /* Print any appropriate error messages, and partially merge
-            the decls.  */
-         (void) duplicate_decls (decl, global_decl);
-       }
+  wrapup_global_declarations (vec, len);
+  check_global_declarations (vec, len);
 
 
-  htab_delete (link_hash_table);
+  free (vec);
 }
 
 }
 
-/* Perform final processing on file-scope data.  */
-
 void
 void
-c_write_global_declarations(void)
+c_write_global_declarations (void)
 {
 {
-  tree link;
-
-  for (link = current_file_decl; link; link = TREE_CHAIN (link))
-    {
-      tree globals = BLOCK_VARS (DECL_INITIAL (link));
-      int len = list_length (globals);
-      tree *vec = xmalloc (sizeof (tree) * len);
-      int i;
-      tree decl;
-
-      /* Process the decls in the order they were written.  */
-
-      for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
-       vec[i] = decl;
-
-      wrapup_global_declarations (vec, len);
+  tree ext_block, t;
 
 
-      check_global_declarations (vec, len);
+  /* We don't want to do this if generating a PCH.  */
+  if (pch_file)
+    return;
 
 
-      /* Clean up.  */
-      free (vec);
-    }
-}
+  /* Don't waste time on further processing if -fsyntax-only or we've
+     encountered errors.  */
+  if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+    return;
 
 
-/* Reset the parser's state in preparation for a new file.  */
+  /* Close the external scope.  */
+  ext_block = pop_scope ();
+  external_scope = 0;
+  if (current_scope)
+    abort ();
 
 
-void
-c_reset_state (void)
-{
-  tree link;
-  tree file_scope_decl;
-
-  /* Pop the global scope.  */
-  if (current_scope != global_scope)
-      current_scope = global_scope;
-  file_scope_decl = current_file_decl;
-  DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
-  BLOCK_SUPERCONTEXT (DECL_INITIAL (file_scope_decl)) = file_scope_decl;
-  truly_local_externals = NULL_TREE;
-
-  /* Start a new global binding level.  */
-  pushlevel (0);
-  global_scope = current_scope;
-  current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
-  TREE_CHAIN (current_file_decl) = file_scope_decl;
-
-  /* Reintroduce the builtin declarations.  */
-  for (link = first_builtin_decl;
-       link != TREE_CHAIN (last_builtin_decl);
-       link = TREE_CHAIN (link))
-    pushdecl (copy_node (link));
+  /* Process all file scopes in this compilation, and the external_scope,
+     through wrapup_global_declarations and check_global_declarations.  */
+  for (t = all_translation_units; t; t = TREE_CHAIN (t))
+    c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
+  c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+
+  /* Generate functions to call static constructors and destructors
+     for targets that do not support .ctors/.dtors sections.  These
+     functions have magic names which are detected by collect2.  */
+  build_cdtor ('I', static_ctors); static_ctors = 0;
+  build_cdtor ('D', static_dtors); static_dtors = 0;
+
+  /* We're done parsing; proceed to optimize and emit assembly.
+     FIXME: shouldn't be the front end's responsibility to call this.  */
+  cgraph_optimize ();
+
+  /* Presently this has to happen after cgraph_optimize.
+     FIXME: shouldn't be the front end's responsibility to call this.  */
+  if (flag_mudflap)
+    mudflap_finish_file ();
 }
 
 #include "gt-c-decl.h"
 }
 
 #include "gt-c-decl.h"