From 8e82c473f504c32c840daf09a347795b62b46fa3 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 31 Oct 2018 12:42:35 +0000 Subject: [PATCH] [C++ PATCH] Simplify overloads https://gcc.gnu.org/ml/gcc-patches/2018-10/msg02026.html 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. From-SVN: r265679 --- gcc/cp/ChangeLog | 10 ++++++ gcc/cp/cp-tree.h | 3 ++ gcc/cp/name-lookup.c | 6 ++-- gcc/cp/tree.c | 51 ++++++++++++--------------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/g++.dg/lookup/using60.C | 18 ++++++++++ 6 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/using60.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d76d3177a1c..8e586a1f514 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2018-10-31 Nathan Sidwell + + * 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. + 2018-10-30 Marek Polacek Implement P0892R2, explicit(bool). diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c9427a0b624..03e88838cbe 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -409,6 +409,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; 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. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 5b026da59e0..f2d9d222505 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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, tree name, int type_or_fns) 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, diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 251c344f181..74018e97bb7 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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, bool deduping) 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 84923163780..18c3ac64478 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-10-31 Nathan Sidwell + + * g++.dg/lookup/using60.C: New. + 2018-10-31 Richard Biener PR middle-end/70359 diff --git a/gcc/testsuite/g++.dg/lookup/using60.C b/gcc/testsuite/g++.dg/lookup/using60.C new file mode 100644 index 00000000000..9a275e908fa --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/using60.C @@ -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); +} -- 2.30.2