/src/abseil-cpp/absl/log/internal/check_op.h
Line  | Count  | Source  | 
1  |  | // Copyright 2022 The Abseil Authors.  | 
2  |  | //  | 
3  |  | // Licensed under the Apache License, Version 2.0 (the "License");  | 
4  |  | // you may not use this file except in compliance with the License.  | 
5  |  | // You may obtain a copy of the License at  | 
6  |  | //  | 
7  |  | //      https://www.apache.org/licenses/LICENSE-2.0  | 
8  |  | //  | 
9  |  | // Unless required by applicable law or agreed to in writing, software  | 
10  |  | // distributed under the License is distributed on an "AS IS" BASIS,  | 
11  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
12  |  | // See the License for the specific language governing permissions and  | 
13  |  | // limitations under the License.  | 
14  |  | //  | 
15  |  | // -----------------------------------------------------------------------------  | 
16  |  | // File: log/internal/check_op.h  | 
17  |  | // -----------------------------------------------------------------------------  | 
18  |  | //  | 
19  |  | // This file declares helpers routines and macros used to implement `CHECK`  | 
20  |  | // macros.  | 
21  |  |  | 
22  |  | #ifndef ABSL_LOG_INTERNAL_CHECK_OP_H_  | 
23  |  | #define ABSL_LOG_INTERNAL_CHECK_OP_H_  | 
24  |  |  | 
25  |  | #include <stdint.h>  | 
26  |  |  | 
27  |  | #include <cstddef>  | 
28  |  | #include <ostream>  | 
29  |  | #include <sstream>  | 
30  |  | #include <string>  | 
31  |  | #include <type_traits>  | 
32  |  | #include <utility>  | 
33  |  |  | 
34  |  | #include "absl/base/attributes.h"  | 
35  |  | #include "absl/base/casts.h"  | 
36  |  | #include "absl/base/config.h"  | 
37  |  | #include "absl/base/nullability.h"  | 
38  |  | #include "absl/base/optimization.h"  | 
39  |  | #include "absl/log/internal/nullguard.h"  | 
40  |  | #include "absl/log/internal/nullstream.h"  | 
41  |  | #include "absl/log/internal/strip.h"  | 
42  |  | #include "absl/strings/has_absl_stringify.h"  | 
43  |  | #include "absl/strings/has_ostream_operator.h"  | 
44  |  | #include "absl/strings/string_view.h"  | 
45  |  |  | 
46  |  | // `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that  | 
47  |  | // should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.  | 
48  |  | #ifdef ABSL_MIN_LOG_LEVEL  | 
49  |  | #define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal)                \  | 
50  |  |   (::absl::LogSeverity::kFatal >=                                      \  | 
51  |  |            static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL) \  | 
52  |  |        ? (literal)                                                     \  | 
53  |  |        : "")  | 
54  |  | #else  | 
55  |  | #define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)  | 
56  |  | #endif  | 
57  |  |  | 
58  |  | #ifdef NDEBUG  | 
59  |  | // `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing.  However, we  | 
60  |  | // still want the compiler to parse `x` and `y`, because we don't want to lose  | 
61  |  | // potentially useful errors and warnings.  | 
62  |  | #define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y)   \  | 
63  |  |   while (false && ((void)(x), (void)(y), 0)) \  | 
64  |  |   ::absl::log_internal::NullStream().InternalStream()  | 
65  |  | #endif  | 
66  |  |  | 
67  |  | #define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \  | 
68  |  |   while (const char* absl_nullable absl_log_internal_check_op_result           \  | 
69  |  |          [[maybe_unused]] = ::absl::log_internal::name##Impl(                  \  | 
70  |  |              ::absl::log_internal::GetReferenceableValue(val1),                \  | 
71  |  |              ::absl::log_internal::GetReferenceableValue(val2),                \  | 
72  |  |              ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val1_text " " #op          \  | 
73  |  |                                                               " " val2_text))) \  | 
74  |  |     ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \  | 
75  |  |   ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>(     \  | 
76  |  |                               absl_log_internal_check_op_result))              \  | 
77  |  |       .InternalStream()  | 
78  |  | #define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2,        \  | 
79  |  |                                     val2_text)                              \  | 
80  |  |   while (const char* absl_nullable absl_log_internal_qcheck_op_result =     \  | 
81  |  |              ::absl::log_internal::name##Impl(                              \  | 
82  |  |                  ::absl::log_internal::GetReferenceableValue(val1),         \  | 
83  |  |                  ::absl::log_internal::GetReferenceableValue(val2),         \  | 
84  |  |                  ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(                    \  | 
85  |  |                      val1_text " " #op " " val2_text)))                     \  | 
86  |  |     ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                     \  | 
87  |  |   ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \  | 
88  |  |                                absl_log_internal_qcheck_op_result))         \  | 
89  |  |       .InternalStream()  | 
90  |  | #define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2,     \  | 
91  |  |                                       s2_text)                                 \  | 
92  |  |   while (const char* absl_nullable absl_log_internal_check_strop_result =      \  | 
93  |  |              ::absl::log_internal::Check##func##expected##Impl(                \  | 
94  |  |                  (s1), (s2),                                                   \  | 
95  |  |                  ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op        \  | 
96  |  |                                                                 " " s2_text))) \  | 
97  |  |     ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \  | 
98  |  |   ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>(     \  | 
99  |  |                               absl_log_internal_check_strop_result))           \  | 
100  |  |       .InternalStream()  | 
101  |  | #define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2,    \  | 
102  |  |                                        s2_text)                                \  | 
103  |  |   while (const char* absl_nullable absl_log_internal_qcheck_strop_result =     \  | 
104  |  |              ::absl::log_internal::Check##func##expected##Impl(                \  | 
105  |  |                  (s1), (s2),                                                   \  | 
106  |  |                  ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op        \  | 
107  |  |                                                                 " " s2_text))) \  | 
108  |  |     ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                        \  | 
109  |  |   ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>(    \  | 
110  |  |                                absl_log_internal_qcheck_strop_result))         \  | 
111  |  |       .InternalStream()  | 
112  |  |  | 
113  |  | // This one is tricky:  | 
114  |  | // * We must evaluate `val` exactly once, yet we need to do two things with it:  | 
115  |  | //   evaluate `.ok()` and (sometimes) `.ToString()`.  | 
116  |  | // * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.  | 
117  |  | // * `val` might be e.g. `ATemporary().GetStatus()`, which may return a  | 
118  |  | //   reference to a member of `ATemporary` that is only valid until the end of  | 
119  |  | //   the full expression.  | 
120  |  | // * We don't want this file to depend on `absl::Status` `#include`s or linkage,  | 
121  |  | //   nor do we want to move the definition to status and introduce a dependency  | 
122  |  | //   in the other direction.  We can be assured that callers must already have a  | 
123  |  | //   `Status` and the necessary `#include`s and linkage.  | 
124  |  | // * Callsites should be small and fast (at least when `val.ok()`): one branch,  | 
125  |  | //   minimal stack footprint.  | 
126  |  | //   * In particular, the string concat stuff should be out-of-line and emitted  | 
127  |  | //     in only one TU to save linker input size  | 
128  |  | // * We want the `val.ok()` check inline so static analyzers and optimizers can  | 
129  |  | //   see it.  | 
130  |  | // * As usual, no braces so we can stream into the expansion with `operator<<`.  | 
131  |  | // * Also as usual, it must expand to a single (partial) statement with no  | 
132  |  | //   ambiguous-else problems.  | 
133  |  | // * When stripped by `ABSL_MIN_LOG_LEVEL`, we must discard the `<expr> is OK`  | 
134  |  | //   string literal and abort without doing any streaming.  We don't need to  | 
135  |  | //   strip the call to stringify the non-ok `Status` as long as we don't log it;  | 
136  |  | //   dropping the `Status`'s message text is out of scope.  | 
137  |  | #define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text)                         \  | 
138  |  |   for (::std::pair<const ::absl::Status* absl_nonnull,                    \  | 
139  |  |                    const char* absl_nonnull>                              \  | 
140  |  |            absl_log_internal_check_ok_goo;                                \  | 
141  |  |        absl_log_internal_check_ok_goo.first =                             \  | 
142  |  |            ::absl::log_internal::AsStatus(val),                           \  | 
143  |  |        absl_log_internal_check_ok_goo.second =                            \  | 
144  |  |            ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())  \  | 
145  |  |                ? "" /* Don't use nullptr, to keep the annotation happy */ \  | 
146  |  |                : ::absl::status_internal::MakeCheckFailString(            \  | 
147  |  |                      absl_log_internal_check_ok_goo.first,                \  | 
148  |  |                      ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text      \  | 
149  |  |                                                             " is OK")),   \  | 
150  |  |        !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)   \  | 
151  |  |     ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                    \  | 
152  |  |   ABSL_LOG_INTERNAL_CHECK(absl_log_internal_check_ok_goo.second)          \  | 
153  |  |       .InternalStream()  | 
154  |  | #define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text)                        \  | 
155  |  |   for (::std::pair<const ::absl::Status* absl_nonnull,                    \  | 
156  |  |                    const char* absl_nonnull>                              \  | 
157  |  |            absl_log_internal_qcheck_ok_goo;                               \  | 
158  |  |        absl_log_internal_qcheck_ok_goo.first =                            \  | 
159  |  |            ::absl::log_internal::AsStatus(val),                           \  | 
160  |  |        absl_log_internal_qcheck_ok_goo.second =                           \  | 
161  |  |            ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok()) \  | 
162  |  |                ? "" /* Don't use nullptr, to keep the annotation happy */ \  | 
163  |  |                : ::absl::status_internal::MakeCheckFailString(            \  | 
164  |  |                      absl_log_internal_qcheck_ok_goo.first,               \  | 
165  |  |                      ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text      \  | 
166  |  |                                                             " is OK")),   \  | 
167  |  |        !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());)  \  | 
168  |  |     ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                   \  | 
169  |  |   ABSL_LOG_INTERNAL_QCHECK(absl_log_internal_qcheck_ok_goo.second)        \  | 
170  |  |       .InternalStream()  | 
171  |  |  | 
172  |  | namespace absl { | 
173  |  | ABSL_NAMESPACE_BEGIN  | 
174  |  |  | 
175  |  | class Status;  | 
176  |  | template <typename T>  | 
177  |  | class StatusOr;  | 
178  |  |  | 
179  |  | namespace status_internal { | 
180  |  | ABSL_ATTRIBUTE_PURE_FUNCTION const char* absl_nonnull MakeCheckFailString(  | 
181  |  |     const absl::Status* absl_nonnull status, const char* absl_nonnull prefix);  | 
182  |  | }  // namespace status_internal  | 
183  |  |  | 
184  |  | namespace log_internal { | 
185  |  |  | 
186  |  | // Convert a Status or a StatusOr to its underlying status value.  | 
187  |  | //  | 
188  |  | // (This implementation does not require a dep on absl::Status to work.)  | 
189  | 0  | inline const absl::Status* absl_nonnull AsStatus(const absl::Status& s) { | 
190  | 0  |   return &s;  | 
191  | 0  | }  | 
192  |  | template <typename T>  | 
193  |  | const absl::Status* absl_nonnull AsStatus(const absl::StatusOr<T>& s) { | 
194  |  |   return &s.status();  | 
195  |  | }  | 
196  |  |  | 
197  |  | // A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.  | 
198  |  | // See `MakeCheckOpString` for sample usage.  | 
199  |  | class CheckOpMessageBuilder final { | 
200  |  |  public:  | 
201  |  |   // Inserts `exprtext` and ` (` to the stream.  | 
202  |  |   explicit CheckOpMessageBuilder(const char* absl_nonnull exprtext);  | 
203  | 0  |   ~CheckOpMessageBuilder() = default;  | 
204  |  |   // For inserting the first variable.  | 
205  | 0  |   std::ostream& ForVar1() { return stream_; } | 
206  |  |   // For inserting the second variable (adds an intermediate ` vs. `).  | 
207  |  |   std::ostream& ForVar2();  | 
208  |  |   // Get the result (inserts the closing `)`).  | 
209  |  |   const char* absl_nonnull NewString();  | 
210  |  |  | 
211  |  |  private:  | 
212  |  |   std::ostringstream stream_;  | 
213  |  | };  | 
214  |  |  | 
215  |  | // This formats a value for a failing `CHECK_XX` statement.  Ordinarily, it uses  | 
216  |  | // the definition for `operator<<`, with a few special cases below.  | 
217  |  | template <typename T>  | 
218  | 0  | inline void MakeCheckOpValueString(std::ostream& os, const T& v) { | 
219  | 0  |   os << log_internal::NullGuard<T>::Guard(v);  | 
220  | 0  | } Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<bool>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<long>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, long const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<unsigned long>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, unsigned long const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<float>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, float const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<double>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, double const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<std::__1::basic_string_view<char, std::__1::char_traits<char> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<char const*>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const* const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<signed char const*>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, signed char const* const&) Unexecuted instantiation: void absl::log_internal::MakeCheckOpValueString<unsigned char const*>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, unsigned char const* const&)  | 
221  |  |  | 
222  |  | // Overloads for char types provide readable values for unprintable characters.  | 
223  |  | void MakeCheckOpValueString(std::ostream& os, char v);  | 
224  |  | void MakeCheckOpValueString(std::ostream& os, signed char v);  | 
225  |  | void MakeCheckOpValueString(std::ostream& os, unsigned char v);  | 
226  |  | void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p);  | 
227  |  |  | 
228  |  | // A wrapper for types that have no operator<<.  | 
229  |  | struct UnprintableWrapper { | 
230  |  |   template <typename T>  | 
231  |  |   explicit UnprintableWrapper(const T&) {} | 
232  |  |  | 
233  |  |   friend std::ostream& operator<<(std::ostream& os, UnprintableWrapper);  | 
234  |  | };  | 
235  |  |  | 
236  |  | namespace detect_specialization { | 
237  |  |  | 
238  |  | // MakeCheckOpString is being specialized for every T and U pair that is being  | 
239  |  | // passed to the CHECK_op macros. However, there is a lot of redundancy in these  | 
240  |  | // specializations that creates unnecessary library and binary bloat.  | 
241  |  | // The number of instantiations tends to be O(n^2) because we have two  | 
242  |  | // independent inputs. This technique works by reducing `n`.  | 
243  |  | //  | 
244  |  | // Most user-defined types being passed to CHECK_op end up being printed as a  | 
245  |  | // builtin type. For example, enums tend to be implicitly converted to its  | 
246  |  | // underlying type when calling operator<<, and pointers are printed with the  | 
247  |  | // `const void*` overload.  | 
248  |  | // To reduce the number of instantiations we coerce these values before calling  | 
249  |  | // MakeCheckOpString instead of inside it.  | 
250  |  | //  | 
251  |  | // To detect if this coercion is needed, we duplicate all the relevant  | 
252  |  | // operator<< overloads as specified in the standard, just in a different  | 
253  |  | // namespace. If the call to `stream << value` becomes ambiguous, it means that  | 
254  |  | // one of these overloads is the one selected by overload resolution. We then  | 
255  |  | // do overload resolution again just with our overload set to see which one gets  | 
256  |  | // selected. That tells us which type to coerce to.  | 
257  |  | // If the augmented call was not ambiguous, it means that none of these were  | 
258  |  | // selected and we can't coerce the input.  | 
259  |  | //  | 
260  |  | // As a secondary step to reduce code duplication, we promote integral types to  | 
261  |  | // their 64-bit variant. This does not change the printed value, but reduces the  | 
262  |  | // number of instantiations even further. Promoting an integer is very cheap at  | 
263  |  | // the call site.  | 
264  |  | int64_t operator<<(std::ostream&, short value);           // NOLINT  | 
265  |  | int64_t operator<<(std::ostream&, unsigned short value);  // NOLINT  | 
266  |  | int64_t operator<<(std::ostream&, int value);  | 
267  |  | int64_t operator<<(std::ostream&, unsigned int value);  | 
268  |  | int64_t operator<<(std::ostream&, long value);                 // NOLINT  | 
269  |  | uint64_t operator<<(std::ostream&, unsigned long value);       // NOLINT  | 
270  |  | int64_t operator<<(std::ostream&, long long value);            // NOLINT  | 
271  |  | uint64_t operator<<(std::ostream&, unsigned long long value);  // NOLINT  | 
272  |  | float operator<<(std::ostream&, float value);  | 
273  |  | double operator<<(std::ostream&, double value);  | 
274  |  | long double operator<<(std::ostream&, long double value);  | 
275  |  | bool operator<<(std::ostream&, bool value);  | 
276  |  | const void* absl_nullable operator<<(std::ostream&,  | 
277  |  |                                      const void* absl_nullable value);  | 
278  |  | const void* absl_nullable operator<<(std::ostream&, std::nullptr_t);  | 
279  |  |  | 
280  |  | // These `char` overloads are specified like this in the standard, so we have to  | 
281  |  | // write them exactly the same to ensure the call is ambiguous.  | 
282  |  | // If we wrote it in a different way (eg taking std::ostream instead of the  | 
283  |  | // template) then one call might have a higher rank than the other and it would  | 
284  |  | // not be ambiguous.  | 
285  |  | template <typename Traits>  | 
286  |  | char operator<<(std::basic_ostream<char, Traits>&, char);  | 
287  |  | template <typename Traits>  | 
288  |  | signed char operator<<(std::basic_ostream<char, Traits>&, signed char);  | 
289  |  | template <typename Traits>  | 
290  |  | unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);  | 
291  |  | template <typename Traits>  | 
292  |  | const char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,  | 
293  |  |                                     const char* absl_nonnull);  | 
294  |  | template <typename Traits>  | 
295  |  | const signed char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,  | 
296  |  |                                            const signed char* absl_nonnull);  | 
297  |  | template <typename Traits>  | 
298  |  | const unsigned char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,  | 
299  |  |                                              const unsigned char* absl_nonnull);  | 
300  |  |  | 
301  |  | // This overload triggers when the call is not ambiguous.  | 
302  |  | // It means that T is being printed with some overload not on this list.  | 
303  |  | // We keep the value as `const T&`.  | 
304  |  | template <typename T, typename = decltype(std::declval<std::ostream&>()  | 
305  |  |                                           << std::declval<const T&>())>  | 
306  |  | const T& Detect(int);  | 
307  |  |  | 
308  |  | // This overload triggers when the call is ambiguous.  | 
309  |  | // It means that T is either one from this list or printed as one from this  | 
310  |  | // list. Eg an unscoped enum that decays to `int` for printing.  | 
311  |  | // We ask the overload set to give us the type we want to convert it to.  | 
312  |  | template <typename T>  | 
313  |  | decltype(detect_specialization::operator<<(  | 
314  |  |     std::declval<std::ostream&>(), std::declval<const T&>())) Detect(char);  | 
315  |  |  | 
316  |  | // A sink for AbslStringify which redirects everything to a std::ostream.  | 
317  |  | class StringifySink { | 
318  |  |  public:  | 
319  |  |   explicit StringifySink(std::ostream& os ABSL_ATTRIBUTE_LIFETIME_BOUND);  | 
320  |  |  | 
321  |  |   void Append(absl::string_view text);  | 
322  |  |   void Append(size_t length, char ch);  | 
323  |  |   friend void AbslFormatFlush(StringifySink* absl_nonnull sink,  | 
324  |  |                               absl::string_view text);  | 
325  |  |  | 
326  |  |  private:  | 
327  |  |   std::ostream& os_;  | 
328  |  | };  | 
329  |  |  | 
330  |  | // Wraps a type implementing AbslStringify, and implements operator<<.  | 
331  |  | template <typename T>  | 
332  |  | class StringifyToStreamWrapper { | 
333  |  |  public:  | 
334  |  |   explicit StringifyToStreamWrapper(const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND)  | 
335  |  |       : v_(v) {} | 
336  |  |  | 
337  |  |   friend std::ostream& operator<<(std::ostream& os,  | 
338  |  |                                   const StringifyToStreamWrapper& wrapper) { | 
339  |  |     StringifySink sink(os);  | 
340  |  |     AbslStringify(sink, wrapper.v_);  | 
341  |  |     return os;  | 
342  |  |   }  | 
343  |  |  | 
344  |  |  private:  | 
345  |  |   const T& v_;  | 
346  |  | };  | 
347  |  |  | 
348  |  | // This overload triggers when T implements AbslStringify.  | 
349  |  | // StringifyToStreamWrapper is used to allow MakeCheckOpString to use  | 
350  |  | // operator<<.  | 
351  |  | template <typename T>  | 
352  |  | std::enable_if_t<HasAbslStringify<T>::value,  | 
353  |  |                  StringifyToStreamWrapper<T>>  | 
354  |  | Detect(...);  // Ellipsis has lowest preference when int passed.  | 
355  |  |  | 
356  |  | // This overload triggers when T is neither possible to print nor an enum.  | 
357  |  | template <typename T>  | 
358  |  | std::enable_if_t<std::negation_v<std::disjunction<  | 
359  |  |                      std::is_convertible<T, int>, std::is_enum<T>,  | 
360  |  |                      std::is_pointer<T>, std::is_same<T, std::nullptr_t>,  | 
361  |  |                      HasOstreamOperator<T>, HasAbslStringify<T>>>,  | 
362  |  |                  UnprintableWrapper>  | 
363  |  | Detect(...);  | 
364  |  |  | 
365  |  | // Equivalent to the updated std::underlying_type from C++20, which is no  | 
366  |  | // longer undefined behavior for non-enum types.  | 
367  |  | template <typename T, typename EnableT = void>  | 
368  |  | struct UnderlyingType {}; | 
369  |  |  | 
370  |  | template <typename T>  | 
371  |  | struct UnderlyingType<T, std::enable_if_t<std::is_enum_v<T>>> { | 
372  |  |   using type = std::underlying_type_t<T>;  | 
373  |  | };  | 
374  |  | template <typename T>  | 
375  |  | using UnderlyingTypeT = typename UnderlyingType<T>::type;  | 
376  |  |  | 
377  |  | // This overload triggers when T is a scoped enum that has not defined an output  | 
378  |  | // stream operator (operator<<) or AbslStringify. It causes the enum value to be  | 
379  |  | // converted to a type that can be streamed. For consistency with other enums, a  | 
380  |  | // scoped enum backed by a bool or char is converted to its underlying type, and  | 
381  |  | // one backed by another integer is converted to (u)int64_t.  | 
382  |  | template <typename T>  | 
383  |  | std::enable_if_t<  | 
384  |  |     std::conjunction_v<std::is_enum<T>,  | 
385  |  |                        std::negation<std::is_convertible<T, int>>,  | 
386  |  |                        std::negation<HasOstreamOperator<T>>,  | 
387  |  |                        std::negation<HasAbslStringify<T>>>,  | 
388  |  |     std::conditional_t<std::is_same_v<UnderlyingTypeT<T>, bool> ||  | 
389  |  |                            std::is_same_v<UnderlyingTypeT<T>, char> ||  | 
390  |  |                            std::is_same_v<UnderlyingTypeT<T>, signed char> ||  | 
391  |  |                            std::is_same_v<UnderlyingTypeT<T>, unsigned char>,  | 
392  |  |                        UnderlyingTypeT<T>,  | 
393  |  |                        std::conditional_t<std::is_signed_v<UnderlyingTypeT<T>>,  | 
394  |  |                                           int64_t, uint64_t>>>  | 
395  |  | Detect(...);  | 
396  |  |  | 
397  |  | template <typename T>  | 
398  |  | using Detected = decltype(Detect<T>(0));  | 
399  |  | }  // namespace detect_specialization  | 
400  |  |  | 
401  |  | // If the comparison will happen as pointers, decay `char*` arguments to `void*`  | 
402  |  | // when printing them. There is no evidence that they are a NULL terminated  | 
403  |  | // C-String so printing them as such could lead to UB, and more importantly we  | 
404  |  | // compared pointers so showing the pointers is a better result.  | 
405  |  | template <typename T>  | 
406  | 0  | constexpr bool IsCharStarOrVoidStar() { | 
407  | 0  |   if constexpr (std::is_reference_v<T>) { | 
408  | 0  |     return IsCharStarOrVoidStar<std::remove_reference_t<T>>();  | 
409  | 0  |   } else if constexpr (std::is_array_v<T>) { | 
410  | 0  |     return IsCharStarOrVoidStar<std::decay_t<T>>();  | 
411  | 0  |   } else { | 
412  | 0  |     using U = std::remove_const_t<std::remove_pointer_t<T>>;  | 
413  | 0  |     return std::is_pointer_v<T> &&  | 
414  | 0  |         (std::is_same_v<char, U> || std::is_same_v<unsigned char, U> ||  | 
415  | 0  |          std::is_same_v<signed char, U> || std::is_void_v<U>);  | 
416  | 0  |   }  | 
417  | 0  | } Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<long>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<bool>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<unsigned long>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<float>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<double>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<char>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<unsigned char>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<std::__1::basic_string_view<char, std::__1::char_traits<char> > const>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<char const*>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<signed char const*>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<unsigned char const*>() Unexecuted instantiation: bool absl::log_internal::IsCharStarOrVoidStar<void const*>()  | 
418  |  |  | 
419  |  | template <typename T1, typename T2,  | 
420  |  |           typename U1 = detect_specialization::Detected<T1>,  | 
421  |  |           typename U2 = detect_specialization::Detected<T2>>  | 
422  |  | using CheckOpStreamType =  | 
423  |  |     std::conditional_t<IsCharStarOrVoidStar<U1>() && IsCharStarOrVoidStar<U2>(),  | 
424  |  |                        const void*, U1>;  | 
425  |  |  | 
426  |  | // Build the error message string.  Specify no inlining for code size.  | 
427  |  | template <typename T1, typename T2>  | 
428  |  | ABSL_ATTRIBUTE_RETURNS_NONNULL const char* absl_nonnull MakeCheckOpString(  | 
429  |  |     T1 v1, T2 v2, const char* absl_nonnull exprtext) ABSL_ATTRIBUTE_NOINLINE;  | 
430  |  |  | 
431  |  | template <typename T1, typename T2>  | 
432  |  | const char* absl_nonnull MakeCheckOpString(T1 v1, T2 v2,  | 
433  | 0  |                                            const char* absl_nonnull exprtext) { | 
434  |  |   if constexpr (std::is_same_v<CheckOpStreamType<T1, T2>, UnprintableWrapper> &&  | 
435  |  |                 std::is_same_v<CheckOpStreamType<T2, T1>, UnprintableWrapper>) { | 
436  |  |     // No sense printing " (UNPRINTABLE vs. UNPRINTABLE)"  | 
437  |  |     return exprtext;  | 
438  | 0  |   } else { | 
439  | 0  |     CheckOpMessageBuilder comb(exprtext);  | 
440  | 0  |     MakeCheckOpValueString(comb.ForVar1(), v1);  | 
441  | 0  |     MakeCheckOpValueString(comb.ForVar2(), v2);  | 
442  | 0  |     return comb.NewString();  | 
443  | 0  |   }  | 
444  | 0  | } Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<bool, bool>(bool, bool, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<long, long>(long, long, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<unsigned long, unsigned long>(unsigned long, unsigned long, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<float, float>(float, float, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<double, double>(double, double, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<char, char>(char, char, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<unsigned char, unsigned char>(unsigned char, unsigned char, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&>(std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<char const*, char const*>(char const*, char const*, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<signed char const*, signed char const*>(signed char const*, signed char const*, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<unsigned char const*, unsigned char const*>(unsigned char const*, unsigned char const*, char const*) Unexecuted instantiation: char const* absl::log_internal::MakeCheckOpString<void const*, void const*>(void const*, void const*, char const*)  | 
445  |  |  | 
446  |  | // Add a few commonly used instantiations as extern to reduce size of objects  | 
447  |  | // files.  | 
448  |  | #define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \  | 
449  |  |   extern template const char* absl_nonnull MakeCheckOpString(   \  | 
450  |  |       x, x, const char* absl_nonnull)  | 
451  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);  | 
452  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);  | 
453  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);  | 
454  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);  | 
455  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);  | 
456  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);  | 
457  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);  | 
458  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);  | 
459  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);  | 
460  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char* absl_nonnull);  | 
461  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(  | 
462  |  |     const signed char* absl_nonnull);  | 
463  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(  | 
464  |  |     const unsigned char* absl_nonnull);  | 
465  |  | ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void* absl_nonnull);  | 
466  |  | #undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN  | 
467  |  |  | 
468  |  | // `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result  | 
469  |  | // string iff `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`, instead returning an empty  | 
470  |  | // string.  | 
471  |  | #ifdef ABSL_MIN_LOG_LEVEL  | 
472  |  | #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \  | 
473  |  |   ((::absl::LogSeverity::kFatal >=                                       \  | 
474  |  |     static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL))         \  | 
475  |  |        ? MakeCheckOpString<U1, U2>(v1, v2, exprtext)                     \  | 
476  |  |        : "")  | 
477  |  | #else  | 
478  |  | #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \  | 
479  |  |   MakeCheckOpString<U1, U2>(v1, v2, exprtext)  | 
480  |  | #endif  | 
481  |  |  | 
482  |  | // Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family.  The  | 
483  |  | // `(int, int)` override works around the issue that the compiler will not  | 
484  |  | // instantiate the template version of the function on values of unnamed enum  | 
485  |  | // type.  | 
486  |  | #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op)                          \  | 
487  |  |   template <typename T1, typename T2>                                      \  | 
488  |  |   inline constexpr const char* absl_nullable name##Impl(                   \  | 
489  | 0  |       const T1& v1, const T2& v2, const char* absl_nonnull exprtext) {     \ | 
490  | 0  |     using U1 = CheckOpStreamType<T1, T2>;                                  \  | 
491  | 0  |     using U2 = CheckOpStreamType<T2, T1>;                                  \  | 
492  | 0  |     return ABSL_PREDICT_TRUE(v1 op v2)                                     \  | 
493  | 0  |                ? nullptr                                                   \  | 
494  | 0  |                : ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, U1(v1),    \  | 
495  | 0  |                                                         U2(v2), exprtext); \  | 
496  | 0  |   }                                                                        \ Unexecuted instantiation: char const* absl::log_internal::Check_EQImpl<int, int>(int const&, int const&, char const*) Unexecuted instantiation: char const* absl::log_internal::Check_NEImpl<int, int>(int const&, int const&, char const*) Unexecuted instantiation: char const* absl::log_internal::Check_LEImpl<int, int>(int const&, int const&, char const*) Unexecuted instantiation: char const* absl::log_internal::Check_LTImpl<int, int>(int const&, int const&, char const*) Unexecuted instantiation: char const* absl::log_internal::Check_GEImpl<int, int>(int const&, int const&, char const*) Unexecuted instantiation: char const* absl::log_internal::Check_GTImpl<int, int>(int const&, int const&, char const*)  | 
497  |  |   inline constexpr const char* absl_nullable name##Impl(                   \  | 
498  | 0  |       int v1, int v2, const char* absl_nonnull exprtext) {                 \ | 
499  | 0  |     return name##Impl<int, int>(v1, v2, exprtext);                         \  | 
500  | 0  |   } Unexecuted instantiation: absl::log_internal::Check_EQImpl(int, int, char const*) Unexecuted instantiation: absl::log_internal::Check_NEImpl(int, int, char const*) Unexecuted instantiation: absl::log_internal::Check_LEImpl(int, int, char const*) Unexecuted instantiation: absl::log_internal::Check_LTImpl(int, int, char const*) Unexecuted instantiation: absl::log_internal::Check_GEImpl(int, int, char const*) Unexecuted instantiation: absl::log_internal::Check_GTImpl(int, int, char const*)  | 
501  |  |  | 
502  |  | ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)  | 
503  |  | ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)  | 
504  |  | ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)  | 
505  |  | ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)  | 
506  |  | ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)  | 
507  |  | ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)  | 
508  |  | #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT  | 
509  |  | #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL  | 
510  |  |  | 
511  |  | const char* absl_nullable CheckstrcmptrueImpl(  | 
512  |  |     const char* absl_nullable s1, const char* absl_nullable s2,  | 
513  |  |     const char* absl_nonnull exprtext);  | 
514  |  | const char* absl_nullable CheckstrcmpfalseImpl(  | 
515  |  |     const char* absl_nullable s1, const char* absl_nullable s2,  | 
516  |  |     const char* absl_nonnull exprtext);  | 
517  |  | const char* absl_nullable CheckstrcasecmptrueImpl(  | 
518  |  |     const char* absl_nullable s1, const char* absl_nullable s2,  | 
519  |  |     const char* absl_nonnull exprtext);  | 
520  |  | const char* absl_nullable CheckstrcasecmpfalseImpl(  | 
521  |  |     const char* absl_nullable s1, const char* absl_nullable s2,  | 
522  |  |     const char* absl_nonnull exprtext);  | 
523  |  |  | 
524  |  | // `CHECK_EQ` and friends want to pass their arguments by reference, however  | 
525  |  | // this winds up exposing lots of cases where people have defined and  | 
526  |  | // initialized static const data members but never declared them (i.e. in a .cc  | 
527  |  | // file), meaning they are not referenceable.  This function avoids that problem  | 
528  |  | // for integers (the most common cases) by overloading for every primitive  | 
529  |  | // integer type, even the ones we discourage, and returning them by value.  | 
530  |  | // NOLINTBEGIN(runtime/int)  | 
531  |  | // NOLINTBEGIN(google-runtime-int)  | 
532  |  | template <typename T>  | 
533  |  | inline constexpr const T& GetReferenceableValue(const T& t) { | 
534  |  |   return t;  | 
535  |  | }  | 
536  | 0  | inline constexpr char GetReferenceableValue(char t) { return t; } | 
537  | 0  | inline constexpr unsigned char GetReferenceableValue(unsigned char t) { | 
538  | 0  |   return t;  | 
539  | 0  | }  | 
540  | 0  | inline constexpr signed char GetReferenceableValue(signed char t) { return t; } | 
541  | 0  | inline constexpr short GetReferenceableValue(short t) { return t; } | 
542  | 0  | inline constexpr unsigned short GetReferenceableValue(unsigned short t) { | 
543  | 0  |   return t;  | 
544  | 0  | }  | 
545  | 0  | inline constexpr int GetReferenceableValue(int t) { return t; } | 
546  | 0  | inline constexpr unsigned int GetReferenceableValue(unsigned int t) { | 
547  | 0  |   return t;  | 
548  | 0  | }  | 
549  | 0  | inline constexpr long GetReferenceableValue(long t) { return t; } | 
550  | 0  | inline constexpr unsigned long GetReferenceableValue(unsigned long t) { | 
551  | 0  |   return t;  | 
552  | 0  | }  | 
553  | 0  | inline constexpr long long GetReferenceableValue(long long t) { return t; } | 
554  |  | inline constexpr unsigned long long GetReferenceableValue(  | 
555  | 0  |     unsigned long long t) { | 
556  | 0  |   return t;  | 
557  | 0  | }  | 
558  |  | // NOLINTEND(google-runtime-int)  | 
559  |  | // NOLINTEND(runtime/int)  | 
560  |  |  | 
561  |  | }  // namespace log_internal  | 
562  |  | ABSL_NAMESPACE_END  | 
563  |  | }  // namespace absl  | 
564  |  |  | 
565  |  | #endif  // ABSL_LOG_INTERNAL_CHECK_OP_H_  |