Skip to content

Crash on invalid coroutine code #77111

@ilya-biryukov

Description

@ilya-biryukov

See godbolt.

#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):

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.

Metadata

Metadata

Labels

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions