// -*-c++-*-
// vim: set ft=cpp:

/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#pragma once

#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#  define CMake_HAVE_CXX_IN_PLACE
#endif

#if (__cplusplus >= 202302L ||                                                \
     (defined(_MSVC_LANG) && _MSVC_LANG >= 202302L)) &&                       \
  defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L)
#  define CMake_HAVE_CXX_UNREACHABLE
#endif

#include <cstdlib> // IWYU pragma: export
#include <utility> // IWYU pragma: export

namespace cm {

#if defined(CMake_HAVE_CXX_IN_PLACE)

using std::in_place_t;
using std::in_place;

#else

struct in_place_t
{
  explicit in_place_t() = default;
};

constexpr in_place_t in_place{};

#endif

#if defined(CMake_HAVE_CXX_UNREACHABLE)

using std::unreachable;

#else

[[noreturn]] inline void unreachable()
{
#  if defined(_MSC_VER)
  __assume(0);
  std::abort();
#  elif defined(__has_builtin)
#    if __has_builtin(__builtin_unreachable)
  __builtin_unreachable();
#    else
  std::abort();
#    endif
#  elif defined(__GNUC__) && defined(__GNUC_MINOR__) &&                       \
    ((__GNUC__ * 100 + __GNUC_MINOR__) >= 405)
  __builtin_unreachable();
#  else
  std::abort();
#  endif
}

#endif
}
