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 <ostream>
28 #include <sstream>
29 #include <string>
30 #include <utility>
31
32 #include "absl/base/attributes.h"
33 #include "absl/base/config.h"
34 #include "absl/base/optimization.h"
35 #include "absl/log/internal/nullguard.h"
36 #include "absl/log/internal/nullstream.h"
37 #include "absl/log/internal/strip.h"
38
39 // `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that
40 // should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.
41 #ifdef ABSL_MIN_LOG_LEVEL
42 #define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) \
43 (::absl::LogSeverity::kFatal >= \
44 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
45 ? (literal) \
46 : "")
47 #else
48 #define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)
49 #endif
50
51 #ifdef NDEBUG
52 // `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing. However, we
53 // still want the compiler to parse `x` and `y`, because we don't want to lose
54 // potentially useful errors and warnings.
55 #define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y) \
56 while (false && ((void)(x), (void)(y), 0)) \
57 ::absl::log_internal::NullStream().InternalStream()
58 #endif
59
60 #define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val2) \
61 while ( \
62 ::std::string* absl_log_internal_check_op_result ABSL_ATTRIBUTE_UNUSED = \
63 ::absl::log_internal::name##Impl( \
64 ::absl::log_internal::GetReferenceableValue(val1), \
65 ::absl::log_internal::GetReferenceableValue(val2), \
66 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val1 " " #op \
67 " " #val2))) \
68 ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_op_result).InternalStream()
69 #define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val2) \
70 while (::std::string* absl_log_internal_qcheck_op_result = \
71 ::absl::log_internal::name##Impl( \
72 ::absl::log_internal::GetReferenceableValue(val1), \
73 ::absl::log_internal::GetReferenceableValue(val2), \
74 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val1 " " #op \
75 " " #val2))) \
76 ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_op_result).InternalStream()
77 #define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s2) \
78 while (::std::string* absl_log_internal_check_strop_result = \
79 ::absl::log_internal::Check##func##expected##Impl( \
80 (s1), (s2), \
81 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#s1 " " #op " " #s2))) \
82 ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_strop_result) \
83 .InternalStream()
84 #define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s2) \
85 while (::std::string* absl_log_internal_qcheck_strop_result = \
86 ::absl::log_internal::Check##func##expected##Impl( \
87 (s1), (s2), \
88 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#s1 " " #op " " #s2))) \
89 ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_strop_result) \
90 .InternalStream()
91 // This one is tricky:
92 // * We must evaluate `val` exactly once, yet we need to do two things with it:
93 // evaluate `.ok()` and (sometimes) `.ToString()`.
94 // * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.
95 // * `val` might be e.g. `ATemporary().GetStatus()`, which may return a
96 // reference to a member of `ATemporary` that is only valid until the end of
97 // the full expression.
98 // * We don't want this file to depend on `absl::Status` `#include`s or linkage,
99 // nor do we want to move the definition to status and introduce a dependency
100 // in the other direction. We can be assured that callers must already have a
101 // `Status` and the necessary `#include`s and linkage.
102 // * Callsites should be small and fast (at least when `val.ok()`): one branch,
103 // minimal stack footprint.
104 // * In particular, the string concat stuff should be out-of-line and emitted
105 // in only one TU to save linker input size
106 // * We want the `val.ok()` check inline so static analyzers and optimizers can
107 // see it.
108 // * As usual, no braces so we can stream into the expansion with `operator<<`.
109 // * Also as usual, it must expand to a single (partial) statement with no
110 // ambiguous-else problems.
111 #define ABSL_LOG_INTERNAL_CHECK_OK(val) \
112 for (::std::pair<const ::absl::Status*, ::std::string*> \
113 absl_log_internal_check_ok_goo; \
114 absl_log_internal_check_ok_goo.first = \
115 ::absl::log_internal::AsStatus(val), \
116 absl_log_internal_check_ok_goo.second = \
117 ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
118 ? nullptr \
119 : ::absl::status_internal::MakeCheckFailString( \
120 absl_log_internal_check_ok_goo.first, \
121 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val " is OK")), \
122 !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
123 ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second) \
124 .InternalStream()
125 #define ABSL_LOG_INTERNAL_QCHECK_OK(val) \
126 for (::std::pair<const ::absl::Status*, ::std::string*> \
127 absl_log_internal_check_ok_goo; \
128 absl_log_internal_check_ok_goo.first = \
129 ::absl::log_internal::AsStatus(val), \
130 absl_log_internal_check_ok_goo.second = \
131 ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
132 ? nullptr \
133 : ::absl::status_internal::MakeCheckFailString( \
134 absl_log_internal_check_ok_goo.first, \
135 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val " is OK")), \
136 !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
137 ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_check_ok_goo.second) \
138 .InternalStream()
139
140 namespace absl {
141 ABSL_NAMESPACE_BEGIN
142
143 class Status;
144 template <typename T>
145 class StatusOr;
146
147 namespace status_internal {
148 std::string* MakeCheckFailString(const absl::Status* status,
149 const char* prefix);
150 } // namespace status_internal
151
152 namespace log_internal {
153
154 // Convert a Status or a StatusOr to its underlying status value.
155 //
156 // (This implementation does not require a dep on absl::Status to work.)
AsStatus(const absl::Status & s)157 inline const absl::Status* AsStatus(const absl::Status& s) { return &s; }
158 template <typename T>
AsStatus(const absl::StatusOr<T> & s)159 const absl::Status* AsStatus(const absl::StatusOr<T>& s) {
160 return &s.status();
161 }
162
163 // A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.
164 // See `MakeCheckOpString` for sample usage.
165 class CheckOpMessageBuilder final {
166 public:
167 // Inserts `exprtext` and ` (` to the stream.
168 explicit CheckOpMessageBuilder(const char* exprtext);
169 ~CheckOpMessageBuilder() = default;
170 // For inserting the first variable.
ForVar1()171 std::ostream& ForVar1() { return stream_; }
172 // For inserting the second variable (adds an intermediate ` vs. `).
173 std::ostream& ForVar2();
174 // Get the result (inserts the closing `)`).
175 std::string* NewString();
176
177 private:
178 std::ostringstream stream_;
179 };
180
181 // This formats a value for a failing `CHECK_XX` statement. Ordinarily, it uses
182 // the definition for `operator<<`, with a few special cases below.
183 template <typename T>
MakeCheckOpValueString(std::ostream & os,const T & v)184 inline void MakeCheckOpValueString(std::ostream& os, const T& v) {
185 os << log_internal::NullGuard<T>::Guard(v);
186 }
187
188 // Overloads for char types provide readable values for unprintable characters.
189 void MakeCheckOpValueString(std::ostream& os, char v);
190 void MakeCheckOpValueString(std::ostream& os, signed char v);
191 void MakeCheckOpValueString(std::ostream& os, unsigned char v);
192 void MakeCheckOpValueString(std::ostream& os, const void* p);
193
194 namespace detect_specialization {
195
196 // MakeCheckOpString is being specialized for every T and U pair that is being
197 // passed to the CHECK_op macros. However, there is a lot of redundancy in these
198 // specializations that creates unnecessary library and binary bloat.
199 // The number of instantiations tends to be O(n^2) because we have two
200 // independent inputs. This technique works by reducing `n`.
201 //
202 // Most user-defined types being passed to CHECK_op end up being printed as a
203 // builtin type. For example, enums tend to be implicitly converted to its
204 // underlying type when calling operator<<, and pointers are printed with the
205 // `const void*` overload.
206 // To reduce the number of instantiations we coerce these values before calling
207 // MakeCheckOpString instead of inside it.
208 //
209 // To detect if this coercion is needed, we duplicate all the relevant
210 // operator<< overloads as specified in the standard, just in a different
211 // namespace. If the call to `stream << value` becomes ambiguous, it means that
212 // one of these overloads is the one selected by overload resolution. We then
213 // do overload resolution again just with our overload set to see which one gets
214 // selected. That tells us which type to coerce to.
215 // If the augmented call was not ambiguous, it means that none of these were
216 // selected and we can't coerce the input.
217 //
218 // As a secondary step to reduce code duplication, we promote integral types to
219 // their 64-bit variant. This does not change the printed value, but reduces the
220 // number of instantiations even further. Promoting an integer is very cheap at
221 // the call site.
222 int64_t operator<<(std::ostream&, short value); // NOLINT
223 int64_t operator<<(std::ostream&, unsigned short value); // NOLINT
224 int64_t operator<<(std::ostream&, int value);
225 int64_t operator<<(std::ostream&, unsigned int value);
226 int64_t operator<<(std::ostream&, long value); // NOLINT
227 uint64_t operator<<(std::ostream&, unsigned long value); // NOLINT
228 int64_t operator<<(std::ostream&, long long value); // NOLINT
229 uint64_t operator<<(std::ostream&, unsigned long long value); // NOLINT
230 float operator<<(std::ostream&, float value);
231 double operator<<(std::ostream&, double value);
232 long double operator<<(std::ostream&, long double value);
233 bool operator<<(std::ostream&, bool value);
234 const void* operator<<(std::ostream&, const void* value);
235 const void* operator<<(std::ostream&, std::nullptr_t);
236
237 // These `char` overloads are specified like this in the standard, so we have to
238 // write them exactly the same to ensure the call is ambiguous.
239 // If we wrote it in a different way (eg taking std::ostream instead of the
240 // template) then one call might have a higher rank than the other and it would
241 // not be ambiguous.
242 template <typename Traits>
243 char operator<<(std::basic_ostream<char, Traits>&, char);
244 template <typename Traits>
245 signed char operator<<(std::basic_ostream<char, Traits>&, signed char);
246 template <typename Traits>
247 unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
248 template <typename Traits>
249 const char* operator<<(std::basic_ostream<char, Traits>&, const char*);
250 template <typename Traits>
251 const signed char* operator<<(std::basic_ostream<char, Traits>&,
252 const signed char*);
253 template <typename Traits>
254 const unsigned char* operator<<(std::basic_ostream<char, Traits>&,
255 const unsigned char*);
256
257 // This overload triggers when the call is not ambiguous.
258 // It means that T is being printed with some overload not on this list.
259 // We keep the value as `const T&`.
260 template <typename T, typename = decltype(std::declval<std::ostream&>()
261 << std::declval<const T&>())>
262 const T& Detect(int);
263
264 // This overload triggers when the call is ambiguous.
265 // It means that T is either one from this list or printed as one from this
266 // list. Eg an enum that decays to `int` for printing.
267 // We ask the overload set to give us the type we want to convert it to.
268 template <typename T>
269 decltype(detect_specialization::operator<<(std::declval<std::ostream&>(),
270 std::declval<const T&>()))
271 Detect(char);
272
273 } // namespace detect_specialization
274
275 template <typename T>
276 using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0));
277
278 // Build the error message string. Specify no inlining for code size.
279 template <typename T1, typename T2>
280 ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* MakeCheckOpString(
281 T1 v1, T2 v2, const char* exprtext) ABSL_ATTRIBUTE_NOINLINE;
282
283 template <typename T1, typename T2>
MakeCheckOpString(T1 v1,T2 v2,const char * exprtext)284 std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) {
285 CheckOpMessageBuilder comb(exprtext);
286 MakeCheckOpValueString(comb.ForVar1(), v1);
287 MakeCheckOpValueString(comb.ForVar2(), v2);
288 return comb.NewString();
289 }
290
291 // Add a few commonly used instantiations as extern to reduce size of objects
292 // files.
293 #define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
294 extern template std::string* MakeCheckOpString(x, x, const char*)
295 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
296 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
297 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
298 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);
299 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);
300 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);
301 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
302 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
303 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
304 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*);
305 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*);
306 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*);
307 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*);
308 #undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
309
310 // Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family. The
311 // `(int, int)` override works around the issue that the compiler will not
312 // instantiate the template version of the function on values of unnamed enum
313 // type.
314 #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op) \
315 template <typename T1, typename T2> \
316 inline constexpr ::std::string* name##Impl(const T1& v1, const T2& v2, \
317 const char* exprtext) { \
318 using U1 = CheckOpStreamType<T1>; \
319 using U2 = CheckOpStreamType<T2>; \
320 return ABSL_PREDICT_TRUE(v1 op v2) \
321 ? nullptr \
322 : MakeCheckOpString<U1, U2>(v1, v2, exprtext); \
323 } \
324 inline constexpr ::std::string* name##Impl(int v1, int v2, \
325 const char* exprtext) { \
326 return name##Impl<int, int>(v1, v2, exprtext); \
327 }
328
329 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)
330 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)
331 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)
332 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)
333 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)
334 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)
335 #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
336
337 std::string* CheckstrcmptrueImpl(const char* s1, const char* s2,
338 const char* exprtext);
339 std::string* CheckstrcmpfalseImpl(const char* s1, const char* s2,
340 const char* exprtext);
341 std::string* CheckstrcasecmptrueImpl(const char* s1, const char* s2,
342 const char* exprtext);
343 std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2,
344 const char* exprtext);
345
346 // `CHECK_EQ` and friends want to pass their arguments by reference, however
347 // this winds up exposing lots of cases where people have defined and
348 // initialized static const data members but never declared them (i.e. in a .cc
349 // file), meaning they are not referenceable. This function avoids that problem
350 // for integers (the most common cases) by overloading for every primitive
351 // integer type, even the ones we discourage, and returning them by value.
352 template <typename T>
GetReferenceableValue(const T & t)353 inline constexpr const T& GetReferenceableValue(const T& t) {
354 return t;
355 }
GetReferenceableValue(char t)356 inline constexpr char GetReferenceableValue(char t) { return t; }
GetReferenceableValue(unsigned char t)357 inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
358 return t;
359 }
GetReferenceableValue(signed char t)360 inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
GetReferenceableValue(short t)361 inline constexpr short GetReferenceableValue(short t) { return t; } // NOLINT
GetReferenceableValue(unsigned short t)362 inline constexpr unsigned short GetReferenceableValue( // NOLINT
363 unsigned short t) { // NOLINT
364 return t;
365 }
GetReferenceableValue(int t)366 inline constexpr int GetReferenceableValue(int t) { return t; }
GetReferenceableValue(unsigned int t)367 inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
GetReferenceableValue(long t)368 inline constexpr long GetReferenceableValue(long t) { return t; } // NOLINT
GetReferenceableValue(unsigned long t)369 inline constexpr unsigned long GetReferenceableValue( // NOLINT
370 unsigned long t) { // NOLINT
371 return t;
372 }
GetReferenceableValue(long long t)373 inline constexpr long long GetReferenceableValue(long long t) { // NOLINT
374 return t;
375 }
GetReferenceableValue(unsigned long long t)376 inline constexpr unsigned long long GetReferenceableValue( // NOLINT
377 unsigned long long t) { // NOLINT
378 return t;
379 }
380
381 } // namespace log_internal
382 ABSL_NAMESPACE_END
383 } // namespace absl
384
385 #endif // ABSL_LOG_INTERNAL_CHECK_OP_H_
386