check_op.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_CHECK_OP_H_
  5. #define BASE_CHECK_OP_H_
  6. #include <cstddef>
  7. #include <string>
  8. #include <type_traits>
  9. #include "base/base_export.h"
  10. #include "base/check.h"
  11. #include "base/dcheck_is_on.h"
  12. #include "base/debug/debugging_buildflags.h"
  13. #include "base/template_util.h"
  14. // This header defines the (DP)CHECK_EQ etc. macros.
  15. //
  16. // (DP)CHECK_EQ(x, y) is similar to (DP)CHECK(x == y) but will also log the
  17. // values of x and y if the condition doesn't hold. This works for basic types
  18. // and types with an operator<< or .ToString() method.
  19. //
  20. // The operands are evaluated exactly once, and even in build modes where e.g.
  21. // DCHECK is disabled, the operands and their stringification methods are still
  22. // referenced to avoid warnings about unused variables or functions.
  23. //
  24. // To support the stringification of the check operands, this header is
  25. // *significantly* larger than base/check.h, so it should be avoided in common
  26. // headers.
  27. //
  28. // This header also provides the (DP)CHECK macros (by including check.h), so if
  29. // you use e.g. both CHECK_EQ and CHECK, including this header is enough. If you
  30. // only use CHECK however, please include the smaller check.h instead.
  31. namespace logging {
  32. // Functions for turning check operand values into strings.
  33. // Caller takes ownership of the returned string.
  34. BASE_EXPORT char* CheckOpValueStr(int v);
  35. BASE_EXPORT char* CheckOpValueStr(unsigned v);
  36. BASE_EXPORT char* CheckOpValueStr(long v);
  37. BASE_EXPORT char* CheckOpValueStr(unsigned long v);
  38. BASE_EXPORT char* CheckOpValueStr(long long v);
  39. BASE_EXPORT char* CheckOpValueStr(unsigned long long v);
  40. BASE_EXPORT char* CheckOpValueStr(const void* v);
  41. BASE_EXPORT char* CheckOpValueStr(std::nullptr_t v);
  42. BASE_EXPORT char* CheckOpValueStr(double v);
  43. BASE_EXPORT char* CheckOpValueStr(const std::string& v);
  44. // Convert a streamable value to string out-of-line to avoid <sstream>.
  45. BASE_EXPORT char* StreamValToStr(const void* v,
  46. void (*stream_func)(std::ostream&,
  47. const void*));
  48. #ifdef __has_builtin
  49. #define SUPPORTS_BUILTIN_ADDRESSOF (__has_builtin(__builtin_addressof))
  50. #else
  51. #define SUPPORTS_BUILTIN_ADDRESSOF 0
  52. #endif
  53. template <typename T>
  54. inline typename std::enable_if<
  55. base::internal::SupportsOstreamOperator<const T&>::value &&
  56. !std::is_function<typename std::remove_pointer<T>::type>::value,
  57. char*>::type
  58. CheckOpValueStr(const T& v) {
  59. auto f = [](std::ostream& s, const void* p) {
  60. s << *reinterpret_cast<const T*>(p);
  61. };
  62. // operator& might be overloaded, so do the std::addressof dance.
  63. // __builtin_addressof is preferred since it also handles Obj-C ARC pointers.
  64. // Some casting is still needed, because T might be volatile.
  65. #if SUPPORTS_BUILTIN_ADDRESSOF
  66. const void* vp = const_cast<const void*>(
  67. reinterpret_cast<const volatile void*>(__builtin_addressof(v)));
  68. #else
  69. const void* vp = reinterpret_cast<const void*>(
  70. const_cast<const char*>(&reinterpret_cast<const volatile char&>(v)));
  71. #endif
  72. return StreamValToStr(vp, f);
  73. }
  74. #undef SUPPORTS_BUILTIN_ADDRESSOF
  75. // Overload for types that have no operator<< but do have .ToString() defined.
  76. template <typename T>
  77. inline typename std::enable_if<
  78. !base::internal::SupportsOstreamOperator<const T&>::value &&
  79. base::internal::SupportsToString<const T&>::value,
  80. char*>::type
  81. CheckOpValueStr(const T& v) {
  82. // .ToString() may not return a std::string, e.g. blink::WTF::String.
  83. return CheckOpValueStr(v.ToString());
  84. }
  85. // Provide an overload for functions and function pointers. Function pointers
  86. // don't implicitly convert to void* but do implicitly convert to bool, so
  87. // without this function pointers are always printed as 1 or 0. (MSVC isn't
  88. // standards-conforming here and converts function pointers to regular
  89. // pointers, so this is a no-op for MSVC.)
  90. template <typename T>
  91. inline typename std::enable_if<
  92. std::is_function<typename std::remove_pointer<T>::type>::value,
  93. char*>::type
  94. CheckOpValueStr(const T& v) {
  95. return CheckOpValueStr(reinterpret_cast<const void*>(v));
  96. }
  97. // We need overloads for enums that don't support operator<<.
  98. // (i.e. scoped enums where no operator<< overload was declared).
  99. template <typename T>
  100. inline typename std::enable_if<
  101. !base::internal::SupportsOstreamOperator<const T&>::value &&
  102. std::is_enum<T>::value,
  103. char*>::type
  104. CheckOpValueStr(const T& v) {
  105. return CheckOpValueStr(
  106. static_cast<typename std::underlying_type<T>::type>(v));
  107. }
  108. // Captures the result of a CHECK_op and facilitates testing as a boolean.
  109. class CheckOpResult {
  110. public:
  111. // An empty result signals success.
  112. constexpr CheckOpResult() {}
  113. // A non-success result. expr_str is something like "foo != bar". v1_str and
  114. // v2_str are the stringified run-time values of foo and bar. Takes ownership
  115. // of v1_str and v2_str.
  116. BASE_EXPORT CheckOpResult(const char* expr_str, char* v1_str, char* v2_str);
  117. // Returns true if the check succeeded.
  118. constexpr explicit operator bool() const { return !message_; }
  119. friend class CheckError;
  120. private:
  121. char* message_ = nullptr;
  122. };
  123. #if defined(OFFICIAL_BUILD) && defined(NDEBUG) && \
  124. !BUILDFLAG(DCHECK_IS_CONFIGURABLE)
  125. // Discard log strings to reduce code bloat.
  126. #define CHECK_OP(name, op, val1, val2) CHECK((val1)op(val2))
  127. #else
  128. // Helper macro for binary operators.
  129. // The 'switch' is used to prevent the 'else' from being ambiguous when the
  130. // macro is used in an 'if' clause such as:
  131. // if (a == 1)
  132. // CHECK_EQ(2, a);
  133. #define CHECK_OP(name, op, val1, val2) \
  134. switch (0) \
  135. case 0: \
  136. default: \
  137. if (::logging::CheckOpResult true_if_passed = \
  138. ::logging::Check##name##Impl((val1), (val2), \
  139. #val1 " " #op " " #val2)) \
  140. ; \
  141. else \
  142. ::logging::CheckError::CheckOp(__FILE__, __LINE__, &true_if_passed) \
  143. .stream()
  144. #endif
  145. // The second overload avoids address-taking of static members for
  146. // fundamental types.
  147. #define DEFINE_CHECK_OP_IMPL(name, op) \
  148. template <typename T, typename U, \
  149. std::enable_if_t<!std::is_fundamental<T>::value || \
  150. !std::is_fundamental<U>::value, \
  151. int> = 0> \
  152. constexpr ::logging::CheckOpResult Check##name##Impl( \
  153. const T& v1, const U& v2, const char* expr_str) { \
  154. if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
  155. return ::logging::CheckOpResult(); \
  156. return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1), \
  157. CheckOpValueStr(v2)); \
  158. } \
  159. template <typename T, typename U, \
  160. std::enable_if_t<std::is_fundamental<T>::value && \
  161. std::is_fundamental<U>::value, \
  162. int> = 0> \
  163. constexpr ::logging::CheckOpResult Check##name##Impl(T v1, U v2, \
  164. const char* expr_str) { \
  165. if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
  166. return ::logging::CheckOpResult(); \
  167. return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1), \
  168. CheckOpValueStr(v2)); \
  169. }
  170. // clang-format off
  171. DEFINE_CHECK_OP_IMPL(EQ, ==)
  172. DEFINE_CHECK_OP_IMPL(NE, !=)
  173. DEFINE_CHECK_OP_IMPL(LE, <=)
  174. DEFINE_CHECK_OP_IMPL(LT, < )
  175. DEFINE_CHECK_OP_IMPL(GE, >=)
  176. DEFINE_CHECK_OP_IMPL(GT, > )
  177. #undef DEFINE_CHECK_OP_IMPL
  178. #define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
  179. #define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
  180. #define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
  181. #define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
  182. #define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
  183. #define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
  184. // clang-format on
  185. #if DCHECK_IS_ON()
  186. #define DCHECK_OP(name, op, val1, val2) \
  187. switch (0) \
  188. case 0: \
  189. default: \
  190. if (::logging::CheckOpResult true_if_passed = \
  191. ::logging::Check##name##Impl((val1), (val2), \
  192. #val1 " " #op " " #val2)) \
  193. ; \
  194. else \
  195. ::logging::CheckError::DCheckOp(__FILE__, __LINE__, &true_if_passed) \
  196. .stream()
  197. #else
  198. // Don't do any evaluation but still reference the same stuff as when enabled.
  199. #define DCHECK_OP(name, op, val1, val2) \
  200. EAT_CHECK_STREAM_PARAMS((::logging::CheckOpValueStr(val1), \
  201. ::logging::CheckOpValueStr(val2), (val1)op(val2)))
  202. #endif
  203. // clang-format off
  204. #define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
  205. #define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
  206. #define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
  207. #define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
  208. #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
  209. #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
  210. // clang-format on
  211. } // namespace logging
  212. #endif // BASE_CHECK_OP_H_