return conv;
}
-/* Returns nonzero if T1 is reference-related to T2. */
+/* Returns nonzero if T1 is reference-related to T2.
+
+ This is considered when a reference to T1 is initialized by a T2. */
bool
reference_related_p (tree t1, tree t2)
}
bool copy_list_init = false;
+ bool single_list_conv = false;
if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
{
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
from = etype;
goto skip;
}
+ else if (CLASS_TYPE_P (etype) && TYPE_HAS_CONVERSION (etype))
+ /* CWG1996: jason's proposed drafting adds "or initializing T from E
+ would bind directly". We check that in the direct binding with
+ conversion code below. */
+ single_list_conv = true;
}
/* Otherwise, if T is a reference type, a prvalue temporary of the type
referenced by T is copy-list-initialized, and the reference is bound
(possibly cv-qualified) object to the (possibly cv-qualified) same
object type (or a reference to it), to a (possibly cv-qualified) base
class of that type (or a reference to it).... */
- else if (CLASS_TYPE_P (from) && !related_p
- && !(flags & LOOKUP_NO_CONVERSION))
+ else if (!related_p
+ && !(flags & LOOKUP_NO_CONVERSION)
+ && (CLASS_TYPE_P (from) || single_list_conv))
{
+ tree rexpr = expr;
+ if (single_list_conv)
+ rexpr = CONSTRUCTOR_ELT (expr, 0)->value;
+
/* [dcl.init.ref]
If the initializer expression
the reference is bound to the lvalue result of the conversion
in the second case. */
- z_candidate *cand = build_user_type_conversion_1 (rto, expr, flags,
+ z_candidate *cand = build_user_type_conversion_1 (rto, rexpr, flags,
complain);
if (cand)
{
--- /dev/null
+// CWG1996
+// { dg-do compile { target c++11 } }
+
+struct D { constexpr D() {} } d;
+struct S {
+ template <class T>
+ constexpr operator T& () const { return d; }
+};
+constexpr S s;
+constexpr const D &dr1(s);
+static_assert (&dr1 == &d, "");
+constexpr const D &dr2{s};
+static_assert (&dr2 == &d, "");