blob: 19de039cea32d54dca57c2248f757f72d0560995 [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"
Peter Boström88d58882022-08-18 18:32:4313#include "base/debug/debugging_buildflags.h"
Hans Wennborg12aea3e2020-04-14 15:29:0014#include "base/immediate_crash.h"
15
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ömf01d8262022-11-16 19:35:3865 // Used by CheckOp. Takes ownership of `log_message`.
66 explicit CheckError(LogMessage* log_message) : log_message_(log_message) {}
67
Hans Wennborg12aea3e2020-04-14 15:29:0068 static CheckError Check(const char* file, int line, const char* condition);
Hans Wennborg12aea3e2020-04-14 15:29:0069
70 static CheckError DCheck(const char* file, int line, const char* condition);
Hans Wennborg12aea3e2020-04-14 15:29:0071
72 static CheckError PCheck(const char* file, int line, const char* condition);
73 static CheckError PCheck(const char* file, int line);
74
75 static CheckError DPCheck(const char* file, int line, const char* condition);
76
Hans Wennborg0472f8c2020-04-23 19:27:2777 static CheckError NotImplemented(const char* file,
78 int line,
79 const char* function);
80
Peter Boströmae771d5e2022-07-15 18:48:0581 static CheckError NotReached(const char* file, int line);
82
Hans Wennborg12aea3e2020-04-14 15:29:0083 // Stream for adding optional details to the error message.
84 std::ostream& stream();
85
Peter Boströmd7080b22022-08-29 18:42:3986 NOMERGE NOT_TAIL_CALLED ~CheckError();
Hans Wennborg12aea3e2020-04-14 15:29:0087
Peter Boström67c8f16d2022-06-23 21:58:2988 CheckError(const CheckError&) = delete;
89 CheckError& operator=(const CheckError&) = delete;
Hans Wennborg12aea3e2020-04-14 15:29:0090
Peter Boström2b2875bb2022-10-28 23:50:1591 template <typename T>
92 std::ostream& operator<<(T&& streamed_type) {
93 return stream() << streamed_type;
94 }
95
Hans Wennborg12aea3e2020-04-14 15:29:0096 private:
Peter Boström67c8f16d2022-06-23 21:58:2997 LogMessage* const log_message_;
Hans Wennborg12aea3e2020-04-14 15:29:0098};
99
Peter Boströmc9dda6492022-11-03 22:27:26100// The 'switch' is used to prevent the 'else' from being ambiguous when the
101// macro is used in an 'if' clause such as:
102// if (a == 1)
103// CHECK(Foo());
104//
105// TODO(crbug.com/1380930): Remove the const bool when the blink-gc plugin has
106// been updated to accept `if (LIKELY(!field_))` as well as `if (!field_)`.
107#define CHECK_FUNCTION_IMPL(check_failure_invocation, condition) \
108 switch (0) \
109 case 0: \
110 default: \
111 if (const bool checky_bool_lol = static_cast<bool>(condition); \
112 LIKELY(ANALYZER_ASSUME_TRUE(checky_bool_lol))) \
113 ; \
114 else \
115 check_failure_invocation
Peter Boström2f8318f2022-10-12 03:28:29116
Peter Boströmd0a383c2022-10-29 04:09:12117#if defined(OFFICIAL_BUILD) && !defined(NDEBUG)
118#error "Debug builds are not expected to be optimized as official builds."
119#endif // defined(OFFICIAL_BUILD) && !defined(NDEBUG)
Hans Wennborg12aea3e2020-04-14 15:29:00120
Peter Boströmd0a383c2022-10-29 04:09:12121#if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON()
Peter Boströmb30544d2022-10-21 00:17:58122// Note that this uses IMMEDIATE_CRASH_ALWAYS_INLINE to force-inline in debug
123// mode as well. See LoggingTest.CheckCausesDistinctBreakpoints.
124[[noreturn]] IMMEDIATE_CRASH_ALWAYS_INLINE void CheckFailure() {
Peter Boström25c6ec72022-11-02 23:25:19125 base::ImmediateCrash();
Peter Boströmb30544d2022-10-21 00:17:58126}
127
Hans Wennborg12aea3e2020-04-14 15:29:00128// Discard log strings to reduce code bloat.
129//
130// This is not calling BreakDebugger since this is called frequently, and
131// calling an out-of-line function instead of a noreturn inline macro prevents
132// compiler optimizations.
133#define CHECK(condition) \
Peter Boströmb30544d2022-10-21 00:17:58134 UNLIKELY(!(condition)) ? logging::CheckFailure() : EAT_CHECK_STREAM_PARAMS()
Hans Wennborg12aea3e2020-04-14 15:29:00135
Gabriel Charettefe051042022-01-19 09:27:29136#define CHECK_WILL_STREAM() false
137
Peter Boströmc9dda6492022-11-03 22:27:26138// Strip the conditional string from official builds.
139#define PCHECK(condition) \
140 CHECK_FUNCTION_IMPL(::logging::CheckError::PCheck(__FILE__, __LINE__), \
141 condition)
Hans Wennborg12aea3e2020-04-14 15:29:00142
143#else
144
Gabriel Charettefe051042022-01-19 09:27:29145#define CHECK_WILL_STREAM() true
146
Peter Boström2f8318f2022-10-12 03:28:29147#define CHECK(condition) \
Peter Boströmc9dda6492022-11-03 22:27:26148 CHECK_FUNCTION_IMPL( \
149 ::logging::CheckError::Check(__FILE__, __LINE__, #condition), condition)
Peter Boström2f8318f2022-10-12 03:28:29150
Peter Boströmc9dda6492022-11-03 22:27:26151#define PCHECK(condition) \
152 CHECK_FUNCTION_IMPL( \
153 ::logging::CheckError::PCheck(__FILE__, __LINE__, #condition), \
154 condition)
Hans Wennborg12aea3e2020-04-14 15:29:00155
156#endif
157
Hans Wennborg12aea3e2020-04-14 15:29:00158#if DCHECK_IS_ON()
159
Peter Boströmc9dda6492022-11-03 22:27:26160#define DCHECK(condition) \
161 CHECK_FUNCTION_IMPL( \
162 ::logging::CheckError::DCheck(__FILE__, __LINE__, #condition), \
163 condition)
164#define DPCHECK(condition) \
165 CHECK_FUNCTION_IMPL( \
166 ::logging::CheckError::DPCheck(__FILE__, __LINE__, #condition), \
167 condition)
Hans Wennborg12aea3e2020-04-14 15:29:00168
169#else
170
171#define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
172#define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
173
174#endif
175
176// Async signal safe checking mechanism.
177BASE_EXPORT void RawCheck(const char* message);
Takashi Sakamoto05c5e732021-09-09 03:18:27178BASE_EXPORT void RawError(const char* message);
Hans Wennborg12aea3e2020-04-14 15:29:00179#define RAW_CHECK(condition) \
180 do { \
181 if (!(condition)) \
182 ::logging::RawCheck("Check failed: " #condition "\n"); \
183 } while (0)
184
185} // namespace logging
186
187#endif // BASE_CHECK_H_