name-lookup.c (check_local_shadow): New, broke out of ...

* name-lookup.c (check_local_shadow): New, broke out of ...
	(pushdecl_maybe_friend_1): ... here.  Call it.

From-SVN: r248123
This commit is contained in:
Nathan Sidwell 2017-05-16 19:20:25 +00:00 committed by Nathan Sidwell
parent b3d762eb74
commit c0c248220b
2 changed files with 215 additions and 215 deletions

View file

@ -1,5 +1,8 @@
2017-05-16 Nathan Sidwell <nathan@acm.org>
* name-lookup.c (check_local_shadow): New, broke out of ...
(pushdecl_maybe_friend_1): ... here. Call it.
* cp-tree.h (OVL_NESTED_P, OVL_LOOKUP_P): New.
(ovl_first): Move inline definition to end of file.
(ovl_make, lookup_add): Declare.

View file

@ -1184,6 +1184,215 @@ supplement_binding (cxx_binding *binding, tree decl)
return ret;
}
/* DECL is being declared at a local scope. Emit suitable shadow
warnings. */
static void
check_local_shadow (tree decl)
{
/* Don't complain about the parms we push and then pop
while tentatively parsing a function declarator. */
if (TREE_CODE (decl) == PARM_DECL && !DECL_CONTEXT (decl))
return;
/* Inline decls shadow nothing. */
if (DECL_FROM_INLINE (decl))
return;
/* External decls are something else. */
if (DECL_EXTERNAL (decl))
return;
tree old = NULL_TREE;
cp_binding_level *old_scope = NULL;
if (cxx_binding *binding = outer_binding (DECL_NAME (decl), NULL, true))
{
old = binding->value;
old_scope = binding->scope;
}
while (old && VAR_P (old) && DECL_DEAD_FOR_LOCAL (old))
old = DECL_SHADOWED_FOR_VAR (old);
tree shadowed = NULL_TREE;
if (old
&& (TREE_CODE (old) == PARM_DECL
|| VAR_P (old)
|| (TREE_CODE (old) == TYPE_DECL
&& (!DECL_ARTIFICIAL (old)
|| TREE_CODE (decl) == TYPE_DECL)))
&& (!DECL_ARTIFICIAL (decl)
|| DECL_IMPLICIT_TYPEDEF_P (decl)
|| (VAR_P (decl) && DECL_ANON_UNION_VAR_P (decl))))
{
/* DECL shadows a local thing possibly of interest. */
/* Don't complain if it's from an enclosing function. */
if (DECL_CONTEXT (old) == current_function_decl
&& TREE_CODE (decl) != PARM_DECL
&& TREE_CODE (old) == PARM_DECL)
{
/* Go to where the parms should be and see if we find
them there. */
cp_binding_level *b = current_binding_level->level_chain;
if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
/* Skip the ctor/dtor cleanup level. */
b = b->level_chain;
/* ARM $8.3 */
if (b->kind == sk_function_parms)
{
error ("declaration of %q#D shadows a parameter", decl);
return;
}
}
/* The local structure or class can't use parameters of
the containing function anyway. */
if (DECL_CONTEXT (old) != current_function_decl)
{
for (cp_binding_level *scope = current_binding_level;
scope != old_scope; scope = scope->level_chain)
if (scope->kind == sk_class
&& !LAMBDA_TYPE_P (scope->this_entity))
return;
}
/* Error if redeclaring a local declared in a
init-statement or in the condition of an if or
switch statement when the new declaration is in the
outermost block of the controlled statement.
Redeclaring a variable from a for or while condition is
detected elsewhere. */
else if (VAR_P (old)
&& old_scope == current_binding_level->level_chain
&& (old_scope->kind == sk_cond || old_scope->kind == sk_for))
{
error ("redeclaration of %q#D", decl);
inform (DECL_SOURCE_LOCATION (old),
"%q#D previously declared here", old);
return;
}
/* C++11:
3.3.3/3: The name declared in an exception-declaration (...)
shall not be redeclared in the outermost block of the handler.
3.3.3/2: A parameter name shall not be redeclared (...) in
the outermost block of any handler associated with a
function-try-block.
3.4.1/15: The function parameter names shall not be redeclared
in the exception-declaration nor in the outermost block of a
handler for the function-try-block. */
else if ((TREE_CODE (old) == VAR_DECL
&& old_scope == current_binding_level->level_chain
&& old_scope->kind == sk_catch)
|| (TREE_CODE (old) == PARM_DECL
&& (current_binding_level->kind == sk_catch
|| current_binding_level->level_chain->kind == sk_catch)
&& in_function_try_handler))
{
if (permerror (input_location, "redeclaration of %q#D", decl))
inform (DECL_SOURCE_LOCATION (old),
"%q#D previously declared here", old);
return;
}
/* If '-Wshadow=compatible-local' is specified without other
-Wshadow= flags, we will warn only when the type of the
shadowing variable (DECL) can be converted to that of the
shadowed parameter (OLD_LOCAL). The reason why we only check
if DECL's type can be converted to OLD_LOCAL's type (but not the
other way around) is because when users accidentally shadow a
parameter, more than often they would use the variable
thinking (mistakenly) it's still the parameter. It would be
rare that users would use the variable in the place that
expects the parameter but thinking it's a new decl. */
enum opt_code warning_code;
if (warn_shadow)
warning_code = OPT_Wshadow;
else if (warn_shadow_local)
warning_code = OPT_Wshadow_local;
else if (warn_shadow_compatible_local
&& can_convert (TREE_TYPE (old), TREE_TYPE (decl), tf_none))
warning_code = OPT_Wshadow_compatible_local;
else
return;
const char *msg;
if (TREE_CODE (old) == PARM_DECL)
msg = "declaration of %q#D shadows a parameter";
else if (is_capture_proxy (old))
msg = "declaration of %qD shadows a lambda capture";
else
msg = "declaration of %qD shadows a previous local";
if (warning_at (input_location, warning_code, msg, decl))
{
shadowed = old;
goto inform_shadowed;
}
return;
}
if (!warn_shadow)
return;
/* Don't warn for artificial things that are not implicit typedefs. */
if (DECL_ARTIFICIAL (decl) && !DECL_IMPLICIT_TYPEDEF_P (decl))
return;
if (nonlambda_method_basetype ())
if (tree member = lookup_member (current_nonlambda_class_type (),
DECL_NAME (decl), /*protect=*/0,
/*want_type=*/false, tf_warning_or_error))
{
member = MAYBE_BASELINK_FUNCTIONS (member);
/* Warn if a variable shadows a non-function, or the variable
is a function or a pointer-to-function. */
if ((TREE_CODE (member) != FUNCTION_DECL
&& TREE_CODE (member) != OVERLOAD)
|| TREE_CODE (decl) == FUNCTION_DECL
|| TYPE_PTRFN_P (TREE_TYPE (decl))
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
{
if (warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a member of %qT",
decl, current_nonlambda_class_type ())
&& DECL_P (member))
{
shadowed = member;
goto inform_shadowed;
}
}
return;
}
/* Now look for a namespace shadow. */
old = get_namespace_binding (current_namespace, DECL_NAME (decl));
if (old
&& (VAR_P (old)
|| (TREE_CODE (old) == TYPE_DECL
&& (!DECL_ARTIFICIAL (old)
|| TREE_CODE (decl) == TYPE_DECL)))
&& !instantiating_current_function_p ())
/* XXX shadow warnings in outer-more namespaces */
{
if (warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a global declaration",
decl))
{
shadowed = old;
goto inform_shadowed;
}
return;
}
return;
inform_shadowed:
inform (DECL_SOURCE_LOCATION (shadowed), "shadowed declaration is here");
}
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope). IS_FRIEND is true if X is
@ -1570,13 +1779,11 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
/* Here to install a non-global value. */
tree oldglobal = get_namespace_binding (current_namespace, name);
tree oldlocal = NULL_TREE;
cp_binding_level *oldscope = NULL;
cxx_binding *oldbinding = outer_binding (name, NULL, true);
if (oldbinding)
{
oldlocal = oldbinding->value;
oldscope = oldbinding->scope;
}
check_local_shadow (x);
if (need_new_binding)
{
@ -1637,216 +1844,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
/* Don't complain about the parms we push and then pop
while tentatively parsing a function declarator. */
if (TREE_CODE (x) == PARM_DECL && DECL_CONTEXT (x) == NULL_TREE)
/* Ignore. */;
/* Warn if shadowing an argument at the top level of the body. */
else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
/* Inline decls shadow nothing. */
&& !DECL_FROM_INLINE (x)
&& (TREE_CODE (oldlocal) == PARM_DECL
|| VAR_P (oldlocal)
/* If the old decl is a type decl, only warn if the
old decl is an explicit typedef or if both the old
and new decls are type decls. */
|| (TREE_CODE (oldlocal) == TYPE_DECL
&& (!DECL_ARTIFICIAL (oldlocal)
|| TREE_CODE (x) == TYPE_DECL)))
/* Don't check for internally generated vars unless
it's an implicit typedef (see create_implicit_typedef
in decl.c) or anonymous union variable. */
&& (!DECL_ARTIFICIAL (x)
|| DECL_IMPLICIT_TYPEDEF_P (x)
|| (VAR_P (x) && DECL_ANON_UNION_VAR_P (x))))
{
bool nowarn = false;
/* Don't complain if it's from an enclosing function. */
if (DECL_CONTEXT (oldlocal) == current_function_decl
&& TREE_CODE (x) != PARM_DECL
&& TREE_CODE (oldlocal) == PARM_DECL)
{
/* Go to where the parms should be and see if we find
them there. */
cp_binding_level *b = current_binding_level->level_chain;
if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
/* Skip the ctor/dtor cleanup level. */
b = b->level_chain;
/* ARM $8.3 */
if (b->kind == sk_function_parms)
{
error ("declaration of %q#D shadows a parameter", x);
nowarn = true;
}
}
/* The local structure or class can't use parameters of
the containing function anyway. */
if (DECL_CONTEXT (oldlocal) != current_function_decl)
{
cp_binding_level *scope = current_binding_level;
tree context = DECL_CONTEXT (oldlocal);
for (; scope; scope = scope->level_chain)
{
if (scope->kind == sk_function_parms
&& scope->this_entity == context)
break;
if (scope->kind == sk_class
&& !LAMBDA_TYPE_P (scope->this_entity))
{
nowarn = true;
break;
}
}
}
/* Error if redeclaring a local declared in a
init-statement or in the condition of an if or
switch statement when the new declaration is in the
outermost block of the controlled statement.
Redeclaring a variable from a for or while condition is
detected elsewhere. */
else if (VAR_P (oldlocal)
&& oldscope == current_binding_level->level_chain
&& (oldscope->kind == sk_cond
|| oldscope->kind == sk_for))
{
error ("redeclaration of %q#D", x);
inform (DECL_SOURCE_LOCATION (oldlocal),
"%q#D previously declared here", oldlocal);
nowarn = true;
}
/* C++11:
3.3.3/3: The name declared in an exception-declaration (...)
shall not be redeclared in the outermost block of the handler.
3.3.3/2: A parameter name shall not be redeclared (...) in
the outermost block of any handler associated with a
function-try-block.
3.4.1/15: The function parameter names shall not be redeclared
in the exception-declaration nor in the outermost block of a
handler for the function-try-block. */
else if ((VAR_P (oldlocal)
&& oldscope == current_binding_level->level_chain
&& oldscope->kind == sk_catch)
|| (TREE_CODE (oldlocal) == PARM_DECL
&& (current_binding_level->kind == sk_catch
|| (current_binding_level->level_chain->kind
== sk_catch))
&& in_function_try_handler))
{
if (permerror (input_location, "redeclaration of %q#D", x))
inform (DECL_SOURCE_LOCATION (oldlocal),
"%q#D previously declared here", oldlocal);
nowarn = true;
}
if ((warn_shadow
|| warn_shadow_local
|| warn_shadow_compatible_local)
&& !nowarn)
{
bool warned;
enum opt_code warning_code;
/* If '-Wshadow=compatible-local' is specified without other
-Wshadow= flags, we will warn only when the type of the
shadowing variable (i.e. x) can be converted to that of
the shadowed parameter (oldlocal). The reason why we only
check if x's type can be converted to oldlocal's type
(but not the other way around) is because when users
accidentally shadow a parameter, more than often they
would use the variable thinking (mistakenly) it's still
the parameter. It would be rare that users would use the
variable in the place that expects the parameter but
thinking it's a new decl. */
if (warn_shadow)
warning_code = OPT_Wshadow;
else if (can_convert (TREE_TYPE (oldlocal), TREE_TYPE (x),
tf_none))
warning_code = OPT_Wshadow_compatible_local;
else
warning_code = OPT_Wshadow_local;
if (TREE_CODE (oldlocal) == PARM_DECL)
warned = warning_at (input_location, warning_code,
"declaration of %q#D shadows a parameter", x);
else if (is_capture_proxy (oldlocal))
warned = warning_at (input_location, warning_code,
"declaration of %qD shadows a lambda capture",
x);
else
warned = warning_at (input_location, warning_code,
"declaration of %qD shadows a previous local",
x);
if (warned)
inform (DECL_SOURCE_LOCATION (oldlocal),
"shadowed declaration is here");
}
}
/* Maybe warn if shadowing something else. */
else if (warn_shadow && !DECL_EXTERNAL (x)
/* No shadow warnings for internally generated vars unless
it's an implicit typedef (see create_implicit_typedef
in decl.c). */
&& (! DECL_ARTIFICIAL (x) || DECL_IMPLICIT_TYPEDEF_P (x))
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
tree member;
if (nonlambda_method_basetype ())
member = lookup_member (current_nonlambda_class_type (),
name,
/*protect=*/0,
/*want_type=*/false,
tf_warning_or_error);
else
member = NULL_TREE;
if (member && !TREE_STATIC (member))
{
if (BASELINK_P (member))
member = BASELINK_FUNCTIONS (member);
member = OVL_CURRENT (member);
/* Do not warn if a variable shadows a function, unless
the variable is a function or a pointer-to-function. */
if (TREE_CODE (member) != FUNCTION_DECL
|| TREE_CODE (x) == FUNCTION_DECL
|| TYPE_PTRFN_P (TREE_TYPE (x))
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (x)))
{
if (warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a member of %qT",
x, current_nonlambda_class_type ())
&& DECL_P (member))
inform (DECL_SOURCE_LOCATION (member),
"shadowed declaration is here");
}
}
else if (oldglobal != NULL_TREE
&& (VAR_P (oldglobal)
/* If the old decl is a type decl, only warn if the
old decl is an explicit typedef or if both the
old and new decls are type decls. */
|| (TREE_CODE (oldglobal) == TYPE_DECL
&& (!DECL_ARTIFICIAL (oldglobal)
|| TREE_CODE (x) == TYPE_DECL)))
&& !instantiating_current_function_p ())
/* XXX shadow warnings in outer-more namespaces */
{
if (warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a "
"global declaration", x))
inform (DECL_SOURCE_LOCATION (oldglobal),
"shadowed declaration is here");
}
}
}
if (VAR_P (x))