conv_binds_ref_to_prvalue was expecting that if a user-defined conversion uses a conversion function returning a reference, the conversion will have reference type. This wasn't the case, because build_user_type_conversion_1 strips the reference from the return type to get the type of the conversion.
It seems to me that in the case of direct binding to a reference, we want the conversion to have reference type. Tested x86_64-pc-linux-gnu, applying to trunk.
commit 819e3be84751834a5e70df910f1d1726ea1b82f5 Author: Jason Merrill <ja...@redhat.com> Date: Wed Apr 4 20:27:29 2018 -0400 PR c++/85215 - ICE with copy-init from conversion. * call.c (merge_conversion_sequences): Fix type of direct binding sequence. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7c99e8ad910..f2ada2768de 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3642,6 +3642,12 @@ merge_conversion_sequences (conversion *user_seq, conversion *std_seq) (*t)->bad_p = true; } + if ((*t)->rvaluedness_matches_p) + /* We're binding a reference directly to the result of the conversion. + build_user_type_conversion_1 stripped the REFERENCE_TYPE from the return + type, but we want it back. */ + user_seq->type = TREE_TYPE (TREE_TYPE (user_seq->cand->fn)); + /* Replace the identity conversion with the user conversion sequence. */ *t = user_seq; diff --git a/gcc/testsuite/g++.dg/cpp1z/elide3.C b/gcc/testsuite/g++.dg/cpp1z/elide3.C new file mode 100644 index 00000000000..ca4d24708a8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/elide3.C @@ -0,0 +1,15 @@ +// PR c++/85215 +// { dg-do compile { target c++11 } } + +template <typename _Tp> struct vector { + vector(vector &&) noexcept; +}; + +template <typename T> struct any_container { + operator vector<T> &&(); +}; + +void f (any_container<int> c) +{ + vector<int> shape (c); +}