Commit 339a28b9 by Zack Weinberg Committed by Zack Weinberg

c-decl.c (struct binding_level): Add shadowed_tags and function_body...


2003-04-10  Zack Weinberg  <zack@codesourcery.com>

	* c-decl.c (struct binding_level): Add shadowed_tags and
	function_body; remove this_block, tag_transparent, and
	subblocks_tag_transparent; update comments.
	(clear_binding_level, lookup_tag_reverse): Kill.
	(make_binding_level): Use ggc_alloc_cleared or memset.
	(lookup_tag): Remove struct binding_level* parameter.  All
	callers changed. Just look at IDENTIFIER_TAG_VALUE, and
	current_binding_level->tags if asked for thislevel_only or if
	we might have to diagnose "struct foo; union foo;"
	(pushlevel): Ignore argument.  Do not push another binding
	level on the transition from the parameters to the top level
	of the function body; just tweak the flags and proceed.
	(poplevel): Overhaul.  Clear IDENTIFIER_TAG_VALUEs; on exiting
	a function body, separate the parameter list from the
	top-level local variables.
	(set_block): Do nothing.
	(pushtag): Set IDENTIFIER_TAG_VALUE and add an entry to
	shadowed_tags if necessary.
	(warn_if_shadowing): Nuke the special case for local shadowing
	parameter.
	(pushdecl): Do not create a shadow entry if we are replacing
	an older decl in the same binding level.
	(pushdecl_function_level): Tweak for new way of indicating
	function scope.
	(shadow_tag_warned): Use TYPE_NAME, not	lookup_tag_reverse.
	(start_function): Don't set subblocks_tag_transparent.
	(finish_function): Fix up the binding_level stack for totally
	empty functions.  Otherwise, don't call poplevel.

	* c-common.c (shadow_warning): MANDATORY argument is no longer
	necessary.  Always use plain warning.
	* c-common.h: Update to match.

	* cfglayout.c (scope_to_insns_initialize): Clear block when we
	hit the FUNCTION_DECL.
	* function.c: Do not create cyclic tree structure.

2003-04-10  Zack Weinberg  <zack@codesourcery.com>

	* c-tree.h (struct lang_identifier): Replace global_value,
	local_value members with symbol_value, tag_value.  Kill
	implicit_decl and limbo_value.
	(IDENTIFIER_GLOBAL_VALUE, IDENTIFIER_LOCAL_VALUE,
	IDENTIFIER_LIMBO_VALUE, IDENTIFIER_IMPLICIT_DECL,
	C_MISSING_PROTOTYPE_WARNED): Kill.
	(IDENTIFIER_SYMBOL_VALUE, IDENTIFIER_TAG_VALUE,
	C_DECL_IMPLICIT, C_DECL_ISNT_PROTOTYPE): New.
	(C_DECL_ANTICIPATED): Rename to C_DECL_INVISIBLE.
	(implicit_decl_warning, lookup_name_current_level,
	record_function_scope_shadow): Don't prototype.
	(pushdecl_function_level): Prototype.

	* c-decl.c (truly_local_externals): New variable.
	(struct binding_level): Adjust commentary.
	(get_function_binding_level, clear_limbo_values,
	record_function_scope_shadow): Kill.
	(lookup_name_current_level, implicit_decl_warning): Are	now static.
	(any_external_decl, record_external_decl): New static functions.
	(clone_underlying type): Split out of pushdecl.
	(c_print_identifier): Update to match changes to struct
	lang_identifier.
	(poplevel): Delete #if 0 block.  Make externals invisible
	instead of clearing their IDENTIFIER_SYMBOL_VALUEs.  Don't
	call clear_limbo_values.  Refer to IDENTIFIER_SYMBOL_VALUE not
	IDENTIFIER_GLOBAL_VALUE or IDENTIFIER_LOCAL_VALUE.
	(duplicate-decls): For real parm decl after a forward decl,
	set TREE_ASM_WRITTEN here.  Allow void foo(...) followed by
	foo(...) { } with only a warning.  Say whether a previous
	declaration was implicit.
	(warn_if_shadowing): Now handles all shadowing, not just
	local-over-local.  Clarify comments.
	(pushdecl): Rewritten.  There is no longer a distinction
	between global and local symbol values; they're all
	IDENTIFIER_SYMBOL_VALUE.  Call record_external_decl on all
	DECL_EXTERNAL decls, and use any_external_decl to check
	against previous externals.  Kill #if 0 blocks.  Don't
	tolerate error_mark_node being NULL.
	(pushdecl_top_level): Handle only those cases which
	Objective C (the only user) needs.
	(pushdecl_function_level): New function.
	(implicitly_declare): Create ordinary decls with
	C_DECL_IMPLICIT set.  Recycle old decls, however they got
	created.
	(lookup_name): It's always IDENTIFIER_SYMBOL_VALUE. Return 0
	for C_DECL_INVISIBLE symbols.
	(lookup_name_current_level): Likewise.  Use chain_member.
	(c_make_fname_decl): Don't muck with DECL_CONTEXT.
	Use pushdecl_function_level.
	(builtin_function): Use C_DECL_INVISIBLE.
	(start_function): Don't muck with IDENTIFIER_IMPLICIT_DECL.
	Use C_DECL_ISNT_PROTOTYPE and C_DECL_IMPLICIT.
	(store_parm_decls): It's IDENTIFIER_SYMBOL_VALUE now.
	(identifier_global_value): Same.  Must scan
	global_binding_level in extremis.

	* c-typeck.c (undeclared_variable): New static function, split
	from build_external_ref.
	(build_external_ref): Use DECL_CONTEXT, not
	IDENTIFIER_LOCAL_VALUE, to decide whether a local hides
	an instance variable.  Restructure for clarity.
	* objc/objc-act.c: Use identifier_global_value, not
	IDENTIFIER_GLOBAL_VALUE.

cp:
	* decl.c: Update all calls to shadow_warning.

testsuite:
	* gcc.c-torture/execute/builtin-noret-2.c: New.
	* gcc.c-torture/execute/builtin-noret-2.x: New.
	XFAIL builtin-noret-2.c at -O1 and above.
	* gcc.dg/redecl.c: New.
	* gcc.dg/Wshadow-1.c: Update error regexps.

From-SVN: r65460
parent b1e0a93e
2003-04-10 Zack Weinberg <zack@codesourcery.com>
* c-decl.c (struct binding_level): Add shadowed_tags and
function_body; remove this_block, tag_transparent, and
subblocks_tag_transparent; update comments.
(clear_binding_level, lookup_tag_reverse): Kill.
(make_binding_level): Use ggc_alloc_cleared or memset.
(lookup_tag): Remove struct binding_level* parameter. All
callers changed. Just look at IDENTIFIER_TAG_VALUE, and
current_binding_level->tags if asked for thislevel_only or if
we might have to diagnose "struct foo; union foo;"
(pushlevel): Ignore argument. Do not push another binding
level on the transition from the parameters to the top level
of the function body; just tweak the flags and proceed.
(poplevel): Overhaul. Clear IDENTIFIER_TAG_VALUEs; on exiting
a function body, separate the parameter list from the
top-level local variables.
(set_block): Do nothing.
(pushtag): Set IDENTIFIER_TAG_VALUE and add an entry to
shadowed_tags if necessary.
(warn_if_shadowing): Nuke the special case for local shadowing
parameter.
(pushdecl): Do not create a shadow entry if we are replacing
an older decl in the same binding level.
(pushdecl_function_level): Tweak for new way of indicating
function scope.
(shadow_tag_warned): Use TYPE_NAME, not lookup_tag_reverse.
(start_function): Don't set subblocks_tag_transparent.
(finish_function): Fix up the binding_level stack for totally
empty functions. Otherwise, don't call poplevel.
* c-common.c (shadow_warning): MANDATORY argument is no longer
necessary. Always use plain warning.
* c-common.h: Update to match.
* cfglayout.c (scope_to_insns_initialize): Clear block when we
hit the FUNCTION_DECL.
* function.c: Do not create cyclic tree structure.
2003-04-10 Zack Weinberg <zack@codesourcery.com>
* c-tree.h (struct lang_identifier): Replace global_value,
local_value members with symbol_value, tag_value. Kill
implicit_decl and limbo_value.
(IDENTIFIER_GLOBAL_VALUE, IDENTIFIER_LOCAL_VALUE,
IDENTIFIER_LIMBO_VALUE, IDENTIFIER_IMPLICIT_DECL,
C_MISSING_PROTOTYPE_WARNED): Kill.
(IDENTIFIER_SYMBOL_VALUE, IDENTIFIER_TAG_VALUE,
C_DECL_IMPLICIT, C_DECL_ISNT_PROTOTYPE): New.
(C_DECL_ANTICIPATED): Rename to C_DECL_INVISIBLE.
(implicit_decl_warning, lookup_name_current_level,
record_function_scope_shadow): Don't prototype.
(pushdecl_function_level): Prototype.
* c-decl.c (truly_local_externals): New variable.
(struct binding_level): Adjust commentary.
(get_function_binding_level, clear_limbo_values,
record_function_scope_shadow): Kill.
(lookup_name_current_level, implicit_decl_warning): Are now static.
(any_external_decl, record_external_decl): New static functions.
(clone_underlying type): Split out of pushdecl.
(c_print_identifier): Update to match changes to struct
lang_identifier.
(poplevel): Delete #if 0 block. Make externals invisible
instead of clearing their IDENTIFIER_SYMBOL_VALUEs. Don't
call clear_limbo_values. Refer to IDENTIFIER_SYMBOL_VALUE not
IDENTIFIER_GLOBAL_VALUE or IDENTIFIER_LOCAL_VALUE.
(duplicate-decls): For real parm decl after a forward decl,
set TREE_ASM_WRITTEN here. Allow void foo(...) followed by
foo(...) { } with only a warning. Say whether a previous
declaration was implicit.
(warn_if_shadowing): Now handles all shadowing, not just
local-over-local. Clarify comments.
(pushdecl): Rewritten. There is no longer a distinction
between global and local symbol values; they're all
IDENTIFIER_SYMBOL_VALUE. Call record_external_decl on all
DECL_EXTERNAL decls, and use any_external_decl to check
against previous externals. Kill #if 0 blocks. Don't
tolerate error_mark_node being NULL.
(pushdecl_top_level): Handle only those cases which
Objective C (the only user) needs.
(pushdecl_function_level): New function.
(implicitly_declare): Create ordinary decls with
C_DECL_IMPLICIT set. Recycle old decls, however they got
created.
(lookup_name): It's always IDENTIFIER_SYMBOL_VALUE. Return 0
for C_DECL_INVISIBLE symbols.
(lookup_name_current_level): Likewise. Use chain_member.
(c_make_fname_decl): Don't muck with DECL_CONTEXT.
Use pushdecl_function_level.
(builtin_function): Use C_DECL_INVISIBLE.
(start_function): Don't muck with IDENTIFIER_IMPLICIT_DECL.
Use C_DECL_ISNT_PROTOTYPE and C_DECL_IMPLICIT.
(store_parm_decls): It's IDENTIFIER_SYMBOL_VALUE now.
(identifier_global_value): Same. Must scan
global_binding_level in extremis.
* c-typeck.c (undeclared_variable): New static function, split
from build_external_ref.
(build_external_ref): Use DECL_CONTEXT, not
IDENTIFIER_LOCAL_VALUE, to decide whether a local hides
an instance variable. Restructure for clarity.
* objc/objc-act.c: Use identifier_global_value, not
IDENTIFIER_GLOBAL_VALUE.
2003-04-08 Jonathan Wakely <redi@gcc.gnu.org> 2003-04-08 Jonathan Wakely <redi@gcc.gnu.org>
* doc/extend.texi (Template Instantiation): Refer to ISO standard, * doc/extend.texi (Template Instantiation): Refer to ISO standard,
......
...@@ -4778,12 +4778,10 @@ c_common_insert_default_attributes (decl) ...@@ -4778,12 +4778,10 @@ c_common_insert_default_attributes (decl)
} }
/* Output a -Wshadow warning MSGCODE about NAME, and give the location /* Output a -Wshadow warning MSGCODE about NAME, and give the location
of the previous declaration DECL. MANDATORY says whether this is a of the previous declaration DECL. */
mandatory warning (i.e. use pedwarn). */
void void
shadow_warning (msgcode, mandatory, name, decl) shadow_warning (msgcode, name, decl)
enum sw_kind msgcode; enum sw_kind msgcode;
int mandatory; /* really bool */
const char *name; const char *name;
tree decl; tree decl;
{ {
...@@ -4793,7 +4791,7 @@ shadow_warning (msgcode, mandatory, name, decl) ...@@ -4793,7 +4791,7 @@ shadow_warning (msgcode, mandatory, name, decl)
/* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration") /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration")
}; };
(mandatory ? pedwarn : warning) (msgs[msgcode], name); warning (msgs[msgcode], name);
warning_with_file_and_line (DECL_SOURCE_FILE (decl), warning_with_file_and_line (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl), DECL_SOURCE_LINE (decl),
"shadowed declaration is here"); "shadowed declaration is here");
......
...@@ -335,7 +335,7 @@ extern tree c_begin_while_stmt PARAMS ((void)); ...@@ -335,7 +335,7 @@ extern tree c_begin_while_stmt PARAMS ((void));
extern void c_finish_while_stmt_cond PARAMS ((tree, tree)); extern void c_finish_while_stmt_cond PARAMS ((tree, tree));
enum sw_kind { SW_PARAM = 0, SW_LOCAL, SW_GLOBAL }; enum sw_kind { SW_PARAM = 0, SW_LOCAL, SW_GLOBAL };
extern void shadow_warning PARAMS ((enum sw_kind, int, extern void shadow_warning PARAMS ((enum sw_kind,
const char *, tree)); const char *, tree));
/* Extra information associated with a DECL. Other C dialects extend /* Extra information associated with a DECL. Other C dialects extend
......
/* Process declarations and variables for C compiler. /* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002 Free Software Foundation, Inc. 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -122,6 +122,10 @@ static GTY(()) tree named_labels; ...@@ -122,6 +122,10 @@ static GTY(()) tree named_labels;
static GTY(()) tree shadowed_labels; static GTY(()) tree shadowed_labels;
/* 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;
/* Set to 0 at beginning of a function definition, set to 1 if /* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */ a return statement that specifies a return value is seen. */
...@@ -159,9 +163,6 @@ static int current_extern_inline; ...@@ -159,9 +163,6 @@ static int current_extern_inline;
* the current one out to the global one. * the current one out to the global one.
*/ */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
struct binding_level GTY(()) struct binding_level GTY(())
{ {
/* A chain of _DECL nodes for all variables, constants, functions, /* A chain of _DECL nodes for all variables, constants, functions,
...@@ -177,35 +178,34 @@ struct binding_level GTY(()) ...@@ -177,35 +178,34 @@ struct binding_level GTY(())
*/ */
tree tags; tree tags;
/* For each level, a list of shadowed outer-level local definitions /* For each level, a list of shadowed outer-level definitions
to be restored when this level is popped. to be restored when this level is popped.
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and 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). */ whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
tree shadowed; tree shadowed;
/* For each level, a list of shadowed outer-level tag definitions
to be restored when this level 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;
/* For each level (except not the global one), /* For each level (except not the global one),
a chain of BLOCK nodes for all the levels a chain of BLOCK nodes for all the levels
that were entered and exited one level down. */ that were entered and exited one level down. */
tree blocks; tree blocks;
/* The BLOCK node for this level, if one has been preallocated.
If 0, the BLOCK is allocated (if needed) when the level is popped. */
tree this_block;
/* The binding level which this one is contained in (inherits from). */ /* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain; struct binding_level *level_chain;
/* Nonzero for the level that holds the parameters of a function. */ /* Nonzero if we are currently filling this level with parameter
declarations. */
char parm_flag; char parm_flag;
/* Nonzero if this level "doesn't exist" for tags. */ /* Nonzero if this is the outermost block scope of a function body.
char tag_transparent; This scope contains both the parameters and the local variables
declared in the outermost block. */
/* Nonzero if sublevels of this level "don't exist" for tags. char function_body;
This is set in the parm level of a function definition
while reading the function body, so that the outermost block
of the function body will be tag-transparent. */
char subblocks_tag_transparent;
/* Nonzero means make a BLOCK for this level regardless of all else. */ /* Nonzero means make a BLOCK for this level regardless of all else. */
char keep; char keep;
...@@ -239,12 +239,6 @@ static GTY((deletable (""))) struct binding_level *free_binding_level; ...@@ -239,12 +239,6 @@ static GTY((deletable (""))) struct binding_level *free_binding_level;
static GTY(()) struct binding_level *global_binding_level; static GTY(()) struct binding_level *global_binding_level;
/* Binding level structures are initialized by copying this one. */
static struct binding_level clear_binding_level
= {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
NULL};
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */ /* Nonzero means unconditionally make a BLOCK for the next level pushed. */
static int keep_next_level_flag; static int keep_next_level_flag;
...@@ -269,23 +263,24 @@ tree static_ctors, static_dtors; ...@@ -269,23 +263,24 @@ tree static_ctors, static_dtors;
/* Forward declarations. */ /* Forward declarations. */
static struct binding_level *make_binding_level PARAMS ((void)); static struct binding_level *make_binding_level PARAMS ((void));
static struct binding_level *get_function_binding_level PARAMS ((void));
static void pop_binding_level PARAMS ((struct binding_level **)); static void pop_binding_level PARAMS ((struct binding_level **));
static void clear_limbo_values PARAMS ((tree));
static int duplicate_decls PARAMS ((tree, tree, int)); static int duplicate_decls PARAMS ((tree, tree, int));
static int redeclaration_error_message PARAMS ((tree, tree)); static int redeclaration_error_message PARAMS ((tree, tree));
static void implicit_decl_warning PARAMS ((tree));
static void storedecls PARAMS ((tree)); static void storedecls PARAMS ((tree));
static void storetags PARAMS ((tree)); static void storetags PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree, static tree lookup_tag PARAMS ((enum tree_code, tree, int));
struct binding_level *, int)); static tree lookup_name_current_level PARAMS ((tree));
static tree lookup_tag_reverse PARAMS ((tree));
static tree grokdeclarator PARAMS ((tree, tree, enum decl_context, static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
int)); int));
static tree grokparms PARAMS ((tree, int)); static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree)); static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, int)); static tree c_make_fname_decl PARAMS ((tree, int));
static void c_expand_body_1 PARAMS ((tree, int)); static void c_expand_body_1 PARAMS ((tree, int));
static tree any_external_decl PARAMS ((tree));
static void record_external_decl PARAMS ((tree));
static void warn_if_shadowing PARAMS ((tree, tree)); static void warn_if_shadowing PARAMS ((tree, tree));
static void clone_underlying_type PARAMS ((tree));
static bool flexible_array_type_p PARAMS ((tree)); static bool flexible_array_type_p PARAMS ((tree));
/* States indicating how grokdeclarator() should handle declspecs marked /* States indicating how grokdeclarator() should handle declspecs marked
...@@ -306,11 +301,9 @@ c_print_identifier (file, node, indent) ...@@ -306,11 +301,9 @@ c_print_identifier (file, node, indent)
tree node; tree node;
int indent; int indent;
{ {
print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4); print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4);
print_node (file, "local", IDENTIFIER_LOCAL_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, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
if (C_IS_RESERVED_WORD (node)) if (C_IS_RESERVED_WORD (node))
{ {
tree rid = ridpointers[C_RID_CODE (node)]; tree rid = ridpointers[C_RID_CODE (node)];
...@@ -350,25 +343,18 @@ c_finish_incomplete_decl (decl) ...@@ -350,25 +343,18 @@ c_finish_incomplete_decl (decl)
static struct binding_level * static struct binding_level *
make_binding_level () make_binding_level ()
{ {
struct binding_level *result;
if (free_binding_level) if (free_binding_level)
{ {
struct binding_level *result = free_binding_level; result = free_binding_level;
free_binding_level = result->level_chain; free_binding_level = result->level_chain;
return result; memset (result, 0, sizeof(struct binding_level));
} }
else else
return (struct binding_level *) ggc_alloc (sizeof (struct binding_level)); result = (struct binding_level *)
} ggc_alloc_cleared (sizeof (struct binding_level));
/* Return the outermost binding level for the current function. */
static struct binding_level *
get_function_binding_level ()
{
struct binding_level *b = current_binding_level;
while (b->level_chain->parm_flag == 0) return result;
b = b->level_chain;
return b;
} }
/* Remove a binding level from a list and add it to the level chain. */ /* Remove a binding level from a list and add it to the level chain. */
...@@ -408,8 +394,7 @@ kept_level_p () ...@@ -408,8 +394,7 @@ kept_level_p ()
&& current_binding_level->blocks != 0) && current_binding_level->blocks != 0)
|| current_binding_level->keep || current_binding_level->keep
|| current_binding_level->names != 0 || current_binding_level->names != 0
|| (current_binding_level->tags != 0 || current_binding_level->tags != 0);
&& !current_binding_level->tag_transparent));
} }
/* Identify this binding level as a level of parameters. /* Identify this binding level as a level of parameters.
...@@ -432,57 +417,45 @@ in_parm_level_p () ...@@ -432,57 +417,45 @@ in_parm_level_p ()
return current_binding_level->parm_flag; return current_binding_level->parm_flag;
} }
/* Enter a new binding level. /* Enter a new binding level. */
If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
not for that of tags. */
void void
pushlevel (tag_transparent) pushlevel (dummy)
int tag_transparent; int dummy ATTRIBUTE_UNUSED;
{ {
struct binding_level *newlevel = NULL_BINDING_LEVEL; /* If this is the top level of a function, make sure that
NAMED_LABELS is 0. */
/* If this is the top level of a function,
just make sure that NAMED_LABELS is 0. */
if (current_binding_level == global_binding_level) if (current_binding_level == global_binding_level)
{
named_labels = 0; named_labels = 0;
}
newlevel = make_binding_level (); if (keep_next_if_subblocks)
{
/* This is the transition from the parameters to the top level
of the function body. These are the same scope
(C99 6.2.1p4,6) so we do not push another binding level.
/* Add this level to the front of the chain (stack) of levels that XXX Note kludge - keep_next_if_subblocks is set only by
are active. */ store_parm_decls, which in turn is called when and only
when we are about to encounter the opening curly brace for
the function body. */
current_binding_level->parm_flag = 0;
current_binding_level->function_body = 1;
current_binding_level->keep |= keep_next_level_flag;
current_binding_level->keep_if_subblocks = 1;
*newlevel = clear_binding_level;
newlevel->tag_transparent
= (tag_transparent
|| (current_binding_level
? current_binding_level->subblocks_tag_transparent
: 0));
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->keep = keep_next_level_flag;
keep_next_level_flag = 0; keep_next_level_flag = 0;
newlevel->keep_if_subblocks = keep_next_if_subblocks;
keep_next_if_subblocks = 0; keep_next_if_subblocks = 0;
} }
else
/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */ {
struct binding_level *newlevel = make_binding_level ();
static void
clear_limbo_values (block)
tree block;
{
tree tem;
for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem))
if (DECL_NAME (tem) != 0)
IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0;
for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem)) newlevel->keep = keep_next_level_flag;
clear_limbo_values (tem); newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
keep_next_level_flag = 0;
}
} }
/* Exit a binding level. /* Exit a binding level.
...@@ -507,95 +480,103 @@ poplevel (keep, reverse, functionbody) ...@@ -507,95 +480,103 @@ poplevel (keep, reverse, functionbody)
int functionbody; int functionbody;
{ {
tree link; tree link;
/* The chain of decls was accumulated in reverse order. tree block;
Put it into forward order, just for cleanliness. */ tree decl;
tree decls; tree decls = current_binding_level->names;
tree tags = current_binding_level->tags; tree tags = current_binding_level->tags;
tree subblocks = current_binding_level->blocks; tree subblocks = current_binding_level->blocks;
tree block = 0;
tree decl;
int block_previously_created;
keep |= current_binding_level->keep; functionbody |= current_binding_level->function_body;
keep |= (current_binding_level->keep || functionbody
|| (current_binding_level->keep_if_subblocks && subblocks != 0));
/* This warning is turned off because it causes warnings for /* We used to warn about unused variables in expand_end_bindings,
declarations like `extern struct foo *x'. */ i.e. while generating RTL. But in function-at-a-time mode we may
#if 0 choose to never expand a function at all (e.g. auto inlining), so
/* Warn about incomplete structure types in this level. */ we do this explicitly now. */
for (link = tags; link; link = TREE_CHAIN (link)) warn_about_unused_variables (decls);
if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
/* Clear out the name-meanings declared on this level.
Propagate TREE_ADDRESSABLE from nested functions to their
containing functions. */
for (link = decls; link; link = TREE_CHAIN (link))
{ {
tree type = TREE_VALUE (link); if (DECL_NAME (link) != 0)
tree type_name = TYPE_NAME (type);
char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
? type_name
: DECL_NAME (type_name));
switch (TREE_CODE (type))
{ {
case RECORD_TYPE: if (DECL_EXTERNAL (link))
error ("`struct %s' incomplete in scope ending here", id); /* External decls stay in the symbol-value slot but are
break; inaccessible. */
case UNION_TYPE: C_DECL_INVISIBLE (link) = 1;
error ("`union %s' incomplete in scope ending here", id); else
break; IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0;
case ENUMERAL_TYPE:
error ("`enum %s' incomplete in scope ending here", id);
break;
} }
if (TREE_CODE (link) == FUNCTION_DECL
&& ! TREE_ASM_WRITTEN (link)
&& DECL_INITIAL (link) != 0
&& TREE_ADDRESSABLE (link)
&& DECL_ABSTRACT_ORIGIN (link) != 0
&& DECL_ABSTRACT_ORIGIN (link) != link)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (link)) = 1;
} }
#endif /* 0 */
/* Get the decls in the order they were written. /* Clear out the tag-meanings declared on this level. */
Usually current_binding_level->names is in reverse order. for (link = tags; link; link = TREE_CHAIN (link))
But parameter decls were previously put in forward order. */ if (TREE_PURPOSE (link))
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = 0;
if (reverse) /* Restore all name-meanings of the outer levels
current_binding_level->names that were shadowed by this level. */
= decls = nreverse (current_binding_level->names);
else
decls = current_binding_level->names;
/* Output any nested inline functions within this block for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
if they weren't already output. */ IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
for (decl = decls; decl; decl = TREE_CHAIN (decl)) /* Restore all tag-meanings of the outer levels
if (TREE_CODE (decl) == FUNCTION_DECL that were shadowed by this level. */
&& ! TREE_ASM_WRITTEN (decl)
&& DECL_INITIAL (decl) != 0 for (link = current_binding_level->shadowed_tags; link;
&& TREE_ADDRESSABLE (decl)) link = TREE_CHAIN (link))
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
/* If this is the top level block of a function, remove all
PARM_DECLs from current_binding_level->names; they are already
stored in DECL_ARGUMENTS of cfun->decl in proper order, should
not be put in BLOCK_VARS, and furthermore reversing them will
cause trouble later. They are all together at the end of the
list. */
if (functionbody && decls)
{
if (TREE_CODE (decls) == PARM_DECL)
decls = 0;
else
{ {
/* If this decl was copied from a file-scope decl link = decls;
on account of a block-scope extern decl, while (TREE_CHAIN (link)
propagate TREE_ADDRESSABLE to the file-scope decl. && TREE_CODE (TREE_CHAIN (link)) != PARM_DECL)
link = TREE_CHAIN (link);
DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is TREE_CHAIN (link) = 0;
true, since then the decl goes through save_for_inline_copying. */ }
if (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
} }
/* We used to warn about unused variables in expand_end_bindings, /* Get the decls in the order they were written.
i.e. while generating RTL. But in function-at-a-time mode we may Usually current_binding_level->names is in reverse order.
choose to never expand a function at all (e.g. auto inlining), so But parameter decls were previously put in forward order. */
we do this explicitly now. */
warn_about_unused_variables (getdecls ()); if (reverse)
decls = nreverse (decls);
/* If there were any declarations or structure tags in that level, /* If there were any declarations or structure tags in that level,
or if this level is a function body, or if this level is a function body,
create a BLOCK to record them for the life of this function. */ create a BLOCK to record them for the life of this function. */
block = 0; block = 0;
block_previously_created = (current_binding_level->this_block != 0); if (keep)
if (block_previously_created)
block = current_binding_level->this_block;
else if (keep || functionbody
|| (current_binding_level->keep_if_subblocks && subblocks != 0))
block = make_node (BLOCK);
if (block != 0)
{ {
block = make_node (BLOCK);
BLOCK_VARS (block) = decls; BLOCK_VARS (block) = decls;
BLOCK_SUBBLOCKS (block) = subblocks; BLOCK_SUBBLOCKS (block) = subblocks;
TREE_USED (block) = 1;
} }
/* In each subblock, record that this is its superior. */ /* In each subblock, record that this is its superior. */
...@@ -603,50 +584,31 @@ poplevel (keep, reverse, functionbody) ...@@ -603,50 +584,31 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link)) for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block; BLOCK_SUPERCONTEXT (link) = block;
/* Clear out the meanings of the local variables of this level. */ /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
binding contour so that they point to the appropriate construct, i.e.
for (link = decls; link; link = TREE_CHAIN (link)) either to the current FUNCTION_DECL node, or else to the BLOCK node
{ we just constructed.
if (DECL_NAME (link) != 0)
{
/* If the ident. was used or addressed via a local extern decl,
don't forget that fact. */
if (DECL_EXTERNAL (link))
{
if (TREE_USED (link))
TREE_USED (DECL_NAME (link)) = 1;
if (TREE_ADDRESSABLE (link))
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
}
IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
}
}
/* Restore all name-meanings of the outer levels Note that for tagged types whose scope is just the formal parameter
that were shadowed by this level. */ 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. */
for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) decl = functionbody ? current_function_decl : block;
IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); if (decl)
for (link = tags; link; link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = decl;
/* If the level being exited is the top level of a function, /* If the level being exited is the top level of a function, check
check over all the labels, and clear out the current over all the labels, and clear out the current (function local)
(function local) meanings of their names. */ meanings of their names. Then add them to BLOCK_VARS. */
if (functionbody) if (functionbody)
{ {
clear_limbo_values (block);
/* If this is the top level block of a function,
the vars are the function's parameters.
Don't leave them in the BLOCK because they are
found in the FUNCTION_DECL instead. */
BLOCK_VARS (block) = 0;
/* Clear out the definitions of all label names,
since their scopes end here,
and add them to BLOCK_VARS. */
for (link = named_labels; link; link = TREE_CHAIN (link)) for (link = named_labels; link; link = TREE_CHAIN (link))
{ {
tree label = TREE_VALUE (link); tree label = TREE_VALUE (link);
...@@ -677,11 +639,8 @@ poplevel (keep, reverse, functionbody) ...@@ -677,11 +639,8 @@ poplevel (keep, reverse, functionbody)
if (functionbody) if (functionbody)
DECL_INITIAL (current_function_decl) = block; DECL_INITIAL (current_function_decl) = block;
else if (block) else if (block)
{
if (!block_previously_created)
current_binding_level->blocks current_binding_level->blocks
= chainon (current_binding_level->blocks, block); = chainon (current_binding_level->blocks, block);
}
/* If we did not make a block for the level just exited, /* If we did not make a block for the level just exited,
any blocks made for inner levels any blocks made for inner levels
(since they cannot be recorded as subblocks in that level) (since they cannot be recorded as subblocks in that level)
...@@ -691,30 +650,6 @@ poplevel (keep, reverse, functionbody) ...@@ -691,30 +650,6 @@ poplevel (keep, reverse, functionbody)
current_binding_level->blocks current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks); = chainon (current_binding_level->blocks, subblocks);
/* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
binding contour 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. */
if (functionbody)
for (link = tags; link; link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = current_function_decl;
else if (block)
for (link = tags; link; link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = block;
if (block)
TREE_USED (block) = 1;
return block; return block;
} }
...@@ -731,18 +666,14 @@ insert_block (block) ...@@ -731,18 +666,14 @@ insert_block (block)
= chainon (current_binding_level->blocks, block); = chainon (current_binding_level->blocks, block);
} }
/* Set the BLOCK node for the innermost scope /* Set the BLOCK node for the innermost scope (the one we are
(the one we are currently in). */ currently in). The RTL expansion machinery requires us to provide
this hook, but it is not useful in function-at-a-time mode. */
void void
set_block (block) set_block (block)
tree block; tree block ATTRIBUTE_UNUSED;
{ {
current_binding_level->this_block = block;
current_binding_level->names = chainon (current_binding_level->names,
BLOCK_VARS (block));
current_binding_level->blocks = chainon (current_binding_level->blocks,
BLOCK_SUBBLOCKS (block));
} }
void void
...@@ -826,12 +757,7 @@ void ...@@ -826,12 +757,7 @@ void
pushtag (name, type) pushtag (name, type)
tree name, type; tree name, type;
{ {
struct binding_level *b; struct binding_level *b = current_binding_level;
/* Find the proper binding level for this type tag. */
for (b = current_binding_level; b->tag_transparent; b = b->level_chain)
continue;
if (name) if (name)
{ {
...@@ -839,6 +765,11 @@ pushtag (name, type) ...@@ -839,6 +765,11 @@ pushtag (name, type)
if (TYPE_NAME (type) == 0) if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = name; 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); b->tags = tree_cons (name, type, b->tags);
...@@ -966,11 +897,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level) ...@@ -966,11 +897,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
return 0; return 0;
} }
/* For real parm decl following a forward decl, /* For real parm decl following a forward decl, return 1 so old decl
return 1 so old decl will be reused. */ will be reused. Only allow this to happen once. */
if (types_match && TREE_CODE (newdecl) == PARM_DECL if (types_match && TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl)) && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
{
TREE_ASM_WRITTEN (olddecl) = 0;
return 1; return 1;
}
/* The new declaration is the same kind of object as the old one. /* The new declaration is the same kind of object as the old one.
The declarations may partially match. Print warnings if they don't The declarations may partially match. Print warnings if they don't
...@@ -1107,6 +1041,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level) ...@@ -1107,6 +1041,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
we will come back here again. */ we will come back here again. */
DECL_IN_SYSTEM_HEADER (newdecl) = 1; DECL_IN_SYSTEM_HEADER (newdecl) = 1;
} }
/* Permit void foo (...) to match int foo (...) if the latter is the
definition and implicit int was used. See c-torture/compile/920625-2.c. */
else if (!types_match && new_is_definition
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
&& C_FUNCTION_IMPLICIT_INT (newdecl))
{
pedwarn_with_decl (newdecl, "conflicting types for `%s'");
/* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
}
else if (!types_match else if (!types_match
/* Permit char *foo (int, ...); followed by char *foo (); /* Permit char *foo (int, ...); followed by char *foo ();
if not pedantic. */ if not pedantic. */
...@@ -1151,6 +1099,9 @@ duplicate_decls (newdecl, olddecl, different_binding_level) ...@@ -1151,6 +1099,9 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
} }
} }
} }
if (C_DECL_IMPLICIT (olddecl))
error_with_decl (olddecl, "previous implicit declaration of `%s'");
else
error_with_decl (olddecl, "previous declaration of `%s'"); error_with_decl (olddecl, "previous declaration of `%s'");
/* This is safer because the initializer might contain references /* This is safer because the initializer might contain references
...@@ -1592,160 +1543,81 @@ duplicate_decls (newdecl, olddecl, different_binding_level) ...@@ -1592,160 +1543,81 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
return 1; return 1;
} }
/* Return any external DECL associated with ID, whether or not it is
currently in scope. */
static tree
any_external_decl (id)
tree id;
{
tree decl = IDENTIFIER_SYMBOL_VALUE (id);
tree t;
if (decl && 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. */
static void
record_external_decl (decl)
tree decl;
{
tree name = DECL_NAME (decl);
if (!IDENTIFIER_SYMBOL_VALUE (name))
return;
truly_local_externals = tree_cons (name, decl, truly_local_externals);
}
/* Check whether decl-node X shadows an existing declaration. /* Check whether decl-node X shadows an existing declaration.
OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X, OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X,
which might be a NULL_TREE. */ which might be a NULL_TREE. */
static void static void
warn_if_shadowing (x, oldlocal) warn_if_shadowing (x, old)
tree x, oldlocal; tree x, old;
{ {
tree sym;
const char *name; const char *name;
if (DECL_EXTERNAL (x)) /* Nothing to shadow? */
return; if (old == 0
/* Shadow warnings not wanted? */
sym = DECL_NAME (x); || !warn_shadow
name = IDENTIFIER_POINTER (sym);
/* Warn if shadowing an argument at the top level of the body. */
if (oldlocal != 0
/* This warning doesn't apply to the parms of a nested fcn. */
&& ! current_binding_level->parm_flag
/* Check that this is one level down from the parms. */
&& current_binding_level->level_chain->parm_flag
/* Check that the decl being shadowed
comes from the parm level, one level up. */
&& chain_member (oldlocal, current_binding_level->level_chain->names))
shadow_warning (SW_PARAM, true, name, oldlocal);
/* Maybe warn if shadowing something else. */
else if (warn_shadow
/* No shadow warnings for internally generated vars. */ /* No shadow warnings for internally generated vars. */
&& DECL_SOURCE_LINE (x) != 0 || DECL_SOURCE_LINE (x) == 0
/* No shadow warnings for vars made for inlining. */ /* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x)) || DECL_FROM_INLINE (x)
{
if (TREE_CODE (x) == PARM_DECL
&& current_binding_level->level_chain->parm_flag)
/* Don't warn about the parm names in function declarator /* Don't warn about the parm names in function declarator
within a function declarator. within a function declarator.
It would be nice to avoid warning in any function It would be nice to avoid warning in any function
declarator in a declaration, as opposed to a definition, declarator in a declaration, as opposed to a definition,
but there is no way to tell it's not a definition. */ but there is no way to tell it's not a definition. */
; || (TREE_CODE (x) == PARM_DECL
else if (oldlocal) && current_binding_level->level_chain->parm_flag))
{ return;
if (TREE_CODE (oldlocal) == PARM_DECL)
shadow_warning (SW_PARAM, false, name, oldlocal);
else
shadow_warning (SW_LOCAL, false, name, oldlocal);
}
else if (IDENTIFIER_GLOBAL_VALUE (sym) != 0
&& IDENTIFIER_GLOBAL_VALUE (sym) != error_mark_node)
shadow_warning (SW_GLOBAL, false, name,
IDENTIFIER_GLOBAL_VALUE (sym));
}
}
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
Returns either X or an old decl for the same name.
If an old decl is returned, it may have been smashed
to agree with what X says. */
tree
pushdecl (x)
tree x;
{
tree t;
tree name = DECL_NAME (x);
struct binding_level *b = current_binding_level;
/* Functions need the lang_decl data. */
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
ggc_alloc_cleared (sizeof (struct lang_decl));
DECL_CONTEXT (x) = current_function_decl;
/* A local extern declaration for a function doesn't constitute nesting.
A local auto declaration does, since it's a forward decl
for a nested function coming later. */
if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
if (name) name = IDENTIFIER_POINTER (DECL_NAME (x));
{
int different_binding_level = 0;
if (warn_nested_externs if (TREE_CODE (old) == PARM_DECL)
&& DECL_EXTERNAL (x) shadow_warning (SW_PARAM, name, old);
&& b != global_binding_level else if (DECL_CONTEXT (old) == 0)
&& x != IDENTIFIER_IMPLICIT_DECL (name) shadow_warning (SW_GLOBAL, name, old);
/* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__. */ else
&& !DECL_IN_SYSTEM_HEADER (x)) shadow_warning (SW_LOCAL, name, old);
warning ("nested extern declaration of `%s'", }
IDENTIFIER_POINTER (name));
t = lookup_name_current_level (name);
if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
{
t = IDENTIFIER_GLOBAL_VALUE (name);
/* Type decls at global scope don't conflict with externs declared
inside lexical blocks. */
if (! t || TREE_CODE (t) == TYPE_DECL)
/* If there's no visible global declaration, try for an
invisible one. */
t = IDENTIFIER_LIMBO_VALUE (name);
different_binding_level = 1;
}
if (t != 0 && t == error_mark_node)
/* error_mark_node is 0 for a while during initialization! */
{
t = 0;
error_with_decl (x, "`%s' used prior to declaration");
}
/* If this decl is `static' and an implicit decl was seen previously,
warn. */
if (TREE_PUBLIC (name)
/* Don't test for DECL_EXTERNAL, because grokdeclarator
sets this for all functions. */
&& ! TREE_PUBLIC (x)
&& (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level)
/* We used to warn also for explicit extern followed by static,
but sometimes you need to do it that way. */
&& IDENTIFIER_IMPLICIT_DECL (name) != 0)
{
pedwarn ("`%s' was declared implicitly `extern' and later `static'",
IDENTIFIER_POINTER (name));
pedwarn_with_file_and_line
(DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)),
DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)),
"previous declaration of `%s'",
IDENTIFIER_POINTER (name));
TREE_THIS_VOLATILE (name) = 1;
}
if (t != 0 && duplicate_decls (x, t, different_binding_level)) /* Subroutine of pushdecl.
{
if (TREE_CODE (t) == PARM_DECL)
{
/* Don't allow more than one "real" duplicate
of a forward parm decl. */
TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
return t;
}
return t;
}
/* If we are processing a typedef statement, generate a whole new X is a TYPE_DECL for a typedef statement. Create a brand new
..._TYPE node (which will be just a variant of the existing ..._TYPE node (which will be just a variant of the existing
..._TYPE node with identical properties) and then install the ..._TYPE node with identical properties) and then install X
TYPE_DECL node generated to represent the typedef name as the as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
TYPE_NAME of this brand new (duplicate) ..._TYPE node.
The whole point here is to end up with a situation where each The whole point here is to end up with a situation where each
and every ..._TYPE node the compiler creates will be uniquely and every ..._TYPE node the compiler creates will be uniquely
...@@ -1784,8 +1656,10 @@ pushdecl (x) ...@@ -1784,8 +1656,10 @@ pushdecl (x)
in the source file, we can easily check to see if we are working in the source file, we can easily check to see if we are working
on a standard type by checking the current value of lineno. */ on a standard type by checking the current value of lineno. */
if (TREE_CODE (x) == TYPE_DECL) static void
{ clone_underlying_type (x)
tree x;
{
if (DECL_SOURCE_LINE (x) == 0) if (DECL_SOURCE_LINE (x) == 0)
{ {
if (TYPE_NAME (TREE_TYPE (x)) == 0) if (TYPE_NAME (TREE_TYPE (x)) == 0)
...@@ -1801,201 +1675,93 @@ pushdecl (x) ...@@ -1801,201 +1675,93 @@ pushdecl (x)
TREE_USED (tt) = TREE_USED (x); TREE_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt; TREE_TYPE (x) = tt;
} }
} }
/* Multiple external decls of the same identifier ought to match.
We get warnings about inline functions where they are defined.
Avoid duplicate warnings where they are used. */
if (TREE_PUBLIC (x)
&& ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
{
tree decl;
if (IDENTIFIER_LIMBO_VALUE (name) != 0)
/* Decls in limbo are always extern, so no need to check that. */
decl = IDENTIFIER_LIMBO_VALUE (name);
else
decl = 0;
if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
/* If old decl is built-in, we already warned if we should. */
&& !DECL_BUILT_IN (decl))
{
pedwarn_with_decl (x,
"type mismatch with previous external decl");
pedwarn_with_decl (decl, "previous external decl of `%s'");
}
}
/* If a function has had an implicit declaration, and then is defined,
make sure they are compatible. */
if (IDENTIFIER_IMPLICIT_DECL (name) != 0 /* Record a decl-node X as belonging to the current lexical scope.
&& IDENTIFIER_GLOBAL_VALUE (name) == 0 Check for errors (such as an incompatible declaration for the same
&& TREE_CODE (x) == FUNCTION_DECL name already seen in the same scope).
&& ! comptypes (TREE_TYPE (x),
TREE_TYPE (IDENTIFIER_IMPLICIT_DECL (name))))
{
warning_with_decl (x, "type mismatch with previous implicit declaration");
warning_with_decl (IDENTIFIER_IMPLICIT_DECL (name),
"previous implicit declaration of `%s'");
}
/* This name is new in its binding level. Returns either X or an old decl for the same name.
Install the new declaration and return it. */ If an old decl is returned, it may have been smashed
if (b == global_binding_level) to agree with what X says. */
{
/* Install a global value. */
/* If the first global decl has external linkage, tree
warn if we later see static one. */ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x)) tree x;
TREE_PUBLIC (name) = 1; {
tree name = DECL_NAME (x);
struct binding_level *scope = current_binding_level;
IDENTIFIER_GLOBAL_VALUE (name) = x; #ifdef ENABLE_CHECKING
if (error_mark_node == 0)
/* Called too early. */
abort ();
#endif
/* We no longer care about any previous block level declarations. */ /* Functions need the lang_decl data. */
IDENTIFIER_LIMBO_VALUE (name) = 0; if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
ggc_alloc_cleared (sizeof (struct lang_decl));
/* Don't forget if the function was used via an implicit decl. */ /* A local extern declaration for a function doesn't constitute nesting.
if (IDENTIFIER_IMPLICIT_DECL (name) A local auto declaration does, since it's a forward decl
&& TREE_USED (IDENTIFIER_IMPLICIT_DECL (name))) for a nested function coming later. */
TREE_USED (x) = 1, TREE_USED (name) = 1; if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
else
DECL_CONTEXT (x) = current_function_decl;
/* Don't forget if its address was taken in that way. */ if (name)
if (IDENTIFIER_IMPLICIT_DECL (name) {
&& TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name))) tree old;
TREE_ADDRESSABLE (x) = 1;
/* Warn about mismatches against previous implicit decl. */ if (warn_nested_externs
if (IDENTIFIER_IMPLICIT_DECL (name) != 0 && scope != global_binding_level
/* If this real decl matches the implicit, don't complain. */ && DECL_EXTERNAL (x)
&& ! (TREE_CODE (x) == FUNCTION_DECL && !DECL_IN_SYSTEM_HEADER (x))
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x))) warning ("nested extern declaration of `%s'",
== integer_type_node)))
pedwarn ("`%s' was previously implicitly declared to return `int'",
IDENTIFIER_POINTER (name)); IDENTIFIER_POINTER (name));
/* If this decl is `static' and an `extern' was seen previously, old = lookup_name_current_level (name);
that is erroneous. */ if (old && duplicate_decls (x, old, 0))
if (TREE_PUBLIC (name) return old;
&& ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x)) if (DECL_EXTERNAL (x) || scope == global_binding_level)
{ {
/* Okay to redeclare an ANSI built-in as static. */ /* Find and check against a previous, not-in-scope, external
if (t != 0 && DECL_BUILT_IN (t)) decl for this identifier. (C99 s???: If two declarations
; with external linkage, referring to the same object, have
/* Okay to declare a non-ANSI built-in as anything. */ incompatible types, the behavior is undefined). */
else if (t != 0 && DECL_BUILT_IN_NONANSI (t)) tree ext = any_external_decl (name);
; if (ext)
/* Okay to have global type decl after an earlier extern
declaration inside a lexical block. */
else if (TREE_CODE (x) == TYPE_DECL)
;
else if (IDENTIFIER_IMPLICIT_DECL (name))
{ {
if (! TREE_THIS_VOLATILE (name)) if (duplicate_decls (x, ext, scope != global_binding_level))
pedwarn ("`%s' was declared implicitly `extern' and later `static'", x = copy_node (ext);
IDENTIFIER_POINTER (name));
} }
else else
pedwarn ("`%s' was declared `extern' and later `static'", record_external_decl (x);
IDENTIFIER_POINTER (name));
}
} }
else
{
/* Here to install a non-global value. */
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
IDENTIFIER_LOCAL_VALUE (name) = x;
/* If this is an extern function declaration, see if we if (TREE_CODE (x) == TYPE_DECL)
have a global definition or declaration for the function. */ clone_underlying_type (x);
if (oldlocal == 0
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL
&& DECL_EXTERNAL (x)
&& ! DECL_DECLARED_INLINE_P (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (x),
TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name))))
pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one");
else
{
/* Inner extern decl is inline if global one is.
Copy enough to really inline it. */
if (DECL_DECLARED_INLINE_P (oldglobal))
{
DECL_DECLARED_INLINE_P (x)
= DECL_DECLARED_INLINE_P (oldglobal);
DECL_INLINE (x) = DECL_INLINE (oldglobal);
DECL_INITIAL (x) = (current_function_decl == oldglobal
? 0 : DECL_INITIAL (oldglobal));
DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
DECL_NUM_STMTS (x) = DECL_NUM_STMTS (oldglobal);
DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
DECL_RESULT (x) = DECL_RESULT (oldglobal);
TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
DECL_ABSTRACT_ORIGIN (x)
= DECL_ABSTRACT_ORIGIN (oldglobal);
}
/* Inner extern decl is built-in if global one is. */
if (DECL_BUILT_IN (oldglobal))
{
DECL_BUILT_IN_CLASS (x) = DECL_BUILT_IN_CLASS (oldglobal);
DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
/* Keep the arg types from a file-scope fcn defn. */
if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0
&& DECL_INITIAL (oldglobal)
&& TYPE_ARG_TYPES (TREE_TYPE (x)) == 0)
TREE_TYPE (x) = TREE_TYPE (oldglobal);
}
}
#if 0
/* This case is probably sometimes the right thing to do. */
/* If we have a local external declaration,
then any file-scope declaration should not
have been static. */
if (oldlocal == 0 && oldglobal != 0
&& !TREE_PUBLIC (oldglobal)
&& DECL_EXTERNAL (x) && TREE_PUBLIC (x))
warning ("`%s' locally external but globally static",
IDENTIFIER_POINTER (name));
#endif
/* If we have a local external declaration, /* If storing a local value, there may already be one
and no file-scope declaration has yet been seen, (inherited). If so, record it for restoration when this
then if we later have a file-scope decl it must not be static. */ binding level ends. Take care not to do this if we are
if (oldlocal == 0 replacing an older decl in the same binding level (i.e.
&& DECL_EXTERNAL (x) duplicate_decls returned false, above). */
&& TREE_PUBLIC (x)) if (scope != global_binding_level
&& IDENTIFIER_SYMBOL_VALUE (name)
&& IDENTIFIER_SYMBOL_VALUE (name) != old)
{ {
if (oldglobal == 0) warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name));
TREE_PUBLIC (name) = 1; scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
scope->shadowed);
/* Save this decl, so that we can do type checking against
other decls after it falls out of scope.
Only save it once. This prevents temporary decls created in
expand_inline_function from being used here, since this
will have been set when the inline function was parsed.
It also helps give slightly better warnings. */
if (IDENTIFIER_LIMBO_VALUE (name) == 0)
IDENTIFIER_LIMBO_VALUE (name) = x;
} }
warn_if_shadowing (x, oldlocal); /* Install the new declaration in the requested binding level. */
IDENTIFIER_SYMBOL_VALUE (name) = x;
/* If storing a local value, there may already be one (inherited). C_DECL_INVISIBLE (x) = 0;
If so, record it for restoration when this binding level ends. */
if (oldlocal != 0)
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
}
/* Keep list of variables in this level with incomplete type. /* Keep list of variables in this level with incomplete type.
If the input is erroneous, we can have error_mark in the type If the input is erroneous, we can have error_mark in the type
...@@ -2010,96 +1776,131 @@ pushdecl (x) ...@@ -2010,96 +1776,131 @@ pushdecl (x)
element = TREE_TYPE (element); element = TREE_TYPE (element);
if (TREE_CODE (element) == RECORD_TYPE if (TREE_CODE (element) == RECORD_TYPE
|| TREE_CODE (element) == UNION_TYPE) || TREE_CODE (element) == UNION_TYPE)
b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list); scope->incomplete_list = tree_cons (NULL_TREE, x,
scope->incomplete_list);
} }
} }
/* Put decls on list in reverse order. /* Put decls on list in reverse order.
We will reverse them later if necessary. */ We will reverse them later if necessary. */
TREE_CHAIN (x) = b->names; TREE_CHAIN (x) = scope->names;
b->names = x; scope->names = x;
return x; return x;
} }
/* Record that the local value of NAME is shadowed at function scope. /* Record X as belonging to the global scope (C99 "file scope").
This is used by build_external_ref in c-typeck.c. */ This is used only internally by the Objective C front end,
void and is limited to its needs. It will hork if there is _any_
record_function_scope_shadow (name) visible binding for X (not just a global one). */
tree name; tree
pushdecl_top_level (x)
tree x;
{ {
struct binding_level *b = get_function_binding_level (); tree name, old;
b->shadowed = tree_cons (name, IDENTIFIER_LOCAL_VALUE (name),
b->shadowed); if (TREE_CODE (x) != VAR_DECL)
} abort ();
/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */ name = DECL_NAME (x);
old = IDENTIFIER_SYMBOL_VALUE (name);
if (old)
{
if (DECL_CONTEXT (old))
abort ();
if (!duplicate_decls (x, old, 0))
abort ();
return old;
}
DECL_CONTEXT (x) = 0;
IDENTIFIER_SYMBOL_VALUE (name) = x;
TREE_CHAIN (x) = global_binding_level->names;
global_binding_level->names = x;
return x;
}
/* Record X as belonging to the outermost scope of the current
function. This is used only internally, by c_make_fname_decl and
build_external_ref, and is limited to their needs. The NAME is
provided as a separate argument because build_external_ref wants to
use error_mark_node for X. For VAR_DECLs, duplicate_decls is not
called; if there is any preexisting decl for this identifier, it is
an ICE. */
tree tree
pushdecl_top_level (x) pushdecl_function_level (x, name)
tree x; tree x;
tree name;
{ {
tree t; struct binding_level *scope;
struct binding_level *b = current_binding_level;
current_binding_level = global_binding_level; scope = current_binding_level;
t = pushdecl (x); while (scope->function_body == 0)
current_binding_level = b; scope = scope->level_chain;
return t; if (!scope)
abort ();
if (x == error_mark_node)
scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
scope->shadowed);
else if (TREE_CODE (x) == VAR_DECL)
{
if (name != DECL_NAME (x))
abort ();
if (IDENTIFIER_SYMBOL_VALUE (name))
abort ();
DECL_CONTEXT (x) = current_function_decl;
TREE_CHAIN (x) = scope->names;
scope->names = x;
}
IDENTIFIER_SYMBOL_VALUE (name) = x;
return x;
} }
/* Generate an implicit declaration for identifier FUNCTIONID /* Generate an implicit declaration for identifier FUNCTIONID as a
as a function of type int (). Print a warning if appropriate. */ function of type int (). */
tree tree
implicitly_declare (functionid) implicitly_declare (functionid)
tree functionid; tree functionid;
{ {
tree decl; tree decl = any_external_decl (functionid);
int traditional_warning = 0;
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
/* We used to reuse an old implicit decl here, if (decl && decl != error_mark_node)
but this loses with inline functions because it can clobber {
the saved decl chains. */ /* Implicit declaration of a function already declared
#if 0 (somehow) in a different scope, or as a built-in.
if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0) If this is the first time this has happened, warn;
decl = IDENTIFIER_IMPLICIT_DECL (functionid); then recycle the old declaration. */
else if (!C_DECL_IMPLICIT (decl))
#endif {
decl = build_decl (FUNCTION_DECL, functionid, default_function_type); implicit_decl_warning (DECL_NAME (decl));
if (DECL_CONTEXT (decl))
/* Warn of implicit decl following explicit local extern decl. warning_with_decl (decl, "previous declaration of `%s'");
This is probably a program designed for traditional C. */ C_DECL_IMPLICIT (decl) = 1;
if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0) }
traditional_warning = 1; return pushdecl (decl);
}
/* Warn once of an implicit declaration. */
implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0);
/* Not seen before. */
decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
DECL_EXTERNAL (decl) = 1; DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
C_DECL_IMPLICIT (decl) = 1;
/* Record that we have an implicit decl and this is it. */ implicit_decl_warning (functionid);
IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
/* ANSI standard says implicit declarations are in the innermost block. /* ANSI standard says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */ So we record the decl in the standard fashion. */
pushdecl (decl); decl = pushdecl (decl);
/* This is a no-op in c-lang.c or something real in objc-act.c. */
if (flag_objc)
objc_check_decl (decl);
/* No need to call objc_check_decl here - it's a function type. */
rest_of_decl_compilation (decl, NULL, 0, 0); rest_of_decl_compilation (decl, NULL, 0, 0);
if (implicit_warning)
implicit_decl_warning (functionid);
else if (warn_traditional && traditional_warning)
warning ("function `%s' was previously declared within a block",
IDENTIFIER_POINTER (functionid));
/* Write a record describing this implicit function declaration to the /* Write a record describing this implicit function declaration to the
prototypes file (if requested). */ prototypes file (if requested). */
...@@ -2111,7 +1912,7 @@ implicitly_declare (functionid) ...@@ -2111,7 +1912,7 @@ implicitly_declare (functionid)
return decl; return decl;
} }
void static void
implicit_decl_warning (id) implicit_decl_warning (id)
tree id; tree id;
{ {
...@@ -2353,37 +2154,42 @@ storetags (tags) ...@@ -2353,37 +2154,42 @@ storetags (tags)
/* Given NAME, an IDENTIFIER_NODE, /* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name. return the structure (or union or enum) definition for that name.
Searches binding levels from BINDING_LEVEL up to the global level. If THISLEVEL_ONLY is nonzero, searches only the current_binding_level.
If THISLEVEL_ONLY is nonzero, searches only the specified context
(but skips any tag-transparent contexts to find one that is
meaningful for tags).
CODE says which kind of type the caller wants; CODE says which kind of type the caller wants;
it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE. it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
If the wrong kind of type is found, an error is reported. */ If the wrong kind of type is found, an error is reported. */
static tree static tree
lookup_tag (code, name, binding_level, thislevel_only) lookup_tag (code, name, thislevel_only)
enum tree_code code; enum tree_code code;
struct binding_level *binding_level;
tree name; tree name;
int thislevel_only; int thislevel_only;
{ {
struct binding_level *level; tree tag = IDENTIFIER_TAG_VALUE (name);
int thislevel = 1; int thislevel = 0;
for (level = binding_level; level; level = level->level_chain) if (!tag)
{ return 0;
tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) /* We only care about whether it's in this level if
{ thislevel_only was set or it might be a type clash. */
if (TREE_PURPOSE (tail) == name) if (thislevel_only || TREE_CODE (tag) != code)
{ {
if (TREE_CODE (TREE_VALUE (tail)) != code) if (current_binding_level == global_binding_level
|| purpose_member (name, current_binding_level->tags))
thislevel = 1;
}
if (thislevel_only && !thislevel)
return 0;
if (TREE_CODE (tag) != code)
{ {
/* Definition isn't the kind we were looking for. */ /* Definition isn't the kind we were looking for. */
pending_invalid_xref = name; pending_invalid_xref = name;
pending_invalid_xref_file = input_filename; pending_invalid_xref_file = input_filename;
pending_invalid_xref_line = lineno; pending_invalid_xref_line = lineno;
/* If in the same binding level as a declaration as a tag /* If in the same binding level as a declaration as a tag
of a different type, this must not be allowed to of a different type, this must not be allowed to
shadow that tag, so give the error immediately. shadow that tag, so give the error immediately.
...@@ -2391,17 +2197,7 @@ lookup_tag (code, name, binding_level, thislevel_only) ...@@ -2391,17 +2197,7 @@ lookup_tag (code, name, binding_level, thislevel_only)
if (thislevel) if (thislevel)
pending_xref_error (); pending_xref_error ();
} }
return TREE_VALUE (tail); return tag;
}
}
if (! level->tag_transparent)
{
if (thislevel_only)
return NULL_TREE;
thislevel = 0;
}
}
return NULL_TREE;
} }
/* Print an error message now /* Print an error message now
...@@ -2420,26 +2216,6 @@ pending_xref_error () ...@@ -2420,26 +2216,6 @@ pending_xref_error ()
pending_invalid_xref = 0; pending_invalid_xref = 0;
} }
/* Given a type, find the tag that was defined for it and return the tag name.
Otherwise return 0. */
static tree
lookup_tag_reverse (type)
tree type;
{
struct binding_level *level;
for (level = current_binding_level; level; level = level->level_chain)
{
tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_VALUE (tail) == type)
return TREE_PURPOSE (tail);
}
}
return NULL_TREE;
}
/* Look up NAME in the current binding level and its superiors /* Look up NAME in the current binding level and its superiors
in the namespace of variables, functions and typedefs. in the namespace of variables, functions and typedefs.
...@@ -2450,35 +2226,33 @@ tree ...@@ -2450,35 +2226,33 @@ tree
lookup_name (name) lookup_name (name)
tree name; tree name;
{ {
tree val; tree decl = IDENTIFIER_SYMBOL_VALUE (name);
if (decl == 0 || decl == error_mark_node)
if (current_binding_level != global_binding_level return decl;
&& IDENTIFIER_LOCAL_VALUE (name)) if (C_DECL_INVISIBLE (decl))
val = IDENTIFIER_LOCAL_VALUE (name); return 0;
else return decl;
val = IDENTIFIER_GLOBAL_VALUE (name);
return val;
} }
/* Similar to `lookup_name' but look only at current binding level. */ /* Similar to `lookup_name' but look only at the current binding level. */
tree static tree
lookup_name_current_level (name) lookup_name_current_level (name)
tree name; tree name;
{ {
tree t; tree decl = IDENTIFIER_SYMBOL_VALUE (name);
if (current_binding_level == global_binding_level) if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
return IDENTIFIER_GLOBAL_VALUE (name);
if (IDENTIFIER_LOCAL_VALUE (name) == 0)
return 0; return 0;
for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) if (current_binding_level == global_binding_level)
if (DECL_NAME (t) == name) return decl;
break;
return t; /* Scan the current scope for a decl with name NAME. */
if (chain_member (decl, current_binding_level->names))
return decl;
return 0;
} }
/* Create the predefined scalar types of C, /* Create the predefined scalar types of C,
...@@ -2558,8 +2332,6 @@ c_make_fname_decl (id, type_dep) ...@@ -2558,8 +2332,6 @@ c_make_fname_decl (id, type_dep)
build_index_type (size_int (length))); build_index_type (size_int (length)));
decl = build_decl (VAR_DECL, id, type); decl = build_decl (VAR_DECL, id, type);
/* We don't push the decl, so have to set its context here. */
DECL_CONTEXT (decl) = current_function_decl;
TREE_STATIC (decl) = 1; TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1; TREE_READONLY (decl) = 1;
...@@ -2572,13 +2344,7 @@ c_make_fname_decl (id, type_dep) ...@@ -2572,13 +2344,7 @@ c_make_fname_decl (id, type_dep)
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
if (current_function_decl) if (current_function_decl)
{ pushdecl_function_level (decl, DECL_NAME (decl));
/* Add the decls to the outermost block. */
struct binding_level *old = current_binding_level;
current_binding_level = get_function_binding_level ();
pushdecl (decl);
current_binding_level = old;
}
finish_decl (decl, init, NULL_TREE); finish_decl (decl, init, NULL_TREE);
...@@ -2616,7 +2382,7 @@ builtin_function (name, type, function_code, class, library_name, attrs) ...@@ -2616,7 +2382,7 @@ builtin_function (name, type, function_code, class, library_name, attrs)
/* Warn if a function in the namespace for users /* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */ is used without an occasion to consider it declared. */
if (name[0] != '_' || name[1] != '_') if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1; C_DECL_INVISIBLE (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */ /* Possibly apply some default attributes to this built-in function. */
if (attrs) if (attrs)
...@@ -2680,7 +2446,7 @@ shadow_tag_warned (declspecs, warned) ...@@ -2680,7 +2446,7 @@ shadow_tag_warned (declspecs, warned)
/* Used to test also that TYPE_SIZE (value) != 0. /* Used to test also that TYPE_SIZE (value) != 0.
That caused warning for `struct foo;' at top level in the file. */ That caused warning for `struct foo;' at top level in the file. */
{ {
tree name = lookup_tag_reverse (value); tree name = TYPE_NAME (value);
tree t; tree t;
found_tag++; found_tag++;
...@@ -2696,7 +2462,7 @@ shadow_tag_warned (declspecs, warned) ...@@ -2696,7 +2462,7 @@ shadow_tag_warned (declspecs, warned)
} }
else else
{ {
t = lookup_tag (code, name, current_binding_level, 1); t = lookup_tag (code, name, 1);
if (t == 0) if (t == 0)
{ {
...@@ -4950,7 +4716,7 @@ xref_tag (code, name) ...@@ -4950,7 +4716,7 @@ xref_tag (code, name)
/* If a cross reference is requested, look up the type /* If a cross reference is requested, look up the type
already defined for this tag and return it. */ already defined for this tag and return it. */
tree ref = lookup_tag (code, name, current_binding_level, 0); tree ref = lookup_tag (code, name, 0);
/* If this is the right type of tag, return what we found. /* If this is the right type of tag, return what we found.
(This reference will be shadowed by shadow_tag later if appropriate.) (This reference will be shadowed by shadow_tag later if appropriate.)
If this is the wrong type of tag, do not return it. If it was the If this is the wrong type of tag, do not return it. If it was the
...@@ -5004,7 +4770,7 @@ start_struct (code, name) ...@@ -5004,7 +4770,7 @@ start_struct (code, name)
tree ref = 0; tree ref = 0;
if (name != 0) if (name != 0)
ref = lookup_tag (code, name, current_binding_level, 1); ref = lookup_tag (code, name, 1);
if (ref && TREE_CODE (ref) == code) if (ref && TREE_CODE (ref) == code)
{ {
if (TYPE_FIELDS (ref)) if (TYPE_FIELDS (ref))
...@@ -5432,7 +5198,7 @@ start_enum (name) ...@@ -5432,7 +5198,7 @@ start_enum (name)
forward reference. */ forward reference. */
if (name != 0) if (name != 0)
enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1); enumtype = lookup_tag (ENUMERAL_TYPE, name, 1);
if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE) if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{ {
...@@ -5750,27 +5516,16 @@ start_function (declspecs, declarator, attributes) ...@@ -5750,27 +5516,16 @@ start_function (declspecs, declarator, attributes)
current_function_prototype_line = DECL_SOURCE_LINE (old_decl); current_function_prototype_line = DECL_SOURCE_LINE (old_decl);
} }
/* If there is no explicit declaration, look for any out-of-scope implicit
declarations. */
if (old_decl == 0)
old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1));
/* Optionally warn of old-fashioned def with no previous prototype. */ /* Optionally warn of old-fashioned def with no previous prototype. */
if (warn_strict_prototypes if (warn_strict_prototypes
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
&& !(old_decl != 0 && C_DECL_ISNT_PROTOTYPE (old_decl))
&& (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
|| (DECL_BUILT_IN (old_decl)
&& ! C_DECL_ANTICIPATED (old_decl)))))
warning ("function declaration isn't a prototype"); warning ("function declaration isn't a prototype");
/* Optionally warn of any global def with no previous prototype. */ /* Optionally warn of any global def with no previous prototype. */
else if (warn_missing_prototypes else if (warn_missing_prototypes
&& TREE_PUBLIC (decl1) && TREE_PUBLIC (decl1)
&& !(old_decl != 0 && ! MAIN_NAME_P (DECL_NAME (decl1))
&& (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0 && C_DECL_ISNT_PROTOTYPE (old_decl))
|| (DECL_BUILT_IN (old_decl)
&& ! C_DECL_ANTICIPATED (old_decl))))
&& ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous prototype for `%s'"); warning_with_decl (decl1, "no previous prototype for `%s'");
/* Optionally warn of any def with no previous prototype /* Optionally warn of any def with no previous prototype
if the function has already been used. */ if the function has already been used. */
...@@ -5789,7 +5544,7 @@ start_function (declspecs, declarator, attributes) ...@@ -5789,7 +5544,7 @@ start_function (declspecs, declarator, attributes)
if the function has already been used. */ if the function has already been used. */
else if (warn_missing_declarations else if (warn_missing_declarations
&& old_decl != 0 && TREE_USED (old_decl) && old_decl != 0 && TREE_USED (old_decl)
&& old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))) && C_DECL_IMPLICIT (old_decl))
warning_with_decl (decl1, warning_with_decl (decl1,
"`%s' was used with no declaration before its definition"); "`%s' was used with no declaration before its definition");
...@@ -5872,7 +5627,6 @@ start_function (declspecs, declarator, attributes) ...@@ -5872,7 +5627,6 @@ start_function (declspecs, declarator, attributes)
pushlevel (0); pushlevel (0);
declare_parm_level (1); declare_parm_level (1);
current_binding_level->subblocks_tag_transparent = 1;
make_decl_rtl (current_function_decl, NULL); make_decl_rtl (current_function_decl, NULL);
...@@ -5965,10 +5719,10 @@ store_parm_decls () ...@@ -5965,10 +5719,10 @@ store_parm_decls ()
for (decl = current_binding_level->names; for (decl = current_binding_level->names;
decl; decl = TREE_CHAIN (decl)) decl; decl = TREE_CHAIN (decl))
if (DECL_NAME (decl)) if (DECL_NAME (decl))
IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0; IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = 0;
for (link = current_binding_level->shadowed; for (link = current_binding_level->shadowed;
link; link = TREE_CHAIN (link)) link; link = TREE_CHAIN (link))
IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
current_binding_level->names = 0; current_binding_level->names = 0;
current_binding_level->shadowed = 0; current_binding_level->shadowed = 0;
} }
...@@ -6347,13 +6101,27 @@ finish_function (nested, can_defer_p) ...@@ -6347,13 +6101,27 @@ finish_function (nested, can_defer_p)
{ {
tree fndecl = current_function_decl; tree fndecl = current_function_decl;
/* When a function declaration is totally empty, e.g.
void foo(void) { }
(the argument list is irrelevant) the compstmt rule will not
bother calling pushlevel/poplevel, which means we get here with
the binding_level stack out of sync. Detect this situation by
noticing that the current_binding_level 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 binding level - see there for details. */
if (current_binding_level->parm_flag && keep_next_if_subblocks)
{
pushlevel (0);
poplevel (1, 0, 1);
}
#if 0 #if 0
/* This caused &foo to be of type ptr-to-const-function which then /* This caused &foo to be of type ptr-to-const-function which then
got a warning when stored in a ptr-to-function variable. */ got a warning when stored in a ptr-to-function variable. */
TREE_READONLY (fndecl) = 1; TREE_READONLY (fndecl) = 1;
#endif #endif
poplevel (1, 0, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
/* Must mark the RESULT_DECL as being in this function. */ /* Must mark the RESULT_DECL as being in this function. */
...@@ -6918,14 +6686,23 @@ c_expand_decl_stmt (t) ...@@ -6918,14 +6686,23 @@ c_expand_decl_stmt (t)
c_expand_body_1 (decl, 1); c_expand_body_1 (decl, 1);
} }
/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since /* Return the global value of T as a symbol. */
the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++. */
tree tree
identifier_global_value (t) identifier_global_value (t)
tree t; tree t;
{ {
return IDENTIFIER_GLOBAL_VALUE (t); tree decl = IDENTIFIER_SYMBOL_VALUE (t);
if (decl == 0 || DECL_CONTEXT (decl) == 0)
return decl;
/* Shadowed by something else; find the true global value. */
for (decl = global_binding_level->names; decl; decl = TREE_CHAIN (decl))
if (DECL_NAME (decl) == t)
return decl;
/* Only local values for this decl. */
return 0;
} }
/* Record a builtin type for C. If NAME is non-NULL, it is the name used; /* Record a builtin type for C. If NAME is non-NULL, it is the name used;
......
/* Definitions for C parsing and type checking. /* Definitions for C parsing and type checking.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998, Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
1999, 2000, 2001, 2002 Free Software Foundation, Inc. 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -37,11 +37,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -37,11 +37,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
struct lang_identifier GTY(()) struct lang_identifier GTY(())
{ {
struct c_common_identifier common_id; struct c_common_identifier common_id;
tree global_value; tree symbol_value;
tree local_value; tree tag_value;
tree label_value; tree label_value;
tree implicit_decl;
tree limbo_value;
}; };
/* The resulting tree type. */ /* The resulting tree type. */
...@@ -70,26 +68,17 @@ struct lang_decl GTY(()) ...@@ -70,26 +68,17 @@ struct lang_decl GTY(())
/* Macros for access to language-specific slots in an identifier. */ /* Macros for access to language-specific slots in an identifier. */
/* Each of these slots contains a DECL node or null. */ /* Each of these slots contains a DECL node or null. */
/* This represents the value which the identifier has in the /* The value of the identifier in the namespace of "ordinary identifiers"
file-scope namespace. */ (data objects, enum constants, functions, typedefs). */
#define IDENTIFIER_GLOBAL_VALUE(NODE) \ #define IDENTIFIER_SYMBOL_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->global_value) (((struct lang_identifier *) (NODE))->symbol_value)
/* This represents the value which the identifier has in the current /* The value of the identifier in the namespace of struct, union,
scope. */ and enum tags. */
#define IDENTIFIER_LOCAL_VALUE(NODE) \ #define IDENTIFIER_TAG_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->local_value) (((struct lang_identifier *) (NODE))->tag_value)
/* This represents the value which the identifier has as a label in /* The value of the identifier in the namespace of labels. */
the current label scope. */
#define IDENTIFIER_LABEL_VALUE(NODE) \ #define IDENTIFIER_LABEL_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->label_value) (((struct lang_identifier *) (NODE))->label_value)
/* This records the extern decl of this identifier, if it has had one
at any point in this compilation. */
#define IDENTIFIER_LIMBO_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->limbo_value)
/* This records the implicit function decl of this identifier, if it
has had one at any point in this compilation. */
#define IDENTIFIER_IMPLICIT_DECL(NODE) \
(((struct lang_identifier *) (NODE))->implicit_decl)
/* In identifiers, C uses the following fields in a special way: /* In identifiers, C uses the following fields in a special way:
TREE_PUBLIC to record that there was a previous local extern decl. TREE_PUBLIC to record that there was a previous local extern decl.
...@@ -129,13 +118,6 @@ struct lang_type GTY(()) ...@@ -129,13 +118,6 @@ struct lang_type GTY(())
#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE) #define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
#define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE) #define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
#if 0 /* Not used. */
/* Record whether a decl for a function or function pointer has
already been mentioned (in a warning) because it was called
but didn't have a prototype. */
#define C_MISSING_PROTOTYPE_WARNED(DECL) DECL_LANG_FLAG_2 (DECL)
#endif
/* Store a value in that field. */ /* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \ #define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \
(TREE_COMPLEXITY (EXP) = (int) (CODE)) (TREE_COMPLEXITY (EXP) = (int) (CODE))
...@@ -147,10 +129,22 @@ struct lang_type GTY(()) ...@@ -147,10 +129,22 @@ struct lang_type GTY(())
return type. */ return type. */
#define C_FUNCTION_IMPLICIT_INT(EXP) DECL_LANG_FLAG_1 (EXP) #define C_FUNCTION_IMPLICIT_INT(EXP) DECL_LANG_FLAG_1 (EXP)
/* Nonzero for a declaration of a built in function if there has been no /* For a FUNCTION_DECL, nonzero if it was an implicit declaration. */
occasion that would declare the function in ordinary C. #define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
Using the function draws a pedantic warning in this case. */
#define C_DECL_ANTICIPATED(EXP) DECL_LANG_FLAG_3 (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)
/* 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
(but this is presently difficult because some of them need FILE*). */
#define C_DECL_ISNT_PROTOTYPE(EXP) \
(EXP == 0 \
|| (TYPE_ARG_TYPES (TREE_TYPE (EXP)) == 0 \
&& !DECL_BUILT_IN (EXP)))
/* For FUNCTION_TYPE, a hidden list of types of arguments. The same as /* For FUNCTION_TYPE, a hidden list of types of arguments. The same as
TYPE_ARG_TYPES for functions with prototypes, but created for functions TYPE_ARG_TYPES for functions with prototypes, but created for functions
...@@ -207,11 +201,9 @@ extern tree grokfield PARAMS ((const char *, int, tree ...@@ -207,11 +201,9 @@ extern tree grokfield PARAMS ((const char *, int, tree
extern tree groktypename PARAMS ((tree)); extern tree groktypename PARAMS ((tree));
extern tree groktypename_in_parm_context PARAMS ((tree)); extern tree groktypename_in_parm_context PARAMS ((tree));
extern tree implicitly_declare PARAMS ((tree)); extern tree implicitly_declare PARAMS ((tree));
extern void implicit_decl_warning PARAMS ((tree));
extern int in_parm_level_p PARAMS ((void)); extern int in_parm_level_p PARAMS ((void));
extern void keep_next_level PARAMS ((void)); extern void keep_next_level PARAMS ((void));
extern tree lookup_name PARAMS ((tree)); extern tree lookup_name PARAMS ((tree));
extern tree lookup_name_current_level PARAMS ((tree));
extern void parmlist_tags_warning PARAMS ((void)); extern void parmlist_tags_warning PARAMS ((void));
extern void pending_xref_error PARAMS ((void)); extern void pending_xref_error PARAMS ((void));
extern void c_push_function_context PARAMS ((struct function *)); extern void c_push_function_context PARAMS ((struct function *));
...@@ -220,8 +212,8 @@ extern void pop_label_level PARAMS ((void)); ...@@ -220,8 +212,8 @@ extern void pop_label_level PARAMS ((void));
extern void push_label_level PARAMS ((void)); extern void push_label_level PARAMS ((void));
extern void push_parm_decl PARAMS ((tree)); extern void push_parm_decl PARAMS ((tree));
extern tree pushdecl_top_level PARAMS ((tree)); extern tree pushdecl_top_level PARAMS ((tree));
extern tree pushdecl_function_level PARAMS ((tree, tree));
extern void pushtag PARAMS ((tree, tree)); extern void pushtag PARAMS ((tree, tree));
extern void record_function_scope_shadow PARAMS ((tree));
extern tree set_array_declarator_type PARAMS ((tree, tree, int)); extern tree set_array_declarator_type PARAMS ((tree, tree, int));
extern tree shadow_label PARAMS ((tree)); extern tree shadow_label PARAMS ((tree));
extern void shadow_tag PARAMS ((tree)); extern void shadow_tag PARAMS ((tree));
......
/* Build expressions with type checking for C compiler. /* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -59,6 +59,7 @@ static int type_lists_compatible_p PARAMS ((tree, tree)); ...@@ -59,6 +59,7 @@ static int type_lists_compatible_p PARAMS ((tree, tree));
static tree decl_constant_value_for_broken_optimization PARAMS ((tree)); static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
static tree default_function_array_conversion PARAMS ((tree)); static tree default_function_array_conversion PARAMS ((tree));
static tree lookup_field PARAMS ((tree, tree)); static tree lookup_field PARAMS ((tree, tree));
static void undeclared_variable PARAMS ((tree));
static tree convert_arguments PARAMS ((tree, tree, tree, tree)); static tree convert_arguments PARAMS ((tree, tree, tree, tree));
static tree pointer_diff PARAMS ((tree, tree)); static tree pointer_diff PARAMS ((tree, tree));
static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int)); static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int));
...@@ -1375,53 +1376,19 @@ build_array_ref (array, index) ...@@ -1375,53 +1376,19 @@ build_array_ref (array, index)
} }
} }
/* Build an external reference to identifier ID. FUN indicates /* Issue an error message for a reference to an undeclared variable ID,
whether this will be used for a function call. */ including a reference to a builtin outside of function-call context.
tree Arrange to suppress further errors for the same identifier. */
build_external_ref (id, fun) static void
undeclared_variable (id)
tree id; tree id;
int fun;
{ {
tree ref;
tree decl = lookup_name (id);
tree objc_ivar = lookup_objc_ivar (id);
if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
if (!decl || decl == error_mark_node || C_DECL_ANTICIPATED (decl))
{
if (objc_ivar)
ref = objc_ivar;
else if (fun)
{
if (!decl || decl == error_mark_node)
/* Ordinary implicit function declaration. */
ref = implicitly_declare (id);
else
{
/* Implicit declaration of built-in function. Don't
change the built-in declaration, but don't let this
go by silently, either. */
implicit_decl_warning (id);
/* only issue this warning once */
C_DECL_ANTICIPATED (decl) = 0;
ref = decl;
}
}
else
{
/* Don't complain about something that's already been
complained about. */
if (decl == error_mark_node)
return error_mark_node;
/* Reference to undeclared variable, including reference to
builtin outside of function-call context. */
if (current_function_decl == 0) if (current_function_decl == 0)
{
error ("`%s' undeclared here (not in a function)", error ("`%s' undeclared here (not in a function)",
IDENTIFIER_POINTER (id)); IDENTIFIER_POINTER (id));
IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
}
else else
{ {
error ("`%s' undeclared (first use in this function)", error ("`%s' undeclared (first use in this function)",
...@@ -1434,22 +1401,30 @@ build_external_ref (id, fun) ...@@ -1434,22 +1401,30 @@ build_external_ref (id, fun)
undeclared_variable_notice = 1; undeclared_variable_notice = 1;
} }
/* Set IDENTIFIER_LOCAL_VALUE (id) to error_mark_node and /* Set IDENTIFIER_SYMBOL_VALUE (id) to error_mark_node
add a function-scope shadow entry which will undo that. at function scope. This suppresses further warnings
This suppresses further warnings about this undeclared about this undeclared identifier in this function. */
identifier in this function. */ pushdecl_function_level (error_mark_node, id);
record_function_scope_shadow (id);
IDENTIFIER_LOCAL_VALUE (id) = error_mark_node;
}
return error_mark_node;
}
} }
else }
/* Build an external reference to identifier ID. FUN indicates
whether this will be used for a function call. */
tree
build_external_ref (id, fun)
tree id;
int fun;
{
tree ref;
tree decl = lookup_name (id);
tree objc_ivar = lookup_objc_ivar (id);
if (decl && decl != error_mark_node)
{ {
/* Properly declared variable or function reference. */ /* Properly declared variable or function reference. */
if (!objc_ivar) if (!objc_ivar)
ref = decl; ref = decl;
else if (decl != objc_ivar && IDENTIFIER_LOCAL_VALUE (id)) else if (decl != objc_ivar && DECL_CONTEXT (decl) != 0)
{ {
warning ("local declaration of `%s' hides instance variable", warning ("local declaration of `%s' hides instance variable",
IDENTIFIER_POINTER (id)); IDENTIFIER_POINTER (id));
...@@ -1458,10 +1433,27 @@ build_external_ref (id, fun) ...@@ -1458,10 +1433,27 @@ build_external_ref (id, fun)
else else
ref = objc_ivar; ref = objc_ivar;
} }
else if (objc_ivar)
ref = objc_ivar;
else if (fun)
/* Implicit function declaration. */
ref = implicitly_declare (id);
else if (decl == error_mark_node)
/* Don't complain about something that's already been
complained about. */
return error_mark_node;
else
{
undeclared_variable (id);
return error_mark_node;
}
if (TREE_TYPE (ref) == error_mark_node) if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node; return error_mark_node;
if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref);
if (!skip_evaluation) if (!skip_evaluation)
assemble_external (ref); assemble_external (ref);
TREE_USED (ref) = 1; TREE_USED (ref) = 1;
......
...@@ -239,6 +239,8 @@ scope_to_insns_initialize () ...@@ -239,6 +239,8 @@ scope_to_insns_initialize ()
break; break;
case NOTE_INSN_BLOCK_END: case NOTE_INSN_BLOCK_END:
block = BLOCK_SUPERCONTEXT (block); block = BLOCK_SUPERCONTEXT (block);
if (block && TREE_CODE (block) == FUNCTION_DECL)
block = 0;
delete_insn (insn); delete_insn (insn);
break; break;
default: default:
......
2003-04-10 Zack Weinberg <zack@codesourcery.com>
* decl.c: Update all calls to shadow_warning.
2003-04-10 Mark Mitchell <mark@codesourcery.com> 2003-04-10 Mark Mitchell <mark@codesourcery.com>
* class.c (layout_class_type): Correct handling for overlong * class.c (layout_class_type): Correct handling for overlong
......
...@@ -4001,7 +4001,7 @@ pushdecl (tree x) ...@@ -4001,7 +4001,7 @@ pushdecl (tree x)
} }
if (warn_shadow && !err) if (warn_shadow && !err)
shadow_warning (SW_PARAM, false, shadow_warning (SW_PARAM,
IDENTIFIER_POINTER (name), oldlocal); IDENTIFIER_POINTER (name), oldlocal);
} }
...@@ -4019,12 +4019,12 @@ pushdecl (tree x) ...@@ -4019,12 +4019,12 @@ pushdecl (tree x)
IDENTIFIER_POINTER (name)); IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL) && TREE_CODE (oldlocal) == VAR_DECL)
shadow_warning (SW_LOCAL, false, shadow_warning (SW_LOCAL,
IDENTIFIER_POINTER (name), oldlocal); IDENTIFIER_POINTER (name), oldlocal);
else if (oldglobal != NULL_TREE else if (oldglobal != NULL_TREE
&& TREE_CODE (oldglobal) == VAR_DECL) && TREE_CODE (oldglobal) == VAR_DECL)
/* XXX shadow warnings in outer-more namespaces */ /* XXX shadow warnings in outer-more namespaces */
shadow_warning (SW_GLOBAL, false, shadow_warning (SW_GLOBAL,
IDENTIFIER_POINTER (name), oldglobal); IDENTIFIER_POINTER (name), oldglobal);
} }
} }
......
...@@ -6000,10 +6000,16 @@ reorder_blocks_1 (insns, current_block, p_block_stack) ...@@ -6000,10 +6000,16 @@ reorder_blocks_1 (insns, current_block, p_block_stack)
BLOCK_SUBBLOCKS (block) = 0; BLOCK_SUBBLOCKS (block) = 0;
TREE_ASM_WRITTEN (block) = 1; TREE_ASM_WRITTEN (block) = 1;
/* When there's only one block for the entire function,
current_block == block and we mustn't do this, it
will cause infinite recursion. */
if (block != current_block)
{
BLOCK_SUPERCONTEXT (block) = current_block; BLOCK_SUPERCONTEXT (block) = current_block;
BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block); BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
BLOCK_SUBBLOCKS (current_block) = block; BLOCK_SUBBLOCKS (current_block) = block;
current_block = block; current_block = block;
}
VARRAY_PUSH_TREE (*p_block_stack, block); VARRAY_PUSH_TREE (*p_block_stack, block);
} }
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
......
...@@ -5298,8 +5298,8 @@ build_protocol_reference (p) ...@@ -5298,8 +5298,8 @@ build_protocol_reference (p)
objc_protocol_template), objc_protocol_template),
NULL_TREE)); NULL_TREE));
if (IDENTIFIER_GLOBAL_VALUE (ident)) if (identifier_global_value (ident))
decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */ decl = identifier_global_value (ident); /* Set by pushdecl. */
else else
{ {
decl = build_decl (VAR_DECL, ident, ptype); decl = build_decl (VAR_DECL, ident, ptype);
......
2003-04-10 Zack Weinberg <zack@codesourcery.com>
* gcc.c-torture/execute/builtin-noret-2.c: New.
* gcc.c-torture/execute/builtin-noret-2.x: New.
XFAIL builtin-noret-2.c at -O1 and above.
* gcc.dg/redecl.c: New.
* gcc.dg/Wshadow-1.c: Update error regexps.
2003-04-10 Mark Mitchell <mark@codesourcery.com> 2003-04-10 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/bitfield10.C: New test. * g++.dg/abi/bitfield10.C: New test.
......
/* Test for builtin noreturn attributes when the visible declarations
are function-local. Doesn't presently work. Modified from
builtin-noret-1.c by Zack Weinberg <zack@codesourcery.com>. */
extern void tabort (void);
extern void texit (void);
extern void t_exit (void);
extern void t_Exit (void);
extern void link_failure (void);
int
main (void)
{
volatile int i = 0;
/* The real test here is that the program links. */
if (i)
tabort ();
if (i)
texit ();
if (i)
t_exit ();
if (i)
t_Exit ();
exit (0);
}
void
tabort (void)
{
extern void abort (void);
abort ();
link_failure ();
}
void
texit (void)
{
extern void exit (int);
exit (1);
link_failure ();
}
void
t_exit (void)
{
extern void _exit (int);
_exit (1);
link_failure ();
}
/* Some non-Unix libcs might not have _exit. This version should never
get called. */
static void
_exit (int i)
{
abort ();
}
void
t_Exit (void)
{
extern void _Exit (int);
_Exit (1);
link_failure ();
}
/* Some libcs might not have _Exit. This version should never get called. */
static void
_Exit (int i)
{
abort ();
}
/* When optimizing, no calls to link_failure should remain. In any case,
link_failure should not be called. */
#ifndef __OPTIMIZE__
void
link_failure (void)
{
abort ();
}
#endif
# This test fails at -O1 and higher.
set torture_eval_before_compile {
global compiler_conditional_xfail_data
set compiler_conditional_xfail_data {
"Fails at all optimization levels but -O0, see PR10375." \
{ "*-*-*" } \
{ "-O*" } \
{ "-O0" }
}
}
return 0
...@@ -10,10 +10,10 @@ void foo (double decl1) /* { dg-warning "shadows a global decl" } */ ...@@ -10,10 +10,10 @@ void foo (double decl1) /* { dg-warning "shadows a global decl" } */
{ {
} }
void foo1 (int d) /* { dg-warning "shadowed declaration" } */ void foo1 (int d) /* { dg-warning "previous declaration" } */
{ {
double d; /* { dg-bogus "warning" "warning in place of error" } */ double d; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "shadows a parameter" "" { target *-*-* } 15 } */ /* { dg-error "redeclared as different" "" { target *-*-* } 15 } */
} }
void foo2 (int d) /* { dg-warning "shadowed declaration" } */ void foo2 (int d) /* { dg-warning "shadowed declaration" } */
......
/* Test for various situations where a new declaration of an
identifier conflicts with an earlier declaration which isn't in the
same scope. These are all undefined behavior per C89 sections
6.1.2.2p7, 6.1.2.6p2, and 6.3.2.2p2/footnote 38 (C99 6.2.2p7 and
6.2.7p2 - implicit declarations are invalid in C99). */
/* { dg-do compile } */
/* { dg-options "-std=c89 -pedantic -Wall -Wno-unused" } */
/* Extern at function scope, clashing with extern at file scope */
extern int foo1; /* { dg-error "previous" } */
extern int bar1(int); /* { dg-error "previous" } */
void test1(void)
{
extern double foo1; /* { dg-error "conflict" } */
extern double bar1(double); /* { dg-error "conflict" } */
}
/* Extern at file scope, clashing with extern at function scope */
void test2(void)
{
extern double foo2; /* { dg-error "previous" } */
extern double bar2(double); /* { dg-error "previous" } */
}
extern int foo2; /* { dg-error "conflict" } */
extern int bar2(int); /* { dg-error "conflict" } */
/* Extern at function scope, clashing with extern at earlier function
scope. Also, don't be fooled by a typedef at file scope. */
typedef float baz3; /* { dg-bogus } */
void prime3(void)
{
extern int foo3; /* { dg-error "previous" } */
extern int bar3(int); /* { dg-error "previous" } */
extern int baz3; /* { dg-error "previous" } */
}
void test3(void)
{
extern double foo3; /* { dg-error "conflict" } */
extern double bar3(double); /* { dg-error "conflict" } */
extern double baz3; /* { dg-error "conflict" } */
}
/* Extern at function scope, clashing with previous implicit decl. */
void prime4(void)
{
bar4(); /* { dg-error "previous|implicit" } */
}
void test4(void)
{
extern double bar4(double); /* { dg-error "conflict" } */
}
/* Implicit decl, clashing with extern at previous function scope. */
void prime5(void)
{
extern double bar5(double); /* { dg-error "previous" "" { xfail *-*-* } } */
}
void test5(void)
{
bar5(1); /* { dg-error "implicit" } */
}
/* Extern then static, both at file scope. */
extern int test6(int); /* { dg-warning "previous" "" { xfail *-*-* } } */
static int test6(int x)
{ return x; } /* { dg-warning "follows non-static" } */
/* Extern then static, extern at previous function scope. */
void prime7(void)
{
extern int test7(int); /* { dg-warning "previous" "" { xfail *-*-* } } */
}
static int test7(int x)
{ return x; } /* { dg-warning "follows non-static" } */
/* Implicit decl then static. */
void prime8(void)
{
test8(); /* { dg-warning "previous" "" { xfail *-*-* } } */
/* { dg-warning "implicit" "" { target *-*-* } 96 } */
}
static int test8(int x)
{ return x; } /* { dg-warning "follows non-static" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment