// Test for PR56919. Tests the destroy function contains the call to delete function only.
//
// REQUIRES: x86-registered-target
//
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -O3 -S -o - | FileCheck %s

#include "Inputs/coroutine.h"

namespace std {

template <typename T> struct remove_reference { using type = T; };
template <typename T> struct remove_reference<T &> { using type = T; };
template <typename T> struct remove_reference<T &&> { using type = T; };

template <typename T>
constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {
  return static_cast<typename std::remove_reference<T>::type &&>(t);
}

}

template <typename T>
class Task final {
 public:
  using value_type = T;

  class promise_type final {
   public: 
    Task<void> get_return_object() { return Task<void>(std::coroutine_handle<promise_type>::from_promise(*this)); }

    void unhandled_exception();

    std::suspend_always initial_suspend() { return {}; }

    auto await_transform(Task<void> co) {
      return await_transform(std::move(co.handle_.promise()));
    }

    auto await_transform(promise_type&& awaited) {
      struct Awaitable {
        promise_type&& awaited;

        bool await_ready() { return false; }

        std::coroutine_handle<> await_suspend(
            const std::coroutine_handle<> handle) {
          // Register our handle to be resumed once the awaited promise's coroutine
          // finishes, and then resume that coroutine.
          awaited.registered_handle_ = handle;
          return std::coroutine_handle<promise_type>::from_promise(awaited);
        }

        void await_resume() {}

       private:
      };

      return Awaitable{std::move(awaited)};
    }

    void return_void() {}

    // At final suspend resume our registered handle.
    auto final_suspend() noexcept {
      struct FinalSuspendAwaitable final {
        bool await_ready() noexcept { return false; }

        std::coroutine_handle<> await_suspend(
            std::coroutine_handle<> h) noexcept {
          return to_resume;
        }

        void await_resume() noexcept {}

        std::coroutine_handle<> to_resume;
      };

      return FinalSuspendAwaitable{registered_handle_};
    }

   private:
    std::coroutine_handle<promise_type> my_handle() {
      return std::coroutine_handle<promise_type>::from_promise(*this);
    }

    std::coroutine_handle<> registered_handle_;
  };

  ~Task() {
    // Teach llvm that we are only ever destroyed when the coroutine body is done,
    // so there is no need for the jump table in the destroy function. Our coroutine
    // library doesn't expose handles to the user, so we know this constraint isn't
    // violated.
    if (!handle_.done()) {
      __builtin_unreachable();
    }

    handle_.destroy();
  }

 private:
  explicit Task(const std::coroutine_handle<promise_type> handle)
      : handle_(handle) {}

  const std::coroutine_handle<promise_type> handle_;
};

Task<void> Qux() { co_return; }
Task<void> Baz() { co_await Qux(); }
Task<void> Bar() { co_await Baz(); }

// CHECK: _Z3Quxv.destroy:{{.*}}
// CHECK-NEXT: #
// CHECK-NEXT: jmp	_ZdlPv

// CHECK: _Z3Bazv.destroy:{{.*}}
// CHECK-NEXT: #
// CHECK-NEXT: jmp	_ZdlPv

// CHECK: _Z3Barv.destroy:{{.*}}
// CHECK-NEXT: #
// CHECK-NEXT: jmp	_ZdlPv
