https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118074
Bug ID: 118074 Summary: [coroutine] Possible over optimization of co_return Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: newsigma at 163 dot com Target Milestone: --- Hi all, I want to discuss an unusual usage of coroutine and CRTP. The following code gives the expected result using MSVC, but a unpredictable result using GCC and clang. https://godbolt.org/z/r97MbdMhT ``` #include <cstdio> #include <utility> #include <coroutine> template<class T> struct CRCoro { // Curiously Recurring Coroutine struct RValueWrapper { T* p; operator T&&() const noexcept { return std::move(*p); } }; using promise_type = T; T& getDerived() noexcept { return *static_cast<T*>(this); } auto get_return_object() noexcept { return RValueWrapper(&getDerived()); } std::suspend_never initial_suspend() noexcept { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_value(T&& x) noexcept { getDerived() = std::move(x); //asm volatile("" : : "r,m"(getDerived()) : "memory"); // Forcing assignment has observable side effect } void unhandled_exception() {} }; struct A : public CRCoro<A> { int a; }; A func() { A aa{}; aa.a = 5; co_return std::move(aa); } int main() { printf("%d\n", func().a); return 0; } ``` Expected result (MSVC): 5 Build option: -std=c++20 -fcoroutines GCC 10.5, 11.4, 12.4, 13.3, 14.2: 5 GCC trunk: 0 Build option: -std=c++20 -fcoroutines -O2 GCC 10.5, 11.4, 12.4, 13.3, trunk: 0 GCC 14.2: 5 Forcing assignment has observable side effect is a workaround for me. But the trick does not work for trunk. Is it the expected behavior or a bug?