]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR 12267, 12391, 12560, 13129, 14114, 14113
authorZack Weinberg <zack@gcc.gnu.org>
Tue, 23 Mar 2004 23:47:53 +0000 (23:47 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Tue, 23 Mar 2004 23:47:53 +0000 (23:47 +0000)
* 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.

From-SVN: r79883

31 files changed:
gcc/ChangeLog
gcc/c-common.h
gcc/c-decl.c
gcc/c-lang.c
gcc/c-objc-common.c
gcc/c-opts.c
gcc/c-parse.in
gcc/c-tree.h
gcc/c-typeck.c
gcc/coverage.c
gcc/cp/ChangeLog
gcc/cp/cp-lang.c
gcc/cp/parser.c
gcc/langhooks.c
gcc/objc/objc-act.c
gcc/objc/objc-act.h
gcc/objc/objc-lang.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wold-style-definition-1.c
gcc/testsuite/gcc.dg/Wshadow-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-30.c
gcc/testsuite/gcc.dg/decl-5.c
gcc/testsuite/gcc.dg/local1.c
gcc/testsuite/gcc.dg/noncompile/incomplete-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/noncompile/label-1.c
gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c
gcc/testsuite/gcc.dg/noncompile/undeclared-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/redecl-1.c
gcc/testsuite/gcc.dg/unused-4.c
gcc/testsuite/objc.dg/naming-1.m
gcc/tree.c

index 9b4f247b89f1e0e2b852e3e80509b325184fa861..b885df98dc421186ec75e059158bf85e58fba6bb 100644 (file)
@@ -1,8 +1,141 @@
+2004-03-23  Zack Weinberg  <zack@codesourcery.com>
+
+       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.
+
 2004-03-23  Olivier Hainque  <hainque@act-europe.fr>
 
-        * optabs.c (expand_binop): When synthesizing double word rotates
-        from single word shifts, use a new register target if the provided
-        target is not a REG already.
+       * optabs.c (expand_binop): When synthesizing double word rotates
+       from single word shifts, use a new register target if the provided
+       target is not a REG already.
 
 2004-03-23  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * frontends.texi: Add missing line.
 
 2004-03-21  Zack Weinberg  <zack@codesourcery.com>
-            Chris Devers  <cdevers@pobox.com>
-            Joseph S. Myers  <jsm@polyomino.org.uk>
+           Chris Devers  <cdevers@pobox.com>
+           Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * doc/frontends.texi: Rewrite.
        * doc/gcc.texi: Update last modification date.
        (ir_sr70_icmp): Delete.
 
 2004-03-18  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
-       
+
        * tree.h (TREE_CHECK2, TREE_CHECK3, TREE_CHECK5): New macros.
        (tree_check2_failed, tree_check3_failed, tree_check5_failed): New decl.
        (FUNC_OR_METHOD_CHECK, SET_ARRAY_OR_VECTOR_CHECK): New macros.
 
 2004-03-17  Fariborz Jahanian <fjahanian@apple.com>
 
-        * config/rs6000/rs6000.c (rs6000_stack_info): correct reg_size
-        for mixed mode.
-        (rs6000_emit_prologue): Ditto.
-        (rs6000_emit_epilogue): Ditto.
-        * config/rs6000/rs6000.h: Definition of DWARF_CIE_DATA_ALIGNMENT
-        macro for mixed mode.
+       * config/rs6000/rs6000.c (rs6000_stack_info): correct reg_size
+       for mixed mode.
+       (rs6000_emit_prologue): Ditto.
+       (rs6000_emit_epilogue): Ditto.
+       * config/rs6000/rs6000.h: Definition of DWARF_CIE_DATA_ALIGNMENT
+       macro for mixed mode.
 
 2004-03-18  Jan Hubicka  <jh@suse.cz>
 
index 00d5d5c18d451cc62d7c185215b97a0e7cfc7464..4326a59480f35e2c33c4a2911590e4318c664949 100644 (file)
@@ -329,6 +329,8 @@ extern void (*lang_expand_function_end) (void);
    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 46863ed531affd7305f06e35975eae4391811986..e74347997c5780bfbf0d3f552f49a8d29836f4a7 100644 (file)
@@ -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;
+
 \f
-/* Each c_scope structure describes the complete contents of one scope.
-   Three scopes are distinguished specially: the innermost or current
-   scope, the innermost function scope, and the outermost or file scope.
+/* Each c_binding structure describes one binding of an identifier to
+   a decl.  All the decls in a scope - irrespective of namespace - are
+   chained together by the ->prev field, which (as the name implies)
+   runs in reverse order.  All the decls in a given namespace bound to
+   a given identifier are chained by the ->shadowed field, which runs
+   from inner to outer scopes.  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.
 
-   The order of the names, parms, and blocks lists matters, and they
-   are frequently appended to.  To avoid having to walk all the way to
-   the end of the list on each insertion, or reverse the lists later,
-   we maintain a pointer to the last list entry for each of the lists.
+     All declarations that refer to the same object or function shall
+     have compatible type; otherwise, the behavior is undefined.
+
+   Initially only the built-in declarations, which describe compiler
+   intrinsic functions plus a subset of the standard library, are in
+   this scope.
+
+   The order of the blocks list matters, and it is frequently appended
+   to.  To avoid having to walk all the way to the end of the list on
+   each insertion, or reverse the list later, we maintain a pointer to
+   the last list entry.  (FIXME: It should be feasible to use a reversed
+   list here.)
+
+   The bindings list is strictly in reverse order of declarations;
+   pop_scope relies on this.  */
 
-   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;
+
+/* A chain of c_binding structures awaiting reuse.  */
 
-static GTY(()) struct c_scope *global_scope;
+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_scope;
 
 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 *);
 \f
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
@@ -319,9 +353,9 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 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 node, int indent)
               (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;
+}
+
 \f
 /* 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)
     }
 }
 \f
-/* Reuse or create a struct for this scope.  */
-
-static struct c_scope *
-make_scope (void)
-{
-  struct c_scope *result;
-  if (scope_freelist)
-    {
-      result = scope_freelist;
-      scope_freelist = result->outer;
-    }
-  else
-    result = ggc_alloc_cleared (sizeof (struct c_scope));
-
-  return result;
-}
-
-/* Remove the topmost scope from the stack and add it to the
-   free list, updating current_function_scope if necessary.  */
-
-static void
-pop_scope (void)
-{
-  struct c_scope *scope = current_scope;
-
-  current_scope = scope->outer;
-  if (scope->function_body)
-    current_function_scope = scope->outer_function;
-
-  memset (scope, 0, sizeof (struct c_scope));
-  scope->outer = scope_freelist;
-  scope_freelist = scope;
-}
-
 /* The Objective-C front-end often needs to determine the current scope.  */
 
 void *
@@ -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;
+  tree block, context, p;
+  struct c_binding *b;
 
-  if (keep == KEEP_MAYBE)
-    keep = (scope->names || scope->tags);
-
-  keep |= scope->keep;
-  keep |= scope->function_body;
+  bool functionbody = scope->function_body;
+  bool keep = functionbody || scope->keep || scope->bindings;
 
   /* If appropriate, create a BLOCK to record the decls for the life
      of this function.  */
@@ -530,28 +594,44 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
   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_UNUSED, int functionbody)
              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_UNUSED, int functionbody)
     }
 
   /* 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)
-{
-}
 \f
 /* 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));
 }
 \f
@@ -916,8 +1032,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
      unless OLDDECL is a builtin.  OLDDECL will be discarded in any case.  */
   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
-      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, tree olddecl,
        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, tree olddecl,
   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, tree olddecl,
         can't validate the argument list) the built-in definition is
         overridden, but optionally warn this was a bad choice of name.  */
       if (DECL_BUILT_IN (olddecl)
-         && 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, tree olddecl,
     }
   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, tree newtype, tree oldtype)
   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, tree newtype, tree oldtype)
 
       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, tree newtype, tree oldtype)
        }
     }
 
+  /* 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 olddecl)
 }
   
 \f
-/* Return any external DECL associated with ID, whether or not it is
-   currently in scope.  */
-
-static tree
-any_external_decl (tree id)
-{
-  tree decl = IDENTIFIER_SYMBOL_VALUE (id);
-  tree t;
-
-  if (decl == 0 || TREE_CODE (decl) == ERROR_MARK)
-    return 0;
-  else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl))
-    return decl;
-
-  t = purpose_member (id, truly_local_externals);
-  if (t)
-    return TREE_VALUE (t);
-
-  return 0;
-}
-
-/* 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;
+
+       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);
 
-  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))
+      while (b && b->contour != external_scope)
+       b = b->shadowed;
+
+      /* 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))
        {
-         /* 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;
+         bind (name, b->decl, scope);
+         return b->decl;
        }
-      if (DECL_EXTERNAL (x) || scope == global_scope)
+      else if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
        {
-         /* Find and check against a previous, not-in-scope, external
-            decl for this identifier.  (C99 6.2.7p2: All declarations
-            that refer to the same object or function shall have
-            compatible type; otherwise, the behavior is undefined.)  */
-         tree ext = any_external_decl (name);
-         if (ext)
-           {
-             if (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);
+         C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
+         bind (name, x, external_scope);
        }
+    }
 
-      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);
-       }
+  warn_if_shadowing (x);
 
-      /* 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);
-
-         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));
-       }
-    }
+ skip_external_and_shadow_checks:
+  if (TREE_CODE (x) == TYPE_DECL)
+    clone_underlying_type (x);
 
-  if (TREE_CODE (x) == PARM_DECL)
-    SCOPE_LIST_APPEND (scope, parms, x);
-  else
-    SCOPE_LIST_APPEND (scope, names, 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;
 }
 \f
+static void
+implicit_decl_warning (tree id, tree olddecl)
+{
+  void (*diag) (const char *, ...);
+  switch (mesg_implicit_function_declaration)
+    {
+    case 0: return;
+    case 1: diag = warning; break;
+    case 2: diag = error;   break;
+    default: abort ();
+    }
+
+  diag (N_("implicit declaration of function '%E'"), id);
+  if (olddecl)
+    locate_old_decl (olddecl, diag);
+}
+
 /* Generate an implicit declaration for identifier FUNCTIONID as a
    function of type int ().  */
 
 tree
 implicitly_declare (tree functionid)
 {
-  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))
+      /* 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_decl_warning (DECL_NAME (decl));
-         if (! DECL_FILE_SCOPE_P (decl))
-           warning ("%Jprevious declaration of '%D'", decl, decl);
-         C_DECL_IMPLICIT (decl) = 1;
+         /* 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;
        }
-      /* If this function is global, then it must already be in the
-        global scope, so there's no need to push it again.  */
-      if (current_scope == global_scope)
-       return decl;
-      /* If this is a local declaration, make a copy; we can't have
-        the same DECL listed in two different scopes.  */
-      return pushdecl (copy_node (decl));
     }
 
   /* Not seen before.  */
@@ -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);
 }
 \f
 /* Subroutine of lookup_label, declare_label, define_label: construct a
@@ -1923,20 +2036,6 @@ make_label (tree name, location_t location)
   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 name)
              && 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 name)
       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))
@@ -2064,16 +2157,6 @@ define_label (location_t location, tree name)
   DECL_INITIAL (label) = error_mark_node;
   return label;
 }
-\f
-/* Return the list of declarations of the current scope.
-   This hook is optional and not implemented for C.  */
-
-tree
-getdecls (void)
-{
-  return 0;
-}
-
 \f
 /* Given NAME, an IDENTIFIER_NODE,
    return the structure (or union or enum) definition for that name.
@@ -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 (current_scope == global_scope
-         || purpose_member (name, current_scope->tags))
+  if (thislevel_only || TREE_CODE (b->decl) != code)
+    {
+      /* For our purposes, a tag in the external scope is the same as
+        a tag in the file scope.  (Primarily relevant to Objective-C
+        and its builtin structure tags, which get pushed before the
+        file scope is created.)  */ 
+      if (b->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 name, int thislevel_only)
       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;
 }
 \f
@@ -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 type, int function_code,
                  enum built_in_class class, const char *library_name,
                  tree attrs)
 {
-  tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
-  DECL_EXTERNAL (decl) = 1;
+  tree 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 declspecs, int initialized, tree attributes)
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
-       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 declspecs, int initialized, tree attributes)
          }
        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 declspecs, int initialized, tree attributes)
   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 declspecs, int initialized, tree attributes)
      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 asmspec_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 asmspec_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 asmspec_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;
 }
 \f
 static GTY(()) int compound_literal_number;
@@ -2996,7 +3049,7 @@ build_compound_literal (tree type, tree init)
   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 declspecs,
   /* If this looks like a function definition, make it one,
      even if it occurs where parms are expected.
      Then store_parm_decls will reject it and not use it as a parm.  */
-  if (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 declspecs,
       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 declspecs,
                    | (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 declspecs,
     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 declspecs,
        }
       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 declspecs,
   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 declspecs,
           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 declspecs,
        /* 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 declspecs,
        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 declspecs,
           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_flag)
       && !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_flag)
     }
 }
 
-/* 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;
 }
 \f
 /* 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, tree attributes)
 
   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 attributes)
   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 declarator, tree attributes)
     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 declarator, tree attributes)
 #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 declarator, tree attributes)
 
   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 declarator, tree attributes)
 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, tree arg_info)
 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, tree arg_info)
          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, tree arg_info)
             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, tree arg_info)
          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, tree arg_info)
   /* 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, tree arg_info)
     {
       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, tree arg_info)
            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, tree arg_info)
 
                  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, tree arg_info)
                }
              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));
-
-          if (code == RECORD_TYPE)
-            error ("'struct %s' declared in 'for' loop initial declaration",
-                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-          else if (code == UNION_TYPE)
-            error ("'union %s' declared in 'for' loop initial declaration",
-                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-          else
-            error ("'enum %s' declared in 'for' loop initial declaration",
-                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-        }
-    }
+      tree id = b->id;
+      tree decl = b->decl;
 
-  for (t = current_scope->names; t; t = TREE_CHAIN (t))
-    {
-      if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
-       error ("%Jdeclaration of non-variable '%D' in 'for' loop "
-               "initial declaration", t, t);
-      else if (TREE_STATIC (t))
-       error ("%Jdeclaration of static variable '%D' in 'for' loop "
-              "initial declaration", t, t);
-      else if (DECL_EXTERNAL (t))
-       error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
-               "initial declaration", t, t);
+      if (!id)
+       continue;
+
+      switch (TREE_CODE (decl))
+       {
+       case VAR_DECL:
+         if (TREE_STATIC (decl))
+           error ("%Jdeclaration of static variable '%D' in 'for' loop "
+                  "initial declaration", decl, decl);
+         else if (DECL_EXTERNAL (decl))
+           error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
+                  "initial declaration", decl, decl);
+         break;
+
+       case RECORD_TYPE:
+         error ("'struct %E' declared in 'for' loop initial declaration", id);
+         break;
+       case UNION_TYPE:
+         error ("'union %E' declared in 'for' loop initial declaration", id);
+         break;
+       case ENUMERAL_TYPE:
+         error ("'enum %E' declared in 'for' loop initial declaration", id);
+         break;
+       default:
+         error ("%Jdeclaration of non-variable '%D' in 'for' loop "
+                "initial declaration", decl, decl);
+       }
     }
 }
 \f
@@ -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);
+  tree t;
 
-      /* Clean up.  */
-      free (vec);
-    }
-}
+  /* We don't want to do this if generating a PCH.  */
+  if (pch_file)
+    return;
 
-/* Reset the parser's state in preparation for a new file.  */
+  /* 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)));
 
-void
-c_reset_state (void)
-{
-  tree link;
-  tree file_scope_decl;
-
-  /* Pop the global scope.  */
-  if (current_scope != global_scope)
-      current_scope = global_scope;
-  file_scope_decl = current_file_decl;
-  DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
-  BLOCK_SUPERCONTEXT (DECL_INITIAL (file_scope_decl)) = file_scope_decl;
-  truly_local_externals = NULL_TREE;
-
-  /* Start a new global binding level.  */
-  pushlevel (0);
-  global_scope = current_scope;
-  current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
-  TREE_CHAIN (current_file_decl) = file_scope_decl;
-
-  /* Reintroduce the builtin declarations.  */
-  for (link = first_builtin_decl;
-       link != TREE_CHAIN (last_builtin_decl);
-       link = TREE_CHAIN (link))
-    pushdecl (copy_node (link));
+  /* 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 0f8bf4ea49a3d0ad718093dbb83c9bb0f1adbc9f..391e8bddfaf76e21a461659fa0e339c0ff3a7f3d 100644 (file)
@@ -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 575407102fbacbfa3ec470eefdb2d4fc21a896d5..e736110e6be882b22da08c484f8b5662749bc023 100644 (file)
@@ -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;
 
@@ -237,10 +237,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 4eecba91de5ce09b77d230eecc99998a40b1e3e1..ac2fe9761566e629e3d1d9c68ed17b076661cf97 100644 (file)
@@ -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();
-
-         /* 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 ();
+  if (num_in_fnames > 1)
+    fatal_error ("sorry, inter-module analysis temporarily out of commission");
 
-      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 e628aa5fe90d0488824b9a35154f1191a247ee8d..91a42d91814b9d72f0afef67a4e363621600e434 100644 (file)
@@ -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 yyl)
     }
 }
 \f
-/* 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 6da67df0f2f579120964f7d97be86665409608dc..bd53dbc56e9e3a6ff0d2578f7f89bf454fda6a05 100644 (file)
@@ -24,22 +24,21 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #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.  */
 
-/* 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.
+struct c_binding;
 
-   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, tree);
 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 (struct function *);
 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);
@@ -313,6 +287,11 @@ extern int current_function_returns_abnormally;
 
 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);
 extern void *get_current_scope (void);
index 189ec0f580d8902e8d93fb234fe892caf92a1a5a..2e57ba7ccebbba2f64438e44504bdd0cbadee651 100644 (file)
@@ -51,7 +51,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 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, int reflexive)
 \f
 /* 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 88d677c78b84d2b8acb55725bbb4573bbb707e48..ccc8339cb5f41b3bc1b1ef6150eb19aa4f05b9f5 100644 (file)
@@ -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 0f900f53f84282e02b0bbcdacacce1e61ba9c3a0..008aa4adf74358a9683f485f0fba7849ac85169b 100644 (file)
@@ -1,3 +1,10 @@
+2004-03-23  Zack Weinberg  <zack@codesourcery.com>
+
+       PR 12267, 12391, 12560, 13129, 14114, 14113
+       * 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.
+
 2004-03-23  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * typeck.c (build_c_cast): Only look at TREE_CONSTANT_OVERFLOW
        (dump_simple_decl): Likewise.
        (dump_function_decl): Likewise.
        (cv_to_string): Likewise.
-       (dump_type_prefix): Likewise.  Adjust return void.  
+       (dump_type_prefix): Likewise.  Adjust return void.
        * cxx-pretty-print.c (pp_cxx_cv_qualifier_seq): Move to
        cxx_pretty_print.h.
        (pp_cxx_template_keyword_if_needed): Document.
        (pp_cxx_qualified_id): Document case FUNCTION_DECL.  Tidy.
        (pp_cxx_expression): Handle NON_DEPENDENT_EXPR and
-       MUST_NOT_THROW_EXPR.  
+       MUST_NOT_THROW_EXPR.
 
 2004-03-21  Mark Mitchell  <mark@codesourcery.com>
 
@@ -69,7 +76,7 @@
 
        * typeck.c (lookup_destructor): Allow the use of destructors from
        base classes.
-       
+
 2004-03-19  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * cxx-pretty-print.c (pp_cxx_unqualified_id): Use
        * pt.c (do_type_instantiation): On systems where weak symbols
        don't go in a static archive's TOC, explicit instantiation of a
        class must imply *explicit* instantiation of its memeber.
-       
+
 2004-03-11  Kazu Hirata  <kazu@cs.umass.edu>
 
        * call.c, cp-tree.h, pt.c: Fix comment typos.
 
        PR c++/14510
        * decl.c (xref_tag): Disregard non-type declarations when
-       looking up a tagged type. 
+       looking up a tagged type.
 
 2004-03-09  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR debug/14079
        * name-lookup.c (add_decl_to_level): Add extern variables, as well
        as static, to static_decls array.
-       
+
 2004-03-05  Jason Merrill  <jason@redhat.com>
 
        * tree.c (list_hash_pieces): s/TYPE_HASH/TREE_HASH/.
        * parser.c (cp_parser_late_parsing_default_args): Check that there
        are no extra tokens after the end of the default-argument
        expression.
-       
+
 2004-03-01  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/14324
        PR c++/14337
        * pt.c (tsubst_qualified_id): Handle dependent qualifying scopes.
        (tsubst_expr): Do not call tsubst_copy, even when
-       processing_template_decl.       
+       processing_template_decl.
 
 2004-03-01  Jeff Law  <law@redhat.com>
 
 2004-02-23  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
        PR c++/14143
-       * name-lookup.c (arg_assoc_class): Don't look into template 
+       * name-lookup.c (arg_assoc_class): Don't look into template
        arguments if it is not a primary template.
 
 2004-02-20  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 2004-02-19  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
        PR c++/14181
-       * parser.c (cp_parser_new_expression): Parse an ill-formed 
+       * parser.c (cp_parser_new_expression): Parse an ill-formed
        direct-new-declarator after a parenthesized type-id to emit good
        diagnostic.
 
        whether or not a friend template is a definition.
        (tsubst_decl): Clear DECL_INITIAL for new FUNCTION_DECLs.
        * tree.c (build_zc_wrapper): Remove.
-       
+
 2004-02-12  Zack Weinberg  <zack@codesourcery.com>
 
        * cp-lang.c: Don't define LANG_HOOKS_BUILTIN_TYPE_DECLS.
index 176a145f3ee5c6c503d6200363ddb5f4d1442fc2..b0b927b850e9b7e4f55025249e0aaa1df6965b8d 100644 (file)
@@ -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
@@ -409,3 +402,14 @@ cxx_initialize_diagnostics (diagnostic_context *context)
   /* 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 e964f48753f86e2c96389db3d4491e596cade44e..e58fda4cc4fa73d35073fee566872b5e6410f1ea 100644 (file)
@@ -15347,7 +15347,6 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
 }
 
 \f
-
 /* 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 4e9c3e983becbb20a3b2d96f98aa590ffb671f2e..3e15a359333c62d7f3732b65e98fb80676fa153d 100644 (file)
@@ -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 1d76cc4d98959392f8019c4eed4f4116fbf59bdd..89abaf4c19856c285c54f817d3611fdec324fe6b 100644 (file)
@@ -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 context, int superflag)
 
   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 context, int superflag)
       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 ();
 }
@@ -8801,8 +8781,6 @@ finish_objc (void)
       objc_implementation_context = NULL_TREE;
     }
 
-  generate_forward_declaration_to_string_table ();
-
   /* Process the static instances here because initialization of objc_symtab
      depends on them.  */
   if (objc_static_instances)
index abbf65627311ed50554252ae5d71bc727857939a..db7eeca514143d85c65ee670889719254ffa03ec 100644 (file)
@@ -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[OCTI_MAX];
 #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 72c772c40b49df7afa74a35975fe69ce4d1d7945..877867ac39ddaf40930fcce16266477a9e53c649 100644 (file)
@@ -55,6 +55,8 @@ enum c_language_kind c_language = clk_objc;
 #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_objc;
 #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 c111369c3e378ed4d8b7061eab894cbe2e2273ca..de52f548e686e747d320833d102f47bbadab7286 100644 (file)
@@ -1,3 +1,15 @@
+2004-03-23  Zack Weinberg  <zack@codesourcery.com>
+
+       PR 12267, 12391, 12560, 13129, 14114, 14113
+       * 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.
+
 2004-03-23  Roger Sayle  <roger@eyesopen.com>
 
        PR optimization/14669
        * g++.dg/template/spec13.C: New test.
 
        * g++.dg/lookup/using11.C: New test.
-       
+
        * g++.dg/lookup/koenig3.C: New test.
 
        * g++.dg/template/operator2.C: New test.
-       
+
        * g++.dg/expr/dtor3.C: New test.
        * g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error
        marker.
index d4fb8bd8da164f899e9ad73c25e225007da2676c..aa016338b5e8472f9d2caf6f3e3bfd1b9c3dc152 100644 (file)
@@ -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) {}
 
diff --git a/gcc/testsuite/gcc.dg/Wshadow-2.c b/gcc/testsuite/gcc.dg/Wshadow-2.c
new file mode 100644 (file)
index 0000000..b0c0512
--- /dev/null
@@ -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 9ed0be53c40190e5259b531393a1248f43f627d5..7c700c514dcecb73c5cc89fc57015119ca236b85 100644 (file)
@@ -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 d7c36a4a1bc33ce507baa09ac9bf88f8e218ba31..9b7782464598bb47f86f24223ea1b87c965271d5 100644 (file)
@@ -10,7 +10,7 @@ void a()
 {
   void c();
   c();
-} /* { dg-bogus "error" "PR c/14114" { xfail *-*-* } } */
+}
 
 void b()
 {
index 700070ae1d6055ff23556a9e0677645350f50349..9d6fdb167523814c53431c1378f5352d2ed28983 100644 (file)
@@ -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;
diff --git a/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c b/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
new file mode 100644 (file)
index 0000000..735ef46
--- /dev/null
@@ -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 c646b48fb8d4f2d0b9fef6db0ce665aad9eb0797..e9bde7b3b7b6ffdd9ac8830323b9cc86ebe91628 100644 (file)
@@ -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 0c5599434f8bd51cfb7e6aada26aa69fd940431d..76d4d96edaf9ee7a947bf2752cc715d93fca3869 100644 (file)
@@ -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++;
 
diff --git a/gcc/testsuite/gcc.dg/noncompile/undeclared-1.c b/gcc/testsuite/gcc.dg/noncompile/undeclared-1.c
new file mode 100644 (file)
index 0000000..5bb7c2a
--- /dev/null
@@ -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 09b70d7b6cdc0afc18d5a0c2304b2f3e97eb4722..14877667e91d7fc9763e365c287c10a5e37b7a78 100644 (file)
@@ -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 99e845f45a3c1bb1d2ff434edfe9b97f447e331c..4b33a7fbb698f3e3236c29df5a9a42c48b24c3c4 100644 (file)
@@ -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 69d98b7be517219558b48ae44de0de9c8c391302..1be7eba664c6df6bfbd81a49621eefb0d932e9b6 100644 (file)
@@ -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 bca58f04c0156929750b48e43527ebe92573e147..eca5f20dd7b48aa6e3d087c3d1d3c388d13e58f2 100644 (file)
@@ -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;
 }