https://gcc.gnu.org/g:b35afe75674ff9f79cf9685d099bc80f10442216

commit r11-11446-gb35afe75674ff9f79cf9685d099bc80f10442216
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Apr 2 10:52:28 2024 -0400

    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.c (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.
    
    (cherry picked from commit 5d7e9a35024f065b25f61747859c7cb7a770c92b)

Diff:
---
 gcc/cp/call.c                           | 23 +++++++++--------------
 gcc/testsuite/g++.dg/conversion/ref10.C |  5 +++++
 gcc/testsuite/g++.dg/conversion/ref11.C | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7c3ce1693e1..fbe29f38384 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7816,7 +7816,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, complain & ~tf_no_cleanup);
@@ -7897,19 +7905,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 00000000000..1913f733a6b
--- /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 00000000000..bb9b835034c
--- /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);
+}

Reply via email to