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

    <tr>
        <th>Summary</th>
        <td>
            Crash on invalid coroutine code
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          ilya-biryukov
      </td>
    </tr>
</table>

<pre>
    See [godbolt](https://gcc.godbolt.org/z/To4dcc16j).
```cpp
#include <coroutine>

struct Status {
    ~Status();
};

struct awaiter {
    struct promise_type {};
    bool await_ready();

 // Note: std::coroutine_handle<> was intended.
    Status await_suspend(std::coroutine_handle<> coro) { coro.destroy(); }
};

awaiter five();
awaiter sum() {
    co_return co_await five();
}
```

Expected: Clang shows an error that `Status` must be `bool`, `void` or `coroutine_handle`.
Actual: Clang crashes and produces the following output (assertions enabled):
```shell
foo.cc:28:10: error: no member named 'initial_suspend' in 'std::coroutine_traits<SOr<int>>::promise_type'
   28 | SOr<int> sum() { co_return co_await five(); }
      | ^~~
clang++: .../llvm-project/llvm/include/llvm/Support/Casting.h:706: auto llvm::cast_if_present(Y *) [X = clang::CallExpr, Y = clang::Expr]: Assertion `isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!"' failed.
...
 #0 0x0000558a59ddfba4 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) .../llvm-project/llvm/lib/Support/Unix/Signals.inc:723:13
...
#10 0x0000558a5c552876 buildCoroutineHandle .../llvm-project/clang/lib/Sema/SemaCoroutine.cpp:0:0
#11 0x0000558a5c552876 buildCoawaitCalls(clang::Sema&, clang::VarDecl*, clang::SourceLocation, clang::Expr*) .../llvm-project/clang/lib/Sema/SemaCoroutine.cpp:497:7
#12 0x0000558a5c551791 clang::Sema::BuildResolvedCoawaitExpr(clang::SourceLocation, clang::Expr*, clang::Expr*, bool) .../llvm-project/clang/lib/Sema/SemaCoroutine.cpp:0:7
```

Clang does not check the return type is `std::coroutine_handle` and because `Status` has a destructor, a call to it will have wrappers for running cleanups. Whereas the coroutine code expects `CallExpr` and the corresponding cast fails.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykVk9z3LYO_zTcCyYaiVr92cMeZNmed3jzXqdO0-TkoUjsigmX1JCU19tDPnuHlPZv7aSdemSbAiAAP-AnQMw5udWIa1LckeJ-wUbfG7uW6sA-dNIexm_mZdEZcVg_IQIp7rZGdEZ5UtwTWvfeD47kDaGPhD5uOU9mdWLsltDHPwh9_GiWgvOs_EroKiHpPUkbUqbTxYdhltBcaq5GgUDylhtrRi81kvxh1se_ztuRe3jyzI8OSHU3iQEAvk9CQmtCVySfNaS6P58vXbA9kx7ttY9ZN1izkw6f_WHAaHDhJJh1xqjJwbNFJg63MSfDqSTwP-OR5A04L0Kd8uaE7blnWigkeUvyB9gzB1J71AJFco41Q52iudENqAWh9c-8BTGhq5B9PCcCnbfmnCoEUO-U6FibjXzBG2xHlRt3k-a6gNw8W_Sj1eEUbd9ycg59pMFl9IfXAbnHgA9axfQWXG_2DpgGtNZY8D3zQMp0bniZwm50HjoMwtCb4JC24e7FSBEMjA13f6lVmc6VbrgfmTpH5Ja5HkNMEdggRo4OfI-wMUqZvdRbMKMfRg-E1sw5tF4a7QA16xSKCLa5weh6VGqSbYxJOCd5Q2uSN1kaAkds4aAN7HDXoQXNdiiA0Epq6SVT5_5XIHVQvEEDb5n0juTt0_8tyVupfXiHwhXsLqlNaHXqHK2BVC1cPnPd45-29kwoiD_BHSkevn-fhDzUldC7cOUNJElC6KNSL7sPgzVfkfv5ltDHeQ6cBU_jMBgbLFrmvNTbpCd5U6Vl8MRGbyAaToVgzj_LzfNg0aH2hNZfgNAmoijuPgPJ72HKJZq3TKmH18EGvny5VUZFcR-iNMceBx5Jx0jefg5FpfUnpqJzWhJaAqH0NoO8_XiYTIMds9txh9qD2YDU3OwG5mWnEKaOZITS0N4Nk-o0B0KxjjMlTyF9TdM0LYqaFSshNh1bXuB3BzcdfrFS-yfP-LePlvHQp7ORZftn47xFtot5t2HyhOx-1BYlu6te_KblaxDIrWbKJVIHQlc0D4zObxInNM-uEudFQeuqhG6USrRH8v4nvpZvZzET6JgG7tj87_R0EpZJ3qTx9xQ2-0HYSONAgbA2Lho_eY-FuZB-YvYeuYpsulI8mdFy_K_hLDDkRjmxq3m3un8b13JVhQKfkdEbZFm1yuAWRTzdBbi_ojPqBY-wp7zqfwzjPWkcvP8aZHoB8a3lMI1nYdCBNh54j_xbHMzzbIorW7rwlr6_Iss0DvYOORsdXq-SnjlgELflyL2Jg4EBZ0qBNyA97KVS0LMXhL1lw4DWwcZYsKPWYS1whUyPg0vg9x4tsmltnFIAbgQCxhUXszwNoDmp2dqiG4wW0SNzPs4DN79MC7HOxSpfsQWusypdLstVsaKLfl2l1VLU3YaXneBik63KuqZ8uUqLXGzqZbeQa5rSZZqlRVYsyzxLGE1XFa_psu5YhxtOlinumFRJ6F_4hFtI50ZcV1WWZQvFOlQufihSOreUhm9Gu4797satI8tUSefd2YOXXuG6DRsVjAapX5iS4qYki9Gq9c3HpPT92CXc7C5m0DWtYnKO0MeY358BAAD__2QjSRQ">