This patch fixes the second case reported in 80891. We were asserting
the wrong thing -- the node could well be a lookup, but it must be
marked USED (otherwise there's no need to copy it). I also noticed that
in marking a lookup, we were not marking the underlying overloads as
used -- which is part of the point so that future pushdecls know the
overload is immutable.
I thought I had a testcase for that, so I'm not sure how it slipped
through. Will try and create a more robust testcase later.
nathan
--
Nathan Sidwell
2017-05-29 Nathan Sidwell <nat...@acm.org>
PR c++/80891 (#2)
* tree.c (ovl_copy): Adjust assert, copy OVL_LOOKUP.
(ovl_used): New.
(lookup_keep): Call it.
PR c++/80891 (#2)
* g++.dg/lookup/pr80891-2.C: New.
Index: cp/tree.c
===================================================================
--- cp/tree.c (revision 248520)
+++ cp/tree.c (working copy)
@@ -2139,12 +2139,13 @@ ovl_copy (tree ovl)
else
result = make_node (OVERLOAD);
- gcc_assert (!OVL_NESTED_P (ovl) && !OVL_LOOKUP_P (ovl));
+ gcc_checking_assert (!OVL_NESTED_P (ovl) && OVL_USED_P (ovl));
TREE_TYPE (result) = TREE_TYPE (ovl);
OVL_FUNCTION (result) = OVL_FUNCTION (ovl);
OVL_CHAIN (result) = OVL_CHAIN (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;
}
@@ -2395,6 +2396,22 @@ lookup_maybe_add (tree fns, tree lookup)
return lookup_add (fns, lookup);
}
+/* Regular overload OVL is part of a kept lookup. Mark the nodes on
+ it as immutable. */
+
+static void
+ovl_used (tree ovl)
+{
+ for (;
+ ovl && TREE_CODE (ovl) == OVERLOAD
+ && !OVL_USED_P (ovl);
+ ovl = OVL_CHAIN (ovl))
+ {
+ gcc_checking_assert (!OVL_LOOKUP_P (ovl));
+ OVL_USED_P (ovl) = true;
+ }
+}
+
/* If KEEP is true, preserve the contents of a lookup so that it is
available for a later instantiation. Otherwise release the LOOKUP
nodes for reuse. */
@@ -2407,12 +2424,18 @@ lookup_keep (tree lookup, bool keep)
&& OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup);
lookup = OVL_CHAIN (lookup))
if (keep)
- OVL_USED_P (lookup) = true;
+ {
+ OVL_USED_P (lookup) = true;
+ ovl_used (OVL_FUNCTION (lookup));
+ }
else
{
OVL_FUNCTION (lookup) = ovl_cache;
ovl_cache = lookup;
}
+
+ if (keep)
+ ovl_used (lookup);
}
/* Returns nonzero if X is an expression for a (possibly overloaded)
Index: testsuite/g++.dg/lookup/pr80891-2.C
===================================================================
--- testsuite/g++.dg/lookup/pr80891-2.C (revision 0)
+++ testsuite/g++.dg/lookup/pr80891-2.C (working copy)
@@ -0,0 +1,29 @@
+// PR c++/80891 part 1
+// instantiation-time ADL for swap needs to copy a previous lookup
+// node, but gets confused.
+
+void swap();
+
+namespace boost {
+ void swap();
+}
+
+using namespace boost;
+
+template <typename T>
+void reversible_container_test ()
+{
+ using namespace boost;
+ T a;
+ swap (a);
+}
+
+namespace boost {
+ struct A {};
+ template <typename T> void swap(T);
+}
+
+void test_ptr_vector()
+{
+ reversible_container_test<A>;
+}