https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115550

            Bug ID: 115550
           Summary: [coroutines] Reference to reference in promise
                    constructor template argument corresponding to
                    coroutine *this
           Product: gcc
           Version: 11.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: henri.vettenranta at bitwise dot fi
  Target Milestone: ---

Created attachment 58467
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58467&action=edit
Preprocessed source that triggers the bug

The attached preprocessed file is from GCC 11.4.0, but the bug can also be
reproduced with GCC 14.1.0 on godbolt.org.

When the coroutine promise type constructor is a template using a forwarding
reference for the first parameter and the coroutine in question is a non-static
member function, GCC seems to deduce the promise constructor template type
argument to be a reference to a reference. In the attached code, it can be seen
that removing one reference results in one reference being left, and removing
two references results in a different type.

This may have the same underlying cause as bug 104981. It would not be
surprising if some internal compiler code removed the outer reference and
expected to be left with a type that is not a reference. I can't preclude this
being just a coincidence, however.

Relevant parts of the code (full preprocessed source in the attachment):

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>
            >);
        }

        // ...
    };
};

struct x
{
    coroutine f()
    {
        co_return;
    }
};

===

$ g++ -v -Wall -Wextra -Wpedantic -std=c++20 -c -o /dev/null gcccoroctorbug.i
Using built-in specs.
COLLECT_GCC=g++
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs
--enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr
--with-gcc-major-version-only --program-suffix=-11
--program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object
--disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib
--enable-libphobos-checking=release --with-target-system-zlib=auto
--enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet
--with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32
--enable-multilib --with-tune=generic
--enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr
--without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
--with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 
COLLECT_GCC_OPTIONS='-v' '-Wall' '-Wextra' '-Wpedantic' '-std=c++20' '-c' '-o'
'/dev/null' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/11/cc1plus -fpreprocessed gcccoroctorbug.i
-quiet -dumpbase gcccoroctorbug.i -dumpbase-ext .i -mtune=generic -march=x86-64
-Wall -Wextra -Wpedantic -std=c++20 -version -fasynchronous-unwind-tables
-fstack-protector-strong -Wformat-security -fstack-clash-protection
-fcf-protection -o /tmp/ccWWTO55.s
GNU C++20 (Ubuntu 11.4.0-1ubuntu1~22.04) version 11.4.0 (x86_64-linux-gnu)
        compiled by GNU C version 11.4.0, GMP version 6.2.1, MPFR version
4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++20 (Ubuntu 11.4.0-1ubuntu1~22.04) version 11.4.0 (x86_64-linux-gnu)
        compiled by GNU C version 11.4.0, GMP version 6.2.1, MPFR version
4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: d591828bb4d392ae8b7b160e5bb0b95f
gcccoroctorbug.cpp: In instantiation of
‘coroutine::promise_type::promise_type(Arg&&) [with Arg = x&&]’:
gcccoroctorbug.cpp:44:5:   required from here
gcccoroctorbug.cpp:23:27: error: static assertion failed
   23 |             static_assert(same_as<
      |                           ^~~~~~~~
   24 |                 remove_reference_t<remove_reference_t<Arg>>,
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   25 |                 remove_reference_t<Arg>
      |                 ~~~~~~~~~~~~~~~~~~~~~~~
   26 |             >);
      |             ~              
gcccoroctorbug.cpp:23:27: note: ‘same_as<x, x&>’ evaluates to false
gcccoroctorbug.cpp:23:27: note: constraints not satisfied
gcccoroctorbug.cpp:14:9:   required by the constraints of ‘template<class T,
class U> concept same_as’
gcccoroctorbug.cpp:14:34: note: the expression ‘is_same<
<template-parameter-1-1>, <template-parameter-1-2> >::value [with T = x; U =
x&]’ evaluated to ‘false’
   14 | concept same_as = is_same<T, U>::value;
      |                                  ^~~~~

===

Note that even though the error message says Arg = x&&, it seems that this
should be understood as Arg being lvalue reference to lvalue reference to x,
not rvalue reference to x.

Reply via email to