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

    <tr>
        <th>Summary</th>
        <td>
            No thread switched in coroutine example from cppreference.com
        </td>
    </tr>

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

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

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

<pre>
    Consider the following code example from cppreference.com ([link](https://en.cppreference.com/w/cpp/language/coroutines#Example)) with small modification (assert added):

```C++
#include <cassert>
#include <coroutine>
#include <iostream>
#include <stdexcept>
#include <thread>
 
auto switch_to_new_thread(std::jthread& out)
{
    struct awaitable
 {
        std::jthread* p_out;
        bool await_ready() { return false; }
        void await_suspend(std::coroutine_handle<> h)
 {
            std::jthread& out = *p_out;
            if (out.joinable())
                throw std::runtime_error("Output jthread parameter not empty");
            out = std::jthread([h] { h.resume(); });
            // Potential undefined behavior: accessing potentially destroyed *this
            // std::cout << "New thread ID: " << p_out->get_id() << '\n';
            std::cout << "New thread ID: " << out.get_id() << '\n'; // this is OK
        }
        void await_resume() {}
    };
    return awaitable{&out};
}
 
struct task
{
    struct promise_type
    {
        task get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
 void unhandled_exception() {}
    };
};
 
task resuming_on_new_thread(std::jthread& out)
{
    const auto thread0 = std::this_thread::get_id();
    std::cout << "Coroutine started on thread: " << thread0 << '\n';
    co_await switch_to_new_thread(out);
    // awaiter destroyed here
    const auto thread1 = std::this_thread::get_id();
    std::cout << "Coroutine resumed on thread: " << thread1 << '\n';
    // Oops Clang
    assert(thread0 != thread1);
}
 
int main()
{
    std::jthread out;
 resuming_on_new_thread(out);
}
```

The results among Clang 15.0, GCC 12.2 and MSVC 19.33 are following ([link](https://godbolt.org/z/sj8zeKeMo)):
![image](https://user-images.githubusercontent.com/10415461/208910337-324e8de9-84dd-4a73-bffc-32131b9497d7.png)

So it looks like Clang is not resuming coroutine on other thread but on the previous. The description of this example on cppreference.com states the following:

> Note that because the coroutine is fully suspended before entering awaiter.await_suspend(), that function is free to transfer the coroutine handle across threads, with no additional synchronization. For example, it can put it inside a callback, scheduled to run on a threadpool when async I/O operation completes. In that case, since the current coroutine may have been resumed and thus executed the awaiter object's destructor, all concurrently as await_suspend() continues its execution on the current thread, await_suspend() should treat *this as destroyed and not access it after the handle was published to other threads.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V1uP4jgW_jXm5QhEHK4PPFRRxag1mu7VzmpfkWOfEHc5duRLMfSvX9lJIFBQPdrWIESq4uPv3I8_M-fkQSNuyPyZzF9GLPjK2M2X3_5Np9lsVBhx2myNdlKgBV8hlEYpc5T6ANwIBPyL1Y1CKK2pgTeNxRItao4TbmogdEXmz0rqNzJ_IXRVed84kj8RuiN0h3pyu4PQ3ZHQHW8aQneK6UNgB4wvjDXBS42O0Py11UnomtA1HKWvwNVMKaiNkKXkzEujo27mHFoPTAgUUTp_ItMXMu1_F9P2uyX0OX7btzSXmqsgEEi-5S0EyV_vrvZWPViXxnmLrH6w7LzAvzg2j-B9ZZGJ8yK0Dxa8AXeUnld7b_Yaj_tOkK6cF9HJ_Ol7_2oBJvjoe4u_7LwEAHDeBu6BHZn0rFDYaxnKtHK3oE_Q7CNsfiNZGKNavH0UPMX003VEBIs-WA0lUw5J_gxk-XK9991I0e11wTWor_w5R3pfMS0UknxL8leozp59NPu-6SkeQPIXIPTpvhfxI8tYPyb4yXcjdYpO8uWi7-bjK2uOF302aC9r3KO1xqat9FvwTfDQWQINs6xGjxa08YB140-E0lSld-zpjf7oUGywisxfUpSriUUX6t7YLs4PMNsmhH8Zj9pLpiBogaXUKKDAir1LY0n-BIxzdC42fNNLqhMIdN6aE4oYR19J9xB_kMPkxJbkWyCUfsUjdLH48hIVEUr75ZSYMclfD-j3UvR11O9dkvlWx8c9t_4ffTHRP1XVOxS9Beng2-_Xyj8r6WFaUqkOZeM_Q0-6Xrk05vKZ0EUs1YHgBaF9dN3smXt73OuNNbV0uPenBof6b8IYQSDGo7Vkb4rvyP3Hbu4cudfO5yx0zbzX-I4WpJaxgAYt_suQpdQfALVpB-vfRE6J6nyNf9_LU5IJuh0_Yt_iS6P_Rk6v8ts-UoRTUUh92Bv9C2OcG-08pFOhlZ5eT4pYrj10ejEs9Ku6e9Q52374gvPMehRgNJwRh310MeCzTuVmn2r70SnWuTrc0rVe2oZ2MH0qtPhJLLJ_LhZtS_8sFtlPYtE59s00DraR8FyWOupBV-eo0ix60wEPLb4dBlJ7qJnsivPuPLiuMLg6CB8W5k1mzmrPVGrIr_5TtUFS3gGrjT60DkI2n0wJ3cJv2y1kdEKBaQF__PnfLWTrSZ4Ds0OW-TmFPBhRGOUnxh4I3f0gdOe-r37g7_iH6U7rM-ejGZk_yzryyTtAwaEdp1U3OUhfhSK-4UbHI69jptl0ls1ni4zQHZ2u1tk0z5fjnM5wJXA9Xs2EGM_YMh8XZcnHOc3yrFjP1kuxnDT6cMlD-v3TgPSgjHlzoOQbdrGRLtGBPgFw5j2xzIyvEglPCSuCb0sPobH4Lk1wE4ghF-i4lWk2gSnb06pn6UZ_5OjOM4_umtvfMuX8Fb4aj-Ar5qFAzoLDtONin3RQhsgMukmcWERpLAJqjzY603Xv5JblpUxtW_AyaJ5Mj3gWEWIrW6Zd2d0_LhrbUQyMW-NcFxYXgdKNQJvI-2XEYgrcSfPKGi1_pMvBBHbG9lGJW6QHzjREgiY9yHTfAQacKVUw_hZFHK9QBIUimmSDjsFkndomEt9jhRpY1ARfCN19A9Ogbe8i3ERFHt0EvujWUc5c0uyk5l0sg7Wo_cDDmp2gYu8IBaI-D5zYLr4KMavIQxzHcXc_GvuzeunaKRm4jwx0C_GCxI3utKgTMPeBb8eTLNa81AEdSN_rSLWkr6zsZ8L2LoirTFAC4u3H9wwxKrwM7uhFLPWWXsaos9J3Oe4ye2QOmlAo6ao26sMGcJOR2ORina_ZCDfZYpkt6HKRL0bVplis2LpYlVkxpWtasOWKzXi2pHPGaFHmfCQ3dEppRmmW5dNpvphwOpviquDz-VKIWVGQ2RRrJtVEqfc6DpeRdC7gZr5e5KuRYgUql27MlGo8QlqM7H3-MrKbuGdchIMjs6mSzrsLipde4eZrfzp1ByAKkHqQ9k_v1KNg1eZmCKZ51Q2pqKt7jBtr2mLYJQsdobvkwf8CAAD__7wJ3BY">