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>;
+}

Reply via email to