[c++]: Unconfuse lookup_name_real API a bit

The API for lookup_name_real is really confusing.  This addresses the part
where we have NONCLASS to say DON'T search class scopes, and BLOCK_P to say
DO search block scopes.  I've added a single bitmask to explicitly say which
scopes to search.  I used an enum class so one can't accidentally misorder
it.  It's also reordered so we don't mix it up with the parameters that say
what kind of thing we're looking for.

	gcc/cp/
	* name-lookup.h (enum class LOOK_where): New.
	(operator|, operator&): Overloads for it.
	(lookup_name_real): Replace NONCLASS & BLOCK_P parms with WHERE.
	* name-lookup.c (identifier_type_value_w): Adjust
	lookup_name_real call.
	(lookup_name_real_1): Replace NONCLASS and BLOCK_P parameters
	with WHERE bitmask. Don't search namespaces if not asked to.
	(lookup_name_real): Adjust lookup_name_real_1 call.
	(lookup_name_nonclass, lookup_name)
	(lookup_name_prefer_type): Likewise.
	* call.c (build_operator_new_call)
	(add_operator_candidates): Adjust lookup_name_real calls.
	* parser.c (cp_parser_lookup_name): Likewise.
	* pt.c (tsubst_friend_class, lookup_init_capture_pack)
	(tsubst_expr): Likewise.
	* semantics.c (capture_decltype): Likewise.
	libcc1/
	* libcp1plugin.cc (plugin_build_dependent_expr): Likewise.
This commit is contained in:
Nathan Sidwell 2020-08-13 10:59:00 -07:00
parent 55484a0f81
commit 0c5f6bbfe2
7 changed files with 71 additions and 33 deletions

View File

@ -4704,7 +4704,7 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
up in the global scope.
we disregard block-scope declarations of "operator new". */
fns = lookup_name_real (fnname, 0, 1, /*block_p=*/false, 0, 0);
fns = lookup_name_real (fnname, LOOK_where::NAMESPACE, 0, 0, 0);
fns = lookup_arg_dependent (fnname, fns, *args);
if (align_arg)
@ -5982,7 +5982,8 @@ add_operator_candidates (z_candidate **candidates,
consider. */
if (!memonly)
{
tree fns = lookup_name_real (fnname, 0, 1, /*block_p=*/true, 0, 0);
tree fns = lookup_name_real (fnname, LOOK_where::BLOCK_NAMESPACE,
0, 0, 0);
fns = lookup_arg_dependent (fnname, fns, arglist);
add_candidates (fns, NULL_TREE, arglist, NULL_TREE,
NULL_TREE, false, NULL_TREE, NULL_TREE,

View File

@ -3741,7 +3741,7 @@ identifier_type_value_1 (tree id)
return REAL_IDENTIFIER_TYPE_VALUE (id);
/* Have to search for it. It must be on the global level, now.
Ask lookup_name not to return non-types. */
id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, 0);
id = lookup_name_real (id, LOOK_where::BLOCK_NAMESPACE, 2, 0, 0);
if (id)
return TREE_TYPE (id);
return NULL_TREE;
@ -6413,10 +6413,16 @@ innermost_non_namespace_value (tree name)
namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one
such declaration, or return a TREE_LIST with all the overloaded
definitions if there are many, or return 0 if it is undefined.
definitions if there are many, or return NULL_TREE if it is undefined.
Hidden name, either friend declaration or built-in function, are
not ignored.
WHERE controls which scopes are considered. It is a bit mask of
LOOKUP_where::BLOCK (look in block scope), LOOKUP_where::CLASS
(look in class scopes) & LOOKUP_where::NAMESPACE (look in namespace
scopes). It is an error for no bits to be set. These scopes are
searched from innermost to outermost.
If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
Otherwise we prefer non-TYPE_DECLs.
@ -6425,12 +6431,14 @@ innermost_non_namespace_value (tree name)
BLOCK_P is false, bindings in block scopes are ignored. */
static tree
lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
lookup_name_real_1 (tree name, LOOK_where where, int prefer_type,
int namespaces_only, int flags)
{
cxx_binding *iter;
tree val = NULL_TREE;
gcc_checking_assert (unsigned (where) != 0);
query_oracle (name);
/* Conversion operators are handled specially because ordinary
@ -6468,17 +6476,19 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
/* First, look in non-namespace scopes. */
if (current_class_type == NULL_TREE)
nonclass = 1;
/* Maybe avoid searching the binding stack at all. */
where = LOOK_where (unsigned (where) & ~unsigned (LOOK_where::CLASS));
if (block_p || !nonclass)
for (iter = outer_binding (name, NULL, !nonclass);
if (where & (LOOK_where::BLOCK | LOOK_where::CLASS))
for (iter = outer_binding (name, NULL, where & LOOK_where::CLASS);
iter;
iter = outer_binding (name, iter, !nonclass))
iter = outer_binding (name, iter, where & LOOK_where::CLASS))
{
tree binding;
/* Skip entities we don't want. */
if (LOCAL_BINDING_P (iter) ? !block_p : nonclass)
if (!(where & (LOCAL_BINDING_P (iter)
? LOOK_where::BLOCK : LOOK_where::CLASS)))
continue;
/* If this is the kind of thing we're looking for, we're done. */
@ -6548,7 +6558,7 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
}
/* Now lookup in namespace scopes. */
if (!val)
if (!val && (where & LOOK_where::NAMESPACE))
{
name_lookup lookup (name, flags);
if (lookup.search_unqualified
@ -6566,12 +6576,12 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
/* Wrapper for lookup_name_real_1. */
tree
lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
lookup_name_real (tree name, LOOK_where where, int prefer_type,
int namespaces_only, int flags)
{
tree ret;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
ret = lookup_name_real_1 (name, prefer_type, nonclass, block_p,
ret = lookup_name_real_1 (name, where, prefer_type,
namespaces_only, flags);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
@ -6580,19 +6590,20 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
tree
lookup_name_nonclass (tree name)
{
return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, 0);
return lookup_name_real (name, LOOK_where::BLOCK_NAMESPACE,
0, 0, 0);
}
tree
lookup_name (tree name)
{
return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, 0);
return lookup_name_real (name, LOOK_where::ALL, 0, 0, 0);
}
tree
lookup_name_prefer_type (tree name, int prefer_type)
{
return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, 0, 0);
return lookup_name_real (name, LOOK_where::ALL, prefer_type, 0, 0);
}
/* Look up NAME for type used in elaborated name specifier in

View File

@ -278,8 +278,33 @@ extern void push_binding_level (cp_binding_level *);
extern bool handle_namespace_attrs (tree, tree);
extern void pushlevel_class (void);
extern void poplevel_class (void);
/* What kind of scopes name lookup looks in. An enum class so we
don't accidentally mix integers. */
enum class LOOK_where
{
BLOCK = 1 << 0, /* Consider block scopes. */
CLASS = 1 << 1, /* Consider class scopes. */
NAMESPACE = 1 << 2, /* Consider namespace scopes. */
ALL = BLOCK | CLASS | NAMESPACE,
BLOCK_NAMESPACE = BLOCK | NAMESPACE,
CLASS_NAMESPACE = CLASS | NAMESPACE,
};
constexpr LOOK_where operator| (LOOK_where a, LOOK_where b)
{
return LOOK_where (unsigned (a) | unsigned (b));
}
constexpr bool operator& (LOOK_where a, LOOK_where b)
{
return 0 != (unsigned (a) & unsigned (b));
}
extern tree lookup_name_prefer_type (tree, int);
extern tree lookup_name_real (tree, int, int, bool, int, int);
extern tree lookup_name_real (tree, LOOK_where, int prefer_type,
int namespaces_only, int flags);
extern tree lookup_type_scope (tree, tag_scope);
extern tree get_namespace_binding (tree ns, tree id);
extern void set_global_binding (tree decl);

View File

@ -28459,17 +28459,17 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
if (!decl)
/* Look it up in the enclosing context. DR 141: When looking for a
template-name after -> or ., only consider class templates. */
decl = lookup_name_real (name, prefer_type_arg (tag_type, is_template),
/*nonclass=*/0,
/*block_p=*/true, is_namespace, 0);
decl = lookup_name_real (name, LOOK_where::ALL,
prefer_type_arg (tag_type, is_template),
is_namespace, 0);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
}
else
{
decl = lookup_name_real (name, prefer_type_arg (tag_type),
/*nonclass=*/0,
/*block_p=*/true, is_namespace, 0);
decl = lookup_name_real (name, LOOK_where::ALL,
prefer_type_arg (tag_type),
is_namespace, 0);
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
}

View File

@ -11183,9 +11183,9 @@ tsubst_friend_class (tree friend_tmpl, tree args)
push_nested_class (context);
}
tmpl = lookup_name_real (DECL_NAME (friend_tmpl), /*prefer_type=*/false,
/*non_class=*/false, /*block_p=*/false,
/*namespaces_only=*/false, LOOKUP_HIDDEN);
tmpl = lookup_name_real (DECL_NAME (friend_tmpl), LOOK_where::CLASS_NAMESPACE,
/*prefer_type=*/0, /*namespaces_only=*/false,
LOOKUP_HIDDEN);
if (tmpl && DECL_CLASS_TEMPLATE_P (tmpl))
{
@ -17835,7 +17835,7 @@ lookup_init_capture_pack (tree decl)
for (int i = 0; i < len; ++i)
{
tree ename = vec ? make_ith_pack_parameter_name (cname, i) : cname;
tree elt = lookup_name_real (ename, 0, 0, true, 0, LOOKUP_NORMAL);
tree elt = lookup_name_real (ename, LOOK_where::ALL, 0, 0, LOOKUP_NORMAL);
if (vec)
TREE_VEC_ELT (vec, i) = elt;
else
@ -17940,9 +17940,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
tree inst;
if (!DECL_PACK_P (decl))
{
inst = lookup_name_real (DECL_NAME (decl), /*prefer_type*/0,
/*nonclass*/1, /*block_p=*/true,
/*ns_only*/0, LOOKUP_HIDDEN);
inst = lookup_name_real (DECL_NAME (decl),
LOOK_where::BLOCK_NAMESPACE,
/*prefer_type*/0, /*ns_only*/0,
LOOKUP_HIDDEN);
gcc_assert (inst != decl && is_capture_proxy (inst));
}
else if (is_normal_capture_proxy (decl))

View File

@ -10322,8 +10322,8 @@ static tree
capture_decltype (tree decl)
{
tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
/*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
tree cap = lookup_name_real (DECL_NAME (decl), LOOK_where::BLOCK_NAMESPACE,
/*type*/0, /*ns*/false, LOOKUP_HIDDEN);
tree type;
if (cap && is_capture_proxy (cap))

View File

@ -2652,7 +2652,7 @@ plugin_build_dependent_expr (cc1_plugin::connection *self,
}
tree res = identifier;
if (!scope)
res = lookup_name_real (res, 0, 0, true, 0, 0);
res = lookup_name_real (res, LOOK_where::BLOCK_NAMESPACE, 0, 0, 0);
else if (!TYPE_P (scope) || !dependent_scope_p (scope))
{
res = lookup_qualified_name (scope, res, false, true);