diff options
author | Jason Merrill <jason@redhat.com> | 2024-04-12 13:24:44 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2024-04-12 15:34:29 -0400 |
commit | d435571b54b02946c97b5b24f20e5a7058fd96a1 (patch) | |
tree | dcefab193f8f1cc586c1722e3dc0757f5c899e3b /gcc/cp | |
parent | c9500083073ff5e0f5c1c9db92d7ce6e51a62919 (diff) | |
download | gcc-d435571b54b02946c97b5b24f20e5a7058fd96a1.zip gcc-d435571b54b02946c97b5b24f20e5a7058fd96a1.tar.gz gcc-d435571b54b02946c97b5b24f20e5a7058fd96a1.tar.bz2 |
c++: reference list-init, conversion fn [PR113141]
The original testcase in PR113141 is an instance of CWG1996; the standard
fails to consider conversion functions when initializing a reference
directly from an initializer-list of one element, but then does consider
them when initializing a temporary. I have a proposed fix for this defect,
which is implemented here.
DR 1996
PR c++/113141
gcc/cp/ChangeLog:
* call.cc (reference_binding): Check direct binding from
a single-element list.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/initlist-ref1.C: New test.
* g++.dg/cpp0x/initlist-ref2.C: New test.
* g++.dg/cpp0x/initlist-ref3.C: New test.
Co-authored-by: Patrick Palka <ppalka@redhat.com>
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/call.cc | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 9568b5e..15b5647 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -1596,7 +1596,9 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, 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) @@ -1757,6 +1759,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, } bool copy_list_init = false; + bool single_list_conv = false; if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)) { maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); @@ -1783,6 +1786,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, 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 @@ -1907,9 +1915,14 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, (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 @@ -1923,7 +1936,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, 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) { |