Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / check.h
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
10 #include "base/base_export.h"
11 #include "base/compiler_specific.h"
12 #include "base/dcheck_is_on.h"
13 #include "base/immediate_crash.h"
14 #include "base/location.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
42 namespace logging {
43
44 // Class used to explicitly ignore an ostream, and optionally a boolean value.
45 class VoidifyStream {
46  public:
47   VoidifyStream() = default;
48   explicit VoidifyStream(bool) {}
49
50   // This operator has lower precedence than << but higher than ?:
51   void operator&(std::ostream&) {}
52 };
53
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)
58 BASE_EXPORT extern std::ostream* g_swallow_stream;
59
60 class LogMessage;
61
62 // Class used for raising a check error upon destruction.
63 class BASE_EXPORT CheckError {
64  public:
65   static CheckError Check(
66       const char* condition,
67       const base::Location& location = base::Location::Current());
68   // 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());
73
74   static CheckError DCheck(
75       const char* condition,
76       const base::Location& location = base::Location::Current());
77   // 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());
82
83   static CheckError DumpWillBeCheck(
84       const char* condition,
85       const base::Location& location = base::Location::Current());
86   // 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());
91
92   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());
97
98   static CheckError DPCheck(
99       const char* condition,
100       const base::Location& location = base::Location::Current());
101
102   static CheckError DumpWillBeNotReachedNoreturn(
103       const base::Location& location = base::Location::Current());
104
105   static CheckError NotImplemented(
106       const char* function,
107       const base::Location& location = base::Location::Current());
108
109   // Stream for adding optional details to the error message.
110   std::ostream& stream();
111
112   // 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();
115
116   CheckError(const CheckError&) = delete;
117   CheckError& operator=(const CheckError&) = delete;
118
119   template <typename T>
120   std::ostream& operator<<(T&& streamed_type) {
121     return stream() << streamed_type;
122   }
123
124  protected:
125   // Takes ownership of `log_message`.
126   explicit CheckError(LogMessage* log_message) : log_message_(log_message) {}
127
128   LogMessage* const log_message_;
129 };
130
131 class BASE_EXPORT NotReachedError : public CheckError {
132  public:
133   static NotReachedError NotReached(
134       const base::Location& location = base::Location::Current());
135
136   // 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
140   // TODO(crbug.com/851128): Mark [[noreturn]] once this is CHECK-fatal on all
141   // builds.
142   NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedError();
143
144  private:
145   using CheckError::CheckError;
146 };
147
148 // 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.
150 class BASE_EXPORT NotReachedNoreturnError : public CheckError {
151  public:
152   explicit NotReachedNoreturnError(
153       const base::Location& location = base::Location::Current());
154
155   [[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedNoreturnError();
156 };
157
158 // 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 //
164 // 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_)`.
171 #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)
183
184 #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)
187
188 #if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON()
189 // 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() {
192   base::ImmediateCrash();
193 }
194
195 // 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
199 // 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().
202 #define CHECK(condition) \
203   UNLIKELY(!(condition)) ? logging::CheckFailure() : EAT_CHECK_STREAM_PARAMS()
204
205 #define CHECK_WILL_STREAM() false
206
207 // Strip the conditional string from official builds.
208 #define PCHECK(condition) \
209   LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::PCheck(), condition)
210
211 #else
212
213 #define CHECK_WILL_STREAM() true
214
215 #define CHECK(condition)                                                \
216   LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::Check(#condition), \
217                               condition)
218
219 #define PCHECK(condition)                                                \
220   LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::PCheck(#condition), \
221                               condition)
222
223 #endif
224
225 #if DCHECK_IS_ON()
226
227 #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)
233
234 #else
235
236 #define DCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
237 #define DPCHECK(condition) EAT_CHECK_STREAM_PARAMS(!(condition))
238
239 #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.
263 #define DUMP_WILL_BE_CHECK(condition) \
264   LOGGING_CHECK_FUNCTION_IMPL(        \
265       ::logging::CheckError::DumpWillBeCheck(#condition), condition)
266
267 // Async signal safe checking mechanism.
268 [[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     }                                                               \
274   } while (0)
275
276 }  // namespace logging
277
278 #endif  // BASE_CHECK_H_