diff options
author | Jason Merrill <jason@redhat.com> | 2024-04-02 10:52:28 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2024-04-02 14:11:13 -0400 |
commit | 5d7e9a35024f065b25f61747859c7cb7a770c92b (patch) | |
tree | 23711ec0873aad4663f5ec2595b0cf56637ab596 /gcc | |
parent | 0e64bbb8823f7b3757befc878ed177dfb59943d1 (diff) | |
download | gcc-5d7e9a35024f065b25f61747859c7cb7a770c92b.zip gcc-5d7e9a35024f065b25f61747859c7cb7a770c92b.tar.gz gcc-5d7e9a35024f065b25f61747859c7cb7a770c92b.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/call.cc | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ref10.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ref11.C | 33 |
3 files changed, 47 insertions, 14 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 9e4c807..9568b5e 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 0000000..1913f73 --- /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 0000000..bb9b835 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref11.C @@ -0,0 +1,33 @@ +// PR c++/114562 +// { dg-do compile { target c++11 } } + +template <typename T> +struct Optional { + Optional(T&&); +}; + +struct MyClass { + MyClass(Optional<const void*>); +}; + +// const void* NONE = nullptr; // Correct Error +void* NONE = nullptr; // Crash + +void beforeParam(); + +template<typename T> +struct Create { + template <typename U> static T create(U &&) noexcept; +}; + + +template <typename T> +template<typename U> +T Create<T>::create(U && u) noexcept { + return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue reference" } + // return T( (u) ); // Correct Error +} + +void test_func() { + Create<MyClass>::create(NONE); +} |