From: Jason Merrill Date: Tue, 2 Apr 2024 14:52:28 +0000 (-0400) Subject: c++: binding reference to comma expr [PR114561] X-Git-Tag: basepoints/gcc-15~382 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5d7e9a35024f065b25f61747859c7cb7a770c92b;p=thirdparty%2Fgcc.git c++: binding reference to comma expr [PR114561] We represent a reference binding where the referent type is more qualified by a ck_ref_bind around a ck_qual. We performed the ck_qual and then tried to undo it with STRIP_NOPS, but that doesn't work if the conversion is buried in COMPOUND_EXPR. So instead let's avoid performing that fake conversion in the first place. PR c++/114561 PR c++/114562 gcc/cp/ChangeLog: * call.cc (convert_like_internal): Avoid adding qualification conversion in direct reference binding. gcc/testsuite/ChangeLog: * g++.dg/conversion/ref10.C: New test. * g++.dg/conversion/ref11.C: New test. --- diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 9e4c80736007..9568b5eb2c44 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -8742,7 +8742,15 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, break; }; - expr = convert_like (next_conversion (convs), expr, fn, argnum, + conversion *nc = next_conversion (convs); + if (convs->kind == ck_ref_bind && nc->kind == ck_qual + && !convs->need_temporary_p) + /* direct_reference_binding might have inserted a ck_qual under + this ck_ref_bind for the benefit of conversion sequence ranking. + Don't actually perform that conversion. */ + nc = next_conversion (nc); + + expr = convert_like (nc, expr, fn, argnum, convs->kind == ck_ref_bind ? issue_conversion_warnings : false, c_cast_p, /*nested_p=*/true, complain & ~tf_no_cleanup); @@ -8820,19 +8828,6 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, { tree ref_type = totype; - /* direct_reference_binding might have inserted a ck_qual under - this ck_ref_bind for the benefit of conversion sequence ranking. - Ignore the conversion; we'll create our own below. */ - if (next_conversion (convs)->kind == ck_qual - && !convs->need_temporary_p) - { - gcc_assert (same_type_p (TREE_TYPE (expr), - next_conversion (convs)->type)); - /* Strip the cast created by the ck_qual; cp_build_addr_expr - below expects an lvalue. */ - STRIP_NOPS (expr); - } - if (convs->bad_p && !next_conversion (convs)->bad_p) { tree extype = TREE_TYPE (expr); diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C b/gcc/testsuite/g++.dg/conversion/ref10.C new file mode 100644 index 000000000000..1913f733a6b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref10.C @@ -0,0 +1,5 @@ +// PR c++/114561 + +void create(void* u) { + const void* const& r = ( (void)0, u ); +} diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C b/gcc/testsuite/g++.dg/conversion/ref11.C new file mode 100644 index 000000000000..bb9b835034c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref11.C @@ -0,0 +1,33 @@ +// PR c++/114562 +// { dg-do compile { target c++11 } } + +template +struct Optional { + Optional(T&&); +}; + +struct MyClass { + MyClass(Optional); +}; + +// const void* NONE = nullptr; // Correct Error +void* NONE = nullptr; // Crash + +void beforeParam(); + +template +struct Create { + template static T create(U &&) noexcept; +}; + + +template +template +T Create::create(U && u) noexcept { + return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue reference" } + // return T( (u) ); // Correct Error +} + +void test_func() { + Create::create(NONE); +}