Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 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> |
mikt | 2db0a94 | 2024-02-27 05:19:54 | [diff] [blame] | 9 | #include <memory> |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 10 | |
| 11 | #include "base/base_export.h" |
| 12 | #include "base/compiler_specific.h" |
Hans Wennborg | 944479f | 2020-06-25 21:39:25 | [diff] [blame] | 13 | #include "base/dcheck_is_on.h" |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 14 | #include "base/immediate_crash.h" |
Peter Boström | d4ec69f2 | 2023-04-04 17:46:55 | [diff] [blame] | 15 | #include "base/location.h" |
Peter Boström | 2505209 | 2023-12-09 00:27:24 | [diff] [blame] | 16 | #include "base/macros/if.h" |
| 17 | #include "base/macros/is_empty.h" |
| 18 | #include "base/not_fatal_until.h" |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 19 | |
| 20 | // This header defines the CHECK, DCHECK, and DPCHECK macros. |
| 21 | // |
| 22 | // CHECK dies with a fatal error if its condition is not true. It is not |
| 23 | // controlled by NDEBUG, so the check will be executed regardless of compilation |
| 24 | // mode. |
| 25 | // |
| 26 | // DCHECK, the "debug mode" check, is enabled depending on NDEBUG and |
| 27 | // DCHECK_ALWAYS_ON, and its severity depends on DCHECK_IS_CONFIGURABLE. |
| 28 | // |
| 29 | // (D)PCHECK is like (D)CHECK, but includes the system error code (c.f. |
| 30 | // perror(3)). |
| 31 | // |
| 32 | // Additional information can be streamed to these macros and will be included |
| 33 | // in the log output if the condition doesn't hold (you may need to include |
| 34 | // <ostream>): |
| 35 | // |
| 36 | // CHECK(condition) << "Additional info."; |
| 37 | // |
| 38 | // The condition is evaluated exactly once. Even in build modes where e.g. |
| 39 | // DCHECK is disabled, the condition and any stream arguments are still |
| 40 | // referenced to avoid warnings about unused variables and functions. |
| 41 | // |
Peter Boström | 2505209 | 2023-12-09 00:27:24 | [diff] [blame] | 42 | // An optional base::NotFatalUntil argument can be provided to make the |
| 43 | // instance non-fatal (dumps without crashing) before a provided milestone. That |
| 44 | // is: CHECK(false, base::NotFatalUntil::M120); starts crashing in M120. CHECKs |
| 45 | // with a milestone argument preserve logging even in official builds, and |
| 46 | // will upload the CHECK's log message in crash reports for remote diagnostics. |
| 47 | // This is recommended for use in situations that are not flag guarded, or where |
| 48 | // we have low pre-stable coverage. Using this lets us probe for would-be CHECK |
| 49 | // failures for a milestone or two before rolling out a CHECK. |
| 50 | // |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 51 | // For the (D)CHECK_EQ, etc. macros, see base/check_op.h. However, that header |
| 52 | // is *significantly* larger than check.h, so try to avoid including it in |
| 53 | // header files. |
| 54 | |
| 55 | namespace logging { |
| 56 | |
Peter Boström | c9dda649 | 2022-11-03 22:27:26 | [diff] [blame] | 57 | // Class used to explicitly ignore an ostream, and optionally a boolean value. |
| 58 | class VoidifyStream { |
| 59 | public: |
| 60 | VoidifyStream() = default; |
Brett Brotherton | f161a06a | 2022-11-11 18:20:24 | [diff] [blame] | 61 | explicit VoidifyStream(bool) {} |
Peter Boström | c9dda649 | 2022-11-03 22:27:26 | [diff] [blame] | 62 | |
Adam Rice | ce0a8f95 | 2023-11-17 00:32:00 | [diff] [blame] | 63 | // Binary & has lower precedence than << but higher than ?: |
Peter Boström | c9dda649 | 2022-11-03 22:27:26 | [diff] [blame] | 64 | void operator&(std::ostream&) {} |
| 65 | }; |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 66 | |
| 67 | // Macro which uses but does not evaluate expr and any stream parameters. |
| 68 | #define EAT_CHECK_STREAM_PARAMS(expr) \ |
| 69 | true ? (void)0 \ |
| 70 | : ::logging::VoidifyStream(expr) & (*::logging::g_swallow_stream) |
| 71 | BASE_EXPORT extern std::ostream* g_swallow_stream; |
| 72 | |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 73 | class LogMessage; |
| 74 | |
| 75 | // Class used for raising a check error upon destruction. |
| 76 | class BASE_EXPORT CheckError { |
| 77 | public: |
Peter Boström | ce41a1e98 | 2025-03-12 04:36:46 | [diff] [blame] | 78 | // Takes ownership of `log_message`. |
| 79 | explicit CheckError(LogMessage* log_message); |
| 80 | |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 81 | // All instances that take a base::Location should use |
| 82 | // base::Location::CurrentWithoutFunctionName() by default since we |
| 83 | // immediately pass file_name() and line_number() to LogMessage's constructor |
| 84 | // and discard the function_name() anyways. This saves ~23k on the Android |
| 85 | // size bots (as of 2024-12-17) but that's the official build that barely uses |
| 86 | // these for CHECKs. The size gains are believed to be significantly larger on |
| 87 | // developer builds and official+DCHECK where all CHECK failures generate |
| 88 | // logs. |
| 89 | |
Peter Boström | ce41a1e98 | 2025-03-12 04:36:46 | [diff] [blame] | 90 | // TODO(pbos): Make all static methods that currently return some version of |
| 91 | // CheckError return LogMessage*. |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 92 | static CheckError Check(const char* condition, |
| 93 | base::NotFatalUntil fatal_milestone, |
| 94 | const base::Location& location = |
| 95 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | e7a8bbd | 2023-05-12 06:59:17 | [diff] [blame] | 96 | // Takes ownership over (free()s after using) `log_message_str`, for use with |
| 97 | // CHECK_op macros. |
Peter Boström | ce41a1e98 | 2025-03-12 04:36:46 | [diff] [blame] | 98 | static LogMessage* CheckOp(char* log_message_str, |
| 99 | base::NotFatalUntil fatal_milestone, |
| 100 | const base::Location& location = |
| 101 | base::Location::CurrentWithoutFunctionName()); |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 102 | |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 103 | static CheckError DCheck(const char* condition, |
| 104 | const base::Location& location = |
| 105 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | e7a8bbd | 2023-05-12 06:59:17 | [diff] [blame] | 106 | // Takes ownership over (free()s after using) `log_message_str`, for use with |
| 107 | // DCHECK_op macros. |
Peter Boström | ce41a1e98 | 2025-03-12 04:36:46 | [diff] [blame] | 108 | static LogMessage* DCheckOp(char* log_message_str, |
| 109 | const base::Location& location = |
| 110 | base::Location::CurrentWithoutFunctionName()); |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 111 | |
Peter Boström | bc4629d | 2023-05-09 03:21:38 | [diff] [blame] | 112 | static CheckError DumpWillBeCheck( |
| 113 | const char* condition, |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 114 | const base::Location& location = |
| 115 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | bf47582 | 2023-05-17 17:17:50 | [diff] [blame] | 116 | // Takes ownership over (free()s after using) `log_message_str`, for use with |
| 117 | // DUMP_WILL_BE_CHECK_op macros. |
Peter Boström | ce41a1e98 | 2025-03-12 04:36:46 | [diff] [blame] | 118 | static LogMessage* DumpWillBeCheckOp( |
Peter Boström | bf47582 | 2023-05-17 17:17:50 | [diff] [blame] | 119 | char* log_message_str, |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 120 | const base::Location& location = |
| 121 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | bc4629d | 2023-05-09 03:21:38 | [diff] [blame] | 122 | |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 123 | static CheckError DPCheck(const char* condition, |
| 124 | const base::Location& location = |
| 125 | base::Location::CurrentWithoutFunctionName()); |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 126 | |
Peter Boström | 7c561ce3 | 2023-05-11 22:18:01 | [diff] [blame] | 127 | static CheckError NotImplemented( |
| 128 | const char* function, |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 129 | const base::Location& location = |
| 130 | base::Location::CurrentWithoutFunctionName()); |
Hans Wennborg | 0472f8c | 2020-04-23 19:27:27 | [diff] [blame] | 131 | |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 132 | // Stream for adding optional details to the error message. |
| 133 | std::ostream& stream(); |
| 134 | |
Peter Boström | a1021e1 | 2023-01-19 04:02:40 | [diff] [blame] | 135 | // Try really hard to get the call site and callee as separate stack frames in |
| 136 | // crash reports. |
| 137 | NOMERGE NOINLINE NOT_TAIL_CALLED ~CheckError(); |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 138 | |
Peter Boström | 67c8f16d | 2022-06-23 21:58:29 | [diff] [blame] | 139 | CheckError(const CheckError&) = delete; |
| 140 | CheckError& operator=(const CheckError&) = delete; |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 141 | |
Peter Boström | 2b2875bb | 2022-10-28 23:50:15 | [diff] [blame] | 142 | template <typename T> |
Peter Boström | abe9494 | 2025-03-10 21:51:10 | [diff] [blame] | 143 | CheckError& operator<<(T&& streamed_type) { |
| 144 | stream() << streamed_type; |
| 145 | return *this; |
Peter Boström | 2b2875bb | 2022-10-28 23:50:15 | [diff] [blame] | 146 | } |
| 147 | |
Peter Boström | 92cdf19b | 2023-02-06 18:52:29 | [diff] [blame] | 148 | protected: |
mikt | 2db0a94 | 2024-02-27 05:19:54 | [diff] [blame] | 149 | std::unique_ptr<LogMessage> log_message_; |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 150 | }; |
| 151 | |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 152 | // Used for NOTREACHED(), its destructor is importantly [[noreturn]]. |
| 153 | class BASE_EXPORT CheckNoreturnError : public CheckError { |
| 154 | public: |
| 155 | [[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~CheckNoreturnError(); |
| 156 | |
| 157 | static CheckNoreturnError Check( |
| 158 | const char* condition, |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 159 | const base::Location& location = |
| 160 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 161 | // Takes ownership over (free()s after using) `log_message_str`, for use with |
| 162 | // CHECK_op macros. |
Peter Boström | ce41a1e98 | 2025-03-12 04:36:46 | [diff] [blame] | 163 | static LogMessage* CheckOp(char* log_message_str, |
| 164 | const base::Location& location = |
| 165 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 166 | |
| 167 | static CheckNoreturnError PCheck( |
| 168 | const char* condition, |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 169 | const base::Location& location = |
| 170 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 171 | static CheckNoreturnError PCheck( |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 172 | const base::Location& location = |
| 173 | base::Location::CurrentWithoutFunctionName()); |
Taiyo Mizuhashi | ba9a0c4 | 2024-12-18 18:39:35 | [diff] [blame] | 174 | |
| 175 | private: |
| 176 | using CheckError::CheckError; |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 177 | }; |
| 178 | |
| 179 | // Used for NOTREACHED(base::NotFatalUntil) and DUMP_WILL_BE_NOTREACHED(). |
Peter Boström | d7df624 | 2022-12-13 18:05:40 | [diff] [blame] | 180 | class BASE_EXPORT NotReachedError : public CheckError { |
| 181 | public: |
Peter Boström | d4ec69f2 | 2023-04-04 17:46:55 | [diff] [blame] | 182 | static NotReachedError NotReached( |
Peter Boström | e238462 | 2024-11-15 00:46:51 | [diff] [blame] | 183 | base::NotFatalUntil fatal_milestone, |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 184 | const base::Location& location = |
| 185 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | d7df624 | 2022-12-13 18:05:40 | [diff] [blame] | 186 | |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 187 | static NotReachedError DumpWillBeNotReached( |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 188 | const base::Location& location = |
| 189 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 190 | |
Peter Boström | a1021e1 | 2023-01-19 04:02:40 | [diff] [blame] | 191 | NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedError(); |
Peter Boström | d7df624 | 2022-12-13 18:05:40 | [diff] [blame] | 192 | |
| 193 | private: |
| 194 | using CheckError::CheckError; |
| 195 | }; |
| 196 | |
Peter Boström | e238462 | 2024-11-15 00:46:51 | [diff] [blame] | 197 | // Used for NOTREACHED(), its destructor is importantly [[noreturn]]. |
Peter Boström | 92cdf19b | 2023-02-06 18:52:29 | [diff] [blame] | 198 | class BASE_EXPORT NotReachedNoreturnError : public CheckError { |
| 199 | public: |
Peter Boström | 7c561ce3 | 2023-05-11 22:18:01 | [diff] [blame] | 200 | explicit NotReachedNoreturnError( |
Peter Boström | 5f34e2f | 2024-12-19 01:07:54 | [diff] [blame] | 201 | const base::Location& location = |
| 202 | base::Location::CurrentWithoutFunctionName()); |
Peter Boström | 92cdf19b | 2023-02-06 18:52:29 | [diff] [blame] | 203 | |
| 204 | [[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedNoreturnError(); |
| 205 | }; |
| 206 | |
Daniel Cheng | 27f4a25f | 2023-06-07 00:20:51 | [diff] [blame] | 207 | // A helper macro for checks that log to streams that makes it easier for the |
| 208 | // compiler to identify and warn about dead code, e.g.: |
| 209 | // |
| 210 | // return 2; |
Peter Boström | 8c29f4a | 2024-05-08 01:12:11 | [diff] [blame] | 211 | // NOTREACHED_IN_MIGRATION(); |
Daniel Cheng | 27f4a25f | 2023-06-07 00:20:51 | [diff] [blame] | 212 | // |
Peter Boström | c9dda649 | 2022-11-03 22:27:26 | [diff] [blame] | 213 | // The 'switch' is used to prevent the 'else' from being ambiguous when the |
| 214 | // macro is used in an 'if' clause such as: |
| 215 | // if (a == 1) |
| 216 | // CHECK(Foo()); |
| 217 | // |
Peter Boström | f9d97ed9 | 2024-11-26 19:12:30 | [diff] [blame] | 218 | // The weird ternary is to still generate an "is not contextually convertible to |
| 219 | // 'bool' when provided weird parameters (regardless of ANALYZER_ASSUME_TRUE's |
| 220 | // implementation). See base/check_nocompile.nc. |
Peter Boström | 7a747d8 | 2025-02-25 03:38:23 | [diff] [blame] | 221 | // |
| 222 | // The lambda is here to here permit the compiler to out-of-line much of the |
| 223 | // CHECK-failure path and optimize better for the fast path. |
Peter Boström | f9d97ed9 | 2024-11-26 19:12:30 | [diff] [blame] | 224 | #define LOGGING_CHECK_FUNCTION_IMPL(check_stream, condition) \ |
| 225 | switch (0) \ |
| 226 | case 0: \ |
| 227 | default: \ |
| 228 | if (ANALYZER_ASSUME_TRUE((condition) ? true : false)) \ |
| 229 | [[likely]]; \ |
| 230 | else \ |
Peter Boström | 7a747d8 | 2025-02-25 03:38:23 | [diff] [blame] | 231 | [&]() { return (check_stream); }() |
Peter Boström | 2f8318f | 2022-10-12 03:28:29 | [diff] [blame] | 232 | |
Peter Boström | f9d97ed9 | 2024-11-26 19:12:30 | [diff] [blame] | 233 | // A helper macro like LOGGING_CHECK_FUNCTION_IMPL above but discarding any |
| 234 | // log-stream parameters rather than evaluate them on failure. |
| 235 | #define DISCARDING_CHECK_FUNCTION_IMPL(check_failure, condition) \ |
| 236 | switch (0) \ |
| 237 | case 0: \ |
| 238 | default: \ |
| 239 | if (!ANALYZER_ASSUME_TRUE((condition) ? true : false)) \ |
| 240 | check_failure; \ |
| 241 | else [[likely]] \ |
| 242 | EAT_CHECK_STREAM_PARAMS() |
| 243 | |
Peter Boström | d0a383c | 2022-10-29 04:09:12 | [diff] [blame] | 244 | #if defined(OFFICIAL_BUILD) && !defined(NDEBUG) |
| 245 | #error "Debug builds are not expected to be optimized as official builds." |
| 246 | #endif // defined(OFFICIAL_BUILD) && !defined(NDEBUG) |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 247 | |
Peter Boström | d0a383c | 2022-10-29 04:09:12 | [diff] [blame] | 248 | #if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON() |
Peter Boström | b010f7b | 2024-11-12 02:57:16 | [diff] [blame] | 249 | |
| 250 | // Official non-DCHECK builds do not preserve CHECK() logging (including |
| 251 | // evaluation of logging arguments). This generates more compact code which is |
| 252 | // good for both speed and binary size. |
| 253 | #define CHECK_WILL_STREAM() false |
| 254 | |
Peter Boström | b30544d | 2022-10-21 00:17:58 | [diff] [blame] | 255 | // Note that this uses IMMEDIATE_CRASH_ALWAYS_INLINE to force-inline in debug |
| 256 | // mode as well. See LoggingTest.CheckCausesDistinctBreakpoints. |
Peter Boström | 7c638300 | 2024-09-10 11:15:35 | [diff] [blame] | 257 | [[noreturn]] NOMERGE IMMEDIATE_CRASH_ALWAYS_INLINE void CheckFailure() { |
Peter Boström | 25c6ec7 | 2022-11-02 23:25:19 | [diff] [blame] | 258 | base::ImmediateCrash(); |
Peter Boström | b30544d | 2022-10-21 00:17:58 | [diff] [blame] | 259 | } |
| 260 | |
Peter Boström | 2505209 | 2023-12-09 00:27:24 | [diff] [blame] | 261 | // Discard log strings to reduce code bloat when there is no NotFatalUntil |
| 262 | // argument (which temporarily preserves logging both locally and in crash |
| 263 | // reports). |
Peter Boström | d20dbbd | 2024-11-27 01:29:57 | [diff] [blame] | 264 | #define CHECK_INTERNAL_IMPL(cond) \ |
| 265 | DISCARDING_CHECK_FUNCTION_IMPL(::logging::CheckFailure(), cond) |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 266 | |
| 267 | #else |
| 268 | |
Peter Boström | b010f7b | 2024-11-12 02:57:16 | [diff] [blame] | 269 | // Generate logging versions of CHECKs to help diagnosing failures. |
Gabriel Charette | fe05104 | 2022-01-19 09:27:29 | [diff] [blame] | 270 | #define CHECK_WILL_STREAM() true |
| 271 | |
Peter Boström | d20dbbd | 2024-11-27 01:29:57 | [diff] [blame] | 272 | #define CHECK_INTERNAL_IMPL(cond) \ |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 273 | LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckNoreturnError::Check(#cond), cond) |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 274 | |
| 275 | #endif |
| 276 | |
Peter Boström | d20dbbd | 2024-11-27 01:29:57 | [diff] [blame] | 277 | #define CHECK(cond, ...) \ |
| 278 | BASE_IF(BASE_IS_EMPTY(__VA_ARGS__), CHECK_INTERNAL_IMPL(cond), \ |
| 279 | LOGGING_CHECK_FUNCTION_IMPL( \ |
| 280 | logging::CheckError::Check(#cond, __VA_ARGS__), cond)) |
| 281 | |
| 282 | // Strip the conditional string based on CHECK_WILL_STREAM() |
Peter Boström | 7b1ecd86 | 2024-11-28 02:50:40 | [diff] [blame] | 283 | #define PCHECK(cond) \ |
| 284 | LOGGING_CHECK_FUNCTION_IMPL( \ |
| 285 | BASE_IF(CHECK_WILL_STREAM(), \ |
| 286 | ::logging::CheckNoreturnError::PCheck(#cond), \ |
| 287 | ::logging::CheckNoreturnError::PCheck()), \ |
Peter Boström | d20dbbd | 2024-11-27 01:29:57 | [diff] [blame] | 288 | cond) |
| 289 | |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 290 | #if DCHECK_IS_ON() |
| 291 | |
Daniel Cheng | 27f4a25f | 2023-06-07 00:20:51 | [diff] [blame] | 292 | #define DCHECK(condition) \ |
| 293 | LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DCheck(#condition), \ |
| 294 | condition) |
| 295 | #define DPCHECK(condition) \ |
| 296 | LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DPCheck(#condition), \ |
| 297 | condition) |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 298 | |
| 299 | #else |
| 300 | |
| 301 | #define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition)) |
| 302 | #define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition)) |
| 303 | |
Peter Boström | bc4629d | 2023-05-09 03:21:38 | [diff] [blame] | 304 | #endif // DCHECK_IS_ON() |
| 305 | |
| 306 | // The DUMP_WILL_BE_CHECK() macro provides a convenient way to non-fatally dump |
| 307 | // in official builds if a condition is false. This is used to more cautiously |
| 308 | // roll out a new CHECK() (or upgrade a DCHECK) where the caller isn't entirely |
| 309 | // sure that something holds true in practice (but asserts that it should). This |
| 310 | // is especially useful for platforms that have a low pre-stable population and |
| 311 | // code areas that are rarely exercised. |
| 312 | // |
| 313 | // On DCHECK builds this macro matches DCHECK behavior. |
| 314 | // |
| 315 | // This macro isn't optimized (preserves filename, line number and log messages |
| 316 | // in official builds), as they are expected to be in product temporarily. When |
| 317 | // using this macro, leave a TODO(crbug.com/nnnn) entry referring to a bug |
| 318 | // related to its rollout. Then put a NextAction on the bug to come back and |
| 319 | // clean this up (replace with a CHECK). A DUMP_WILL_BE_CHECK() that's been left |
| 320 | // untouched for a long time without bug updates suggests that issues that |
| 321 | // would've prevented enabling this CHECK have either not been discovered or |
| 322 | // have been resolved. |
| 323 | // |
| 324 | // Using this macro is preferred over direct base::debug::DumpWithoutCrashing() |
| 325 | // invocations as it communicates intent to eventually end up as a CHECK. It |
| 326 | // also preserves the log message so setting crash keys to get additional debug |
| 327 | // info isn't required as often. |
Peter Boström | 2505209 | 2023-12-09 00:27:24 | [diff] [blame] | 328 | #define DUMP_WILL_BE_CHECK(condition, ...) \ |
| 329 | LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DumpWillBeCheck( \ |
| 330 | #condition __VA_OPT__(, ) __VA_ARGS__), \ |
| 331 | condition) |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 332 | |
| 333 | // Async signal safe checking mechanism. |
Peter Boström | efa8c00 | 2023-04-28 02:33:53 | [diff] [blame] | 334 | [[noreturn]] BASE_EXPORT void RawCheckFailure(const char* message); |
| 335 | #define RAW_CHECK(condition) \ |
| 336 | do { \ |
Peter Kasting | fa48899 | 2024-08-06 07:48:14 | [diff] [blame] | 337 | if (!(condition)) [[unlikely]] { \ |
Peter Boström | efa8c00 | 2023-04-28 02:33:53 | [diff] [blame] | 338 | ::logging::RawCheckFailure("Check failed: " #condition "\n"); \ |
| 339 | } \ |
Hans Wennborg | 12aea3e | 2020-04-14 15:29:00 | [diff] [blame] | 340 | } while (0) |
| 341 | |
| 342 | } // namespace logging |
| 343 | |
| 344 | #endif // BASE_CHECK_H_ |