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