tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

check_op.h (23849B)


      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             [[maybe_unused]] =                 \
     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.)
    192 inline absl::Nonnull<const absl::Status*> AsStatus(const absl::Status& s) {
    193  return &s;
    194 }
    195 template <typename T>
    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.
    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>
    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:
    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>
    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>
    452 inline constexpr const T& GetReferenceableValue(const T& t) {
    453  return t;
    454 }
    455 inline constexpr char GetReferenceableValue(char t) { return t; }
    456 inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
    457  return t;
    458 }
    459 inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
    460 inline constexpr short GetReferenceableValue(short t) { return t; }
    461 inline constexpr unsigned short GetReferenceableValue(unsigned short t) {
    462  return t;
    463 }
    464 inline constexpr int GetReferenceableValue(int t) { return t; }
    465 inline constexpr unsigned int GetReferenceableValue(unsigned int t) {
    466  return t;
    467 }
    468 inline constexpr long GetReferenceableValue(long t) { return t; }
    469 inline constexpr unsigned long GetReferenceableValue(unsigned long t) {
    470  return t;
    471 }
    472 inline constexpr long long GetReferenceableValue(long long t) { return 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_