aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zack@codesourcery.com>2003-04-11 04:26:55 +0000
committerZack Weinberg <zack@gcc.gnu.org>2003-04-11 04:26:55 +0000
commit339a28b96a306cb323a66e9142ab090d36f42ba8 (patch)
tree17de84c82d5527a115d97db14a145ae19c48be07
parentb1e0a93ee513ccd9fa7d32947f2f568d379f358e (diff)
downloadgcc-339a28b96a306cb323a66e9142ab090d36f42ba8.zip
gcc-339a28b96a306cb323a66e9142ab090d36f42ba8.tar.gz
gcc-339a28b96a306cb323a66e9142ab090d36f42ba8.tar.bz2
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
-rw-r--r--gcc/ChangeLog105
-rw-r--r--gcc/c-common.c8
-rw-r--r--gcc/c-common.h2
-rw-r--r--gcc/c-decl.c1309
-rw-r--r--gcc/c-tree.h66
-rw-r--r--gcc/c-typeck.c114
-rw-r--r--gcc/cfglayout.c2
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/function.c14
-rw-r--r--gcc/objc/objc-act.c4
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.c84
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.x12
-rw-r--r--gcc/testsuite/gcc.dg/Wshadow-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/redecl-1.c101
16 files changed, 962 insertions, 881 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b156338..25ecc06 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,108 @@
+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>
* doc/extend.texi (Template Instantiation): Refer to ISO standard,
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 7048d9a..a2cad23 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4778,12 +4778,10 @@ c_common_insert_default_attributes (decl)
}
/* Output a -Wshadow warning MSGCODE about NAME, and give the location
- of the previous declaration DECL. MANDATORY says whether this is a
- mandatory warning (i.e. use pedwarn). */
+ of the previous declaration DECL. */
void
-shadow_warning (msgcode, mandatory, name, decl)
+shadow_warning (msgcode, name, decl)
enum sw_kind msgcode;
- int mandatory; /* really bool */
const char *name;
tree decl;
{
@@ -4793,7 +4791,7 @@ shadow_warning (msgcode, mandatory, name, decl)
/* 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),
DECL_SOURCE_LINE (decl),
"shadowed declaration is here");
diff --git a/gcc/c-common.h b/gcc/c-common.h
index ed67ce6f..432b351 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -335,7 +335,7 @@ extern tree c_begin_while_stmt PARAMS ((void));
extern void c_finish_while_stmt_cond PARAMS ((tree, tree));
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));
/* Extra information associated with a DECL. Other C dialects extend
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 20073080..4b2e6e1 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C compiler.
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.
@@ -122,6 +122,10 @@ static GTY(()) tree named_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
a return statement that specifies a return value is seen. */
@@ -159,9 +163,6 @@ static int current_extern_inline;
* 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(())
{
/* A chain of _DECL nodes for all variables, constants, functions,
@@ -177,35 +178,34 @@ struct binding_level GTY(())
*/
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.
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
tree shadowed;
+ /* For each 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),
a chain of BLOCK nodes for all the levels
that were entered and exited one level down. */
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). */
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;
- /* Nonzero if this level "doesn't exist" for tags. */
- char tag_transparent;
-
- /* Nonzero if sublevels of this level "don't exist" for tags.
- 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 if this is the outermost block scope of a function body.
+ This scope contains both the parameters and the local variables
+ declared in the outermost block. */
+ char function_body;
/* Nonzero means make a BLOCK for this level regardless of all else. */
char keep;
@@ -239,12 +239,6 @@ static GTY((deletable (""))) struct binding_level *free_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. */
static int keep_next_level_flag;
@@ -269,23 +263,24 @@ tree static_ctors, static_dtors;
/* Forward declarations. */
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 clear_limbo_values PARAMS ((tree));
static int duplicate_decls PARAMS ((tree, tree, int));
static int redeclaration_error_message PARAMS ((tree, tree));
+static void implicit_decl_warning PARAMS ((tree));
static void storedecls PARAMS ((tree));
static void storetags PARAMS ((tree));
-static tree lookup_tag PARAMS ((enum tree_code, tree,
- struct binding_level *, int));
-static tree lookup_tag_reverse PARAMS ((tree));
+static tree lookup_tag PARAMS ((enum tree_code, tree, int));
+static tree lookup_name_current_level PARAMS ((tree));
static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
int));
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl 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 clone_underlying_type PARAMS ((tree));
static bool flexible_array_type_p PARAMS ((tree));
/* States indicating how grokdeclarator() should handle declspecs marked
@@ -306,11 +301,9 @@ c_print_identifier (file, node, indent)
tree node;
int indent;
{
- print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
- print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
+ print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4);
+ print_node (file, "tag", IDENTIFIER_TAG_VALUE (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
- print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
- print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
if (C_IS_RESERVED_WORD (node))
{
tree rid = ridpointers[C_RID_CODE (node)];
@@ -350,25 +343,18 @@ c_finish_incomplete_decl (decl)
static struct binding_level *
make_binding_level ()
{
+ struct binding_level *result;
if (free_binding_level)
{
- struct binding_level *result = free_binding_level;
+ result = free_binding_level;
free_binding_level = result->level_chain;
- return result;
+ memset (result, 0, sizeof(struct binding_level));
}
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)
- b = b->level_chain;
- return b;
+ return result;
}
/* Remove a binding level from a list and add it to the level chain. */
@@ -408,8 +394,7 @@ kept_level_p ()
&& current_binding_level->blocks != 0)
|| current_binding_level->keep
|| current_binding_level->names != 0
- || (current_binding_level->tags != 0
- && !current_binding_level->tag_transparent));
+ || current_binding_level->tags != 0);
}
/* Identify this binding level as a level of parameters.
@@ -432,57 +417,45 @@ in_parm_level_p ()
return current_binding_level->parm_flag;
}
-/* Enter a new binding level.
- If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
- not for that of tags. */
+/* Enter a new binding level. */
void
-pushlevel (tag_transparent)
- int tag_transparent;
+pushlevel (dummy)
+ int dummy ATTRIBUTE_UNUSED;
{
- struct binding_level *newlevel = NULL_BINDING_LEVEL;
-
- /* If this is the top level of a function,
- just make sure that NAMED_LABELS is 0. */
+ /* If this is the top level of a function, make sure that
+ NAMED_LABELS is 0. */
if (current_binding_level == global_binding_level)
+ named_labels = 0;
+
+ if (keep_next_if_subblocks)
{
- named_labels = 0;
+ /* 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.
+
+ XXX Note kludge - keep_next_if_subblocks is set only by
+ 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;
+
+ keep_next_level_flag = 0;
+ keep_next_if_subblocks = 0;
}
+ else
+ {
+ struct binding_level *newlevel = make_binding_level ();
- newlevel = make_binding_level ();
-
- /* Add this level to the front of the chain (stack) of levels that
- are active. */
-
- *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;
- newlevel->keep_if_subblocks = keep_next_if_subblocks;
- keep_next_if_subblocks = 0;
-}
-
-/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */
-
-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))
- clear_limbo_values (tem);
+ newlevel->keep = keep_next_level_flag;
+ newlevel->level_chain = current_binding_level;
+ current_binding_level = newlevel;
+ keep_next_level_flag = 0;
+ }
}
/* Exit a binding level.
@@ -507,95 +480,103 @@ poplevel (keep, reverse, functionbody)
int functionbody;
{
tree link;
- /* The chain of decls was accumulated in reverse order.
- Put it into forward order, just for cleanliness. */
- tree decls;
+ tree block;
+ tree decl;
+ tree decls = current_binding_level->names;
tree tags = current_binding_level->tags;
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
- declarations like `extern struct foo *x'. */
-#if 0
- /* Warn about incomplete structure types in this level. */
+ /* We used to warn about unused variables in expand_end_bindings,
+ i.e. while generating RTL. But in function-at-a-time mode we may
+ choose to never expand a function at all (e.g. auto inlining), so
+ we do this explicitly now. */
+ warn_about_unused_variables (decls);
+
+ /* 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))
+ {
+ if (DECL_NAME (link) != 0)
+ {
+ if (DECL_EXTERNAL (link))
+ /* External decls stay in the symbol-value slot but are
+ inaccessible. */
+ C_DECL_INVISIBLE (link) = 1;
+ else
+ IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0;
+ }
+
+ 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;
+ }
+
+ /* Clear out the tag-meanings declared on this level. */
for (link = tags; link; link = TREE_CHAIN (link))
- if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
- {
- tree type = TREE_VALUE (link);
- 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:
- error ("`struct %s' incomplete in scope ending here", id);
- break;
- case UNION_TYPE:
- error ("`union %s' incomplete in scope ending here", id);
- break;
- case ENUMERAL_TYPE:
- error ("`enum %s' incomplete in scope ending here", id);
- break;
- }
- }
-#endif /* 0 */
+ if (TREE_PURPOSE (link))
+ IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = 0;
+
+ /* Restore all name-meanings of the outer levels
+ that were shadowed by this level. */
+
+ for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
+ IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+
+ /* Restore all tag-meanings of the outer levels
+ that were shadowed by this level. */
+
+ for (link = current_binding_level->shadowed_tags; link;
+ 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
+ {
+ link = decls;
+ while (TREE_CHAIN (link)
+ && TREE_CODE (TREE_CHAIN (link)) != PARM_DECL)
+ link = TREE_CHAIN (link);
+
+ TREE_CHAIN (link) = 0;
+ }
+ }
/* Get the decls in the order they were written.
Usually current_binding_level->names is in reverse order.
But parameter decls were previously put in forward order. */
if (reverse)
- current_binding_level->names
- = decls = nreverse (current_binding_level->names);
- else
- decls = current_binding_level->names;
-
- /* Output any nested inline functions within this block
- if they weren't already output. */
-
- for (decl = decls; decl; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == FUNCTION_DECL
- && ! TREE_ASM_WRITTEN (decl)
- && DECL_INITIAL (decl) != 0
- && TREE_ADDRESSABLE (decl))
- {
- /* If this decl was copied from a file-scope decl
- on account of a block-scope extern decl,
- propagate TREE_ADDRESSABLE to the file-scope decl.
-
- DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
- 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,
- i.e. while generating RTL. But in function-at-a-time mode we may
- choose to never expand a function at all (e.g. auto inlining), so
- we do this explicitly now. */
- warn_about_unused_variables (getdecls ());
+ decls = nreverse (decls);
/* If there were any declarations or structure tags in that level,
or if this level is a function body,
create a BLOCK to record them for the life of this function. */
block = 0;
- block_previously_created = (current_binding_level->this_block != 0);
- 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)
+ if (keep)
{
+ block = make_node (BLOCK);
BLOCK_VARS (block) = decls;
BLOCK_SUBBLOCKS (block) = subblocks;
+ TREE_USED (block) = 1;
}
/* In each subblock, record that this is its superior. */
@@ -603,50 +584,31 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
- /* Clear out the meanings of the local variables of this level. */
-
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- 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;
- }
- }
+ /* 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.
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
+ 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. */
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ decl = functionbody ? current_function_decl : block;
+ 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,
- check over all the labels, and clear out the current
- (function local) meanings of their names. */
+ /* If the level being exited is the top level of a function, check
+ over all the labels, and clear out the current (function local)
+ meanings of their names. Then add them to BLOCK_VARS. */
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))
{
tree label = TREE_VALUE (link);
@@ -677,11 +639,8 @@ poplevel (keep, reverse, functionbody)
if (functionbody)
DECL_INITIAL (current_function_decl) = block;
else if (block)
- {
- if (!block_previously_created)
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
- }
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, block);
/* If we did not make a block for the level just exited,
any blocks made for inner levels
(since they cannot be recorded as subblocks in that level)
@@ -691,30 +650,6 @@ poplevel (keep, reverse, functionbody)
current_binding_level->blocks
= 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;
}
@@ -731,18 +666,14 @@ insert_block (block)
= chainon (current_binding_level->blocks, block);
}
-/* Set the BLOCK node for the innermost scope
- (the one we are currently in). */
+/* Set the BLOCK node for the innermost scope (the one we are
+ currently in). The RTL expansion machinery requires us to provide
+ this hook, but it is not useful in function-at-a-time mode. */
void
set_block (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
@@ -826,12 +757,7 @@ void
pushtag (name, type)
tree name, type;
{
- struct binding_level *b;
-
- /* Find the proper binding level for this type tag. */
-
- for (b = current_binding_level; b->tag_transparent; b = b->level_chain)
- continue;
+ struct binding_level *b = current_binding_level;
if (name)
{
@@ -839,6 +765,11 @@ pushtag (name, type)
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = name;
+
+ if (IDENTIFIER_TAG_VALUE (name))
+ b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name),
+ b->shadowed_tags);
+ IDENTIFIER_TAG_VALUE (name) = type;
}
b->tags = tree_cons (name, type, b->tags);
@@ -966,11 +897,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
return 0;
}
- /* For real parm decl following a forward decl,
- return 1 so old decl will be reused. */
+ /* For real parm decl following a forward decl, return 1 so old decl
+ will be reused. Only allow this to happen once. */
if (types_match && TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
- return 1;
+ {
+ TREE_ASM_WRITTEN (olddecl) = 0;
+ return 1;
+ }
/* The new declaration is the same kind of object as the old one.
The declarations may partially match. Print warnings if they don't
@@ -1107,6 +1041,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
we will come back here again. */
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
/* Permit char *foo (int, ...); followed by char *foo ();
if not pedantic. */
@@ -1151,7 +1099,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
}
}
}
- error_with_decl (olddecl, "previous declaration of `%s'");
+ if (C_DECL_IMPLICIT (olddecl))
+ error_with_decl (olddecl, "previous implicit declaration of `%s'");
+ else
+ error_with_decl (olddecl, "previous declaration of `%s'");
/* This is safer because the initializer might contain references
to variables that were declared between olddecl and newdecl. This
@@ -1592,58 +1543,137 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
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.
- 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. */
static void
-warn_if_shadowing (x, oldlocal)
- tree x, oldlocal;
+warn_if_shadowing (x, old)
+ tree x, old;
{
- tree sym;
const char *name;
- if (DECL_EXTERNAL (x))
+ /* Nothing to shadow? */
+ if (old == 0
+ /* Shadow warnings not wanted? */
+ || !warn_shadow
+ /* No shadow warnings for internally generated vars. */
+ || DECL_SOURCE_LINE (x) == 0
+ /* No shadow warnings for vars made for inlining. */
+ || DECL_FROM_INLINE (x)
+ /* Don't warn about the parm names in function declarator
+ within a function declarator.
+ It would be nice to avoid warning in any function
+ declarator in a declaration, as opposed to a definition,
+ but there is no way to tell it's not a definition. */
+ || (TREE_CODE (x) == PARM_DECL
+ && current_binding_level->level_chain->parm_flag))
return;
- sym = DECL_NAME (x);
- 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. */
- && DECL_SOURCE_LINE (x) != 0
- /* No shadow warnings for vars made for inlining. */
- && ! DECL_FROM_INLINE (x))
+ name = IDENTIFIER_POINTER (DECL_NAME (x));
+
+ if (TREE_CODE (old) == PARM_DECL)
+ shadow_warning (SW_PARAM, name, old);
+ else if (DECL_CONTEXT (old) == 0)
+ shadow_warning (SW_GLOBAL, name, old);
+ else
+ shadow_warning (SW_LOCAL, name, old);
+}
+
+
+/* Subroutine of pushdecl.
+
+ 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 with identical properties) and then install X
+ as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
+
+ The whole point here is to end up with a situation where each
+ and every ..._TYPE node the compiler creates will be uniquely
+ associated with AT MOST one node representing a typedef name.
+ This way, even though the compiler substitutes corresponding
+ ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
+ early on, later parts of the compiler can always do the reverse
+ translation and get back the corresponding typedef name. For
+ example, given:
+
+ typedef struct S MY_TYPE;
+ MY_TYPE object;
+
+ Later parts of the compiler might only know that `object' was of
+ type `struct S' if it were not for code just below. With this
+ code however, later parts of the compiler see something like:
+
+ struct S' == struct S
+ typedef struct S' MY_TYPE;
+ struct S' object;
+
+ And they can then deduce (from the node for type struct S') that
+ the original object declaration was:
+
+ MY_TYPE object;
+
+ Being able to do this is important for proper support of protoize,
+ and also for generating precise symbolic debugging information
+ which takes full account of the programmer's (typedef) vocabulary.
+
+ Obviously, we don't want to generate a duplicate ..._TYPE node if
+ the TYPE_DECL node that we are now processing really represents a
+ standard built-in type.
+
+ Since all standard types are effectively declared at line zero
+ 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. */
+
+static void
+clone_underlying_type (x)
+ tree x;
+{
+ if (DECL_SOURCE_LINE (x) == 0)
{
- if (TREE_CODE (x) == PARM_DECL
- && current_binding_level->level_chain->parm_flag)
- /* Don't warn about the parm names in function declarator
- within a function declarator.
- It would be nice to avoid warning in any function
- declarator in a declaration, as opposed to a definition,
- but there is no way to tell it's not a definition. */
- ;
- else if (oldlocal)
- {
- 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));
+ if (TYPE_NAME (TREE_TYPE (x)) == 0)
+ TYPE_NAME (TREE_TYPE (x)) = x;
+ }
+ else if (TREE_TYPE (x) != error_mark_node
+ && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
+ {
+ tree tt = TREE_TYPE (x);
+ DECL_ORIGINAL_TYPE (x) = tt;
+ tt = build_type_copy (tt);
+ TYPE_NAME (tt) = x;
+ TREE_USED (tt) = TREE_USED (x);
+ TREE_TYPE (x) = tt;
}
}
@@ -1659,343 +1689,79 @@ tree
pushdecl (x)
tree x;
{
- tree t;
tree name = DECL_NAME (x);
- struct binding_level *b = current_binding_level;
+ struct binding_level *scope = current_binding_level;
+
+#ifdef ENABLE_CHECKING
+ if (error_mark_node == 0)
+ /* Called too early. */
+ abort ();
+#endif
/* 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;
+ else
+ DECL_CONTEXT (x) = current_function_decl;
if (name)
{
- int different_binding_level = 0;
+ tree old;
if (warn_nested_externs
+ && scope != global_binding_level
&& DECL_EXTERNAL (x)
- && b != global_binding_level
- && x != IDENTIFIER_IMPLICIT_DECL (name)
- /* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__. */
&& !DECL_IN_SYSTEM_HEADER (x))
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))
- {
- 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
- ..._TYPE node (which will be just a variant of the existing
- ..._TYPE node with identical properties) and then install the
- TYPE_DECL node generated to represent the typedef name as the
- TYPE_NAME of this brand new (duplicate) ..._TYPE node.
-
- The whole point here is to end up with a situation where each
- and every ..._TYPE node the compiler creates will be uniquely
- associated with AT MOST one node representing a typedef name.
- This way, even though the compiler substitutes corresponding
- ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
- early on, later parts of the compiler can always do the reverse
- translation and get back the corresponding typedef name. For
- example, given:
-
- typedef struct S MY_TYPE;
- MY_TYPE object;
-
- Later parts of the compiler might only know that `object' was of
- type `struct S' if it were not for code just below. With this
- code however, later parts of the compiler see something like:
-
- struct S' == struct S
- typedef struct S' MY_TYPE;
- struct S' object;
-
- And they can then deduce (from the node for type struct S') that
- the original object declaration was:
-
- MY_TYPE object;
-
- Being able to do this is important for proper support of protoize,
- and also for generating precise symbolic debugging information
- which takes full account of the programmer's (typedef) vocabulary.
-
- Obviously, we don't want to generate a duplicate ..._TYPE node if
- the TYPE_DECL node that we are now processing really represents a
- standard built-in type.
-
- Since all standard types are effectively declared at line zero
- 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. */
-
- if (TREE_CODE (x) == TYPE_DECL)
+ old = lookup_name_current_level (name);
+ if (old && duplicate_decls (x, old, 0))
+ return old;
+ if (DECL_EXTERNAL (x) || scope == global_binding_level)
{
- if (DECL_SOURCE_LINE (x) == 0)
+ /* Find and check against a previous, not-in-scope, external
+ decl for this identifier. (C99 s???: If two declarations
+ with external linkage, referring to the same object, have
+ incompatible types, the behavior is undefined). */
+ tree ext = any_external_decl (name);
+ if (ext)
{
- if (TYPE_NAME (TREE_TYPE (x)) == 0)
- TYPE_NAME (TREE_TYPE (x)) = x;
+ if (duplicate_decls (x, ext, scope != global_binding_level))
+ x = copy_node (ext);
}
- else if (TREE_TYPE (x) != error_mark_node
- && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
- {
- tree tt = TREE_TYPE (x);
- DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_type_copy (tt);
- TYPE_NAME (tt) = x;
- TREE_USED (tt) = TREE_USED (x);
- 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
- && IDENTIFIER_GLOBAL_VALUE (name) == 0
- && TREE_CODE (x) == FUNCTION_DECL
- && ! 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'");
+ record_external_decl (x);
}
-
- /* This name is new in its binding level.
- Install the new declaration and return it. */
- if (b == global_binding_level)
+
+ if (TREE_CODE (x) == TYPE_DECL)
+ clone_underlying_type (x);
+
+ /* If storing a local value, there may already be one
+ (inherited). If so, record it for restoration when this
+ binding level ends. Take care not to do this if we are
+ replacing an older decl in the same binding level (i.e.
+ duplicate_decls returned false, above). */
+ if (scope != global_binding_level
+ && IDENTIFIER_SYMBOL_VALUE (name)
+ && IDENTIFIER_SYMBOL_VALUE (name) != old)
{
- /* Install a global value. */
-
- /* If the first global decl has external linkage,
- warn if we later see static one. */
- if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
- TREE_PUBLIC (name) = 1;
-
- IDENTIFIER_GLOBAL_VALUE (name) = x;
-
- /* We no longer care about any previous block level declarations. */
- IDENTIFIER_LIMBO_VALUE (name) = 0;
-
- /* Don't forget if the function was used via an implicit decl. */
- if (IDENTIFIER_IMPLICIT_DECL (name)
- && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
- TREE_USED (x) = 1, TREE_USED (name) = 1;
-
- /* Don't forget if its address was taken in that way. */
- if (IDENTIFIER_IMPLICIT_DECL (name)
- && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
- TREE_ADDRESSABLE (x) = 1;
-
- /* Warn about mismatches against previous implicit decl. */
- if (IDENTIFIER_IMPLICIT_DECL (name) != 0
- /* If this real decl matches the implicit, don't complain. */
- && ! (TREE_CODE (x) == FUNCTION_DECL
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x)))
- == integer_type_node)))
- pedwarn ("`%s' was previously implicitly declared to return `int'",
- IDENTIFIER_POINTER (name));
-
- /* If this decl is `static' and an `extern' was seen previously,
- that is erroneous. */
- if (TREE_PUBLIC (name)
- && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x))
- {
- /* Okay to redeclare an ANSI built-in as static. */
- if (t != 0 && DECL_BUILT_IN (t))
- ;
- /* Okay to declare a non-ANSI built-in as anything. */
- else if (t != 0 && DECL_BUILT_IN_NONANSI (t))
- ;
- /* 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))
- pedwarn ("`%s' was declared implicitly `extern' and later `static'",
- IDENTIFIER_POINTER (name));
- }
- else
- pedwarn ("`%s' was declared `extern' and later `static'",
- IDENTIFIER_POINTER (name));
- }
+ warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name));
+ scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
+ scope->shadowed);
}
- 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
- have a global definition or declaration for the function. */
- 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,
- and no file-scope declaration has yet been seen,
- then if we later have a file-scope decl it must not be static. */
- if (oldlocal == 0
- && DECL_EXTERNAL (x)
- && TREE_PUBLIC (x))
- {
- if (oldglobal == 0)
- TREE_PUBLIC (name) = 1;
-
- /* 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);
- /* If storing a local value, there may already be one (inherited).
- If so, record it for restoration when this binding level ends. */
- if (oldlocal != 0)
- b->shadowed = tree_cons (name, oldlocal, b->shadowed);
- }
+ /* Install the new declaration in the requested binding level. */
+ IDENTIFIER_SYMBOL_VALUE (name) = x;
+ C_DECL_INVISIBLE (x) = 0;
/* Keep list of variables in this level with incomplete type.
If the input is erroneous, we can have error_mark in the type
@@ -2010,96 +1776,131 @@ pushdecl (x)
element = TREE_TYPE (element);
if (TREE_CODE (element) == RECORD_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.
We will reverse them later if necessary. */
- TREE_CHAIN (x) = b->names;
- b->names = x;
+ TREE_CHAIN (x) = scope->names;
+ scope->names = x;
return x;
}
-/* Record that the local value of NAME is shadowed at function scope.
- This is used by build_external_ref in c-typeck.c. */
-void
-record_function_scope_shadow (name)
- tree name;
+/* Record X as belonging to the global scope (C99 "file scope").
+ This is used only internally by the Objective C front end,
+ and is limited to its needs. It will hork if there is _any_
+ visible binding for X (not just a global one). */
+tree
+pushdecl_top_level (x)
+ tree x;
{
- struct binding_level *b = get_function_binding_level ();
- b->shadowed = tree_cons (name, IDENTIFIER_LOCAL_VALUE (name),
- b->shadowed);
-}
+ tree name, old;
+
+ if (TREE_CODE (x) != VAR_DECL)
+ abort ();
+
+ 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;
+ }
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
+ 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
-pushdecl_top_level (x)
+pushdecl_function_level (x, name)
tree x;
+ tree name;
{
- tree t;
- struct binding_level *b = current_binding_level;
+ struct binding_level *scope;
+
+ scope = current_binding_level;
+ while (scope->function_body == 0)
+ scope = scope->level_chain;
+ 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 ();
- current_binding_level = global_binding_level;
- t = pushdecl (x);
- current_binding_level = b;
- return t;
+ 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
- as a function of type int (). Print a warning if appropriate. */
+/* Generate an implicit declaration for identifier FUNCTIONID as a
+ function of type int (). */
tree
implicitly_declare (functionid)
tree functionid;
{
- tree decl;
- int traditional_warning = 0;
- /* Only one "implicit declaration" warning per identifier. */
- int implicit_warning;
+ tree decl = any_external_decl (functionid);
- /* We used to reuse an old implicit decl here,
- but this loses with inline functions because it can clobber
- the saved decl chains. */
-#if 0
- if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
- decl = IDENTIFIER_IMPLICIT_DECL (functionid);
- else
-#endif
- decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
-
- /* Warn of implicit decl following explicit local extern decl.
- This is probably a program designed for traditional C. */
- if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0)
- traditional_warning = 1;
-
- /* Warn once of an implicit declaration. */
- implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0);
+ if (decl && decl != error_mark_node)
+ {
+ /* Implicit declaration of a function already declared
+ (somehow) in a different scope, or as a built-in.
+ If this is the first time this has happened, warn;
+ then recycle the old declaration. */
+ if (!C_DECL_IMPLICIT (decl))
+ {
+ implicit_decl_warning (DECL_NAME (decl));
+ if (DECL_CONTEXT (decl))
+ warning_with_decl (decl, "previous declaration of `%s'");
+ C_DECL_IMPLICIT (decl) = 1;
+ }
+ return pushdecl (decl);
+ }
+ /* Not seen before. */
+ decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
-
- /* Record that we have an implicit decl and this is it. */
- IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
+ C_DECL_IMPLICIT (decl) = 1;
+ implicit_decl_warning (functionid);
/* ANSI standard says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
- 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);
+ decl = pushdecl (decl);
+ /* No need to call objc_check_decl here - it's a function type. */
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
prototypes file (if requested). */
@@ -2111,7 +1912,7 @@ implicitly_declare (functionid)
return decl;
}
-void
+static void
implicit_decl_warning (id)
tree id;
{
@@ -2353,55 +2154,50 @@ storetags (tags)
/* Given NAME, an IDENTIFIER_NODE,
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 specified context
- (but skips any tag-transparent contexts to find one that is
- meaningful for tags).
+ If THISLEVEL_ONLY is nonzero, searches only the current_binding_level.
CODE says which kind of type the caller wants;
it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
If the wrong kind of type is found, an error is reported. */
static tree
-lookup_tag (code, name, binding_level, thislevel_only)
+lookup_tag (code, name, thislevel_only)
enum tree_code code;
- struct binding_level *binding_level;
tree name;
int thislevel_only;
{
- struct binding_level *level;
- int thislevel = 1;
+ tree tag = IDENTIFIER_TAG_VALUE (name);
+ int thislevel = 0;
- for (level = binding_level; level; level = level->level_chain)
+ if (!tag)
+ return 0;
+
+ /* We only care about whether it's in this level if
+ thislevel_only was set or it might be a type clash. */
+ if (thislevel_only || TREE_CODE (tag) != code)
{
- tree tail;
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_PURPOSE (tail) == name)
- {
- if (TREE_CODE (TREE_VALUE (tail)) != code)
- {
- /* Definition isn't the kind we were looking for. */
- pending_invalid_xref = name;
- pending_invalid_xref_file = input_filename;
- pending_invalid_xref_line = lineno;
- /* If in the same binding level as a declaration as a tag
- of a different type, this must not be allowed to
- shadow that tag, so give the error immediately.
- (For example, "struct foo; union foo;" is invalid.) */
- if (thislevel)
- pending_xref_error ();
- }
- return TREE_VALUE (tail);
- }
- }
- if (! level->tag_transparent)
- {
- if (thislevel_only)
- return NULL_TREE;
- thislevel = 0;
- }
+ if (current_binding_level == global_binding_level
+ || purpose_member (name, current_binding_level->tags))
+ thislevel = 1;
}
- return NULL_TREE;
+
+ if (thislevel_only && !thislevel)
+ return 0;
+
+ if (TREE_CODE (tag) != code)
+ {
+ /* Definition isn't the kind we were looking for. */
+ pending_invalid_xref = name;
+ pending_invalid_xref_file = input_filename;
+ pending_invalid_xref_line = lineno;
+
+ /* If in the same binding level as a declaration as a tag
+ of a different type, this must not be allowed to
+ shadow that tag, so give the error immediately.
+ (For example, "struct foo; union foo;" is invalid.) */
+ if (thislevel)
+ pending_xref_error ();
+ }
+ return tag;
}
/* Print an error message now
@@ -2420,26 +2216,6 @@ pending_xref_error ()
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
in the namespace of variables, functions and typedefs.
@@ -2450,35 +2226,33 @@ tree
lookup_name (name)
tree name;
{
- tree val;
-
- if (current_binding_level != global_binding_level
- && IDENTIFIER_LOCAL_VALUE (name))
- val = IDENTIFIER_LOCAL_VALUE (name);
- else
- val = IDENTIFIER_GLOBAL_VALUE (name);
- return val;
+ tree decl = IDENTIFIER_SYMBOL_VALUE (name);
+ if (decl == 0 || decl == error_mark_node)
+ return decl;
+ if (C_DECL_INVISIBLE (decl))
+ return 0;
+ return decl;
}
-/* 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)
tree name;
{
- tree t;
+ tree decl = IDENTIFIER_SYMBOL_VALUE (name);
- if (current_binding_level == global_binding_level)
- return IDENTIFIER_GLOBAL_VALUE (name);
-
- if (IDENTIFIER_LOCAL_VALUE (name) == 0)
+ if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
return 0;
- for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
- if (DECL_NAME (t) == name)
- break;
+ if (current_binding_level == global_binding_level)
+ return decl;
- 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,
@@ -2558,8 +2332,6 @@ c_make_fname_decl (id, type_dep)
build_index_type (size_int (length)));
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_READONLY (decl) = 1;
@@ -2572,14 +2344,8 @@ c_make_fname_decl (id, type_dep)
TREE_USED (decl) = 1;
if (current_function_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;
- }
-
+ pushdecl_function_level (decl, DECL_NAME (decl));
+
finish_decl (decl, init, NULL_TREE);
return decl;
@@ -2616,7 +2382,7 @@ builtin_function (name, type, function_code, class, library_name, attrs)
/* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */
if (name[0] != '_' || name[1] != '_')
- C_DECL_ANTICIPATED (decl) = 1;
+ C_DECL_INVISIBLE (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
if (attrs)
@@ -2680,7 +2446,7 @@ shadow_tag_warned (declspecs, warned)
/* Used to test also that TYPE_SIZE (value) != 0.
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;
found_tag++;
@@ -2696,7 +2462,7 @@ shadow_tag_warned (declspecs, warned)
}
else
{
- t = lookup_tag (code, name, current_binding_level, 1);
+ t = lookup_tag (code, name, 1);
if (t == 0)
{
@@ -4950,7 +4716,7 @@ xref_tag (code, name)
/* If a cross reference is requested, look up the type
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.
(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
@@ -5004,7 +4770,7 @@ start_struct (code, name)
tree ref = 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 (TYPE_FIELDS (ref))
@@ -5432,7 +5198,7 @@ start_enum (name)
forward reference. */
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)
{
@@ -5750,27 +5516,16 @@ start_function (declspecs, declarator, attributes)
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. */
if (warn_strict_prototypes
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
- && !(old_decl != 0
- && (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
- || (DECL_BUILT_IN (old_decl)
- && ! C_DECL_ANTICIPATED (old_decl)))))
+ && C_DECL_ISNT_PROTOTYPE (old_decl))
warning ("function declaration isn't a prototype");
/* Optionally warn of any global def with no previous prototype. */
else if (warn_missing_prototypes
&& TREE_PUBLIC (decl1)
- && !(old_decl != 0
- && (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
- || (DECL_BUILT_IN (old_decl)
- && ! C_DECL_ANTICIPATED (old_decl))))
- && ! MAIN_NAME_P (DECL_NAME (decl1)))
+ && ! MAIN_NAME_P (DECL_NAME (decl1))
+ && C_DECL_ISNT_PROTOTYPE (old_decl))
warning_with_decl (decl1, "no previous prototype for `%s'");
/* Optionally warn of any def with no previous prototype
if the function has already been used. */
@@ -5789,7 +5544,7 @@ start_function (declspecs, declarator, attributes)
if the function has already been used. */
else if (warn_missing_declarations
&& old_decl != 0 && TREE_USED (old_decl)
- && old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)))
+ && C_DECL_IMPLICIT (old_decl))
warning_with_decl (decl1,
"`%s' was used with no declaration before its definition");
@@ -5872,7 +5627,6 @@ start_function (declspecs, declarator, attributes)
pushlevel (0);
declare_parm_level (1);
- current_binding_level->subblocks_tag_transparent = 1;
make_decl_rtl (current_function_decl, NULL);
@@ -5965,10 +5719,10 @@ store_parm_decls ()
for (decl = current_binding_level->names;
decl; decl = TREE_CHAIN (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;
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->shadowed = 0;
}
@@ -6347,13 +6101,27 @@ finish_function (nested, can_defer_p)
{
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
/* This caused &foo to be of type ptr-to-const-function which then
got a warning when stored in a ptr-to-function variable. */
TREE_READONLY (fndecl) = 1;
#endif
- poplevel (1, 0, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
/* Must mark the RESULT_DECL as being in this function. */
@@ -6918,14 +6686,23 @@ c_expand_decl_stmt (t)
c_expand_body_1 (decl, 1);
}
-/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
- the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++. */
+/* Return the global value of T as a symbol. */
tree
identifier_global_value (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;
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 29352f5..368c970 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -1,6 +1,6 @@
/* Definitions for C parsing and type checking.
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.
@@ -37,11 +37,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
struct lang_identifier GTY(())
{
struct c_common_identifier common_id;
- tree global_value;
- tree local_value;
+ tree symbol_value;
+ tree tag_value;
tree label_value;
- tree implicit_decl;
- tree limbo_value;
};
/* The resulting tree type. */
@@ -70,26 +68,17 @@ struct lang_decl GTY(())
/* Macros for access to language-specific slots in an identifier. */
/* Each of these slots contains a DECL node or null. */
-/* This represents the value which the identifier has in the
- file-scope namespace. */
-#define IDENTIFIER_GLOBAL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->global_value)
-/* This represents the value which the identifier has in the current
- scope. */
-#define IDENTIFIER_LOCAL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->local_value)
-/* This represents the value which the identifier has as a label in
- the current label scope. */
+/* The value of the identifier in the namespace of "ordinary identifiers"
+ (data objects, enum constants, functions, typedefs). */
+#define IDENTIFIER_SYMBOL_VALUE(NODE) \
+ (((struct lang_identifier *) (NODE))->symbol_value)
+/* The value of the identifier in the namespace of struct, union,
+ and enum tags. */
+#define IDENTIFIER_TAG_VALUE(NODE) \
+ (((struct lang_identifier *) (NODE))->tag_value)
+/* The value of the identifier in the namespace of labels. */
#define IDENTIFIER_LABEL_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->label_value)
-/* 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:
TREE_PUBLIC to record that there was a previous local extern decl.
@@ -129,13 +118,6 @@ struct lang_type GTY(())
#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (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. */
#define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \
(TREE_COMPLEXITY (EXP) = (int) (CODE))
@@ -147,10 +129,22 @@ struct lang_type GTY(())
return type. */
#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
- occasion that would declare the function in ordinary C.
- Using the function draws a pedantic warning in this case. */
-#define C_DECL_ANTICIPATED(EXP) DECL_LANG_FLAG_3 (EXP)
+/* For a FUNCTION_DECL, nonzero if it was an implicit declaration. */
+#define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
+
+/* Nonzero for a declaration of an external object which is not
+ currently in scope. This is either a built-in declaration of
+ a library function, before a real declaration has been seen,
+ or a declaration that appeared in an inner scope that has ended. */
+#define C_DECL_INVISIBLE(EXP) DECL_LANG_FLAG_3 (EXP)
+
+/* 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
TYPE_ARG_TYPES for functions with prototypes, but created for functions
@@ -207,11 +201,9 @@ extern tree grokfield PARAMS ((const char *, int, tree
extern tree groktypename PARAMS ((tree));
extern tree groktypename_in_parm_context PARAMS ((tree));
extern tree implicitly_declare PARAMS ((tree));
-extern void implicit_decl_warning PARAMS ((tree));
extern int in_parm_level_p PARAMS ((void));
extern void keep_next_level PARAMS ((void));
extern tree lookup_name PARAMS ((tree));
-extern tree lookup_name_current_level PARAMS ((tree));
extern void parmlist_tags_warning PARAMS ((void));
extern void pending_xref_error PARAMS ((void));
extern void c_push_function_context PARAMS ((struct function *));
@@ -220,8 +212,8 @@ extern void pop_label_level PARAMS ((void));
extern void push_label_level PARAMS ((void));
extern void push_parm_decl 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 record_function_scope_shadow PARAMS ((tree));
extern tree set_array_declarator_type PARAMS ((tree, tree, int));
extern tree shadow_label PARAMS ((tree));
extern void shadow_tag PARAMS ((tree));
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index e63865e..ec9418b 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -1,6 +1,6 @@
/* Build expressions with type checking for C compiler.
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.
@@ -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 default_function_array_conversion PARAMS ((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 pointer_diff PARAMS ((tree, tree));
static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int));
@@ -1375,6 +1376,38 @@ build_array_ref (array, index)
}
}
+/* Issue an error message for a reference to an undeclared variable ID,
+ including a reference to a builtin outside of function-call context.
+ Arrange to suppress further errors for the same identifier. */
+static void
+undeclared_variable (id)
+ tree id;
+{
+ if (current_function_decl == 0)
+ {
+ error ("`%s' undeclared here (not in a function)",
+ IDENTIFIER_POINTER (id));
+ IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
+ }
+ else
+ {
+ error ("`%s' undeclared (first use in this function)",
+ IDENTIFIER_POINTER (id));
+
+ if (! undeclared_variable_notice)
+ {
+ error ("(Each undeclared identifier is reported only once");
+ error ("for each function it appears in.)");
+ undeclared_variable_notice = 1;
+ }
+
+ /* Set IDENTIFIER_SYMBOL_VALUE (id) to error_mark_node
+ at function scope. This suppresses further warnings
+ about this undeclared identifier in this function. */
+ pushdecl_function_level (error_mark_node, id);
+ }
+}
+
/* Build an external reference to identifier ID. FUN indicates
whether this will be used for a function call. */
tree
@@ -1386,70 +1419,12 @@ build_external_ref (id, fun)
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)
- error ("`%s' undeclared here (not in a function)",
- IDENTIFIER_POINTER (id));
- else
- {
- error ("`%s' undeclared (first use in this function)",
- IDENTIFIER_POINTER (id));
-
- if (! undeclared_variable_notice)
- {
- error ("(Each undeclared identifier is reported only once");
- error ("for each function it appears in.)");
- undeclared_variable_notice = 1;
- }
-
- /* Set IDENTIFIER_LOCAL_VALUE (id) to error_mark_node and
- add a function-scope shadow entry which will undo that.
- This suppresses further warnings about this undeclared
- identifier in this function. */
- record_function_scope_shadow (id);
- IDENTIFIER_LOCAL_VALUE (id) = error_mark_node;
- }
- return error_mark_node;
- }
- }
- else
+ if (decl && decl != error_mark_node)
{
/* Properly declared variable or function reference. */
if (!objc_ivar)
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",
IDENTIFIER_POINTER (id));
@@ -1458,10 +1433,27 @@ build_external_ref (id, fun)
else
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)
return error_mark_node;
+ if (TREE_DEPRECATED (ref))
+ warn_deprecated_use (ref);
+
if (!skip_evaluation)
assemble_external (ref);
TREE_USED (ref) = 1;
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index 3420bd1..9c5b85a 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -239,6 +239,8 @@ scope_to_insns_initialize ()
break;
case NOTE_INSN_BLOCK_END:
block = BLOCK_SUPERCONTEXT (block);
+ if (block && TREE_CODE (block) == FUNCTION_DECL)
+ block = 0;
delete_insn (insn);
break;
default:
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3e3e4f3..a272d5e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+2003-04-10 Zack Weinberg <zack@codesourcery.com>
+
+ * decl.c: Update all calls to shadow_warning.
+
2003-04-10 Mark Mitchell <mark@codesourcery.com>
* class.c (layout_class_type): Correct handling for overlong
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4734d76..28d1493 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4001,7 +4001,7 @@ pushdecl (tree x)
}
if (warn_shadow && !err)
- shadow_warning (SW_PARAM, false,
+ shadow_warning (SW_PARAM,
IDENTIFIER_POINTER (name), oldlocal);
}
@@ -4019,12 +4019,12 @@ pushdecl (tree x)
IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
- shadow_warning (SW_LOCAL, false,
+ shadow_warning (SW_LOCAL,
IDENTIFIER_POINTER (name), oldlocal);
else if (oldglobal != NULL_TREE
&& TREE_CODE (oldglobal) == VAR_DECL)
/* XXX shadow warnings in outer-more namespaces */
- shadow_warning (SW_GLOBAL, false,
+ shadow_warning (SW_GLOBAL,
IDENTIFIER_POINTER (name), oldglobal);
}
}
diff --git a/gcc/function.c b/gcc/function.c
index 306e752..1f2ed44 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -6000,10 +6000,16 @@ reorder_blocks_1 (insns, current_block, p_block_stack)
BLOCK_SUBBLOCKS (block) = 0;
TREE_ASM_WRITTEN (block) = 1;
- BLOCK_SUPERCONTEXT (block) = current_block;
- BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
- BLOCK_SUBBLOCKS (current_block) = block;
- current_block = block;
+ /* 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_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
+ BLOCK_SUBBLOCKS (current_block) = block;
+ current_block = block;
+ }
VARRAY_PUSH_TREE (*p_block_stack, block);
}
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index c23c622..b9ac315 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -5298,8 +5298,8 @@ build_protocol_reference (p)
objc_protocol_template),
NULL_TREE));
- if (IDENTIFIER_GLOBAL_VALUE (ident))
- decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
+ if (identifier_global_value (ident))
+ decl = identifier_global_value (ident); /* Set by pushdecl. */
else
{
decl = build_decl (VAR_DECL, ident, ptype);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 52be21c..7b23832 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+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>
* g++.dg/abi/bitfield10.C: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.c b/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.c
new file mode 100644
index 0000000..077153b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.c
@@ -0,0 +1,84 @@
+/* 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
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.x b/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.x
new file mode 100644
index 0000000..7926a94
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.x
@@ -0,0 +1,12 @@
+# 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
diff --git a/gcc/testsuite/gcc.dg/Wshadow-1.c b/gcc/testsuite/gcc.dg/Wshadow-1.c
index 320d4f8..c9c3acb 100644
--- a/gcc/testsuite/gcc.dg/Wshadow-1.c
+++ b/gcc/testsuite/gcc.dg/Wshadow-1.c
@@ -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" } */
- /* { dg-error "shadows a parameter" "" { target *-*-* } 15 } */
+ /* { dg-error "redeclared as different" "" { target *-*-* } 15 } */
}
void foo2 (int d) /* { dg-warning "shadowed declaration" } */
diff --git a/gcc/testsuite/gcc.dg/redecl-1.c b/gcc/testsuite/gcc.dg/redecl-1.c
new file mode 100644
index 0000000..d2355ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/redecl-1.c
@@ -0,0 +1,101 @@
+/* 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" } */