89 lines · cpp
1// Test for PR59221. Tests the compiler wouldn't misoptimize the final result.2//3// REQUIRES: x86-registered-target4//5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -O1 -emit-llvm -o - | FileCheck %s6 7#include "Inputs/coroutine.h"8 9template <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 {15 auto await_suspend(std::coroutine_handle<promise_type> me) const noexcept {16 return me.promise().caller;17 }18 };19 20 constexpr auto initial_suspend() const noexcept {21 return std::suspend_always();22 }23 constexpr auto final_suspend() const noexcept {24 return final_awaiter{};25 }26 auto unhandled_exception() noexcept {27 // ignore28 }29 constexpr void return_value(T v) noexcept {30 value = v;31 } 32 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 41 task(promise_type & p) noexcept: promise{p} { }42 43 ~task() noexcept {44 coroutine_handle::from_promise(promise).destroy();45 }46 47 auto await_ready() noexcept {48 return false;49 }50 51 auto await_suspend(std::coroutine_handle<> caller) noexcept {52 promise.caller = caller;53 return coroutine_handle::from_promise(promise);54 }55 56 constexpr auto await_resume() const noexcept {57 return promise.value;58 }59 60 // non-coroutine access to result61 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 73static inline auto a() noexcept -> task<int> {74 co_return 42;75}76 77static inline auto test() noexcept -> task<int> {78 co_return co_await a();79}80 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