From patchwork Tue May 16 14:50:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 763015 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3wS0kQ5QVdz9s4q for ; Wed, 17 May 2017 00:50:54 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="KGPVNnfH"; dkim-atps=neutral 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=KNmebL3rClfMbSAhBmJDc5HsJdt0NvAnoQ46A7cbtf1RKmF60O FfWQcz+qJButIcLKHBk7gCJ0HM0bSvLvNWpFfmessiUMJWtiaC5cdj/ATvXcTXsN AxNErMjhvVg15nrSx/pZ1PMSGuK3zFQY73B41q6cQ3imdYZ5GlmGsIlW4= 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=LlWq8U6D0oanktqsjChPFXaOcKs=; b=KGPVNnfHx7aXulgM7BZU ng6IO+t2LDYjdA9lTokPW6qzfva3pZ8pehqySwdghO/v6giAmg5OelNUhWXYCELd kILHjeXZXdeM3630u1QGBA0TXrNz8ZCorXZVoZtpLxDrW3US4nSU8KY4hkJgd0fG pl/gxIlRZnxlHxKzL/iMh0o= Received: (qmail 74691 invoked by alias); 16 May 2017 14:50:35 -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 70593 invoked by uid 89); 16 May 2017 14:50:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=parm, lam X-HELO: mail-yw0-f174.google.com Received: from mail-yw0-f174.google.com (HELO mail-yw0-f174.google.com) (209.85.161.174) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 16 May 2017 14:50:30 +0000 Received: by mail-yw0-f174.google.com with SMTP id l14so54104422ywk.1 for ; Tue, 16 May 2017 07:50:33 -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=ZLWmZ4gZ0b5ddQQFydPTL+LQ6DEUeotOPdTDWfEGoFA=; b=hwL3evYB6duHt1oUdxcRNeLV/Vh9JlcpRbxDadFwg5Vs63QS8qDLsxuMFhUMN+8TZT 0DGfp6SpDEc9gq713goymcU7200pNfSu9vsL82iRqTkn1k0XBmOWm9de2Vv5iUGB7/Ms ZLdP0RotsopXvx5qxe9fsO8YyvaQQTrHDlhm2+Xk+L6Jz/Rh6V7grR7fA/KI9dtFv/DT RPRfZJXUXIJAAGutxHH4yY5U8S4lP6MimFi1YKgi6OmoQV2bjWIHDCw3BDzx6a2avaEK d/4rnRUikj+orAZ/9bgvWyQaWTKFVjaGobb3i+lheXelVPHZM55TpBPo53T6YvDtESOB O5vQ== X-Gm-Message-State: AODbwcA0lFdU8FUYtOZWW20y7JTF+BNQDVvsDRfFmNEDWhUrb0jgboT6 x7rnI0hPbEr+Sw== X-Received: by 10.129.2.2 with SMTP id 2mr9722805ywc.23.1494946232052; Tue, 16 May 2017 07:50:32 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::7:4a1a]) by smtp.googlemail.com with ESMTPSA id r136sm6398149ywg.26.2017.05.16.07.50.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 May 2017 07:50:31 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] OVERLOAD iterators #1 Message-ID: <3e8c0773-23c6-0b33-8ea5-e26bc2bfd8ad@acm.org> Date: Tue, 16 May 2017 10:50:30 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0 MIME-Version: 1.0 This patch implements new iterators for OVERLOADs. There are two iterators: ovl_iterator for a plain iterator, that held on a binding lkp_iterator for the overload set returned by lookup. To use them simply: for (lkp_iterator iter (INIT); iter; ++iter) { tree fn = *iter; ... } Currently the latter simply defers to the former, but I'll be changing lookup so that it can return an overload of overloads. (Right now it simply flattens things, which is sub-optimal). This changes the easier cases of iteration to use these. I'll be working through the other cases to convert them. nathan 2017-05-16 Nathan Sidwell * cp-tree.h (class ovl_iterator, class lkp_iterator): New OVERLOAD iterators. (MAYBE_BASELINK_FUNCTIONS): New. * constraint.cc (resolve_constraint_check): Use lkp_iterator. * decl2.c (maybe_warn_sized_delete): Use ovl_iterator. * lambda.c (maybe_generic_this_capture): Use lkp_iterator. * method.c (inherited_ctor_binfo): Use ovl_iterator. (binfo_inherited_from): Likewise. * parser.c (lookup_literal_operator): Use lkp_iterator. * pt.c (iterative_hash_template_arg): Use lkp_iterator. (print_candidates_1): Likewise. (determine_specialization): Likewise. (resolve_overloaded_unification): Likewise. (resolve_nondeduced_context): Likewise. (type_dependent_expression_p): Likewise. (dependent_template_p): Likewise. * ptree.c (cxx_print_xnode): Likewise. * semantics.c (omp_reduction_lookup): Use lkp_iterator. (classtype_has_nothrow_assign_or_copy_p): Use ovl_iterator. * typeck.c (check_template_keyword): Use lkp_iterator. Index: constraint.cc =================================================================== --- constraint.cc (revision 248109) +++ constraint.cc (working copy) @@ -204,10 +204,10 @@ resolve_constraint_check (tree ovl, tree { int nerrs = 0; tree cands = NULL_TREE; - for (tree p = ovl; p != NULL_TREE; p = OVL_NEXT (p)) + for (lkp_iterator iter (ovl); iter; ++iter) { // Get the next template overload. - tree tmpl = OVL_CURRENT (p); + tree tmpl = *iter; if (TREE_CODE (tmpl) != TEMPLATE_DECL) continue; Index: cp-tree.h =================================================================== --- cp-tree.h (revision 248109) +++ cp-tree.h (working copy) @@ -636,6 +636,62 @@ struct GTY(()) tree_overload { tree function; }; +/* Iterator for a 1 dimensional overload. */ + +class ovl_iterator +{ + tree ovl; + + public: + ovl_iterator (tree o) + :ovl (o) + {} + + ovl_iterator &operator= (const ovl_iterator &from) + { + ovl = from.ovl; + + return *this; + } + + public: + operator bool () const + { + return ovl; + } + ovl_iterator &operator++ () + { + ovl = TREE_CODE (ovl) != OVERLOAD ? NULL_TREE : OVL_CHAIN (ovl); + return *this; + } + tree operator* () const + { + tree fn = TREE_CODE (ovl) != OVERLOAD ? ovl : OVL_FUNCTION (ovl); + + /* Check this is not an unexpected 2-dimensional overload. */ + gcc_checking_assert (TREE_CODE (fn) != OVERLOAD); + + return fn; + } +}; + +/* Iterator over a (potentially) 2 dimensional overload, which is + produced by name lookup. */ + +/* Note this is currently a placeholder, as the name-lookup changes + are not yet committed. */ + +class lkp_iterator : public ovl_iterator +{ + typedef ovl_iterator parent; + + public: + lkp_iterator (tree o) + : parent (o) + { + } +}; + struct GTY(()) tree_template_decl { struct tree_decl_common common; tree arguments; @@ -653,6 +709,10 @@ struct GTY(()) tree_template_decl { a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR. */ #define BASELINK_FUNCTIONS(NODE) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->functions) +/* If T is a BASELINK, grab the functions, otherwise just T, which is + expected to already be a (list of) functions. */ +#define MAYBE_BASELINK_FUNCTIONS(T) \ + (BASELINK_P (T) ? BASELINK_FUNCTIONS (T) : T) /* The BINFO in which the search for the functions indicated by this baselink began. This base is used to determine the accessibility of functions selected by overload resolution. */ Index: decl2.c =================================================================== --- decl2.c (revision 248109) +++ decl2.c (working copy) @@ -4390,10 +4390,10 @@ maybe_warn_sized_delete (enum tree_code tree sized = NULL_TREE; tree unsized = NULL_TREE; - for (tree ovl = IDENTIFIER_GLOBAL_VALUE (cp_operator_id (code)); - ovl; ovl = OVL_NEXT (ovl)) + for (ovl_iterator iter (IDENTIFIER_GLOBAL_VALUE (cp_operator_id (code))); + iter; ++iter) { - tree fn = OVL_CURRENT (ovl); + tree fn = *iter; /* We're only interested in usual deallocation functions. */ if (!usual_deallocation_fn_p (fn)) continue; Index: lambda.c =================================================================== --- lambda.c (revision 248109) +++ lambda.c (working copy) @@ -841,18 +841,15 @@ maybe_generic_this_capture (tree object, bool id_expr = TREE_CODE (fns) == TEMPLATE_ID_EXPR; if (id_expr) fns = TREE_OPERAND (fns, 0); - for (; fns; fns = OVL_NEXT (fns)) - { - tree fn = OVL_CURRENT (fns); - if ((!id_expr || TREE_CODE (fn) == TEMPLATE_DECL) - && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) - { - /* Found a non-static member. Capture this. */ - lambda_expr_this_capture (lam, true); - break; - } - } + for (lkp_iterator iter (fns); iter; ++iter) + if ((!id_expr || TREE_CODE (*iter) == TEMPLATE_DECL) + && DECL_NONSTATIC_MEMBER_FUNCTION_P (*iter)) + { + /* Found a non-static member. Capture this. */ + lambda_expr_this_capture (lam, true); + break; + } } } Index: method.c =================================================================== --- method.c (revision 248109) +++ method.c (working copy) @@ -538,9 +538,9 @@ inherited_ctor_binfo (tree binfo, tree f return binfo; tree results = NULL_TREE; - for (; inh; inh = OVL_NEXT (inh)) + for (ovl_iterator iter (inh); iter; ++iter) { - tree one = inherited_ctor_binfo_1 (binfo, OVL_CURRENT (inh)); + tree one = inherited_ctor_binfo_1 (binfo, *iter); if (!results) results = one; else if (one != results) @@ -593,9 +593,9 @@ binfo_inherited_from (tree binfo, tree i { /* inh is an OVERLOAD if we inherited the same constructor along multiple paths, check all of them. */ - for (; inh; inh = OVL_NEXT (inh)) + for (ovl_iterator iter (inh); iter; ++iter) { - tree fn = OVL_CURRENT (inh); + tree fn = *iter; tree base = DECL_CONTEXT (fn); tree base_binfo = NULL_TREE; for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) Index: parser.c =================================================================== --- parser.c (revision 248109) +++ parser.c (working copy) @@ -4061,16 +4061,16 @@ cp_parser_string_literal (cp_parser *par static tree lookup_literal_operator (tree name, vec *args) { - tree decl, fns; + tree decl; decl = lookup_name (name); if (!decl || !is_overloaded_fn (decl)) return error_mark_node; - for (fns = decl; fns; fns = OVL_NEXT (fns)) + for (lkp_iterator iter (decl); iter; ++iter) { unsigned int ix; bool found = true; - tree fn = OVL_CURRENT (fns); + tree fn = *iter; tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); if (parmtypes != NULL_TREE) { Index: pt.c =================================================================== --- pt.c (revision 248109) +++ pt.c (working copy) @@ -1746,8 +1746,8 @@ iterative_hash_template_arg (tree arg, h return val; case OVERLOAD: - for (; arg; arg = OVL_NEXT (arg)) - val = iterative_hash_template_arg (OVL_CURRENT (arg), val); + for (lkp_iterator iter (arg); iter; ++iter) + val = iterative_hash_template_arg (*iter, val); return val; case CONSTRUCTOR: @@ -1926,15 +1926,15 @@ print_candidates_1 (tree fns, char **str for (; fns; fns = TREE_CHAIN (fns)) print_candidates_1 (TREE_VALUE (fns), str, more || TREE_CHAIN (fns)); else - while (fns) + for (lkp_iterator iter (fns); iter;) { - tree cand = OVL_CURRENT (fns); + tree cand = *iter; + ++iter; - fns = OVL_NEXT (fns); const char *pfx = *str; if (!pfx) { - if (more || fns) + if (more || iter) pfx = _("candidates are:"); else pfx = _("candidate is:"); @@ -2102,9 +2102,9 @@ determine_specialization (tree template_ if (targs != error_mark_node) templates = tree_cons (targs, fns, templates); } - else for (; fns; fns = OVL_NEXT (fns)) + else for (lkp_iterator iter (fns); iter; ++iter) { - tree fn = OVL_CURRENT (fns); + tree fn = *iter; if (TREE_CODE (fn) == TEMPLATE_DECL) { @@ -19379,9 +19379,9 @@ resolve_overloaded_unification (tree tpa tree expl_subargs = TREE_OPERAND (arg, 1); arg = TREE_OPERAND (arg, 0); - for (; arg; arg = OVL_NEXT (arg)) + for (lkp_iterator iter (arg); iter; ++iter) { - tree fn = OVL_CURRENT (arg); + tree fn = *iter; tree subargs, elem; if (TREE_CODE (fn) != TEMPLATE_DECL) @@ -19420,15 +19420,17 @@ resolve_overloaded_unification (tree tpa not just the function on its own. */ return false; else - for (; arg; arg = OVL_NEXT (arg)) - if (try_one_overload (tparms, targs, tempargs, parm, - TREE_TYPE (OVL_CURRENT (arg)), - strict, sub_strict, addr_p, explain_p) - && (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg)))) - { - goodfn = OVL_CURRENT (arg); - ++good; - } + for (lkp_iterator iter (arg); iter; ++iter) + { + tree fn = *iter; + if (try_one_overload (tparms, targs, tempargs, parm, TREE_TYPE (fn), + strict, sub_strict, addr_p, explain_p) + && (!goodfn || !decls_match (goodfn, fn))) + { + goodfn = fn; + ++good; + } + } /* [temp.deduct.type] A template-argument can be deduced from a pointer to function or pointer to member function argument if the set of @@ -19510,9 +19512,9 @@ resolve_nondeduced_context (tree orig_ex tree badfn = NULL_TREE; tree badargs = NULL_TREE; - for (; arg; arg = OVL_NEXT (arg)) + for (lkp_iterator iter (arg); iter; ++iter) { - tree fn = OVL_CURRENT (arg); + tree fn = *iter; tree subargs, elem; if (TREE_CODE (fn) != TEMPLATE_DECL) @@ -23926,12 +23928,10 @@ type_dependent_expression_p (tree expres gcc_assert (TREE_CODE (expression) == OVERLOAD || TREE_CODE (expression) == FUNCTION_DECL); - while (expression) - { - if (type_dependent_expression_p (OVL_CURRENT (expression))) - return true; - expression = OVL_NEXT (expression); - } + for (lkp_iterator iter (expression); iter; ++iter) + if (type_dependent_expression_p (*iter)) + return true; + return false; } @@ -24284,12 +24284,9 @@ dependent_template_p (tree tmpl) { if (TREE_CODE (tmpl) == OVERLOAD) { - while (tmpl) - { - if (dependent_template_p (OVL_CURRENT (tmpl))) - return true; - tmpl = OVL_NEXT (tmpl); - } + for (lkp_iterator iter (tmpl); iter; ++iter) + if (dependent_template_p (*iter)) + return true; return false; } Index: ptree.c =================================================================== --- ptree.c (revision 248109) +++ ptree.c (working copy) @@ -236,8 +236,9 @@ cxx_print_xnode (FILE *file, tree node, indent + 4); break; case OVERLOAD: - print_node (file, "function", OVL_FUNCTION (node), indent+4); - print_node (file, "chain", TREE_CHAIN (node), indent+4); + print_node (file, "name", OVL_NAME (node), indent+4); + for (lkp_iterator iter (node); iter; ++iter) + print_node (file, "function", *iter, indent+4); break; case TEMPLATE_PARM_INDEX: print_node (file, "decl", TEMPLATE_PARM_DECL (node), indent+4); Index: semantics.c =================================================================== --- semantics.c (revision 248109) +++ semantics.c (working copy) @@ -5205,26 +5205,33 @@ omp_reduction_lookup (location_t loc, tr type), false, false); tree fns = id; - if (id && is_overloaded_fn (id)) - id = get_fns (id); - for (; id; id = OVL_NEXT (id)) + id = NULL_TREE; + if (fns && is_overloaded_fn (fns)) { - tree fndecl = OVL_CURRENT (id); - if (TREE_CODE (fndecl) == FUNCTION_DECL) + for (lkp_iterator iter (get_fns (fns)); iter; ++iter) { - tree argtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); - if (same_type_p (TREE_TYPE (argtype), type)) - break; + tree fndecl = *iter; + if (TREE_CODE (fndecl) == FUNCTION_DECL) + { + tree argtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); + if (same_type_p (TREE_TYPE (argtype), type)) + { + id = fndecl; + break; + } + } + } + + if (id && BASELINK_P (fns)) + { + if (baselinkp) + *baselinkp = fns; + else + baselink = fns; } } - if (id && BASELINK_P (fns)) - { - if (baselinkp) - *baselinkp = fns; - else - baselink = fns; - } - if (id == NULL_TREE && CLASS_TYPE_P (type) && TYPE_BINFO (type)) + + if (!id && CLASS_TYPE_P (type) && TYPE_BINFO (type)) { vec ambiguous = vNULL; tree binfo = TYPE_BINFO (type), base_binfo, ret = NULL_TREE; @@ -9062,9 +9069,9 @@ classtype_has_nothrow_assign_or_copy_p ( else return false; - for (; fns; fns = OVL_NEXT (fns)) + for (ovl_iterator iter (fns); iter; ++iter) { - tree fn = OVL_CURRENT (fns); + tree fn = *iter; if (assign_p) { Index: typeck.c =================================================================== --- typeck.c (revision 248109) +++ typeck.c (working copy) @@ -2628,23 +2628,20 @@ check_template_keyword (tree decl) permerror (input_location, "%qD is not a template", decl); else { - tree fns; - fns = decl; - if (BASELINK_P (fns)) - fns = BASELINK_FUNCTIONS (fns); - while (fns) + bool found = false; + + for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (decl)); + !found && iter; ++iter) { - tree fn = OVL_CURRENT (fns); + tree fn = *iter; if (TREE_CODE (fn) == TEMPLATE_DECL - || TREE_CODE (fn) == TEMPLATE_ID_EXPR) - break; - if (TREE_CODE (fn) == FUNCTION_DECL - && DECL_USE_TEMPLATE (fn) - && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (fn))) - break; - fns = OVL_NEXT (fns); + || TREE_CODE (fn) == TEMPLATE_ID_EXPR + || (TREE_CODE (fn) == FUNCTION_DECL + && DECL_USE_TEMPLATE (fn) + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))) + found = true; } - if (!fns) + if (!found) permerror (input_location, "%qD is not a template", decl); } }