#ifndef PASTIS_ASSERT_HPP #define PASTIS_ASSERT_HPP #include <rang.hpp> #include <iostream> #include <string> class AssertError { private: const std::string m_file; const int m_line; const std::string m_function; const std::string m_message; public: friend std::ostream& operator<<(std::ostream& os, const AssertError& assert_error) { os << '\n' << rang::style::bold << "*** Assertion error ***\n" << " at " << assert_error.m_file << ':' << assert_error.m_line << '\n' << " in " << assert_error.m_function << '\n' << "*** " << rang::fgB::red << assert_error.m_message << rang::fg::reset << rang::style::reset << '\n'; return os; } AssertError(const AssertError&) = default; AssertError(std::string file, int line, std::string function, std::string message) : m_file(file), m_line(line), m_function(function), m_message(message) { ; } ~AssertError() = default; }; #pragma GCC diagnostic ignored "-Wattributes" inline bool __attribute__((analyzer_noreturn)) _pastis_assert(const bool& assert) { return assert; } #pragma GCC diagnostic pop #ifdef NDEBUG // Useless test is there to check syntax even in optimized mode. Costs nothing. #define Assert(assertion) \ if (not _pastis_assert(assertion)) {} #else // NDEBUG #define Assert(assertion) \ if (not _pastis_assert(assertion)) { \ throw AssertError(__FILE__, \ __LINE__, \ __PRETTY_FUNCTION__, \ (#assertion)); \ } #endif // NDEBUG // stores the current state of Assert macro. This is useful for instance to // noexcept management of Assert throws #ifdef NDEBUG #define NO_ASSERT true #else // NDEBUG #define NO_ASSERT false #endif // NDEBUG #endif // PASTIS_ASSERT_HPP