<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/62335>62335</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [clang++] Crash when calling coroutine handle.destroy() in await suspend()
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          FunMiles
      </td>
    </tr>
</table>

<pre>
    0


I have an example of code that works with g++ 12, older clang++ (v14.0.0 on Mac OS with experimental coroutines) and clang++ in unoptimized compilation but crashes with -O2 or -O3 turned on. The crash happens when calling destroy on the handle of the suspended coroutine. The docs on cppreference.com states that when await_resume is called:

the coroutine is suspended (its coroutine state is populated with local variables and current suspension point). awaiter.await_suspend(handle) is called, where handle is the coroutine handle representing the current coroutine. Inside that function, the suspended coroutine state is observable via that handle, and it's this function's responsibility to schedule it to resume on some executor, or to be destroyed.

My code does just that. It destroys the calling subroutine and resumes another coroutine. Unfortunately, in MacOS, clang++ 14.0.2 (recent update) makes this code crash but only when -O2 or -O3 are used.

The below code is the minimum code I could build to demonstrate the problem. Note that almost any change will not be able to demonstrate the crash. For example, removing the loop in main (the part inside is called only once) will avoid the crash. The compiler does very aggressive optimization such that running the debugger does not allow to stop in several places that might be useful.

Is this, as I think, a bug in clang++ or am I missing some detail of C++ legalese?

```.cpp
#include <iostream>
#if __has_include(<coroutine>)
#include <coroutine>
namespace crt = std;
#else
#include <experimental/coroutine>
namespace crt = std::experimental::coroutines_v1;
#endif

struct Timer {
    auto die_or_return(int t, bool destroy_handle=false)
    {
        struct awaiter {
            bool await_ready() const noexcept { return false; }

            void await_resume() const noexcept {}
            /* https://en.cppreference.com/w/cpp/language/coroutines states:
 * The coroutine is suspended (its coroutine state is populated with local variables and current suspension point).
             * awaiter.await_suspend(handle) is called, where handle is the coroutine handle representing the current coroutine.
             * Inside that function, the suspended coroutine state is observable via that handle,
 * and it's this function's responsibility to schedule it to resume on some executor,
             * or to be destroyed (returning false counts as scheduling)
             */
            crt::coroutine_handle<> await_suspend(crt::coroutine_handle<> h) noexcept
            {
 auto n = next;
                if (destroy_handle) {
 h.destroy();
                }
                return n;
 }
            crt::coroutine_handle<> next;
            bool destroy_handle;
        };

        return awaiter{ender, destroy_handle};
    }

    crt::coroutine_handle<> ender = crt::noop_coroutine();
};

inline static bool active{true};

struct [[nodiscard]] autodestruct_task {
    struct promise_type {
        ~promise_type() { active = false; std::cout << "Dying" << std::endl; }
        autodestruct_task get_return_object() noexcept
        {
            return autodestruct_task{crt::coroutine_handle<promise_type>::from_promise(*this)};
 }

        crt::suspend_always initial_suspend() noexcept { return {}; }

        /// If the coroutine does not suspend at the end, its handle is automatically
        /// destroyed.
 crt::suspend_never final_suspend() noexcept {return {}; }

        void return_void() noexcept {}

        void unhandled_exception() noexcept { std::terminate(); }
    };

 crt::coroutine_handle<promise_type> handle;

    explicit autodestruct_task(crt::coroutine_handle<promise_type> h) noexcept : handle(h) {}

};

autodestruct_task test_death(Timer &timer) {
 co_await timer.die_or_return(0,true);
}

autodestruct_task end_task() {
    std::cout << "Ending" << std::endl;
 co_return;
}

int main() {
    Timer timer;
    timer.ender = end_task().handle;
    auto tsk_handle = test_death(timer).handle;
 while (active && !tsk_handle.done()) {
        std::cout << "Resume" << std::endl;
        tsk_handle();
    }
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWE2P4rrS_jVmUxoETtPAgkU3PUi9mHek98xdI-MUxKcdO7IdaO7i_varcpyQ8NFz7uLooNE0icv18dTHYyO8VweDuGKzVzZ7G4k6FNatNrX5oTT60c7m59WETd7Y5KX__zsU4oggDOCnKCuNYPcgbY4QChHgZN2Hh5MKBRwYf2X8Faac8TVYnaMDqYVp3zO-OE6fxpPxBKyBH0LCzz-anfhZoVMlmiA0SOtsHZRBz_gShMkHSpSB2tgqqFL9G3OQtqyUFkFZA7s6gHTCF5gc-vaTg3Xw7WcGoXYGc7BmDL8KbMSgEFWFxsOpQANSaK3MAXL0wdkzuRgKhEKYvImZnnztKzR5NJy8bBTmVnraIqvK4R4dGoljaUvwQQT0CSuyI05Cha1DX5cIyke7mLNsADrZ6iyQ1MUw4wsVfG81WiCZyla1FgHzJnptpdBwFE6JnUbfIFk7hyYkdZ5Qq6wygfHluPEM3bjxMFlkfNFAQMm4uMvXFI3r8FEehj6n9w4rhx5NIGijRPKgh9-78aotp31tJCWTDDwA_BKw3Xl0R4oOjko0Clpn1zFeFRifk2vK91TPPTj0lTVe7ZRW4QzBgpcF5jWFEugxJcga8LZEwE-UdbAuVrYjgR22pYL5uJ-7H-emPXKLHv6sfYiOjeE9tBsSVqngfL1rIyOXG8OULhsK6qALUP8ye-tCbURAfSZPVGyjn3_Q936TxC7jVCoOJaFdV7kIMYWl-MAESPSy6QRqHWv0uSnRXt8Ih1D7qwip4Heo7alRkXJfKqPKumzevYO0tc5hVyudE1w5ltb44Ch1JF05u9NYjuH_bEi5F7q0PoAwZ5CFMAeEk9IajA0EdkzzHUUxgDFsrGsHFKHhsLTHtua0tRVhVQplCJRoX7gAqqm8rqwbDKyREapoXRytyvuG4viIUwddk-MjujOIw8Gh9-qIkKZTM5R8LYsmPFcb03qU464-HFoFFKHQhCfVYWic9XhEJzRUWsh2gJTqUEQwao_7Wg-S8t5kNVa-h3d6MB_xCXb1gTT2K8Q6ECW8Q6m8j0VIRZ5jEErTrFsnMY0HodEjyzYDZnieNP_GsqrSK54pI3WdI7BsrawPDkXJsu-X5T1st4Xw2yTH-IJl6668SZQv7ykbiMR1I0r0lZCUlAAsewMfcpa9drtRe7ynqk80jG_-suYXlr0M9sY3F6baHqcD8yZX-z5gPrhaBvilSnTA5kkSAEDUVNMKt9ZtHRJN0YA3AQLlbmetbqfGNo227G0vKLwWLNIyUEmfZDCN9Nt1-kTlLR2J_EwJ4UuQ1F5gLH5KrAJthcYxaOxmr8Dmb_3o-kpju_Q57qHWTkl_O-Mbxl-gCKHyBDI9btCMr3mV8c2JElhVjG-ormtxwH5GfWLejliB9P76B3j1Nsjoyj_Etg-8-Xs4uIf838XGD-K55eiGDamOCZxYysRRJnial8meogG5vK-TavFmQbpwNQu6Nl2z7DtcZ_d38gUlvu2SO-3R9XGcGyZOKIOfoZs-cPVRewr8aoTwZU9TMU6rTac-1HS3X-mTpoO57Lwr-rvQH4ZxdwheyZHFbgAPVpJ3qd3Y_JVKOZ7jrlT2NAzCvbz6XQRRc0xJJ2msrbYXmhkifOu0MrrtLiXTgJZBHZHNX4Or8XZHGvTxUvdqbK68FC5nszc2e4tFEqOsZdgG4T-GRJD2Vs6WyuM2nCu8ZYr_9JfTMCdOaPyK0Xa80HGltDWx55pla2Ccv51jY_H21YVTTa4HhNJavfX8gCER5Nbu_kQZki_3m-Uu4bWlcK2bzV-_Su0AgOx7I7d3ttymlejJS3P6Wg7q6AFRdtbSYNgKfRJnD8qooITuzYt-hH0qTvz5mIsb5mR8A-_7K7LozpzJDIgQJaLFNRALXniGwCqpGoXW50cmri9CtwEaOs3CXpkvo_urwcVDRioG-n5H1Vc7a9PEl28b-UhDt1B3VRrQlcrEC1Tq32HB3hk-_0M9wdVIu-jFz0orqcKdiv2aSW4sDGPLXjqKXhQtGQzxug3ptiMD-rDNUYSC8UU62vLnQF-GDCPtNo5fiGvj69PuhPF1HG5Xo_FL41RUCYmhsTjX7o-h7yb_eg5d_E3OPXCHzud0mbxnvAGiQaHPJ03sF4oYBjC-w2uR4oP_SHmNuwaYt1DfbD4ViuT5oh3S_JnxZ2B8elE3zm1HSNcxfAXi_6dT_e9ATJ-LwTvHiwus3Zf2ZjnKV1m-zJZihKvp84Jn88lkPh8Vq-f9UzZ7XszEDJf58nm-nz5lGV8upJjtJ7NsP1IrPuHZ5Ik_8elkOp2Ps-VsOZdL8SR3073EKXuaYCmUHmt9LMfWHUbK-xpXzzzLZiMtdqh9_JWUc4MniIuMczZ7G7kV7fm2qw-ePU208sFftAQVdPx5tXfRJhZex59YBj8yXp_ch0cwuqw3DTMYlaPa6dXwZnRQoah36UJEjqQ_3ypnG47cRPc945sY3n8DAAD__6Rr6Xg">