Add `absl::down_cast`

PiperOrigin-RevId: 850445526
Change-Id: I15e34dc543dc5aa72ae58ff471410d219fef2444
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index cd633a1..10e6cd1 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -6,6 +6,7 @@
   "algorithm/container.h"
   "base/attributes.h"
   "base/call_once.h"
+  "base/casts.cc"
   "base/casts.h"
   "base/config.h"
   "base/const_init.h"
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 1486722..1d27796 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -257,6 +257,7 @@
 cc_library(
     name = "base",
     srcs = [
+        "casts.cc",
         "internal/cycleclock.cc",
         "internal/spinlock.cc",
         "internal/sysinfo.cc",
@@ -296,8 +297,6 @@
         ":config",
         ":core_headers",
         ":cycleclock_internal",
-        ":dynamic_annotations",
-        ":log_severity",
         ":nullability",
         ":raw_logging_internal",
         ":spinlock_wait",
@@ -612,7 +611,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":base",
-        ":core_headers",
+        ":config",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index e257f99..84decab 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -263,6 +263,7 @@
     "internal/unscaledcycleclock.h"
     "internal/unscaledcycleclock_config.h"
   SRCS
+    "casts.cc"
     "internal/cycleclock.cc"
     "internal/spinlock.cc"
     "internal/sysinfo.cc"
diff --git a/absl/base/casts.cc b/absl/base/casts.cc
new file mode 100644
index 0000000..d864a8c
--- /dev/null
+++ b/absl/base/casts.cc
@@ -0,0 +1,61 @@
+// Copyright 2025 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/casts.h"
+
+#include <cstdlib>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+
+#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
+#include <cxxabi.h>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace base_internal {
+
+namespace {
+
+std::string DemangleCppString(const char* mangled) {
+  std::string out;
+  int status = 0;
+  char* demangled = nullptr;
+#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
+  demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);
+#endif
+  if (status == 0 && demangled != nullptr) {
+    out.append(demangled);
+    free(demangled);
+  } else {
+    out.append(mangled);
+  }
+  return out;
+}
+
+}  // namespace
+
+void BadDownCastCrash(const char* source_type, const char* target_type) {
+  ABSL_RAW_LOG(FATAL, "down cast from %s to %s failed",
+               DemangleCppString(source_type).c_str(),
+               DemangleCppString(target_type).c_str());
+}
+
+}  // namespace base_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/casts.h b/absl/base/casts.h
index 35f5f93..480855a 100644
--- a/absl/base/casts.h
+++ b/absl/base/casts.h
@@ -34,7 +34,10 @@
 #endif  // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/macros.h"
+#include "absl/base/optimization.h"
+#include "absl/base/options.h"
 #include "absl/meta/type_traits.h"
 
 namespace absl {
@@ -191,6 +194,112 @@
 
 #endif  // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
 
+namespace base_internal {
+
+[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void BadDownCastCrash(
+    const char* source_type, const char* target_type);
+
+template <typename To, typename From>
+inline void ValidateDownCast(From* f ABSL_ATTRIBUTE_UNUSED) {
+  // Assert only if RTTI is enabled and in debug mode or hardened asserts are
+  // enabled.
+#ifdef ABSL_INTERNAL_HAS_RTTI
+#if !defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2)
+  // Suppress erroneous nonnull comparison warning on older GCC.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnonnull-compare"
+#endif
+  if (ABSL_PREDICT_FALSE(f != nullptr && dynamic_cast<To>(f) == nullptr)) {
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+    absl::base_internal::BadDownCastCrash(
+        typeid(*f).name(), typeid(std::remove_pointer_t<To>).name());
+  }
+#endif
+#endif
+}
+
+}  // namespace base_internal
+
+// An "upcast", i.e. a conversion from a pointer to an object to a pointer to a
+// base subobject, always succeeds if the base is unambiguous and accessible,
+// and so it's fine to use implicit_cast.
+//
+// A "downcast", i.e. a conversion from a pointer to an object to a pointer
+// to a more-derived object that may contain the original object as a base
+// subobject, cannot safely be done using static_cast, because you do not
+// generally know whether the source object is really the base subobject of
+// a containing, more-derived object of the target type. Thus, when you
+// downcast in a polymorphic type hierarchy, you should use the following
+// function template.
+//
+// This function only returns null when the input is null. In debug mode, we
+// use dynamic_cast to double-check whether the downcast is legal (we die if
+// it's not). In normal mode, we do the efficient static_cast instead. Because
+// the process will die in debug mode, it's important to test to make sure the
+// cast is legal before calling this function!
+//
+// dynamic_cast should be avoided except as allowed by the style guide
+// (https://google.github.io/styleguide/cppguide.html#Run-Time_Type_Information__RTTI_).
+
+template <typename To, typename From>  // use like this: down_cast<T*>(foo);
+[[nodiscard]]
+inline To down_cast(From* f) {  // so we only accept pointers
+  static_assert(std::is_pointer<To>::value, "target type not a pointer");
+  // dynamic_cast allows casting to the same type or a more cv-qualified
+  // version of the same type without them being polymorphic.
+  if constexpr (!std::is_same<std::remove_cv_t<std::remove_pointer_t<To>>,
+                              std::remove_cv_t<From>>::value) {
+    static_assert(std::is_polymorphic<From>::value,
+                  "source type must be polymorphic");
+    static_assert(std::is_polymorphic<std::remove_pointer_t<To>>::value,
+                  "target type must be polymorphic");
+  }
+  static_assert(
+      std::is_convertible<std::remove_cv_t<std::remove_pointer_t<To>>*,
+                          std::remove_cv_t<From>*>::value,
+      "target type not derived from source type");
+
+  absl::base_internal::ValidateDownCast<To>(f);
+
+  return static_cast<To>(f);
+}
+
+// Overload of down_cast for references. Use like this:
+// absl::down_cast<T&>(foo). The code is slightly convoluted because we're still
+// using the pointer form of dynamic cast. (The reference form throws an
+// exception if it fails.)
+//
+// There's no need for a special const overload either for the pointer
+// or the reference form. If you call down_cast with a const T&, the
+// compiler will just bind From to const T.
+template <typename To, typename From>
+[[nodiscard]]
+inline To down_cast(From& f) {
+  static_assert(std::is_lvalue_reference<To>::value,
+                "target type not a reference");
+  // dynamic_cast allows casting to the same type or a more cv-qualified
+  // version of the same type without them being polymorphic.
+  if constexpr (!std::is_same<std::remove_cv_t<std::remove_reference_t<To>>,
+                              std::remove_cv_t<From>>::value) {
+    static_assert(std::is_polymorphic<From>::value,
+                  "source type must be polymorphic");
+    static_assert(std::is_polymorphic<std::remove_reference_t<To>>::value,
+                  "target type must be polymorphic");
+  }
+  static_assert(
+      std::is_convertible<std::remove_cv_t<std::remove_reference_t<To>>*,
+                          std::remove_cv_t<From>*>::value,
+      "target type not derived from source type");
+
+  absl::base_internal::ValidateDownCast<std::remove_reference_t<To>*>(
+      std::addressof(f));
+
+  return static_cast<To>(f);
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/base/casts_test.cc b/absl/base/casts_test.cc
index 25f92cc..772225e 100644
--- a/absl/base/casts_test.cc
+++ b/absl/base/casts_test.cc
@@ -18,40 +18,134 @@
 #include <utility>
 
 #include "gtest/gtest.h"
+#include "absl/base/options.h"
 
 namespace {
 
-struct Base {
-  explicit Base(int value) : x(value) {}
-  Base(const Base& other) = delete;
-  Base& operator=(const Base& other) = delete;
+struct BaseForImplicitCast {
+  explicit BaseForImplicitCast(int value) : x(value) {}
+  BaseForImplicitCast(const BaseForImplicitCast& other) = delete;
+  BaseForImplicitCast& operator=(const BaseForImplicitCast& other) = delete;
   int x;
 };
-struct Derived : Base {
-  explicit Derived(int value) : Base(value) {}
+struct DerivedForImplicitCast : BaseForImplicitCast {
+  explicit DerivedForImplicitCast(int value) : BaseForImplicitCast(value) {}
 };
 
+static_assert(std::is_same_v<decltype(absl::implicit_cast<BaseForImplicitCast&>(
+                                 std::declval<DerivedForImplicitCast&>())),
+                             BaseForImplicitCast&>);
 static_assert(
-    std::is_same_v<
-        decltype(absl::implicit_cast<Base&>(std::declval<Derived&>())), Base&>);
-static_assert(std::is_same_v<decltype(absl::implicit_cast<const Base&>(
-                                 std::declval<Derived>())),
-                             const Base&>);
+    std::is_same_v<decltype(absl::implicit_cast<const BaseForImplicitCast&>(
+                       std::declval<DerivedForImplicitCast>())),
+                   const BaseForImplicitCast&>);
 
 TEST(ImplicitCastTest, LValueReference) {
-  Derived derived(5);
-  EXPECT_EQ(&absl::implicit_cast<Base&>(derived), &derived);
-  EXPECT_EQ(&absl::implicit_cast<const Base&>(derived), &derived);
+  DerivedForImplicitCast derived(5);
+  EXPECT_EQ(&absl::implicit_cast<BaseForImplicitCast&>(derived), &derived);
+  EXPECT_EQ(&absl::implicit_cast<const BaseForImplicitCast&>(derived),
+            &derived);
 }
 
 TEST(ImplicitCastTest, RValueReference) {
-  Derived derived(5);
-  Base&& base = absl::implicit_cast<Base&&>(std::move(derived));
+  DerivedForImplicitCast derived(5);
+  BaseForImplicitCast&& base =
+      absl::implicit_cast<BaseForImplicitCast&&>(std::move(derived));
   EXPECT_EQ(&base, &derived);
 
-  const Derived cderived(6);
-  const Base&& cbase = absl::implicit_cast<const Base&&>(std::move(cderived));
+  const DerivedForImplicitCast cderived(6);
+  const BaseForImplicitCast&& cbase =
+      absl::implicit_cast<const BaseForImplicitCast&&>(std::move(cderived));
   EXPECT_EQ(&cbase, &cderived);
 }
 
+class BaseForDownCast {
+ public:
+  virtual ~BaseForDownCast() = default;
+};
+
+class DerivedForDownCast : public BaseForDownCast {};
+class Derived2ForDownCast : public BaseForDownCast {};
+
+TEST(DownCastTest, Pointer) {
+  DerivedForDownCast derived;
+  BaseForDownCast* const base_ptr = &derived;
+
+  // Tests casting a BaseForDownCast* to a DerivedForDownCast*.
+  EXPECT_EQ(&derived, absl::down_cast<DerivedForDownCast*>(base_ptr));
+
+  // Tests casting a const BaseForDownCast* to a const DerivedForDownCast*.
+  const BaseForDownCast* const_base_ptr = base_ptr;
+  EXPECT_EQ(&derived,
+            absl::down_cast<const DerivedForDownCast*>(const_base_ptr));
+
+  // Tests casting a BaseForDownCast* to a const DerivedForDownCast*.
+  EXPECT_EQ(&derived, absl::down_cast<const DerivedForDownCast*>(base_ptr));
+
+  // Tests casting a BaseForDownCast* to a BaseForDownCast* (an identity cast).
+  EXPECT_EQ(base_ptr, absl::down_cast<BaseForDownCast*>(base_ptr));
+
+  // Tests down casting NULL.
+  EXPECT_EQ(nullptr,
+            (absl::down_cast<DerivedForDownCast*, BaseForDownCast>(nullptr)));
+
+  // Tests a bad downcast. We have to disguise the badness just enough
+  // that the compiler doesn't warn about it at compile time.
+  BaseForDownCast* base2 = new BaseForDownCast();
+#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \
+                                                  ABSL_OPTION_HARDENED == 2))
+  EXPECT_DEATH(static_cast<void>(absl::down_cast<DerivedForDownCast*>(base2)),
+               ".*down cast from .*BaseForDownCast.* to "
+               ".*DerivedForDownCast.* failed.*");
+#endif
+  delete base2;
+}
+
+TEST(DownCastTest, Reference) {
+  DerivedForDownCast derived;
+  BaseForDownCast& base_ref = derived;
+
+  // Tests casting a BaseForDownCast& to a DerivedForDownCast&.
+  // NOLINTNEXTLINE(runtime/casting)
+  EXPECT_EQ(&derived, &absl::down_cast<DerivedForDownCast&>(base_ref));
+
+  // Tests casting a const BaseForDownCast& to a const DerivedForDownCast&.
+  const BaseForDownCast& const_base_ref = base_ref;
+  // NOLINTNEXTLINE(runtime/casting)
+  EXPECT_EQ(&derived,
+            &absl::down_cast<const DerivedForDownCast&>(const_base_ref));
+
+  // Tests casting a BaseForDownCast& to a const DerivedForDownCast&.
+  // NOLINTNEXTLINE(runtime/casting)
+  EXPECT_EQ(&derived, &absl::down_cast<const DerivedForDownCast&>(base_ref));
+
+  // Tests casting a BaseForDownCast& to a BaseForDownCast& (an identity cast).
+  // NOLINTNEXTLINE(runtime/casting)
+  EXPECT_EQ(&base_ref, &absl::down_cast<BaseForDownCast&>(base_ref));
+
+  // Tests a bad downcast. We have to disguise the badness just enough
+  // that the compiler doesn't warn about it at compile time.
+  BaseForDownCast& base2 = *new BaseForDownCast();
+#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \
+                                                  ABSL_OPTION_HARDENED == 2))
+  EXPECT_DEATH(static_cast<void>(absl::down_cast<DerivedForDownCast&>(base2)),
+               ".*down cast from .*BaseForDownCast.* to "
+               ".*DerivedForDownCast.* failed.*");
+#endif
+  delete &base2;
+}
+
+TEST(DownCastTest, ErrorMessage) {
+  DerivedForDownCast derived;
+  BaseForDownCast& base = derived;
+  (void)base;
+
+#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \
+                                                  ABSL_OPTION_HARDENED == 2))
+  EXPECT_DEATH(static_cast<void>(absl::down_cast<Derived2ForDownCast&>(base)),
+               ".*down cast from .*DerivedForDownCast.* to "
+               ".*Derived2ForDownCast.* failed.*");
+#endif
+}
+
 }  // namespace