// 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: movl	$40, %esi
// CHECK-NEXT: jmp	_ZdlPvm@PLT

// CHECK: _Z3Bazv.destroy:{{.*}}
// CHECK-NEXT: #
// CHECK-NEXT: movl	$80, %esi
// CHECK-NEXT: jmp	_ZdlPvm

// CHECK: _Z3Barv.destroy:{{.*}}
// CHECK-NEXT: #
// CHECK-NEXT: movl	$120, %esi
// CHECK-NEXT: jmp	_ZdlPvm
