diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-19 18:50:08 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-19 18:50:08 +0000 |
commit | f60f68fd2b4e0bc80391358fc56f9facd6d0acf6 (patch) | |
tree | 41bb2db2a1c3d233a5167efd1e9ad17d9c01c739 | |
parent | cf03ba19a953659ff09d08f04eb2918495dd9283 (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/call.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/DRs/dr2137-1.C | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/DRs/dr2137-2.C | 21 |
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()}); +} |