Revised c-decl.c patch - ObjC still not quite right

Ziemowit Laski zlaski@apple.com
Sat Mar 20 22:07:00 GMT 2004


Zack,

I'll make you a deal. :-)  Why don't you review and approve

   http://gcc.gnu.org/ml/gcc-patches/2004-03/msg00222.html

and I'll give you temporary absolution for breaking comp-types-1.m and 
fix the issue once your patch is in.  You game? :-)

--Zem

On 20 Mar 2004, at 0.42, Zack Weinberg wrote:

>
> Here's my revisions to date.  libobjc now builds, but I still see a
> few regressions in the objc testsuite:
>
> FAIL: objc.dg/comp-types-1.m  (test for warnings, line 37)
> FAIL: objc.dg/comp-types-1.m  (test for warnings, line 53)
> FAIL: objc.dg/comp-types-1.m  (test for warnings, line 71)
> FAIL: objc.dg/comp-types-1.m  (test for warnings, line 72)
> FAIL: objc.dg/comp-types-1.m  (test for warnings, line 82)
> FAIL: objc.dg/comp-types-1.m  (test for warnings, line 83)
>
> I can't see any obvious reason why these would have been caused by my
> patch, but neither can I see any obvious other cause for them.
>
> Java works now, I think.  I got the dreaded segfault-that-disappears-
> on-retry building libjava.  *Might* have been an out-of-memory
> condition.
>
> C, C++, F77 are in good shape. Haven't yet incorporated the
> suggestions for better commentary.
>
> All testing is on i686-linux btw.
>
> zw
>
> ===================================================================
> Index: c-common.h
> --- c-common.h	17 Feb 2004 18:32:32 -0000	1.222
> +++ c-common.h	20 Mar 2004 08:40:29 -0000
> @@ -329,6 +329,8 @@ extern void (*lang_expand_function_end)
>     noreturn attribute.  */
>  extern int (*lang_missing_noreturn_ok_p) (tree);
>
> +extern void push_file_scope (void);
> +extern void pop_file_scope (void);
>  extern int yyparse (void);
>  extern stmt_tree current_stmt_tree (void);
>  extern tree *current_scope_stmt_stack (void);
> @@ -950,9 +952,6 @@ extern int self_promoting_args_p (tree);
>  extern tree strip_array_types (tree);
>  extern tree strip_pointer_operator (tree);
>
> -/* This function resets the parsers' state in preparation for parsing
> -   a new file.  */
> -extern void c_reset_state (void);
>  /* This is the basic parsing function.  */
>  extern void c_parse_file (void);
>  /* This is misnamed, it actually performs end-of-compilation 
> processing.  */
> ===================================================================
> Index: c-decl.c
> --- c-decl.c	18 Mar 2004 18:58:01 -0000	1.485
> +++ c-decl.c	20 Mar 2004 08:40:29 -0000
> @@ -108,19 +108,13 @@ static GTY(()) tree c_scope_stmt_stack;
>  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. 
>  */
> -
> -static GTY(()) tree first_builtin_decl;
> -static GTY(()) tree last_builtin_decl;
> -
>  /* A DECL for the current file-scope context.  */
>
>  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.  */
>
> @@ -144,10 +138,56 @@ static int warn_about_return_type;
>  /* 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;
> +
>  
> -/* 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.  Finally, the ->contour field points
> +   back to the relevant scope structure; this is mainly used to make
> +   decls in the externals scope invisible (see below).
> +
> +   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.  */
> +
> +struct c_binding GTY(())
> +{
> +  tree decl;			/* the decl bound */
> +  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 */
> +  struct c_scope *contour;	/* the scope in which this decl is bound */
> +};
> +
> +#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_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.
>
> @@ -157,18 +197,37 @@ static int current_extern_inline;
>     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
> -   global scope even though that isn't the current scope.
> +   file scope even though that isn't the current scope.
> +
> +   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:
> +
> +     If, within the same translation unit, the same identifier appears
> +     with both internal and external linkage, the behavior is
> +     undefined.
> +
> +     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 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.
> +   The bindings list is strictly in reverse order of declarations;
> +   pop_scope relies on this.  */
>
> -   The order of the tags, shadowed, and shadowed_tags
> -   lists does not matter, so we just prepend to these lists.  */
>
>  struct c_scope GTY(())
>  {
> @@ -178,35 +237,18 @@ struct c_scope GTY(())
>    /* 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;
>
> +  /* 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;
> @@ -230,20 +272,28 @@ struct c_scope GTY(())
>
>  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 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 {	\
> @@ -271,7 +321,7 @@ static GTY(()) struct c_scope *global_sc
>
>  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.  */
>
> @@ -282,27 +332,11 @@ static bool next_is_function_body;
>  tree static_ctors, static_dtors;
>
>  /* 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 lookup_name_in_scope (tree, struct c_scope *);
> +static tree c_make_fname_decl (tree, int);
>  static tree grokdeclarator (tree, tree, enum decl_context, int, tree 
> *);
>  static tree grokparms (tree, int);
>  static void layout_array_type (tree);
> -static tree c_make_fname_decl (tree, int);
> -static void c_expand_body_1 (tree, int);
> -static tree any_external_decl (tree);
> -static void record_external_decl (tree);
> -static void warn_if_shadowing (tree, tree);
> -static void 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 *);
>  
>  /* States indicating how grokdeclarator() should handle declspecs 
> marked
>     with __attribute__((deprecated)).  An object declared as
> @@ -319,9 +353,9 @@ static enum deprecated_states deprecated
>  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)];
> @@ -330,6 +364,80 @@ c_print_identifier (FILE *file, tree nod
>  	       (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)
> +{
> +  struct c_binding *b, **here;
> +
> +  if (binding_freelist)
> +    {
> +      b = binding_freelist;
> +      binding_freelist = b->prev;
> +    }
> +  else
> +    b = ggc_alloc (sizeof (struct c_binding));
> +
> +  b->shadowed = 0;
> +  b->decl = decl;
> +  b->id = name;
> +  b->contour = scope;
> +
> +  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)->contour->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;
> +
> +  b->id = 0;
> +  b->decl = 0;
> +  b->contour = 0;
> +  b->shadowed = 0;
> +  b->prev = binding_freelist;
> +  binding_freelist = b;
> +
> +  return prev;
> +}
> +
>  
>  /* Hook called at end of compilation to assume 1 elt
>     for a file-scope tentative array defn that wasn't complete before. 
>  */
> @@ -354,40 +462,6 @@ c_finish_incomplete_decl (tree decl)
>      }
>  }
>  
> -/* 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 *
> @@ -403,30 +477,34 @@ void
>  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)
>      {
> -      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)
> +	    {
> +	      DECL_REGISTER (b->decl) = 0;
> +	      TREE_THIS_VOLATILE (b->decl) = 1;
> +	    }
>  	}
> +
>        /* 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)
>  {
> -  return current_scope == global_scope;
> +  return current_scope == file_scope && 
> !c_override_global_bindings_to_false;
>  }
>
>  void
> @@ -443,19 +521,8 @@ declare_parm_level (void)
>    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
> -pushlevel (int dummy ATTRIBUTE_UNUSED)
> +push_scope (void)
>  {
>    if (next_is_function_body)
>      {
> @@ -480,49 +547,46 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
>      }
>    else
>      {
> -      struct c_scope *scope = make_scope ();
> +      struct c_scope *scope;
> +      if (scope_freelist)
> +	{
> +	  scope = scope_freelist;
> +	  scope_freelist = scope->outer;
> +	}
> +      else
> +	scope = ggc_alloc_cleared (sizeof (struct c_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;
>      }
>  }
>
>  /* 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.
> -
> -   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.
> -
> -   FIXME: Eliminate the need for all arguments.  */
> +   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
> -poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
> +pop_scope (void)
>  {
>    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;
> -
> -  if (keep == KEEP_MAYBE)
> -    keep = (scope->names || scope->tags);
> +  tree block, context, p;
> +  struct c_binding *b;
>
> -  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.  */
> @@ -530,28 +594,44 @@ poplevel (int keep, int dummy ATTRIBUTE_
>    if (keep)
>      {
>        block = make_node (BLOCK);
> -      BLOCK_VARS (block) = scope->names;
>        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)
> +    context = current_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:
> +	  /* Warnings for unused labels, errors for undefined labels.  */
>  	  if (TREE_USED (p) && !DECL_INITIAL (p))
>  	    {
>  	      error ("%Jlabel `%D' used but not defined", p, p);
> @@ -564,94 +644,101 @@ poplevel (int keep, int dummy ATTRIBUTE_
>  	      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;
> +
> +#ifdef ENABLE_CHECKING
> +	  if (I_LABEL_BINDING (b->id) != b) abort ();
> +#endif
> + 	  I_LABEL_BINDING (b->id) = b->shadowed;
> + 	  break;
>
> -	  IDENTIFIER_LABEL_VALUE (DECL_NAME (p)) = 0;
> -	  break;
> +	case ENUMERAL_TYPE:
> +	case UNION_TYPE:
> +	case RECORD_TYPE:
> +	  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:
> +	  /* 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;
> -	  goto normal;
> +	  goto common_symbol;
>
>  	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.  Keep this in sync with
> +	     stmt.c:warn_about_unused_variables, which we cannot use
> +	     since it expects a different data structure.  */
> +	  if (warn_unused_variable
>  	      && !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);
> +
>  	  /* 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 (!C_DECL_IN_EXTERNAL_SCOPE (p) || scope == external_scope)
> +	    {
> +	      TREE_CHAIN (p) = BLOCK_VARS (block);
> +	      BLOCK_VARS (block) = p;
> +	    }
>
> -	default:
> -	normal:
> -	  if (DECL_NAME (p))
> +	  /* 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)
>  	    {
> -	      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;
> +#ifdef ENABLE_CHECKING
> +	      if (I_SYMBOL_BINDING (b->id) != b) abort ();
> +#endif
> +	      I_SYMBOL_BINDING (b->id) = b->shadowed;
>  	    }
>  	  break;
> +
> +	default:
> +	  abort ();
>  	}
>      }
>
> -  /* 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.
> -
> -     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.  */
> -
> -  decl = scope->function_body ? current_function_decl : block;
> -  for (p = scope->tags; p; p = TREE_CHAIN (p))
> +
> +  /* Dispose of the block that we just made inside some higher level. 
>  */
> +  if ((scope->function_body || scope == file_scope) && context)
>      {
> -      if (TREE_PURPOSE (p))
> -	IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0;
> -      if (decl)
> -	TYPE_CONTEXT (TREE_VALUE (p)) = decl;
> +      DECL_INITIAL (context) = block;
> +      BLOCK_SUPERCONTEXT (block) = context;
>      }
> -
> -  /* 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. 
>  */
> -  if (scope->function_body && current_function_decl)
> -    DECL_INITIAL (current_function_decl) = block;
>    else if (scope->outer)
>      {
>        if (block)
> @@ -664,11 +751,60 @@ poplevel (int keep, int dummy ATTRIBUTE_
>      }
>
>    /* 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;
>  }
>
> +void
> +push_file_scope (void)
> +{
> +  tree decl;
> +  tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
> +  TREE_CHAIN (file_decl) = current_file_decl;
> +  current_file_decl = file_decl;
> +
> +  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);
> +}
> +
> +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 ();
> +
> +  /* Kludge: don't actually pop the file scope if generating a
> +     precompiled header, so that macros and local symbols are still
> +     visible to the PCH generator.  */
> +  if (pch_file)
> +    return;
> +
> +  /* And pop off the file scope.  */
> +  pop_scope ();
> +  file_scope = 0;
> +
> +  cpp_undef_all (parse_in);
> +}
> +
>  /* 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.  */
> @@ -679,15 +815,6 @@ insert_block (tree 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)
> -{
> -}
>  
>  /* Push a definition or a declaration of struct, union or enum tag 
> "name".
>     "type" should be the type node.
> @@ -696,24 +823,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.  */
>
> -void
> +static void
>  pushtag (tree name, tree type)
>  {
> -  struct c_scope *b = current_scope;
> -
>    /* 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);
>
>    /* 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
> @@ -725,7 +841,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.
> -     This will be updated in poplevel.  */
> +     This will be updated in pop_scope.  */
>    TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
>  }
>  
> @@ -916,8 +1032,9 @@ diagnose_mismatched_decls (tree 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);
> @@ -927,7 +1044,7 @@ diagnose_mismatched_decls (tree newdecl,
>  	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;
>      }
> @@ -935,7 +1052,7 @@ diagnose_mismatched_decls (tree newdecl,
>    if (!comptypes (oldtype, newtype, COMPARE_STRICT))
>      {
>        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.  */
> @@ -1013,13 +1130,14 @@ diagnose_mismatched_decls (tree newdecl,
>  	 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)
> -	    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;
>  	}
> @@ -1190,8 +1308,15 @@ diagnose_mismatched_decls (tree newdecl,
>      }
>    else /* PARM_DECL, VAR_DECL */
>      {
> -      /* Redeclaration of a PARM_DECL is invalid unless this is the
> -	 real position of a forward-declared parameter (GCC extension).  */
> +      /* 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)))
>  	{
> @@ -1258,13 +1383,26 @@ merge_decls (tree newdecl, tree olddecl,
>    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))
>      {
> +      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;
> -      return;
>      }
>
>    DECL_ATTRIBUTES (newdecl)
> @@ -1421,9 +1559,11 @@ merge_decls (tree newdecl, tree 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);
> +	  C_DECL_DECLARED_BUILTIN (newdecl) = 1;
>  	}
>
>        /* Also preserve various other info from the definition.  */
> @@ -1454,6 +1594,9 @@ merge_decls (tree newdecl, tree olddecl,
>  	}
>      }
>
> +  /* This bit must not get wiped out.  */
> +  C_DECL_IN_EXTERNAL_SCOPE (newdecl) |= C_DECL_IN_EXTERNAL_SCOPE 
> (olddecl);
> +
>    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
>       But preserve OLDDECL's DECL_UID.  */
>    {
> @@ -1495,69 +1638,49 @@ duplicate_decls (tree newdecl, tree oldd
>  }
>
>  
> -/* Return any external DECL associated with ID, whether or not it is
> -   currently in scope.  */
> -
> -static tree
> -any_external_decl (tree id)
> -{
> -  tree decl = IDENTIFIER_SYMBOL_VALUE (id);
> -  tree t;
> -
> -  if (decl == 0 || TREE_CODE (decl) == ERROR_MARK)
> -    return 0;
> -  else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl))
> -    return decl;
> -
> -  t = purpose_member (id, truly_local_externals);
> -  if (t)
> -    return TREE_VALUE (t);
> -
> -  return 0;
> -}
> -
> -/* Record an external decl DECL.  This only does something if a
> -   shadowing decl already exists.  */
> +/* Check whether decl-node NEW shadows an existing declaration.  */
>  static void
> -record_external_decl (tree decl)
> +warn_if_shadowing (tree new)
>  {
> -  tree name = DECL_NAME (decl);
> -  if (!IDENTIFIER_SYMBOL_VALUE (name))
> -    return;
> -
> -  truly_local_externals = tree_cons (name, decl, 
> truly_local_externals);
> -}
> +  struct c_binding *b;
>
> -/* 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.  */
> -static void
> -warn_if_shadowing (tree x, tree old)
> -{
> -  /* Nothing to shadow?  */
> -  if (old == 0
> -      /* Shadow warnings not wanted?  */
> -      || !warn_shadow
> +  /* Shadow warnings wanted?  */
> +  if (!warn_shadow
>        /* No shadow warnings for internally generated vars.  */
> -      || DECL_SOURCE_LINE (x) == 0
> +      || DECL_SOURCE_LINE (new) == 0
>        /* No shadow warnings for vars made for inlining.  */
> -      || DECL_FROM_INLINE (x)
> +      || DECL_FROM_INLINE (new)
>        /* 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) == PARM_DECL && 
> current_scope->outer->parm_flag))
>      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?  Do not be confused by a second 
> binding
> +     to the same decl in the externals scope.  */
> +  for (b = I_SYMBOL_BINDING (DECL_NAME (new)); b; b = b->shadowed)
> +    if (b->decl && b->decl != new && b->contour != external_scope)
> +      {
> +	tree old = b->decl;
>
> -  warning ("%Jshadowed declaration is here", old);
> +	if (TREE_CODE (old) == PARM_DECL)
> +	  warning ("%Jdeclaration of '%D' shadows a parameter", new, new);
> +	else if (DECL_FILE_SCOPE_P (old))
> +	  warning ("%Jdeclaration of '%D' shadows a global declaration",
> +		   new, new);
> +	else if (TREE_CODE (old) == FUNCTION_DECL && DECL_BUILT_IN (old))
> +	  warning ("%Jdeclaration of '%D' shadows a built-in function",
> +		   new, new);
> +	else
> +	  warning ("%Jdeclaration of '%D' shadows a previous local", new, 
> new);
> +
> +	if (TREE_CODE (old) != FUNCTION_DECL || !DECL_BUILT_IN (old))
> +	  warning ("%Jshadowed declaration is here", old);
> +
> +	break;
> +      }
>  }
>
>
> @@ -1638,12 +1761,7 @@ pushdecl (tree x)
>  {
>    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;
>
>    /* Functions need the lang_decl data.  */
>    if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
> @@ -1659,130 +1777,110 @@ pushdecl (tree x)
>    else
>      DECL_CONTEXT (x) = current_function_decl;
>
> -  if (name)
> +  /* Anonymous decls are just inserted in the scope.  */
> +  if (!name)
>      {
> -      tree old;
> +      bind (name, x, scope);
> +      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->contour == scope)
> +    {
> +      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)
> +    {
>        if (warn_nested_externs
> -	  && scope != global_scope
> -	  && DECL_EXTERNAL (x)
> +	  && scope != file_scope
>  	  && !DECL_IN_SYSTEM_HEADER (x))
>  	warning ("nested extern declaration of `%s'",
>  		 IDENTIFIER_POINTER (name));
>
> -      old = lookup_name_current_level (name);
> -      if (old && duplicate_decls (x, old))
> -	{
> -	  /* 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)
> -	    {
> -	      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;
> -		  }
> -	    }
> -	  return old;
> -	}
> -      if (DECL_EXTERNAL (x) || scope == global_scope)
> -	{
> -	  /* 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 (duplicate_decls (x, ext))
> -		{
> -		  /* XXX This copy_node call violates the basic
> -		     assumption that there is only one DECL for any
> -		     given object.  This causes all sorts of problems
> -		     elsewhere.  To correct it we must stop chaining
> -		     DECLs directly within the scope structure (work
> -		     in progress).  -zw 2004-03-05  */
> -		  x = copy_node (ext);
> -
> -		  /* Kludge around one of the worst consequences of
> -		     the above copy_node call, viz. that the arg_info
> -		     block created by get_parm_info can survive in a
> -		     copied FUNCTION_DECL after store_parm_decls is
> -		     done with it, and confuse the debug info
> -		     generators.  */
> -		  if (TREE_CODE (ext) == FUNCTION_DECL
> -		      && DECL_ARGUMENTS (ext)
> -		      && TREE_CODE (DECL_ARGUMENTS (ext)) == TREE_LIST)
> -		    DECL_ARGUMENTS (ext) = 0;
> -		}
> -	    }
> -	  else
> -	    record_external_decl (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)
> -	{
> -	  warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name));
> -	  scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
> -				       scope->shadowed);
> -	}
> -
> -      /* 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)))
> -	{
> -	  tree element = TREE_TYPE (x);
> -
> -	  while (TREE_CODE (element) == ARRAY_TYPE)
> -	    element = TREE_TYPE (element);
> -	  element = TYPE_MAIN_VARIANT (element);
> +      while (b && b->contour != external_scope)
> +	b = b->shadowed;
>
> -	  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));
> +      /* 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
> +	  && (DECL_EXTERNAL (x) || TREE_PUBLIC (x)
> +	      || same_translation_unit_p (x, b->decl))
> +	  && duplicate_decls (x, b->decl))
> +	{
> +	  bind (name, b->decl, scope);
> +	  return b->decl;
> +	}
> +      else if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
> +	{
> +	  C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
> +	  bind (name, x, external_scope);
>  	}
>      }
>
> -  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);
> +
> +  /* 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;
>  }
>
> -/* 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.  */
> @@ -1797,44 +1895,72 @@ pushdecl_top_level (tree x)
>
>    name = DECL_NAME (x);
>
> -  if (IDENTIFIER_SYMBOL_VALUE (name))
> +  if (I_SYMBOL_BINDING (name))
>      abort ();
>
>    DECL_CONTEXT (x) = current_file_decl;
> -  IDENTIFIER_SYMBOL_VALUE (name) = x;
> +  if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
> +    {
> +      C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
> +      bind (name, x, external_scope);
> +    }
> +  if (file_scope)
> +    bind (name, x, file_scope);
>
> -  SCOPE_LIST_APPEND (global_scope, names, x);
>    return x;
>  }
>  
> +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)
>  {
> -  tree decl = any_external_decl (functionid);
> +  tree decl = lookup_name_in_scope (functionid, external_scope);
>
>    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))
> -	{
> -	  implicit_decl_warning (DECL_NAME (decl));
> -	  if (! DECL_FILE_SCOPE_P (decl))
> -	    warning ("%Jprevious declaration of '%D'", decl, decl);
> -	  C_DECL_IMPLICIT (decl) = 1;
> -	}
> -      /* 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));
> +      /* 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_SOURCE_LINE (decl) == 0)
> +	{
> +	  bind (functionid, decl, file_scope);
> +	  return decl;
> +	}
> +      else
> +	{
> +	  /* Implicit declaration of a function already declared
> +	     (somehow) in a different scope, or as a built-in.
> +	     If this is the first time this has happened, warn;
> +	     then recycle the old declaration.  */
> +	  if (!C_DECL_IMPLICIT (decl))
> +	    {
> +	      implicit_decl_warning (functionid, decl);
> +	      C_DECL_IMPLICIT (decl) = 1;
> +	    }
> +	  bind (functionid, decl, current_scope);
> +	  return decl;
> +	}
>      }
>
>    /* Not seen before.  */
> @@ -1842,7 +1968,7 @@ implicitly_declare (tree functionid)
>    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.  */
> @@ -1861,16 +1987,6 @@ implicitly_declare (tree functionid)
>    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
> @@ -1884,14 +2000,12 @@ undeclared_variable (tree id)
>
>    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
>      {
> -      error ("`%s' undeclared (first use in this function)",
> -	     IDENTIFIER_POINTER (id));
> +      error ("'%E' undeclared (first use in this function)", id);
>
>        if (! already)
>  	{
> @@ -1900,12 +2014,11 @@ undeclared_variable (tree id)
>  	  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);
>  }
>  
>  /* Subroutine of lookup_label, declare_label, define_label: construct 
> a
> @@ -1923,20 +2036,6 @@ make_label (tree name, location_t locati
>    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
> @@ -1957,7 +2056,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__.  */
> -  label = IDENTIFIER_LABEL_VALUE (name);
> +  label = I_LABEL_DECL (name);
>    if (label && (DECL_CONTEXT (label) == current_function_decl
>  		|| C_DECLARED_LABEL_FLAG (label)))
>      {
> @@ -1973,7 +2072,7 @@ lookup_label (tree name)
>    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);
>    return label;
>  }
>
> @@ -1988,26 +2087,25 @@ lookup_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 */
> -  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->contour == current_scope)
> +    {
> +      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.  */
> -  bind_label (name, label, current_scope);
> +  bind (name, label, current_scope);
>    return label;
>  }
>
> @@ -2018,13 +2116,11 @@ declare_label (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.  */
> -  label = IDENTIFIER_LABEL_VALUE (name);
> +  tree label = I_LABEL_DECL (name);
>
>    if (label
>        && ((DECL_CONTEXT (label) == current_function_decl
> @@ -2033,10 +2129,7 @@ define_label (location_t location, tree
>  	      && 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)
> @@ -2052,7 +2145,7 @@ define_label (location_t location, tree
>        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);
>      }
>
>    if (warn_traditional && !in_system_header && lookup_name (name))
> @@ -2065,16 +2158,6 @@ define_label (location_t location, tree
>    return label;
>  }
>  
> -/* Return the list of declarations of the current scope.
> -   This hook is optional and not implemented for C.  */
> -
> -tree
> -getdecls (void)
> -{
> -  return 0;
> -}
> -
> -
>  /* 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.
> @@ -2085,25 +2168,29 @@ getdecls (void)
>  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;
>
> -  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.  */
> -  if (thislevel_only || TREE_CODE (tag) != code)
> +  if (thislevel_only || TREE_CODE (b->decl) != code)
>      {
> -      if (current_scope == global_scope
> -	  || purpose_member (name, current_scope->tags))
> +      /* 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->contour == current_scope
> +	  || (current_scope == file_scope && b->contour == external_scope))
>  	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;
> @@ -2116,7 +2203,7 @@ lookup_tag (enum tree_code code, tree na
>        if (thislevel)
>  	pending_xref_error ();
>      }
> -  return tag;
> +  return b->decl;
>  }
>
>  /* Print an error message now
> @@ -2143,36 +2230,22 @@ pending_xref_error (void)
>  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->contour != external_scope || TREE_CODE (b->decl) == 
> TYPE_DECL))
> +    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
> -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->contour == scope)
> +      return b->decl;
>    return 0;
>  }
>  
> @@ -2193,9 +2266,9 @@ c_init_decl_processing (void)
>
>    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
> @@ -2203,9 +2276,6 @@ c_init_decl_processing (void)
>    input_location.file = "<internal>";
>    input_location.line = 0;
>
> -  /* 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);
>
>    c_common_nodes_and_builtins ();
> @@ -2231,9 +2301,6 @@ c_init_decl_processing (void)
>
>    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
> @@ -2269,8 +2336,7 @@ c_make_fname_decl (tree id, int type_dep
>    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);
>      }
>
>    finish_decl (decl, init, NULL_TREE);
> @@ -2292,20 +2358,31 @@ builtin_function (const char *name, tree
>  		  enum built_in_class class, const char *library_name,
>  		  tree attrs)
>  {
> -  tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
> -  DECL_EXTERNAL (decl) = 1;
> +  tree id = get_identifier (name);
> +  tree decl = build_decl (FUNCTION_DECL, id, type);
>    TREE_PUBLIC (decl) = 1;
> +  DECL_EXTERNAL (decl) = 1;
> +  DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared (sizeof (struct 
> lang_decl));
> +  DECL_BUILT_IN_CLASS (decl) = class;
> +  DECL_FUNCTION_CODE (decl) = function_code;
>    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 ();
> +
> +  C_DECL_IN_EXTERNAL_SCOPE (decl) = 1;
> +  bind (id, decl, external_scope);
> +
> +  /* 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)
> @@ -2519,34 +2596,31 @@ start_decl (tree declarator, tree declsp
>    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:
> -	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:
> -	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.  */
> -	error ("parameter `%s' is initialized",
> -	       IDENTIFIER_POINTER (DECL_NAME (decl)));
> +	error ("parameter '%D' is initialized", decl);
>  	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)))
> @@ -2562,14 +2636,12 @@ start_decl (tree declarator, tree declsp
>  	  }
>  	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))))
>  	  {
> -	    error ("elements of array `%s' have incomplete type",
> -		   IDENTIFIER_POINTER (DECL_NAME (decl)));
> +	    error ("elements of array '%D' have incomplete type", decl);
>  	    initialized = 0;
>  	  }
>        }
> @@ -2577,12 +2649,12 @@ start_decl (tree declarator, tree declsp
>    if (initialized)
>      {
>        DECL_EXTERNAL (decl) = 0;
> -      if (current_scope == global_scope)
> +      if (current_scope == file_scope)
>  	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.
> -	 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;
>      }
>
> @@ -2643,21 +2715,6 @@ start_decl (tree declarator, tree declsp
>       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);
> -    }
> -
>    return tem;
>  }
>
> @@ -2674,7 +2731,7 @@ finish_decl (tree decl, tree init, tree
>    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);
> @@ -2812,7 +2869,7 @@ finish_decl (tree decl, tree init, tree
>      }
>
>    /* 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);
>
>    /* Output the assembler code and/or RTL code for variables and 
> functions,
> @@ -2891,7 +2948,7 @@ finish_decl (tree decl, tree init, tree
>    /* 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.  */
> @@ -2955,14 +3012,13 @@ push_parm_decl (tree parm)
>    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)
>  {
> -  tree parm;
> +  struct c_binding *b;
>
>    if (pedantic && !current_scope->warned_forward_parm_decls)
>      {
> @@ -2970,12 +3026,9 @@ mark_forward_parm_decls (void)
>        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;
>  }
>  
>  static GTY(()) int compound_literal_number;
> @@ -2996,7 +3049,7 @@ build_compound_literal (tree type, tree
>    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;
> @@ -3316,8 +3369,7 @@ grokdeclarator (tree declarator, tree de
>    /* 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.
> @@ -3413,11 +3465,11 @@ grokdeclarator (tree declarator, tree de
>        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));
> +	   else if (TREE_TYPE (t) == error_mark_node)
> +	    ;
>  	  else
>  	    {
>  	      type = TREE_TYPE (t);
> @@ -3674,7 +3726,7 @@ grokdeclarator (tree declarator, tree de
>  		    | (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'");
> @@ -3712,12 +3764,12 @@ grokdeclarator (tree declarator, tree de
>      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);
>        }
> -    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);
> @@ -3970,14 +4022,15 @@ grokdeclarator (tree declarator, tree de
>  	}
>        else if (TREE_CODE (declarator) == CALL_EXPR)
>  	{
> -	  /* Declaring a function type.  Say it's a definition only
> -	   for the CALL_EXPR closest to the identifier.  */
> +	  /* Say it's a definition only for the CALL_EXPR closest to
> +	     the identifier.  */
>  	  bool really_funcdef = (funcdef_flag
>  				 && (TREE_CODE (TREE_OPERAND (declarator, 0))
>  				     == IDENTIFIER_NODE));
>  	  tree arg_types;
>
> -	  /* 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.  */
>  	  if (type == error_mark_node)
>  	    continue;
>
> @@ -4186,7 +4239,7 @@ grokdeclarator (tree declarator, tree de
>    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)))))))
>      {
> @@ -4321,10 +4374,10 @@ grokdeclarator (tree declarator, tree de
>  	   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);
> +			  || current_scope == file_scope);
>
>  	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);
> @@ -4333,7 +4386,7 @@ grokdeclarator (tree declarator, tree de
>  	/* 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);
> @@ -4414,20 +4467,23 @@ grokdeclarator (tree declarator, tree de
>  	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
> -	   `static' and the global declaration is not visible.  */
> -	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
> +		&& global_decl != visible_decl
>  		&& TREE_CODE (global_decl) == VAR_DECL
> -		&& lookup_name (declarator) != global_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);
> @@ -4443,7 +4499,7 @@ grokdeclarator (tree declarator, tree de
>  	   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)));
> @@ -4518,7 +4574,10 @@ grokparms (tree arg_info, int funcdef_fl
>        && !in_system_header)
>      warning ("function declaration isn't a prototype");
>
> -  if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == 
> 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");
> @@ -4574,141 +4633,193 @@ grokparms (tree arg_info, int funcdef_fl
>      }
>  }
>
> -/* 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:
> +/* 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.
> +                      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
> -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;
>
> -  /* 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))
> -    {
> -      if (TREE_THIS_VOLATILE (parms)
> -	  || TREE_READONLY (parms)
> -	  || DECL_REGISTER (parms))
> -	error ("'void' as only parameter may not be qualified");
> -
> -      list = make_node (TREE_LIST);
> -      ARG_INFO_TYPES (list) = build_tree_list (0, void_type_node);
> -      return list;
> -    }
> +  /* 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;
>
> -  /* Sanity check all of the parameter declarations.  */
> -  for (decl = parms; decl; decl = TREE_CHAIN (decl))
> -    {
> +  /* This function is only called if there was *something* on the
> +     parameter list.  */
>  #ifdef ENABLE_CHECKING
> -      if (TREE_CODE (decl) != PARM_DECL)
> -	abort ();
> -      if (TREE_ASM_WRITTEN (decl))
> -	abort ();
> +  if (b == 0)
> +    abort ();
>  #endif
>
> -      /* 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;
> +  /* 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 (b->decl)
> +	  || TREE_READONLY (b->decl)
> +	  || DECL_REGISTER (b->decl))
> +	error ("'void' as only parameter may not be qualified");
>
> -      /* Check for (..., void, ...) and issue an error.  */
> -      if (VOID_TYPE_P (type) && !DECL_NAME (decl) && 
> !gave_void_only_once_err)
> -	{
> -	  error ("'void' must be the only parameter");
> -	  gave_void_only_once_err = true;
> -	}
> +      /* There cannot be an ellipsis.  */
> +      if (ellipsis)
> +	error ("'void' must be the only parameter");
>
> -      type = build_tree_list (0, type);
> -      *last_type = type;
> -      last_type = &TREE_CHAIN (type);
> +      ARG_INFO_TYPES (arg_info) = void_list_node;
> +      return arg_info;
>      }
>
> -  /* 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 ();
> -
> -	  error ("%Jparameter '%D' has just a forward declaration",
> -		 decl, decl);
> -      }
> +  if (!ellipsis)
> +    types = void_list_node;
>
> -  /* 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))
> +  /* Break up the bindings list into parms, tags, types, and others;
> +     apply sanity checks; purge the name-to-decl bindings.  */
> +  while (b)
>      {
> -      enum tree_code code = TREE_CODE (TREE_VALUE (decl));
> +      tree decl = b->decl;
> +      tree type = TREE_TYPE (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;
>
> -      /* The keyword should not be translated.  */
> -      switch (code)
> +      switch (TREE_CODE (decl))
>  	{
> -	case RECORD_TYPE:   keyword = "struct"; break;
> -	case UNION_TYPE:    keyword = "union";  break;
> -	case ENUMERAL_TYPE: keyword = "enum";   break;
> -	default: abort ();
> -	}
> +	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;
> +	    }
>
> -      if (TREE_PURPOSE (decl))
> -	/* The %s will be one of 'struct', 'union', or 'enum'.  */
> -	warning ("'%s %E' declared inside parameter list",
> -		 keyword, TREE_PURPOSE (decl));
> -      else
> -	/* The %s will be one of 'struct', 'union', or 'enum'.  */
> -	warning ("anonymous %s declared inside parameter list", keyword);
> +	  /* 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;
>
> -      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 ENUMERAL_TYPE: keyword = "struct"; goto tag;
> +	case UNION_TYPE:    keyword = "union"; goto tag;
> +	case RECORD_TYPE:   keyword = "enum"; 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;
> +	    }
>
> +	  /* 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);
> +	
> +	      if (! explained_incomplete_types)
> +		{
> +		  warning ("its scope is only this definition or declaration,"
> +			   " which is probably not what you want");
> +		  explained_incomplete_types = true;
> +		}
> +	    }
>
> -  if (void_at_end)
> -    {
> -      type = build_tree_list (0, void_type_node);
> -      *last_type = type;
> +	  tags = tree_cons (b->id, decl, tags);
> +	  break;
> +
> +	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.  */
> +	  if (b->id)
> +	    {
> +#ifdef ENABLE_CHECKING
> +	      if (I_SYMBOL_BINDING (b->id) != b) abort ();
> +#endif
> +	      I_SYMBOL_BINDING (b->id) = b->shadowed;
> +	    }
> +
> +	  TREE_CHAIN (decl) = others;
> +	  others = decl;
> +	  break;
> +
> +	  /* Other things that might be encountered.  */
> +	case LABEL_DECL:
> +	case FUNCTION_DECL:
> +	case VAR_DECL:
> +	case ERROR_MARK:
> +	default:
> +	  abort ();
> +	}
> +
> +      b = free_binding_and_advance (b);
>      }
>
> -  list = make_node (TREE_LIST);
> -  ARG_INFO_PARMS  (list) = parms;
> -  ARG_INFO_TAGS   (list) = tags;
> -  ARG_INFO_TYPES  (list) = types;
> -  ARG_INFO_OTHERS (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;
>  }
>  
>  /* Get the struct, enum or union (CODE says which) with tag NAME.
> @@ -4927,7 +5038,7 @@ tree
>  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,
> @@ -4937,19 +5048,6 @@ finish_struct (tree t, tree fieldlist, t
>
>    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))
> @@ -5219,10 +5317,7 @@ finish_enum (tree enumtype, tree values,
>    tree pair, tem;
>    tree minnode = 0, maxnode = 0, enum_value_type;
>    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);
>
>    decl_attributes (&enumtype, attributes, (int) 
> ATTR_FLAG_TYPE_IN_PLACE);
>
> @@ -5351,16 +5446,19 @@ build_enumerator (tree name, tree value)
>
>    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
>  	{
> -	  error ("enumerator value for `%s' not integer constant",
> -		 IDENTIFIER_POINTER (name));
> -	  value = 0;
> +	  value = default_conversion (value);
> +	  constant_expression_warning (value);
>  	}
>      }
>
> @@ -5377,6 +5475,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'");
> +      /* XXX This causes -pedantic to change the meaning of the 
> program.
> +	 Remove?  -zw 2004-03-15  */
>        value = convert (integer_type_node, value);
>      }
>
> @@ -5463,13 +5563,13 @@ start_function (tree declspecs, tree dec
>      pedwarn_c99 ("return type defaults to `int'");
>
>    /* 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.  */
> -  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)
>        && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
> @@ -5534,7 +5634,7 @@ start_function (tree declspecs, tree dec
>  #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'. 
>  */
> @@ -5600,7 +5700,7 @@ start_function (tree declspecs, tree dec
>
>    current_function_decl = pushdecl (decl1);
>
> -  pushlevel (0);
> +  push_scope ();
>    declare_parm_level ();
>
>    make_decl_rtl (current_function_decl, NULL);
> @@ -5639,75 +5739,56 @@ start_function (tree declspecs, tree dec
>  static void
>  store_parm_decls_newstyle (tree fndecl, tree arg_info)
>  {
> -  tree decl, last;
> -
> -  tree parms = ARG_INFO_PARMS (arg_info);
> -  tree tags = ARG_INFO_TAGS (arg_info);
> +  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.  */
> -      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
> +	   && DECL_CONTEXT (fndecl) == current_file_decl
> +	   && 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.  */
> -  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;
> -      if (DECL_NAME (decl) == 0)
> -	error ("%Jparameter name omitted", decl);
> +      if (DECL_NAME (decl))
> +	bind (DECL_NAME (decl), decl, current_scope);
>        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.  */
> -  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;
> -      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);
>      }
> -  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))
> -      {
> -	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);
>  }
>
>  /* Subroutine of store_parm_decls which handles old-style function
> @@ -5716,19 +5797,21 @@ store_parm_decls_newstyle (tree fndecl,
>  static void
>  store_parm_decls_oldstyle (tree fndecl, tree arg_info)
>  {
> +  struct c_binding *b;
>    tree parm, decl, last;
> -
> -  /* This is the identifier list from the function declarator.  */
>    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
> -  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
>
> +  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))
> @@ -5740,17 +5823,18 @@ store_parm_decls_oldstyle (tree fndecl,
>  	  continue;
>  	}
>
> -      decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
> -      if (decl && DECL_CONTEXT (decl) == fndecl)
> +      b = I_SYMBOL_BINDING (TREE_VALUE (parm));
> +      if (b && b->contour == current_scope)
>  	{
> +	  decl = b->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))
>  	    {
> -	      error ("%Jmultiple parameters named \"%D\"", decl, decl);
> +	      error ("%Jmultiple parameters named '%D'", decl, decl);
>  	      TREE_PURPOSE (parm) = 0;
>  	      continue;
>  	    }
> @@ -5758,7 +5842,7 @@ store_parm_decls_oldstyle (tree fndecl,
>  	     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);
> @@ -5773,9 +5857,9 @@ store_parm_decls_oldstyle (tree fndecl,
>  	  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)
> -	    warning ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
> +	    warning ("%Jtype of '%D' defaults to 'int'", decl, decl);
>  	}
>
>        TREE_PURPOSE (parm) = decl;
> @@ -5785,17 +5869,21 @@ store_parm_decls_oldstyle (tree fndecl,
>    /* 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)))
>  	{
> -	  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))
>  	{
> -	  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.
> @@ -5817,7 +5905,6 @@ store_parm_decls_oldstyle (tree fndecl,
>      {
>        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))
> @@ -5827,7 +5914,6 @@ store_parm_decls_oldstyle (tree fndecl,
>  	    last = TREE_PURPOSE (parm);
>  	    DECL_WEAK (last) = 0;
>  	  }
> -      current_scope->parms_last = last;
>        TREE_CHAIN (last) = 0;
>      }
>
> @@ -5877,7 +5963,7 @@ store_parm_decls_oldstyle (tree fndecl,
>
>  		  if (pedantic)
>  		    {
> -		      pedwarn ("promoted argument \"%D\" "
> +		      pedwarn ("promoted argument '%D' "
>  			       "doesn't match prototype", parm);
>  		      pedwarn ("%Hprototype declaration",
>  			       &current_function_prototype_locus);
> @@ -5885,7 +5971,7 @@ store_parm_decls_oldstyle (tree fndecl,
>  		}
>  	      else
>  		{
> -		  error ("argument \"%D\" doesn't match prototype", parm);
> +		  error ("argument '%D' doesn't match prototype", parm);
>  		  error ("%Hprototype declaration",
>  			 &current_function_prototype_locus);
>  		}
> @@ -5947,26 +6033,26 @@ store_parm_decls (void)
>    /* The argument information block for FNDECL.  */
>    tree arg_info = DECL_ARGUMENTS (fndecl);
>
> -  /* True if this definition is written with a prototype.  Since this
> -     is a function definition, we can treat a null parameter list
> -     (i.e. "foo()") as prototyped (C99 6.7.5.3p14) - this reduces
> -     overhead.  */
> -  bool prototype = (!ARG_INFO_PARMS (arg_info)
> -		    || TREE_CODE (ARG_INFO_PARMS (arg_info)) != 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.  */
> +  bool proto = ARG_INFO_TYPES (arg_info) != 0;
>
> -  if (prototype)
> +  if (proto)
>      store_parm_decls_newstyle (fndecl, arg_info);
>    else
>      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).  */
>
> -  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);
> @@ -6014,17 +6100,17 @@ finish_function (void)
>    /* 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
> +     bother calling push_scope/pop_scope, 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
> +     Note that the call to push_scope 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);
> +      push_scope ();
> +      pop_scope ();
>      }
>
>    if (TREE_CODE (fndecl) == FUNCTION_DECL
> @@ -6168,7 +6254,7 @@ c_expand_body (tree fndecl)
>  void
>  check_for_loop_decls (void)
>  {
> -  tree t;
> +  struct c_binding *b;
>
>    if (!flag_isoc99)
>      {
> @@ -6192,35 +6278,38 @@ check_for_loop_decls (void)
>       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));
> +      tree id = b->id;
> +      tree decl = b->decl;
>
> -          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)));
> -        }
> -    }
> +      if (!id)
> +	continue;
>
> -  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);
> +      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);
> +	}
>      }
>  }
>  
> @@ -6373,16 +6462,12 @@ c_expand_decl_stmt (tree t)
>  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->contour == file_scope || b->contour == external_scope)
> +      return b->decl;
>
> -  /* Only local values for this decl.  */
>    return 0;
>  }
>
> @@ -6393,14 +6478,11 @@ void
>  record_builtin_type (enum rid rid_index, const char *name, tree type)
>  {
>    tree id;
> -  tree tdecl;
>    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);
> +  pushdecl (build_decl (TYPE_DECL, id, type));
>  }
>
>  /* Build the void_list_node (void_type_node having been created).  */
> @@ -6447,178 +6529,42 @@ c_static_assembler_name (tree decl)
>      lhd_set_decl_assembler_name (decl);
>  }
>
> -/* Hash and equality functions for link_hash_table: key off
> -   DECL_ASSEMBLER_NAME.  */
> -
> -static hashval_t
> -link_hash_hash (const void *x_p)
> -{
> -  tree x = (tree)x_p;
> -  return (hashval_t) (long)DECL_ASSEMBLER_NAME (x);
> -}
> -
> -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);
> -}
> -
> -/* 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 file-scope data.  */
> +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 = xmalloc (sizeof (tree) * len);
> +  size_t i;
>    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;
> -
> -	  /* Print any appropriate error messages, and partially merge
> -	     the decls.  */
> -	  (void) duplicate_decls (decl, global_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;
>
> -  htab_delete (link_hash_table);
> +  wrapup_global_declarations (vec, len);
> +  check_global_declarations (vec, len);
> +
> +  free (vec);
>  }
>
> -/* Perform final processing on file-scope data.  */
> -
>  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);
> -
> -      check_global_declarations (vec, len);
> -
> -      /* Clean up.  */
> -      free (vec);
> -    }
> -}
> +  tree t;
>
> -/* Reset the parser's state in preparation for a new file.  */
> +  /* We don't want to do this if generating a PCH.  */
> +  if (pch_file)
> +    return;
>
> -void
> -c_reset_state (void)
> -{
> -  tree link;
> -  tree file_scope_decl;
> +  /* Process all file scopes in this compilation.  */
> +  for (t = current_file_decl; t; t = TREE_CHAIN (t))
> +    c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
>
> -  /* 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));
> +  /* Now do the same for the externals scope.  */
> +  t = pop_scope ();
> +  if (t)
> +    c_write_global_declarations_1 (BLOCK_VARS (t));
>  }
>
>  #include "gt-c-decl.h"
> ===================================================================
> Index: c-lang.c
> --- c-lang.c	4 Feb 2004 19:15:16 -0000	1.121
> +++ c-lang.c	20 Mar 2004 08:40:29 -0000
> @@ -65,6 +65,8 @@ enum c_language_kind c_language = clk_c;
>  #define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
>  #undef LANG_HOOKS_PARSE_FILE
>  #define LANG_HOOKS_PARSE_FILE c_common_parse_file
> +#undef LANG_HOOKS_CLEAR_BINDING_STACK
> +#define LANG_HOOKS_CLEAR_BINDING_STACK lhd_do_nothing
>  #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
>  #define LANG_HOOKS_TRUTHVALUE_CONVERSION 
> c_objc_common_truthvalue_conversion
>  #undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
> @@ -136,6 +138,19 @@ enum c_language_kind c_language = clk_c;
>  #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
>  #define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
>
> +/* The C front end's scoping structure is very different from
> +   that expected by the language-independent code; it is best
> +   to disable all of pushlevel, poplevel, set_block, and getdecls.
> +   This means it must also provide its own write_globals.  */
> +
> +#undef LANG_HOOKS_PUSHLEVEL
> +#define LANG_HOOKS_PUSHLEVEL lhd_do_nothing_i
> +#undef LANG_HOOKS_POPLEVEL
> +#define LANG_HOOKS_POPLEVEL lhd_do_nothing_iii_return_null_tree
> +#undef LANG_HOOKS_SET_BLOCK
> +#define LANG_HOOKS_SET_BLOCK lhd_do_nothing_t
> +#undef LANG_HOOKS_GETDECLS
> +#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
>  #undef LANG_HOOKS_WRITE_GLOBALS
>  #define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
>
> ===================================================================
> Index: c-objc-common.c
> --- c-objc-common.c	14 Mar 2004 22:26:00 -0000	1.41
> +++ c-objc-common.c	20 Mar 2004 08:40:29 -0000
> @@ -206,7 +206,7 @@ start_cdtor (int method_type)
>
>    body = c_begin_compound_stmt ();
>
> -  pushlevel (0);
> +  push_scope ();
>    clear_last_expr ();
>    add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
>
> @@ -220,7 +220,7 @@ finish_cdtor (tree body)
>    tree block;
>
>    scope = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
> -  block = poplevel (0, 0, 0);
> +  block = pop_scope ();
>    SCOPE_STMT_BLOCK (TREE_PURPOSE (scope)) = block;
>    SCOPE_STMT_BLOCK (TREE_VALUE (scope)) = block;
>
> @@ -236,10 +236,6 @@ c_objc_common_finish_file (void)
>  {
>    if (pch_file)
>      c_common_write_pch ();
> -
> -  /* If multiple translation units were built, copy information 
> between
> -     them based on linkage rules.  */
> -  merge_translation_unit_decls ();
>
>    cgraph_finalize_compilation_unit ();
>    cgraph_optimize ();
> ===================================================================
> Index: c-opts.c
> --- c-opts.c	4 Mar 2004 02:39:37 -0000	1.107
> +++ c-opts.c	20 Mar 2004 08:40:29 -0000
> @@ -1216,41 +1216,24 @@ c_common_init (void)
>  /* Initialize the integrated preprocessor after debug output has been
>     initialized; loop over each input file.  */
>  void
> -c_common_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
> +c_common_parse_file (int set_yydebug)
>  {
> -  unsigned file_index;
> -
>  #if YYDEBUG != 0
>    yydebug = set_yydebug;
>  #else
> -  warning ("YYDEBUG not defined");
> +  if (set_yydebug)
> +    warning ("YYDEBUG not defined");
>  #endif
>
> -  file_index = 0;
> -
> -  do
> -    {
> -      if (file_index > 0)
> -	{
> -	  /* Reset the state of the parser.  */
> -	  c_reset_state();
> +  if (num_in_fnames > 1)
> +    fatal_error ("sorry, inter-module analysis temporarily out of 
> commission");
>
> -	  /* Reset cpplib's macros and start a new file.  */
> -	  cpp_undef_all (parse_in);
> -	  main_input_filename = this_input_filename
> -	    = cpp_read_main_file (parse_in, in_fnames[file_index]);
> -	  if (this_input_filename == NULL)
> -	    break;
> -	}
> -      finish_options ();
> -      if (file_index == 0)
> -	pch_init();
> -      c_parse_file ();
> -
> -      file_index++;
> -    } while (file_index < num_in_fnames);
> -
> +  finish_options ();
> +  pch_init ();
> +  push_file_scope ();
> +  c_parse_file ();
>    finish_file ();
> +  pop_file_scope ();
>  }
>
>  /* Common finish hook for the C, ObjC and C++ front ends.  */
> ===================================================================
> Index: c-parse.in
> --- c-parse.in	27 Feb 2004 02:01:06 -0000	1.202
> +++ c-parse.in	20 Mar 2004 08:40:29 -0000
> @@ -208,7 +208,7 @@ do {									\
>  %type <ttype> any_word
>
>  %type <ttype> compstmt compstmt_start compstmt_nostart 
> compstmt_primary_start
> -%type <ttype> do_stmt_start poplevel stmt label
> +%type <ttype> do_stmt_start pop_scope stmt label
>
>  %type <ttype> c99_block_start c99_block_end
>  %type <ttype> declarator
> @@ -328,8 +328,6 @@ static int objc_need_raw_identifier;
>  #define OBJC_NEED_RAW_IDENTIFIER(VAL)	/* nothing */
>  @@end_ifc
>
> -static bool parsing_iso_function_signature;
> -
>  /* Tell yyparse how to print a token's value, if yydebug is set.  */
>
>  #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
> @@ -368,11 +366,6 @@ extdefs:
>  	;
>
>  extdef:
> -	extdef_1
> -	{ parsing_iso_function_signature = false; } /* Reset after any 
> external definition.  */
> -	;
> -
> -extdef_1:
>  	fndef
>  	| datadef
>  	| asmdef
> @@ -741,28 +734,8 @@ primary:
>  	;
>
>  old_style_parm_decls:
> -	old_style_parm_decls_1
> -	{
> -	  parsing_iso_function_signature = false; /* Reset after decls.  */
> -	}
> -	;
> -
> -old_style_parm_decls_1:
>  	/* empty */
> -	{
> -	  if (warn_traditional && !in_system_header
> -	      && parsing_iso_function_signature)
> -	    warning ("traditional C rejects ISO C style function 
> definitions");
> -	  if (warn_old_style_definition && !in_system_header
> -	      && !parsing_iso_function_signature)
> -	    warning ("old-style parameter declaration");
> -	  parsing_iso_function_signature = false; /* Reset after warning.  */
> -	}
>  	| datadecls
> -	{
> -	  if (warn_old_style_definition && !in_system_header)
> -	    warning ("old-style parameter declaration");
> -	}
>  	;
>
>  /* The following are analogous to lineno_decl, decls and decl
> @@ -1555,7 +1528,6 @@ nested_function:
>  		      pop_function_context ();
>  		      YYERROR1;
>  		    }
> -		  parsing_iso_function_signature = false; /* Don't warn about 
> nested functions.  */
>  		}
>  	   old_style_parm_decls save_location
>  		{ tree decl = current_function_decl;
> @@ -1586,7 +1558,6 @@ notype_nested_function:
>  		      pop_function_context ();
>  		      YYERROR1;
>  		    }
> -		  parsing_iso_function_signature = false; /* Don't warn about 
> nested functions.  */
>  		}
>  	  old_style_parm_decls save_location
>  		{ tree decl = current_function_decl;
> @@ -1620,9 +1591,6 @@ after_type_declarator:
>  		{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
>  	| after_type_declarator '(' parmlist_or_identifiers  %prec '.'
>  		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
> -/*	| after_type_declarator '(' error ')'  %prec '.'
> -		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
> -		  poplevel (0, 0, 0); }  */
>  	| after_type_declarator array_declarator  %prec '.'
>  		{ $$ = set_array_declarator_type ($2, $1, 0); }
>  	| '*' maybe_type_quals_attrs after_type_declarator  %prec UNARY
> @@ -1645,9 +1613,6 @@ parm_declarator:
>  parm_declarator_starttypename:
>  	  parm_declarator_starttypename '(' parmlist_or_identifiers  %prec 
> '.'
>  		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
> -/*	| parm_declarator_starttypename '(' error ')'  %prec '.'
> -		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
> -		  poplevel (0, 0, 0); }  */
>  	| parm_declarator_starttypename array_declarator  %prec '.'
>  		{ $$ = set_array_declarator_type ($2, $1, 0); }
>  	| TYPENAME
> @@ -1659,9 +1624,6 @@ parm_declarator_starttypename:
>  parm_declarator_nostarttypename:
>  	  parm_declarator_nostarttypename '(' parmlist_or_identifiers  %prec 
> '.'
>  		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
> -/*	| parm_declarator_nostarttypename '(' error ')'  %prec '.'
> -		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
> -		  poplevel (0, 0, 0); }  */
>  	| parm_declarator_nostarttypename array_declarator  %prec '.'
>  		{ $$ = set_array_declarator_type ($2, $1, 0); }
>  	| '*' maybe_type_quals_attrs parm_declarator_starttypename  %prec 
> UNARY
> @@ -1678,9 +1640,6 @@ parm_declarator_nostarttypename:
>  notype_declarator:
>  	  notype_declarator '(' parmlist_or_identifiers  %prec '.'
>  		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
> -/*	| notype_declarator '(' error ')'  %prec '.'
> -		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
> -		  poplevel (0, 0, 0); }  */
>  	| '(' maybe_attribute notype_declarator ')'
>  		{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
>  	| '*' maybe_type_quals_attrs notype_declarator  %prec UNARY
> @@ -2037,14 +1996,14 @@ lineno_stmt_decl_or_labels:
>  errstmt:  error ';'
>  	;
>
> -pushlevel:  /* empty */
> -		{ pushlevel (0);
> +push_scope:  /* empty */
> +		{ push_scope ();
>  		  clear_last_expr ();
>  		  add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
>  		}
>  	;
>
> -poplevel:  /* empty */
> +pop_scope:  /* empty */
>                  {
>  @@ifobjc
>  		  if (c_dialect_objc ())
> @@ -2059,7 +2018,7 @@ c99_block_start: /* empty */
>  		{ if (flag_isoc99)
>  		    {
>  		      $$ = c_begin_compound_stmt ();
> -		      pushlevel (0);
> +		      push_scope ();
>  		      clear_last_expr ();
>  		      add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
>  		    }
> @@ -2075,7 +2034,7 @@ c99_block_end: /* empty */
>                  { if (flag_isoc99)
>  		    {
>  		      tree scope_stmt = add_scope_stmt (/*begin_p=*/0, 
> /*partial_p=*/0);
> -		      $$ = poplevel (KEEP_MAYBE, 0, 0);
> +		      $$ = pop_scope ();
>  		      SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
>  			= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
>  			= $$;
> @@ -2124,8 +2083,8 @@ compstmt_start: '{' { compstmt_count++;
>
>  compstmt_nostart: '}'
>  		{ $$ = convert (void_type_node, integer_zero_node); }
> -	| pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
> -		{ $$ = poplevel (KEEP_MAYBE, 0, 0);
> +	| push_scope maybe_label_decls compstmt_contents_nonempty '}' 
> pop_scope
> +		{ $$ = pop_scope ();
>  		  SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
>  		    = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
>  		    = $$; }
> @@ -2589,11 +2548,11 @@ start_string_translation:
>     "void bar (int (__attribute__((__mode__(SI))) int foo));".  */
>  parmlist:
>  	  maybe_attribute
> -		{ pushlevel (0);
> +		{ push_scope ();
>  		  declare_parm_level (); }
>  	  parmlist_1
>  		{ $$ = $3;
> -		  poplevel (0, 0, 0); }
> +		  pop_scope (); }
>  	;
>
>  parmlist_1:
> @@ -2606,32 +2565,23 @@ parmlist_1:
>  	  parmlist_1
>  		{ $$ = $6; }
>  	| error ')'
> -		{ $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
> +		{ $$ = make_node (TREE_LIST); }
>  	;
>
>  /* This is what appears inside the parens in a function declarator.
>     Is value is represented in the format that grokdeclarator expects. 
>  */
>  parmlist_2:  /* empty */
> -		{ $$ = get_parm_info (0); }
> +		{ $$ = make_node (TREE_LIST); }
>  	| ELLIPSIS
> -		{ $$ = get_parm_info (0);
> -		  /* Gcc used to allow this as an extension.  However, it does
> -		     not work for all targets, and thus has been disabled.
> -		     Also, since func (...) and func () are indistinguishable,
> -		     it caused problems with the code in expand_builtin which
> -		     tries to verify that BUILT_IN_NEXT_ARG is being used
> -		     correctly.  */
> +		{ $$ = make_node (TREE_LIST);
> +		  /* Suppress -Wold-style-definition for this case.  */
> +		  TREE_CHAIN ($$) = error_mark_node;
>  		  error ("ISO C requires a named argument before `...'");
> -		  parsing_iso_function_signature = true;
>  		}
>  	| parms
> -		{ $$ = get_parm_info (1);
> -		  parsing_iso_function_signature = true;
> -		}
> +		{ $$ = get_parm_info (/*ellipsis=*/false); }
>  	| parms ',' ELLIPSIS
> -		{ $$ = get_parm_info (0);
> -		  parsing_iso_function_signature = true;
> -		}
> +		{ $$ = get_parm_info (/*ellipsis=*/true); }
>  	;
>
>  parms:
> @@ -2706,11 +2656,11 @@ setspecs_fp:
>     Its value is a list of ..._TYPE nodes or a list of identifiers.  */
>  parmlist_or_identifiers:
>  	  maybe_attribute
> -		{ pushlevel (0);
> +		{ push_scope ();
>  		  declare_parm_level (); }
>  	  parmlist_or_identifiers_1
>  		{ $$ = $3;
> -		  poplevel (0, 0, 0); }
> +		  pop_scope (); }
>  	;
>
>  parmlist_or_identifiers_1:
> @@ -3128,13 +3078,13 @@ optparmlist:
>  		}
>  	| ','
>  		{
> -		  pushlevel (0);
> +		  push_scope ();
>  		}
>  	  parmlist_2
>  		{
>  		  /* returns a tree list node generated by get_parm_info */
>  		  $$ = $3;
> -		  poplevel (0, 0, 0);
> +		  pop_scope ();
>  		}
>  	;
>
> @@ -3799,22 +3749,14 @@ yyprint (FILE *file, int yychar, YYSTYPE
>      }
>  }
>  
> -/* This is not the ideal place to put these, but we have to get them 
> out
> -   of c-lex.c because cp/lex.c has its own versions.  */
> +/* This is not the ideal place to put this, but we have to get it out
> +   of c-lex.c because cp/lex.c has its own version.  */
>
>  /* Parse the file.  */
>  void
>  c_parse_file (void)
>  {
>    yyparse ();
> -  /* In case there were missing closebraces, get us back to the global
> -     binding level.  */
> -  while (! global_bindings_p ())
> -    poplevel (0, 0, 0);
> -  /* __FUNCTION__ is defined at file scope ("").  This
> -     call may not be necessary as my tests indicate it
> -     still works without it.  */
> -  finish_fname_decls ();
>
>    if (malloced_yyss)
>      {
> ===================================================================
> Index: c-tree.h
> --- c-tree.h	29 Feb 2004 23:43:20 -0000	1.141
> +++ c-tree.h	20 Mar 2004 08:40:29 -0000
> @@ -24,22 +24,21 @@ Software Foundation, 59 Temple Place - S
>
>  #include "c-common.h"
>
> -/* Language-dependent contents of an identifier.  */
> +/* 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.  The contents of these lists
> +   are private to c-decl.c.  */
> +
> +struct c_binding;
>
> -/* The limbo_value is used for block level extern declarations, which 
> need
> -   to be type checked against subsequent extern declarations.  They 
> can't
> -   be referenced after they fall out of scope, so they can't be 
> global.
> -
> -   The rid_code field is used for keywords.  It is in all
> -   lang_identifier nodes, because some keywords are only special in a
> -   particular context.  */
> +/* Language-dependent contents of an identifier.  */
>
>  struct lang_identifier GTY(())
>  {
>    struct c_common_identifier common_id;
> -  tree symbol_value;
> -  tree tag_value;
> -  tree label_value;
> +  struct c_binding *symbol_binding; /* vars, funcs, constants, 
> typedefs */
> +  struct c_binding *tag_binding;    /* struct/union/enum tags */
> +  struct c_binding *label_binding;  /* labels */
>  };
>
>  /* The resulting tree type.  */
> @@ -64,26 +63,6 @@ struct lang_decl GTY(())
>    tree pending_sizes;
>  };
>
> -/* Macros for access to language-specific slots in an identifier.  */
> -/* Each of these slots contains a DECL node or null.  */
> -
> -/* The value of the identifier in the namespace of "ordinary 
> identifiers"
> -   (data objects, enum constants, functions, typedefs).  */
> -#define IDENTIFIER_SYMBOL_VALUE(NODE)	\
> -  (((struct lang_identifier *) (NODE))->symbol_value)
> -/* The value of the identifier in the namespace of struct, union,
> -   and enum tags.  */
> -#define IDENTIFIER_TAG_VALUE(NODE)	\
> -  (((struct lang_identifier *) (NODE))->tag_value)
> -/* The value of the identifier in the namespace of labels.  */
> -#define IDENTIFIER_LABEL_VALUE(NODE)	\
> -  (((struct lang_identifier *) (NODE))->label_value)
> -
> -/* In identifiers, C uses the following fields in a special way:
> -   TREE_PUBLIC        to record that there was a previous local 
> extern decl.
> -   TREE_USED          to record that such a decl was used.
> -   TREE_ADDRESSABLE   to record that the address of such a decl was 
> used.  */
> -
>  /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is 
> read-only.  */
>  #define C_TYPE_FIELDS_READONLY(TYPE) TREE_LANG_FLAG_1 (TYPE)
>
> @@ -128,11 +107,13 @@ struct lang_type GTY(())
>  /* For a FUNCTION_DECL, nonzero if it was an implicit declaration.  */
>  #define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
>
> -/* Nonzero for a declaration of an external object which is not
> -   currently in scope.  This is either a built-in declaration of
> -   a library function, before a real declaration has been seen,
> -   or a declaration that appeared in an inner scope that has ended.  
> */
> -#define C_DECL_INVISIBLE(EXP) DECL_LANG_FLAG_3 (EXP)
> +/* For any decl, nonzero if it is bound in the externals scope and
> +   pop_scope mustn't chain it into any higher block.  */
> +#define C_DECL_IN_EXTERNAL_SCOPE(EXP) DECL_LANG_FLAG_3 (EXP)
> +
> +/* For FUNCTION_DECLs, evaluates true if the decl is built-in but has
> +   been declared.  */
> +#define C_DECL_DECLARED_BUILTIN(EXP) DECL_LANG_FLAG_4 (EXP)
>
>  /* Nonzero for a decl which either doesn't exist or isn't a prototype.
>     N.B. Could be simplified if all built-in decls had complete 
> prototypes
> @@ -147,11 +128,6 @@ struct lang_type GTY(())
>     without prototypes.  */
>  #define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_BINFO (NODE)
>
> -/* Values for the first parameter to poplevel.  */
> -#define KEEP_NO		0
> -#define KEEP_YES	1
> -#define KEEP_MAYBE	2
> -
>  /* Save and restore the variables in this file and elsewhere
>     that keep track of the progress of compilation of the current 
> function.
>     Used for nested functions.  */
> @@ -181,9 +157,9 @@ extern int c_in_case_stmt;
>
>  extern int global_bindings_p (void);
>  extern tree getdecls (void);
> -extern void pushlevel (int);
> +extern void push_scope (void);
> +extern tree pop_scope (void);
>  extern void insert_block (tree);
> -extern void set_block (tree);
>  extern tree pushdecl (tree);
>  extern void c_expand_body (tree);
>
> @@ -203,12 +179,11 @@ extern void finish_decl (tree, tree, tre
>  extern tree finish_enum (tree, tree, tree);
>  extern void finish_function (void);
>  extern tree finish_struct (tree, tree, tree);
> -extern tree get_parm_info (int);
> +extern tree get_parm_info (bool);
>  extern tree grokfield (tree, tree, tree);
>  extern tree groktypename (tree);
>  extern tree groktypename_in_parm_context (tree);
>  extern tree implicitly_declare (tree);
> -extern int  in_parm_level_p (void);
>  extern void keep_next_level (void);
>  extern tree lookup_name (tree);
>  extern void pending_xref_error (void);
> @@ -216,7 +191,6 @@ extern void c_push_function_context (str
>  extern void c_pop_function_context (struct function *);
>  extern void push_parm_decl (tree);
>  extern tree pushdecl_top_level (tree);
> -extern void pushtag (tree, tree);
>  extern tree set_array_declarator_type (tree, tree, int);
>  extern void shadow_tag (tree);
>  extern void shadow_tag_warned (tree, int);
> @@ -230,7 +204,6 @@ extern tree c_begin_compound_stmt (void)
>  extern void c_expand_decl_stmt (tree);
>  extern void c_static_assembler_name (tree);
>  extern tree make_pointer_declarator (tree, tree);
> -extern void merge_translation_unit_decls (void);
>
>  /* in c-objc-common.c */
>  extern int c_disregard_inline_limits (tree);
> @@ -257,6 +230,7 @@ enum {
>  };
>
>  extern tree require_complete_type (tree);
> +extern int same_translation_unit_p (tree, tree);
>  extern int comptypes (tree, tree, int);
>  extern tree c_size_in_bytes (tree);
>  extern bool c_mark_addressable (tree);
> @@ -312,6 +286,11 @@ extern int current_function_returns_abno
>  /* Nonzero means we are reading code that came from a system header 
> file.  */
>
>  extern int system_header_p;
> +
> +/* True means global_bindings_p should return false even if the scope 
> stack
> +   says we are in file scope.  */
> +
> +extern bool c_override_global_bindings_to_false;
>
>  /* In c-decl.c */
>  extern void c_finish_incomplete_decl (tree);
> ===================================================================
> Index: c-typeck.c
> --- c-typeck.c	18 Mar 2004 20:58:34 -0000	1.289
> +++ c-typeck.c	20 Mar 2004 08:40:30 -0000
> @@ -51,7 +51,6 @@ Software Foundation, 59 Temple Place - S
>  static int missing_braces_mentioned;
>
>  static tree qualify_type (tree, tree);
> -static int same_translation_unit_p (tree, tree);
>  static int tagged_types_tu_compatible_p (tree, tree, int);
>  static int comp_target_types (tree, tree, int);
>  static int function_types_compatible_p (tree, tree, int);
> @@ -369,9 +368,9 @@ common_type (tree t1, tree t2)
>
>  	/* If both args specify argument types, we must merge the two
>  	   lists, argument by argument.  */
> -
> -	pushlevel (0);
> -	declare_parm_level ();
> +	/* Tell global_bindings_p to return false so that variable_size
> +	   doesn't abort on VLAs in parameter types.  */
> +	c_override_global_bindings_to_false = true;
>
>  	len = list_length (p1);
>  	newargs = 0;
> @@ -434,8 +433,7 @@ common_type (tree t1, tree t2)
>  	  parm_done: ;
>  	  }
>
> -	poplevel (0, 0, 0);
> -
> +	c_override_global_bindings_to_false = false;
>  	t1 = build_function_type (valtype, newargs);
>  	/* ... falls through ...  */
>        }
> @@ -614,11 +612,11 @@ comp_target_types (tree ttl, tree ttr, i
>  
>  /* Subroutines of `comptypes'.  */
>
> -/* Determine whether two types derive from the same translation unit.
> -   If the CONTEXT chain ends in a null, that type's context is still
> -   being parsed, so if two types have context chains ending in null,
> +/* Determine whether two trees derive from the same translation unit.
> +   If the CONTEXT chain ends in a null, that tree's context is still
> +   being parsed, so if two trees have context chains ending in null,
>     they're in the same translation unit.  */
> -static int
> +int
>  same_translation_unit_p (tree t1, tree t2)
>  {
>    while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
> @@ -633,7 +631,7 @@ same_translation_unit_p (tree t1, tree t
>    while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
>      switch (TREE_CODE_CLASS (TREE_CODE (t2)))
>        {
> -      case 'd': t2 = DECL_CONTEXT (t1); break;
> +      case 'd': t2 = DECL_CONTEXT (t2); break;
>        case 't': t2 = TYPE_CONTEXT (t2); break;
>        case 'b': t2 = BLOCK_SUPERCONTEXT (t2); break;
>        default: abort ();
> ===================================================================
> Index: coverage.c
> --- coverage.c	14 Mar 2004 22:26:01 -0000	1.31
> +++ coverage.c	20 Mar 2004 08:40:30 -0000
> @@ -902,7 +902,6 @@ create_coverage (void)
>    DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, 
> void_type_node);
>    DECL_UNINLINABLE (ctor) = 1;
>
> -  ctor = lang_hooks.decls.pushdecl (ctor);
>    rest_of_decl_compilation (ctor, 0, 1, 0);
>    announce_function (ctor);
>    current_function_decl = ctor;
> ===================================================================
> Index: langhooks.c
> --- langhooks.c	14 Mar 2004 22:26:06 -0000	1.60
> +++ langhooks.c	20 Mar 2004 08:40:30 -0000
> @@ -216,7 +216,7 @@ void
>  lhd_clear_binding_stack (void)
>  {
>    while (! lang_hooks.decls.global_bindings_p ())
> -    poplevel (0, 0, 0);
> +    lang_hooks.decls.poplevel (0, 0, 0);
>  }
>
>  /* Type promotion for variable arguments.  */
> ===================================================================
> Index: tree.c
> --- tree.c	19 Mar 2004 19:36:52 -0000	1.358
> +++ tree.c	20 Mar 2004 08:40:30 -0000
> @@ -941,11 +941,23 @@ chain_member (tree elem, tree chain)
>  int
>  list_length (tree t)
>  {
> -  tree tail;
> +  tree p = t;
> +#ifdef ENABLE_TREE_CHECKING
> +  tree q = t;
> +#endif
>    int len = 0;
>
> -  for (tail = t; tail; tail = TREE_CHAIN (tail))
> -    len++;
> +  while (p)
> +    {
> +      p = TREE_CHAIN (p);
> +#ifdef ENABLE_TREE_CHECKING
> +      if (len % 2)
> +	q = TREE_CHAIN (q);
> +      if (p == q)
> +	abort ();
> +#endif
> +      len++;
> +    }
>
>    return len;
>  }
> ===================================================================
> Index: cp/cp-lang.c
> --- cp/cp-lang.c	15 Mar 2004 18:20:51 -0000	1.74
> +++ cp/cp-lang.c	20 Mar 2004 08:40:32 -0000
> @@ -388,13 +388,6 @@ cp_var_mod_type_p (tree type)
>    return false;
>  }
>
> -/* Stub routine to tell people that this doesn't work yet.  */
> -void
> -c_reset_state (void)
> -{
> -  sorry ("inter-module optimisations not implemented yet");
> -}
> -
>  /* Construct a C++-aware pretty-printer for CONTEXT.  It is assumed
>     that CONTEXT->printer is an already constructed basic 
> pretty_printer.  */
>  static void
> @@ -408,4 +401,15 @@ cxx_initialize_diagnostics (diagnostic_c
>
>    /* It is safe to free this object because it was previously 
> malloc()'d.  */
>    free (base);
> +}
> +
> +/* Stubs to keep c-opts.c happy.  */
> +void
> +push_file_scope (void)
> +{
> +}
> +
> +void
> +pop_file_scope (void)
> +{
>  }
> ===================================================================
> Index: cp/parser.c
> --- cp/parser.c	19 Mar 2004 09:58:41 -0000	1.186
> +++ cp/parser.c	20 Mar 2004 08:40:32 -0000
> @@ -15347,7 +15347,6 @@ cp_parser_allow_gnu_extensions_p (cp_par
>  }
>
>  
> -
>  /* The parser.  */
>
>  static GTY (()) cp_parser *the_parser;
> @@ -15360,6 +15359,14 @@ void
>  c_parse_file (void)
>  {
>    bool error_occurred;
> +  static bool already_called = false;
> +
> +  if (already_called)
> +    {
> +      sorry ("inter-module optimizations not implemented for C++");
> +      return;
> +    }
> +  already_called = true;
>
>    the_parser = cp_parser_new ();
>    push_deferring_access_checks (flag_access_control
> ===================================================================
> Index: objc/objc-act.c
> --- objc/objc-act.c	6 Mar 2004 00:26:42 -0000	1.207
> +++ objc/objc-act.c	20 Mar 2004 08:40:34 -0000
> @@ -64,8 +64,6 @@ Boston, MA 02111-1307, USA.  */
>  #include "diagnostic.h"
>  #include "cgraph.h"
>
> -#define OBJC_VOID_AT_END	build_tree_list (NULL_TREE, void_type_node)
> -
>  /* This is the default way of generating a method name.  */
>  /* I am not sure it is really correct.
>     Perhaps there's a danger that it will make name conflicts
> @@ -161,7 +159,6 @@ static void generate_ivar_lists (void);
>  static void generate_dispatch_tables (void);
>  static void generate_shared_structures (void);
>  static tree generate_protocol_list (tree);
> -static void generate_forward_declaration_to_string_table (void);
>  static void build_protocol_reference (tree);
>
>  static tree build_keyword_selector (tree);
> @@ -1238,7 +1235,7 @@ synth_module_prologue (void)
>          = build_function_type (IMP_type,
>                                 tree_cons (NULL_TREE, id_type,
>                                            tree_cons (NULL_TREE, 
> selector_type,
> -                                                     
> OBJC_VOID_AT_END)));
> +                                                     
> void_list_node)));
>        umsg_decl = builtin_function (TAG_MSGSEND,
>  				    temp_type, 0, NOT_BUILT_IN,
>  				    NULL, NULL_TREE);
> @@ -1248,7 +1245,7 @@ synth_module_prologue (void)
>          = build_function_type (IMP_type,
>                                 tree_cons (NULL_TREE, super_type,
>                                            tree_cons (NULL_TREE, 
> selector_type,
> -                                                     
> OBJC_VOID_AT_END)));
> +                                                     
> void_list_node)));
>        umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
>  					  temp_type, 0, NOT_BUILT_IN,
>  					  NULL, NULL_TREE);
> @@ -1259,7 +1256,7 @@ synth_module_prologue (void)
>    temp_type = build_function_type (id_type,
>  				   tree_cons (NULL_TREE,
>  					      const_string_type_node,
> -					      OBJC_VOID_AT_END));
> +					      void_list_node));
>
>    objc_get_class_decl
>      = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
> @@ -1305,8 +1302,6 @@ synth_module_prologue (void)
>        TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
>      }
>
> -  generate_forward_declaration_to_string_table ();
> -
>    /* Forward declare constant_string_id and constant_string_type.  */
>    if (!constant_string_class_name)
>      constant_string_class_name = default_constant_string_class_name;
> @@ -1877,7 +1872,7 @@ build_module_descriptor (void)
>  				 get_identifier (TAG_EXECCLASS),
>  				 build_function_type (void_type_node,
>  					tree_cons (NULL_TREE, ptr_type_node,
> -						   OBJC_VOID_AT_END)));
> +						   void_list_node)));
>  						
>      DECL_EXTERNAL (execclass_decl) = 1;
>      DECL_ARTIFICIAL (execclass_decl) = 1;
> @@ -1892,7 +1887,7 @@ build_module_descriptor (void)
>      start_function (void_list_node_1,
>  		    build_nt (CALL_EXPR, init_function_name,
>  			      tree_cons (NULL_TREE, NULL_TREE,
> -					 OBJC_VOID_AT_END),
> +					 void_list_node),
>  			      NULL_TREE),
>  		    NULL_TREE);
>      store_parm_decls ();
> @@ -1919,22 +1914,6 @@ build_module_descriptor (void)
>    }
>  }
>
> -/* extern const char _OBJC_STRINGS[]; */
> -
> -static void
> -generate_forward_declaration_to_string_table (void)
> -{
> -  tree sc_spec, decl_specs, expr_decl;
> -
> -  sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], 
> NULL_TREE);
> -  decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], 
> sc_spec);
> -
> -  expr_decl
> -    = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), 
> NULL_TREE);
> -
> -  UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
> -}
> -
>  /* Return the DECL of the string IDENT in the SECTION.  */
>
>  static tree
> @@ -2699,7 +2678,7 @@ objc_enter_block (void)
>    block = begin_compound_stmt (0);
>  #else
>    block = c_begin_compound_stmt ();
> -  pushlevel (0);
> +  push_scope ();
>    clear_last_expr ();
>    add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
>  #endif
> @@ -2724,7 +2703,7 @@ objc_exit_block (void)
>    finish_compound_stmt (0, block);
>  #else
>    scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
> -  inner = poplevel (KEEP_MAYBE, 1, 0);
> +  inner = pop_scope ();
>
>    SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
>  	= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
> @@ -3331,7 +3310,7 @@ build_objc_exception_stuff (void)
>      = build_function_type (id_type,
>  			   tree_cons (NULL_TREE,
>  				      build_pointer_type (objc_exception_data_template),
> -				      OBJC_VOID_AT_END));
> +				      void_list_node));
>    objc_exception_extract_decl
>      = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, 
> NOT_BUILT_IN, NULL, NULL_TREE);
>    /* void objc_exception_try_enter(struct _objc_exception_data *); */
> @@ -3340,7 +3319,7 @@ build_objc_exception_stuff (void)
>      = build_function_type (void_type_node,
>  			   tree_cons (NULL_TREE,
>  				      build_pointer_type (objc_exception_data_template),
> -				      OBJC_VOID_AT_END));
> +				      void_list_node));
>    objc_exception_try_enter_decl
>      = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, 
> NOT_BUILT_IN, NULL, NULL_TREE);
>    objc_exception_try_exit_decl
> @@ -3350,7 +3329,7 @@ build_objc_exception_stuff (void)
>    /* void objc_sync_exit(id); */
>    temp_type = build_function_type (void_type_node,
>  				   tree_cons (NULL_TREE, id_type,
> -					      OBJC_VOID_AT_END));
> +					      void_list_node));
>    objc_exception_throw_decl
>      = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, 
> NOT_BUILT_IN, NULL, NULL_TREE);
>    DECL_ATTRIBUTES (objc_exception_throw_decl)
> @@ -3363,7 +3342,7 @@ build_objc_exception_stuff (void)
>    temp_type = build_function_type (integer_type_node,
>  				   tree_cons (NULL_TREE, id_type,
>  					      tree_cons (NULL_TREE, id_type,
> -							 OBJC_VOID_AT_END)));
> +							 void_list_node)));
>    objc_exception_match_decl
>      = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, 
> NOT_BUILT_IN, NULL, NULL_TREE);
>  	
> @@ -5463,7 +5442,7 @@ get_arg_type_list (tree meth, int contex
>
>    if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
>      /* We have a `, ...' immediately following the selector,
> -       finalize the arglist...simulate get_parm_info (0).  */
> +       finalize the arglist...simulate get_parm_info (true).  */
>      ;
>    else if (METHOD_ADD_ARGS (meth))
>      {
> @@ -5472,8 +5451,8 @@ get_arg_type_list (tree meth, int contex
>        chainon (arglist, add_arg_list);
>      }
>    else
> -    /* finalize the arglist...simulate get_parm_info (1) */
> -    chainon (arglist, OBJC_VOID_AT_END);
> +    /* finalize the arglist...simulate get_parm_info (false) */
> +    chainon (arglist, void_list_node);
>
>    return arglist;
>  }
> @@ -7539,7 +7518,8 @@ start_method_def (tree method)
>    UOBJC_SUPER_decl = NULL_TREE;
>
>    /* Must be called BEFORE start_function.  */
> -  pushlevel (0);
> +  push_scope ();
> +  declare_parm_level ();
>
>    /* Generate prototype declarations for arguments..."new-style".  */
>    synth_self_and_ucmd_args ();
> @@ -7819,9 +7799,9 @@ continue_method_def (void)
>
>    if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
>      /* We have a `, ...' immediately following the selector.  */
> -    parmlist = get_parm_info (0);
> +    parmlist = get_parm_info (/*ellipsis=*/true);
>    else
> -    parmlist = get_parm_info (1); /* place a `void_at_end' */
> +    parmlist = get_parm_info (/*ellipsis=*/false);
>
>  #ifndef OBJCPLUS
>    /* Set self_decl from the first argument...this global is used by
> @@ -7829,7 +7809,7 @@ continue_method_def (void)
>    self_decl = TREE_PURPOSE (parmlist);
>  #endif /* !OBJCPLUS */
>
> -  poplevel (0, 0, 0);
> +  pop_scope ();
>    really_start_method (objc_method_context, parmlist);
>    store_parm_decls ();
>  }
> @@ -8800,8 +8780,6 @@ finish_objc (void)
>        objc_ivar_chain = NULL_TREE;
>        objc_implementation_context = NULL_TREE;
>      }
> -
> -  generate_forward_declaration_to_string_table ();
>
>    /* Process the static instances here because initialization of 
> objc_symtab
>       depends on them.  */
> ===================================================================
> Index: objc/objc-act.h
> --- objc/objc-act.h	15 Oct 2003 00:10:27 -0000	1.20
> +++ objc/objc-act.h	20 Mar 2004 08:40:34 -0000
> @@ -234,7 +234,6 @@ enum objc_tree_index
>      OCTI_MCLS_DECL,
>      OCTI_SEL_TABLE_DECL,
>      OCTI_MODULES_DECL,
> -    OCTI_STRG_DECL,
>
>      OCTI_INTF_CTX,
>      OCTI_IMPL_CTX,
> @@ -360,7 +359,6 @@ extern GTY(()) tree objc_global_trees[OC
>  #define UOBJC_METACLASS_decl		objc_global_trees[OCTI_MCLS_DECL]
>  #define 
> UOBJC_SELECTOR_TABLE_decl	objc_global_trees[OCTI_SEL_TABLE_DECL]
>  #define UOBJC_MODULES_decl		objc_global_trees[OCTI_MODULES_DECL]
> -#define UOBJC_STRINGS_decl		objc_global_trees[OCTI_STRG_DECL]
>
>  /* The following are used when compiling a class implementation.
>     implementation_template will normally be an interface, however if
> ===================================================================
> Index: objc/objc-lang.c
> --- objc/objc-lang.c	3 Feb 2004 11:22:41 -0000	1.40
> +++ objc/objc-lang.c	20 Mar 2004 08:40:34 -0000
> @@ -55,6 +55,8 @@ enum c_language_kind c_language = clk_ob
>  #define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
>  #undef LANG_HOOKS_PARSE_FILE
>  #define LANG_HOOKS_PARSE_FILE c_common_parse_file
> +#undef LANG_HOOKS_CLEAR_BINDING_STACK
> +#define LANG_HOOKS_CLEAR_BINDING_STACK lhd_do_nothing
>  #undef LANG_HOOKS_EXPAND_EXPR
>  #define LANG_HOOKS_EXPAND_EXPR c_expand_expr
>  #undef LANG_HOOKS_MARK_ADDRESSABLE
> @@ -130,6 +132,19 @@ enum c_language_kind c_language = clk_ob
>  #undef LANG_HOOKS_TYPE_PROMOTES_TO
>  #define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
>
> +/* The C front end's scoping structure is very different from
> +   that expected by the language-independent code; it is best
> +   to disable all of pushlevel, poplevel, set_block, and getdecls.
> +   This means it must also provide its own write_globals.  */
> +
> +#undef LANG_HOOKS_PUSHLEVEL
> +#define LANG_HOOKS_PUSHLEVEL lhd_do_nothing_i
> +#undef LANG_HOOKS_POPLEVEL
> +#define LANG_HOOKS_POPLEVEL lhd_do_nothing_iii_return_null_tree
> +#undef LANG_HOOKS_SET_BLOCK
> +#define LANG_HOOKS_SET_BLOCK lhd_do_nothing_t
> +#undef LANG_HOOKS_GETDECLS
> +#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
>  #undef LANG_HOOKS_WRITE_GLOBALS
>  #define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
>
> ===================================================================
> Index: testsuite/gcc.dg/Wold-style-definition-1.c
> --- testsuite/gcc.dg/Wold-style-definition-1.c	15 Sep 2003 09:31:16 
> -0000	1.1
> +++ testsuite/gcc.dg/Wold-style-definition-1.c	20 Mar 2004 08:40:41 
> -0000
> @@ -5,19 +5,19 @@
>  /* { dg-options "-Wold-style-definition" } */
>
>  void
> -bar (a) int a; { } /* { dg-warning "old-style parameter declaration" 
> } */
> +bar (a) int a; { } /* { dg-warning "old-style function definition" } 
> */
>
> -void bar1 () {} /* { dg-warning "old-style parameter declaration" } */
> +void bar1 () {} /* { dg-warning "old-style function definition" } */
>
>  extern void bar2 (void);
>
> -void bar2 () {} /* { dg-warning "old-style parameter declaration" } */
> +void bar2 () {} /* { dg-warning "old-style function definition" } */
>
>  extern void bar3 (int);
>
> -void bar3 (a) {} /* { dg-warning "old-style parameter declaration" } 
> */
> +void bar3 (a) {} /* { dg-warning "old-style function definition" } */
>
> -void bar4 (a) {} /* { dg-warning "old-style parameter declaration" } 
> */
> +void bar4 (a) {} /* { dg-warning "old-style function definition" } */
>
>  void bar5 (int a) {}
>
> ===================================================================
> Index: testsuite/gcc.dg/Wshadow-2.c
> --- testsuite/gcc.dg/Wshadow-2.c	1 Jan 1970 00:00:00 -0000
> +++ testsuite/gcc.dg/Wshadow-2.c	20 Mar 2004 08:40:41 -0000
> @@ -0,0 +1,10 @@
> +/* Bogus warning for a double declaration of the same extern variable,
> +   first at file scope, then at block scope.  PR 13129.  */
> +
> +/* { dg-options "-Wshadow" } */
> +
> +extern struct foo bar;
> +void dummy()
> +{
> +  extern struct foo bar;  /* { dg-bogus "shadows" } */
> +}
> ===================================================================
> Index: testsuite/gcc.dg/builtins-30.c
> --- testsuite/gcc.dg/builtins-30.c	24 Jan 2004 05:27:45 -0000	1.2
> +++ testsuite/gcc.dg/builtins-30.c	20 Mar 2004 08:40:41 -0000
> @@ -7,20 +7,20 @@ extern double strtod (const char *, char
>  /* A built-in function may be overridden by an old-style definition
>     specifying too few arguments... */
>  double nan ()
> -{  /* { dg-warning "shadowing built-in" } */
> +{  /* { dg-warning "shadows a built-in" } */
>    return strtod ("nan", 0);
>  }
>
>  /* the right number, but the wrong type, arguments... */
>  float nanf (foo)
> -     int foo UNUSED;  /* { dg-warning "shadowing built-in" } */
> +     int foo UNUSED;  /* { dg-warning "shadows a built-in" } */
>  {
>    return strtod ("nan", 0);
>  }
>
>  /* or too many arguments.  */
>  long double nanl (foo, bar)
> -     const char *foo UNUSED;  /* { dg-warning "shadowing built-in" } 
> */
> +     const char *foo UNUSED;  /* { dg-warning "shadows a built-in" } 
> */
>       int bar UNUSED;
>  {
>    return strtod ("nan", 0);
> ===================================================================
> Index: testsuite/gcc.dg/decl-5.c
> --- testsuite/gcc.dg/decl-5.c	6 Mar 2004 09:28:51 -0000	1.1
> +++ testsuite/gcc.dg/decl-5.c	20 Mar 2004 08:40:41 -0000
> @@ -10,7 +10,7 @@ void a()
>  {
>    void c();
>    c();
> -} /* { dg-bogus "error" "PR c/14114" { xfail *-*-* } } */
> +}
>
>  void b()
>  {
> ===================================================================
> Index: testsuite/gcc.dg/local1.c
> --- testsuite/gcc.dg/local1.c	18 Mar 2004 18:58:07 -0000	1.2
> +++ testsuite/gcc.dg/local1.c	20 Mar 2004 08:40:41 -0000
> @@ -1,3 +1,19 @@
> +/* This is allowed, with the effect that the 'extern' declaration at 
> block
> +   scope refers to the same object as the 'static' declaration at 
> file scope.
> +
> +      C90 6.1.2.2 [as corrected by TC1], C99 6.2.2:
> +
> +          For an identifier declared with the storage-class specifier
> +          extern in a scope in which a prior declaration of that
> +          identifier is visible, if the prior declaration specifies
> +          internal or external linkage, the linkage of the identifier 
> at
> +          the later daclaration is the same as the linkage specified 
> at
> +          the prior declaration.  If no prior declaration is visible,
> +          or if the prior declaration specifies no linkage, then the
> +          identifer has external linkage.
> +
> +   This is PR 14366.  */
> +
>  static int i;
>
>  extern int i;
> ===================================================================
> Index: testsuite/gcc.dg/redecl-1.c
> --- testsuite/gcc.dg/redecl-1.c	11 Jan 2004 01:18:58 -0000	1.2
> +++ testsuite/gcc.dg/redecl-1.c	20 Mar 2004 08:40:41 -0000
> @@ -64,7 +64,7 @@ void test4(void)
>
>  void prime5(void)
>  {
> -  extern double bar5(double);	/* { dg-error "previous" "" { xfail 
> *-*-* } } */
> +  extern double bar5(double);	/* { dg-error "previous" "" } */
>  }
>
>  void test5(void)
> ===================================================================
> Index: testsuite/gcc.dg/unused-4.c
> --- testsuite/gcc.dg/unused-4.c	13 Nov 2003 19:40:19 -0000	1.2
> +++ testsuite/gcc.dg/unused-4.c	20 Mar 2004 08:40:41 -0000
> @@ -1,6 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-Wunused -O3" } */
>
> -static const int i = 0;
> +static const int i = 0;		/* { dg-warning "unused variable" } */
>  static void f() { }		/* { dg-warning "defined but not used" } */
>  static inline void g() { }
> ===================================================================
> Index: testsuite/gcc.dg/noncompile/incomplete-3.c
> --- testsuite/gcc.dg/noncompile/incomplete-3.c	1 Jan 1970 00:00:00 
> -0000
> +++ testsuite/gcc.dg/noncompile/incomplete-3.c	20 Mar 2004 08:40:41 
> -0000
> @@ -0,0 +1,9 @@
> +/* Both occurrences of "c" should get diagnostics.  PR 12391.  */
> +typedef struct { int a; } b_t;
> +
> +int foo (void)
> +{
> +  b_t d;
> +  struct b_t *c = &d;	/* { dg-warning "incompatible pointer type" } */
> +  c->a;			/* { dg-error "incomplete type" } */
> +}
> ===================================================================
> Index: testsuite/gcc.dg/noncompile/label-1.c
> --- testsuite/gcc.dg/noncompile/label-1.c	19 Jul 2003 23:32:55 
> -0000	1.1
> +++ testsuite/gcc.dg/noncompile/label-1.c	20 Mar 2004 08:40:41 -0000
> @@ -28,7 +28,7 @@ void c(void)
>  /* can't have two labels with the same name in the same function */
>  void d(void)
>  {
> - l: dummy();  /* { dg-error "previously defined" "prev def same 
> scope" } */
> + l: dummy();  /* { dg-error "previous definition" "prev def same 
> scope" } */
>   l: dummy();  /* { dg-error "duplicate label" "dup label same scope" 
> } */
>   goto l;
>  }
> @@ -36,7 +36,7 @@ void d(void)
>  /* even at different scopes */
>  void e(void)
>  {
> - l: dummy();	/* { dg-error "previously defined"  "prev def diff 
> scope" } */
> + l: dummy();	/* { dg-error "previous definition"  "prev def diff 
> scope" } */
>    {
>    l: dummy();	/* { dg-error "duplicate label" "dup label diff scope" 
> } */
>    }
> @@ -150,7 +150,7 @@ void m(void)
>
>  void n(void)
>  {
> -  __label__ l; /* { dg-error "previously declared" "outer label decl" 
> } */
> +  __label__ l; /* { dg-error "previous declaration" "outer label 
> decl" } */
>    void nest(void)
>      {
>      l: goto l;  /* { dg-error "duplicate label" "inner label defn" } 
> */
> ===================================================================
> Index: testsuite/gcc.dg/noncompile/label-lineno-1.c
> --- testsuite/gcc.dg/noncompile/label-lineno-1.c	19 Jul 2003 23:32:55 
> -0000	1.3
> +++ testsuite/gcc.dg/noncompile/label-lineno-1.c	20 Mar 2004 08:40:41 
> -0000
> @@ -4,7 +4,7 @@
>  void
>  foo(int i)
>  {
> - my_label: /* { dg-error "previously defined" "prev label" } */
> + my_label: /* { dg-error "previous definition" "prev label" } */
>
>    i++;
>
> ===================================================================
> Index: testsuite/gcc.dg/noncompile/undeclared-1.c
> --- testsuite/gcc.dg/noncompile/undeclared-1.c	1 Jan 1970 00:00:00 
> -0000
> +++ testsuite/gcc.dg/noncompile/undeclared-1.c	20 Mar 2004 08:40:41 
> -0000
> @@ -0,0 +1,8 @@
> +/* Test for no ICE with an undeclared identifier in an enum in 
> old-style
> +   parameter decls.  PR 12560.  */
> +/* { dg-options "-w" } */
> +
> +foo(c)
> +     enum { a = b } c;  /* { dg-error "undeclared|for each" } */
> +{
> +}
> ===================================================================
> Index: testsuite/objc.dg/naming-1.m
> --- testsuite/objc.dg/naming-1.m	17 Mar 2003 20:58:44 -0000	1.2
> +++ testsuite/objc.dg/naming-1.m	20 Mar 2004 08:40:42 -0000
> @@ -9,9 +9,7 @@ void foo(void)
>  {
>          int View;	/* ok */
>          View = 1;	/* ok */
> -	View *view;	/* { dg-error "`view' undeclared" } */
> -	/* { dg-error "is reported only once" "" { target *-*-* } 12 } */
> -	/* { dg-error "function it appears in" "" { target *-*-* } 12 } */
> +	View *view;	/* { dg-error "undeclared|only once|it appears" } */
>  }
>
>  void bar(void)



More information about the Gcc-patches mailing list