// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCUDACXX___VERBOSE_ABORT
#define _LIBCUDACXX___VERBOSE_ABORT

#include <cuda/std/detail/__config>

#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
#  pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
#  pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
#  pragma system_header
#endif // no system header

#include <cuda/std/detail/libcxx/include/__availability>

// Provide a default implementation of __libcpp_verbose_abort if we know that neither the built
// library nor the user is providing one. Otherwise, just declare it and use the one from the
// built library or the one provided by the user.
//
// We can't provide a great implementation because it needs to be pretty much
// dependency-free (this is included everywhere else in the library).
#if defined(_LIBCUDACXX_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) \
  && !defined(_LIBCUDACXX_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED)

extern "C" void abort();

_LIBCUDACXX_BEGIN_NAMESPACE_STD

_CCCL_NORETURN _LIBCUDACXX_ATTRIBUTE_FORMAT(__printf__, 1, 2)
  _LIBCUDACXX_HIDE_FROM_ABI void __libcpp_verbose_abort(const char*, ...)
{
  ::abort();
  __builtin_unreachable(); // never reached, but needed to tell the compiler that the function never returns
}

_LIBCUDACXX_END_NAMESPACE_STD

#else

_LIBCUDACXX_BEGIN_NAMESPACE_STD

_CCCL_NORETURN
_CCCL_HOST_DEVICE _LIBCUDACXX_ATTRIBUTE_FORMAT(__printf__, 1, 2) void __libcpp_verbose_abort(const char* __format, ...);

_LIBCUDACXX_END_NAMESPACE_STD

#endif

#endif // _LIBCUDACXX___VERBOSE_ABORT
