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

	PR c++/85634
	* cp-tree.h (lookup_keep): Drop KEEP parm.
	(lookup_list_keep): Delete.
	(maybe_get_fns): Declare.
	* parser.c (cp_parser_primary_expression): Call lookup_keep here.
	(cp_parser_template_id): Not here ...
	* decl.c (cp_finish_decl): ... nor here ...
	* init.c (build_raw_new_expr): ... nor here ...
	* pt.c (process_template_parm): ... nor here ...
	* semantics.c (perform_koenig_lookup): Call lookup_keep.
	(finish_call_expr): Not here.
	* tree.c (ovl_cache): Delete.
	(ovl_make, ovl_copy): No cache.
	(lookup_keep): Always keep.
	(lookup_list_keep): Delete.
	(maybe_get_fns): New, broken out of ...
	(get_fns): ... here.  Call it.
	(built_min_nt_loc, build_min, build_min_non_dep): Drop lookup_keep.
	(build_min_nt_call_vec): Likewise.

	PR c++/85634
	* g++.dg/lookup/pr85634.C: New.

Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 261799)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -7094,11 +7094,11 @@ extern void lookup_mark				(tree lookup,
 extern tree lookup_add				(tree fns, tree lookup);
 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 void lookup_keep				(tree lookup);
 extern int is_overloaded_fn			(tree) ATTRIBUTE_PURE;
 extern bool really_overloaded_fn		(tree) ATTRIBUTE_PURE;
 extern tree dependent_name			(tree);
+extern tree maybe_get_fns			(tree) ATTRIBUTE_PURE;
 extern tree get_fns				(tree) ATTRIBUTE_PURE;
 extern tree get_first_fn			(tree) ATTRIBUTE_PURE;
 extern tree ovl_scope				(tree);
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 261799)
+++ gcc/cp/decl.c	(working copy)
@@ -6973,11 +6973,8 @@ cp_finish_decl (tree decl, tree init, bo
 	}
 
       if (init)
-	{
-	  if (TREE_CODE (init) == TREE_LIST)
-	    lookup_list_keep (init, true);
-	  DECL_INITIAL (decl) = init;
-	}
+	DECL_INITIAL (decl) = init;
+
       if (dep_init)
 	{
 	  retrofit_lang_decl (decl);
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	(revision 261799)
+++ gcc/cp/init.c	(working copy)
@@ -2403,12 +2403,7 @@ build_raw_new_expr (vec<tree, va_gc> *pl
   else if (init->is_empty ())
     init_list = void_node;
   else
-    {
-      init_list = build_tree_list_vec (init);
-      for (tree v = init_list; v; v = TREE_CHAIN (v))
-	if (TREE_CODE (TREE_VALUE (v)) == OVERLOAD)
-	  lookup_keep (TREE_VALUE (v), true);
-    }
+    init_list = build_tree_list_vec (init);
 
   new_expr = build4 (NEW_EXPR, build_pointer_type (type),
 		     build_tree_list_vec (placement), type, nelts,
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 261799)
+++ gcc/cp/parser.c	(working copy)
@@ -5603,6 +5603,14 @@ cp_parser_primary_expression (cp_parser
 	      }
 	  }
 
+	if (processing_template_decl)
+	  if (tree fns = maybe_get_fns (decl))
+	    /* It's too difficult to mark ths in all the places where
+	       we know for sure we need to keep the lookup, so do it
+	       now.  The cost is extra GC to recycle the lookups
+	       resolved at parse time.  */
+	    lookup_keep (fns);
+
 	decl = (finish_id_expression
 		(id_expression, decl, parser->scope,
 		 idk,
@@ -15989,11 +15997,6 @@ cp_parser_template_id (cp_parser *parser
       token->type = CPP_TEMPLATE_ID;
       token->location = combined_loc;
 
-      /* We must mark the lookup as kept, so we don't throw it away on
-	 the first parse.  */
-      if (is_overloaded_fn (template_id))
-	lookup_keep (get_fns (template_id), true);
-
       /* Retrieve any deferred checks.  Do not pop this access checks yet
 	 so the memory will not be reclaimed during token replacing below.  */
       token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 261799)
+++ gcc/cp/pt.c	(working copy)
@@ -4431,9 +4431,6 @@ process_template_parm (tree list, locati
 
   pushdecl (decl);
 
-  if (defval && TREE_CODE (defval) == OVERLOAD)
-    lookup_keep (defval, true);
-  
   /* Build the parameter node linking the parameter declaration,
      its default argument (if any), and its constraints (if any). */
   parm = build_tree_list (defval, parm);
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 261799)
+++ gcc/cp/semantics.c	(working copy)
@@ -2325,6 +2325,11 @@ perform_koenig_lookup (cp_expr fn, vec<t
 	  else
 	    fn = identifier;
 	}
+      else if (TREE_CODE (fn) == OVERLOAD && processing_template_decl)
+	/* FIXME: We shouldn't really need to mark the lookup here, as
+	   resolving the (non-dependent) call should save the single
+	   function we resolve to.  Related to PR c++/83529.  */
+	lookup_keep (fn);
     }
 
   if (fn && template_id && fn != error_mark_node)
@@ -2385,10 +2390,7 @@ finish_call_expr (tree fn, vec<tree, va_
 	  SET_EXPR_LOCATION (result, cp_expr_loc_or_loc (fn, input_location));
 	  KOENIG_LOOKUP_P (result) = koenig_p;
 	  if (is_overloaded_fn (fn))
-	    {
-	      fn = get_fns (fn);
-	      lookup_keep (fn, true);
-	    }
+	    fn = get_fns (fn);
 
 	  if (cfun)
 	    {
@@ -2575,10 +2577,6 @@ finish_call_expr (tree fn, vec<tree, va_
       result = convert_from_reference (result);
     }
 
-  /* Free or retain OVERLOADs from lookup.  */
-  if (is_overloaded_fn (orig_fn))
-    lookup_keep (get_fns (orig_fn), processing_template_decl);
-
   return result;
 }
 
Index: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c	(revision 261799)
+++ gcc/cp/tree.c	(working copy)
@@ -2131,25 +2131,12 @@ build_ref_qualified_type (tree type, cp_
   return build_cp_fntype_variant (type, rqual, raises, late);
 }
 
-/* Cache of free ovl nodes.  Uses OVL_FUNCTION for chaining.  */
-static GTY((deletable)) tree ovl_cache;
-
 /* Make a raw overload node containing FN.  */
 
 tree
 ovl_make (tree fn, tree next)
 {
-  tree result = ovl_cache;
-
-  if (result)
-    {
-      ovl_cache = OVL_FUNCTION (result);
-      /* Zap the flags.  */
-      memset (result, 0, sizeof (tree_base));
-      TREE_SET_CODE (result, OVERLOAD);
-    }
-  else
-    result = make_node (OVERLOAD);
+  tree result = make_node (OVERLOAD);
 
   if (TREE_CODE (fn) == OVERLOAD)
     OVL_NESTED_P (result) = true;
@@ -2164,17 +2151,7 @@ ovl_make (tree fn, tree next)
 static tree
 ovl_copy (tree ovl)
 {
-  tree result = ovl_cache;
-
-  if (result)
-    {
-      ovl_cache = OVL_FUNCTION (result);
-      /* Zap the flags.  */
-      memset (result, 0, sizeof (tree_base));
-      TREE_SET_CODE (result, OVERLOAD);
-    }
-  else
-    result = make_node (OVERLOAD);
+  tree result = make_node (OVERLOAD);
 
   gcc_checking_assert (!OVL_NESTED_P (ovl) && OVL_USED_P (ovl));
   TREE_TYPE (result) = TREE_TYPE (ovl);
@@ -2413,44 +2390,22 @@ ovl_used (tree ovl)
     }
 }
 
-/* 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.  */
+/* Preserve the contents of a lookup so that it is available for a
+   later instantiation.  */
 
 void
-lookup_keep (tree lookup, bool keep)
+lookup_keep (tree lookup)
 {
   for (;
        lookup && TREE_CODE (lookup) == OVERLOAD
 	 && OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup);
        lookup = OVL_CHAIN (lookup))
-    if (keep)
-      {
-	OVL_USED_P (lookup) = true;
-	ovl_used (OVL_FUNCTION (lookup));
-      }
-    else
-      {
-	OVL_FUNCTION (lookup) = ovl_cache;
-	ovl_cache = lookup;
-      }
-
-  if (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);
+      OVL_USED_P (lookup) = true;
+      ovl_used (OVL_FUNCTION (lookup));
     }
+
+  ovl_used (lookup);
 }
 
 /* Returns nonzero if X is an expression for a (possibly overloaded)
@@ -2505,10 +2460,11 @@ really_overloaded_fn (tree x)
   return is_overloaded_fn (x) == 2;
 }
 
-/* Get the overload set FROM refers to.  */
+/* Get the overload set FROM refers to.  Returns NULL if it's not an
+   overload set.  */
 
 tree
-get_fns (tree from)
+maybe_get_fns (tree from)
 {
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (from) == OFFSET_REF
@@ -2518,9 +2474,23 @@ get_fns (tree from)
     from = BASELINK_FUNCTIONS (from);
   if (TREE_CODE (from) == TEMPLATE_ID_EXPR)
     from = TREE_OPERAND (from, 0);
-  gcc_assert (TREE_CODE (from) == OVERLOAD
-	      || TREE_CODE (from) == FUNCTION_DECL);
-  return from;
+
+  if (TREE_CODE (from) == OVERLOAD
+      || TREE_CODE (from) == FUNCTION_DECL)
+    return from;
+
+  return NULL;
+}
+
+/* FROM refers to an overload set.  Return that set (or die).  */
+
+tree
+get_fns (tree from)
+{
+  tree res = maybe_get_fns (from);
+
+  gcc_assert (res);
+  return res;
 }
 
 /* Return the first function of the overload set FROM refers to.  */
@@ -3306,12 +3276,7 @@ build_min_nt_loc (location_t loc, enum t
   length = TREE_CODE_LENGTH (code);
 
   for (i = 0; i < length; i++)
-    {
-      tree x = va_arg (p, tree);
-      TREE_OPERAND (t, i) = x;
-      if (x && TREE_CODE (x) == OVERLOAD)
-	lookup_keep (x, true);
-    }
+    TREE_OPERAND (t, i) = va_arg (p, tree);
 
   va_end (p);
   return t;
@@ -3339,21 +3304,12 @@ build_min (enum tree_code code, tree tt,
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
-      if (x)
-	{
-	  if (!TYPE_P (x) && TREE_SIDE_EFFECTS (x))
-	    TREE_SIDE_EFFECTS (t) = 1;
-	  if (TREE_CODE (x) == OVERLOAD)
-	    lookup_keep (x, true);
-	}
+      if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x))
+	TREE_SIDE_EFFECTS (t) = 1;
     }
 
   va_end (p);
 
-  if (code == CAST_EXPR)
-    /* The single operand is a TREE_LIST, which we have to check.  */
-    lookup_list_keep (TREE_OPERAND (t, 0), true);
-
   return t;
 }
 
@@ -3382,12 +3338,7 @@ build_min_non_dep (enum tree_code code,
   TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
 
   for (i = 0; i < length; i++)
-    {
-      tree x = va_arg (p, tree);
-      TREE_OPERAND (t, i) = x;
-      if (x && TREE_CODE (x) == OVERLOAD)
-	lookup_keep (x, true);
-    }
+    TREE_OPERAND (t, i) = va_arg (p, tree);
 
   if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
     /* This should not be considered a COMPOUND_EXPR, because it
@@ -3410,11 +3361,8 @@ build_min_nt_call_vec (tree fn, vec<tree
   CALL_EXPR_FN (ret) = fn;
   CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
   FOR_EACH_VEC_SAFE_ELT (args, ix, t)
-    {
-      CALL_EXPR_ARG (ret, ix) = t;
-      if (TREE_CODE (t) == OVERLOAD)
-	lookup_keep (t, true);
-    }
+    CALL_EXPR_ARG (ret, ix) = t;
+
   return ret;
 }
 
Index: gcc/testsuite/g++.dg/lookup/pr85634.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/pr85634.C	(revision 0)
+++ gcc/testsuite/g++.dg/lookup/pr85634.C	(working copy)
@@ -0,0 +1,18 @@
+// PR c++/85634 ICE managing lookup set
+
+namespace N {
+  template <class T> void Foo (T *const &);
+}
+
+using namespace N;
+
+template<class T> void Foo (const T &);
+
+
+template <class T>
+void Frob()
+{
+  void (*op)(const T&) = Foo;
+}
+
+template void Frob<int *>();
