Coverage Report

Created: 2024-09-23 06:29

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