From 0c5f6bbfe2ec7c3d6425fee43c53948a3652f738 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 13 Aug 2020 10:59:00 -0700 Subject: [PATCH] [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. --- gcc/cp/call.c | 5 +++-- gcc/cp/name-lookup.c | 39 +++++++++++++++++++++++++-------------- gcc/cp/name-lookup.h | 27 ++++++++++++++++++++++++++- gcc/cp/parser.c | 12 ++++++------ gcc/cp/pt.c | 15 ++++++++------- gcc/cp/semantics.c | 4 ++-- libcc1/libcp1plugin.cc | 2 +- 7 files changed, 71 insertions(+), 33 deletions(-) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f164b211c9f..47a368d069d 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4704,7 +4704,7 @@ build_operator_new_call (tree fnname, vec **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, diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 9f30d907a09..4fdac9421d1 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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 diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 9a185936853..4368c14d48c 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 981c625a3cd..2c45a3d6f41 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cb81d8e9229..5fd16bf781c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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)) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3096fe83433..e979a8b716c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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)) diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index 01aecf00735..24582c74a86 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -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);