diff mbox series

[PR,c++/84970] lookup marking

Message ID 104ba059-2270-d992-c2f5-94588d7ecdf2@acm.org
State New
Headers show
Series [PR,c++/84970] lookup marking | expand

Commit Message

Nathan Sidwell March 20, 2018, 3:54 p.m. UTC
This is another case of lookups escaping into template bodies, without 
being marked.  In this case an initializer list.

in the non-template case, we try and recycle these lookup nodes 
immediately.  But for templates we have to mark lookups, so we don't try 
and mutate them via the binding.  When the lookup involved via a using 
directive we can detect the marking failure.

nathan
diff mbox series

Patch

2018-03-20  Nathan Sidwell  <nathan@acm.org>

	PR c++/84970
	* cp-tree.h (lookup_list_keep): Declare.
	* tree.c (lookup_list_keep): New, broken out of ...
	(build_min): ... here.  Call it.
	* decl.c (cp_finish_decl): Call lookup_list_keep.

	PR c++/84970
	* g++.dg/lookup/pr84970.C: New.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 258676)
+++ cp/cp-tree.h	(working copy)
@@ -7012,6 +7012,7 @@  extern tree lookup_add				(tree fns, tre
 extern tree lookup_maybe_add			(tree fns, tree lookup,
 						 bool deduping);
 extern void lookup_keep				(tree lookup, bool keep);
+extern void lookup_list_keep			(tree list, bool keep);
 extern int is_overloaded_fn			(tree) ATTRIBUTE_PURE;
 extern bool really_overloaded_fn		(tree) ATTRIBUTE_PURE;
 extern tree dependent_name			(tree);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 258676)
+++ cp/decl.c	(working copy)
@@ -7034,7 +7034,11 @@  cp_finish_decl (tree decl, tree init, bo
 	}
 
       if (init)
-	DECL_INITIAL (decl) = init;
+	{
+	  if (TREE_CODE (init) == TREE_LIST)
+	    lookup_list_keep (init, true);
+	  DECL_INITIAL (decl) = init;
+	}
       if (dep_init)
 	{
 	  retrofit_lang_decl (decl);
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 258676)
+++ cp/tree.c	(working copy)
@@ -2436,6 +2436,20 @@  lookup_keep (tree lookup, bool keep)
     ovl_used (lookup);
 }
 
+/* LIST is a TREE_LIST whose TREE_VALUEs may be OVERLOADS that need
+   keeping, or may be ignored.  */
+
+void
+lookup_list_keep (tree list, bool keep)
+{
+  for (; list; list = TREE_CHAIN (list))
+    {
+      tree v = TREE_VALUE (list);
+      if (TREE_CODE (v) == OVERLOAD)
+	lookup_keep (v, keep);
+    }
+}
+
 /* Returns nonzero if X is an expression for a (possibly overloaded)
    function.  If "f" is a function or function template, "f", "c->f",
    "c.f", "C::f", and "f<int>" will all be considered possibly
@@ -3315,9 +3329,7 @@  build_min (enum tree_code code, tree tt,
 
   if (code == CAST_EXPR)
     /* The single operand is a TREE_LIST, which we have to check.  */
-    for (tree v = TREE_OPERAND (t, 0); v; v = TREE_CHAIN (v))
-      if (TREE_CODE (TREE_VALUE (v)) == OVERLOAD)
-	lookup_keep (TREE_VALUE (v), true);
+    lookup_list_keep (TREE_OPERAND (t, 0), true);
 
   return t;
 }
Index: testsuite/g++.dg/lookup/pr84970.C
===================================================================
--- testsuite/g++.dg/lookup/pr84970.C	(revision 0)
+++ testsuite/g++.dg/lookup/pr84970.C	(working copy)
@@ -0,0 +1,21 @@ 
+// PR c++/84970 ICE with deferred initializer
+
+namespace bob {
+  void a();
+}
+using namespace bob;
+
+void a (int);
+
+template <typename b>
+void *x (b)
+{
+  void (*c)(b) (a);
+
+  return (void *)c;
+}
+
+void d () {
+  x (1);
+}
+