From: Per Bothner Date: Fri, 25 Aug 1995 23:05:26 +0000 (-0400) Subject: (struct binding_level): New fields dead_vars_from_for and is_for_scope. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8d6e462ba263caef7e9663232267af59b15b86cd;p=gcc.git (struct binding_level): New fields dead_vars_from_for and is_for_scope. (note_level_for_for): New function. (poplevel): Special processing if is_for_scope. (pushdecl): Warn if for-scope variable shadows local. From-SVN: r10273 --- diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 9c49b35be91..50ca421517e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -552,6 +552,11 @@ struct binding_level structure or union types. */ unsigned int n_incomplete; + /* List of VAR_DECLS saved from a previous for statement. + These would be dead in ANSI-conformant code, but might + be referenced in traditional code. */ + tree dead_vars_from_for; + /* 1 for the level that holds the parameters of a function. 2 for the level that holds a class declaration. 3 for levels that hold parameter declarations. */ @@ -583,6 +588,9 @@ struct binding_level /* This is set for a namespace binding level. */ unsigned namespace_p : 1; + /* True if this level is that of a for-statement. */ + unsigned is_for_scope : 1; + /* One bit left for this word. */ #if defined(DEBUG_CP_BINDING_LEVELS) @@ -939,6 +947,12 @@ pushlevel (tag_transparent) keep_next_level_flag = 0; } +int +note_level_for_for () +{ + current_binding_level->is_for_scope = 1; +} + void pushlevel_temporary (tag_transparent) int tag_transparent; @@ -1097,28 +1111,81 @@ poplevel (keep, reverse, functionbody) /* Clear out the meanings of the local variables of this level. */ - for (link = decls; link; link = TREE_CHAIN (link)) + for (link = current_binding_level->dead_vars_from_for; + link != NULL_TREE; link = TREE_CHAIN (link)) { - if (DECL_NAME (link) != NULL_TREE) + if (DECL_DEAD_FOR_LOCAL (link)) { - /* If the ident. was used or addressed via a local extern decl, - don't forget that fact. */ - if (DECL_EXTERNAL (link)) + tree id = DECL_NAME (link); + if (IDENTIFIER_LOCAL_VALUE (id) == link) + IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link); + } + } + + if (current_binding_level->is_for_scope && flag_new_for_scope == 1) + { + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (TREE_CODE (link) == VAR_DECL) + DECL_DEAD_FOR_LOCAL (link) = 1; + } + } + else + { + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (DECL_NAME (link) != NULL_TREE) { - if (TREE_USED (link)) - TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1; - if (TREE_ADDRESSABLE (link)) - TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; + /* 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_ASSEMBLER_NAME (link)) = 1; + if (TREE_ADDRESSABLE (link)) + TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; + } + IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; } - IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; } } /* 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_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + if (current_binding_level->is_for_scope && flag_new_for_scope == 1) + { + struct binding_level *outer = current_binding_level->level_chain; + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + { + tree id = TREE_PURPOSE (link); + tree decl = IDENTIFIER_LOCAL_VALUE (id); + if (DECL_DEAD_FOR_LOCAL (decl)) + DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link); + else + IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link); + } + + /* Save declarations made in a 'for' statement so we can support pre-ANSI + 'for' scoping semantics. */ + + /* We append the current names of for-variables to those from previous + declarations, so that when we get around to do an poplevel + on the OUTER level, we restore the any shadowed readl bindings. + Note that the new names are put first on the combined list, + so they get to be restored first. This is important if there are + two for-loops using the same for-variable in the same block. + The binding we really want restored is whatever binding was shadowed + by the *first* for-variable, not the binding shadowed by the + second for-variable (which would be the first for-variable). */ + outer->dead_vars_from_for + = chainon (current_binding_level->names, outer->dead_vars_from_for); + } + else + { + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + } for (link = current_binding_level->class_shadowed; link; link = TREE_CHAIN (link)) IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); @@ -3029,15 +3096,16 @@ pushdecl (x) else if (t != NULL_TREE) { - if (TREE_CODE (t) == PARM_DECL) + file = DECL_SOURCE_FILE (t); + line = DECL_SOURCE_LINE (t); + if (TREE_CODE (x) == VAR_DECL && DECL_DEAD_FOR_LOCAL (x)) + ; /* This is OK. */ + else if (TREE_CODE (t) == PARM_DECL) { if (DECL_CONTEXT (t) == NULL_TREE) fatal ("parse errors have confused me too much"); } - file = DECL_SOURCE_FILE (t); - line = DECL_SOURCE_LINE (t); - - if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) + else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) || (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))) && is_overloaded_fn (t)) @@ -3303,6 +3371,13 @@ pushdecl (x) if (b->parm_flag == 1) cp_error ("declaration of `%#D' shadows a parameter", name); } + else if (oldlocal != NULL_TREE && b->is_for_scope + && !DECL_DEAD_FOR_LOCAL (oldlocal)) + { + warning ("variable `%s' shadows local", + IDENTIFIER_POINTER (name)); + cp_warning_at (" this is the shadowed declaration", oldlocal); + } /* Maybe warn if shadowing something else. */ else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */