My recent relaxing of overload ordering broken an invariant that
unhiding a hidden decl was assuming. Fixed thusly.
nathan
--
Nathan Sidwell
2018-11-07 Nathan Sidwell <nat...@acm.org>
PR c++/87904
* cp-tree.h (struct tree_overload): Fix comment.
* tree.c (ovl_iterator::reveal_node): Propagate OVL_DEDUP_P.
PR c++/87904
* g++.dg/lookup/pr87904.C: New.
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h (revision 265851)
+++ gcc/cp/cp-tree.h (working copy)
@@ -723,8 +723,7 @@ typedef struct ptrmem_cst * ptrmem_cst_t
#define OVL_SINGLE_P(NODE) \
(TREE_CODE (NODE) != OVERLOAD || !OVL_CHAIN (NODE))
-/* OVL_HIDDEN_P nodes come first, then OVL_USING_P nodes, then regular
- fns. */
+/* OVL_HIDDEN_P nodes come before other nodes. */
struct GTY(()) tree_overload {
struct tree_common common;
Index: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c (revision 265851)
+++ gcc/cp/tree.c (working copy)
@@ -2261,13 +2261,17 @@ ovl_iterator::reveal_node (tree overload
OVL_HIDDEN_P (node) = false;
if (tree chain = OVL_CHAIN (node))
- if (TREE_CODE (chain) == OVERLOAD
- && (OVL_USING_P (chain) || OVL_HIDDEN_P (chain)))
+ if (TREE_CODE (chain) == OVERLOAD)
{
- /* The node needs moving, and the simplest way is to remove it
- and reinsert. */
- overload = remove_node (overload, node);
- overload = ovl_insert (OVL_FUNCTION (node), overload);
+ if (OVL_HIDDEN_P (chain))
+ {
+ /* The node needs moving, and the simplest way is to remove it
+ and reinsert. */
+ overload = remove_node (overload, node);
+ overload = ovl_insert (OVL_FUNCTION (node), overload);
+ }
+ else if (OVL_DEDUP_P (chain))
+ OVL_DEDUP_P (node) = true;
}
return overload;
}
Index: gcc/testsuite/g++.dg/lookup/pr87904.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/pr87904.C (nonexistent)
+++ gcc/testsuite/g++.dg/lookup/pr87904.C (working copy)
@@ -0,0 +1,21 @@
+// PR c++ 87904 ICE failing to initiate deduping
+
+namespace X {
+ void Foo (char);
+}
+
+struct B {
+ friend void Foo (int);
+};
+
+using X::Foo;
+
+void Foo (float);
+void Foo(int);
+
+void frob ()
+{
+ using namespace X;
+
+ Foo (1);
+}