Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / base / check_op.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_OP_H_
6 #define BASE_CHECK_OP_H_
7
8 #include <cstddef>
9 #include <string>
10 #include <string_view>
11 #include <type_traits>
12
13 #include "base/base_export.h"
14 #include "base/check.h"
15 #include "base/dcheck_is_on.h"
16 #include "base/memory/raw_ptr_exclusion.h"
17 #include "base/strings/to_string.h"
18 #include "base/types/supports_ostream_operator.h"
19
20 // This header defines the (DP)CHECK_EQ etc. macros.
21 //
22 // (DP)CHECK_EQ(x, y) is similar to (DP)CHECK(x == y) but will also log the
23 // values of x and y if the condition doesn't hold. This works for basic types
24 // and types with an operator<< or .ToString() method.
25 //
26 // The operands are evaluated exactly once, and even in build modes where e.g.
27 // DCHECK is disabled, the operands and their stringification methods are still
28 // referenced to avoid warnings about unused variables or functions.
29 //
30 // To support the stringification of the check operands, this header is
31 // *significantly* larger than base/check.h, so it should be avoided in common
32 // headers.
33 //
34 // This header also provides the (DP)CHECK macros (by including check.h), so if
35 // you use e.g. both CHECK_EQ and CHECK, including this header is enough. If you
36 // only use CHECK however, please include the smaller check.h instead.
37
38 namespace logging {
39
40 // Functions for turning check operand values into NUL-terminated C strings.
41 // Caller takes ownership of the result and must release it with `free`.
42 // This would normally be defined by <ostream>, but this header tries to avoid
43 // including <ostream> to reduce compile-time. See https://crrev.com/c/2128112.
44 BASE_EXPORT char* CheckOpValueStr(int v);
45 BASE_EXPORT char* CheckOpValueStr(unsigned v);
46 BASE_EXPORT char* CheckOpValueStr(long v);
47 BASE_EXPORT char* CheckOpValueStr(unsigned long v);
48 BASE_EXPORT char* CheckOpValueStr(long long v);
49 BASE_EXPORT char* CheckOpValueStr(unsigned long long v);
50 BASE_EXPORT char* CheckOpValueStr(const void* v);
51 BASE_EXPORT char* CheckOpValueStr(std::nullptr_t v);
52 BASE_EXPORT char* CheckOpValueStr(double v);
53 // Although the standard defines operator<< for std::string and std::string_view
54 // in their respective headers, libc++ requires <ostream> for them. See
55 // https://github.com/llvm/llvm-project/issues/61070. So we define non-<ostream>
56 // versions here too.
57 BASE_EXPORT char* CheckOpValueStr(const std::string& v);
58 BASE_EXPORT char* CheckOpValueStr(std::string_view v);
59
60 // Convert a streamable value to string out-of-line to avoid <sstream>.
61 BASE_EXPORT char* StreamValToStr(const void* v,
62                                  void (*stream_func)(std::ostream&,
63                                                      const void*));
64
65 #ifdef __has_builtin
66 #define SUPPORTS_BUILTIN_ADDRESSOF (__has_builtin(__builtin_addressof))
67 #else
68 #define SUPPORTS_BUILTIN_ADDRESSOF 0
69 #endif
70
71 template <typename T>
72 inline std::enable_if_t<
73     base::internal::SupportsOstreamOperator<const T&> &&
74         !std::is_function_v<typename std::remove_pointer<T>::type>,
75     char*>
76 CheckOpValueStr(const T& v) {
77   auto f = [](std::ostream& s, const void* p) {
78     s << *reinterpret_cast<const T*>(p);
79   };
80
81   // operator& might be overloaded, so do the std::addressof dance.
82   // __builtin_addressof is preferred since it also handles Obj-C ARC pointers.
83   // Some casting is still needed, because T might be volatile.
84 #if SUPPORTS_BUILTIN_ADDRESSOF
85   const void* vp = const_cast<const void*>(
86       reinterpret_cast<const volatile void*>(__builtin_addressof(v)));
87 #else
88   const void* vp = reinterpret_cast<const void*>(
89       const_cast<const char*>(&reinterpret_cast<const volatile char&>(v)));
90 #endif
91   return StreamValToStr(vp, f);
92 }
93
94 #undef SUPPORTS_BUILTIN_ADDRESSOF
95
96 // Overload for types that have no operator<< but do have .ToString() defined.
97 template <typename T>
98 inline std::enable_if_t<!base::internal::SupportsOstreamOperator<const T&> &&
99                             base::internal::SupportsToString<const T&>,
100                         char*>
101 CheckOpValueStr(const T& v) {
102   // .ToString() may not return a std::string, e.g. blink::WTF::String.
103   return CheckOpValueStr(v.ToString());
104 }
105
106 // Provide an overload for functions and function pointers. Function pointers
107 // don't implicitly convert to void* but do implicitly convert to bool, so
108 // without this function pointers are always printed as 1 or 0. (MSVC isn't
109 // standards-conforming here and converts function pointers to regular
110 // pointers, so this is a no-op for MSVC.)
111 template <typename T>
112 inline std::enable_if_t<
113     std::is_function_v<typename std::remove_pointer<T>::type>,
114     char*>
115 CheckOpValueStr(const T& v) {
116   return CheckOpValueStr(reinterpret_cast<const void*>(v));
117 }
118
119 // We need overloads for enums that don't support operator<<.
120 // (i.e. scoped enums where no operator<< overload was declared).
121 template <typename T>
122 inline std::enable_if_t<!base::internal::SupportsOstreamOperator<const T&> &&
123                             std::is_enum_v<T>,
124                         char*>
125 CheckOpValueStr(const T& v) {
126   return CheckOpValueStr(
127       static_cast<typename std::underlying_type<T>::type>(v));
128 }
129
130 // Takes ownership of `v1_str` and `v2_str`, destroying them with free(). For
131 // use with CheckOpValueStr() which allocates these strings using strdup().
132 // Returns allocated string (with strdup) for passing into
133 // ::logging::CheckError::(D)CheckOp methods.
134 // TODO(pbos): Annotate this ABSL_ATTRIBUTE_RETURNS_NONNULL after solving
135 // compile failure.
136 BASE_EXPORT char* CreateCheckOpLogMessageString(const char* expr_str,
137                                                 char* v1_str,
138                                                 char* v2_str);
139
140 // Helper macro for binary operators.
141 // The 'switch' is used to prevent the 'else' from being ambiguous when the
142 // macro is used in an 'if' clause such as:
143 // if (a == 1)
144 //   CHECK_EQ(2, a);
145 #define CHECK_OP_FUNCTION_IMPL(check_failure_function, name, op, val1, val2) \
146   switch (0)                                                                 \
147   case 0:                                                                    \
148   default:                                                                   \
149     if (char* const message_on_fail = ::logging::Check##name##Impl(          \
150             (val1), (val2), #val1 " " #op " " #val2);                        \
151         !message_on_fail)                                                    \
152       ;                                                                      \
153     else                                                                     \
154       check_failure_function(message_on_fail)
155
156 #if !CHECK_WILL_STREAM()
157
158 // Discard log strings to reduce code bloat.
159 #define CHECK_OP(name, op, val1, val2) CHECK((val1)op(val2))
160
161 #else
162
163 #define CHECK_OP(name, op, val1, val2) \
164   CHECK_OP_FUNCTION_IMPL(::logging::CheckError::CheckOp, name, op, val1, val2)
165
166 #endif
167
168 // The second overload avoids address-taking of static members for
169 // fundamental types.
170 #define DEFINE_CHECK_OP_IMPL(name, op)                                         \
171   template <                                                                   \
172       typename T, typename U,                                                  \
173       std::enable_if_t<!std::is_fundamental_v<T> || !std::is_fundamental_v<U>, \
174                        int> = 0>                                               \
175   constexpr char* Check##name##Impl(const T& v1, const U& v2,                  \
176                                     const char* expr_str) {                    \
177     if (LIKELY(ANALYZER_ASSUME_TRUE(v1 op v2)))                                \
178       return nullptr;                                                          \
179     return CreateCheckOpLogMessageString(expr_str, CheckOpValueStr(v1),        \
180                                          CheckOpValueStr(v2));                 \
181   }                                                                            \
182   template <                                                                   \
183       typename T, typename U,                                                  \
184       std::enable_if_t<std::is_fundamental_v<T> && std::is_fundamental_v<U>,   \
185                        int> = 0>                                               \
186   constexpr char* Check##name##Impl(T v1, U v2, const char* expr_str) {        \
187     if (LIKELY(ANALYZER_ASSUME_TRUE(v1 op v2)))                                \
188       return nullptr;                                                          \
189     return CreateCheckOpLogMessageString(expr_str, CheckOpValueStr(v1),        \
190                                          CheckOpValueStr(v2));                 \
191   }
192
193 // clang-format off
194 DEFINE_CHECK_OP_IMPL(EQ, ==)
195 DEFINE_CHECK_OP_IMPL(NE, !=)
196 DEFINE_CHECK_OP_IMPL(LE, <=)
197 DEFINE_CHECK_OP_IMPL(LT, < )
198 DEFINE_CHECK_OP_IMPL(GE, >=)
199 DEFINE_CHECK_OP_IMPL(GT, > )
200 #undef DEFINE_CHECK_OP_IMPL
201 #define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
202 #define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
203 #define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
204 #define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
205 #define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
206 #define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
207 // clang-format on
208
209 #if DCHECK_IS_ON()
210
211 #define DCHECK_OP(name, op, val1, val2) \
212   CHECK_OP_FUNCTION_IMPL(::logging::CheckError::DCheckOp, name, op, val1, val2)
213
214 #else
215
216 // Don't do any evaluation but still reference the same stuff as when enabled.
217 #define DCHECK_OP(name, op, val1, val2)                      \
218   EAT_CHECK_STREAM_PARAMS((::logging::CheckOpValueStr(val1), \
219                            ::logging::CheckOpValueStr(val2), (val1)op(val2)))
220
221 #endif
222
223 // clang-format off
224 #define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
225 #define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
226 #define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
227 #define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
228 #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
229 #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
230 // clang-format on
231
232 #define DUMP_WILL_BE_CHECK_OP(name, op, val1, val2)                          \
233   CHECK_OP_FUNCTION_IMPL(::logging::CheckError::DumpWillBeCheckOp, name, op, \
234                          val1, val2)
235
236 #define DUMP_WILL_BE_CHECK_EQ(val1, val2) \
237   DUMP_WILL_BE_CHECK_OP(EQ, ==, val1, val2)
238 #define DUMP_WILL_BE_CHECK_NE(val1, val2) \
239   DUMP_WILL_BE_CHECK_OP(NE, !=, val1, val2)
240 #define DUMP_WILL_BE_CHECK_LE(val1, val2) \
241   DUMP_WILL_BE_CHECK_OP(LE, <=, val1, val2)
242 #define DUMP_WILL_BE_CHECK_LT(val1, val2) \
243   DUMP_WILL_BE_CHECK_OP(LT, <, val1, val2)
244 #define DUMP_WILL_BE_CHECK_GE(val1, val2) \
245   DUMP_WILL_BE_CHECK_OP(GE, >=, val1, val2)
246 #define DUMP_WILL_BE_CHECK_GT(val1, val2) \
247   DUMP_WILL_BE_CHECK_OP(GT, >, val1, val2)
248
249 }  // namespace logging
250
251 #endif  // BASE_CHECK_OP_H_