[libcxx-commits] [libcxx] [libcxxabi] [libcxx] Use alias for detecting overriden function (PR #114961)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 26 11:16:00 PST 2024


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/114961

>From 02cffe21d36f820fe88e8c900738dbd526a998b0 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Sat, 19 Oct 2024 15:12:41 -0700
Subject: [PATCH 1/6] [libcxx] Use alias for detecting overriden function

This mechanism is preferable in environments like embedded since it
doesn't require special handling of the custom section.
---
 libcxx/src/include/overridable_function.h | 115 +++++++++-------------
 libcxx/src/new.cpp                        |  20 ++--
 2 files changed, 58 insertions(+), 77 deletions(-)

diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index 6c70f6242ddd63..09487d84df8b50 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -29,7 +29,7 @@
 // This is a low-level utility which does not work on all platforms, since it needs
 // to make assumptions about the object file format in use. Furthermore, it requires
 // the "base definition" of the function (the one we want to check whether it has been
-// overridden) to be annotated with the _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE macro.
+// overridden) to be defined using the _LIBCPP_OVERRIDABLE_FUNCTION macro.
 //
 // This currently works with Mach-O files (used on Darwin) and with ELF files (used on Linux
 // and others). On platforms where we know how to implement this detection, the macro
@@ -42,93 +42,74 @@
 // -------------------
 //
 // Let's say we want to check whether a weak function `f` has been overridden by the user.
-// The general mechanism works by placing `f`'s definition (in the libc++ built library)
-// inside a special section, which we do using the `__section__` attribute via the
-// _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE macro.
+// The general mechanism works by defining a symbol `f_impl__` and a weak alias `f` via the
+// _LIBCPP_OVERRIDABLE_FUNCTION macro.
 //
 // Then, when comes the time to check whether the function has been overridden, we take
-// the address of the function and we check whether it falls inside the special function
-// we created. This can be done by finding pointers to the start and the end of the section
-// (which is done differently for ELF and Mach-O), and then checking whether `f` falls
-// within those bounds. If it falls within those bounds, then `f` is still inside the
-// special section and so it is the version we defined in the libc++ built library, i.e.
-// it was not overridden. Otherwise, it was overridden by the user because it falls
-// outside of the section.
+// the address of the function `f` and we check whether it is different from `f_impl__`.
+// If so it means the function was overriden by the user.
 //
 // Important note
 // --------------
 //
-// This mechanism should never be used outside of the libc++ built library. In particular,
-// attempting to use this within the libc++ headers will not work at all because we don't
-// want to be defining special sections inside user's executables which use our headers.
+// This mechanism should never be used outside of the libc++ built library.
 //
 
 #if defined(_LIBCPP_OBJECT_FORMAT_MACHO)
 
-#  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
-#  define _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE                                                                 \
-    __attribute__((__section__("__TEXT,__lcxx_override,regular,pure_instructions")))
-
 _LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Ret, class... _Args>
-_LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) noexcept {
-  // Declare two dummy bytes and give them these special `__asm` values. These values are
-  // defined by the linker, which means that referring to `&__lcxx_override_start` will
-  // effectively refer to the address where the section starts (and same for the end).
-  extern char __lcxx_override_start __asm("section$start$__TEXT$__lcxx_override");
-  extern char __lcxx_override_end __asm("section$end$__TEXT$__lcxx_override");
-
-  // Now get a uintptr_t out of these locations, and out of the function pointer.
-  uintptr_t __start = reinterpret_cast<uintptr_t>(&__lcxx_override_start);
-  uintptr_t __end   = reinterpret_cast<uintptr_t>(&__lcxx_override_end);
-  uintptr_t __ptr   = reinterpret_cast<uintptr_t>(__fptr);
-
-#  if __has_feature(ptrauth_calls)
-  // We must pass a void* to ptrauth_strip since it only accepts a pointer type. Also, in particular,
-  // we must NOT pass a function pointer, otherwise we will strip the function pointer, and then attempt
-  // to authenticate and re-sign it when casting it to a uintptr_t again, which will fail because we just
-  // stripped the function pointer. See rdar://122927845.
-  __ptr = reinterpret_cast<uintptr_t>(ptrauth_strip(reinterpret_cast<void*>(__ptr), ptrauth_key_function_pointer));
-#  endif
-
-  // Finally, the function was overridden if it falls outside of the section's bounds.
-  return __ptr < __start || __ptr > __end;
-}
-_LIBCPP_END_NAMESPACE_STD
 
-// The NVPTX linker cannot create '__start/__stop' sections.
-#elif defined(_LIBCPP_OBJECT_FORMAT_ELF) && !defined(__NVPTX__)
+template <typename _Func>
+constexpr _Func* __overload_of(_Func* f) { return f; }
 
-#  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
-#  define _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE __attribute__((__section__("__lcxx_override")))
+template <auto _Func>
+constexpr bool __is_function_overridden();
 
-// This is very similar to what we do for Mach-O above. The ELF linker will implicitly define
-// variables with those names corresponding to the start and the end of the section.
-//
-// See https://stackoverflow.com/questions/16552710/how-do-you-get-the-start-and-end-addresses-of-a-custom-elf-section
-extern char __start___lcxx_override;
-extern char __stop___lcxx_override;
+_LIBCPP_END_NAMESPACE_STD
+
+#  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
+#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) \
+  extern "C" type symbol##_impl__ arglist; \
+  __asm__(".globl _" _LIBCPP_TOSTRING(symbol)); \
+  __asm__(".set _" _LIBCPP_TOSTRING(symbol) ", _" _LIBCPP_TOSTRING(symbol##_impl__)); \
+  extern __typeof(symbol##_impl__) name __attribute__((weak_import)); \
+  _LIBCPP_BEGIN_NAMESPACE_STD \
+  template <> \
+  constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() { \
+    return __overload_of<type arglist>(name) != symbol##_impl__; \
+  } \
+  _LIBCPP_END_NAMESPACE_STD \
+  type symbol##_impl__ arglist
+
+#elif defined(_LIBCPP_OBJECT_FORMAT_ELF)
 
 _LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Ret, class... _Args>
-_LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) noexcept {
-  uintptr_t __start = reinterpret_cast<uintptr_t>(&__start___lcxx_override);
-  uintptr_t __end   = reinterpret_cast<uintptr_t>(&__stop___lcxx_override);
-  uintptr_t __ptr   = reinterpret_cast<uintptr_t>(__fptr);
-
-#  if __has_feature(ptrauth_calls)
-  // We must pass a void* to ptrauth_strip since it only accepts a pointer type. See full explanation above.
-  __ptr = reinterpret_cast<uintptr_t>(ptrauth_strip(reinterpret_cast<void*>(__ptr), ptrauth_key_function_pointer));
-#  endif
-
-  return __ptr < __start || __ptr > __end;
-}
+
+template <typename _Func>
+constexpr _Func* __overload_of(_Func* f) { return f; }
+
+template <auto _Func>
+constexpr bool __is_function_overridden();
+
 _LIBCPP_END_NAMESPACE_STD
 
+#  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
+#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) \
+  extern "C" type symbol##_impl__ arglist; \
+  [[gnu::weak, gnu::alias(_LIBCPP_TOSTRING(symbol##_impl__))]] type name arglist; \
+  _LIBCPP_BEGIN_NAMESPACE_STD \
+  template <> \
+  constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() { \
+    return __overload_of<type arglist>(name) != symbol##_impl__; \
+  } \
+  _LIBCPP_END_NAMESPACE_STD \
+  type symbol##_impl__ arglist
+
 #else
 
 #  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 0
-#  define _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE /* nothing */
+#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) \
+  _LIBCPP_WEAK type name arglist
 
 #endif
 
diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index b0c731678cac30..3e99aed455c4b5 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -43,7 +43,7 @@ static void* operator_new_impl(std::size_t size) {
   return p;
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_Znmw, void *, operator new, (std::size_t size)) _THROW_BAD_ALLOC {
   void* p = operator_new_impl(size);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -54,7 +54,7 @@ _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
 #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
+      !std::__is_function_overridden<std::__overload_of<void* (std::size_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
       "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
@@ -74,7 +74,7 @@ _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
 #  endif
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_Znam, void*, operator new[], (size_t size)) _THROW_BAD_ALLOC {
   return ::operator new(size);
 }
 
@@ -82,7 +82,7 @@ _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
 #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
+      !std::__is_function_overridden<std::__overload_of<void* (std::size_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
       "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
@@ -136,8 +136,9 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm
   return p;
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
-operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
+//_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
+//operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_ZnwmSt11align_val_t, void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {
   void* p = operator_new_aligned_impl(size, alignment);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -148,7 +149,7 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s
 #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
+      !std::__is_function_overridden<std::__overload_of<void* (std::size_t, std::align_val_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
       "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
@@ -168,8 +169,7 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s
 #    endif
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
-operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_ZnamSt11align_val_t, void *, operator new[], (size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {
   return ::operator new(size, alignment);
 }
 
@@ -177,7 +177,7 @@ _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const
 #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
+      !std::__is_function_overridden<std::__overload_of<void* (std::size_t, std::align_val_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
       "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "

>From 87c86275a06e815cd11a084f37c9f5ae0c78dd3c Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Tue, 5 Nov 2024 22:07:35 -0800
Subject: [PATCH 2/6] Review feedback

---
 libcxx/src/include/overridable_function.h | 21 +++++++++++----------
 libcxx/src/new.cpp                        |  2 --
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index 09487d84df8b50..8a68e69011d1c8 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -34,9 +34,9 @@
 // This currently works with Mach-O files (used on Darwin) and with ELF files (used on Linux
 // and others). On platforms where we know how to implement this detection, the macro
 // _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION is defined to 1, and it is defined to 0 on
-// other platforms. The _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE macro is defined to
-// nothing on unsupported platforms so that it can be used to decorate functions regardless
-// of whether detection is actually supported.
+// other platforms. The _LIBCPP_OVERRIDABLE_FUNCTION macro expands to regular function
+// definition on unsupported platforms so that it can be used to decorate functions
+// regardless of whether detection is actually supported.
 //
 // How does this work?
 // -------------------
@@ -52,18 +52,19 @@
 // Important note
 // --------------
 //
-// This mechanism should never be used outside of the libc++ built library.
+// This mechanism should never be used outside of the libc++ built library. Functions defined
+// with this macro must be defined at global scope.
 //
 
 #if defined(_LIBCPP_OBJECT_FORMAT_MACHO)
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <typename _Func>
-constexpr _Func* __overload_of(_Func* f) { return f; }
+template <class _Func>
+_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) { return f; }
 
 template <auto _Func>
-constexpr bool __is_function_overridden();
+_LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
 
 _LIBCPP_END_NAMESPACE_STD
 
@@ -85,11 +86,11 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <typename _Func>
-constexpr _Func* __overload_of(_Func* f) { return f; }
+template <class _Func>
+_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) { return f; }
 
 template <auto _Func>
-constexpr bool __is_function_overridden();
+_LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index 3e99aed455c4b5..4d5db33d143c01 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -136,8 +136,6 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm
   return p;
 }
 
-//_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
-//operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
 _LIBCPP_OVERRIDABLE_FUNCTION(_ZnwmSt11align_val_t, void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {
   void* p = operator_new_aligned_impl(size, alignment);
   if (p == nullptr)

>From d7add3367a940c7faa9cb2fcdab44699b1a5913d Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Tue, 5 Nov 2024 22:36:33 -0800
Subject: [PATCH 3/6] Fix formatting

---
 libcxx/src/include/overridable_function.h | 55 ++++++++++++-----------
 libcxx/src/new.cpp                        | 16 ++++---
 2 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index 8a68e69011d1c8..0ce9f9c1cee50d 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -61,7 +61,9 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Func>
-_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) { return f; }
+_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) {
+  return f;
+}
 
 template <auto _Func>
 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
@@ -69,25 +71,27 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
 _LIBCPP_END_NAMESPACE_STD
 
 #  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
-#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) \
-  extern "C" type symbol##_impl__ arglist; \
-  __asm__(".globl _" _LIBCPP_TOSTRING(symbol)); \
-  __asm__(".set _" _LIBCPP_TOSTRING(symbol) ", _" _LIBCPP_TOSTRING(symbol##_impl__)); \
-  extern __typeof(symbol##_impl__) name __attribute__((weak_import)); \
-  _LIBCPP_BEGIN_NAMESPACE_STD \
-  template <> \
-  constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() { \
-    return __overload_of<type arglist>(name) != symbol##_impl__; \
-  } \
-  _LIBCPP_END_NAMESPACE_STD \
-  type symbol##_impl__ arglist
+#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist)                                                    \
+    extern "C" type symbol##_impl__ arglist;                                                                           \
+    __asm__(".globl _" _LIBCPP_TOSTRING(symbol));                                                                      \
+    __asm__(".set _" _LIBCPP_TOSTRING(symbol) ", _" _LIBCPP_TOSTRING(symbol##_impl__));                                \
+    extern __typeof(symbol##_impl__) name __attribute__((weak_import));                                                \
+    _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
+    template <>                                                                                                        \
+    constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() {                                     \
+      return __overload_of<type arglist>(name) != symbol##_impl__;                                                     \
+    }                                                                                                                  \
+    _LIBCPP_END_NAMESPACE_STD                                                                                          \
+    type symbol##_impl__ arglist
 
 #elif defined(_LIBCPP_OBJECT_FORMAT_ELF)
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Func>
-_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) { return f; }
+_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) {
+  return f;
+}
 
 template <auto _Func>
 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
@@ -95,22 +99,21 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
 _LIBCPP_END_NAMESPACE_STD
 
 #  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
-#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) \
-  extern "C" type symbol##_impl__ arglist; \
-  [[gnu::weak, gnu::alias(_LIBCPP_TOSTRING(symbol##_impl__))]] type name arglist; \
-  _LIBCPP_BEGIN_NAMESPACE_STD \
-  template <> \
-  constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() { \
-    return __overload_of<type arglist>(name) != symbol##_impl__; \
-  } \
-  _LIBCPP_END_NAMESPACE_STD \
-  type symbol##_impl__ arglist
+#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist)                                                    \
+    extern "C" type symbol##_impl__ arglist;                                                                           \
+    [[gnu::weak, gnu::alias(_LIBCPP_TOSTRING(symbol##_impl__))]] type name arglist;                                    \
+    _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
+    template <>                                                                                                        \
+    constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() {                                     \
+      return __overload_of<type arglist>(name) != symbol##_impl__;                                                     \
+    }                                                                                                                  \
+    _LIBCPP_END_NAMESPACE_STD                                                                                          \
+    type symbol##_impl__ arglist
 
 #else
 
 #  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 0
-#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) \
-  _LIBCPP_WEAK type name arglist
+#  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist) _LIBCPP_WEAK type name arglist
 
 #endif
 
diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index 4d5db33d143c01..73bde4ac04b34e 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -43,7 +43,7 @@ static void* operator_new_impl(std::size_t size) {
   return p;
 }
 
-_LIBCPP_OVERRIDABLE_FUNCTION(_Znmw, void *, operator new, (std::size_t size)) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_Znmw, void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC {
   void* p = operator_new_impl(size);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -54,7 +54,7 @@ _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
 #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void* (std::size_t)>(&operator new)>(),
+      !std::__is_function_overridden<std::__overload_of<void*(std::size_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
       "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
@@ -82,7 +82,7 @@ _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
 #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void* (std::size_t)>(&operator new[])>(),
+      !std::__is_function_overridden<std::__overload_of<void*(std::size_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
       "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
@@ -136,7 +136,8 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm
   return p;
 }
 
-_LIBCPP_OVERRIDABLE_FUNCTION(_ZnwmSt11align_val_t, void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_ZnwmSt11align_val_t, void*, operator new, (std::size_t size, std::align_val_t alignment))
+_THROW_BAD_ALLOC {
   void* p = operator_new_aligned_impl(size, alignment);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -147,7 +148,7 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s
 #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void* (std::size_t, std::align_val_t)>(&operator new)>(),
+      !std::__is_function_overridden<std::__overload_of<void*(std::size_t, std::align_val_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
       "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
@@ -167,7 +168,8 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s
 #    endif
 }
 
-_LIBCPP_OVERRIDABLE_FUNCTION(_ZnamSt11align_val_t, void *, operator new[], (size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_ZnamSt11align_val_t, void*, operator new[], (size_t size, std::align_val_t alignment))
+_THROW_BAD_ALLOC {
   return ::operator new(size, alignment);
 }
 
@@ -175,7 +177,7 @@ _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const
 #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void* (std::size_t, std::align_val_t)>(&operator new[])>(),
+      !std::__is_function_overridden<std::__overload_of<void*(std::size_t, std::align_val_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
       "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "

>From ab62cfd940a816f51323833c2123e6fcf08a430d Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Wed, 6 Nov 2024 11:56:47 -0800
Subject: [PATCH 4/6] Use `static_cast`

---
 libcxx/src/include/overridable_function.h | 18 ++-----
 libcxx/src/new.cpp                        | 14 +++--
 libcxxabi/src/stdlib_new_delete.cpp       | 64 +++++++++++------------
 3 files changed, 41 insertions(+), 55 deletions(-)

diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index 0ce9f9c1cee50d..bae4327d99012a 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -60,11 +60,6 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Func>
-_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) {
-  return f;
-}
-
 template <auto _Func>
 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
 
@@ -78,8 +73,8 @@ _LIBCPP_END_NAMESPACE_STD
     extern __typeof(symbol##_impl__) name __attribute__((weak_import));                                                \
     _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
     template <>                                                                                                        \
-    constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() {                                     \
-      return __overload_of<type arglist>(name) != symbol##_impl__;                                                     \
+    constexpr bool __is_function_overridden<static_cast<type(*) arglist>(name)>() {                                    \
+      return static_cast<type(*) arglist>(name) != symbol##_impl__;                                                    \
     }                                                                                                                  \
     _LIBCPP_END_NAMESPACE_STD                                                                                          \
     type symbol##_impl__ arglist
@@ -88,11 +83,6 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Func>
-_LIBCPP_HIDE_FROM_ABI constexpr _Func* __overload_of(_Func* f) {
-  return f;
-}
-
 template <auto _Func>
 _LIBCPP_HIDE_FROM_ABI constexpr bool __is_function_overridden();
 
@@ -104,8 +94,8 @@ _LIBCPP_END_NAMESPACE_STD
     [[gnu::weak, gnu::alias(_LIBCPP_TOSTRING(symbol##_impl__))]] type name arglist;                                    \
     _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
     template <>                                                                                                        \
-    constexpr bool __is_function_overridden<__overload_of<type arglist>(name)>() {                                     \
-      return __overload_of<type arglist>(name) != symbol##_impl__;                                                     \
+    constexpr bool __is_function_overridden<static_cast<type(*) arglist>(name)>() {                                    \
+      return static_cast<type(*) arglist>(name) != symbol##_impl__;                                                    \
     }                                                                                                                  \
     _LIBCPP_END_NAMESPACE_STD                                                                                          \
     type symbol##_impl__ arglist
diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp
index 73bde4ac04b34e..a5b1a5921c9199 100644
--- a/libcxx/src/new.cpp
+++ b/libcxx/src/new.cpp
@@ -43,7 +43,7 @@ static void* operator_new_impl(std::size_t size) {
   return p;
 }
 
-_LIBCPP_OVERRIDABLE_FUNCTION(_Znmw, void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_Znwm, void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC {
   void* p = operator_new_impl(size);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -54,7 +54,7 @@ _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
 #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void*(std::size_t)>(&operator new)>(),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
       "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
@@ -82,7 +82,7 @@ _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
 #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void*(std::size_t)>(&operator new[])>(),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
       "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
@@ -148,7 +148,7 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s
 #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void*(std::size_t, std::align_val_t)>(&operator new)>(),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
       "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
@@ -169,15 +169,13 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s
 }
 
 _LIBCPP_OVERRIDABLE_FUNCTION(_ZnamSt11align_val_t, void*, operator new[], (size_t size, std::align_val_t alignment))
-_THROW_BAD_ALLOC {
-  return ::operator new(size, alignment);
-}
+_THROW_BAD_ALLOC { return ::operator new(size, alignment); }
 
 _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
 #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
 #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden<std::__overload_of<void*(std::size_t, std::align_val_t)>(&operator new[])>(),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
       "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp
index b802559d479e2c..1dd651fd99bbdd 100644
--- a/libcxxabi/src/stdlib_new_delete.cpp
+++ b/libcxxabi/src/stdlib_new_delete.cpp
@@ -63,7 +63,7 @@ static void* operator_new_impl(std::size_t size) {
   return p;
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_Znwm, void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC {
   void* p = operator_new_impl(size);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -71,55 +71,55 @@ _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std
 }
 
 _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
-#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
-#  if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+#  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
       "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
       "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "
       "contract (since it should return nullptr upon failure). Please make sure you override "
       "`operator new(size_t, nothrow_t)` as well.");
-#  endif
+#    endif
 
   return operator_new_impl(size);
-#else
+#  else
   void* p = nullptr;
   try {
     p = ::operator new(size);
   } catch (...) {
   }
   return p;
-#endif
+#  endif
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_Znam, void*, operator new[], (size_t size)) _THROW_BAD_ALLOC {
   return ::operator new(size);
 }
 
 _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
-#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
-#  if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+#  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
       "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
       "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
       "contract (since it should return nullptr upon failure). Please make sure you override "
       "`operator new[](size_t, nothrow_t)` as well.");
-#  endif
+#    endif
 
   return operator_new_impl(size);
-#else
+#  else
   void* p = nullptr;
   try {
     p = ::operator new[](size);
   } catch (...) {
   }
   return p;
-#endif
+#  endif
 }
 
 _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
@@ -134,7 +134,7 @@ _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept {
 
 _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
 
-#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
+#  if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
 
 static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
   if (size == 0)
@@ -156,8 +156,8 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm
   return p;
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
-operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
+_LIBCPP_OVERRIDABLE_FUNCTION(_ZnwmSt11align_val_t, void*, operator new, (std::size_t size, std::align_val_t alignment))
+_THROW_BAD_ALLOC {
   void* p = operator_new_aligned_impl(size, alignment);
   if (p == nullptr)
     __throw_bad_alloc_shim();
@@ -165,39 +165,37 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
 }
 
 _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
-#  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
-#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+#    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+#      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)>(),
       "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
       "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
       "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
       "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
       "`operator new(size_t, align_val_t, nothrow_t)` as well.");
-#    endif
+#      endif
 
   return operator_new_aligned_impl(size, alignment);
-#  else
+#    else
   void* p = nullptr;
   try {
     p = ::operator new(size, alignment);
   } catch (...) {
   }
   return p;
-#  endif
+#    endif
 }
 
-_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
-operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
-  return ::operator new(size, alignment);
-}
+_LIBCPP_OVERRIDABLE_FUNCTION(_ZnamSt11align_val_t, void*, operator new[], (size_t size, std::align_val_t alignment))
+_THROW_BAD_ALLOC { return ::operator new(size, alignment); }
 
 _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
-#  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
-#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+#    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+#      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
   _LIBCPP_ASSERT_SHIM(
-      !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
+      !std::__is_function_overridden<static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])>(),
       "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
       "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
       "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
@@ -205,17 +203,17 @@ _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const
       "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
       "override "
       "`operator new[](size_t, align_val_t, nothrow_t)` as well.");
-#    endif
+#      endif
 
   return operator_new_aligned_impl(size, alignment);
-#  else
+#    else
   void* p = nullptr;
   try {
     p = ::operator new[](size, alignment);
   } catch (...) {
   }
   return p;
-#  endif
+#    endif
 }
 
 _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }

>From c2f4b04784c1a3bbd9c15a904e59915d7f43baed Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Wed, 6 Nov 2024 13:00:13 -0800
Subject: [PATCH 5/6] Use static symbols

---
 libcxx/src/include/overridable_function.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index bae4327d99012a..ad67ae21f54899 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -67,7 +67,7 @@ _LIBCPP_END_NAMESPACE_STD
 
 #  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
 #  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist)                                                    \
-    extern "C" type symbol##_impl__ arglist;                                                                           \
+    static type symbol##_impl__ arglist __asm__(_LIBCPP_TOSTRING(symbol##_impl__));                                    \
     __asm__(".globl _" _LIBCPP_TOSTRING(symbol));                                                                      \
     __asm__(".set _" _LIBCPP_TOSTRING(symbol) ", _" _LIBCPP_TOSTRING(symbol##_impl__));                                \
     extern __typeof(symbol##_impl__) name __attribute__((weak_import));                                                \
@@ -77,7 +77,7 @@ _LIBCPP_END_NAMESPACE_STD
       return static_cast<type(*) arglist>(name) != symbol##_impl__;                                                    \
     }                                                                                                                  \
     _LIBCPP_END_NAMESPACE_STD                                                                                          \
-    type symbol##_impl__ arglist
+    static type symbol##_impl__ arglist
 
 #elif defined(_LIBCPP_OBJECT_FORMAT_ELF)
 
@@ -90,7 +90,7 @@ _LIBCPP_END_NAMESPACE_STD
 
 #  define _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 1
 #  define _LIBCPP_OVERRIDABLE_FUNCTION(symbol, type, name, arglist)                                                    \
-    extern "C" type symbol##_impl__ arglist;                                                                           \
+    static type symbol##_impl__ arglist __asm__(_LIBCPP_TOSTRING(symbol##_impl__));                                    \
     [[gnu::weak, gnu::alias(_LIBCPP_TOSTRING(symbol##_impl__))]] type name arglist;                                    \
     _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
     template <>                                                                                                        \
@@ -98,7 +98,7 @@ _LIBCPP_END_NAMESPACE_STD
       return static_cast<type(*) arglist>(name) != symbol##_impl__;                                                    \
     }                                                                                                                  \
     _LIBCPP_END_NAMESPACE_STD                                                                                          \
-    type symbol##_impl__ arglist
+    static type symbol##_impl__ arglist
 
 #else
 

>From dea7e3653d8f0c581a0cc7624cdceecb21664f97 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 7 Nov 2024 10:55:47 -0800
Subject: [PATCH 6/6] Remove `constexpr`

---
 libcxx/src/include/overridable_function.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index ad67ae21f54899..51428d76d47dca 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -73,7 +73,7 @@ _LIBCPP_END_NAMESPACE_STD
     extern __typeof(symbol##_impl__) name __attribute__((weak_import));                                                \
     _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
     template <>                                                                                                        \
-    constexpr bool __is_function_overridden<static_cast<type(*) arglist>(name)>() {                                    \
+    bool __is_function_overridden<static_cast<type(*) arglist>(name)>() {                                              \
       return static_cast<type(*) arglist>(name) != symbol##_impl__;                                                    \
     }                                                                                                                  \
     _LIBCPP_END_NAMESPACE_STD                                                                                          \
@@ -94,7 +94,7 @@ _LIBCPP_END_NAMESPACE_STD
     [[gnu::weak, gnu::alias(_LIBCPP_TOSTRING(symbol##_impl__))]] type name arglist;                                    \
     _LIBCPP_BEGIN_NAMESPACE_STD                                                                                        \
     template <>                                                                                                        \
-    constexpr bool __is_function_overridden<static_cast<type(*) arglist>(name)>() {                                    \
+    bool __is_function_overridden<static_cast<type(*) arglist>(name)>() {                                              \
       return static_cast<type(*) arglist>(name) != symbol##_impl__;                                                    \
     }                                                                                                                  \
     _LIBCPP_END_NAMESPACE_STD                                                                                          \



More information about the libcxx-commits mailing list