[libcxx-commits] [libcxx] [libc++] Define behaviour for calling target() and target_type() on -fno-rtti std::functions (PR #209471)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 30 04:44:19 PDT 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/209471
>From 7baeddbc0fb3aba0a152870d326438a71b451721 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 14 Jul 2026 15:05:59 +0200
Subject: [PATCH] [libc++] Define behaviour for calling target() and
target_type() on -fno-rtti std::functions
---
libcxx/include/__functional/function.h | 22 ++++++++---
.../func.wrap.func/rtti_mixing.assert.sh.cpp | 39 +++++++++++++++++++
2 files changed, 55 insertions(+), 6 deletions(-)
create mode 100644 libcxx/test/extensions/libcxx/utilities/function.objects/func.wrap/func.wrap.func/rtti_mixing.assert.sh.cpp
diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index 0adc336424e2e..dbfa4b84f1b0e 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -145,10 +145,12 @@ class __base<_Rp(_ArgTypes...)> {
virtual void destroy() _NOEXCEPT = 0;
virtual void destroy_deallocate() _NOEXCEPT = 0;
virtual _Rp operator()(_ArgTypes&&...) = 0;
-# if _LIBCPP_HAS_RTTI
- virtual const void* target(const type_info&) const _NOEXCEPT = 0;
- virtual const std::type_info& target_type() const _NOEXCEPT = 0;
-# endif // _LIBCPP_HAS_RTTI
+ virtual const void* target(const type_info&) const _NOEXCEPT {
+ _LIBCPP_ASSERT_NON_NULL(false, "Trying to access type_info of std::function created in -fno-rtti mode!");
+ }
+ virtual const std::type_info& target_type() const _NOEXCEPT {
+ _LIBCPP_ASSERT_NON_NULL(false, "Trying to access type_info of std::function created in -fno-rtti-mode!");
+ }
};
_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
@@ -516,11 +518,19 @@ class __policy_func<_Rp(_ArgTypes...)> {
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return !__policy_->__is_null; }
# if _LIBCPP_HAS_RTTI
- _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT { return *__policy_->__type_info; }
+ _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT {
+ _LIBCPP_ASSERT_NON_NULL(
+ __policy_->__type_info, "Trying to access type_info of std::functions created in -fno-rtti mode!");
+ return *__policy_->__type_info;
+ }
template <typename _Tp>
_LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT {
- if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info)
+ if (__policy_->__is_null)
+ return nullptr;
+ _LIBCPP_ASSERT_NON_NULL(
+ __policy_->__type_info, "Trying to access type_info of std::function created in -fno-rtti mode!");
+ if (typeid(_Tp) != *__policy_->__type_info)
return nullptr;
if (__policy_->__clone) // Out of line storage.
return reinterpret_cast<const _Tp*>(__buf_.__large);
diff --git a/libcxx/test/extensions/libcxx/utilities/function.objects/func.wrap/func.wrap.func/rtti_mixing.assert.sh.cpp b/libcxx/test/extensions/libcxx/utilities/function.objects/func.wrap/func.wrap.func/rtti_mixing.assert.sh.cpp
new file mode 100644
index 0000000000000..5240a2d604fab
--- /dev/null
+++ b/libcxx/test/extensions/libcxx/utilities/function.objects/func.wrap/func.wrap.func/rtti_mixing.assert.sh.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, libcpp-hardening-mode=none
+
+// Ensure that passing std::functions across -fno-rtti/-frtti boundaries works.
+
+#include <cassert>
+#include <functional>
+#include <typeinfo>
+
+// RUN: %{cxx} %s %{flags} %{compile_flags} -c -frtti -o %t.tu1.o
+// RUN: %{cxx} %s %{flags} %{compile_flags} -c -DNO_RTTI -fno-rtti -o %t.tu2.o
+// RUN: %{cxx} %t.tu1.o %t.tu2.o %{flags} %{link_flags} -o %t.exe
+// RUN: %{exec} %t.exe
+
+std::function<void()> get_func();
+
+#ifdef NO_RTTI
+std::function<void()> get_func() {
+ return get_func;
+}
+#else
+
+// This can only be included once.
+#include "check_assertion.h"
+
+int main(int, char**) {
+ TEST_LIBCPP_ASSERT_FAILURE(get_func().target<int>(), "");
+ TEST_LIBCPP_ASSERT_FAILURE(get_func().target_type(), "");
+
+ return 0;
+}
+#endif
More information about the libcxx-commits
mailing list