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