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

            Bug ID: 125289
           Summary: Segmentation fault when awaitable derives from
                    abstract class
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rw at rolrolrol dot de
  Target Milestone: ---

// c++ compiler frontend crashes when fed with code below
// see on godbolt: https://godbolt.org/z/GEc4PK973

#include <coroutine>


struct ReturnObject {
    struct promise_type {

        promise_type(){}
        unsigned value_;

        ReturnObject get_return_object() {
            return ReturnObject {
                .h_ = std::coroutine_handle<promise_type>::from_promise(*this)
            };
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
        void return_value(int a){}
    };

    std::coroutine_handle<promise_type> h_;
    operator std::coroutine_handle<promise_type>() const { return h_; }
};


template<typename PromiseType, typename AwaitReturn>
struct AbstractAwaitable
{
    virtual bool await_ready()  = 0;
    virtual bool await_suspend(std::coroutine_handle<PromiseType> h) = 0;
    virtual AwaitReturn await_resume() = 0;
};


template<typename PromiseType>
struct Awaitable : public AbstractAwaitable<PromiseType, void>
{
    Awaitable(int &io_context)
        : m_ioContext(io_context)
        , m_timer(io_context)
    {}
    bool await_ready() override { return false; } // false means yes, do call
await_suspend
    bool await_suspend(std::coroutine_handle<PromiseType> h) override
    {

        m_promise = &h.promise();
        return false;     // says no don't suspend coroutine after all
    }
    void await_resume() override {  }

    PromiseType *m_promise = nullptr;
    int &m_ioContext;
    int m_timer;
};


using AwaitableTimer = Awaitable<ReturnObject::promise_type>;


ReturnObject counter(AwaitableTimer &timer)
{
    co_await timer;
    co_return 5;
}


int main()
{
    int io_context;
    AwaitableTimer timer{io_context};
    std::coroutine_handle<ReturnObject::promise_type> h = counter(timer);
    io_context.run();
    h.destroy();
}

Reply via email to