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.

From-SVN: r235219
This commit is contained in:
Jason Merrill 2016-04-19 14:50:08 -04:00 committed by Jason Merrill
parent 06ec22b7f6
commit 218e9dde70
4 changed files with 64 additions and 1 deletions

View File

@ -1,5 +1,10 @@
2016-04-19 Jason Merrill <jason@redhat.com> 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. * constexpr.c (breaks): Handle EXIT_EXPR.
(cxx_eval_loop_expr): Handle COMPOUND_EXPR body. (cxx_eval_loop_expr): Handle COMPOUND_EXPR body.
(cxx_eval_constant_expression): Handle EXIT_EXPR, improve handling (cxx_eval_constant_expression): Handle EXIT_EXPR, improve handling

View File

@ -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); cand = build_user_type_conversion_1 (to, expr, flags, complain);
if (cand) 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 /* 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 is now handled after the recursive call to this function at the end

View File

@ -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 ();
}

View File

@ -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()});
}