File: coro-destructor-of-final_suspend.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 (90 lines) | stat: -rw-r--r-- 2,233 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
89
90
// This addresses https://github.com/llvm/llvm-project/issues/57339
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fcxx-exceptions \
// RUN:     -fexceptions -emit-llvm -o - %s -O1 | FileCheck %s

#include "Inputs/coroutine.h"

struct gen {
  struct promise_type {
    gen get_return_object() noexcept {
      return gen{std::coroutine_handle<promise_type>::from_promise(*this)};
    }
    std::suspend_always initial_suspend() noexcept { return {}; }

    struct final_awaiter {
      ~final_awaiter() noexcept;
      bool await_ready() noexcept {
        return false;
      }
      void await_suspend(std::coroutine_handle<>) noexcept {}
      void await_resume() noexcept {}
    };

    final_awaiter final_suspend() noexcept {
      return {};
    }

    void unhandled_exception() {
      throw;
    }
    void return_void() {}
  };

  gen(std::coroutine_handle<promise_type> coro) noexcept
  : coro(coro)
  {
  }

  ~gen() noexcept {
    if (coro) {
      coro.destroy();
    }
  }

  gen(gen&& g) noexcept
  : coro(g.coro)
  {
    g.coro = {};
  }

  std::coroutine_handle<promise_type> coro;
};

struct X {};

gen maybe_throwing(bool x) {
  if (x) {
    throw X{};
  }
  co_return;
}

// CHECK: define{{.*}}@_Z14maybe_throwingb.destroy
// CHECK: %[[INDEX:.+]] = load i1, ptr %index.addr, align 1
// CHECK: br i1 %[[INDEX]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]]
// CHECK: [[AFTERSUSPEND]]:
// CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev(
// CHECK: [[CORO_FREE]]:
// CHECK: call{{.*}}_ZdlPv

void noexcept_call() noexcept;

gen no_throwing() {
  noexcept_call();
  co_return;
}

// CHECK: define{{.*}}@_Z11no_throwingv.resume({{.*}}%[[ARG:.+]])
// CHECK: resume:
// CHECK:   call{{.*}}@_Z13noexcept_callv()
// CHECK:   store ptr null, ptr %[[ARG]]
// CHECK:   ret void

// CHECK: define{{.*}}@_Z11no_throwingv.destroy({{.*}}%[[ARG:.+]])
// CHECK: %[[RESUME_FN_ADDR:.+]] = load ptr, ptr %[[ARG]]
// CHECK: %[[IF_NULL:.+]] = icmp eq ptr %[[RESUME_FN_ADDR]], null
// CHECK: br i1 %[[IF_NULL]], label %[[AFTERSUSPEND:.+]], label %[[CORO_FREE:.+]]
// CHECK: [[AFTERSUSPEND]]:
// CHECK: call{{.*}}_ZN3gen12promise_type13final_awaiterD1Ev(
// CHECK: [[CORO_FREE]]:
// CHECK: call{{.*}}_ZdlPv