aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-03-03 02:31:54 -0500
committerJason Merrill <jason@gcc.gnu.org>2017-03-03 02:31:54 -0500
commitfb5ce60890c11a637aa1809389a9e8f6f7b87360 (patch)
treee6eefc85ee94c7cd7955656f0a9ac5d017180d41 /gcc
parentde35db4271bdfc6a648a5c5f504308c84ecb639b (diff)
downloadgcc-fb5ce60890c11a637aa1809389a9e8f6f7b87360.zip
gcc-fb5ce60890c11a637aa1809389a9e8f6f7b87360.tar.gz
gcc-fb5ce60890c11a637aa1809389a9e8f6f7b87360.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/call.c16
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/pt.c44
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction36.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction38.C27
6 files changed, 98 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7b68b13..be98880 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index babab00..dc629b9 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 31edc5f..7583672 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3b320fc..13293eb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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);
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction36.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction36.C
new file mode 100644
index 0000000..129e29e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction36.C
@@ -0,0 +1,15 @@
+// { 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;
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction38.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction38.C
new file mode 100644
index 0000000..fe6c200
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction38.C
@@ -0,0 +1,27 @@
+// { 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;