From patchwork Wed Oct 31 12:40:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 991389 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-488728-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="KlqZBacs"; 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 42lScb1Ns1z9s3l for ; Wed, 31 Oct 2018 23:41:01 +1100 (AEDT) Received: (qmail 44121 invoked by alias); 31 Oct 2018 12:40:55 -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 44102 invoked by uid 89); 31 Oct 2018 12:40:54 -0000 Authentication-Results: sourceware.org; auth=none 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=engage, sk:fields_, klass, name-lookup.c X-HELO: mail-yb1-f179.google.com Received: from mail-yb1-f179.google.com (HELO mail-yb1-f179.google.com) (209.85.219.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 31 Oct 2018 12:40:52 +0000 Received: by mail-yb1-f179.google.com with SMTP id d18-v6so6532011yba.4 for ; Wed, 31 Oct 2018 05:40:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=cLhR5qycQ5soxPhWHQCU+F0x+/6VblIJl7PRt33zK/Q=; b=KlqZBacsN0tJoxS10HvDUAtJi9HOrGl76Rvjradur54IXQqlYqGJg3nDoDlnr/+wSd VRAck0gxYu/x4hL81VDwKfHHTlDrEfvNw15GYmkQzh1eXzBjUM7jwOPgj4WJtCHNL4+d CsXieccU8NI52k1u5ictqjZD62VwFXGqYYaFLST56LSRL0oUm17y/5vsRCYkYmq2+03R KuTNXgghxJB+xRUCLGfzokiCzIg1xb+hfkKnmZ7n5v5J/pc/SCjA7HHTvI643Sn9PVNC r08ynk7Iaf0qz3jrBZeZo7wdOIjKAOY/Up2Kxx5najcvCdkyaxxc8fPs1E/YCpt5CdrJ YfSg== Received: from ?IPv6:2620:10d:c0a3:20fb:7903:c84d:a328:45c1? ([2620:10d:c091:200::7:9eec]) by smtp.googlemail.com with ESMTPSA id p133-v6sm7439645ywb.101.2018.10.31.05.40.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 31 Oct 2018 05:40:50 -0700 (PDT) Sender: Nathan Sidwell To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] Simplify overloads Message-ID: <374c8f9b-bc6b-299a-cc30-15d884d1d670@acm.org> Date: Wed, 31 Oct 2018 08:40:49 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 When I redid namespace-scope name lookup I made overload sets ordered hidden, then using, then other. This was with an eye to how modules would need to extend that to add 'exported' on the end. Turns out that's not needed, so we can simplify a bit. This patch changes things so that using and non-using decls are unordered, but still come after the hidden decls. We have to add another flag into the overload though to say whether a set contains a using-decl. That engages de-duplication machinery during the lookup. Previously that machinery could just look at the first (non-hidden) decl to find out it was needed. I've been using a variant of this on the modules branch for some time. booted & tested on x86_64-linux, applying to trunk. nathan 2018-10-31 Nathan Sidwell gcc/cp/ * cp-tree.h (OVL_DEDUP_P): New. * name-lookup.c (name_lookup::add_overload): Check OVL_DEDUP_P. (get_class_binding_direct): Likwise. * tree.c (ovl_make): Propagate OVL_DEDUP_P. (ovl_copy): Copy it. (ovl_insert): Do not keep using-decls ordered. (lookup_maybe_add): Adjust comment. gcc/testsuite/ * g++.dg/lookup/using60.C: New. Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 265671) +++ gcc/cp/cp-tree.h (working copy) @@ -409,6 +409,7 @@ extern GTY(()) tree cp_global_trees[CPTI SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT) REINTERPRET_CAST_P (in NOP_EXPR) ALIGNOF_EXPR_STD_P (in ALIGNOF_EXPR) + OVL_DEDUP_P (in OVERLOAD) 1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -695,6 +696,8 @@ typedef struct ptrmem_cst * ptrmem_cst_t #define OVL_CHAIN(NODE) \ (((struct tree_overload*)OVERLOAD_CHECK (NODE))->common.chain) +/* If set, this or a subsequent overload contains decls that need deduping. */ +#define OVL_DEDUP_P(NODE) TREE_LANG_FLAG_0 (OVERLOAD_CHECK (NODE)) /* If set, this was imported in a using declaration. */ #define OVL_USING_P(NODE) TREE_LANG_FLAG_1 (OVERLOAD_CHECK (NODE)) /* If set, this overload is a hidden decl. */ Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 265671) +++ gcc/cp/name-lookup.c (working copy) @@ -422,7 +422,8 @@ name_lookup::add_overload (tree fns) tree probe = fns; if (flags & LOOKUP_HIDDEN) probe = ovl_skip_hidden (probe); - if (probe && TREE_CODE (probe) == OVERLOAD && OVL_USING_P (probe)) + 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. */ @@ -1260,7 +1261,8 @@ get_class_binding_direct (tree klass, tr if (type_or_fns < 0) /* Don't bother looking for field. We don't want it. */; - else if (!val || (TREE_CODE (val) == OVERLOAD && OVL_USING_P (val))) + else if (!val || (TREE_CODE (val) == OVERLOAD + && OVL_DEDUP_P (val))) /* Dependent using declarations are a 'field', make sure we return that even if we saw an overload already. */ if (tree field_val = fields_linear_search (klass, lookup, Index: gcc/cp/tree.c =================================================================== --- gcc/cp/tree.c (revision 265671) +++ gcc/cp/tree.c (working copy) @@ -2153,6 +2153,8 @@ ovl_make (tree fn, tree next) TREE_TYPE (result) = (next || TREE_CODE (fn) == TEMPLATE_DECL ? unknown_type_node : TREE_TYPE (fn)); + if (next && TREE_CODE (next) == OVERLOAD && OVL_DEDUP_P (next)) + OVL_DEDUP_P (result) = true; OVL_FUNCTION (result) = fn; OVL_CHAIN (result) = next; return result; @@ -2167,64 +2169,54 @@ ovl_copy (tree ovl) TREE_TYPE (result) = TREE_TYPE (ovl); OVL_FUNCTION (result) = OVL_FUNCTION (ovl); OVL_CHAIN (result) = OVL_CHAIN (ovl); + OVL_DEDUP_P (result) = OVL_DEDUP_P (ovl); + OVL_LOOKUP_P (result) = OVL_LOOKUP_P (ovl); OVL_HIDDEN_P (result) = OVL_HIDDEN_P (ovl); OVL_USING_P (result) = OVL_USING_P (ovl); - OVL_LOOKUP_P (result) = OVL_LOOKUP_P (ovl); return result; } /* Add FN to the (potentially NULL) overload set OVL. USING_P is true, if FN is via a using declaration. We also pay attention to - DECL_HIDDEN. Overloads are ordered as hidden, using, regular. */ + DECL_HIDDEN. We keep the hidden decls first, but remaining ones + are unordered. */ tree ovl_insert (tree fn, tree maybe_ovl, bool using_p) { - bool copying = false; /* Checking use only. */ - bool hidden_p = DECL_HIDDEN_P (fn); - int weight = (hidden_p << 1) | (using_p << 0); - - tree result = NULL_TREE; + tree result = maybe_ovl; tree insert_after = NULL_TREE; - /* Find insertion point. */ - while (maybe_ovl && TREE_CODE (maybe_ovl) == OVERLOAD - && (weight < ((OVL_HIDDEN_P (maybe_ovl) << 1) - | (OVL_USING_P (maybe_ovl) << 0)))) + /* Skip hidden. */ + for (; maybe_ovl && TREE_CODE (maybe_ovl) == OVERLOAD + && OVL_HIDDEN_P (maybe_ovl); + maybe_ovl = OVL_CHAIN (maybe_ovl)) { gcc_checking_assert (!OVL_LOOKUP_P (maybe_ovl) - && (!copying || OVL_USED_P (maybe_ovl))); - if (OVL_USED_P (maybe_ovl)) - { - copying = true; - maybe_ovl = ovl_copy (maybe_ovl); - if (insert_after) - OVL_CHAIN (insert_after) = maybe_ovl; - } - if (!result) - result = maybe_ovl; + && !OVL_USED_P (maybe_ovl)); insert_after = maybe_ovl; - maybe_ovl = OVL_CHAIN (maybe_ovl); } - tree trail = fn; + bool hidden_p = DECL_HIDDEN_P (fn); if (maybe_ovl || using_p || hidden_p || TREE_CODE (fn) == TEMPLATE_DECL) { - trail = ovl_make (fn, maybe_ovl); + maybe_ovl = ovl_make (fn, maybe_ovl); if (hidden_p) - OVL_HIDDEN_P (trail) = true; + OVL_HIDDEN_P (maybe_ovl) = true; if (using_p) - OVL_USING_P (trail) = true; + OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true; } + else + maybe_ovl = fn; if (insert_after) { - OVL_CHAIN (insert_after) = trail; + OVL_CHAIN (insert_after) = maybe_ovl; TREE_TYPE (insert_after) = unknown_type_node; } else - result = trail; + result = maybe_ovl; return result; } @@ -2367,7 +2359,8 @@ lookup_maybe_add (tree fns, tree lookup, for (; fns != probe; fns = OVL_CHAIN (fns)) { lookup = lookup_add (OVL_FUNCTION (fns), lookup); - /* Propagate OVL_USING, but OVL_HIDDEN doesn't matter. */ + /* Propagate OVL_USING, but OVL_HIDDEN & + OVL_DEDUP_P don't matter. */ if (OVL_USING_P (fns)) OVL_USING_P (lookup) = true; } Index: gcc/testsuite/g++.dg/lookup/using60.C =================================================================== --- gcc/testsuite/g++.dg/lookup/using60.C (revision 0) +++ gcc/testsuite/g++.dg/lookup/using60.C (working copy) @@ -0,0 +1,18 @@ +// ICE with overloads not ordering using decls. Failed to invoke +// deduping logic + +void remove (const char *); + +namespace std +{ + using ::remove; + + void remove (); +} + +using namespace std; + +void test01 () +{ + remove (0); +}