From patchwork Wed Aug 23 21:11:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 805181 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-460840-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="UfqHRgsG"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xd0VV6BMgz9t38 for ; Thu, 24 Aug 2017 07:11:58 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=xLb7RRIqNy75NuFHeegkMsjnb//jipP5GK76gkGtfN2rVlbkOl Ub4ss2C7ZbwKyhK/myvLmOrkQi2/IC7Yh5MMU+RqERT+ZFYSJk2S3g3QKLIK3EoE bxtuZn39/fK9ShZbBcfCtn43ee6vuJQrrCkrbIrlTNFPUaVNmssPP0/J0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=A7ihwcuNYhVayIanGKALKrWpYNQ=; b=UfqHRgsGjp0TZ/A1dXPE swktFqGogzhwcbMN0JMEto3BZnPAZ0HW32J0t7S/S3LDlrOPQxE4sTpShHsSZFoJ 0ZorspLV6UNz+mGmXbsJqrYBhkCej8iLWFKrNkh/U/g0LYEVisak6DciJ2dyjN7g QDAGHvGrM6DnqJZszUaEUR8= Received: (qmail 26854 invoked by alias); 23 Aug 2017 21:11:47 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 26410 invoked by uid 89); 23 Aug 2017 21:11:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-15.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-yw0-f172.google.com Received: from mail-yw0-f172.google.com (HELO mail-yw0-f172.google.com) (209.85.161.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 23 Aug 2017 21:11:44 +0000 Received: by mail-yw0-f172.google.com with SMTP id y64so7996832ywf.3 for ; Wed, 23 Aug 2017 14:11:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=dpWep43czWAN31dUaRwXKXQne8SwwAG33qtqXPs8Jv8=; b=I/8MpKgIUzr9JV32Ot+lG0OGKpgcKoMezkunHMQ1J7gSdS9b4/HEJT2mX+9WPtCSMB jSRtK36+JUZDFd5wqo4JuqyQA1fRq7vaiZPoo+tN3axlha8BnthKY4jctkuK4TbnC9cg 2StTASMSYCvGk4AdNM7Z+lt86fKsqtFnehRkPhQZBXwWipnR+AIbXUHUswlKg6kEzWVc os9IaOWeS7TYsiClmREZlYY76RoL2GZzuTDC8bJb0T+kNz7+Lnnph1K/yyLPLBf7zqD6 pTyOXxMW99L+J4Sx+E14T35oRQ2HSobS1pGGuZIUzMYis5gnsJrct7uZ6mP8n2a+HiEN uovg== X-Gm-Message-State: AHYfb5jXQWQeCJqhwTRHWmX4ffkTYm5FKG6qGwGIxX32jsDMKOgTNHfF E3JJ3ybYrBfqmA== X-Received: by 10.129.88.214 with SMTP id m205mr3185928ywb.318.1503522702232; Wed, 23 Aug 2017 14:11:42 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a1:1102:495f:7267:5ff:a250? ([2620:10d:c091:180::1:ac9e]) by smtp.googlemail.com with ESMTPSA id u186sm909270ywd.73.2017.08.23.14.11.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Aug 2017 14:11:41 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] move class lookup fns Message-ID: <4f655f22-65d5-a652-4848-b5e49d0be1bb@acm.org> Date: Wed, 23 Aug 2017 17:11:39 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 this patch moves the direct class member lookup functions from search.c to name-lookup.c. I'll be morphing them into a saner data representation. These are the functions that look only in a specified class. The hierarchy searching functions remain in search.c This is a direct transplant with no change of functionality, so that future diffs don't have extraneous churn. Applied to trunk. nathan 2017-08-23 Nathan Sidwell * cp-tree.h (lookup_field_1, lookup_fnfields_slot, lookup_fnfields_slot_nolazy, lookup_all_conversions): Move declatations to ... * name-lookup.h (lookup_field_1, lookup_fnfields_slot, lookup_fnfields_slot_nolazy, lookup_all_conversions): ... here. * search.c (lookup_conversion_operator, lookup_fnfields_slot_nolazy, lookup_field_1, lookup_fnfields_slot, lookup_all_conversions): Move to ... * name-lookup.c (lookup_conversion_operator, lookup_fnfields_slot_nolazy, lookup_field_1, lookup_fnfields_slot, lookup_all_conversions): ... here. Index: cp-tree.h =================================================================== --- cp-tree.h (revision 251316) +++ cp-tree.h (working copy) @@ -6563,11 +6563,7 @@ extern tree lookup_base extern tree dcast_base_hint (tree, tree); extern int accessible_p (tree, tree, bool); extern int accessible_in_template_p (tree, tree); -extern tree lookup_field_1 (tree, tree, bool); extern tree lookup_field (tree, tree, int, bool); -extern tree lookup_fnfields_slot (tree, tree); -extern tree lookup_fnfields_slot_nolazy (tree, tree); -extern tree lookup_all_conversions (tree); extern tree lookup_fnfields (tree, tree, int); extern tree lookup_member (tree, tree, int, bool, tsubst_flags_t, Index: name-lookup.c =================================================================== --- name-lookup.c (revision 251313) +++ name-lookup.c (working copy) @@ -1089,6 +1089,258 @@ lookup_arg_dependent (tree name, tree fn return fns; } +/* Return the conversion operators in CLASS_TYPE corresponding to + "operator TYPE ()". Only CLASS_TYPE itself is searched; this + routine does not scan the base classes of CLASS_TYPE. */ + +static tree +lookup_conversion_operator (tree class_type, tree type) +{ + tree tpls = NULL_TREE; + + if (TYPE_HAS_CONVERSION (class_type)) + { + tree fns; + vec *methods = CLASSTYPE_METHOD_VEC (class_type); + + for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT; + vec_safe_iterate (methods, i, &fns); ++i) + { + /* All the conversion operators come near the beginning of + the class. Therefore, if FN is not a conversion + operator, there is no matching conversion operator in + CLASS_TYPE. */ + tree fn = OVL_FIRST (fns); + if (!DECL_CONV_FN_P (fn)) + break; + + if (TREE_CODE (fn) == TEMPLATE_DECL) + /* All the templated conversion functions are on the same + slot, so remember it. */ + tpls = fns; + else if (same_type_p (DECL_CONV_FN_TYPE (fn), type)) + return fns; + } + } + + return tpls; +} + +/* TYPE is a class type. Return the member functions in the method + vector with name NAME. Does not lazily declare implicitly-declared + member functions. */ + +tree +lookup_fnfields_slot_nolazy (tree type, tree name) +{ + vec *method_vec = CLASSTYPE_METHOD_VEC (type); + if (!method_vec) + return NULL_TREE; + + if (IDENTIFIER_CONV_OP_P (name)) + return lookup_conversion_operator (type, TREE_TYPE (name)); + + /* Skip the conversion operators. */ + int i; + tree fns; + for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; + vec_safe_iterate (method_vec, i, &fns); + ++i) + if (!DECL_CONV_FN_P (OVL_FIRST (fns))) + break; + + /* If the type is complete, use binary search. */ + if (COMPLETE_TYPE_P (type)) + { + int lo; + int hi; + + lo = i; + hi = method_vec->length (); + while (lo < hi) + { + i = (lo + hi) / 2; + + fns = (*method_vec)[i]; + tree fn_name = OVL_NAME (fns); + if (fn_name > name) + hi = i; + else if (fn_name < name) + lo = i + 1; + else + return fns; + } + } + else + for (; vec_safe_iterate (method_vec, i, &fns); ++i) + { + if (OVL_NAME (fns) == name) + return fns; + } + + return NULL_TREE; +} + +/* Do a 1-level search for NAME as a member of TYPE. The caller must + figure out whether it can access this field. (Since it is only one + level, this is reasonable.) */ + +tree +lookup_field_1 (tree type, tree name, bool want_type) +{ + tree field; + + gcc_assert (identifier_p (name) && RECORD_OR_UNION_TYPE_P (type)); + + if (CLASSTYPE_SORTED_FIELDS (type)) + { + tree *fields = &CLASSTYPE_SORTED_FIELDS (type)->elts[0]; + int lo = 0, hi = CLASSTYPE_SORTED_FIELDS (type)->len; + int i; + + while (lo < hi) + { + i = (lo + hi) / 2; + + if (DECL_NAME (fields[i]) > name) + hi = i; + else if (DECL_NAME (fields[i]) < name) + lo = i + 1; + else + { + field = NULL_TREE; + + /* We might have a nested class and a field with the + same name; we sorted them appropriately via + field_decl_cmp, so just look for the first or last + field with this name. */ + if (want_type) + { + do + field = fields[i--]; + while (i >= lo && DECL_NAME (fields[i]) == name); + if (!DECL_DECLARES_TYPE_P (field)) + field = NULL_TREE; + } + else + { + do + field = fields[i++]; + while (i < hi && DECL_NAME (fields[i]) == name); + } + + if (field) + { + field = strip_using_decl (field); + if (is_overloaded_fn (field)) + field = NULL_TREE; + } + + return field; + } + } + return NULL_TREE; + } + + field = TYPE_FIELDS (type); + + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + tree decl = field; + + if (DECL_DECLARES_FUNCTION_P (decl)) + /* Functions are kep separately, at the moment. */ + continue; + + gcc_assert (DECL_P (field)); + if (DECL_NAME (field) == NULL_TREE + && ANON_AGGR_TYPE_P (TREE_TYPE (field))) + { + tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type); + if (temp) + return temp; + } + + if (TREE_CODE (decl) == USING_DECL + && DECL_NAME (decl) == name) + { + decl = strip_using_decl (decl); + if (is_overloaded_fn (decl)) + continue; + } + + if (DECL_NAME (decl) == name + && (!want_type || DECL_DECLARES_TYPE_P (decl))) + return decl; + } + + /* We used to special-case vptr_identifier. Make sure it's not + special any more. */ + gcc_assert (name != vptr_identifier || !TYPE_VFIELD (type)); + + return NULL_TREE; +} + +/* TYPE is a class type. Return the overloads in + the method vector with name NAME. Lazily create ctors etc. */ + +tree +lookup_fnfields_slot (tree type, tree name) +{ + type = complete_type (type); + + if (COMPLETE_TYPE_P (type)) + { + if (IDENTIFIER_CTOR_P (name)) + { + if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) + lazily_declare_fn (sfk_constructor, type); + if (CLASSTYPE_LAZY_COPY_CTOR (type)) + lazily_declare_fn (sfk_copy_constructor, type); + if (CLASSTYPE_LAZY_MOVE_CTOR (type)) + lazily_declare_fn (sfk_move_constructor, type); + } + else if (name == cp_assignment_operator_id (NOP_EXPR)) + { + if (CLASSTYPE_LAZY_COPY_ASSIGN (type)) + lazily_declare_fn (sfk_copy_assignment, type); + if (CLASSTYPE_LAZY_MOVE_ASSIGN (type)) + lazily_declare_fn (sfk_move_assignment, type); + } + else if (IDENTIFIER_DTOR_P (name)) + { + if (CLASSTYPE_LAZY_DESTRUCTOR (type)) + lazily_declare_fn (sfk_destructor, type); + } + } + + return lookup_fnfields_slot_nolazy (type, name); +} + +/* Collect all the conversion operators of KLASS. */ + +tree +lookup_all_conversions (tree klass) +{ + tree lkp = NULL_TREE; + + if (vec *methods = CLASSTYPE_METHOD_VEC (klass)) + { + tree ovl; + for (int idx = CLASSTYPE_FIRST_CONVERSION_SLOT; + methods->iterate (idx, &ovl); ++idx) + { + if (!DECL_CONV_FN_P (OVL_FIRST (ovl))) + /* There are no more conversion functions. */ + break; + + lkp = lookup_add (ovl, lkp); + } + } + + return lkp; +} + /* Compute the chain index of a binding_entry given the HASH value of its name and the total COUNT of chains. COUNT is assumed to be a power of 2. */ @@ -3319,7 +3571,7 @@ do_pushdecl_with_scope (tree x, cp_bindi current_function_decl = function_decl; return x; } - + /* Inject X into the local scope just before the function parms. */ tree Index: name-lookup.h =================================================================== --- name-lookup.h (revision 251313) +++ name-lookup.h (working copy) @@ -319,6 +319,10 @@ extern void pop_decl_namespace (void); extern void do_namespace_alias (tree, tree); extern tree do_class_using_decl (tree, tree); extern tree lookup_arg_dependent (tree, tree, vec *); +extern tree lookup_field_1 (tree, tree, bool); +extern tree lookup_fnfields_slot (tree, tree); +extern tree lookup_fnfields_slot_nolazy (tree, tree); +extern tree lookup_all_conversions (tree); extern tree innermost_non_namespace_value (tree); extern cxx_binding *outer_binding (tree, cxx_binding *, bool); extern void cp_emit_debug_info_for_using (tree, tree); Index: search.c =================================================================== --- search.c (revision 251315) +++ search.c (working copy) @@ -353,106 +353,6 @@ dcast_base_hint (tree subtype, tree targ Otherwise, return a DECL with the indicated name. If WANT_TYPE is true, type declarations are preferred. */ -/* Do a 1-level search for NAME as a member of TYPE. The caller must - figure out whether it can access this field. (Since it is only one - level, this is reasonable.) */ - -tree -lookup_field_1 (tree type, tree name, bool want_type) -{ - tree field; - - gcc_assert (identifier_p (name) && RECORD_OR_UNION_TYPE_P (type)); - - if (CLASSTYPE_SORTED_FIELDS (type)) - { - tree *fields = &CLASSTYPE_SORTED_FIELDS (type)->elts[0]; - int lo = 0, hi = CLASSTYPE_SORTED_FIELDS (type)->len; - int i; - - while (lo < hi) - { - i = (lo + hi) / 2; - - if (DECL_NAME (fields[i]) > name) - hi = i; - else if (DECL_NAME (fields[i]) < name) - lo = i + 1; - else - { - field = NULL_TREE; - - /* We might have a nested class and a field with the - same name; we sorted them appropriately via - field_decl_cmp, so just look for the first or last - field with this name. */ - if (want_type) - { - do - field = fields[i--]; - while (i >= lo && DECL_NAME (fields[i]) == name); - if (!DECL_DECLARES_TYPE_P (field)) - field = NULL_TREE; - } - else - { - do - field = fields[i++]; - while (i < hi && DECL_NAME (fields[i]) == name); - } - - if (field) - { - field = strip_using_decl (field); - if (is_overloaded_fn (field)) - field = NULL_TREE; - } - - return field; - } - } - return NULL_TREE; - } - - field = TYPE_FIELDS (type); - - for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) - { - tree decl = field; - - if (DECL_DECLARES_FUNCTION_P (decl)) - /* Functions are kep separately, at the moment. */ - continue; - - gcc_assert (DECL_P (field)); - if (DECL_NAME (field) == NULL_TREE - && ANON_AGGR_TYPE_P (TREE_TYPE (field))) - { - tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type); - if (temp) - return temp; - } - - if (TREE_CODE (decl) == USING_DECL - && DECL_NAME (decl) == name) - { - decl = strip_using_decl (decl); - if (is_overloaded_fn (decl)) - continue; - } - - if (DECL_NAME (decl) == name - && (!want_type || DECL_DECLARES_TYPE_P (decl))) - return decl; - } - - /* We used to special-case vptr_identifier. Make sure it's not - special any more. */ - gcc_assert (name != vptr_identifier || !TYPE_VFIELD (type)); - - return NULL_TREE; -} - /* Return the FUNCTION_DECL, RECORD_TYPE, UNION_TYPE, or NAMESPACE_DECL corresponding to the innermost non-block scope. */ @@ -1454,158 +1354,6 @@ lookup_fnfields (tree xbasetype, tree na return rval; } -/* Return the conversion operators in CLASS_TYPE corresponding to - "operator TYPE ()". Only CLASS_TYPE itself is searched; this - routine does not scan the base classes of CLASS_TYPE. */ - -static tree -lookup_conversion_operator (tree class_type, tree type) -{ - tree tpls = NULL_TREE; - - if (TYPE_HAS_CONVERSION (class_type)) - { - tree fns; - vec *methods = CLASSTYPE_METHOD_VEC (class_type); - - for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (methods, i, &fns); ++i) - { - /* All the conversion operators come near the beginning of - the class. Therefore, if FN is not a conversion - operator, there is no matching conversion operator in - CLASS_TYPE. */ - tree fn = OVL_FIRST (fns); - if (!DECL_CONV_FN_P (fn)) - break; - - if (TREE_CODE (fn) == TEMPLATE_DECL) - /* All the templated conversion functions are on the same - slot, so remember it. */ - tpls = fns; - else if (same_type_p (DECL_CONV_FN_TYPE (fn), type)) - return fns; - } - } - - return tpls; -} - -/* TYPE is a class type. Return the member functions in the method - vector with name NAME. Does not lazily declare implicitly-declared - member functions. */ - -tree -lookup_fnfields_slot_nolazy (tree type, tree name) -{ - vec *method_vec = CLASSTYPE_METHOD_VEC (type); - if (!method_vec) - return NULL_TREE; - - if (IDENTIFIER_CONV_OP_P (name)) - return lookup_conversion_operator (type, TREE_TYPE (name)); - - /* Skip the conversion operators. */ - int i; - tree fns; - for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (method_vec, i, &fns); - ++i) - if (!DECL_CONV_FN_P (OVL_FIRST (fns))) - break; - - /* If the type is complete, use binary search. */ - if (COMPLETE_TYPE_P (type)) - { - int lo; - int hi; - - lo = i; - hi = method_vec->length (); - while (lo < hi) - { - i = (lo + hi) / 2; - - fns = (*method_vec)[i]; - tree fn_name = OVL_NAME (fns); - if (fn_name > name) - hi = i; - else if (fn_name < name) - lo = i + 1; - else - return fns; - } - } - else - for (; vec_safe_iterate (method_vec, i, &fns); ++i) - { - if (OVL_NAME (fns) == name) - return fns; - } - - return NULL_TREE; -} - -/* TYPE is a class type. Return the overloads in - the method vector with name NAME. Lazily create ctors etc. */ - -tree -lookup_fnfields_slot (tree type, tree name) -{ - type = complete_type (type); - - if (COMPLETE_TYPE_P (type)) - { - if (IDENTIFIER_CTOR_P (name)) - { - if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) - lazily_declare_fn (sfk_constructor, type); - if (CLASSTYPE_LAZY_COPY_CTOR (type)) - lazily_declare_fn (sfk_copy_constructor, type); - if (CLASSTYPE_LAZY_MOVE_CTOR (type)) - lazily_declare_fn (sfk_move_constructor, type); - } - else if (name == cp_assignment_operator_id (NOP_EXPR)) - { - if (CLASSTYPE_LAZY_COPY_ASSIGN (type)) - lazily_declare_fn (sfk_copy_assignment, type); - if (CLASSTYPE_LAZY_MOVE_ASSIGN (type)) - lazily_declare_fn (sfk_move_assignment, type); - } - else if (IDENTIFIER_DTOR_P (name)) - { - if (CLASSTYPE_LAZY_DESTRUCTOR (type)) - lazily_declare_fn (sfk_destructor, type); - } - } - - return lookup_fnfields_slot_nolazy (type, name); -} - -/* Collect all the conversion operators of KLASS. */ - -tree -lookup_all_conversions (tree klass) -{ - tree lkp = NULL_TREE; - - if (vec *methods = CLASSTYPE_METHOD_VEC (klass)) - { - tree ovl; - for (int idx = CLASSTYPE_FIRST_CONVERSION_SLOT; - methods->iterate (idx, &ovl); ++idx) - { - if (!DECL_CONV_FN_P (OVL_FIRST (ovl))) - /* There are no more conversion functions. */ - break; - - lkp = lookup_add (ovl, lkp); - } - } - - return lkp; -} - /* DECL is the result of a qualified name lookup. QUALIFYING_SCOPE is the class or namespace used to qualify the name. CONTEXT_CLASS is the class corresponding to the object in which DECL will be used.