check.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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_H_
  5. #define BASE_CHECK_H_
  6. #include <iosfwd>
  7. #include "base/base_export.h"
  8. #include "base/compiler_specific.h"
  9. #include "base/dcheck_is_on.h"
  10. #include "base/debug/debugging_buildflags.h"
  11. #include "base/immediate_crash.h"
  12. // This header defines the CHECK, DCHECK, and DPCHECK macros.
  13. //
  14. // CHECK dies with a fatal error if its condition is not true. It is not
  15. // controlled by NDEBUG, so the check will be executed regardless of compilation
  16. // mode.
  17. //
  18. // DCHECK, the "debug mode" check, is enabled depending on NDEBUG and
  19. // DCHECK_ALWAYS_ON, and its severity depends on DCHECK_IS_CONFIGURABLE.
  20. //
  21. // (D)PCHECK is like (D)CHECK, but includes the system error code (c.f.
  22. // perror(3)).
  23. //
  24. // Additional information can be streamed to these macros and will be included
  25. // in the log output if the condition doesn't hold (you may need to include
  26. // <ostream>):
  27. //
  28. // CHECK(condition) << "Additional info.";
  29. //
  30. // The condition is evaluated exactly once. Even in build modes where e.g.
  31. // DCHECK is disabled, the condition and any stream arguments are still
  32. // referenced to avoid warnings about unused variables and functions.
  33. //
  34. // For the (D)CHECK_EQ, etc. macros, see base/check_op.h. However, that header
  35. // is *significantly* larger than check.h, so try to avoid including it in
  36. // header files.
  37. namespace logging {
  38. // Class used to explicitly ignore an ostream, and optionally a boolean value.
  39. class VoidifyStream {
  40. public:
  41. VoidifyStream() = default;
  42. explicit VoidifyStream(bool ignored) {}
  43. // This operator has lower precedence than << but higher than ?:
  44. void operator&(std::ostream&) {}
  45. };
  46. // Helper macro which avoids evaluating the arguents to a stream if the
  47. // condition is false.
  48. #define LAZY_CHECK_STREAM(stream, condition) \
  49. !(condition) ? (void)0 : ::logging::VoidifyStream() & (stream)
  50. // Macro which uses but does not evaluate expr and any stream parameters.
  51. #define EAT_CHECK_STREAM_PARAMS(expr) \
  52. true ? (void)0 \
  53. : ::logging::VoidifyStream(expr) & (*::logging::g_swallow_stream)
  54. BASE_EXPORT extern std::ostream* g_swallow_stream;
  55. class CheckOpResult;
  56. class LogMessage;
  57. // Class used for raising a check error upon destruction.
  58. class BASE_EXPORT CheckError {
  59. public:
  60. static CheckError Check(const char* file, int line, const char* condition);
  61. static CheckError CheckOp(const char* file, int line, CheckOpResult* result);
  62. static CheckError DCheck(const char* file, int line, const char* condition);
  63. static CheckError DCheckOp(const char* file, int line, CheckOpResult* result);
  64. static CheckError PCheck(const char* file, int line, const char* condition);
  65. static CheckError PCheck(const char* file, int line);
  66. static CheckError DPCheck(const char* file, int line, const char* condition);
  67. static CheckError NotImplemented(const char* file,
  68. int line,
  69. const char* function);
  70. static CheckError NotReached(const char* file, int line);
  71. // Stream for adding optional details to the error message.
  72. std::ostream& stream();
  73. NOMERGE ~CheckError();
  74. CheckError(const CheckError&) = delete;
  75. CheckError& operator=(const CheckError&) = delete;
  76. private:
  77. explicit CheckError(LogMessage* log_message);
  78. LogMessage* const log_message_;
  79. };
  80. #if defined(OFFICIAL_BUILD) && defined(NDEBUG) && \
  81. !BUILDFLAG(DCHECK_IS_CONFIGURABLE)
  82. // Discard log strings to reduce code bloat.
  83. //
  84. // This is not calling BreakDebugger since this is called frequently, and
  85. // calling an out-of-line function instead of a noreturn inline macro prevents
  86. // compiler optimizations.
  87. #define CHECK(condition) \
  88. UNLIKELY(!(condition)) ? IMMEDIATE_CRASH() : EAT_CHECK_STREAM_PARAMS()
  89. #define CHECK_WILL_STREAM() false
  90. #define PCHECK(condition) \
  91. LAZY_CHECK_STREAM( \
  92. ::logging::CheckError::PCheck(__FILE__, __LINE__).stream(), \
  93. UNLIKELY(!(condition)))
  94. #else
  95. #define CHECK(condition) \
  96. LAZY_CHECK_STREAM( \
  97. ::logging::CheckError::Check(__FILE__, __LINE__, #condition).stream(), \
  98. !ANALYZER_ASSUME_TRUE(condition))
  99. #define CHECK_WILL_STREAM() true
  100. #define PCHECK(condition) \
  101. LAZY_CHECK_STREAM( \
  102. ::logging::CheckError::PCheck(__FILE__, __LINE__, #condition).stream(), \
  103. !ANALYZER_ASSUME_TRUE(condition))
  104. #endif
  105. #if DCHECK_IS_ON()
  106. #define DCHECK(condition) \
  107. LAZY_CHECK_STREAM( \
  108. ::logging::CheckError::DCheck(__FILE__, __LINE__, #condition).stream(), \
  109. !ANALYZER_ASSUME_TRUE(condition))
  110. #define DPCHECK(condition) \
  111. LAZY_CHECK_STREAM( \
  112. ::logging::CheckError::DPCheck(__FILE__, __LINE__, #condition).stream(), \
  113. !ANALYZER_ASSUME_TRUE(condition))
  114. #else
  115. #define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
  116. #define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
  117. #endif
  118. // Async signal safe checking mechanism.
  119. BASE_EXPORT void RawCheck(const char* message);
  120. BASE_EXPORT void RawError(const char* message);
  121. #define RAW_CHECK(condition) \
  122. do { \
  123. if (!(condition)) \
  124. ::logging::RawCheck("Check failed: " #condition "\n"); \
  125. } while (0)
  126. } // namespace logging
  127. #endif // BASE_CHECK_H_