| // Test for PR59221. Tests the compiler wouldn't misoptimize the final result. |
| // |
| // REQUIRES: x86-registered-target |
| // |
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -O3 -S -emit-llvm -o - | FileCheck %s |
| |
| #include "Inputs/coroutine.h" |
| |
| template <typename T> struct task { |
| struct promise_type { |
| T value{123}; |
| std::coroutine_handle<> caller{std::noop_coroutine()}; |
| |
| struct final_awaiter: std::suspend_always { |
| auto await_suspend(std::coroutine_handle<promise_type> me) const noexcept { |
| return me.promise().caller; |
| } |
| }; |
| |
| constexpr auto initial_suspend() const noexcept { |
| return std::suspend_always(); |
| } |
| constexpr auto final_suspend() const noexcept { |
| return final_awaiter{}; |
| } |
| auto unhandled_exception() noexcept { |
| // ignore |
| } |
| constexpr void return_value(T v) noexcept { |
| value = v; |
| } |
| constexpr auto & get_return_object() noexcept { |
| return *this; |
| } |
| }; |
| |
| using coroutine_handle = std::coroutine_handle<promise_type>; |
| |
| promise_type & promise{nullptr}; |
| |
| task(promise_type & p) noexcept: promise{p} { } |
| |
| ~task() noexcept { |
| coroutine_handle::from_promise(promise).destroy(); |
| } |
| |
| auto await_ready() noexcept { |
| return false; |
| } |
| |
| auto await_suspend(std::coroutine_handle<> caller) noexcept { |
| promise.caller = caller; |
| return coroutine_handle::from_promise(promise); |
| } |
| |
| constexpr auto await_resume() const noexcept { |
| return promise.value; |
| } |
| |
| // non-coroutine access to result |
| auto get() noexcept { |
| const auto handle = coroutine_handle::from_promise(promise); |
| |
| if (!handle.done()) { |
| handle.resume(); |
| } |
| |
| return promise.value; |
| } |
| }; |
| |
| |
| static inline auto a() noexcept -> task<int> { |
| co_return 42; |
| } |
| |
| static inline auto test() noexcept -> task<int> { |
| co_return co_await a(); |
| } |
| |
| int foo() { |
| return test().get(); |
| } |
| |
| // Checks that the store for the result value 42 is not misoptimized out. |
| // CHECK: define{{.*}}_Z3foov( |
| // CHECK: store i32 42, ptr %{{.*}} |
| // CHECK: } |