• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/log/internal/log_message.h"
17 
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #ifndef _WIN32
24 #include <unistd.h>
25 #endif
26 
27 #include <algorithm>
28 #include <array>
29 #include <atomic>
30 #include <memory>
31 #include <ostream>
32 #include <string>
33 #include <tuple>
34 
35 #include "absl/base/attributes.h"
36 #include "absl/base/config.h"
37 #include "absl/base/internal/raw_logging.h"
38 #include "absl/base/internal/strerror.h"
39 #include "absl/base/internal/sysinfo.h"
40 #include "absl/base/log_severity.h"
41 #include "absl/container/inlined_vector.h"
42 #include "absl/debugging/internal/examine_stack.h"
43 #include "absl/log/globals.h"
44 #include "absl/log/internal/append_truncated.h"
45 #include "absl/log/internal/globals.h"
46 #include "absl/log/internal/log_format.h"
47 #include "absl/log/internal/log_sink_set.h"
48 #include "absl/log/internal/proto.h"
49 #include "absl/log/log_entry.h"
50 #include "absl/log/log_sink.h"
51 #include "absl/log/log_sink_registry.h"
52 #include "absl/memory/memory.h"
53 #include "absl/strings/string_view.h"
54 #include "absl/time/clock.h"
55 #include "absl/time/time.h"
56 #include "absl/types/span.h"
57 
ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)58 extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
59     AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
60   // Default - Do nothing
61 }
62 
63 namespace absl {
64 ABSL_NAMESPACE_BEGIN
65 namespace log_internal {
66 
67 namespace {
68 // message `logging.proto.Event`
69 enum EventTag : uint8_t {
70   kValue = 7,
71 };
72 
73 // message `logging.proto.Value`
74 enum ValueTag : uint8_t {
75   kString = 1,
76   kStringLiteral = 6,
77 };
78 
79 // Decodes a `logging.proto.Value` from `buf` and writes a string representation
80 // into `dst`.  The string representation will be truncated if `dst` is not
81 // large enough to hold it.  Returns false if `dst` has size zero or one (i.e.
82 // sufficient only for a nul-terminator) and no decoded data could be written.
83 // This function may or may not write a nul-terminator into `dst`, and it may or
84 // may not truncate the data it writes in order to do make space for that nul
85 // terminator.  In any case, `dst` will be advanced to point at the byte where
86 // subsequent writes should begin.
PrintValue(absl::Span<char> & dst,absl::Span<const char> buf)87 bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
88   if (dst.size() <= 1) return false;
89   ProtoField field;
90   while (field.DecodeFrom(&buf)) {
91     switch (field.tag()) {
92       case ValueTag::kString:
93       case ValueTag::kStringLiteral:
94         if (field.type() == WireType::kLengthDelimited)
95           if (log_internal::AppendTruncated(field.string_value(), dst) <
96               field.string_value().size())
97             return false;
98     }
99   }
100   return true;
101 }
102 
Basename(absl::string_view filepath)103 absl::string_view Basename(absl::string_view filepath) {
104 #ifdef _WIN32
105   size_t path = filepath.find_last_of("/\\");
106 #else
107   size_t path = filepath.find_last_of('/');
108 #endif
109   if (path != filepath.npos) filepath.remove_prefix(path + 1);
110   return filepath;
111 }
112 
WriteToString(const char * data,void * str)113 void WriteToString(const char* data, void* str) {
114   reinterpret_cast<std::string*>(str)->append(data);
115 }
WriteToStream(const char * data,void * os)116 void WriteToStream(const char* data, void* os) {
117   auto* cast_os = static_cast<std::ostream*>(os);
118   *cast_os << data;
119 }
120 }  // namespace
121 
122 struct LogMessage::LogMessageData final {
123   LogMessageData(const char* file, int line, absl::LogSeverity severity,
124                  absl::Time timestamp);
125   LogMessageData(const LogMessageData&) = delete;
126   LogMessageData& operator=(const LogMessageData&) = delete;
127 
128   // `LogEntry` sent to `LogSink`s; contains metadata.
129   absl::LogEntry entry;
130 
131   // true => this was first fatal msg
132   bool first_fatal;
133   // true => all failures should be quiet
134   bool fail_quietly;
135   // true => PLOG was requested
136   bool is_perror;
137 
138   // Extra `LogSink`s to log to, in addition to `global_sinks`.
139   absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
140   // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
141   // non-sink targets (e.g. stderr, log files).
142   bool extra_sinks_only;
143 
144   std::ostream manipulated;  // ostream with IO manipulators applied
145 
146   // A `logging.proto.Event` proto message is built into `encoded_buf`.
147   std::array<char, kLogMessageBufferSize> encoded_buf;
148   // `encoded_remaining` is the suffix of `encoded_buf` that has not been filled
149   // yet.  If a datum to be encoded does not fit into `encoded_remaining` and
150   // cannot be truncated to fit, the size of `encoded_remaining` will be zeroed
151   // to prevent encoding of any further data.  Note that in this case its data()
152   // pointer will not point past the end of `encoded_buf`.
153   absl::Span<char> encoded_remaining;
154 
155   // A formatted string message is built in `string_buf`.
156   std::array<char, kLogMessageBufferSize> string_buf;
157 
158   void FinalizeEncodingAndFormat();
159 };
160 
LogMessageData(const char * file,int line,absl::LogSeverity severity,absl::Time timestamp)161 LogMessage::LogMessageData::LogMessageData(const char* file, int line,
162                                            absl::LogSeverity severity,
163                                            absl::Time timestamp)
164     : extra_sinks_only(false),
165       manipulated(nullptr),
166       // This `absl::MakeSpan` silences spurious -Wuninitialized from GCC:
167       encoded_remaining(absl::MakeSpan(encoded_buf)) {
168   // Legacy defaults for LOG's ostream:
169   manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
170   entry.full_filename_ = file;
171   entry.base_filename_ = Basename(file);
172   entry.line_ = line;
173   entry.prefix_ = absl::ShouldPrependLogPrefix();
174   entry.severity_ = absl::NormalizeLogSeverity(severity);
175   entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
176   entry.timestamp_ = timestamp;
177   entry.tid_ = absl::base_internal::GetCachedTID();
178 }
179 
FinalizeEncodingAndFormat()180 void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
181   // Note that `encoded_remaining` may have zero size without pointing past the
182   // end of `encoded_buf`, so the difference between `data()` pointers is used
183   // to compute the size of `encoded_data`.
184   absl::Span<const char> encoded_data(
185       encoded_buf.data(),
186       static_cast<size_t>(encoded_remaining.data() - encoded_buf.data()));
187   // `string_remaining` is the suffix of `string_buf` that has not been filled
188   // yet.
189   absl::Span<char> string_remaining(string_buf);
190   // We may need to write a newline and nul-terminator at the end of the decoded
191   // string data.  Rather than worry about whether those should overwrite the
192   // end of the string (if the buffer is full) or be appended, we avoid writing
193   // into the last two bytes so we always have space to append.
194   string_remaining.remove_suffix(2);
195   entry.prefix_len_ =
196       entry.prefix() ? log_internal::FormatLogPrefix(
197                            entry.log_severity(), entry.timestamp(), entry.tid(),
198                            entry.source_basename(), entry.source_line(),
199                            log_internal::ThreadIsLoggingToLogSink()
200                                ? PrefixFormat::kRaw
201                                : PrefixFormat::kNotRaw,
202                            string_remaining)
203                      : 0;
204   // Decode data from `encoded_buf` until we run out of data or we run out of
205   // `string_remaining`.
206   ProtoField field;
207   while (field.DecodeFrom(&encoded_data)) {
208     switch (field.tag()) {
209       case EventTag::kValue:
210         if (field.type() != WireType::kLengthDelimited) continue;
211         if (PrintValue(string_remaining, field.bytes_value())) continue;
212         break;
213     }
214     break;
215   }
216   auto chars_written =
217       static_cast<size_t>(string_remaining.data() - string_buf.data());
218     string_buf[chars_written++] = '\n';
219   string_buf[chars_written++] = '\0';
220   entry.text_message_with_prefix_and_newline_and_nul_ =
221       absl::MakeSpan(string_buf).subspan(0, chars_written);
222 }
223 
LogMessage(const char * file,int line,absl::LogSeverity severity)224 LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
225     : data_(absl::make_unique<LogMessageData>(file, line, severity,
226                                               absl::Now())) {
227   data_->first_fatal = false;
228   data_->is_perror = false;
229   data_->fail_quietly = false;
230 
231   // This logs a backtrace even if the location is subsequently changed using
232   // AtLocation.  This quirk, and the behavior when AtLocation is called twice,
233   // are fixable but probably not worth fixing.
234   LogBacktraceIfNeeded();
235 }
236 
LogMessage(const char * file,int line,InfoTag)237 LogMessage::LogMessage(const char* file, int line, InfoTag)
238     : LogMessage(file, line, absl::LogSeverity::kInfo) {}
LogMessage(const char * file,int line,WarningTag)239 LogMessage::LogMessage(const char* file, int line, WarningTag)
240     : LogMessage(file, line, absl::LogSeverity::kWarning) {}
LogMessage(const char * file,int line,ErrorTag)241 LogMessage::LogMessage(const char* file, int line, ErrorTag)
242     : LogMessage(file, line, absl::LogSeverity::kError) {}
243 
~LogMessage()244 LogMessage::~LogMessage() {
245 #ifdef ABSL_MIN_LOG_LEVEL
246   if (data_->entry.log_severity() <
247           static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
248       data_->entry.log_severity() < absl::LogSeverity::kFatal) {
249     return;
250   }
251 #endif
252   Flush();
253 }
254 
AtLocation(absl::string_view file,int line)255 LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
256   data_->entry.full_filename_ = file;
257   data_->entry.base_filename_ = Basename(file);
258   data_->entry.line_ = line;
259   LogBacktraceIfNeeded();
260   return *this;
261 }
262 
NoPrefix()263 LogMessage& LogMessage::NoPrefix() {
264   data_->entry.prefix_ = false;
265   return *this;
266 }
267 
WithVerbosity(int verbose_level)268 LogMessage& LogMessage::WithVerbosity(int verbose_level) {
269   if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
270     data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
271   } else {
272     data_->entry.verbose_level_ = std::max(0, verbose_level);
273   }
274   return *this;
275 }
276 
WithTimestamp(absl::Time timestamp)277 LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
278   data_->entry.timestamp_ = timestamp;
279   return *this;
280 }
281 
WithThreadID(absl::LogEntry::tid_t tid)282 LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
283   data_->entry.tid_ = tid;
284   return *this;
285 }
286 
WithMetadataFrom(const absl::LogEntry & entry)287 LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
288   data_->entry.full_filename_ = entry.full_filename_;
289   data_->entry.base_filename_ = entry.base_filename_;
290   data_->entry.line_ = entry.line_;
291   data_->entry.prefix_ = entry.prefix_;
292   data_->entry.severity_ = entry.severity_;
293   data_->entry.verbose_level_ = entry.verbose_level_;
294   data_->entry.timestamp_ = entry.timestamp_;
295   data_->entry.tid_ = entry.tid_;
296   return *this;
297 }
298 
WithPerror()299 LogMessage& LogMessage::WithPerror() {
300   data_->is_perror = true;
301   return *this;
302 }
303 
ToSinkAlso(absl::LogSink * sink)304 LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
305   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
306   data_->extra_sinks.push_back(sink);
307   return *this;
308 }
309 
ToSinkOnly(absl::LogSink * sink)310 LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
311   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
312   data_->extra_sinks.clear();
313   data_->extra_sinks.push_back(sink);
314   data_->extra_sinks_only = true;
315   return *this;
316 }
317 
318 #ifdef __ELF__
319 extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
320 extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
321 #endif
322 
FailWithoutStackTrace()323 void LogMessage::FailWithoutStackTrace() {
324   // Now suppress repeated trace logging:
325   log_internal::SetSuppressSigabortTrace(true);
326 #if defined _DEBUG && defined COMPILER_MSVC
327   // When debugging on windows, avoid the obnoxious dialog.
328   __debugbreak();
329 #endif
330 
331 #ifdef __ELF__
332   // For b/8737634, flush coverage if we are in coverage mode.
333   if (&__gcov_dump != nullptr) {
334     __gcov_dump();
335   } else if (&__gcov_flush != nullptr) {
336     __gcov_flush();
337   }
338 #endif
339 
340   abort();
341 }
342 
FailQuietly()343 void LogMessage::FailQuietly() {
344   // _exit. Calling abort() would trigger all sorts of death signal handlers
345   // and a detailed stack trace. Calling exit() would trigger the onexit
346   // handlers, including the heap-leak checker, which is guaranteed to fail in
347   // this case: we probably just new'ed the std::string that we logged.
348   // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
349   // of the program quickly, and it doesn't make much sense for FailQuietly to
350   // offer different guarantees about exit behavior than Fail does. (And as a
351   // consequence for QCHECK and CHECK to offer different exit behaviors)
352   _exit(1);
353 }
354 
operator <<(const std::string & v)355 LogMessage& LogMessage::operator<<(const std::string& v) {
356   CopyToEncodedBuffer<StringType::kNotLiteral>(v);
357   return *this;
358 }
359 
operator <<(absl::string_view v)360 LogMessage& LogMessage::operator<<(absl::string_view v) {
361   CopyToEncodedBuffer<StringType::kNotLiteral>(v);
362   return *this;
363 }
operator <<(std::ostream & (* m)(std::ostream & os))364 LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
365   OstreamView view(*data_);
366   data_->manipulated << m;
367   return *this;
368 }
operator <<(std::ios_base & (* m)(std::ios_base & os))369 LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
370   OstreamView view(*data_);
371   data_->manipulated << m;
372   return *this;
373 }
374 template LogMessage& LogMessage::operator<<(const char& v);
375 template LogMessage& LogMessage::operator<<(const signed char& v);
376 template LogMessage& LogMessage::operator<<(const unsigned char& v);
377 template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
378 template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
379 template LogMessage& LogMessage::operator<<(const int& v);
380 template LogMessage& LogMessage::operator<<(const unsigned int& v);
381 template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
382 template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
383 template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
384 template LogMessage& LogMessage::operator<<(
385     const unsigned long long& v);  // NOLINT
386 template LogMessage& LogMessage::operator<<(void* const& v);
387 template LogMessage& LogMessage::operator<<(const void* const& v);
388 template LogMessage& LogMessage::operator<<(const float& v);
389 template LogMessage& LogMessage::operator<<(const double& v);
390 template LogMessage& LogMessage::operator<<(const bool& v);
391 
Flush()392 void LogMessage::Flush() {
393   if (data_->entry.log_severity() < absl::MinLogLevel()) return;
394 
395   if (data_->is_perror) {
396     InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
397                      << " [" << errno_saver_() << "]";
398   }
399 
400   // Have we already seen a fatal message?
401   ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);
402   if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
403       absl::log_internal::ExitOnDFatal()) {
404     // Exactly one LOG(FATAL) message is responsible for aborting the process,
405     // even if multiple threads LOG(FATAL) concurrently.
406     bool expected_seen_fatal = false;
407     if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,
408                                            std::memory_order_relaxed)) {
409       data_->first_fatal = true;
410     }
411   }
412 
413   data_->FinalizeEncodingAndFormat();
414   data_->entry.encoding_ =
415       absl::string_view(data_->encoded_buf.data(),
416                         static_cast<size_t>(data_->encoded_remaining.data() -
417                                             data_->encoded_buf.data()));
418   SendToLog();
419 }
420 
SetFailQuietly()421 void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
422 
OstreamView(LogMessageData & message_data)423 LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
424     : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining) {
425   // This constructor sets the `streambuf` up so that streaming into an attached
426   // ostream encodes string data in-place.  To do that, we write appropriate
427   // headers into the buffer using a copy of the buffer view so that we can
428   // decide not to keep them later if nothing is ever streamed in.  We don't
429   // know how much data we'll get, but we can use the size of the remaining
430   // buffer as an upper bound and fill in the right size once we know it.
431   message_start_ =
432       EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),
433                          &encoded_remaining_copy_);
434   string_start_ =
435       EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
436                          &encoded_remaining_copy_);
437   setp(encoded_remaining_copy_.data(),
438        encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
439   data_.manipulated.rdbuf(this);
440 }
441 
~OstreamView()442 LogMessage::OstreamView::~OstreamView() {
443   data_.manipulated.rdbuf(nullptr);
444   if (!string_start_.data()) {
445     // The second field header didn't fit.  Whether the first one did or not, we
446     // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
447     // size of `data_->encoded_remaining` so that no more data are encoded.
448     data_.encoded_remaining.remove_suffix(data_.encoded_remaining.size());
449     return;
450   }
451   const absl::Span<const char> contents(pbase(),
452                                         static_cast<size_t>(pptr() - pbase()));
453   if (contents.empty()) return;
454   encoded_remaining_copy_.remove_prefix(contents.size());
455   EncodeMessageLength(string_start_, &encoded_remaining_copy_);
456   EncodeMessageLength(message_start_, &encoded_remaining_copy_);
457   data_.encoded_remaining = encoded_remaining_copy_;
458 }
459 
stream()460 std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
461 
IsFatal() const462 bool LogMessage::IsFatal() const {
463   return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
464          absl::log_internal::ExitOnDFatal();
465 }
466 
PrepareToDie()467 void LogMessage::PrepareToDie() {
468   // If we log a FATAL message, flush all the log destinations, then toss
469   // a signal for others to catch. We leave the logs in a state that
470   // someone else can use them (as long as they flush afterwards)
471   if (data_->first_fatal) {
472     // Notify observers about the upcoming fatal error.
473     ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
474   }
475 
476   if (!data_->fail_quietly) {
477     // Log the message first before we start collecting stack trace.
478     log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
479                              data_->extra_sinks_only);
480 
481     // `DumpStackTrace` generates an empty string under MSVC.
482     // Adding the constant prefix here simplifies testing.
483     data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
484     debugging_internal::DumpStackTrace(
485         0, log_internal::MaxFramesInLogStackTrace(),
486         log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
487         &data_->entry.stacktrace_);
488   }
489 }
490 
Die()491 void LogMessage::Die() {
492   absl::FlushLogSinks();
493 
494   if (data_->fail_quietly) {
495     FailQuietly();
496   } else {
497     FailWithoutStackTrace();
498   }
499 }
500 
SendToLog()501 void LogMessage::SendToLog() {
502   if (IsFatal()) PrepareToDie();
503   // Also log to all registered sinks, even if OnlyLogToStderr() is set.
504   log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
505                            data_->extra_sinks_only);
506   if (IsFatal()) Die();
507 }
508 
LogBacktraceIfNeeded()509 void LogMessage::LogBacktraceIfNeeded() {
510   if (!absl::log_internal::IsInitialized()) return;
511 
512   if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
513                                                 data_->entry.source_line()))
514     return;
515   OstreamView view(*data_);
516   view.stream() << " (stacktrace:\n";
517   debugging_internal::DumpStackTrace(
518       1, log_internal::MaxFramesInLogStackTrace(),
519       log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,
520       &view.stream());
521   view.stream() << ") ";
522 }
523 
524 // Encodes into `data_->encoded_remaining` a partial `logging.proto.Event`
525 // containing the specified string data using a `Value` field appropriate to
526 // `str_type`.  Truncates `str` if necessary, but emits nothing and marks the
527 // buffer full if  even the field headers do not fit.
528 template <LogMessage::StringType str_type>
CopyToEncodedBuffer(absl::string_view str)529 void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
530   auto encoded_remaining_copy = data_->encoded_remaining;
531   auto start = EncodeMessageStart(
532       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
533       &encoded_remaining_copy);
534   // If the `logging.proto.Event.value` field header did not fit,
535   // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
536   // `EncodeStringTruncate` will fail too.
537   if (EncodeStringTruncate(str_type == StringType::kLiteral
538                                ? ValueTag::kStringLiteral
539                                : ValueTag::kString,
540                            str, &encoded_remaining_copy)) {
541     // The string may have been truncated, but the field header fit.
542     EncodeMessageLength(start, &encoded_remaining_copy);
543     data_->encoded_remaining = encoded_remaining_copy;
544   } else {
545     // The field header(s) did not fit; zero `encoded_remaining` so we don't
546     // write anything else later.
547     data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
548   }
549 }
550 template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
551     absl::string_view str);
552 template void LogMessage::CopyToEncodedBuffer<
553     LogMessage::StringType::kNotLiteral>(absl::string_view str);
554 template <LogMessage::StringType str_type>
CopyToEncodedBuffer(char ch,size_t num)555 void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
556   auto encoded_remaining_copy = data_->encoded_remaining;
557   auto value_start = EncodeMessageStart(
558       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
559       &encoded_remaining_copy);
560   auto str_start = EncodeMessageStart(str_type == StringType::kLiteral
561                                           ? ValueTag::kStringLiteral
562                                           : ValueTag::kString,
563                                       num, &encoded_remaining_copy);
564   if (str_start.data()) {
565     // The field headers fit.
566     log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
567     EncodeMessageLength(str_start, &encoded_remaining_copy);
568     EncodeMessageLength(value_start, &encoded_remaining_copy);
569     data_->encoded_remaining = encoded_remaining_copy;
570   } else {
571     // The field header(s) did not fit; zero `encoded_remaining` so we don't
572     // write anything else later.
573     data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
574   }
575 }
576 template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
577     char ch, size_t num);
578 template void LogMessage::CopyToEncodedBuffer<
579     LogMessage::StringType::kNotLiteral>(char ch, size_t num);
580 
LogMessageFatal(const char * file,int line)581 LogMessageFatal::LogMessageFatal(const char* file, int line)
582     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
583 
LogMessageFatal(const char * file,int line,absl::string_view failure_msg)584 LogMessageFatal::LogMessageFatal(const char* file, int line,
585                                  absl::string_view failure_msg)
586     : LogMessage(file, line, absl::LogSeverity::kFatal) {
587   *this << "Check failed: " << failure_msg << " ";
588 }
589 
590 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
591 // disable msvc's warning about the d'tor never returning.
592 #if defined(_MSC_VER) && !defined(__clang__)
593 #pragma warning(push)
594 #pragma warning(disable : 4722)
595 #endif
~LogMessageFatal()596 LogMessageFatal::~LogMessageFatal() {
597   Flush();
598   FailWithoutStackTrace();
599 }
600 #if defined(_MSC_VER) && !defined(__clang__)
601 #pragma warning(pop)
602 #endif
603 
LogMessageQuietlyFatal(const char * file,int line)604 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
605     : LogMessage(file, line, absl::LogSeverity::kFatal) {
606   SetFailQuietly();
607 }
608 
LogMessageQuietlyFatal(const char * file,int line,absl::string_view failure_msg)609 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
610                                                absl::string_view failure_msg)
611     : LogMessage(file, line, absl::LogSeverity::kFatal) {
612   SetFailQuietly();
613   *this << "Check failed: " << failure_msg << " ";
614 }
615 
616 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
617 // disable msvc's warning about the d'tor never returning.
618 #if defined(_MSC_VER) && !defined(__clang__)
619 #pragma warning(push)
620 #pragma warning(disable : 4722)
621 #endif
~LogMessageQuietlyFatal()622 LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
623   Flush();
624   FailQuietly();
625 }
626 #if defined(_MSC_VER) && !defined(__clang__)
627 #pragma warning(pop)
628 #endif
629 
630 }  // namespace log_internal
631 
632 ABSL_NAMESPACE_END
633 }  // namespace absl
634