xref: /llvm-project/clang/test/CodeGenCoroutines/pr59221.cpp (revision c5de4dd1eab00df76c1a68c5f397304ceacb71f2)
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()73 static inline auto a() noexcept -> task<int> {
74 	co_return 42;
75 }
76 
test()77 static inline auto test() noexcept -> task<int> {
78 	co_return co_await a();
79 }
80 
foo()81 int 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