diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-03-23 23:47:53 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-03-23 23:47:53 +0000 |
commit | 393b349a9206e51bea4b0c67c64c8b6e04f43538 (patch) | |
tree | 9fca15bf978e2eb7c57b3483c5dfb6949062ad3d | |
parent | d120ca697af1dc6de33bbfba331c646239a40cfa (diff) | |
download | gcc-393b349a9206e51bea4b0c67c64c8b6e04f43538.tar.gz |
PR 12267, 12391, 12560, 13129, 14114, 14113
* c-tree.h: Forward declare struct c_binding. Declare
c_override_bindings_to_false. Update prototypes.
(struct lang_identifier): Update comments. Change fields to be
struct c_binding *.
(IDENTIFIER_SYMBOL_VALUE, IDENTIFIER_TAG_VALUE)
(IDENTIFIER_LABEL_VALUE, C_DECL_INVISIBLE)
(KEEP_NO, KEEP_YES, KEEP_MAYBE): Delete.
(C_DECL_IN_EXTERNAL_SCOPE, C_DECL_DECLARED_BUILTIN): New.
* c-common.h: Update prototypes.
* c-decl.c (struct c_scope): Update commentary. Remove names,
names_last, parms, parms_last, tags, and shadowed fields. Add
bindings and depth fields.
(scope_freelist): Move to more appropriate location.
(c_print_identifier): Update for changes to struct lang_identifier.
(objc_mark_locals_volatile): Update for new bindings structures.
(global_bindings_p): Honor c_override_global_bindings_to_false.
(pushlevel): Rename to push_scope; take no arguments; use the
scope_freelist; initialize scope->depth and check for overflow.
(poplevel): Rename to pop_scope; totally rewritten for new bindings
structures.
(diagnose_mismatched_decls): Use C_DECL_DECLARED_BUILTIN, not
C_DECL_INVISIBLE, for certain decisions. Adjust some diagnostics.
Improve some commentary. Adjust handling of forward parm decls.
(merge_decls): Set C_DECL_DECLARED_BUILTIN when appropriate.
Preserve C_DECL_IN_EXTERNAL_SCOPE.
(warn_if_shadowing): Correct indentation. Improve diagnostics.
(pushdecl): Remove unnecessary assertion. Short-circuit anonymous
decls. Rewrite for new bindings structures. Improve commentary.
Eliminate the copy_node call.
(implicit_decl_warning): Use the "diag" idiom (as seen in
locate_old_decl) to reduce code duplication; call locate_old_decl
if appropriate. Relocate to remove need for forward declaration.
(implicitly_declare): Adjust for new bindings structures. Kludge
around Objective-C not-really-builtin functions.
(undeclared_variable): Improve diagnostics. If current_function_decl
is nonnull but current_function_scope is null, use current_scope.
Use bind.
(lookup_tag): Adjust for new bindings structures. Kludge around
Objective-C's tag declarations that wind up in the external scope.
(lookup_name): Adjust for new bindings structures. Kludge around
c-common.c's pseudo-typedefs that wind up in the external scope.
(lookup_name_current_level): Rename lookup_name_in_scope; take a
second argument indicating the scope to examine; rewrite for
new bindings structures.
(c_init_decl_processing): Adjust for renamed functions. Do not
initialize current_file_decl, first_builtin_decl, last_builtin_decl.
First scope pushed is the external scope, not the global scope.
(builtin_function): Use bind, not pushdecl. Adjust other bits
for new data structures. Keep track of builtins that should be
made visible automatically.
(start_decl): Adjust diagnostics. Remove unnecessary call to
expand_decl.
(grokparms): Return 0 if arg_types is error_mark_node.
(get_parm_info): Rename "void_at_end" argument to "ellipsis", with
reversed sense. Rewrite for new bindings structures. Do not
leave any decls in the scope, to prevent pop_scope from doing
contradictory things with them.
(finish_struct, finish_enum): Remove redundant diagnostics.
(build_enumerator): Don't cascade diagnostics for error_mark_node.
Mark location where -pedantic changes the meaning of the program.
(store_parm_decls_newstyle, store_parm_decls_oldstyle): Load the
parameter decls into the function's scope structure using bind.
Warn here about function definitions in the wrong style.
Adjust diagnostics.
(store_parm_decls): Correct the determination of whether a
function was defined with a prototype.
(c_write_global_declarations): Operate on all file decls and on
the external scope. Split body of the loop to...
(c_write_global_declarations_1): ... this new function, to avoid
code duplication.
(truly_local_externals, first_builtin_decl, last_builtin_decl)
(make_scope, pop_scope, in_parm_level_p, set_block)
(any_external_decl, record_external_decl, bind_label, getdecls)
(link_hash_hash, link_hash_eq, merge_translation_unit_decls)
(c_reset_state): Delete.
(visible_builtins, c_override_global_bindings_to_false)
(c_binding, I_SYMBOL_BINDING, I_SYMBOL_DECL, I_TAG_BINDING)
(I_TAG_DECL, I_LABEL_BINDING, I_LABEL_DECL, file_scope)
(external_scope, binding_freelist, bind, free_binding_and_advance)
(push_file_scope, pop_file_scope): New.
(pushtag, pushdecl_top_level, lookup_label, declare_label)
(define_label, c_make_fname_decl, finish_decl)
(mark_forward_parm_decls, build_compound_literal)
(grokdeclarator, start_function, check_for_loop_decls)
(identifier_global_value, record_builtin_type): Minor adjustments
for new bindings structures. Improve diagnostics and commentary.
* c-objc-common.c (start_cdtor, finish_cdtor): Adjust calls to
pushlevel/poplevel respectively.
(c_objc_common_finish_file): Don't call merge_translation_unit_decls.
* c-opts.c (c_common_parse_file): Remove spurious ATTRIBUTE_UNUSED.
Warn about YYDEBUG not being defined only if -dy. Remove no-longer-
correct loop over multiple translation units; call fatal_error if
requested to compile more than one file at once. (This disables
IMA temporarily - an up-front error being preferable to a crash.)
* c-parse.in (pushlevel, poplevel rules): Rename push_scope, pop_scope.
(all actions): Adjust calls to pushlevel/poplevel.
(parsing_iso_function_signature): Delete.
(extdef_1): Fold into extdef.
(old_style_parm_decls_1): Fold into old_style_parm_decls. Don't
warn here about function definitions in the wrong style.
(after_tyle_declarator, parm_declarator_starttypename)
(parm_declarator_nostarttypename, notype_declarator): Remove
commented-out productions.
(parmlist_1, parmlist_2): Use make_node, not tree_cons, to create
an empty TREE_LIST node. Adjust calls to get_parm_info.
(parmlist_2 : ELLIPSIS): Tag the arg-info block with error_mark_node
to suppress -Wold-style-definition after this error.
(c_parse_file): Don't clear the binding stack or call
finish_fname_decls here. Correct comment.
* c-typeck.c (same_translation_unit_p): Export.
(common_type): Use c_override_global_bindings_to_false, not
pushlevel/poplevel/declare_parm_level.
* c-lang.c: Override LANG_HOOKS_CLEAR_BINDING_STACK,
LANG_HOOKS_PUSHLEVEL, LANG_HOOKS_POPLEVEL, LANG_HOOKS_SET_BLOCK,
and LANG_HOOKS_GETDECLS with do-nothing stubs.
* objc/objc-lang.c: Likewise.
* objc/objc-act.c: Adjust all calls to pushlevel, poplevel,
get_parm_info.
(OBJC_VOID_AT_END): Delete; replace all uses
with void_list_node.
(generate_forward_declaration_to_string_table): Delete.
* objc/objc-act.h (OCTI_STRG_DECL, UOBJC_STRINGS_decl): Delete.
* coverage.c (create_coverage): Don't pushdecl anything.
* langhooks.c (lhd_clear_binding_stack): Call
lang_hooks.decls.poplevel, not poplevel.
* tree.c (list_length): If ENABLE_TREE_CHECKING, abort on a
circular list rather than going into an infinite loop.
cp:
* cp-lang.c (c_reset_state): Delete.
(push_file_scope, pop_file_scope): New stubs.
* parser.c (c_parse_file): Call sorry() here if called more than once.
testsuite:
* gcc.dg/Wold-style-definition-1.c, gcc.dg/builtins-30.c
* gcc.dg/unused-4.c, gcc.dg/noncompile/label-1.c
* gcc.dg/noncompile/label-lineno-1.c, objc.dg/naming-1.m:
Adjust error regexps.
* gcc.dg/Wshadow-2.c, gcc.dg/noncompile/incomplete-3.c
* gcc.dg/noncompile/undeclared-1.c: New test cases.
* gcc.dg/decl-5.c, gcc.dg/redecl-1.c: Remove XFAIL.
* gcc.dg/local1.c: Add explanatory comment.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@79883 138bc75d-0d04-0410-961f-82ee72b054a4
31 files changed, 1383 insertions, 1319 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b4f247b89f..b885df98dc4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> @@ -198,8 +331,8 @@ * 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. @@ -404,7 +537,7 @@ (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. @@ -462,12 +595,12 @@ 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> diff --git a/gcc/c-common.h b/gcc/c-common.h index 00d5d5c18d4..4326a59480f 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -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. */ diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 46863ed531a..e74347997c5 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -108,19 +108,13 @@ static GTY(()) tree c_scope_stmt_stack; int c_in_iteration_stmt; int c_in_case_stmt; -/* A list of external DECLs that appeared at block scope when there was - some other global meaning for that identifier. */ -static GTY(()) tree truly_local_externals; - -/* All the builtins; this is a subset of the entries of global_scope. */ - -static GTY(()) tree first_builtin_decl; -static GTY(()) tree last_builtin_decl; - /* A DECL for the current file-scope context. */ static GTY(()) tree current_file_decl; +/* A list of decls to be made automatically visible in each file scope. */ +static GTY(()) tree visible_builtins; + /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ @@ -144,10 +138,56 @@ static int warn_about_return_type; /* Nonzero when starting a function declared `extern inline'. */ static int current_extern_inline; + +/* True means global_bindings_p should return false even if the scope stack + says we are in file scope. */ +bool c_override_global_bindings_to_false; + -/* Each c_scope structure describes the complete contents of one scope. - Three scopes are distinguished specially: the innermost or current - scope, the innermost function scope, and the outermost or file scope. +/* Each c_binding structure describes one binding of an identifier to + a decl. All the decls in a scope - irrespective of namespace - are + chained together by the ->prev field, which (as the name implies) + runs in reverse order. All the decls in a given namespace bound to + a given identifier are chained by the ->shadowed field, which runs + from inner to outer scopes. Finally, the ->contour field points + back to the relevant scope structure; this is mainly used to make + decls in the externals scope invisible (see below). + + The ->decl field usually points to a DECL node, but there are two + exceptions. In the namespace of type tags, the bound entity is a + RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node. If an undeclared + identifier is encountered, it is bound to error_mark_node to + suppress further errors about that identifier in the current + function. */ + +struct c_binding GTY(()) +{ + tree decl; /* the decl bound */ + tree id; /* the identifier it's bound to */ + struct c_binding *prev; /* the previous decl in this scope */ + struct c_binding *shadowed; /* the innermost decl shadowed by this one */ + struct c_scope *contour; /* the scope in which this decl is bound */ +}; + +#define I_SYMBOL_BINDING(node) \ + (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->symbol_binding) +#define I_SYMBOL_DECL(node) \ + (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0) + +#define I_TAG_BINDING(node) \ + (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->tag_binding) +#define I_TAG_DECL(node) \ + (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0) + +#define I_LABEL_BINDING(node) \ + (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->label_binding) +#define I_LABEL_DECL(node) \ + (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0) + +/* Each c_scope structure describes the complete contents of one + scope. Four scopes are distinguished specially: the innermost or + current scope, the innermost function scope, the file scope (always + the second to outermost) and the outermost or external scope. Most declarations are recorded in the current scope. @@ -157,18 +197,37 @@ static int current_extern_inline; hence the 'innermost' qualifier.) Explicitly declared labels (using the __label__ extension) appear in the current scope. - Being in the global scope (current_scope == global_scope) causes + Being in the file scope (current_scope == file_scope) causes special behavior in several places below. Also, under some conditions the Objective-C front end records declarations in the - global scope even though that isn't the current scope. + file scope even though that isn't the current scope. + + All declarations with external linkage are recorded in the external + scope, even if they aren't visible there; this models the fact that + such declarations are visible to the entire program, and (with a + bit of cleverness, see pushdecl) allows diagnosis of some violations + of C99 6.2.2p7 and 6.2.7p2: + + If, within the same translation unit, the same identifier appears + with both internal and external linkage, the behavior is + undefined. - 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 *); /* 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; +} + /* Hook called at end of compilation to assume 1 elt for a file-scope tentative array defn that wasn't complete before. */ @@ -354,40 +462,6 @@ c_finish_incomplete_decl (tree decl) } } -/* Reuse or create a struct for this scope. */ - -static struct c_scope * -make_scope (void) -{ - struct c_scope *result; - if (scope_freelist) - { - result = scope_freelist; - scope_freelist = result->outer; - } - else - result = ggc_alloc_cleared (sizeof (struct c_scope)); - - return result; -} - -/* Remove the topmost scope from the stack and add it to the - free list, updating current_function_scope if necessary. */ - -static void -pop_scope (void) -{ - struct c_scope *scope = current_scope; - - current_scope = scope->outer; - if (scope->function_body) - current_function_scope = scope->outer_function; - - memset (scope, 0, sizeof (struct c_scope)); - scope->outer = scope_freelist; - scope_freelist = scope; -} - /* The Objective-C front-end often needs to determine the current scope. */ void * @@ -403,30 +477,34 @@ void objc_mark_locals_volatile (void *enclosing_blk) { struct c_scope *scope; + struct c_binding *b; for (scope = current_scope; scope && scope != enclosing_blk; scope = scope->outer) { - tree decl; - - for (decl = scope->names; decl; decl = TREE_CHAIN (decl)) + for (b = scope->bindings; b; b = b->prev) { - DECL_REGISTER (decl) = 0; - TREE_THIS_VOLATILE (decl) = 1; + if (TREE_CODE (b->decl) == VAR_DECL + || TREE_CODE (b->decl) == PARM_DECL) + { + DECL_REGISTER (b->decl) = 0; + TREE_THIS_VOLATILE (b->decl) = 1; + } } + /* Do not climb up past the current function. */ if (scope->function_body) break; } } -/* Nonzero if we are currently in the global scope. */ +/* Nonzero if we are currently in file scope. */ int global_bindings_p (void) { - return current_scope == global_scope; + return current_scope == file_scope && !c_override_global_bindings_to_false; } void @@ -443,19 +521,8 @@ declare_parm_level (void) current_scope->parm_flag = true; } -/* Nonzero if currently making parm declarations. */ - -int -in_parm_level_p (void) -{ - return current_scope->parm_flag; -} - -/* Enter a new scope. The dummy parameter is for signature - compatibility with lang_hooks.decls.pushlevel. */ - void -pushlevel (int dummy ATTRIBUTE_UNUSED) +push_scope (void) { if (next_is_function_body) { @@ -480,49 +547,46 @@ pushlevel (int dummy ATTRIBUTE_UNUSED) } else { - struct c_scope *scope = make_scope (); + struct c_scope *scope; + if (scope_freelist) + { + scope = scope_freelist; + scope_freelist = scope->outer; + } + else + scope = ggc_alloc_cleared (sizeof (struct c_scope)); scope->keep = keep_next_level_flag; scope->outer = current_scope; + scope->depth = current_scope ? (current_scope->depth + 1) : 0; + + /* Check for scope depth overflow. Unlikely (2^28 == 268,435,456) but + possible. */ + if (current_scope && scope->depth == 0) + { + scope->depth--; + sorry ("GCC supports only %u nested scopes\n", scope->depth); + } + current_scope = scope; keep_next_level_flag = false; } } /* Exit a scope. Restore the state of the identifier-decl mappings - that were in effect when this scope was entered. - - If KEEP is KEEP_YES (1), this scope had explicit declarations, so - create a BLOCK node to record its declarations and subblocks for - debugging output. If KEEP is KEEP_MAYBE, do so only if the names - or tags lists are nonempty. - - The second parameter is ignored; it is present only for - signature compatibility with lang_hooks.decls.poplevel. - - If FUNCTIONBODY is nonzero, this level is the body of a function, - even if current_scope->function_body is not set. This is used - by language-independent code that generates synthetic functions, - and cannot set current_scope->function_body. - - FIXME: Eliminate the need for all arguments. */ + that were in effect when this scope was entered. Return a BLOCK + node containing all the DECLs in this scope that are of interest + to debug info generation. */ tree -poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody) +pop_scope (void) { struct c_scope *scope = current_scope; - tree block; - tree decl; - tree p; - - /* The following line does not use |= due to a bug in HP's C compiler. */ - scope->function_body = scope->function_body | functionbody; + 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) -{ -} /* Push a definition or a declaration of struct, union or enum tag "name". "type" should be the type node. @@ -696,24 +823,13 @@ set_block (tree block ATTRIBUTE_UNUSED) Note that the definition may really be just a forward reference. In that case, the TYPE_SIZE will be zero. */ -void +static void pushtag (tree name, tree type) { - struct c_scope *b = current_scope; - /* Record the identifier as the type's name if it has none. */ - if (name) - { - if (TYPE_NAME (type) == 0) - TYPE_NAME (type) = name; - - if (IDENTIFIER_TAG_VALUE (name)) - b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name), - b->shadowed_tags); - IDENTIFIER_TAG_VALUE (name) = type; - } - - b->tags = tree_cons (name, type, b->tags); + if (name && !TYPE_NAME (type)) + TYPE_NAME (type) = name; + bind (name, type, current_scope); /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the tagged type we just added to the current scope. This fake @@ -725,7 +841,7 @@ pushtag (tree name, tree type) TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type)); /* An approximation for now, so we can tell this is a function-scope tag. - This will be updated in poplevel. */ + This will be updated in pop_scope. */ TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type)); } @@ -916,8 +1032,9 @@ diagnose_mismatched_decls (tree newdecl, 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 = ¤t_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) } -/* 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; } +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); } /* 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)) @@ -2065,16 +2158,6 @@ define_label (location_t location, tree name) return label; } -/* Return the list of declarations of the current scope. - This hook is optional and not implemented for C. */ - -tree -getdecls (void) -{ - return 0; -} - - /* Given NAME, an IDENTIFIER_NODE, return the structure (or union or enum) definition for that name. If THISLEVEL_ONLY is nonzero, searches only the current_scope. @@ -2085,25 +2168,29 @@ getdecls (void) static tree lookup_tag (enum tree_code code, tree name, int thislevel_only) { - tree tag = IDENTIFIER_TAG_VALUE (name); + struct c_binding *b = I_TAG_BINDING (name); int thislevel = 0; - if (!tag) + if (!b || !b->decl) return 0; /* We only care about whether it's in this level if thislevel_only was set or it might be a type clash. */ - if (thislevel_only || TREE_CODE (tag) != code) - { - if (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; } @@ -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; } 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; } /* 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", ¤t_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", ¤t_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); + } } } @@ -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" diff --git a/gcc/c-lang.c b/gcc/c-lang.c index 0f8bf4ea49a..391e8bddfaf 100644 --- a/gcc/c-lang.c +++ b/gcc/c-lang.c @@ -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 diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c index 575407102fb..e736110e6be 100644 --- a/gcc/c-objc-common.c +++ b/gcc/c-objc-common.c @@ -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 (); diff --git a/gcc/c-opts.c b/gcc/c-opts.c index 4eecba91de5..ac2fe976156 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -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. */ diff --git a/gcc/c-parse.in b/gcc/c-parse.in index e628aa5fe90..91a42d91814 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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) } } -/* 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) { diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 6da67df0f2f..bd53dbc56e9 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 189ec0f580d..2e57ba7cceb 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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) /* 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) diff --git a/gcc/coverage.c b/gcc/coverage.c index 88d677c78b8..ccc8339cb5f 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -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; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0f900f53f84..008aa4adf74 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 @@ -17,13 +24,13 @@ (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 @@ -194,7 +201,7 @@ * 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. @@ -203,7 +210,7 @@ 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> @@ -294,7 +301,7 @@ 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/. @@ -326,7 +333,7 @@ * 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 @@ -341,7 +348,7 @@ 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> @@ -429,7 +436,7 @@ 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> @@ -464,7 +471,7 @@ 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. @@ -640,7 +647,7 @@ 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. diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 176a145f3ee..b0b927b850e 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -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) +{ +} diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e964f48753f..e58fda4cc4f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -15347,7 +15347,6 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser) } - /* 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 diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 4e9c3e983be..3e15a359333 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -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. */ diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 1d76cc4d989..89abaf4c198 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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) diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index abbf6562731..db7eeca5141 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -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 diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c index 72c772c40b4..877867ac39d 100644 --- a/gcc/objc/objc-lang.c +++ b/gcc/objc/objc-lang.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c111369c3e3..de52f548e68 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 @@ -55,11 +67,11 @@ * 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. diff --git a/gcc/testsuite/gcc.dg/Wold-style-definition-1.c b/gcc/testsuite/gcc.dg/Wold-style-definition-1.c index d4fb8bd8da1..aa016338b5e 100644 --- a/gcc/testsuite/gcc.dg/Wold-style-definition-1.c +++ b/gcc/testsuite/gcc.dg/Wold-style-definition-1.c @@ -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 index 00000000000..b0c051271ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wshadow-2.c @@ -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" } */ +} diff --git a/gcc/testsuite/gcc.dg/builtins-30.c b/gcc/testsuite/gcc.dg/builtins-30.c index 9ed0be53c40..7c700c514dc 100644 --- a/gcc/testsuite/gcc.dg/builtins-30.c +++ b/gcc/testsuite/gcc.dg/builtins-30.c @@ -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); diff --git a/gcc/testsuite/gcc.dg/decl-5.c b/gcc/testsuite/gcc.dg/decl-5.c index d7c36a4a1bc..9b778246459 100644 --- a/gcc/testsuite/gcc.dg/decl-5.c +++ b/gcc/testsuite/gcc.dg/decl-5.c @@ -10,7 +10,7 @@ void a() { void c(); c(); -} /* { dg-bogus "error" "PR c/14114" { xfail *-*-* } } */ +} void b() { diff --git a/gcc/testsuite/gcc.dg/local1.c b/gcc/testsuite/gcc.dg/local1.c index 700070ae1d6..9d6fdb16752 100644 --- a/gcc/testsuite/gcc.dg/local1.c +++ b/gcc/testsuite/gcc.dg/local1.c @@ -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 index 00000000000..735ef465b38 --- /dev/null +++ b/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c @@ -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" } */ +} diff --git a/gcc/testsuite/gcc.dg/noncompile/label-1.c b/gcc/testsuite/gcc.dg/noncompile/label-1.c index c646b48fb8d..e9bde7b3b7b 100644 --- a/gcc/testsuite/gcc.dg/noncompile/label-1.c +++ b/gcc/testsuite/gcc.dg/noncompile/label-1.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c b/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c index 0c5599434f8..76d4d96edaf 100644 --- a/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c +++ b/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c @@ -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 index 00000000000..5bb7c2a4df9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/noncompile/undeclared-1.c @@ -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" } */ +{ +} diff --git a/gcc/testsuite/gcc.dg/redecl-1.c b/gcc/testsuite/gcc.dg/redecl-1.c index 09b70d7b6cd..14877667e91 100644 --- a/gcc/testsuite/gcc.dg/redecl-1.c +++ b/gcc/testsuite/gcc.dg/redecl-1.c @@ -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) diff --git a/gcc/testsuite/gcc.dg/unused-4.c b/gcc/testsuite/gcc.dg/unused-4.c index 99e845f45a3..4b33a7fbb69 100644 --- a/gcc/testsuite/gcc.dg/unused-4.c +++ b/gcc/testsuite/gcc.dg/unused-4.c @@ -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() { } diff --git a/gcc/testsuite/objc.dg/naming-1.m b/gcc/testsuite/objc.dg/naming-1.m index 69d98b7be51..1be7eba664c 100644 --- a/gcc/testsuite/objc.dg/naming-1.m +++ b/gcc/testsuite/objc.dg/naming-1.m @@ -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) diff --git a/gcc/tree.c b/gcc/tree.c index bca58f04c01..eca5f20dd7b 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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; } |