• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/string_view.h"
44 
45 // `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that
46 // should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.
47 #ifdef ABSL_MIN_LOG_LEVEL
48 #define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal)         \
49   (::absl::LogSeverity::kFatal >=                               \
50            static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
51        ? (literal)                                              \
52        : "")
53 #else
54 #define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)
55 #endif
56 
57 #ifdef NDEBUG
58 // `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing.  However, we
59 // still want the compiler to parse `x` and `y`, because we don't want to lose
60 // potentially useful errors and warnings.
61 #define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y)   \
62   while (false && ((void)(x), (void)(y), 0)) \
63   ::absl::log_internal::NullStream().InternalStream()
64 #endif
65 
66 #define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \
67   while (absl::Nullable<const char*> absl_log_internal_check_op_result         \
68              ABSL_LOG_INTERNAL_ATTRIBUTE_UNUSED_IF_STRIP_LOG =                 \
69                  ::absl::log_internal::name##Impl(                             \
70                      ::absl::log_internal::GetReferenceableValue(val1),        \
71                      ::absl::log_internal::GetReferenceableValue(val2),        \
72                      ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(                   \
73                          val1_text " " #op " " val2_text)))                    \
74     ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \
75   ABSL_LOG_INTERNAL_CHECK(absl::implicit_cast<absl::Nonnull<const char*>>(     \
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 (absl::Nullable<const char*> 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<absl::Nonnull<const char*>>( \
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 (absl::Nullable<const char*> 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<absl::Nonnull<const char*>>(     \
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 (absl::Nullable<const char*> 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<absl::Nonnull<const char*>>(    \
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<absl::Nonnull<const ::absl::Status*>,                   \
139                    absl::Nullable<const char*>>                            \
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                ? nullptr                                                   \
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::implicit_cast<absl::Nonnull<const char*>>( \
153                               absl_log_internal_check_ok_goo.second))      \
154       .InternalStream()
155 #define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text)                          \
156   for (::std::pair<absl::Nonnull<const ::absl::Status*>,                    \
157                    absl::Nullable<const char*>>                             \
158            absl_log_internal_qcheck_ok_goo;                                 \
159        absl_log_internal_qcheck_ok_goo.first =                              \
160            ::absl::log_internal::AsStatus(val),                             \
161        absl_log_internal_qcheck_ok_goo.second =                             \
162            ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok())   \
163                ? nullptr                                                    \
164                : ::absl::status_internal::MakeCheckFailString(              \
165                      absl_log_internal_qcheck_ok_goo.first,                 \
166                      ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text        \
167                                                             " is OK")),     \
168        !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());)    \
169     ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                     \
170   ABSL_LOG_INTERNAL_QCHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \
171                                absl_log_internal_qcheck_ok_goo.second))     \
172       .InternalStream()
173 
174 namespace absl {
175 ABSL_NAMESPACE_BEGIN
176 
177 class Status;
178 template <typename T>
179 class StatusOr;
180 
181 namespace status_internal {
182 ABSL_ATTRIBUTE_PURE_FUNCTION absl::Nonnull<const char*> MakeCheckFailString(
183     absl::Nonnull<const absl::Status*> status,
184     absl::Nonnull<const char*> prefix);
185 }  // namespace status_internal
186 
187 namespace log_internal {
188 
189 // Convert a Status or a StatusOr to its underlying status value.
190 //
191 // (This implementation does not require a dep on absl::Status to work.)
AsStatus(const absl::Status & s)192 inline absl::Nonnull<const absl::Status*> AsStatus(const absl::Status& s) {
193   return &s;
194 }
195 template <typename T>
AsStatus(const absl::StatusOr<T> & s)196 absl::Nonnull<const absl::Status*> AsStatus(const absl::StatusOr<T>& s) {
197   return &s.status();
198 }
199 
200 // A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.
201 // See `MakeCheckOpString` for sample usage.
202 class CheckOpMessageBuilder final {
203  public:
204   // Inserts `exprtext` and ` (` to the stream.
205   explicit CheckOpMessageBuilder(absl::Nonnull<const char*> exprtext);
206   ~CheckOpMessageBuilder() = default;
207   // For inserting the first variable.
ForVar1()208   std::ostream& ForVar1() { return stream_; }
209   // For inserting the second variable (adds an intermediate ` vs. `).
210   std::ostream& ForVar2();
211   // Get the result (inserts the closing `)`).
212   absl::Nonnull<const char*> NewString();
213 
214  private:
215   std::ostringstream stream_;
216 };
217 
218 // This formats a value for a failing `CHECK_XX` statement.  Ordinarily, it uses
219 // the definition for `operator<<`, with a few special cases below.
220 template <typename T>
MakeCheckOpValueString(std::ostream & os,const T & v)221 inline void MakeCheckOpValueString(std::ostream& os, const T& v) {
222   os << log_internal::NullGuard<T>::Guard(v);
223 }
224 
225 // Overloads for char types provide readable values for unprintable characters.
226 void MakeCheckOpValueString(std::ostream& os, char v);
227 void MakeCheckOpValueString(std::ostream& os, signed char v);
228 void MakeCheckOpValueString(std::ostream& os, unsigned char v);
229 void MakeCheckOpValueString(std::ostream& os, const void* p);
230 
231 namespace detect_specialization {
232 
233 // MakeCheckOpString is being specialized for every T and U pair that is being
234 // passed to the CHECK_op macros. However, there is a lot of redundancy in these
235 // specializations that creates unnecessary library and binary bloat.
236 // The number of instantiations tends to be O(n^2) because we have two
237 // independent inputs. This technique works by reducing `n`.
238 //
239 // Most user-defined types being passed to CHECK_op end up being printed as a
240 // builtin type. For example, enums tend to be implicitly converted to its
241 // underlying type when calling operator<<, and pointers are printed with the
242 // `const void*` overload.
243 // To reduce the number of instantiations we coerce these values before calling
244 // MakeCheckOpString instead of inside it.
245 //
246 // To detect if this coercion is needed, we duplicate all the relevant
247 // operator<< overloads as specified in the standard, just in a different
248 // namespace. If the call to `stream << value` becomes ambiguous, it means that
249 // one of these overloads is the one selected by overload resolution. We then
250 // do overload resolution again just with our overload set to see which one gets
251 // selected. That tells us which type to coerce to.
252 // If the augmented call was not ambiguous, it means that none of these were
253 // selected and we can't coerce the input.
254 //
255 // As a secondary step to reduce code duplication, we promote integral types to
256 // their 64-bit variant. This does not change the printed value, but reduces the
257 // number of instantiations even further. Promoting an integer is very cheap at
258 // the call site.
259 int64_t operator<<(std::ostream&, short value);           // NOLINT
260 int64_t operator<<(std::ostream&, unsigned short value);  // NOLINT
261 int64_t operator<<(std::ostream&, int value);
262 int64_t operator<<(std::ostream&, unsigned int value);
263 int64_t operator<<(std::ostream&, long value);                 // NOLINT
264 uint64_t operator<<(std::ostream&, unsigned long value);       // NOLINT
265 int64_t operator<<(std::ostream&, long long value);            // NOLINT
266 uint64_t operator<<(std::ostream&, unsigned long long value);  // NOLINT
267 float operator<<(std::ostream&, float value);
268 double operator<<(std::ostream&, double value);
269 long double operator<<(std::ostream&, long double value);
270 bool operator<<(std::ostream&, bool value);
271 const void* operator<<(std::ostream&, const void* value);
272 const void* operator<<(std::ostream&, std::nullptr_t);
273 
274 // These `char` overloads are specified like this in the standard, so we have to
275 // write them exactly the same to ensure the call is ambiguous.
276 // If we wrote it in a different way (eg taking std::ostream instead of the
277 // template) then one call might have a higher rank than the other and it would
278 // not be ambiguous.
279 template <typename Traits>
280 char operator<<(std::basic_ostream<char, Traits>&, char);
281 template <typename Traits>
282 signed char operator<<(std::basic_ostream<char, Traits>&, signed char);
283 template <typename Traits>
284 unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
285 template <typename Traits>
286 const char* operator<<(std::basic_ostream<char, Traits>&, const char*);
287 template <typename Traits>
288 const signed char* operator<<(std::basic_ostream<char, Traits>&,
289                               const signed char*);
290 template <typename Traits>
291 const unsigned char* operator<<(std::basic_ostream<char, Traits>&,
292                                 const unsigned char*);
293 
294 // This overload triggers when the call is not ambiguous.
295 // It means that T is being printed with some overload not on this list.
296 // We keep the value as `const T&`.
297 template <typename T, typename = decltype(std::declval<std::ostream&>()
298                                           << std::declval<const T&>())>
299 const T& Detect(int);
300 
301 // This overload triggers when the call is ambiguous.
302 // It means that T is either one from this list or printed as one from this
303 // list. Eg an enum that decays to `int` for printing.
304 // We ask the overload set to give us the type we want to convert it to.
305 template <typename T>
306 decltype(detect_specialization::operator<<(std::declval<std::ostream&>(),
307                                            std::declval<const T&>()))
308 Detect(char);
309 
310 // A sink for AbslStringify which redirects everything to a std::ostream.
311 class StringifySink {
312  public:
313   explicit StringifySink(std::ostream& os ABSL_ATTRIBUTE_LIFETIME_BOUND);
314 
315   void Append(absl::string_view text);
316   void Append(size_t length, char ch);
317   friend void AbslFormatFlush(StringifySink* sink, absl::string_view text);
318 
319  private:
320   std::ostream& os_;
321 };
322 
323 // Wraps a type implementing AbslStringify, and implements operator<<.
324 template <typename T>
325 class StringifyToStreamWrapper {
326  public:
StringifyToStreamWrapper(const T & v ABSL_ATTRIBUTE_LIFETIME_BOUND)327   explicit StringifyToStreamWrapper(const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND)
328       : v_(v) {}
329 
330   friend std::ostream& operator<<(std::ostream& os,
331                                   const StringifyToStreamWrapper& wrapper) {
332     StringifySink sink(os);
333     AbslStringify(sink, wrapper.v_);
334     return os;
335   }
336 
337  private:
338   const T& v_;
339 };
340 
341 // This overload triggers when T implements AbslStringify.
342 // StringifyToStreamWrapper is used to allow MakeCheckOpString to use
343 // operator<<.
344 template <typename T>
345 std::enable_if_t<HasAbslStringify<T>::value,
346                  StringifyToStreamWrapper<T>>
347 Detect(...);  // Ellipsis has lowest preference when int passed.
348 }  // namespace detect_specialization
349 
350 template <typename T>
351 using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0));
352 
353 // Build the error message string.  Specify no inlining for code size.
354 template <typename T1, typename T2>
355 ABSL_ATTRIBUTE_RETURNS_NONNULL absl::Nonnull<const char*> MakeCheckOpString(
356     T1 v1, T2 v2, absl::Nonnull<const char*> exprtext) ABSL_ATTRIBUTE_NOINLINE;
357 
358 template <typename T1, typename T2>
MakeCheckOpString(T1 v1,T2 v2,absl::Nonnull<const char * > exprtext)359 absl::Nonnull<const char*> MakeCheckOpString(
360     T1 v1, T2 v2, absl::Nonnull<const char*> exprtext) {
361   CheckOpMessageBuilder comb(exprtext);
362   MakeCheckOpValueString(comb.ForVar1(), v1);
363   MakeCheckOpValueString(comb.ForVar2(), v2);
364   return comb.NewString();
365 }
366 
367 // Add a few commonly used instantiations as extern to reduce size of objects
368 // files.
369 #define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
370   extern template absl::Nonnull<const char*> MakeCheckOpString( \
371       x, x, absl::Nonnull<const char*>)
372 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
373 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
374 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
375 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);
376 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);
377 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);
378 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
379 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
380 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
381 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*);
382 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*);
383 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*);
384 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*);
385 #undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
386 
387 // `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result
388 // string iff `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`, instead returning an empty
389 // string.
390 #ifdef ABSL_MIN_LOG_LEVEL
391 #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \
392   ((::absl::LogSeverity::kFatal >=                                       \
393     static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))                \
394        ? MakeCheckOpString<U1, U2>(v1, v2, exprtext)                     \
395        : "")
396 #else
397 #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \
398   MakeCheckOpString<U1, U2>(v1, v2, exprtext)
399 #endif
400 
401 // Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family.  The
402 // `(int, int)` override works around the issue that the compiler will not
403 // instantiate the template version of the function on values of unnamed enum
404 // type.
405 #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op)                          \
406   template <typename T1, typename T2>                                      \
407   inline constexpr absl::Nullable<const char*> name##Impl(                 \
408       const T1& v1, const T2& v2, absl::Nonnull<const char*> exprtext) {   \
409     using U1 = CheckOpStreamType<T1>;                                      \
410     using U2 = CheckOpStreamType<T2>;                                      \
411     return ABSL_PREDICT_TRUE(v1 op v2)                                     \
412                ? nullptr                                                   \
413                : ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, U1(v1),    \
414                                                         U2(v2), exprtext); \
415   }                                                                        \
416   inline constexpr absl::Nullable<const char*> name##Impl(                 \
417       int v1, int v2, absl::Nonnull<const char*> exprtext) {               \
418     return name##Impl<int, int>(v1, v2, exprtext);                         \
419   }
420 
421 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)
422 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)
423 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)
424 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)
425 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)
426 ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)
427 #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT
428 #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
429 
430 absl::Nullable<const char*> CheckstrcmptrueImpl(
431     absl::Nullable<const char*> s1, absl::Nullable<const char*> s2,
432     absl::Nonnull<const char*> exprtext);
433 absl::Nullable<const char*> CheckstrcmpfalseImpl(
434     absl::Nullable<const char*> s1, absl::Nullable<const char*> s2,
435     absl::Nonnull<const char*> exprtext);
436 absl::Nullable<const char*> CheckstrcasecmptrueImpl(
437     absl::Nullable<const char*> s1, absl::Nullable<const char*> s2,
438     absl::Nonnull<const char*> exprtext);
439 absl::Nullable<const char*> CheckstrcasecmpfalseImpl(
440     absl::Nullable<const char*> s1, absl::Nullable<const char*> s2,
441     absl::Nonnull<const char*> exprtext);
442 
443 // `CHECK_EQ` and friends want to pass their arguments by reference, however
444 // this winds up exposing lots of cases where people have defined and
445 // initialized static const data members but never declared them (i.e. in a .cc
446 // file), meaning they are not referenceable.  This function avoids that problem
447 // for integers (the most common cases) by overloading for every primitive
448 // integer type, even the ones we discourage, and returning them by value.
449 // NOLINTBEGIN(runtime/int)
450 // NOLINTBEGIN(google-runtime-int)
451 template <typename T>
GetReferenceableValue(const T & t)452 inline constexpr const T& GetReferenceableValue(const T& t) {
453   return t;
454 }
GetReferenceableValue(char t)455 inline constexpr char GetReferenceableValue(char t) { return t; }
GetReferenceableValue(unsigned char t)456 inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
457   return t;
458 }
GetReferenceableValue(signed char t)459 inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
GetReferenceableValue(short t)460 inline constexpr short GetReferenceableValue(short t) { return t; }
GetReferenceableValue(unsigned short t)461 inline constexpr unsigned short GetReferenceableValue(unsigned short t) {
462   return t;
463 }
GetReferenceableValue(int t)464 inline constexpr int GetReferenceableValue(int t) { return t; }
GetReferenceableValue(unsigned int t)465 inline constexpr unsigned int GetReferenceableValue(unsigned int t) {
466   return t;
467 }
GetReferenceableValue(long t)468 inline constexpr long GetReferenceableValue(long t) { return t; }
GetReferenceableValue(unsigned long t)469 inline constexpr unsigned long GetReferenceableValue(unsigned long t) {
470   return t;
471 }
GetReferenceableValue(long long t)472 inline constexpr long long GetReferenceableValue(long long t) { return t; }
GetReferenceableValue(unsigned long long t)473 inline constexpr unsigned long long GetReferenceableValue(
474     unsigned long long t) {
475   return t;
476 }
477 // NOLINTEND(google-runtime-int)
478 // NOLINTEND(runtime/int)
479 
480 }  // namespace log_internal
481 ABSL_NAMESPACE_END
482 }  // namespace absl
483 
484 #endif  // ABSL_LOG_INTERNAL_CHECK_OP_H_
485