1#ifndef CHECK_H_ 2#define CHECK_H_ 3 4#include <cmath> 5#include <cstdlib> 6#include <ostream> 7 8#include "benchmark/export.h" 9#include "internal_macros.h" 10#include "log.h" 11 12#if defined(__GNUC__) || defined(__clang__) 13#define BENCHMARK_NOEXCEPT noexcept 14#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) 15#elif defined(_MSC_VER) && !defined(__clang__) 16#if _MSC_VER >= 1900 17#define BENCHMARK_NOEXCEPT noexcept 18#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) 19#else 20#define BENCHMARK_NOEXCEPT 21#define BENCHMARK_NOEXCEPT_OP(x) 22#endif 23#define __func__ __FUNCTION__ 24#else 25#define BENCHMARK_NOEXCEPT 26#define BENCHMARK_NOEXCEPT_OP(x) 27#endif 28 29namespace benchmark { 30namespace internal { 31 32typedef void(AbortHandlerT)(); 33 34BENCHMARK_EXPORT 35AbortHandlerT*& GetAbortHandler(); 36 37BENCHMARK_NORETURN inline void CallAbortHandler() { 38 GetAbortHandler()(); 39 std::abort(); // fallback to enforce noreturn 40} 41 42// CheckHandler is the class constructed by failing BM_CHECK macros. 43// CheckHandler will log information about the failures and abort when it is 44// destructed. 45class CheckHandler { 46 public: 47 CheckHandler(const char* check, const char* file, const char* func, int line) 48 : log_(GetErrorLogInstance()) { 49 log_ << file << ":" << line << ": " << func << ": Check `" << check 50 << "' failed. "; 51 } 52 53 LogType& GetLog() { return log_; } 54 55#if defined(COMPILER_MSVC) 56#pragma warning(push) 57#pragma warning(disable : 4722) 58#endif 59 BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) { 60 log_ << std::endl; 61 CallAbortHandler(); 62 } 63#if defined(COMPILER_MSVC) 64#pragma warning(pop) 65#endif 66 67 CheckHandler& operator=(const CheckHandler&) = delete; 68 CheckHandler(const CheckHandler&) = delete; 69 CheckHandler() = delete; 70 71 private: 72 LogType& log_; 73}; 74 75} // end namespace internal 76} // end namespace benchmark 77 78// The BM_CHECK macro returns a std::ostream object that can have extra 79// information written to it. 80#ifndef NDEBUG 81#define BM_CHECK(b) \ 82 (b ? ::benchmark::internal::GetNullLogInstance() \ 83 : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \ 84 .GetLog()) 85#else 86#define BM_CHECK(b) ::benchmark::internal::GetNullLogInstance() 87#endif 88 89// clang-format off 90// preserve whitespacing between operators for alignment 91#define BM_CHECK_EQ(a, b) BM_CHECK((a) == (b)) 92#define BM_CHECK_NE(a, b) BM_CHECK((a) != (b)) 93#define BM_CHECK_GE(a, b) BM_CHECK((a) >= (b)) 94#define BM_CHECK_LE(a, b) BM_CHECK((a) <= (b)) 95#define BM_CHECK_GT(a, b) BM_CHECK((a) > (b)) 96#define BM_CHECK_LT(a, b) BM_CHECK((a) < (b)) 97 98#define BM_CHECK_FLOAT_EQ(a, b, eps) BM_CHECK(std::fabs((a) - (b)) < (eps)) 99#define BM_CHECK_FLOAT_NE(a, b, eps) BM_CHECK(std::fabs((a) - (b)) >= (eps)) 100#define BM_CHECK_FLOAT_GE(a, b, eps) BM_CHECK((a) - (b) > -(eps)) 101#define BM_CHECK_FLOAT_LE(a, b, eps) BM_CHECK((b) - (a) > -(eps)) 102#define BM_CHECK_FLOAT_GT(a, b, eps) BM_CHECK((a) - (b) > (eps)) 103#define BM_CHECK_FLOAT_LT(a, b, eps) BM_CHECK((b) - (a) > (eps)) 104//clang-format on 105 106#endif // CHECK_H_ 107