diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -398,8 +398,8 @@ diag::warn_coroutine_handle_address_invalid_return_type) << JustAddress->getType(); - return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume, - JustAddress); + return S.MaybeCreateExprWithCleanups( + buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume, JustAddress)); } /// Build calls to await_ready, await_suspend, and await_resume for a co_await diff --git a/clang/test/CodeGenCoroutines/Inputs/coroutine.h b/clang/test/CodeGenCoroutines/Inputs/coroutine.h --- a/clang/test/CodeGenCoroutines/Inputs/coroutine.h +++ b/clang/test/CodeGenCoroutines/Inputs/coroutine.h @@ -15,7 +15,7 @@ return me; } void operator()() { resume(); } - void *address() const { return ptr; } + void *address() const noexcept { return ptr; } void resume() const { __builtin_coro_resume(ptr); } void destroy() const { __builtin_coro_destroy(ptr); } bool done() const { return __builtin_coro_done(ptr); } @@ -52,19 +52,21 @@ } }; - template - bool operator==(coroutine_handle<_PromiseT> const& _Left, - coroutine_handle<_PromiseT> const& _Right) noexcept - { - return _Left.address() == _Right.address(); - } +struct noop_coroutine_promise {}; +using noop_coroutine_handle = coroutine_handle; +coroutine_handle<> noop_coroutine() { return {}; } - template - bool operator!=(coroutine_handle<_PromiseT> const& _Left, - coroutine_handle<_PromiseT> const& _Right) noexcept - { - return !(_Left == _Right); - } +template +bool operator==(coroutine_handle<_PromiseT> const &_Left, + coroutine_handle<_PromiseT> const &_Right) noexcept { + return _Left.address() == _Right.address(); +} + +template +bool operator!=(coroutine_handle<_PromiseT> const &_Left, + coroutine_handle<_PromiseT> const &_Right) noexcept { + return !(_Left == _Right); +} struct suspend_always { bool await_ready() { return false; } diff --git a/clang/test/CodeGenCoroutines/coro-semmetric-transfer.cpp b/clang/test/CodeGenCoroutines/coro-semmetric-transfer.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCoroutines/coro-semmetric-transfer.cpp @@ -0,0 +1,52 @@ +// RUN: %clang -std=c++14 -fcoroutines-ts -fsanitize=address -emit-llvm -S -o - %s | FileCheck %s + +#include "Inputs/coroutine.h" + +namespace coro = std::experimental::coroutines_v1; + +struct detached_task { + struct promise_type { + detached_task get_return_object() noexcept { + return detached_task{coro::coroutine_handle::from_promise(*this)}; + } + + void return_void() noexcept {} + + struct final_awaiter { + bool await_ready() noexcept { return false; } + coro::coroutine_handle<> await_suspend(coro::coroutine_handle h) noexcept { + h.destroy(); + return coro::noop_coroutine(); + } + void await_resume() noexcept {} + }; + + void unhandled_exception() noexcept {} + + final_awaiter final_suspend() noexcept { return {}; } + + coro::suspend_always initial_suspend() noexcept { return {}; } + }; + + ~detached_task() { + if (coro_) { + coro_.destroy(); + coro_ = {}; + } + } + + void start() && { + auto tmp = coro_; + coro_ = {}; + tmp.resume(); + } + + coro::coroutine_handle coro_; +}; + +detached_task foo() { + co_return; +} + +// This is to check that temporary handle returned by the symmetric transfer is not put in the frame. +// CHECK: {{.*}} = call nonnull i8* @_Znwm(i64 48)