• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
29 namespace benchmark {
30 namespace internal {
31 
32 typedef void(AbortHandlerT)();
33 
34 BENCHMARK_EXPORT
35 AbortHandlerT*& GetAbortHandler();
36 
CallAbortHandler()37 BENCHMARK_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.
45 class CheckHandler {
46  public:
CheckHandler(const char * check,const char * file,const char * func,int line)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 
GetLog()53   LogType& GetLog() { return log_; }
54 
55 #if defined(COMPILER_MSVC)
56 #pragma warning(push)
57 #pragma warning(disable : 4722)
58 #endif
~CheckHandler()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