From e38cd64ac6cb4da740d643589c857d2f910b6bba Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 9 Nov 2020 04:59:59 -0800 Subject: [PATCH] c++: ADL refactor This refactors the ADL lookup. It just so happens the refactoring makes dropping modules in simpler :) We break apart the namespace and class fn processing, and move scope iteration to an outer function. It'll also become possible to find the same enum in multiple place, so we need to handle that idempotently. gcc/cp/ * cp-tree.h (LOOKUP_FOUND_P): Add ENUMERAL_TYPE. * name-lookup.c (class name_lookup): Add comments. (name_lookup::adl_namespace_only): Replace with ... (name_lookup::adl_class_fns): ... this and ... (name_lookup::adl_namespace_fns): ... this. (name_lookup::adl_namespace): Deal with inline nests here. (name_lookup::adl_class): Complete the type here. (name_lookup::adl_type): Call broken-out enum .. (name_lookup::adl_enum): New. No need to call the namespace adl if it is class-scope. (name_lookup::search_adl): Iterate over collected scopes here. --- gcc/cp/cp-tree.h | 7 ++- gcc/cp/name-lookup.c | 156 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 109 insertions(+), 54 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 052291c..0813730 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -487,7 +487,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; DECL_TINFO_P (in VAR_DECL) FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) OVL_LOOKUP_P (in OVERLOAD) - LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, NAMESPACE_DECL) + LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL) 5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) @@ -745,9 +745,10 @@ typedef struct ptrmem_cst * ptrmem_cst_t; && flag_hosted) /* Lookup walker marking. */ -#define LOOKUP_SEEN_P(NODE) TREE_VISITED(NODE) +#define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE) #define LOOKUP_FOUND_P(NODE) \ - TREE_LANG_FLAG_4 (TREE_CHECK3(NODE,RECORD_TYPE,UNION_TYPE,NAMESPACE_DECL)) + TREE_LANG_FLAG_4 (TREE_CHECK4 (NODE,RECORD_TYPE,UNION_TYPE,ENUMERAL_TYPE,\ + NAMESPACE_DECL)) /* These two accessors should only be used by OVL manipulators. Other users should use iterators and convenience functions. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 16efd16..410ec59 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -171,8 +171,13 @@ public: public: tree name; /* The identifier being looked for. */ + + /* Usually we just add things to the VALUE binding, but we record + (hidden) IMPLICIT_TYPEDEFs on the type binding, which is used for + using-decl resolution. */ tree value; /* A (possibly ambiguous) set of things found. */ tree type; /* A type that has been found. */ + LOOK_want want; /* What kind of entity we want. */ bool deduping; /* Full deduping is needed because using declarations @@ -263,14 +268,17 @@ private: private: void add_fns (tree); + private: void adl_expr (tree); void adl_type (tree); void adl_template_arg (tree); void adl_class (tree); + void adl_enum (tree); void adl_bases (tree); void adl_class_only (tree); void adl_namespace (tree); - void adl_namespace_only (tree); + void adl_class_fns (tree); + void adl_namespace_fns (tree); public: /* Search namespace + inlines + maybe usings as qualified lookup. */ @@ -433,8 +441,8 @@ name_lookup::add_overload (tree fns) if (probe && TREE_CODE (probe) == OVERLOAD && OVL_DEDUP_P (probe)) { - /* We're about to add something found by a using - declaration, so need to engage deduping mode. */ + /* We're about to add something found by multiple paths, so + need to engage deduping mode. */ lookup_mark (value, true); deduping = true; } @@ -777,20 +785,56 @@ name_lookup::add_fns (tree fns) add_overload (fns); } -/* Add functions of a namespace to the lookup structure. */ +/* Add the overloaded fns of SCOPE. */ void -name_lookup::adl_namespace_only (tree scope) +name_lookup::adl_namespace_fns (tree scope) { - mark_seen (scope); + if (tree *binding = find_namespace_slot (scope, name)) + { + tree val = *binding; + add_fns (ovl_skip_hidden (MAYBE_STAT_DECL (val))); + } +} - /* Look down into inline namespaces. */ - if (vec *inlinees = DECL_NAMESPACE_INLINEES (scope)) - for (unsigned ix = inlinees->length (); ix--;) - adl_namespace_only ((*inlinees)[ix]); +/* Add the hidden friends of SCOPE. */ + +void +name_lookup::adl_class_fns (tree type) +{ + /* Add friends. */ + for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); + list; list = TREE_CHAIN (list)) + if (name == FRIEND_NAME (list)) + { + tree context = NULL_TREE; /* Lazily computed. */ + for (tree friends = FRIEND_DECLS (list); friends; + friends = TREE_CHAIN (friends)) + { + tree fn = TREE_VALUE (friends); - if (tree fns = find_namespace_value (scope, name)) - add_fns (ovl_skip_hidden (fns)); + /* Only interested in global functions with potentially hidden + (i.e. unqualified) declarations. */ + if (!context) + context = decl_namespace_context (type); + if (CP_DECL_CONTEXT (fn) != context) + continue; + + if (!deduping) + { + lookup_mark (value, true); + deduping = true; + } + + /* Template specializations are never found by name lookup. + (Templates themselves can be found, but not template + specializations.) */ + if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn)) + continue; + + add_fns (fn); + } + } } /* Find the containing non-inlined namespace, add it and all its @@ -799,14 +843,17 @@ name_lookup::adl_namespace_only (tree scope) void name_lookup::adl_namespace (tree scope) { - if (seen_p (scope)) + if (see_and_mark (scope)) return; - /* Find the containing non-inline namespace. */ - while (DECL_NAMESPACE_INLINE_P (scope)) - scope = CP_DECL_CONTEXT (scope); + /* Look down into inline namespaces. */ + if (vec *inlinees = DECL_NAMESPACE_INLINEES (scope)) + for (unsigned ix = inlinees->length (); ix--;) + adl_namespace ((*inlinees)[ix]); - adl_namespace_only (scope); + if (DECL_NAMESPACE_INLINE_P (scope)) + /* Mark parent. */ + adl_namespace (CP_DECL_CONTEXT (scope)); } /* Adds the class and its friends to the lookup structure. */ @@ -826,31 +873,6 @@ name_lookup::adl_class_only (tree type) tree context = decl_namespace_context (type); adl_namespace (context); - - complete_type (type); - - /* Add friends. */ - for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; - list = TREE_CHAIN (list)) - if (name == FRIEND_NAME (list)) - for (tree friends = FRIEND_DECLS (list); friends; - friends = TREE_CHAIN (friends)) - { - tree fn = TREE_VALUE (friends); - - /* Only interested in global functions with potentially hidden - (i.e. unqualified) declarations. */ - if (CP_DECL_CONTEXT (fn) != context) - continue; - - /* Template specializations are never found by name lookup. - (Templates themselves can be found, but not template - specializations.) */ - if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn)) - continue; - - add_fns (fn); - } } /* Adds the class and its bases to the lookup structure. @@ -873,7 +895,7 @@ name_lookup::adl_bases (tree type) } /* Adds everything associated with a class argument type to the lookup - structure. Returns true on error. + structure. If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct @@ -897,11 +919,13 @@ name_lookup::adl_class (tree type) return; type = TYPE_MAIN_VARIANT (type); + /* We don't set found here because we have to have set seen first, which is done in the adl_bases walk. */ if (found_p (type)) return; + complete_type (type); adl_bases (type); mark_found (type); @@ -919,6 +943,19 @@ name_lookup::adl_class (tree type) } void +name_lookup::adl_enum (tree type) +{ + type = TYPE_MAIN_VARIANT (type); + if (see_and_mark (type)) + return; + + if (TYPE_CLASS_SCOPE_P (type)) + adl_class_only (TYPE_CONTEXT (type)); + else + adl_namespace (decl_namespace_context (type)); +} + +void name_lookup::adl_expr (tree expr) { if (!expr) @@ -1003,9 +1040,7 @@ name_lookup::adl_type (tree type) return; case ENUMERAL_TYPE: - if (TYPE_CLASS_SCOPE_P (type)) - adl_class_only (TYPE_CONTEXT (type)); - adl_namespace (decl_namespace_context (type)); + adl_enum (type); return; case LANG_TYPE: @@ -1074,10 +1109,9 @@ name_lookup::adl_template_arg (tree arg) tree name_lookup::search_adl (tree fns, vec *args) { - deduping = true; - lookup_mark (fns, true); - value = fns; - + gcc_checking_assert (!vec_safe_length (scopes)); + + /* Gather each associated entity onto the lookup's scope list. */ unsigned ix; tree arg; @@ -1089,7 +1123,27 @@ name_lookup::search_adl (tree fns, vec *args) else adl_expr (arg); - fns = value; + if (vec_safe_length (scopes)) + { + /* Now do the lookups. */ + if (fns) + { + deduping = true; + lookup_mark (fns, true); + } + value = fns; + + for (unsigned ix = scopes->length (); ix--;) + { + tree scope = (*scopes)[ix]; + if (TREE_CODE (scope) == NAMESPACE_DECL) + adl_namespace_fns (scope); + else if (RECORD_OR_UNION_TYPE_P (scope)) + adl_class_fns (scope); + } + + fns = value; + } return fns; } -- 2.7.4