blob: 5842d58858c6aa1c84529e14f6c0de2d72cbd627 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2006 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 04:47:3111#ifndef RTC_BASE_CHECKS_H_
12#define RTC_BASE_CHECKS_H_
henrike@webrtc.orgf0488722014-05-13 18:00:2613
Henrik Kjellanderec78f1c2017-06-29 05:52:5014// If you for some reson need to know if DCHECKs are on, test the value of
15// RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be
16// defined, to either a true or a false value.)
Mirko Bonadei481e3452021-07-30 11:57:2517#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
Henrik Kjellanderec78f1c2017-06-29 05:52:5018#define RTC_DCHECK_IS_ON 1
19#else
20#define RTC_DCHECK_IS_ON 0
21#endif
22
Fredrik Solenberg500e75b2018-05-23 09:49:0123// Annotate a function that will not return control flow to the caller.
24#if defined(_MSC_VER)
25#define RTC_NORETURN __declspec(noreturn)
26#elif defined(__GNUC__)
Jonas Olssona4d87372019-07-05 17:08:3327#define RTC_NORETURN __attribute__((__noreturn__))
Fredrik Solenberg500e75b2018-05-23 09:49:0128#else
29#define RTC_NORETURN
30#endif
31
Henrik Kjellanderec78f1c2017-06-29 05:52:5032#ifdef __cplusplus
33extern "C" {
34#endif
Fredrik Solenberg500e75b2018-05-23 09:49:0135RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg);
Henrik Kjellanderec78f1c2017-06-29 05:52:5036#ifdef __cplusplus
37} // extern "C"
38#endif
39
Artem Titov9dc209a2019-11-28 16:09:3040#ifdef RTC_DISABLE_CHECK_MSG
41#define RTC_CHECK_MSG_ENABLED 0
42#else
43#define RTC_CHECK_MSG_ENABLED 1
44#endif
45
46#if RTC_CHECK_MSG_ENABLED
47#define RTC_CHECK_EVAL_MESSAGE(message) message
48#else
49#define RTC_CHECK_EVAL_MESSAGE(message) ""
50#endif
51
Henrik Kjellanderec78f1c2017-06-29 05:52:5052#ifdef __cplusplus
53// C++ version.
54
Henrik Kjellanderec78f1c2017-06-29 05:52:5055#include <string>
56
Sebastian Janssonf4e085a2019-05-20 16:34:0757#include "absl/meta/type_traits.h"
Danil Chapovalov86528552024-09-30 13:12:4358#include "absl/strings/has_absl_stringify.h"
59#include "absl/strings/str_cat.h"
Mirko Bonadeid4a37a62019-03-11 09:31:2260#include "absl/strings/string_view.h"
Niels Möller94327682022-04-28 11:20:2961#include "api/scoped_refptr.h"
Karl Wiberge40468b2017-11-22 09:42:2662#include "rtc_base/numerics/safe_compare.h"
Jonas Olssonf8e5c112018-06-14 11:14:2263#include "rtc_base/system/inline.h"
Mirko Bonadei35214fc2019-09-23 12:54:2864#include "rtc_base/system/rtc_export.h"
Danil Chapovalovf75ab822024-10-03 09:45:2765#include "rtc_base/type_traits.h"
Henrik Kjellanderec78f1c2017-06-29 05:52:5066
67// The macros here print a message to stderr and abort under various
68// conditions. All will accept additional stream messages. For example:
69// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar.";
70//
71// - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't,
72// it's better to terminate the process than to continue. During development,
73// the reason that it's better to terminate might simply be that the error
74// handling code isn't in place yet; in production, the reason might be that
75// the author of the code truly believes that x will always be true, but that
Magnus Flodman55afe382020-06-12 12:55:4076// they recognizes that if they are wrong, abrupt and unpleasant process
Henrik Kjellanderec78f1c2017-06-29 05:52:5077// termination is still better than carrying on with the assumption violated.
78//
79// RTC_CHECK always evaluates its argument, so it's OK for x to have side
80// effects.
81//
82// - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always
83// true---except that x will only be evaluated in debug builds; in production
84// builds, x is simply assumed to be true. This is useful if evaluating x is
85// expensive and the expected cost of failing to detect the violated
86// assumption is acceptable. You should not handle cases where a production
87// build fails to spot a violated condition, even those that would result in
88// crashes. If the code needs to cope with the error, make it cope, but don't
89// call RTC_DCHECK; if the condition really can't occur, but you'd sleep
90// better at night knowing that the process will suicide instead of carrying
91// on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK.
92//
93// RTC_DCHECK only evaluates its argument in debug builds, so if x has visible
94// side effects, you need to write e.g.
95// bool w = x; RTC_DCHECK(w);
96//
97// - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are
98// specialized variants of RTC_CHECK and RTC_DCHECK that print prettier
99// messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and
100// RTC_DCHECK.
101//
Mirko Bonadei01719fb2020-11-17 13:50:54102// - RTC_FATAL() aborts unconditionally.
Henrik Kjellanderec78f1c2017-06-29 05:52:50103
104namespace rtc {
Jonas Olssonf8e5c112018-06-14 11:14:22105namespace webrtc_checks_impl {
106enum class CheckArgType : int8_t {
107 kEnd = 0,
108 kInt,
109 kLong,
110 kLongLong,
111 kUInt,
112 kULong,
113 kULongLong,
114 kDouble,
115 kLongDouble,
116 kCharP,
117 kStdString,
Mirko Bonadeid4a37a62019-03-11 09:31:22118 kStringView,
Jonas Olssonf8e5c112018-06-14 11:14:22119 kVoidP,
Jonas Olssond000b0a2018-07-03 10:07:53120
121 // kCheckOp doesn't represent an argument type. Instead, it is sent as the
122 // first argument from RTC_CHECK_OP to make FatalLog use the next two
123 // arguments to build the special CHECK_OP error message
124 // (the "a == b (1 vs. 2)" bit).
125 kCheckOp,
Jonas Olssonf8e5c112018-06-14 11:14:22126};
Henrik Kjellanderec78f1c2017-06-29 05:52:50127
Peter Boströme1c89352022-07-22 22:31:02128// These two functions are public so they can be overridden from
129// webrtc_overrides in chromium.
130RTC_NORETURN void WriteFatalLog(const char* file,
131 int line,
132 absl::string_view output);
133RTC_NORETURN void WriteFatalLog(absl::string_view output);
134
Artem Titov9dc209a2019-11-28 16:09:30135#if RTC_CHECK_MSG_ENABLED
Mirko Bonadei35214fc2019-09-23 12:54:28136RTC_NORETURN RTC_EXPORT void FatalLog(const char* file,
137 int line,
138 const char* message,
139 const CheckArgType* fmt,
140 ...);
Artem Titov9dc209a2019-11-28 16:09:30141#else
142RTC_NORETURN RTC_EXPORT void FatalLog(const char* file, int line);
143#endif
Jonas Olssonf8e5c112018-06-14 11:14:22144
145// Wrapper for log arguments. Only ever make values of this type with the
146// MakeVal() functions.
147template <CheckArgType N, typename T>
148struct Val {
149 static constexpr CheckArgType Type() { return N; }
150 T GetVal() const { return val; }
151 T val;
152};
153
Sebastian Janssonb1138622019-04-11 14:48:15154// Case for when we need to construct a temp string and then print that.
155// (We can't use Val<CheckArgType::kStdString, const std::string*>
156// because we need somewhere to store the temp string.)
157struct ToStringVal {
158 static constexpr CheckArgType Type() { return CheckArgType::kStdString; }
159 const std::string* GetVal() const { return &val; }
160 std::string val;
161};
162
Jonas Olssonf8e5c112018-06-14 11:14:22163inline Val<CheckArgType::kInt, int> MakeVal(int x) {
164 return {x};
165}
166inline Val<CheckArgType::kLong, long> MakeVal(long x) {
167 return {x};
168}
169inline Val<CheckArgType::kLongLong, long long> MakeVal(long long x) {
170 return {x};
171}
172inline Val<CheckArgType::kUInt, unsigned int> MakeVal(unsigned int x) {
173 return {x};
174}
175inline Val<CheckArgType::kULong, unsigned long> MakeVal(unsigned long x) {
176 return {x};
177}
178inline Val<CheckArgType::kULongLong, unsigned long long> MakeVal(
179 unsigned long long x) {
180 return {x};
181}
182
183inline Val<CheckArgType::kDouble, double> MakeVal(double x) {
184 return {x};
185}
186inline Val<CheckArgType::kLongDouble, long double> MakeVal(long double x) {
187 return {x};
188}
189
190inline Val<CheckArgType::kCharP, const char*> MakeVal(const char* x) {
191 return {x};
192}
193inline Val<CheckArgType::kStdString, const std::string*> MakeVal(
194 const std::string& x) {
195 return {&x};
196}
Mirko Bonadeid4a37a62019-03-11 09:31:22197inline Val<CheckArgType::kStringView, const absl::string_view*> MakeVal(
198 const absl::string_view& x) {
199 return {&x};
200}
Jonas Olssonf8e5c112018-06-14 11:14:22201
202inline Val<CheckArgType::kVoidP, const void*> MakeVal(const void* x) {
203 return {x};
204}
205
Niels Möller94327682022-04-28 11:20:29206template <typename T>
207inline Val<CheckArgType::kVoidP, const void*> MakeVal(
208 const rtc::scoped_refptr<T>& p) {
209 return {p.get()};
210}
211
Amit Hilbuch10c5a932019-03-18 20:09:18212// The enum class types are not implicitly convertible to arithmetic types.
Sebastian Janssonf4e085a2019-05-20 16:34:07213template <typename T,
214 absl::enable_if_t<std::is_enum<T>::value &&
215 !std::is_arithmetic<T>::value>* = nullptr>
216inline decltype(MakeVal(std::declval<absl::underlying_type_t<T>>())) MakeVal(
217 T x) {
218 return {static_cast<absl::underlying_type_t<T>>(x)};
Amit Hilbuch10c5a932019-03-18 20:09:18219}
220
Danil Chapovalov86528552024-09-30 13:12:43221template <typename T,
Danil Chapovalovebd37322024-10-07 17:16:54222 std::enable_if_t<absl::HasAbslStringify<T>::value>* = nullptr>
Danil Chapovalov86528552024-09-30 13:12:43223ToStringVal MakeVal(const T& x) {
224 return {absl::StrCat(x)};
225}
226
Jonas Olssonf8e5c112018-06-14 11:14:22227// Ephemeral type that represents the result of the logging << operator.
228template <typename... Ts>
229class LogStreamer;
230
231// Base case: Before the first << argument.
232template <>
233class LogStreamer<> final {
234 public:
Amit Hilbuch10c5a932019-03-18 20:09:18235 template <typename U,
Sebastian Janssonf4e085a2019-05-20 16:34:07236 typename V = decltype(MakeVal(std::declval<U>())),
237 absl::enable_if_t<std::is_arithmetic<U>::value ||
238 std::is_enum<U>::value>* = nullptr>
239 RTC_FORCE_INLINE LogStreamer<V> operator<<(U arg) const {
240 return LogStreamer<V>(MakeVal(arg), this);
Jonas Olssonf8e5c112018-06-14 11:14:22241 }
242
Amit Hilbuch10c5a932019-03-18 20:09:18243 template <typename U,
Sebastian Janssonf4e085a2019-05-20 16:34:07244 typename V = decltype(MakeVal(std::declval<U>())),
245 absl::enable_if_t<!std::is_arithmetic<U>::value &&
246 !std::is_enum<U>::value>* = nullptr>
247 RTC_FORCE_INLINE LogStreamer<V> operator<<(const U& arg) const {
248 return LogStreamer<V>(MakeVal(arg), this);
Jonas Olssonf8e5c112018-06-14 11:14:22249 }
250
Artem Titov9dc209a2019-11-28 16:09:30251#if RTC_CHECK_MSG_ENABLED
Jonas Olssonf8e5c112018-06-14 11:14:22252 template <typename... Us>
253 RTC_NORETURN RTC_FORCE_INLINE static void Call(const char* file,
254 const int line,
255 const char* message,
256 const Us&... args) {
257 static constexpr CheckArgType t[] = {Us::Type()..., CheckArgType::kEnd};
258 FatalLog(file, line, message, t, args.GetVal()...);
259 }
Jonas Olssond000b0a2018-07-03 10:07:53260
261 template <typename... Us>
262 RTC_NORETURN RTC_FORCE_INLINE static void CallCheckOp(const char* file,
263 const int line,
264 const char* message,
265 const Us&... args) {
266 static constexpr CheckArgType t[] = {CheckArgType::kCheckOp, Us::Type()...,
267 CheckArgType::kEnd};
268 FatalLog(file, line, message, t, args.GetVal()...);
269 }
Artem Titov9dc209a2019-11-28 16:09:30270#else
271 template <typename... Us>
272 RTC_NORETURN RTC_FORCE_INLINE static void Call(const char* file,
273 const int line) {
274 FatalLog(file, line);
275 }
276#endif
Jonas Olssonf8e5c112018-06-14 11:14:22277};
278
279// Inductive case: We've already seen at least one << argument. The most recent
280// one had type `T`, and the earlier ones had types `Ts`.
281template <typename T, typename... Ts>
282class LogStreamer<T, Ts...> final {
283 public:
284 RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer<Ts...>* prior)
285 : arg_(arg), prior_(prior) {}
286
Amit Hilbuch10c5a932019-03-18 20:09:18287 template <typename U,
Sebastian Janssonf4e085a2019-05-20 16:34:07288 typename V = decltype(MakeVal(std::declval<U>())),
289 absl::enable_if_t<std::is_arithmetic<U>::value ||
290 std::is_enum<U>::value>* = nullptr>
291 RTC_FORCE_INLINE LogStreamer<V, T, Ts...> operator<<(U arg) const {
292 return LogStreamer<V, T, Ts...>(MakeVal(arg), this);
Jonas Olssonf8e5c112018-06-14 11:14:22293 }
294
Amit Hilbuch10c5a932019-03-18 20:09:18295 template <typename U,
Sebastian Janssonf4e085a2019-05-20 16:34:07296 typename V = decltype(MakeVal(std::declval<U>())),
297 absl::enable_if_t<!std::is_arithmetic<U>::value &&
298 !std::is_enum<U>::value>* = nullptr>
299 RTC_FORCE_INLINE LogStreamer<V, T, Ts...> operator<<(const U& arg) const {
300 return LogStreamer<V, T, Ts...>(MakeVal(arg), this);
Jonas Olssonf8e5c112018-06-14 11:14:22301 }
302
Artem Titov9dc209a2019-11-28 16:09:30303#if RTC_CHECK_MSG_ENABLED
Jonas Olssonf8e5c112018-06-14 11:14:22304 template <typename... Us>
305 RTC_NORETURN RTC_FORCE_INLINE void Call(const char* file,
306 const int line,
307 const char* message,
308 const Us&... args) const {
309 prior_->Call(file, line, message, arg_, args...);
310 }
311
Jonas Olssond000b0a2018-07-03 10:07:53312 template <typename... Us>
313 RTC_NORETURN RTC_FORCE_INLINE void CallCheckOp(const char* file,
314 const int line,
315 const char* message,
316 const Us&... args) const {
317 prior_->CallCheckOp(file, line, message, arg_, args...);
318 }
Artem Titov9dc209a2019-11-28 16:09:30319#else
320 template <typename... Us>
321 RTC_NORETURN RTC_FORCE_INLINE void Call(const char* file,
322 const int line) const {
323 prior_->Call(file, line);
324 }
325#endif
Jonas Olssond000b0a2018-07-03 10:07:53326
Jonas Olssonf8e5c112018-06-14 11:14:22327 private:
328 // The most recent argument.
329 T arg_;
330
331 // Earlier arguments.
332 const LogStreamer<Ts...>* prior_;
333};
334
Jonas Olssond000b0a2018-07-03 10:07:53335template <bool isCheckOp>
Jonas Olssonf8e5c112018-06-14 11:14:22336class FatalLogCall final {
337 public:
338 FatalLogCall(const char* file, int line, const char* message)
339 : file_(file), line_(line), message_(message) {}
340
341 // This can be any binary operator with precedence lower than <<.
342 template <typename... Ts>
343 RTC_NORETURN RTC_FORCE_INLINE void operator&(
344 const LogStreamer<Ts...>& streamer) {
Artem Titov9dc209a2019-11-28 16:09:30345#if RTC_CHECK_MSG_ENABLED
Jonas Olssond000b0a2018-07-03 10:07:53346 isCheckOp ? streamer.CallCheckOp(file_, line_, message_)
347 : streamer.Call(file_, line_, message_);
Artem Titov9dc209a2019-11-28 16:09:30348#else
349 streamer.Call(file_, line_);
350#endif
Jonas Olssonf8e5c112018-06-14 11:14:22351 }
352
353 private:
354 const char* file_;
355 int line_;
356 const char* message_;
357};
Artem Titov9dc209a2019-11-28 16:09:30358
Karl Wibergc95b9392020-11-07 23:49:37359#if RTC_DCHECK_IS_ON
360
361// Be helpful, and include file and line in the RTC_CHECK_NOTREACHED error
362// message.
363#define RTC_UNREACHABLE_FILE_AND_LINE_CALL_ARGS __FILE__, __LINE__
364RTC_NORETURN RTC_EXPORT void UnreachableCodeReached(const char* file, int line);
365
366#else
367
368// Be mindful of binary size, and don't include file and line in the
369// RTC_CHECK_NOTREACHED error message.
370#define RTC_UNREACHABLE_FILE_AND_LINE_CALL_ARGS
371RTC_NORETURN RTC_EXPORT void UnreachableCodeReached();
372
373#endif
374
Jonas Olssonf8e5c112018-06-14 11:14:22375} // namespace webrtc_checks_impl
Henrik Kjellanderec78f1c2017-06-29 05:52:50376
Artem Titov96e3b992021-07-26 14:03:14377// The actual stream used isn't important. We reference `ignored` in the code
Henrik Kjellanderec78f1c2017-06-29 05:52:50378// but don't evaluate it; this is to avoid "unused variable" warnings (we do so
379// in a particularly convoluted way with an extra ?: because that appears to be
380// the simplest construct that keeps Visual Studio from complaining about
381// condition being unused).
Jiawei Ou14e5f0b2020-03-04 21:38:02382#define RTC_EAT_STREAM_PARAMETERS(ignored) \
383 (true ? true : ((void)(ignored), true)) \
384 ? static_cast<void>(0) \
385 : ::rtc::webrtc_checks_impl::FatalLogCall<false>("", 0, "") & \
386 ::rtc::webrtc_checks_impl::LogStreamer<>()
Henrik Kjellanderec78f1c2017-06-29 05:52:50387
388// Call RTC_EAT_STREAM_PARAMETERS with an argument that fails to compile if
Artem Titov96e3b992021-07-26 14:03:14389// values of the same types as `a` and `b` can't be compared with the given
390// operation, and that would evaluate `a` and `b` if evaluated.
Henrik Kjellanderec78f1c2017-06-29 05:52:50391#define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \
Jiawei Ou14e5f0b2020-03-04 21:38:02392 RTC_EAT_STREAM_PARAMETERS(((void)::rtc::Safe##op(a, b)))
Henrik Kjellanderec78f1c2017-06-29 05:52:50393
394// RTC_CHECK dies with a fatal error if condition is not true. It is *not*
395// controlled by NDEBUG or anything else, so the check will be executed
396// regardless of compilation mode.
397//
Artem Titov96e3b992021-07-26 14:03:14398// We make sure RTC_CHECK et al. always evaluates `condition`, as
Henrik Kjellanderec78f1c2017-06-29 05:52:50399// doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom.
Artem Titov9dc209a2019-11-28 16:09:30400//
401// RTC_CHECK_OP is a helper macro for binary operators.
402// Don't use this macro directly in your code, use RTC_CHECK_EQ et al below.
403#if RTC_CHECK_MSG_ENABLED
Jiawei Ou14e5f0b2020-03-04 21:38:02404#define RTC_CHECK(condition) \
405 (condition) ? static_cast<void>(0) \
406 : ::rtc::webrtc_checks_impl::FatalLogCall<false>( \
407 __FILE__, __LINE__, #condition) & \
408 ::rtc::webrtc_checks_impl::LogStreamer<>()
Artem Titov9dc209a2019-11-28 16:09:30409
Jiawei Ou14e5f0b2020-03-04 21:38:02410#define RTC_CHECK_OP(name, op, val1, val2) \
411 ::rtc::Safe##name((val1), (val2)) \
412 ? static_cast<void>(0) \
413 : ::rtc::webrtc_checks_impl::FatalLogCall<true>( \
414 __FILE__, __LINE__, #val1 " " #op " " #val2) & \
415 ::rtc::webrtc_checks_impl::LogStreamer<>() << (val1) << (val2)
Danil Chapovaloveeb9cca2020-01-17 16:35:13416#else
Jiawei Ou14e5f0b2020-03-04 21:38:02417#define RTC_CHECK(condition) \
Jared Siskin802e8e52023-04-20 00:35:28418 (condition) ? static_cast<void>(0) \
419 : true ? ::rtc::webrtc_checks_impl::FatalLogCall<false>(__FILE__, __LINE__, \
420 "") & \
421 ::rtc::webrtc_checks_impl::LogStreamer<>() \
422 : ::rtc::webrtc_checks_impl::FatalLogCall<false>("", 0, "") & \
423 ::rtc::webrtc_checks_impl::LogStreamer<>()
Danil Chapovaloveeb9cca2020-01-17 16:35:13424
Jiawei Ou14e5f0b2020-03-04 21:38:02425#define RTC_CHECK_OP(name, op, val1, val2) \
Jared Siskin802e8e52023-04-20 00:35:28426 ::rtc::Safe##name((val1), (val2)) ? static_cast<void>(0) \
427 : true ? ::rtc::webrtc_checks_impl::FatalLogCall<true>(__FILE__, __LINE__, \
428 "") & \
429 ::rtc::webrtc_checks_impl::LogStreamer<>() \
430 : ::rtc::webrtc_checks_impl::FatalLogCall<false>("", 0, "") & \
431 ::rtc::webrtc_checks_impl::LogStreamer<>()
Artem Titov9dc209a2019-11-28 16:09:30432#endif
Henrik Kjellanderec78f1c2017-06-29 05:52:50433
434#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2)
435#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2)
436#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2)
437#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2)
438#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2)
439#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2)
440
441// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates
442// code in debug builds. It does reference the condition parameter in all cases,
443// though, so callers won't risk getting warnings about unused variables.
444#if RTC_DCHECK_IS_ON
445#define RTC_DCHECK(condition) RTC_CHECK(condition)
446#define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2)
447#define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2)
448#define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2)
449#define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2)
450#define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2)
451#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
452#else
453#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition)
454#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2)
455#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2)
456#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2)
457#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2)
458#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2)
459#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2)
460#endif
461
Henrik Kjellanderec78f1c2017-06-29 05:52:50462#define RTC_UNREACHABLE_CODE_HIT false
Artem Titovd3251962021-11-15 15:57:07463#define RTC_DCHECK_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT)
Henrik Kjellanderec78f1c2017-06-29 05:52:50464
Karl Wibergc95b9392020-11-07 23:49:37465// Kills the process with an error message. Never returns. Use when you wish to
466// assert that a point in the code is never reached.
467#define RTC_CHECK_NOTREACHED() \
468 do { \
469 ::rtc::webrtc_checks_impl::UnreachableCodeReached( \
470 RTC_UNREACHABLE_FILE_AND_LINE_CALL_ARGS); \
471 } while (0)
472
Mirko Bonadei01719fb2020-11-17 13:50:54473#define RTC_FATAL() \
Jiawei Ou14e5f0b2020-03-04 21:38:02474 ::rtc::webrtc_checks_impl::FatalLogCall<false>(__FILE__, __LINE__, \
475 "FATAL()") & \
476 ::rtc::webrtc_checks_impl::LogStreamer<>()
Henrik Kjellanderec78f1c2017-06-29 05:52:50477
478// Performs the integer division a/b and returns the result. CHECKs that the
479// remainder is zero.
480template <typename T>
481inline T CheckedDivExact(T a, T b) {
482 RTC_CHECK_EQ(a % b, 0) << a << " is not evenly divisible by " << b;
483 return a / b;
484}
485
486} // namespace rtc
487
488#else // __cplusplus not defined
489// C version. Lacks many features compared to the C++ version, but usage
490// guidelines are the same.
491
Artem Titov9dc209a2019-11-28 16:09:30492#define RTC_CHECK(condition) \
493 do { \
494 if (!(condition)) { \
495 rtc_FatalMessage(__FILE__, __LINE__, \
496 RTC_CHECK_EVAL_MESSAGE("CHECK failed: " #condition)); \
497 } \
Henrik Kjellanderec78f1c2017-06-29 05:52:50498 } while (0)
499
500#define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b))
501#define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b))
502#define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b))
503#define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b))
504#define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b))
505#define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b))
506
Artem Titov9dc209a2019-11-28 16:09:30507#define RTC_DCHECK(condition) \
508 do { \
509 if (RTC_DCHECK_IS_ON && !(condition)) { \
510 rtc_FatalMessage(__FILE__, __LINE__, \
511 RTC_CHECK_EVAL_MESSAGE("DCHECK failed: " #condition)); \
512 } \
Henrik Kjellanderec78f1c2017-06-29 05:52:50513 } while (0)
514
515#define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b))
516#define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b))
517#define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b))
518#define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b))
519#define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b))
520#define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b))
521
522#endif // __cplusplus
kwiberg2e486462016-08-23 12:54:25523
Mirko Bonadei92ea95e2017-09-15 04:47:31524#endif // RTC_BASE_CHECKS_H_