blob: 3e91c0ca834f410202481b13c9770e05b33d5163 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2020 The Chromium Authors
Hans Wennborg12aea3e2020-04-14 15:29:002// 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"
Hans Wennborg944479f2020-06-25 21:39:2512#include "base/dcheck_is_on.h"
Hans Wennborg12aea3e2020-04-14 15:29:0013#include "base/immediate_crash.h"
Peter Boströmd4ec69f22023-04-04 17:46:5514#include "base/location.h"
Hans Wennborg12aea3e2020-04-14 15:29:0015
16// This header defines the CHECK, DCHECK, and DPCHECK macros.
17//
18// CHECK dies with a fatal error if its condition is not true. It is not
19// controlled by NDEBUG, so the check will be executed regardless of compilation
20// mode.
21//
22// DCHECK, the "debug mode" check, is enabled depending on NDEBUG and
23// DCHECK_ALWAYS_ON, and its severity depends on DCHECK_IS_CONFIGURABLE.
24//
25// (D)PCHECK is like (D)CHECK, but includes the system error code (c.f.
26// perror(3)).
27//
28// Additional information can be streamed to these macros and will be included
29// in the log output if the condition doesn't hold (you may need to include
30// <ostream>):
31//
32// CHECK(condition) << "Additional info.";
33//
34// The condition is evaluated exactly once. Even in build modes where e.g.
35// DCHECK is disabled, the condition and any stream arguments are still
36// referenced to avoid warnings about unused variables and functions.
37//
38// For the (D)CHECK_EQ, etc. macros, see base/check_op.h. However, that header
39// is *significantly* larger than check.h, so try to avoid including it in
40// header files.
41
42namespace logging {
43
Peter Boströmc9dda6492022-11-03 22:27:2644// Class used to explicitly ignore an ostream, and optionally a boolean value.
45class VoidifyStream {
46 public:
47 VoidifyStream() = default;
Brett Brothertonf161a06a2022-11-11 18:20:2448 explicit VoidifyStream(bool) {}
Peter Boströmc9dda6492022-11-03 22:27:2649
50 // This operator has lower precedence than << but higher than ?:
51 void operator&(std::ostream&) {}
52};
Hans Wennborg12aea3e2020-04-14 15:29:0053
54// Macro which uses but does not evaluate expr and any stream parameters.
55#define EAT_CHECK_STREAM_PARAMS(expr) \
56 true ? (void)0 \
57 : ::logging::VoidifyStream(expr) & (*::logging::g_swallow_stream)
58BASE_EXPORT extern std::ostream* g_swallow_stream;
59
Hans Wennborg12aea3e2020-04-14 15:29:0060class LogMessage;
61
62// Class used for raising a check error upon destruction.
63class BASE_EXPORT CheckError {
64 public:
Peter Boström7c561ce32023-05-11 22:18:0165 static CheckError Check(
66 const char* condition,
67 const base::Location& location = base::Location::Current());
Peter Boströme7a8bbd2023-05-12 06:59:1768 // Takes ownership over (free()s after using) `log_message_str`, for use with
69 // CHECK_op macros.
70 static CheckError CheckOp(
71 char* log_message_str,
72 const base::Location& location = base::Location::Current());
Hans Wennborg12aea3e2020-04-14 15:29:0073
Peter Boströmd4ec69f22023-04-04 17:46:5574 static CheckError DCheck(
75 const char* condition,
76 const base::Location& location = base::Location::Current());
Peter Boströme7a8bbd2023-05-12 06:59:1777 // Takes ownership over (free()s after using) `log_message_str`, for use with
78 // DCHECK_op macros.
79 static CheckError DCheckOp(
80 char* log_message_str,
81 const base::Location& location = base::Location::Current());
Hans Wennborg12aea3e2020-04-14 15:29:0082
Peter Boströmbc4629d2023-05-09 03:21:3883 static CheckError DumpWillBeCheck(
84 const char* condition,
85 const base::Location& location = base::Location::Current());
Peter Boströmbf475822023-05-17 17:17:5086 // Takes ownership over (free()s after using) `log_message_str`, for use with
87 // DUMP_WILL_BE_CHECK_op macros.
88 static CheckError DumpWillBeCheckOp(
89 char* log_message_str,
90 const base::Location& location = base::Location::Current());
Peter Boströmbc4629d2023-05-09 03:21:3891
Peter Boström7c561ce32023-05-11 22:18:0192 static CheckError PCheck(
93 const char* condition,
94 const base::Location& location = base::Location::Current());
95 static CheckError PCheck(
96 const base::Location& location = base::Location::Current());
Hans Wennborg12aea3e2020-04-14 15:29:0097
Peter Boströmd4ec69f22023-04-04 17:46:5598 static CheckError DPCheck(
99 const char* condition,
100 const base::Location& location = base::Location::Current());
Hans Wennborg12aea3e2020-04-14 15:29:00101
Peter Boströmbf475822023-05-17 17:17:50102 static CheckError DumpWillBeNotReachedNoreturn(
103 const base::Location& location = base::Location::Current());
104
Peter Boström7c561ce32023-05-11 22:18:01105 static CheckError NotImplemented(
106 const char* function,
107 const base::Location& location = base::Location::Current());
Hans Wennborg0472f8c2020-04-23 19:27:27108
Hans Wennborg12aea3e2020-04-14 15:29:00109 // Stream for adding optional details to the error message.
110 std::ostream& stream();
111
Peter Boströma1021e12023-01-19 04:02:40112 // Try really hard to get the call site and callee as separate stack frames in
113 // crash reports.
114 NOMERGE NOINLINE NOT_TAIL_CALLED ~CheckError();
Hans Wennborg12aea3e2020-04-14 15:29:00115
Peter Boström67c8f16d2022-06-23 21:58:29116 CheckError(const CheckError&) = delete;
117 CheckError& operator=(const CheckError&) = delete;
Hans Wennborg12aea3e2020-04-14 15:29:00118
Peter Boström2b2875bb2022-10-28 23:50:15119 template <typename T>
120 std::ostream& operator<<(T&& streamed_type) {
121 return stream() << streamed_type;
122 }
123
Peter Boström92cdf19b2023-02-06 18:52:29124 protected:
Peter Boströme7a8bbd2023-05-12 06:59:17125 // Takes ownership of `log_message`.
126 explicit CheckError(LogMessage* log_message) : log_message_(log_message) {}
127
Peter Boström67c8f16d2022-06-23 21:58:29128 LogMessage* const log_message_;
Hans Wennborg12aea3e2020-04-14 15:29:00129};
130
Peter Boströmd7df6242022-12-13 18:05:40131class BASE_EXPORT NotReachedError : public CheckError {
132 public:
Peter Boströmd4ec69f22023-04-04 17:46:55133 static NotReachedError NotReached(
134 const base::Location& location = base::Location::Current());
Peter Boströmd7df6242022-12-13 18:05:40135
Peter Boström6da0aba2023-01-30 20:13:31136 // Used to trigger a NOTREACHED() without providing file or line while also
137 // discarding log-stream arguments. See base/notreached.h.
138 NOMERGE NOINLINE NOT_TAIL_CALLED static void TriggerNotReached();
139
Peter Boströmd7df6242022-12-13 18:05:40140 // TODO(crbug.com/851128): Mark [[noreturn]] once this is CHECK-fatal on all
141 // builds.
Peter Boströma1021e12023-01-19 04:02:40142 NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedError();
Peter Boströmd7df6242022-12-13 18:05:40143
144 private:
145 using CheckError::CheckError;
146};
147
Peter Boström92cdf19b2023-02-06 18:52:29148// TODO(crbug.com/851128): This should take the name of the above class once all
149// callers of NOTREACHED() have migrated to the CHECK-fatal version.
150class BASE_EXPORT NotReachedNoreturnError : public CheckError {
151 public:
Peter Boström7c561ce32023-05-11 22:18:01152 explicit NotReachedNoreturnError(
153 const base::Location& location = base::Location::Current());
Peter Boström92cdf19b2023-02-06 18:52:29154
155 [[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedNoreturnError();
156};
157
Daniel Cheng27f4a25f2023-06-07 00:20:51158// A helper macro for checks that log to streams that makes it easier for the
159// compiler to identify and warn about dead code, e.g.:
160//
161// return 2;
162// NOTREACHED();
163//
Peter Boströmc9dda6492022-11-03 22:27:26164// The 'switch' is used to prevent the 'else' from being ambiguous when the
165// macro is used in an 'if' clause such as:
166// if (a == 1)
167// CHECK(Foo());
168//
169// TODO(crbug.com/1380930): Remove the const bool when the blink-gc plugin has
170// been updated to accept `if (LIKELY(!field_))` as well as `if (!field_)`.
Daniel Cheng27f4a25f2023-06-07 00:20:51171#define LOGGING_CHECK_FUNCTION_IMPL(check_stream, condition) \
172 switch (0) \
173 case 0: \
174 default: \
175 /* Hint to the optimizer that `condition` is unlikely to be false. */ \
176 /* The optimizer can use this as a hint to place the failure path */ \
177 /* out-of-line, e.g. at the tail of the function. */ \
178 if (const bool probably_true = static_cast<bool>(condition); \
179 LIKELY(ANALYZER_ASSUME_TRUE(probably_true))) \
180 ; \
181 else \
182 (check_stream)
Peter Boström2f8318f2022-10-12 03:28:29183
Peter Boströmd0a383c2022-10-29 04:09:12184#if defined(OFFICIAL_BUILD) && !defined(NDEBUG)
185#error "Debug builds are not expected to be optimized as official builds."
186#endif // defined(OFFICIAL_BUILD) && !defined(NDEBUG)
Hans Wennborg12aea3e2020-04-14 15:29:00187
Peter Boströmd0a383c2022-10-29 04:09:12188#if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON()
Peter Boströmb30544d2022-10-21 00:17:58189// Note that this uses IMMEDIATE_CRASH_ALWAYS_INLINE to force-inline in debug
190// mode as well. See LoggingTest.CheckCausesDistinctBreakpoints.
191[[noreturn]] IMMEDIATE_CRASH_ALWAYS_INLINE void CheckFailure() {
Peter Boström25c6ec72022-11-02 23:25:19192 base::ImmediateCrash();
Peter Boströmb30544d2022-10-21 00:17:58193}
194
Hans Wennborg12aea3e2020-04-14 15:29:00195// Discard log strings to reduce code bloat.
196//
197// This is not calling BreakDebugger since this is called frequently, and
198// calling an out-of-line function instead of a noreturn inline macro prevents
Daniel Cheng27f4a25f2023-06-07 00:20:51199// compiler optimizations. Unlike the other check macros, this one does not use
200// LOGGING_CHECK_FUNCTION_IMPL(), since it is incompatible with
201// EAT_CHECK_STREAM_PARAMETERS().
Hans Wennborg12aea3e2020-04-14 15:29:00202#define CHECK(condition) \
Peter Boströmb30544d2022-10-21 00:17:58203 UNLIKELY(!(condition)) ? logging::CheckFailure() : EAT_CHECK_STREAM_PARAMS()
Hans Wennborg12aea3e2020-04-14 15:29:00204
Gabriel Charettefe051042022-01-19 09:27:29205#define CHECK_WILL_STREAM() false
206
Peter Boströmc9dda6492022-11-03 22:27:26207// Strip the conditional string from official builds.
Peter Boström7c561ce32023-05-11 22:18:01208#define PCHECK(condition) \
Daniel Cheng27f4a25f2023-06-07 00:20:51209 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::PCheck(), condition)
Hans Wennborg12aea3e2020-04-14 15:29:00210
211#else
212
Gabriel Charettefe051042022-01-19 09:27:29213#define CHECK_WILL_STREAM() true
214
Daniel Cheng27f4a25f2023-06-07 00:20:51215#define CHECK(condition) \
216 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::Check(#condition), \
217 condition)
Peter Boström2f8318f2022-10-12 03:28:29218
Daniel Cheng27f4a25f2023-06-07 00:20:51219#define PCHECK(condition) \
220 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::PCheck(#condition), \
221 condition)
Hans Wennborg12aea3e2020-04-14 15:29:00222
223#endif
224
Hans Wennborg12aea3e2020-04-14 15:29:00225#if DCHECK_IS_ON()
226
Daniel Cheng27f4a25f2023-06-07 00:20:51227#define DCHECK(condition) \
228 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DCheck(#condition), \
229 condition)
230#define DPCHECK(condition) \
231 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DPCheck(#condition), \
232 condition)
Hans Wennborg12aea3e2020-04-14 15:29:00233
234#else
235
236#define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
237#define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
238
Peter Boströmbc4629d2023-05-09 03:21:38239#endif // DCHECK_IS_ON()
240
241// The DUMP_WILL_BE_CHECK() macro provides a convenient way to non-fatally dump
242// in official builds if a condition is false. This is used to more cautiously
243// roll out a new CHECK() (or upgrade a DCHECK) where the caller isn't entirely
244// sure that something holds true in practice (but asserts that it should). This
245// is especially useful for platforms that have a low pre-stable population and
246// code areas that are rarely exercised.
247//
248// On DCHECK builds this macro matches DCHECK behavior.
249//
250// This macro isn't optimized (preserves filename, line number and log messages
251// in official builds), as they are expected to be in product temporarily. When
252// using this macro, leave a TODO(crbug.com/nnnn) entry referring to a bug
253// related to its rollout. Then put a NextAction on the bug to come back and
254// clean this up (replace with a CHECK). A DUMP_WILL_BE_CHECK() that's been left
255// untouched for a long time without bug updates suggests that issues that
256// would've prevented enabling this CHECK have either not been discovered or
257// have been resolved.
258//
259// Using this macro is preferred over direct base::debug::DumpWithoutCrashing()
260// invocations as it communicates intent to eventually end up as a CHECK. It
261// also preserves the log message so setting crash keys to get additional debug
262// info isn't required as often.
Daniel Cheng27f4a25f2023-06-07 00:20:51263#define DUMP_WILL_BE_CHECK(condition) \
264 LOGGING_CHECK_FUNCTION_IMPL( \
265 ::logging::CheckError::DumpWillBeCheck(#condition), condition)
Hans Wennborg12aea3e2020-04-14 15:29:00266
267// Async signal safe checking mechanism.
Peter Boströmefa8c002023-04-28 02:33:53268[[noreturn]] BASE_EXPORT void RawCheckFailure(const char* message);
269#define RAW_CHECK(condition) \
270 do { \
271 if (UNLIKELY(!(condition))) { \
272 ::logging::RawCheckFailure("Check failed: " #condition "\n"); \
273 } \
Hans Wennborg12aea3e2020-04-14 15:29:00274 } while (0)
275
276} // namespace logging
277
278#endif // BASE_CHECK_H_