summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-19 18:50:08 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-19 18:50:08 +0000
commitf60f68fd2b4e0bc80391358fc56f9facd6d0acf6 (patch)
tree41bb2db2a1c3d233a5167efd1e9ad17d9c01c739
parentcf03ba19a953659ff09d08f04eb2918495dd9283 (diff)
downloadgcc-f60f68fd2b4e0bc80391358fc56f9facd6d0acf6.tar.gz
DR 2137 - copy-constructor rank in list-initialization
* call.c (implicit_conversion): If we choose a copy constructor for list-initialization from the same type, the conversion is an exact match. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235219 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/call.c19
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2137-1.C20
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2137-2.C21
4 files changed, 64 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a2509af865b..7ff3dc57325 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2016-04-19 Jason Merrill <jason@redhat.com>
+ DR 2137
+ * call.c (implicit_conversion): If we choose a copy constructor
+ for list-initialization from the same type, the conversion is an
+ exact match.
+
* constexpr.c (breaks): Handle EXIT_EXPR.
(cxx_eval_loop_expr): Handle COMPOUND_EXPR body.
(cxx_eval_constant_expression): Handle EXIT_EXPR, improve handling
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ed234904a63..11f2d42108e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1862,7 +1862,24 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
cand = build_user_type_conversion_1 (to, expr, flags, complain);
if (cand)
- conv = cand->second_conv;
+ {
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && CONSTRUCTOR_NELTS (expr) == 1
+ && !is_list_ctor (cand->fn))
+ {
+ /* "If C is not an initializer-list constructor and the
+ initializer list has a single element of type cv U, where U is
+ X or a class derived from X, the implicit conversion sequence
+ has Exact Match rank if U is X, or Conversion rank if U is
+ derived from X." */
+ tree elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ tree elttype = TREE_TYPE (elt);
+ if (reference_related_p (to, elttype))
+ return implicit_conversion (to, elttype, elt,
+ c_cast_p, flags, complain);
+ }
+ conv = cand->second_conv;
+ }
/* We used to try to bind a reference to a temporary here, but that
is now handled after the recursive call to this function at the end
diff --git a/gcc/testsuite/g++.dg/DRs/dr2137-1.C b/gcc/testsuite/g++.dg/DRs/dr2137-1.C
new file mode 100644
index 00000000000..ad6b5325a1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2137-1.C
@@ -0,0 +1,20 @@
+// DR 2137
+// { dg-do run { target c++11 } }
+
+// Test that an initializer_list constructor beats the copy constructor.
+
+#include <initializer_list>
+
+bool ok = false;
+
+struct Q {
+ Q() = default;
+ Q(Q const&) = default;
+ Q(Q&&) = default;
+ Q(std::initializer_list<Q>) { ok = true; }
+};
+
+int main() {
+ Q x = Q { Q() };
+ if (!ok) __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/DRs/dr2137-2.C b/gcc/testsuite/g++.dg/DRs/dr2137-2.C
new file mode 100644
index 00000000000..ba90860b3af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2137-2.C
@@ -0,0 +1,21 @@
+// DR 2137
+// { dg-do link { target c++11 } }
+
+// Test that copying Q is better than converting to R.
+
+struct Q {
+ Q() { }
+ Q(const Q&) { }
+};
+
+struct R {
+ R(const Q&);
+};
+
+void f(Q) { }
+void f(R);
+
+int main()
+{
+ f({Q()});
+}