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.