1 // Copyright 2020 The Chromium Authors
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 #include <memory>
10
11 #include "base/base_export.h"
12 #include "base/compiler_specific.h"
13 #include "base/dcheck_is_on.h"
14 #include "base/immediate_crash.h"
15 #include "base/location.h"
16 #include "base/macros/if.h"
17 #include "base/macros/is_empty.h"
18 #include "base/not_fatal_until.h"
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 //
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 //
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
57 // Class used to explicitly ignore an ostream, and optionally a boolean value.
58 class VoidifyStream {
59 public:
60 VoidifyStream() = default;
VoidifyStream(bool)61 explicit VoidifyStream(bool) {}
62
63 // Binary & has lower precedence than << but higher than ?:
64 void operator&(std::ostream&) {}
65 };
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
73 class LogMessage;
74
75 // Class used for raising a check error upon destruction.
76 class BASE_EXPORT CheckError {
77 public:
78 static CheckError Check(
79 const char* condition,
80 base::NotFatalUntil fatal_milestone,
81 const base::Location& location = base::Location::Current());
82 // Takes ownership over (free()s after using) `log_message_str`, for use with
83 // CHECK_op macros.
84 static CheckError CheckOp(
85 char* log_message_str,
86 base::NotFatalUntil fatal_milestone,
87 const base::Location& location = base::Location::Current());
88
89 static CheckError DCheck(
90 const char* condition,
91 const base::Location& location = base::Location::Current());
92 // Takes ownership over (free()s after using) `log_message_str`, for use with
93 // DCHECK_op macros.
94 static CheckError DCheckOp(
95 char* log_message_str,
96 const base::Location& location = base::Location::Current());
97
98 static CheckError DumpWillBeCheck(
99 const char* condition,
100 const base::Location& location = base::Location::Current());
101 // Takes ownership over (free()s after using) `log_message_str`, for use with
102 // DUMP_WILL_BE_CHECK_op macros.
103 static CheckError DumpWillBeCheckOp(
104 char* log_message_str,
105 const base::Location& location = base::Location::Current());
106
107 static CheckError DPCheck(
108 const char* condition,
109 const base::Location& location = base::Location::Current());
110
111 static CheckError NotImplemented(
112 const char* function,
113 const base::Location& location = base::Location::Current());
114
115 // Stream for adding optional details to the error message.
116 std::ostream& stream();
117
118 // Try really hard to get the call site and callee as separate stack frames in
119 // crash reports.
120 NOMERGE NOINLINE NOT_TAIL_CALLED ~CheckError();
121
122 CheckError(const CheckError&) = delete;
123 CheckError& operator=(const CheckError&) = delete;
124
125 template <typename T>
126 std::ostream& operator<<(T&& streamed_type) {
127 return stream() << streamed_type;
128 }
129
130 protected:
131 // Takes ownership of `log_message`.
132 explicit CheckError(LogMessage* log_message);
133
134 std::unique_ptr<LogMessage> log_message_;
135 };
136
137 // Used for NOTREACHED(), its destructor is importantly [[noreturn]].
138 class BASE_EXPORT CheckNoreturnError : public CheckError {
139 public:
140 [[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~CheckNoreturnError();
141
142 static CheckNoreturnError Check(
143 const char* condition,
144 const base::Location& location = base::Location::Current());
145 // Takes ownership over (free()s after using) `log_message_str`, for use with
146 // CHECK_op macros.
147 static CheckNoreturnError CheckOp(
148 char* log_message_str,
149 const base::Location& location = base::Location::Current());
150
151 static CheckNoreturnError PCheck(
152 const char* condition,
153 const base::Location& location = base::Location::Current());
154 static CheckNoreturnError PCheck(
155 const base::Location& location = base::Location::Current());
156
157 private:
158 using CheckError::CheckError;
159 };
160
161 // Used for NOTREACHED(base::NotFatalUntil) and DUMP_WILL_BE_NOTREACHED().
162 class BASE_EXPORT NotReachedError : public CheckError {
163 public:
164 static NotReachedError NotReached(
165 base::NotFatalUntil fatal_milestone,
166 const base::Location& location = base::Location::Current());
167
168 static NotReachedError DumpWillBeNotReached(
169 const base::Location& location = base::Location::Current());
170
171 NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedError();
172
173 private:
174 using CheckError::CheckError;
175 };
176
177 // Used for NOTREACHED(), its destructor is importantly [[noreturn]].
178 class BASE_EXPORT NotReachedNoreturnError : public CheckError {
179 public:
180 explicit NotReachedNoreturnError(
181 const base::Location& location = base::Location::Current());
182
183 [[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedNoreturnError();
184 };
185
186 // A helper macro for checks that log to streams that makes it easier for the
187 // compiler to identify and warn about dead code, e.g.:
188 //
189 // return 2;
190 // NOTREACHED_IN_MIGRATION();
191 //
192 // The 'switch' is used to prevent the 'else' from being ambiguous when the
193 // macro is used in an 'if' clause such as:
194 // if (a == 1)
195 // CHECK(Foo());
196 //
197 // The weird ternary is to still generate an "is not contextually convertible to
198 // 'bool' when provided weird parameters (regardless of ANALYZER_ASSUME_TRUE's
199 // implementation). See base/check_nocompile.nc.
200 #define LOGGING_CHECK_FUNCTION_IMPL(check_stream, condition) \
201 switch (0) \
202 case 0: \
203 default: \
204 if (ANALYZER_ASSUME_TRUE((condition) ? true : false)) \
205 [[likely]]; \
206 else \
207 (check_stream)
208
209 // A helper macro like LOGGING_CHECK_FUNCTION_IMPL above but discarding any
210 // log-stream parameters rather than evaluate them on failure.
211 #define DISCARDING_CHECK_FUNCTION_IMPL(check_failure, condition) \
212 switch (0) \
213 case 0: \
214 default: \
215 if (!ANALYZER_ASSUME_TRUE((condition) ? true : false)) \
216 check_failure; \
217 else [[likely]] \
218 EAT_CHECK_STREAM_PARAMS()
219
220 #if defined(OFFICIAL_BUILD) && !defined(NDEBUG)
221 #error "Debug builds are not expected to be optimized as official builds."
222 #endif // defined(OFFICIAL_BUILD) && !defined(NDEBUG)
223
224 #if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON()
225
226 // Official non-DCHECK builds do not preserve CHECK() logging (including
227 // evaluation of logging arguments). This generates more compact code which is
228 // good for both speed and binary size.
229 #define CHECK_WILL_STREAM() false
230
231 // Note that this uses IMMEDIATE_CRASH_ALWAYS_INLINE to force-inline in debug
232 // mode as well. See LoggingTest.CheckCausesDistinctBreakpoints.
CheckFailure()233 [[noreturn]] NOMERGE IMMEDIATE_CRASH_ALWAYS_INLINE void CheckFailure() {
234 base::ImmediateCrash();
235 }
236
237 // Discard log strings to reduce code bloat when there is no NotFatalUntil
238 // argument (which temporarily preserves logging both locally and in crash
239 // reports).
240 #define CHECK_INTERNAL_IMPL(cond) \
241 DISCARDING_CHECK_FUNCTION_IMPL(::logging::CheckFailure(), cond)
242
243 #else
244
245 // Generate logging versions of CHECKs to help diagnosing failures.
246 #define CHECK_WILL_STREAM() true
247
248 #define CHECK_INTERNAL_IMPL(cond) \
249 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckNoreturnError::Check(#cond), cond)
250
251 #endif
252
253 #define CHECK(cond, ...) \
254 BASE_IF(BASE_IS_EMPTY(__VA_ARGS__), CHECK_INTERNAL_IMPL(cond), \
255 LOGGING_CHECK_FUNCTION_IMPL( \
256 logging::CheckError::Check(#cond, __VA_ARGS__), cond))
257
258 // Strip the conditional string based on CHECK_WILL_STREAM()
259 #define PCHECK(cond) \
260 LOGGING_CHECK_FUNCTION_IMPL( \
261 BASE_IF(CHECK_WILL_STREAM(), \
262 ::logging::CheckNoreturnError::PCheck(#cond), \
263 ::logging::CheckNoreturnError::PCheck()), \
264 cond)
265
266 #if DCHECK_IS_ON()
267
268 #define DCHECK(condition) \
269 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DCheck(#condition), \
270 condition)
271 #define DPCHECK(condition) \
272 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DPCheck(#condition), \
273 condition)
274
275 #else
276
277 #define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
278 #define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
279
280 #endif // DCHECK_IS_ON()
281
282 // The DUMP_WILL_BE_CHECK() macro provides a convenient way to non-fatally dump
283 // in official builds if a condition is false. This is used to more cautiously
284 // roll out a new CHECK() (or upgrade a DCHECK) where the caller isn't entirely
285 // sure that something holds true in practice (but asserts that it should). This
286 // is especially useful for platforms that have a low pre-stable population and
287 // code areas that are rarely exercised.
288 //
289 // On DCHECK builds this macro matches DCHECK behavior.
290 //
291 // This macro isn't optimized (preserves filename, line number and log messages
292 // in official builds), as they are expected to be in product temporarily. When
293 // using this macro, leave a TODO(crbug.com/nnnn) entry referring to a bug
294 // related to its rollout. Then put a NextAction on the bug to come back and
295 // clean this up (replace with a CHECK). A DUMP_WILL_BE_CHECK() that's been left
296 // untouched for a long time without bug updates suggests that issues that
297 // would've prevented enabling this CHECK have either not been discovered or
298 // have been resolved.
299 //
300 // Using this macro is preferred over direct base::debug::DumpWithoutCrashing()
301 // invocations as it communicates intent to eventually end up as a CHECK. It
302 // also preserves the log message so setting crash keys to get additional debug
303 // info isn't required as often.
304 #define DUMP_WILL_BE_CHECK(condition, ...) \
305 LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::DumpWillBeCheck( \
306 #condition __VA_OPT__(, ) __VA_ARGS__), \
307 condition)
308
309 // Async signal safe checking mechanism.
310 [[noreturn]] BASE_EXPORT void RawCheckFailure(const char* message);
311 #define RAW_CHECK(condition) \
312 do { \
313 if (!(condition)) [[unlikely]] { \
314 ::logging::RawCheckFailure("Check failed: " #condition "\n"); \
315 } \
316 } while (0)
317
318 } // namespace logging
319
320 #endif // BASE_CHECK_H_
321