blob: 6b4de3a3b9c25a9d231622bf4e8d69a2bb6e240a [file] [log] [blame]
Hans Wennborg12aea3e2020-04-14 15:29:001// 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"
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"
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
41namespace logging {
42
43// Class used to explicitly ignore an ostream, and optionally a boolean value.
44class VoidifyStream {
45 public:
46 VoidifyStream() = default;
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)
62BASE_EXPORT extern std::ostream* g_swallow_stream;
63
64class CheckOpResult;
65class LogMessage;
66
67// Class used for raising a check error upon destruction.
68class 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
Hans Wennborg0472f8c2020-04-23 19:27:2781 static CheckError NotImplemented(const char* file,
82 int line,
83 const char* function);
84
Hans Wennborg12aea3e2020-04-14 15:29:0085 // Stream for adding optional details to the error message.
86 std::ostream& stream();
87
Zequan Wu9909f142021-02-10 03:26:0088 NOMERGE ~CheckError();
Hans Wennborg12aea3e2020-04-14 15:29:0089
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
Gabriel Charettefe051042022-01-19 09:27:29111#define CHECK_WILL_STREAM() false
112
Hans Wennborg12aea3e2020-04-14 15:29:00113#define PCHECK(condition) \
114 LAZY_CHECK_STREAM( \
115 ::logging::CheckError::PCheck(__FILE__, __LINE__).stream(), \
116 UNLIKELY(!(condition)))
117
118#else
119
120#define CHECK(condition) \
121 LAZY_CHECK_STREAM( \
122 ::logging::CheckError::Check(__FILE__, __LINE__, #condition).stream(), \
123 !ANALYZER_ASSUME_TRUE(condition))
124
Gabriel Charettefe051042022-01-19 09:27:29125#define CHECK_WILL_STREAM() true
126
Hans Wennborg12aea3e2020-04-14 15:29:00127#define PCHECK(condition) \
128 LAZY_CHECK_STREAM( \
129 ::logging::CheckError::PCheck(__FILE__, __LINE__, #condition).stream(), \
130 !ANALYZER_ASSUME_TRUE(condition))
131
132#endif
133
Hans Wennborg12aea3e2020-04-14 15:29:00134#if DCHECK_IS_ON()
135
136#define DCHECK(condition) \
137 LAZY_CHECK_STREAM( \
138 ::logging::CheckError::DCheck(__FILE__, __LINE__, #condition).stream(), \
139 !ANALYZER_ASSUME_TRUE(condition))
140
141#define DPCHECK(condition) \
142 LAZY_CHECK_STREAM( \
143 ::logging::CheckError::DPCheck(__FILE__, __LINE__, #condition).stream(), \
144 !ANALYZER_ASSUME_TRUE(condition))
145
146#else
147
148#define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
149#define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
150
151#endif
152
153// Async signal safe checking mechanism.
154BASE_EXPORT void RawCheck(const char* message);
Takashi Sakamoto05c5e732021-09-09 03:18:27155BASE_EXPORT void RawError(const char* message);
Hans Wennborg12aea3e2020-04-14 15:29:00156#define RAW_CHECK(condition) \
157 do { \
158 if (!(condition)) \
159 ::logging::RawCheck("Check failed: " #condition "\n"); \
160 } while (0)
161
162} // namespace logging
163
164#endif // BASE_CHECK_H_