Make DLOG(FATAL) not understood as [[noreturn]]

Having DLOG(FATAL) be [[noreturn]] in debug builds makes dead-code
warnings impossible to satisfy between the release and debug build.

PiperOrigin-RevId: 610851706
Change-Id: I07104d6687e2b1a8472ee3ea876d5fd74a70574e
diff --git a/absl/log/internal/log_impl.h b/absl/log/internal/log_impl.h
index 99de6db..b44ed06 100644
--- a/absl/log/internal/log_impl.h
+++ b/absl/log/internal/log_impl.h
@@ -35,11 +35,11 @@
 #ifndef NDEBUG
 #define ABSL_LOG_INTERNAL_DLOG_IMPL(severity)            \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 #else
 #define ABSL_LOG_INTERNAL_DLOG_IMPL(severity)             \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 #endif
 
 // The `switch` ensures that this expansion is the begnning of a statement (as
@@ -58,7 +58,7 @@
   switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
   case 0:                                                                  \
   default:                                                                 \
-    ABSL_LOG_INTERNAL_LOG_IF_IMPL(                                         \
+    ABSL_LOG_INTERNAL_DLOG_IF_IMPL(                                         \
         _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level))       \
         .WithVerbosity(absl_logging_internal_verbose_level)
 #else
@@ -66,7 +66,7 @@
   switch (const int absl_logging_internal_verbose_level = (verbose_level))    \
   case 0:                                                                     \
   default:                                                                    \
-    ABSL_LOG_INTERNAL_LOG_IF_IMPL(                                            \
+    ABSL_LOG_INTERNAL_DLOG_IF_IMPL(                                            \
         _INFO, false && ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
         .WithVerbosity(absl_logging_internal_verbose_level)
 #endif
@@ -82,11 +82,11 @@
 #ifndef NDEBUG
 #define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition)   \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 #else
 #define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition)              \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false && (condition)) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 #endif
 
 // ABSL_LOG_EVERY_N
@@ -132,36 +132,36 @@
 #ifndef NDEBUG
 #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)       \
-  (EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)       \
-  (FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)        \
-  (EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)                   \
-  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #else  // def NDEBUG
 #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)      \
-  (EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)      \
-  (FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)       \
-  (EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
   ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)                  \
-  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 #endif  // def NDEBUG
 
 #define ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n)                \
@@ -243,40 +243,40 @@
 #ifndef NDEBUG
 #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n)  \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n)  \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
                                                    n_seconds)           \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
                                                              n_seconds) \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #else  // def NDEBUG
 #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n)   \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
-      EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n)   \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
-      FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition)  \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
-      EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 
 #define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition,  \
                                                    n_seconds)            \
   ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
       EveryNSec, n_seconds)                                              \
-      ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+      ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
 #endif  // def NDEBUG
 
 #endif  // ABSL_LOG_INTERNAL_LOG_IMPL_H_
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc
index 10ac245..e8a8111 100644
--- a/absl/log/internal/log_message.cc
+++ b/absl/log/internal/log_message.cc
@@ -240,6 +240,8 @@
     : LogMessage(file, line, absl::LogSeverity::kWarning) {}
 LogMessage::LogMessage(const char* file, int line, ErrorTag)
     : LogMessage(file, line, absl::LogSeverity::kError) {}
+LogMessage::LogMessage(const char* file, int line, FatalTag)
+    : LogMessage(file, line, absl::LogSeverity::kFatal) {}
 
 LogMessage::~LogMessage() {
 #ifdef ABSL_MIN_LOG_LEVEL
@@ -587,8 +589,8 @@
   *this << "Check failed: " << failure_msg << " ";
 }
 
-// ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
-// disable msvc's warning about the d'tor never returning.
+// We intentionally don't return from these destructors. Disable MSVC's warning
+// about the destructor never returning as we do so intentionally here.
 #if defined(_MSC_VER) && !defined(__clang__)
 #pragma warning(push)
 #pragma warning(disable : 4722)
@@ -597,28 +599,26 @@
   Flush();
   FailWithoutStackTrace();
 }
-#if defined(_MSC_VER) && !defined(__clang__)
-#pragma warning(pop)
-#endif
 
-LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
+LogMessageQuietly::LogMessageQuietly(const char* file, int line)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {
   SetFailQuietly();
 }
 
+LogMessageQuietly::~LogMessageQuietly() {
+  Flush();
+  FailQuietly();
+}
+
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
+    : LogMessageQuietly(file, line) {}
+
 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
                                                absl::string_view failure_msg)
-    : LogMessage(file, line, absl::LogSeverity::kFatal) {
-  SetFailQuietly();
-  *this << "Check failed: " << failure_msg << " ";
+    : LogMessageQuietly(file, line) {
+    *this << "Check failed: " << failure_msg << " ";
 }
 
-// ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
-// disable msvc's warning about the d'tor never returning.
-#if defined(_MSC_VER) && !defined(__clang__)
-#pragma warning(push)
-#pragma warning(disable : 4722)
-#endif
 LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
   Flush();
   FailQuietly();
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
index 4ecb8a1..737efa1 100644
--- a/absl/log/internal/log_message.h
+++ b/absl/log/internal/log_message.h
@@ -54,6 +54,7 @@
   struct InfoTag {};
   struct WarningTag {};
   struct ErrorTag {};
+  struct FatalTag {};
 
   // Used for `LOG`.
   LogMessage(const char* file, int line,
@@ -66,6 +67,8 @@
              WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
   LogMessage(const char* file, int line,
              ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
+  LogMessage(const char* file, int line,
+             FatalTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
   LogMessage(const LogMessage&) = delete;
   LogMessage& operator=(const LogMessage&) = delete;
   ~LogMessage() ABSL_ATTRIBUTE_COLD;
@@ -357,7 +360,17 @@
   ABSL_ATTRIBUTE_NORETURN ~LogMessageFatal();
 };
 
-class LogMessageQuietlyFatal final : public LogMessage {
+class LogMessageQuietly : public LogMessage {
+ public:
+  // All instances of LogMessageQuietly are FATAL. DLOG(QFATAL) calls this
+  // directly instead of LogMessageQuietlyFatal to make sure the destructor is
+  // not [[noreturn]] even if this is always FATAL.
+  LogMessageQuietly(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+  ~LogMessageQuietly();
+};
+
+// Used for LOG(QFATAL) to make sure it's properly understood as [[noreturn]].
+class LogMessageQuietlyFatal final : public LogMessageQuietly {
  public:
   LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
   LogMessageQuietlyFatal(const char* file, int line,
diff --git a/absl/log/internal/strip.h b/absl/log/internal/strip.h
index f8d2786..f944f44 100644
--- a/absl/log/internal/strip.h
+++ b/absl/log/internal/strip.h
@@ -38,6 +38,11 @@
   ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal)
 #define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
   ::absl::log_internal::NullStreamMaybeFatal(absl_log_internal_severity)
+// Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`.
+#define ABSL_LOGGING_INTERNAL_DLOG_QFATAL \
+  ::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal)
+#define ABSL_LOGGING_INTERNAL_DLOG_FATAL \
+  ::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal)
 #define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL
 #define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
   ABSL_LOGGING_INTERNAL_LOG_QFATAL
@@ -60,6 +65,14 @@
 #define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity)      \
   ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
                                    absl_log_internal_severity)
+
+// Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`.
+#define ABSL_LOGGING_INTERNAL_DLOG_QFATAL \
+  ::absl::log_internal::LogMessageQuietly(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_DLOG_FATAL               \
+  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+                                   ::absl::log_internal::LogMessage::FatalTag{})
+
 // These special cases dispatch to special-case constructors that allow us to
 // avoid an extra function call and shrink non-LTO binaries by a percent or so.
 #define ABSL_LOG_INTERNAL_CHECK(failure_message) \
@@ -69,4 +82,11 @@
                                                failure_message)
 #endif  // !defined(STRIP_LOG) || !STRIP_LOG
 
+// This part of a non-fatal `DLOG`s expands the same as `LOG`.
+#define ABSL_LOGGING_INTERNAL_DLOG_INFO ABSL_LOGGING_INTERNAL_LOG_INFO
+#define ABSL_LOGGING_INTERNAL_DLOG_WARNING ABSL_LOGGING_INTERNAL_LOG_WARNING
+#define ABSL_LOGGING_INTERNAL_DLOG_ERROR ABSL_LOGGING_INTERNAL_LOG_ERROR
+#define ABSL_LOGGING_INTERNAL_DLOG_DFATAL ABSL_LOGGING_INTERNAL_LOG_DFATAL
+#define ABSL_LOGGING_INTERNAL_DLOG_LEVEL ABSL_LOGGING_INTERNAL_LOG_LEVEL
+
 #endif  // ABSL_LOG_INTERNAL_STRIP_H_