// This file is part of the mcl project. // Copyright (c) 2022 merryhime // SPDX-License-Identifier: MIT #pragma once #include #include #include #include "mcl/hint/assume.hpp" namespace mcl::detail { [[noreturn]] void assert_terminate_impl(fmt::string_view msg, fmt::format_args args); template [[noreturn]] void assert_terminate(fmt::string_view msg, Ts... args) { assert_terminate_impl(msg, fmt::make_format_args(args...)); } } // namespace mcl::detail #define UNREACHABLE() ASSERT_FALSE("Unreachable code!") #define ASSERT(expr) \ [&] { \ if (std::is_constant_evaluated()) { \ if (!(expr)) { \ throw std::logic_error{"ASSERT failed at compile time"}; \ } \ } else { \ if (!(expr)) [[unlikely]] { \ ::mcl::detail::assert_terminate(#expr); \ } \ } \ }() #define ASSERT_MSG(expr, ...) \ [&] { \ if (std::is_constant_evaluated()) { \ if (!(expr)) { \ throw std::logic_error{"ASSERT_MSG failed at compile time"}; \ } \ } else { \ if (!(expr)) [[unlikely]] { \ ::mcl::detail::assert_terminate(#expr "\nMessage: " __VA_ARGS__); \ } \ } \ }() #define ASSERT_FALSE(...) ::mcl::detail::assert_terminate("false\nMessage: " __VA_ARGS__) #if defined(NDEBUG) || defined(MCL_IGNORE_ASSERTS) # define DEBUG_ASSERT(expr) ASSUME(expr) # define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr) #else # define DEBUG_ASSERT(expr) ASSERT(expr) # define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__) #endif