Tested on x86_64-pc-linux-gnu, does this look OK for trunk
and perhaps backports?

-- >8 --

When passing *this to the promise type ctor (or operator new) (as
per [dcl.fct.def.coroutine]/4), we add an explicit cast to lvalue
reference, but that's unnecessary since *this is already an lvalue.
And it'd mean we'd have to call convert_from_reference afterwards to
lower the reference-yielding expression into an implicit dereference,
otherwise overload resolution gets confused when computing argument
conversions.  So this patch removes the unnecessary reference cast when
passing *this to the promise ctor, and removes both the cast and
implicit deref when passing *this to operator new, for consistency.

        PR c++/104981
        PR c++/115550

gcc/cp/ChangeLog:

        * coroutines.cc (morph_fn_to_coro): Remove unnecessary calls
        to convert_to_reference and convert_from_reference for *this.

gcc/testsuite/ChangeLog:

        * g++.dg/coroutines/pr104981-preview-this.C: New test.
        * g++.dg/coroutines/pr115550-preview-this.C: New test.
---
 gcc/cp/coroutines.cc                          | 10 +---
 .../g++.dg/coroutines/pr104981-preview-this.C | 34 ++++++++++++++
 .../g++.dg/coroutines/pr115550-preview-this.C | 47 +++++++++++++++++++
 3 files changed, 82 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index f350fc33e9b..b8a53182c38 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4622,11 +4622,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
              /* We pass a reference to *this to the allocator lookup.  */
              tree tt = TREE_TYPE (TREE_TYPE (arg));
              tree this_ref = build1 (INDIRECT_REF, tt, arg);
-             tt = cp_build_reference_type (tt, false);
-             this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
-                                              LOOKUP_NORMAL , NULL_TREE,
-                                              tf_warning_or_error);
-             vec_safe_push (args, convert_from_reference (this_ref));
+             vec_safe_push (args, this_ref);
            }
          else
            vec_safe_push (args, convert_from_reference (arg));
@@ -4849,10 +4845,6 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
              gcc_checking_assert (POINTER_TYPE_P (tt));
              tree ct = TREE_TYPE (tt);
              tree this_ref = build1 (INDIRECT_REF, ct, arg);
-             tree rt = cp_build_reference_type (ct, false);
-             this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
-                                              LOOKUP_NORMAL, NULL_TREE,
-                                              tf_warning_or_error);
              vec_safe_push (promise_args, this_ref);
            }
          else if (parm.rv_ref)
diff --git a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
new file mode 100644
index 00000000000..81eb963db4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
@@ -0,0 +1,34 @@
+// PR c++/104981 - ICE from convert_to_base when passing *this to promise ctor
+
+#include <coroutine>
+
+class Base {};
+
+struct PromiseType;
+
+struct Result {
+ using promise_type = PromiseType;
+};
+
+struct PromiseType {
+  PromiseType(const Base& parser, auto&&...) {}
+
+  Result get_return_object() { return {}; }
+
+  static std::suspend_never initial_suspend() { return {}; }
+  static std::suspend_always final_suspend() noexcept { return {}; }
+  [[noreturn]] static void unhandled_exception() { throw; }
+
+  void return_value(int) {}
+};
+
+struct Derived : Base {
+  Result f() {
+   co_return 42;
+  }
+};
+
+int main() {
+  Derived d;
+  d.f();
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C
new file mode 100644
index 00000000000..f62c07096b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C
@@ -0,0 +1,47 @@
+// PR c++/115550 - wrong deduction when passing *this to promise ctor template
+
+#include <coroutine>
+
+template <typename T> struct remove_reference { using type = T; };
+template <typename T> struct remove_reference<T&> { using type = T; };
+template <typename T> struct remove_reference<T&&> { using type = T; };
+template <typename T> using remove_reference_t = remove_reference<T>::type;
+
+template <typename, typename>
+struct is_same { static inline constexpr bool value = false; };
+template <typename T>
+struct is_same<T, T> { static inline constexpr bool value = true; };
+
+template <typename T, typename U>
+concept same_as = is_same<T, U>::value;
+
+struct coroutine
+{
+    struct promise_type
+    {
+        template <typename Arg>
+        explicit promise_type(Arg&&)
+        {
+            static_assert(same_as<
+                remove_reference_t<remove_reference_t<Arg>>,
+                remove_reference_t<Arg>
+            >);
+        }
+
+        coroutine get_return_object() { return {}; }
+
+        std::suspend_never initial_suspend() noexcept { return {}; }
+        std::suspend_never final_suspend() noexcept { return {}; }
+
+        void return_void() {}
+        void unhandled_exception() {throw;}
+    };
+};
+
+struct x
+{
+    coroutine f()
+    {
+        co_return;
+    }
+};
-- 
2.46.0.rc0.106.g1c4a234a1c

Reply via email to