This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

c-decl.c rewrite - final


Here's the final version of the big c-decl.c rewrite.  To reiterate
the caveats:

- The patch induces a handful of regressions in the objc testsuite.
  Ziemowit Laski has promised to fix these.

- Inter-module optimization is broken to the point where I have
  forcibly disabled it.  I do not believe it will be terribly
  difficult to get it working again.

- The patch does not address PRs 7993, 12336, 13801, or 13956.
  Given the nature of 7993 I would like to ask that one of the
  Objective-C maintainers investigate applying to the 3.4 branch the
  patch that was already applied to the 3.3 branch - it needs fixing
  up to apply cleanly, but should not require a total rewrite.  The
  others I will get to in due course.

I will be out of town from tomorrow until April 2nd, and cannot
promise to do anything about the above issues until Monday the 5th,
nor can I promise to address other issues caused by this patch until
then.  I will, however, be reading my email intermittently.

Bootstrapped i686-linux (all languages except Ada and treelang);
applied to mainline.

zw

	PR 12267, 12391, 12560, 13129, 14114, 14113

	* c-tree.h: Forward declare struct c_binding.  Declare
	c_override_bindings_to_false.  Update prototypes.
	(struct lang_identifier): Update comments.  Change fields to be
	struct c_binding *.
	(IDENTIFIER_SYMBOL_VALUE, IDENTIFIER_TAG_VALUE)
	(IDENTIFIER_LABEL_VALUE, C_DECL_INVISIBLE)
	(KEEP_NO, KEEP_YES, KEEP_MAYBE): Delete.
	(C_DECL_IN_EXTERNAL_SCOPE, C_DECL_DECLARED_BUILTIN): New.
	* c-common.h: Update prototypes.
	* c-decl.c (struct c_scope): Update commentary.  Remove names,
	names_last, parms, parms_last, tags, and shadowed fields.  Add
	bindings and depth fields.
	(scope_freelist): Move to more appropriate location.
	(c_print_identifier): Update for changes to struct lang_identifier.
	(objc_mark_locals_volatile): Update for new bindings structures.
	(global_bindings_p): Honor c_override_global_bindings_to_false.
	(pushlevel): Rename to push_scope; take no arguments; use the
	scope_freelist; initialize scope->depth and check for overflow.
	(poplevel): Rename to pop_scope; totally rewritten for new bindings
	structures.
	(diagnose_mismatched_decls): Use C_DECL_DECLARED_BUILTIN, not
	C_DECL_INVISIBLE, for certain decisions.  Adjust some diagnostics.
	Improve some commentary.  Adjust handling of forward parm decls.
	(merge_decls): Set C_DECL_DECLARED_BUILTIN when appropriate.
	Preserve C_DECL_IN_EXTERNAL_SCOPE.
	(warn_if_shadowing): Correct indentation.  Improve diagnostics.
	(pushdecl): Remove unnecessary assertion.  Short-circuit anonymous
	decls.  Rewrite for new bindings structures.  Improve commentary.
	Eliminate the copy_node call.
	(implicit_decl_warning): Use the "diag" idiom (as seen in
	locate_old_decl) to reduce code duplication; call locate_old_decl
	if appropriate.  Relocate to remove need for forward declaration.
	(implicitly_declare): Adjust for new bindings structures.  Kludge
	around Objective-C not-really-builtin functions.
	(undeclared_variable): Improve diagnostics.  If current_function_decl
	is nonnull but current_function_scope is null, use current_scope.
	Use bind.
	(lookup_tag): Adjust for new bindings structures.  Kludge around
	Objective-C's tag declarations that wind up in the external scope.
	(lookup_name): Adjust for new bindings structures.  Kludge around
	c-common.c's pseudo-typedefs that wind up in the external scope.
	(lookup_name_current_level): Rename lookup_name_in_scope; take a
	second argument indicating the scope to examine; rewrite for
	new bindings structures.
	(c_init_decl_processing): Adjust for renamed functions.  Do not
	initialize current_file_decl, first_builtin_decl, last_builtin_decl.
	First scope pushed is the external scope, not the global scope.
	(builtin_function): Use bind, not pushdecl.  Adjust other bits
	for new data structures.  Keep track of builtins that should be
	made visible automatically.
	(start_decl): Adjust diagnostics.  Remove unnecessary call to
	expand_decl.
	(grokparms): Return 0 if arg_types is error_mark_node.
	(get_parm_info): Rename "void_at_end" argument to "ellipsis", with
	reversed sense.  Rewrite for new bindings structures.  Do not
	leave any decls in the scope, to prevent pop_scope from doing
	contradictory things with them.
	(finish_struct, finish_enum): Remove redundant diagnostics.
	(build_enumerator): Don't cascade diagnostics for error_mark_node.
	Mark location where -pedantic changes the meaning of the program.
	(store_parm_decls_newstyle, store_parm_decls_oldstyle): Load the
	parameter decls into the function's scope structure using bind.
	Warn here about function definitions in the wrong style.
	Adjust diagnostics.
	(store_parm_decls): Correct the determination of whether a
	function was defined with a prototype.
	(c_write_global_declarations): Operate on all file decls and on
	the external scope.  Split body of the loop to...
	(c_write_global_declarations_1): ... this new function, to avoid
	code duplication.
	(truly_local_externals, first_builtin_decl, last_builtin_decl)
	(make_scope, pop_scope, in_parm_level_p, set_block)
	(any_external_decl, record_external_decl, bind_label, getdecls)
	(link_hash_hash, link_hash_eq, merge_translation_unit_decls)
	(c_reset_state): Delete.
	(visible_builtins, c_override_global_bindings_to_false)
	(c_binding, I_SYMBOL_BINDING, I_SYMBOL_DECL, I_TAG_BINDING)
	(I_TAG_DECL, I_LABEL_BINDING, I_LABEL_DECL, file_scope)
	(external_scope, binding_freelist, bind, free_binding_and_advance)
	(push_file_scope, pop_file_scope): New.
	(pushtag, pushdecl_top_level, lookup_label, declare_label)
	(define_label, c_make_fname_decl, finish_decl)
	(mark_forward_parm_decls, build_compound_literal)
	(grokdeclarator, start_function, check_for_loop_decls)
	(identifier_global_value, record_builtin_type): Minor adjustments
	for new bindings structures.  Improve diagnostics and commentary.
	* c-objc-common.c (start_cdtor, finish_cdtor): Adjust calls to
	pushlevel/poplevel respectively.
	(c_objc_common_finish_file): Don't call merge_translation_unit_decls.
	* c-opts.c (c_common_parse_file): Remove spurious ATTRIBUTE_UNUSED.
	Warn about YYDEBUG not being defined only if -dy.  Remove no-longer-
	correct loop over multiple translation units; call fatal_error if
	requested to compile more than one file at once.  (This disables
	IMA temporarily - an up-front error being preferable to a crash.)
	* c-parse.in (pushlevel, poplevel rules): Rename push_scope, pop_scope.
	(all actions): Adjust calls to pushlevel/poplevel.
	(parsing_iso_function_signature): Delete.
	(extdef_1): Fold into extdef.
	(old_style_parm_decls_1): Fold into old_style_parm_decls.  Don't
	warn here about function definitions in the wrong style.
	(after_tyle_declarator, parm_declarator_starttypename)
	(parm_declarator_nostarttypename, notype_declarator): Remove
	commented-out productions.
	(parmlist_1, parmlist_2): Use make_node, not tree_cons, to create
	an empty TREE_LIST node.  Adjust calls to get_parm_info.
	(parmlist_2 : ELLIPSIS): Tag the arg-info block with error_mark_node
	to suppress -Wold-style-definition after this error.
	(c_parse_file): Don't clear the binding stack or call
	finish_fname_decls here.  Correct comment.
	* c-typeck.c (same_translation_unit_p): Export.
	(common_type): Use c_override_global_bindings_to_false, not
	pushlevel/poplevel/declare_parm_level.
	* c-lang.c: Override LANG_HOOKS_CLEAR_BINDING_STACK,
	LANG_HOOKS_PUSHLEVEL, LANG_HOOKS_POPLEVEL, LANG_HOOKS_SET_BLOCK,
	and LANG_HOOKS_GETDECLS with do-nothing stubs.
	* objc/objc-lang.c: Likewise.
	* objc/objc-act.c: Adjust all calls to pushlevel, poplevel,
	get_parm_info.
	(OBJC_VOID_AT_END): Delete; replace all uses
	with void_list_node.
	(generate_forward_declaration_to_string_table): Delete.
	* objc/objc-act.h (OCTI_STRG_DECL, UOBJC_STRINGS_decl): Delete.

	* coverage.c (create_coverage): Don't pushdecl anything.
	* langhooks.c (lhd_clear_binding_stack): Call
	lang_hooks.decls.poplevel, not poplevel.
	* tree.c (list_length): If ENABLE_TREE_CHECKING, abort on a
	circular list rather than going into an infinite loop.

cp:
	* cp-lang.c (c_reset_state): Delete.
	(push_file_scope, pop_file_scope): New stubs.
	* parser.c (c_parse_file): Call sorry() here if called more than once.

testsuite:
	* gcc.dg/Wold-style-definition-1.c, gcc.dg/builtins-30.c
	* gcc.dg/unused-4.c, gcc.dg/noncompile/label-1.c
	* gcc.dg/noncompile/label-lineno-1.c, objc.dg/naming-1.m:
	Adjust error regexps.
	* gcc.dg/Wshadow-2.c, gcc.dg/noncompile/incomplete-3.c
	* gcc.dg/noncompile/undeclared-1.c: New test cases.
	* gcc.dg/decl-5.c, gcc.dg/redecl-1.c: Remove XFAIL.
	* gcc.dg/local1.c: Add explanatory comment.

===================================================================
Index: c-common.h
--- c-common.h	17 Feb 2004 18:32:32 -0000	1.222
+++ c-common.h	23 Mar 2004 22:06:33 -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	22 Mar 2004 15:27:57 -0000	1.488
+++ c-decl.c	23 Mar 2004 22:06:34 -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))
@@ -5228,10 +5326,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);

@@ -5360,16 +5455,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);
 	}
     }

@@ -5386,6 +5484,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);
     }

@@ -5472,13 +5572,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)))
@@ -5543,7 +5643,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'.  */
@@ -5609,7 +5709,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);
@@ -5648,75 +5748,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
@@ -5725,19 +5806,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))
@@ -5749,17 +5832,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;
 	    }
@@ -5767,7 +5851,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);
@@ -5782,9 +5866,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;
@@ -5794,17 +5878,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.
@@ -5826,7 +5914,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))
@@ -5836,7 +5923,6 @@ store_parm_decls_oldstyle (tree fndecl,
 	    last = TREE_PURPOSE (parm);
 	    DECL_WEAK (last) = 0;
 	  }
-      current_scope->parms_last = last;
       TREE_CHAIN (last) = 0;
     }

@@ -5886,7 +5972,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);
@@ -5894,7 +5980,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);
 		}
@@ -5956,26 +6042,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);
@@ -6023,17 +6109,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
@@ -6177,7 +6263,7 @@ c_expand_body (tree fndecl)
 void
 check_for_loop_decls (void)
 {
-  tree t;
+  struct c_binding *b;

   if (!flag_isoc99)
     {
@@ -6201,35 +6287,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);
+	}
     }
 }
 
@@ -6382,16 +6471,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;
 }

@@ -6402,14 +6487,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).  */
@@ -6456,178 +6538,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	23 Mar 2004 22:06:34 -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	20 Mar 2004 04:52:51 -0000	1.42
+++ c-objc-common.c	23 Mar 2004 22:06:34 -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	23 Mar 2004 22:06:34 -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	23 Mar 2004 22:06:35 -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	23 Mar 2004 22:06:35 -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	23 Mar 2004 20:43:38 -0000	1.293
+++ c-typeck.c	23 Mar 2004 22:06:35 -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)
===================================================================
Index: coverage.c
--- coverage.c	20 Mar 2004 16:50:35 -0000	1.32
+++ coverage.c	23 Mar 2004 22:06:36 -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	23 Mar 2004 22:06:36 -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	23 Mar 2004 20:43:39 -0000	1.361
+++ tree.c	23 Mar 2004 22:06:37 -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	23 Mar 2004 22:06:37 -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	23 Mar 2004 22:06:40 -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	23 Mar 2004 22:06:42 -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	23 Mar 2004 22:06:42 -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	23 Mar 2004 22:06:42 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	20 Mar 2004 10:19:11 -0000	1.3
+++ testsuite/gcc.dg/builtins-30.c	23 Mar 2004 22:06:43 -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 cos ()
-{  /* { dg-warning "shadowing built-in" } */
+{  /* { dg-warning "shadows a built-in" } */
   return strtod ("nan", 0);
 }

 /* the right number, but the wrong type, arguments... */
 double sin (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 cosl (foo, bar)
-     long double 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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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	23 Mar 2004 22:06:43 -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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]