1afff89eeSGor Nishanov // Verify that we synthesized the coroutine for a lambda inside of a function template. 2*ec117158SChuanqi Xu // RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s -fexceptions -fcxx-exceptions -disable-llvm-passes | FileCheck %s 3afff89eeSGor Nishanov 4*ec117158SChuanqi Xu namespace std { 5afff89eeSGor Nishanov template <typename R, typename... T> struct coroutine_traits { 6afff89eeSGor Nishanov using promise_type = typename R::promise_type; 7afff89eeSGor Nishanov }; 8afff89eeSGor Nishanov 9afff89eeSGor Nishanov template <class Promise = void> struct coroutine_handle; 10afff89eeSGor Nishanov template <> struct coroutine_handle<void> { 11afff89eeSGor Nishanov static coroutine_handle from_address(void *) noexcept; 12afff89eeSGor Nishanov coroutine_handle() = default; 13afff89eeSGor Nishanov template <class PromiseType> 14afff89eeSGor Nishanov coroutine_handle(coroutine_handle<PromiseType>) noexcept; 15afff89eeSGor Nishanov }; 16afff89eeSGor Nishanov template <class Promise> struct coroutine_handle : coroutine_handle<void> { 17afff89eeSGor Nishanov coroutine_handle() = default; 18afff89eeSGor Nishanov static coroutine_handle from_address(void *) noexcept; 19afff89eeSGor Nishanov }; 20*ec117158SChuanqi Xu } // namespace std 21afff89eeSGor Nishanov 22afff89eeSGor Nishanov struct suspend_always { 23afff89eeSGor Nishanov bool await_ready() noexcept; 24*ec117158SChuanqi Xu void await_suspend(std::coroutine_handle<>) noexcept; 25afff89eeSGor Nishanov void await_resume() noexcept; 26afff89eeSGor Nishanov }; 27afff89eeSGor Nishanov 28afff89eeSGor Nishanov struct Task { 29afff89eeSGor Nishanov struct promise_type { 30afff89eeSGor Nishanov Task get_return_object(); return_voidTask::promise_type31afff89eeSGor Nishanov void return_void() {} 32afff89eeSGor Nishanov suspend_always initial_suspend() noexcept; 33afff89eeSGor Nishanov suspend_always final_suspend() noexcept; 34afff89eeSGor Nishanov void unhandled_exception() noexcept; 35afff89eeSGor Nishanov }; 36afff89eeSGor Nishanov }; 37afff89eeSGor Nishanov SyncAwait(_AwrT && A)38afff89eeSGor Nishanovtemplate <typename _AwrT> auto SyncAwait(_AwrT &&A) { 39afff89eeSGor Nishanov if (!A.await_ready()) { 40afff89eeSGor Nishanov auto AwaitAsync = [&]() -> Task { 41afff89eeSGor Nishanov try { (void)(co_await A); } catch (...) {} 42afff89eeSGor Nishanov }; 43afff89eeSGor Nishanov Task t = AwaitAsync(); 44afff89eeSGor Nishanov } 45afff89eeSGor Nishanov return A.await_resume(); 46afff89eeSGor Nishanov } 47afff89eeSGor Nishanov f()48afff89eeSGor Nishanovvoid f() { 49afff89eeSGor Nishanov suspend_always test; 50afff89eeSGor Nishanov SyncAwait(test); 51afff89eeSGor Nishanov } 52afff89eeSGor Nishanov 53afff89eeSGor Nishanov // Verify that we synthesized the coroutine for a lambda inside SyncAwait 54afff89eeSGor Nishanov // CHECK-LABEL: define linkonce_odr void @_ZZ9SyncAwaitIR14suspend_alwaysEDaOT_ENKUlvE_clEv( 55afff89eeSGor Nishanov // CHECK: alloca %"struct.Task::promise_type" 56afff89eeSGor Nishanov // CHECK: call token @llvm.coro.id( 57afff89eeSGor Nishanov // CHECK: call i8 @llvm.coro.suspend( 58afff89eeSGor Nishanov // CHECK: call i1 @llvm.coro.end( 59