xref: /llvm-project/third-party/benchmark/src/check.h (revision a5b797172cc902db166e9a695716fb81405f86e4)
15dda2efdSMircea Trofin #ifndef CHECK_H_
25dda2efdSMircea Trofin #define CHECK_H_
35dda2efdSMircea Trofin 
45dda2efdSMircea Trofin #include <cmath>
55dda2efdSMircea Trofin #include <cstdlib>
65dda2efdSMircea Trofin #include <ostream>
75dda2efdSMircea Trofin 
8*a5b79717SMircea Trofin #include "benchmark/export.h"
95dda2efdSMircea Trofin #include "internal_macros.h"
105dda2efdSMircea Trofin #include "log.h"
115dda2efdSMircea Trofin 
12*a5b79717SMircea Trofin #if defined(__GNUC__) || defined(__clang__)
13*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT noexcept
14*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
15*a5b79717SMircea Trofin #elif defined(_MSC_VER) && !defined(__clang__)
16*a5b79717SMircea Trofin #if _MSC_VER >= 1900
17*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT noexcept
18*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
19*a5b79717SMircea Trofin #else
20*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT
21*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT_OP(x)
22*a5b79717SMircea Trofin #endif
23*a5b79717SMircea Trofin #define __func__ __FUNCTION__
24*a5b79717SMircea Trofin #else
25*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT
26*a5b79717SMircea Trofin #define BENCHMARK_NOEXCEPT_OP(x)
27*a5b79717SMircea Trofin #endif
28*a5b79717SMircea Trofin 
295dda2efdSMircea Trofin namespace benchmark {
305dda2efdSMircea Trofin namespace internal {
315dda2efdSMircea Trofin 
325dda2efdSMircea Trofin typedef void(AbortHandlerT)();
335dda2efdSMircea Trofin 
34*a5b79717SMircea Trofin BENCHMARK_EXPORT
35*a5b79717SMircea Trofin AbortHandlerT*& GetAbortHandler();
365dda2efdSMircea Trofin 
CallAbortHandler()375dda2efdSMircea Trofin BENCHMARK_NORETURN inline void CallAbortHandler() {
385dda2efdSMircea Trofin   GetAbortHandler()();
395dda2efdSMircea Trofin   std::abort();  // fallback to enforce noreturn
405dda2efdSMircea Trofin }
415dda2efdSMircea Trofin 
42a290770fSMircea Trofin // CheckHandler is the class constructed by failing BM_CHECK macros.
43a290770fSMircea Trofin // CheckHandler will log information about the failures and abort when it is
44a290770fSMircea Trofin // destructed.
455dda2efdSMircea Trofin class CheckHandler {
465dda2efdSMircea Trofin  public:
CheckHandler(const char * check,const char * file,const char * func,int line)475dda2efdSMircea Trofin   CheckHandler(const char* check, const char* file, const char* func, int line)
485dda2efdSMircea Trofin       : log_(GetErrorLogInstance()) {
495dda2efdSMircea Trofin     log_ << file << ":" << line << ": " << func << ": Check `" << check
505dda2efdSMircea Trofin          << "' failed. ";
515dda2efdSMircea Trofin   }
525dda2efdSMircea Trofin 
GetLog()535dda2efdSMircea Trofin   LogType& GetLog() { return log_; }
545dda2efdSMircea Trofin 
55*a5b79717SMircea Trofin #if defined(COMPILER_MSVC)
56*a5b79717SMircea Trofin #pragma warning(push)
57*a5b79717SMircea Trofin #pragma warning(disable : 4722)
58*a5b79717SMircea Trofin #endif
~CheckHandler()595dda2efdSMircea Trofin   BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
605dda2efdSMircea Trofin     log_ << std::endl;
615dda2efdSMircea Trofin     CallAbortHandler();
625dda2efdSMircea Trofin   }
63*a5b79717SMircea Trofin #if defined(COMPILER_MSVC)
64*a5b79717SMircea Trofin #pragma warning(pop)
65*a5b79717SMircea Trofin #endif
665dda2efdSMircea Trofin 
675dda2efdSMircea Trofin   CheckHandler& operator=(const CheckHandler&) = delete;
685dda2efdSMircea Trofin   CheckHandler(const CheckHandler&) = delete;
695dda2efdSMircea Trofin   CheckHandler() = delete;
705dda2efdSMircea Trofin 
715dda2efdSMircea Trofin  private:
725dda2efdSMircea Trofin   LogType& log_;
735dda2efdSMircea Trofin };
745dda2efdSMircea Trofin 
755dda2efdSMircea Trofin }  // end namespace internal
765dda2efdSMircea Trofin }  // end namespace benchmark
775dda2efdSMircea Trofin 
78a290770fSMircea Trofin // The BM_CHECK macro returns a std::ostream object that can have extra
79a290770fSMircea Trofin // information written to it.
805dda2efdSMircea Trofin #ifndef NDEBUG
81a290770fSMircea Trofin #define BM_CHECK(b)                                                          \
825dda2efdSMircea Trofin   (b ? ::benchmark::internal::GetNullLogInstance()                           \
835dda2efdSMircea Trofin      : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
845dda2efdSMircea Trofin            .GetLog())
855dda2efdSMircea Trofin #else
86a290770fSMircea Trofin #define BM_CHECK(b) ::benchmark::internal::GetNullLogInstance()
875dda2efdSMircea Trofin #endif
885dda2efdSMircea Trofin 
895dda2efdSMircea Trofin // clang-format off
905dda2efdSMircea Trofin // preserve whitespacing between operators for alignment
91a290770fSMircea Trofin #define BM_CHECK_EQ(a, b) BM_CHECK((a) == (b))
92a290770fSMircea Trofin #define BM_CHECK_NE(a, b) BM_CHECK((a) != (b))
93a290770fSMircea Trofin #define BM_CHECK_GE(a, b) BM_CHECK((a) >= (b))
94a290770fSMircea Trofin #define BM_CHECK_LE(a, b) BM_CHECK((a) <= (b))
95a290770fSMircea Trofin #define BM_CHECK_GT(a, b) BM_CHECK((a) > (b))
96a290770fSMircea Trofin #define BM_CHECK_LT(a, b) BM_CHECK((a) < (b))
975dda2efdSMircea Trofin 
98a290770fSMircea Trofin #define BM_CHECK_FLOAT_EQ(a, b, eps) BM_CHECK(std::fabs((a) - (b)) <  (eps))
99a290770fSMircea Trofin #define BM_CHECK_FLOAT_NE(a, b, eps) BM_CHECK(std::fabs((a) - (b)) >= (eps))
100a290770fSMircea Trofin #define BM_CHECK_FLOAT_GE(a, b, eps) BM_CHECK((a) - (b) > -(eps))
101a290770fSMircea Trofin #define BM_CHECK_FLOAT_LE(a, b, eps) BM_CHECK((b) - (a) > -(eps))
102a290770fSMircea Trofin #define BM_CHECK_FLOAT_GT(a, b, eps) BM_CHECK((a) - (b) >  (eps))
103a290770fSMircea Trofin #define BM_CHECK_FLOAT_LT(a, b, eps) BM_CHECK((b) - (a) >  (eps))
1045dda2efdSMircea Trofin //clang-format on
1055dda2efdSMircea Trofin 
1065dda2efdSMircea Trofin #endif  // CHECK_H_
107