Mark NOTREACHED as [[noreturn]]

This prevents compiler errors when you write NOTREACHED but do not add a
return statement.

Change-Id: Ic878ba3e89e1e933a1288a3972505f736a6a6964
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/25601
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: Matt Stark <msta@google.com>
diff --git a/src/base/logging.cc b/src/base/logging.cc
index e8929c1..2e1dc6e 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -7,6 +7,7 @@
 #include <limits.h>
 #include <stdint.h>
 
+#include <cstdlib>
 #include <iterator>
 #include <thread>
 
@@ -186,6 +187,26 @@
   }
 }
 
+NotReachedLogMessage::NotReachedLogMessage(const char* file, int line)
+    : log_message_(std::in_place, file, line, LOG_FATAL) {}
+
+// Suppress MSVC warning "destructor never returns, potential memory leak".
+#if defined(COMPILER_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+NotReachedLogMessage::~NotReachedLogMessage() {
+  log_message_.reset();
+  IMMEDIATE_CRASH();
+}
+#if defined(COMPILER_MSVC)
+#pragma warning(pop)
+#endif
+
+std::ostream& NotReachedLogMessage::stream() {
+  return log_message_->stream();
+}
+
 // writes the common header info to the stream
 void LogMessage::Init(const char* file, int line) {
   std::string_view filename(file);
diff --git a/src/base/logging.h b/src/base/logging.h
index a5b3e55..e08d386 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -9,6 +9,7 @@
 
 #include <cassert>
 #include <cstring>
+#include <optional>
 #include <sstream>
 #include <string>
 #include <string_view>
@@ -729,8 +730,6 @@
 #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
 #define DCHECK_GT(val1, val2) DCHECK_OP(GT, >, val1, val2)
 
-#define NOTREACHED() DCHECK(false)
-
 // Redefine the standard assert to use our nice log files
 #undef assert
 #define assert(x) DLOG_ASSERT(x)
@@ -800,6 +799,20 @@
   LogMessage& operator=(const LogMessage&) = delete;
 };
 
+class NotReachedLogMessage {
+ public:
+  NotReachedLogMessage(const char* file, int line);
+  [[noreturn]] ~NotReachedLogMessage();
+
+  std::ostream& stream();
+
+ private:
+  std::optional<LogMessage> log_message_;
+
+  NotReachedLogMessage(const NotReachedLogMessage&) = delete;
+  NotReachedLogMessage& operator=(const NotReachedLogMessage&) = delete;
+};
+
 // This class is used to explicitly ignore values in the conditional
 // logging macros.  This avoids compiler warnings like "value computed
 // is not used" and "statement has no effect".
@@ -811,6 +824,10 @@
   void operator&(std::ostream&) {}
 };
 
+#define NOTREACHED()               \
+  ::logging::LogMessageVoidify() & \
+      ::logging::NotReachedLogMessage(__FILE__, __LINE__).stream()
+
 #if defined(OS_WIN)
 typedef unsigned long SystemErrorCode;
 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)