1 // Test for PR59221. Tests the compiler wouldn't misoptimize the final result. 2 // 3 // REQUIRES: x86-registered-target 4 // 5 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -O1 -emit-llvm -o - | FileCheck %s 6 7 #include "Inputs/coroutine.h" 8 9 template <typename T> struct task { 10 struct promise_type { 11 T value{123}; 12 std::coroutine_handle<> caller{std::noop_coroutine()}; 13 14 struct final_awaiter: std::suspend_always { await_suspendtask::promise_type::final_awaiter15 auto await_suspend(std::coroutine_handle<promise_type> me) const noexcept { 16 return me.promise().caller; 17 } 18 }; 19 initial_suspendtask::promise_type20 constexpr auto initial_suspend() const noexcept { 21 return std::suspend_always(); 22 } final_suspendtask::promise_type23 constexpr auto final_suspend() const noexcept { 24 return final_awaiter{}; 25 } unhandled_exceptiontask::promise_type26 auto unhandled_exception() noexcept { 27 // ignore 28 } return_valuetask::promise_type29 constexpr void return_value(T v) noexcept { 30 value = v; 31 } get_return_objecttask::promise_type32 constexpr auto & get_return_object() noexcept { 33 return *this; 34 } 35 }; 36 37 using coroutine_handle = std::coroutine_handle<promise_type>; 38 39 promise_type & promise{nullptr}; 40 tasktask41 task(promise_type & p) noexcept: promise{p} { } 42 ~tasktask43 ~task() noexcept { 44 coroutine_handle::from_promise(promise).destroy(); 45 } 46 await_readytask47 auto await_ready() noexcept { 48 return false; 49 } 50 await_suspendtask51 auto await_suspend(std::coroutine_handle<> caller) noexcept { 52 promise.caller = caller; 53 return coroutine_handle::from_promise(promise); 54 } 55 await_resumetask56 constexpr auto await_resume() const noexcept { 57 return promise.value; 58 } 59 60 // non-coroutine access to result gettask61 auto get() noexcept { 62 const auto handle = coroutine_handle::from_promise(promise); 63 64 if (!handle.done()) { 65 handle.resume(); 66 } 67 68 return promise.value; 69 } 70 }; 71 72 a()73static inline auto a() noexcept -> task<int> { 74 co_return 42; 75 } 76 test()77static inline auto test() noexcept -> task<int> { 78 co_return co_await a(); 79 } 80 foo()81int foo() { 82 return test().get(); 83 } 84 85 // Checks that the store for the result value 42 is not misoptimized out. 86 // CHECK: define{{.*}}_Z3foov( 87 // CHECK: store i32 42, ptr %{{.*}} 88 // CHECK: } 89