Add non-public API for internal users

PiperOrigin-RevId: 532553508
Change-Id: I813841ff3e5085b64c9b02ca41897bf7f6a8570e
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
index 873eb5c..6198e72 100644
--- a/absl/status/internal/status_internal.h
+++ b/absl/status/internal/status_internal.h
@@ -66,6 +66,10 @@
 
   std::atomic<int32_t> ref;
   absl::StatusCode code;
+
+  // As an internal implementation detail, we guarantee that if status.message()
+  // is non-empty, then the resulting string_view is null terminated.
+  // This is required to implement 'StatusMessageAsCStr(...)'
   std::string message;
   std::unique_ptr<status_internal::Payloads> payloads;
 };
diff --git a/absl/status/status.cc b/absl/status/status.cc
index d011075..26e6829 100644
--- a/absl/status/status.cc
+++ b/absl/status/status.cc
@@ -616,5 +616,12 @@
 
 }  // namespace status_internal
 
+const char* StatusMessageAsCStr(const Status& status) {
+  // As an internal implementation detail, we guarantee that if status.message()
+  // is non-empty, then the resulting string_view is null terminated.
+  auto sv_message = status.message();
+  return sv_message.empty() ? "" : sv_message.data();
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/status/status.h b/absl/status/status.h
index c6c1cd4..595064c 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -886,6 +886,15 @@
 // message-less kCancelled errors are common in the infrastructure.
 inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
 
+// Retrieves a message's status as a null terminated C string. The lifetime of
+// this string is tied to the lifetime of the status object itself.
+//
+// If the status's message is empty, the empty string is returned.
+//
+// StatusMessageAsCStr exists for C support. Use `status.message()` in C++.
+const char* StatusMessageAsCStr(
+    const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND);
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc
index 74a64ac..898a9cb 100644
--- a/absl/status/status_test.cc
+++ b/absl/status/status_test.cc
@@ -132,6 +132,29 @@
   }
 }
 
+TEST(Status, StatusMessageCStringTest) {
+  {
+    absl::Status status = absl::OkStatus();
+    EXPECT_EQ(status.message(), "");
+    EXPECT_STREQ(absl::StatusMessageAsCStr(status), "");
+    EXPECT_EQ(status.message(), absl::StatusMessageAsCStr(status));
+    EXPECT_NE(absl::StatusMessageAsCStr(status), nullptr);
+  }
+  {
+    absl::Status status;
+    EXPECT_EQ(status.message(), "");
+    EXPECT_NE(absl::StatusMessageAsCStr(status), nullptr);
+    EXPECT_STREQ(absl::StatusMessageAsCStr(status), "");
+  }
+  {
+    absl::Status status(absl::StatusCode::kInternal, "message");
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    EXPECT_EQ("message", status.message());
+    EXPECT_STREQ("message", absl::StatusMessageAsCStr(status));
+  }
+}
+
 TEST(Status, ConstructOutOfRangeCode) {
   const int kRawCode = 9999;
   absl::Status status(static_cast<absl::StatusCode>(kRawCode), "");