aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2024-04-02 10:52:28 -0400
committerJason Merrill <jason@redhat.com>2024-04-02 14:11:13 -0400
commit5d7e9a35024f065b25f61747859c7cb7a770c92b (patch)
tree23711ec0873aad4663f5ec2595b0cf56637ab596 /gcc
parent0e64bbb8823f7b3757befc878ed177dfb59943d1 (diff)
downloadgcc-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.cc23
-rw-r--r--gcc/testsuite/g++.dg/conversion/ref10.C5
-rw-r--r--gcc/testsuite/g++.dg/conversion/ref11.C33
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);
+}