+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.
+
2018-06-19 Jason Merrill <jason@redhat.com>
* cp-tree.h (CONSTRUCTOR_NO_IMPLICIT_ZERO): Remove.
}
}
+ 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,
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> ();
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;
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);
}
}
-/* 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)
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
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. */
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;
{
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;
}
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
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;
}