aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/name-lookup.c6
-rw-r--r--gcc/cp/tree.c51
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/lookup/using60.C18
6 files changed, 61 insertions, 31 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d76d317..8e586a1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2018-10-31 Nathan Sidwell <nathan@acm.org>
+
+ * 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 <polacek@redhat.com>
Implement P0892R2, explicit(bool).
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c9427a0..03e8883 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 5b026da..f2d9d22 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 251c344..74018e9 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 8492316..18c3ac6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-31 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/lookup/using60.C: New.
+
2018-10-31 Richard Biener <rguenther@suse.de>
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 0000000..9a275e9
--- /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);
+}