cp-tree.h (OVL_NESTED_P, [...]): New.

* cp-tree.h (OVL_NESTED_P, OVL_LOOKUP_P): New.
	(ovl_first): Move inline definition to end of file.
	(ovl_make, lookup_add): Declare.
	(get_fns, get_first_fn): Make pure.
	* tree.c (ovl_cache): New.
	(ovl_make, lookup_add): New.
	* pt.c (do_class_deduction): Don't add candidates that will be
	elided.

From-SVN: r248121
This commit is contained in:
Nathan Sidwell 2017-05-16 18:29:36 +00:00 committed by Nathan Sidwell
parent a736411aca
commit e09ae85766
4 changed files with 123 additions and 42 deletions

View File

@ -1,7 +1,16 @@
2017-05-16 Nathan Sidwell <nathan@acm.org>
* cp-tree.h (OVL_NESTED_P, OVL_LOOKUP_P): New.
(ovl_first): Move inline definition to end of file.
(ovl_make, lookup_add): Declare.
(get_fns, get_first_fn): Make pure.
* tree.c (ovl_cache): New.
(ovl_make, lookup_add): New.
* pt.c (do_class_deduction): Don't add candidates that will be
elided.
* call.c (build_user_type_conversion_1): Use OVL_FIRST.
(print_error_for_call_faulure): Use OVL_NAME.
(print_error_for_call_failure): Use OVL_NAME.
(build_op_call_1): Use ovl_iterator.
(add_candidates): Use OVL_FIRST & lkp_iterator.
(build_op_delete_call): Use MAYBE_BASELINK_FUNCTIONS &

View File

@ -371,11 +371,13 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
CONSTUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
OVL_NESTED_P (in OVERLOAD)
4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
DECL_TINFO_P (in VAR_DECL)
FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
OVL_LOOKUP_P (in OVERLOAD)
5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
DECL_VTABLE_OR_VTT_P (in VAR_DECL)
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
@ -626,6 +628,11 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
and can be freed afterward. */
#define OVL_ARG_DEPENDENT(NODE) TREE_LANG_FLAG_0 (OVERLOAD_CHECK (NODE))
/* If set, this overload contains a nested overload. */
#define OVL_NESTED_P(NODE) TREE_LANG_FLAG_3 (OVERLOAD_CHECK (NODE))
/* If set, this overload was constructed during lookup. */
#define OVL_LOOKUP_P(NODE) TREE_LANG_FLAG_4 (OVERLOAD_CHECK (NODE))
/* The first decl of an overload. */
#define OVL_FIRST(NODE) ovl_first (NODE)
/* The name of the overload set. */
@ -6733,17 +6740,14 @@ extern tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree);
extern tree build_qualified_name (tree, tree, tree, bool);
extern tree build_ref_qualified_type (tree, cp_ref_qualifier);
inline tree
ovl_first (tree node)
{
while (TREE_CODE (node) == OVERLOAD)
node = OVL_FUNCTION (node);
return node;
}
inline tree ovl_first (tree) ATTRIBUTE_PURE;
extern tree ovl_make (tree fn,
tree next = NULL_TREE);
extern tree lookup_add (tree lookup, tree ovl);
extern int is_overloaded_fn (tree);
extern tree dependent_name (tree);
extern tree get_fns (tree);
extern tree get_first_fn (tree);
extern tree get_fns (tree) ATTRIBUTE_PURE;
extern tree get_first_fn (tree) ATTRIBUTE_PURE;
extern tree ovl_cons (tree, tree);
extern tree build_overload (tree, tree);
extern tree ovl_scope (tree);
@ -7188,6 +7192,16 @@ extern tree cp_ubsan_maybe_instrument_downcast (location_t, tree, tree, tree);
extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
/* Inline bodies. */
inline tree
ovl_first (tree node)
{
while (TREE_CODE (node) == OVERLOAD)
node = OVL_FUNCTION (node);
return node;
}
/* -- end of C++ */
#endif /* ! GCC_CP_TREE_H */

View File

@ -25157,9 +25157,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
tree cands = lookup_qualified_name (CP_DECL_CONTEXT (tmpl), dname,
/*type*/false, /*complain*/false,
/*hidden*/false);
bool elided = false;
if (cands == error_mark_node)
cands = NULL_TREE;
/* Prune explicit deduction guides in copy-initialization context. */
if (flags & LOOKUP_ONLYCONVERTING)
{
for (lkp_iterator iter (cands); !elided && iter; ++iter)
if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
elided = true;
if (elided)
{
/* Found a nonconverting guide, prune the candidates. */
tree pruned = NULL_TREE;
for (lkp_iterator iter (cands); iter; ++iter)
if (!DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
pruned = lookup_add (pruned, *iter);
cands = pruned;
}
}
tree outer_args = NULL_TREE;
if (DECL_CLASS_SCOPE_P (tmpl)
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (tmpl)))
@ -25171,11 +25191,15 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
bool saw_ctor = false;
if (CLASSTYPE_METHOD_VEC (type))
// FIXME cache artificial deduction guides
for (tree fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type));
iter; ++iter)
{
tree fn = OVL_CURRENT (fns);
tree guide = build_deduction_guide (fn, outer_args, complain);
cands = ovl_cons (guide, cands);
tree guide = build_deduction_guide (*iter, outer_args, complain);
if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
elided = true;
else
cands = lookup_add (cands, guide);
saw_ctor = true;
}
@ -25183,41 +25207,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
if (!saw_ctor && args->length() == 0)
{
tree guide = build_deduction_guide (type, outer_args, complain);
cands = ovl_cons (guide, cands);
if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
elided = true;
else
cands = lookup_add (cands, guide);
}
if (args->length() == 1)
{
tree guide = build_deduction_guide (build_reference_type (type),
outer_args, complain);
cands = ovl_cons (guide, cands);
if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
elided = true;
else
cands = lookup_add (cands, guide);
}
/* Prune explicit deduction guides in copy-initialization context. */
tree old_cands = cands;
if (flags & LOOKUP_ONLYCONVERTING)
if (elided && !cands)
{
tree t = cands;
for (; t; t = OVL_NEXT (t))
if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (OVL_CURRENT (t))))
break;
if (t)
{
tree pruned = NULL_TREE;
for (t = cands; t; t = OVL_NEXT (t))
{
tree f = OVL_CURRENT (t);
if (!DECL_NONCONVERTING_P (STRIP_TEMPLATE (f)))
pruned = build_overload (f, pruned);
}
cands = pruned;
if (cands == NULL_TREE)
{
error ("cannot deduce template arguments for copy-initialization"
" of %qT, as it has no non-explicit deduction guides or "
"user-declared constructors", type);
return error_mark_node;
}
}
error ("cannot deduce template arguments for copy-initialization"
" of %qT, as it has no non-explicit deduction guides or "
"user-declared constructors", type);
return error_mark_node;
}
++cp_unevaluated_operand;
@ -25227,7 +25239,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
{
error ("class template argument deduction failed:");
t = build_new_function_call (cands, &args, complain | tf_decltype);
if (old_cands != cands)
if (elided)
inform (input_location, "explicit deduction guides not considered "
"for copy-initialization");
}

View File

@ -2094,6 +2094,52 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual)
return t;
}
/* 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);
if (TREE_CODE (fn) == OVERLOAD)
OVL_NESTED_P (result) = true;
TREE_TYPE (result) = (next || TREE_CODE (fn) == TEMPLATE_DECL
? unknown_type_node : TREE_TYPE (fn));
OVL_FUNCTION (result) = fn;
OVL_CHAIN (result) = next;
return result;
}
/* Add a potential overload into a lookup set. */
tree
lookup_add (tree lookup, tree ovl)
{
if (lookup || TREE_CODE (ovl) == TEMPLATE_DECL)
{
lookup = ovl_make (ovl, lookup);
OVL_LOOKUP_P (lookup) = true;
}
else
lookup = ovl;
return lookup;
}
/* 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