File: pr59221.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (88 lines) | stat: -rw-r--r-- 2,010 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 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 -O1 -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: }