Commit fb5ce608 by Jason Merrill Committed by Jason Merrill

Update overload resolution with deduction guides.

	* pt.c (do_class_deduction): Always build the copy guide.
	(copy_guide_p, template_guide_p): New.
	(build_deduction_guide): Remember the original constructor.
	* call.c (joust): Prefer the copy guide and non-template guides.

From-SVN: r245859
parent de35db42
2017-03-02 Jason Merrill <jason@redhat.com>
Update overload resolution with deduction guides.
* pt.c (do_class_deduction): Always build the copy guide.
(copy_guide_p, template_guide_p): New.
(build_deduction_guide): Remember the original constructor.
* call.c (joust): Prefer the copy guide and non-template guides.
Allow deduction guides to look into primary template.
* cp-tree.h (struct saved_scope): Add deduction_guide_type.
(struct cp_decl_specifier_seq): Add constructor_p.
......
......@@ -9717,6 +9717,22 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
int art2 = DECL_ARTIFICIAL (cand2->fn);
if (art1 != art2)
return art2 - art1;
if (art1)
{
/* Prefer the special copy guide over a declared copy/move
constructor. */
if (copy_guide_p (cand1->fn))
return 1;
if (copy_guide_p (cand2->fn))
return -1;
/* Prefer a candidate generated from a non-template constructor. */
int tg1 = template_guide_p (cand1->fn);
int tg2 = template_guide_p (cand2->fn);
if (tg1 != tg2)
return tg2 - tg1;
}
}
/* or, if not that, F2 is from a using-declaration, F1 is not, and the
......
......@@ -6288,6 +6288,8 @@ extern tree template_parm_to_arg (tree);
extern tree dguide_name (tree);
extern bool dguide_name_p (tree);
extern bool deduction_guide_p (const_tree);
extern bool copy_guide_p (const_tree);
extern bool template_guide_p (const_tree);
/* in repo.c */
extern void init_repo (void);
......
......@@ -24852,6 +24852,35 @@ deduction_guide_p (const_tree fn)
return false;
}
/* True if FN is the copy deduction guide, i.e. A(A)->A. */
bool
copy_guide_p (const_tree fn)
{
gcc_assert (deduction_guide_p (fn));
if (!DECL_ARTIFICIAL (fn))
return false;
tree parms = FUNCTION_FIRST_USER_PARMTYPE (DECL_TI_TEMPLATE (fn));
return (TREE_CHAIN (parms) == void_list_node
&& same_type_p (TREE_VALUE (parms), TREE_TYPE (DECL_NAME (fn))));
}
/* True if FN is a guide generated from a constructor template. */
bool
template_guide_p (const_tree fn)
{
gcc_assert (deduction_guide_p (fn));
if (!DECL_ARTIFICIAL (fn))
return false;
if (tree ctor = DECL_ABSTRACT_ORIGIN (fn))
{
tree tmpl = DECL_TI_TEMPLATE (ctor);
return PRIMARY_TEMPLATE_P (tmpl);
}
return false;
}
/* OLDDECL is a _DECL for a template parameter. Return a similar parameter at
LEVEL:INDEX, using tsubst_args and complain for substitution into non-type
template parameter types. Note that the handling of template template
......@@ -25100,6 +25129,8 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
TREE_TYPE (ded_tmpl) = TREE_TYPE (ded_fn);
DECL_TEMPLATE_INFO (ded_fn) = build_template_info (ded_tmpl, targs);
DECL_PRIMARY_TEMPLATE (ded_tmpl) = ded_tmpl;
if (DECL_P (ctor))
DECL_ABSTRACT_ORIGIN (ded_fn) = ctor;
if (ci)
set_constraints (ded_tmpl, ci);
......@@ -25153,7 +25184,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
}
bool saw_ctor = false;
bool saw_copy = false;
if (CLASSTYPE_METHOD_VEC (type))
// FIXME cache artificial deduction guides
for (tree fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
......@@ -25163,16 +25193,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
cands = ovl_cons (guide, cands);
saw_ctor = true;
tree parms = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (parms && sufficient_parms_p (TREE_CHAIN (parms)))
{
tree pt = TREE_VALUE (parms);
if (TREE_CODE (pt) == REFERENCE_TYPE
&& (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (pt), type)))
saw_copy = true;
}
}
if (!saw_ctor && args->length() == 0)
......@@ -25180,7 +25200,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
tree guide = build_deduction_guide (type, outer_args, complain);
cands = ovl_cons (guide, cands);
}
if (!saw_copy && args->length() == 1)
if (args->length() == 1)
{
tree guide = build_deduction_guide (build_reference_type (type),
outer_args, complain);
......
// { dg-options -std=c++1z }
template <class T> struct A {
A(T&);
A(const A&);
};
int i;
A a = i;
A a2 = a;
template <class,class> struct same;
template <class T> struct same<T,T> {};
same<decltype(a),A<int>> s1;
same<decltype(a2),A<int>> s2;
// { dg-options -std=c++1z }
template <class T> struct A {
using value_type = T;
A(value_type); // #1
A(const A&); // #2
A(T, T, int); // #3
template<class U> A(int, T, U); // #4
}; // A(A); #5, the copy deduction candidate
A x (1, 2, 3); // uses #3, generated from a non-template constructor
template <class T> A(T) -> A<T>; // #6, less specialized than #5
A a (42); // uses #6 to deduce A<int> and #1 to initialize
A b = a; // uses #5 to deduce A<int> and #2 to initialize
template <class T> A(A<T>) -> A<A<T>>; // #7, as specialized as #5
A b2 = a; // uses #7 to deduce A<A<int>> and #1 to initialize
template <class,class> struct same;
template <class T> struct same<T,T> {};
same<decltype(a),A<int>> s1;
same<decltype(b),A<int>> s2;
same<decltype(b2),A<A<int>>> s3;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment