[libcxx-commits] [libcxxabi] make strcmp static (PR #230762)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Oct 10 01:51:00 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/230762
- **[libc++abi] Return whether a dynamic_cast/catch search finished**
- **[libc++abi] Split strcmp and non-strcmp dynamic_casts**
>From 48b36e7cebe1f5b9761e5b1ca9f9cf84224b6774 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 16 Sep 2026 12:17:22 +0200
Subject: [PATCH 1/2] [libc++abi] Return whether a dynamic_cast/catch search
finished
---
libcxxabi/src/private_typeinfo.cpp | 436 +++++++++++++++--------------
libcxxabi/src/private_typeinfo.h | 42 ++-
2 files changed, 240 insertions(+), 238 deletions(-)
diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp
index 74d9a7b358352..98dcfd7e1275f 100644
--- a/libcxxabi/src/private_typeinfo.cpp
+++ b/libcxxabi/src/private_typeinfo.cpp
@@ -181,10 +181,9 @@ const void* dyn_cast_to_derived(
0,
1, // number_of_dst_type
false,
- false,
false};
// Do the search
- dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
+ (void)dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should
// definitely find (static_ptr, static_type), either on a public
@@ -254,9 +253,8 @@ const void* dyn_cast_try_downcast(
0,
1, // number_of_dst_type
false,
- false,
false};
- dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
+ (void)dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
// We have found at least one path from dynamic_ptr to dst_ptr. The
// downcast can succeed.
@@ -276,9 +274,9 @@ const void* dyn_cast_slow(
// Not using giant short cut. Do the search
// Initialize info struct for this search.
- __dynamic_cast_info info = {dst_type, static_ptr, static_type, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false};
+ __dynamic_cast_info info = {dst_type, static_ptr, static_type, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false};
- dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
+ (void)dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should
// definitely find (static_ptr, static_type), either on a public
@@ -444,8 +442,8 @@ bool __class_type_info::can_catch(const __shim_type_info* thrown_type, void*& ad
return false;
// bullet 2
_LIBCXXABI_ASSERT(adjustedPtr, "catching a class without an object?");
- catch_info info = {this, nullptr, nullptr, 0, 0, false, true, nullptr};
- thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
+ catch_info info = {this, nullptr, nullptr, 0, 0, true, nullptr};
+ (void)thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
if (info.path_dst_ptr_to_static_ptr == public_path) {
adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
return true;
@@ -473,7 +471,7 @@ bool __class_type_info::can_catch(const __shim_type_info* thrown_type, void*& ad
// different offset (adjustedPtr) from any previously recorded, this indicates
// an ambiguous case within the virtual base.
-void __class_type_info::process_found_base_class(catch_info* info, void* adjustedPtr, int path_below) const {
+bool __class_type_info::process_found_base_class(catch_info* info, void* adjustedPtr, int path_below) const {
if (info->number_to_static_ptr == 0) {
// First time we found this base
info->dst_ptr_leading_to_static_ptr = adjustedPtr;
@@ -491,23 +489,25 @@ void __class_type_info::process_found_base_class(catch_info* info, void* adjuste
// to a static_type.
info->number_to_static_ptr += 1;
info->path_dst_ptr_to_static_ptr = not_public_path;
- info->search_done = true;
+ return true;
}
+ return false;
}
-void __class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
+bool __class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
if (is_equal(this, info->static_type, false))
- process_found_base_class(info, adjustedPtr, path_below);
+ return process_found_base_class(info, adjustedPtr, path_below);
+ return false;
}
-void __si_class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
+bool __si_class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
if (is_equal(this, info->static_type, false))
- process_found_base_class(info, adjustedPtr, path_below);
+ return process_found_base_class(info, adjustedPtr, path_below);
else
- __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
+ return __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
}
-void __base_class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
+bool __base_class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
bool is_virtual = __offset_flags & __virtual_mask;
ptrdiff_t offset_to_base = 0;
if (info->have_object) {
@@ -532,27 +532,28 @@ void __base_class_type_info::has_unambiguous_public_base(catch_info* info, void*
// .. and reset the pointer.
adjustedPtr = nullptr;
}
- __base_type->has_unambiguous_public_base(
+ return __base_type->has_unambiguous_public_base(
info,
reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(adjustedPtr) + offset_to_base),
(__offset_flags & __public_mask) ? path_below : not_public_path);
}
-void __vmi_class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
+bool __vmi_class_type_info::has_unambiguous_public_base(catch_info* info, void* adjustedPtr, int path_below) const {
if (is_equal(this, info->static_type, false))
- process_found_base_class(info, adjustedPtr, path_below);
+ return process_found_base_class(info, adjustedPtr, path_below);
else {
typedef const __base_class_type_info* Iter;
const Iter e = __base_info + __base_count;
Iter p = __base_info;
- p->has_unambiguous_public_base(info, adjustedPtr, path_below);
+ if (p->has_unambiguous_public_base(info, adjustedPtr, path_below))
+ return true;
if (++p < e) {
do {
- p->has_unambiguous_public_base(info, adjustedPtr, path_below);
- if (info->search_done)
- break;
+ if (p->has_unambiguous_public_base(info, adjustedPtr, path_below))
+ return true;
} while (++p < e);
}
+ return false;
}
}
@@ -635,8 +636,8 @@ bool __pointer_type_info::can_catch(const __shim_type_info* thrown_type, void*&
if (thrown_class_type == 0)
return false;
bool have_object = adjustedPtr != nullptr;
- catch_info info = {catch_class_type, nullptr, nullptr, 0, 0, false, have_object, nullptr};
- thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
+ catch_info info = {catch_class_type, nullptr, nullptr, 0, 0, have_object, nullptr};
+ (void)thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
if (info.path_dst_ptr_to_static_ptr == public_path) {
// In the case of a thrown null pointer, we have no object but we might
// well have computed the offset to where a public sub-object would be.
@@ -861,36 +862,35 @@ __dynamic_cast(const void* static_ptr,
// Record the dst_ptr as pointing to (static_ptr, static_type).
// If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
// then mark this dyanmic_cast as ambiguous and stop the search.
-void __class_type_info::process_static_type_above_dst(
+bool __class_type_info::process_static_type_above_dst(
__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
// Record that we found a static_type
info->found_any_static_type = true;
- if (current_ptr == info->static_ptr) {
- // Record that we found (static_ptr, static_type)
- info->found_our_static_ptr = true;
- if (info->dst_ptr_leading_to_static_ptr == 0) {
- // First time here
- info->dst_ptr_leading_to_static_ptr = dst_ptr;
- info->path_dst_ptr_to_static_ptr = path_below;
- info->number_to_static_ptr = 1;
- // If there is only one dst_type in the entire tree and the path from
- // there to here is public then we are done!
- if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
- info->search_done = true;
- } else if (info->dst_ptr_leading_to_static_ptr == dst_ptr) {
- // We've been here before. Update path to "most public"
- if (info->path_dst_ptr_to_static_ptr == not_public_path)
- info->path_dst_ptr_to_static_ptr = path_below;
- // If there is only one dst_type in the entire tree and the path from
- // there to here is public then we are done!
- if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
- info->search_done = true;
- } else {
- // We've detected an ambiguous cast from (static_ptr, static_type)
- // to a dst_type
- info->number_to_static_ptr += 1;
- info->search_done = true;
- }
+ if (current_ptr != info->static_ptr)
+ return false;
+
+ // Record that we found (static_ptr, static_type)
+ info->found_our_static_ptr = true;
+ if (info->dst_ptr_leading_to_static_ptr == 0) {
+ // First time here
+ info->dst_ptr_leading_to_static_ptr = dst_ptr;
+ info->path_dst_ptr_to_static_ptr = path_below;
+ info->number_to_static_ptr = 1;
+ // If there is only one dst_type in the entire tree and the path from
+ // there to here is public then we are done!
+ return info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path;
+ } else if (info->dst_ptr_leading_to_static_ptr == dst_ptr) {
+ // We've been here before. Update path to "most public"
+ if (info->path_dst_ptr_to_static_ptr == not_public_path)
+ info->path_dst_ptr_to_static_ptr = path_below;
+ // If there is only one dst_type in the entire tree and the path from
+ // there to here is public then we are done!
+ return info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path;
+ } else {
+ // We've detected an ambiguous cast from (static_ptr, static_type)
+ // to a dst_type
+ info->number_to_static_ptr += 1;
+ return true;
}
}
@@ -961,12 +961,13 @@ void __class_type_info::process_static_type_below_dst(
// }
// }
// }
-void __vmi_class_type_info::search_below_dst(
+bool __vmi_class_type_info::search_below_dst(
__dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
typedef const __base_class_type_info* Iter;
- if (is_equal(this, info->static_type, use_strcmp))
+ if (is_equal(this, info->static_type, use_strcmp)) {
process_static_type_below_dst(info, current_ptr, path_below);
- else if (is_equal(this, info->dst_type, use_strcmp)) {
+ return false;
+ } else if (is_equal(this, info->dst_type, use_strcmp)) {
// We've been here before if we've recorded current_ptr in one of these
// two places:
if (current_ptr == info->dst_ptr_leading_to_static_ptr || current_ptr == info->dst_ptr_not_leading_to_static_ptr) {
@@ -1001,9 +1002,8 @@ void __vmi_class_type_info::search_below_dst(
// Zero out found flags
info->found_our_static_ptr = false;
info->found_any_static_type = false;
- p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
- if (info->search_done)
- break;
+ if (p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp))
+ return true;
if (info->found_any_static_type) {
is_dst_type_derived_from_static_type = true;
if (info->found_our_static_ptr) {
@@ -1044,15 +1044,15 @@ void __vmi_class_type_info::search_below_dst(
// (static_ptr, static_type), then the cast from
// (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
// so stop search.
- if (info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path)
- info->search_done = true;
+ return info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path;
}
}
} else {
// This is not a static_type and not a dst_type.
const Iter e = __base_info + __base_count;
Iter p = __base_info;
- p->search_below_dst(info, current_ptr, path_below, use_strcmp);
+ if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ return true;
if (++p < e) {
if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1) {
// If there are multiple paths to a base above from here, or if
@@ -1060,32 +1060,28 @@ void __vmi_class_type_info::search_below_dst(
// then there is no way to break out of this loop early unless
// something below detects the search is done.
do {
- if (info->search_done)
- break;
- p->search_below_dst(info, current_ptr, path_below, use_strcmp);
+ if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ return true;
} while (++p < e);
} else if (__flags & __non_diamond_repeat_mask) {
// There are not multiple paths to any base class from here and a
// dst_type pointing to (static_ptr, static_type) has not yet been
// found.
do {
- if (info->search_done)
- break;
// If we just found a dst_type with a public path to (static_ptr, static_type),
// then the only reason to continue the search is to make sure
// no other dst_type points to (static_ptr, static_type).
// If !diamond, then we don't need to search here.
if (info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == public_path)
break;
- p->search_below_dst(info, current_ptr, path_below, use_strcmp);
+ if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ return true;
} while (++p < e);
} else {
// There are no repeated types above this node.
// There are no nodes with multiple parents above this node.
// no dst_type has been found to (static_ptr, static_type)
do {
- if (info->search_done)
- break;
// If we just found a dst_type with a public path to (static_ptr, static_type),
// then the only reason to continue the search is to make sure
// no other dst_type points to (static_ptr, static_type).
@@ -1097,96 +1093,68 @@ void __vmi_class_type_info::search_below_dst(
// and not a dst_type under here.
if (info->number_to_static_ptr == 1)
break;
- p->search_below_dst(info, current_ptr, path_below, use_strcmp);
+ if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ return true;
} while (++p < e);
}
}
}
+ return false;
}
// This is the same algorithm as __vmi_class_type_info::search_below_dst but
// simplified to the case that there is only a single base class.
-void __si_class_type_info::search_below_dst(
+bool __si_class_type_info::search_below_dst(
__dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
- if (is_equal(this, info->static_type, use_strcmp))
+ if (is_equal(this, info->static_type, use_strcmp)) {
process_static_type_below_dst(info, current_ptr, path_below);
- else if (is_equal(this, info->dst_type, use_strcmp)) {
- // We've been here before if we've recorded current_ptr in one of these
- // two places:
- if (current_ptr == info->dst_ptr_leading_to_static_ptr || current_ptr == info->dst_ptr_not_leading_to_static_ptr) {
- // We've seen this node before, and therefore have already searched
- // its base classes above.
- // Update path to here that is "most public".
- if (path_below == public_path)
- info->path_dynamic_ptr_to_dst_ptr = public_path;
- } else // We have haven't been here before
- {
- // Record the access path that got us here
- // If there is more than one dst_type this path doesn't matter.
- info->path_dynamic_ptr_to_dst_ptr = path_below;
- bool does_dst_type_point_to_our_static_type = false;
- // Only search above here if dst_type derives from static_type, or
- // if it is unknown if dst_type derives from static_type.
- if (info->is_dst_type_derived_from_static_type != no) {
- // Set up flags to record results from all base classes
- bool is_dst_type_derived_from_static_type = false;
- // Zero out found flags
- info->found_our_static_ptr = false;
- info->found_any_static_type = false;
- __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
- if (info->found_any_static_type) {
- is_dst_type_derived_from_static_type = true;
- if (info->found_our_static_ptr)
- does_dst_type_point_to_our_static_type = true;
- }
- // If we found no static_type,s then dst_type doesn't derive
- // from static_type, else it does. Record this result so that
- // next time we hit a dst_type we will know not to search above
- // it if it doesn't derive from static_type.
- if (is_dst_type_derived_from_static_type)
- info->is_dst_type_derived_from_static_type = yes;
- else
- info->is_dst_type_derived_from_static_type = no;
- }
- if (!does_dst_type_point_to_our_static_type) {
- // We found a dst_type that doesn't point to (static_ptr, static_type)
- // So record the address of this dst_ptr and increment the
- // count of the number of such dst_types found in the tree.
- info->dst_ptr_not_leading_to_static_ptr = current_ptr;
- info->number_to_dst_ptr += 1;
- // If there exists another dst with a private path to
- // (static_ptr, static_type), then the cast from
- // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
- if (info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path)
- info->search_done = true;
- }
- }
- } else {
+ return false;
+ }
+
+ if (!is_equal(this, info->dst_type, use_strcmp)) {
// This is not a static_type and not a dst_type
- __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
+ return __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
}
-}
-// This is the same algorithm as __vmi_class_type_info::search_below_dst but
-// simplified to the case that there is no base class.
-void __class_type_info::search_below_dst(
- __dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
- if (is_equal(this, info->static_type, use_strcmp))
- process_static_type_below_dst(info, current_ptr, path_below);
- else if (is_equal(this, info->dst_type, use_strcmp)) {
- // We've been here before if we've recorded current_ptr in one of these
- // two places:
- if (current_ptr == info->dst_ptr_leading_to_static_ptr || current_ptr == info->dst_ptr_not_leading_to_static_ptr) {
- // We've seen this node before, and therefore have already searched
- // its base classes above.
- // Update path to here that is "most public".
- if (path_below == public_path)
- info->path_dynamic_ptr_to_dst_ptr = public_path;
- } else // We have haven't been here before
- {
- // Record the access path that got us here
- // If there is more than one dst_type this path doesn't matter.
- info->path_dynamic_ptr_to_dst_ptr = path_below;
+ // We've been here before if we've recorded current_ptr in one of these
+ // two places:
+ if (current_ptr == info->dst_ptr_leading_to_static_ptr || current_ptr == info->dst_ptr_not_leading_to_static_ptr) {
+ // We've seen this node before, and therefore have already searched
+ // its base classes above.
+ // Update path to here that is "most public".
+ if (path_below == public_path)
+ info->path_dynamic_ptr_to_dst_ptr = public_path;
+ } else // We have haven't been here before
+ {
+ // Record the access path that got us here
+ // If there is more than one dst_type this path doesn't matter.
+ info->path_dynamic_ptr_to_dst_ptr = path_below;
+ bool does_dst_type_point_to_our_static_type = false;
+ // Only search above here if dst_type derives from static_type, or
+ // if it is unknown if dst_type derives from static_type.
+ if (info->is_dst_type_derived_from_static_type != no) {
+ // Set up flags to record results from all base classes
+ bool is_dst_type_derived_from_static_type = false;
+ // Zero out found flags
+ info->found_our_static_ptr = false;
+ info->found_any_static_type = false;
+ if (__base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp))
+ return true;
+ if (info->found_any_static_type) {
+ is_dst_type_derived_from_static_type = true;
+ if (info->found_our_static_ptr)
+ does_dst_type_point_to_our_static_type = true;
+ }
+ // If we found no static_type,s then dst_type doesn't derive
+ // from static_type, else it does. Record this result so that
+ // next time we hit a dst_type we will know not to search above
+ // it if it doesn't derive from static_type.
+ if (is_dst_type_derived_from_static_type)
+ info->is_dst_type_derived_from_static_type = yes;
+ else
+ info->is_dst_type_derived_from_static_type = no;
+ }
+ if (!does_dst_type_point_to_our_static_type) {
// We found a dst_type that doesn't point to (static_ptr, static_type)
// So record the address of this dst_ptr and increment the
// count of the number of such dst_types found in the tree.
@@ -1195,12 +1163,51 @@ void __class_type_info::search_below_dst(
// If there exists another dst with a private path to
// (static_ptr, static_type), then the cast from
// (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
- if (info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path)
- info->search_done = true;
- // We found that dst_type does not derive from static_type
- info->is_dst_type_derived_from_static_type = no;
+ return info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path;
}
}
+ return false;
+}
+
+// This is the same algorithm as __vmi_class_type_info::search_below_dst but
+// simplified to the case that there is no base class.
+bool __class_type_info::search_below_dst(
+ __dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
+ if (is_equal(this, info->static_type, use_strcmp)) {
+ process_static_type_below_dst(info, current_ptr, path_below);
+ return false;
+ }
+
+ else if (!is_equal(this, info->dst_type, use_strcmp))
+ return false;
+
+ // We've been here before if we've recorded current_ptr in one of these
+ // two places:
+ if (current_ptr == info->dst_ptr_leading_to_static_ptr || current_ptr == info->dst_ptr_not_leading_to_static_ptr) {
+ // We've seen this node before, and therefore have already searched
+ // its base classes above.
+ // Update path to here that is "most public".
+ if (path_below == public_path)
+ info->path_dynamic_ptr_to_dst_ptr = public_path;
+ return false;
+ }
+
+ // We have haven't been here before
+
+ // Record the access path that got us here
+ // If there is more than one dst_type this path doesn't matter.
+ info->path_dynamic_ptr_to_dst_ptr = path_below;
+ // We found a dst_type that doesn't point to (static_ptr, static_type)
+ // So record the address of this dst_ptr and increment the
+ // count of the number of such dst_types found in the tree.
+ info->dst_ptr_not_leading_to_static_ptr = current_ptr;
+ info->number_to_dst_ptr += 1;
+ // If there exists another dst with a private path to
+ // (static_ptr, static_type), then the cast from
+ // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
+ // We found that dst_type does not derive from static_type
+ info->is_dst_type_derived_from_static_type = no;
+ return info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path;
}
// Call this function when searching above a dst_type node. This function searches
@@ -1229,97 +1236,98 @@ void __class_type_info::search_below_dst(
// }
// }
// }
-void __vmi_class_type_info::search_above_dst(
+bool __vmi_class_type_info::search_above_dst(
__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
if (is_equal(this, info->static_type, use_strcmp))
- process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
- else {
- typedef const __base_class_type_info* Iter;
- // This is not a static_type and not a dst_type
- // Save flags so they can be restored when returning to nodes below.
- bool found_our_static_ptr = info->found_our_static_ptr;
- bool found_any_static_type = info->found_any_static_type;
- // We've found a dst_type below with a path to here. If the path
- // to here is not public, there may be another path to here that
- // is public. So we have to assume that the path to here is public.
- // We can stop looking above if:
- // 1. We've found a public path to (static_ptr, static_type).
- // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
- // This is detected at the (static_ptr, static_type).
- // 3. We can prove that there is no public path to (static_ptr, static_type)
- // above here.
- const Iter e = __base_info + __base_count;
- Iter p = __base_info;
- // Zero out found flags
- info->found_our_static_ptr = false;
- info->found_any_static_type = false;
- p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
- found_our_static_ptr |= info->found_our_static_ptr;
- found_any_static_type |= info->found_any_static_type;
- if (++p < e) {
- do {
- if (info->search_done)
+ return process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
+
+ typedef const __base_class_type_info* Iter;
+ // This is not a static_type and not a dst_type
+ // Save flags so they can be restored when returning to nodes below.
+ bool found_our_static_ptr = info->found_our_static_ptr;
+ bool found_any_static_type = info->found_any_static_type;
+ // We've found a dst_type below with a path to here. If the path
+ // to here is not public, there may be another path to here that
+ // is public. So we have to assume that the path to here is public.
+ // We can stop looking above if:
+ // 1. We've found a public path to (static_ptr, static_type).
+ // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
+ // This is detected at the (static_ptr, static_type).
+ // 3. We can prove that there is no public path to (static_ptr, static_type)
+ // above here.
+ const Iter e = __base_info + __base_count;
+ Iter p = __base_info;
+ // Zero out found flags
+ info->found_our_static_ptr = false;
+ info->found_any_static_type = false;
+ if (p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp))
+ return true;
+ found_our_static_ptr |= info->found_our_static_ptr;
+ found_any_static_type |= info->found_any_static_type;
+ if (++p < e) {
+ do {
+ if (info->found_our_static_ptr) {
+ // If we found what we're looking for, stop looking above.
+ if (info->path_dst_ptr_to_static_ptr == public_path)
break;
- if (info->found_our_static_ptr) {
- // If we found what we're looking for, stop looking above.
- if (info->path_dst_ptr_to_static_ptr == public_path)
- break;
- // We found a private path to (static_ptr, static_type)
- // If there is no diamond then there is only one path
- // to (static_ptr, static_type) from here and we just found it.
- if (!(__flags & __diamond_shaped_mask))
- break;
- } else if (info->found_any_static_type) {
- // If we found a static_type that isn't the one we're looking
- // for, and if there are no repeated types above here,
- // then stop looking.
- if (!(__flags & __non_diamond_repeat_mask))
- break;
- }
- // Zero out found flags
- info->found_our_static_ptr = false;
- info->found_any_static_type = false;
- p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
- found_our_static_ptr |= info->found_our_static_ptr;
- found_any_static_type |= info->found_any_static_type;
- } while (++p < e);
- }
- // Restore flags
- info->found_our_static_ptr = found_our_static_ptr;
- info->found_any_static_type = found_any_static_type;
+ // We found a private path to (static_ptr, static_type)
+ // If there is no diamond then there is only one path
+ // to (static_ptr, static_type) from here and we just found it.
+ if (!(__flags & __diamond_shaped_mask))
+ break;
+ } else if (info->found_any_static_type) {
+ // If we found a static_type that isn't the one we're looking
+ // for, and if there are no repeated types above here,
+ // then stop looking.
+ if (!(__flags & __non_diamond_repeat_mask))
+ break;
+ }
+ // Zero out found flags
+ info->found_our_static_ptr = false;
+ info->found_any_static_type = false;
+ if (p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp))
+ return true;
+ found_our_static_ptr |= info->found_our_static_ptr;
+ found_any_static_type |= info->found_any_static_type;
+ } while (++p < e);
}
+ // Restore flags
+ info->found_our_static_ptr = found_our_static_ptr;
+ info->found_any_static_type = found_any_static_type;
+ return false;
}
// This is the same algorithm as __vmi_class_type_info::search_above_dst but
// simplified to the case that there is only a single base class.
-void __si_class_type_info::search_above_dst(
+bool __si_class_type_info::search_above_dst(
__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
if (is_equal(this, info->static_type, use_strcmp))
- process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
+ return process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
else
- __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
+ return __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
}
// This is the same algorithm as __vmi_class_type_info::search_above_dst but
// simplified to the case that there is no base class.
-void __class_type_info::search_above_dst(
+bool __class_type_info::search_above_dst(
__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
if (is_equal(this, info->static_type, use_strcmp))
- process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
+ return process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
+ return false;
}
// The search functions for __base_class_type_info are simply convenience
// functions for adjusting the current_ptr and path_below as the search is
// passed up to the base class node.
-void __base_class_type_info::search_above_dst(
+bool __base_class_type_info::search_above_dst(
__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
if (__offset_flags & __virtual_mask) {
const char* vtable = strip_vtable(*static_cast<const char* const*>(current_ptr));
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
- __base_type->search_above_dst(
+ return __base_type->search_above_dst(
info,
dst_ptr,
static_cast<const char*>(current_ptr) + offset_to_base,
@@ -1327,14 +1335,14 @@ void __base_class_type_info::search_above_dst(
use_strcmp);
}
-void __base_class_type_info::search_below_dst(
+bool __base_class_type_info::search_below_dst(
__dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
if (__offset_flags & __virtual_mask) {
const char* vtable = strip_vtable(*static_cast<const char* const*>(current_ptr));
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
- __base_type->search_below_dst(
+ return __base_type->search_below_dst(
info,
static_cast<const char*>(current_ptr) + offset_to_base,
(__offset_flags & __public_mask) ? path_below : not_public_path,
diff --git a/libcxxabi/src/private_typeinfo.h b/libcxxabi/src/private_typeinfo.h
index 62d0addb19eb7..2b5dfa42a6521 100644
--- a/libcxxabi/src/private_typeinfo.h
+++ b/libcxxabi/src/private_typeinfo.h
@@ -76,9 +76,6 @@ struct catch_info {
// Number of dst_types below (static_ptr, static_type)
int number_to_static_ptr;
- // Set whenever a search can be stopped
- bool search_done;
-
// There is no object (seen when we throw a null pointer to object).
bool have_object;
// Virtual base
@@ -127,8 +124,6 @@ struct _LIBCXXABI_HIDDEN __dynamic_cast_info
// communicates to a dst_type node that a static_type was found
// above it, but it wasn't (static_ptr, static_type)
bool found_any_static_type;
- // Set whenever a search can be stopped
- bool search_done;
};
// Has no base class
@@ -136,19 +131,16 @@ class _LIBCXXABI_TYPE_VIS __class_type_info : public __shim_type_info {
public:
_LIBCXXABI_HIDDEN ~__class_type_info() override;
- _LIBCXXABI_HIDDEN void process_static_type_above_dst(__dynamic_cast_info *,
- const void *,
- const void *, int) const;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool
+ process_static_type_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
_LIBCXXABI_HIDDEN void process_static_type_below_dst(__dynamic_cast_info *,
const void *, int) const;
- _LIBCXXABI_HIDDEN void process_found_base_class(catch_info*, void*, int) const;
- _LIBCXXABI_HIDDEN virtual void search_above_dst(__dynamic_cast_info *,
- const void *, const void *,
- int, bool) const;
- _LIBCXXABI_HIDDEN virtual void
- search_below_dst(__dynamic_cast_info *, const void *, int, bool) const;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool process_found_base_class(catch_info*, void*, int) const;
+ _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool
+ search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const;
+ _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const;
_LIBCXXABI_HIDDEN bool can_catch(const __shim_type_info*, void*&) const final;
- _LIBCXXABI_HIDDEN virtual void has_unambiguous_public_base(catch_info*, void*, int) const;
+ _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool has_unambiguous_public_base(catch_info*, void*, int) const;
};
// Has one non-virtual public base class at offset zero
@@ -158,9 +150,10 @@ class _LIBCXXABI_TYPE_VIS __si_class_type_info final : public __class_type_info
_LIBCXXABI_HIDDEN ~__si_class_type_info() final;
- _LIBCXXABI_HIDDEN void search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const final;
- _LIBCXXABI_HIDDEN void search_below_dst(__dynamic_cast_info*, const void*, int, bool) const final;
- _LIBCXXABI_HIDDEN void has_unambiguous_public_base(catch_info*, void*, int) const final;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool
+ search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const final;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const final;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool has_unambiguous_public_base(catch_info*, void*, int) const final;
};
struct _LIBCXXABI_HIDDEN __base_class_type_info
@@ -176,9 +169,9 @@ struct _LIBCXXABI_HIDDEN __base_class_type_info
__offset_shift = 8
};
- void search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const;
- void search_below_dst(__dynamic_cast_info*, const void*, int, bool) const;
- void has_unambiguous_public_base(catch_info*, void*, int) const;
+ [[nodiscard]] bool search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const;
+ [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const;
+ [[nodiscard]] bool has_unambiguous_public_base(catch_info*, void*, int) const;
};
// Has one or more base classes
@@ -197,9 +190,10 @@ class _LIBCXXABI_TYPE_VIS __vmi_class_type_info final : public __class_type_info
_LIBCXXABI_HIDDEN ~__vmi_class_type_info() final;
- _LIBCXXABI_HIDDEN void search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const final;
- _LIBCXXABI_HIDDEN void search_below_dst(__dynamic_cast_info*, const void*, int, bool) const final;
- _LIBCXXABI_HIDDEN void has_unambiguous_public_base(catch_info*, void*, int) const final;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool
+ search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const final;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const final;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool has_unambiguous_public_base(catch_info*, void*, int) const final;
};
class _LIBCXXABI_TYPE_VIS __pbase_type_info : public __shim_type_info {
>From 5e95606d5fb88d09d7b673caaffd274a512c62ed Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 10 Oct 2026 10:50:02 +0200
Subject: [PATCH 2/2] [libc++abi] Split strcmp and non-strcmp dynamic_casts
---
libcxxabi/src/private_typeinfo.cpp | 84 ++++++++++++---------
libcxxabi/src/private_typeinfo.h | 117 +++++++++++++++++++++++++++--
2 files changed, 157 insertions(+), 44 deletions(-)
diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp
index 98dcfd7e1275f..0572aa171cb4c 100644
--- a/libcxxabi/src/private_typeinfo.cpp
+++ b/libcxxabi/src/private_typeinfo.cpp
@@ -183,7 +183,7 @@ const void* dyn_cast_to_derived(
false,
false};
// Do the search
- (void)dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
+ (void)dst_type->search_above_dst<false>(&info, dynamic_ptr, dynamic_ptr, public_path);
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should
// definitely find (static_ptr, static_type), either on a public
@@ -204,7 +204,7 @@ const void* dyn_cast_to_derived(
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false};
info.number_of_dst_type = 1;
- dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
+ dst_type->search_above_dst<true>(&info, dynamic_ptr, dynamic_ptr, public_path);
}
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
@@ -254,7 +254,7 @@ const void* dyn_cast_try_downcast(
1, // number_of_dst_type
false,
false};
- (void)dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
+ (void)dynamic_type->search_above_dst<false>(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path);
if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
// We have found at least one path from dynamic_ptr to dst_ptr. The
// downcast can succeed.
@@ -276,7 +276,7 @@ const void* dyn_cast_slow(
// Initialize info struct for this search.
__dynamic_cast_info info = {dst_type, static_ptr, static_type, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false};
- (void)dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
+ (void)dynamic_type->search_below_dst<false>(&info, dynamic_ptr, public_path);
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should
// definitely find (static_ptr, static_type), either on a public
@@ -296,7 +296,7 @@ const void* dyn_cast_slow(
dst_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false};
- dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
+ dynamic_type->search_below_dst<true>(&info, dynamic_ptr, public_path);
}
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
@@ -961,8 +961,9 @@ void __class_type_info::process_static_type_below_dst(
// }
// }
// }
-bool __vmi_class_type_info::search_below_dst(
- __dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
+template <bool use_strcmp>
+bool __vmi_class_type_info::search_below_dst_impl(
+ __dynamic_cast_info* info, const void* current_ptr, int path_below) const {
typedef const __base_class_type_info* Iter;
if (is_equal(this, info->static_type, use_strcmp)) {
process_static_type_below_dst(info, current_ptr, path_below);
@@ -1002,7 +1003,7 @@ bool __vmi_class_type_info::search_below_dst(
// Zero out found flags
info->found_our_static_ptr = false;
info->found_any_static_type = false;
- if (p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp))
+ if (p->search_above_dst<use_strcmp>(info, current_ptr, current_ptr, public_path))
return true;
if (info->found_any_static_type) {
is_dst_type_derived_from_static_type = true;
@@ -1051,7 +1052,7 @@ bool __vmi_class_type_info::search_below_dst(
// This is not a static_type and not a dst_type.
const Iter e = __base_info + __base_count;
Iter p = __base_info;
- if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ if (p->search_below_dst<use_strcmp>(info, current_ptr, path_below))
return true;
if (++p < e) {
if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1) {
@@ -1060,7 +1061,7 @@ bool __vmi_class_type_info::search_below_dst(
// then there is no way to break out of this loop early unless
// something below detects the search is done.
do {
- if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ if (p->search_below_dst<use_strcmp>(info, current_ptr, path_below))
return true;
} while (++p < e);
} else if (__flags & __non_diamond_repeat_mask) {
@@ -1074,7 +1075,7 @@ bool __vmi_class_type_info::search_below_dst(
// If !diamond, then we don't need to search here.
if (info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == public_path)
break;
- if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ if (p->search_below_dst<use_strcmp>(info, current_ptr, path_below))
return true;
} while (++p < e);
} else {
@@ -1093,7 +1094,7 @@ bool __vmi_class_type_info::search_below_dst(
// and not a dst_type under here.
if (info->number_to_static_ptr == 1)
break;
- if (p->search_below_dst(info, current_ptr, path_below, use_strcmp))
+ if (p->search_below_dst<use_strcmp>(info, current_ptr, path_below))
return true;
} while (++p < e);
}
@@ -1104,8 +1105,9 @@ bool __vmi_class_type_info::search_below_dst(
// This is the same algorithm as __vmi_class_type_info::search_below_dst but
// simplified to the case that there is only a single base class.
-bool __si_class_type_info::search_below_dst(
- __dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
+template <bool use_strcmp>
+bool __si_class_type_info::search_below_dst_impl(
+ __dynamic_cast_info* info, const void* current_ptr, int path_below) const {
if (is_equal(this, info->static_type, use_strcmp)) {
process_static_type_below_dst(info, current_ptr, path_below);
return false;
@@ -1113,7 +1115,7 @@ bool __si_class_type_info::search_below_dst(
if (!is_equal(this, info->dst_type, use_strcmp)) {
// This is not a static_type and not a dst_type
- return __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
+ return __base_type->search_below_dst<use_strcmp>(info, current_ptr, path_below);
}
// We've been here before if we've recorded current_ptr in one of these
@@ -1138,7 +1140,7 @@ bool __si_class_type_info::search_below_dst(
// Zero out found flags
info->found_our_static_ptr = false;
info->found_any_static_type = false;
- if (__base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp))
+ if (__base_type->search_above_dst<use_strcmp>(info, current_ptr, current_ptr, public_path))
return true;
if (info->found_any_static_type) {
is_dst_type_derived_from_static_type = true;
@@ -1171,8 +1173,9 @@ bool __si_class_type_info::search_below_dst(
// This is the same algorithm as __vmi_class_type_info::search_below_dst but
// simplified to the case that there is no base class.
-bool __class_type_info::search_below_dst(
- __dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
+template <bool use_strcmp>
+bool __class_type_info::search_below_dst_impl(
+ __dynamic_cast_info* info, const void* current_ptr, int path_below) const {
if (is_equal(this, info->static_type, use_strcmp)) {
process_static_type_below_dst(info, current_ptr, path_below);
return false;
@@ -1210,6 +1213,13 @@ bool __class_type_info::search_below_dst(
return info->number_to_static_ptr == 1 && info->path_dst_ptr_to_static_ptr == not_public_path;
}
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+bool __class_type_info::search_below_dst_strcmp(
+ __dynamic_cast_info* info, const void* current_ptr, int path_below) const {
+ return search_below_dst_impl<true>(info, current_ptr, path_below);
+}
+#endif
+
// Call this function when searching above a dst_type node. This function searches
// for a public path to (static_ptr, static_type).
// This function is guaranteed not to find a node of type dst_type.
@@ -1236,8 +1246,9 @@ bool __class_type_info::search_below_dst(
// }
// }
// }
-bool __vmi_class_type_info::search_above_dst(
- __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
+template <bool use_strcmp>
+bool __vmi_class_type_info::search_above_dst_impl(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
if (is_equal(this, info->static_type, use_strcmp))
return process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
@@ -1260,7 +1271,7 @@ bool __vmi_class_type_info::search_above_dst(
// Zero out found flags
info->found_our_static_ptr = false;
info->found_any_static_type = false;
- if (p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp))
+ if (p->search_above_dst<use_strcmp>(info, dst_ptr, current_ptr, path_below))
return true;
found_our_static_ptr |= info->found_our_static_ptr;
found_any_static_type |= info->found_any_static_type;
@@ -1285,7 +1296,7 @@ bool __vmi_class_type_info::search_above_dst(
// Zero out found flags
info->found_our_static_ptr = false;
info->found_any_static_type = false;
- if (p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp))
+ if (p->search_above_dst<use_strcmp>(info, dst_ptr, current_ptr, path_below))
return true;
found_our_static_ptr |= info->found_our_static_ptr;
found_any_static_type |= info->found_any_static_type;
@@ -1299,18 +1310,20 @@ bool __vmi_class_type_info::search_above_dst(
// This is the same algorithm as __vmi_class_type_info::search_above_dst but
// simplified to the case that there is only a single base class.
-bool __si_class_type_info::search_above_dst(
- __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
+template <bool use_strcmp>
+bool __si_class_type_info::search_above_dst_impl(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
if (is_equal(this, info->static_type, use_strcmp))
return process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
else
- return __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
+ return __base_type->search_above_dst<use_strcmp>(info, dst_ptr, current_ptr, path_below);
}
// This is the same algorithm as __vmi_class_type_info::search_above_dst but
// simplified to the case that there is no base class.
-bool __class_type_info::search_above_dst(
- __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
+template <bool use_strcmp>
+bool __class_type_info::search_above_dst_impl(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
if (is_equal(this, info->static_type, use_strcmp))
return process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
return false;
@@ -1319,34 +1332,33 @@ bool __class_type_info::search_above_dst(
// The search functions for __base_class_type_info are simply convenience
// functions for adjusting the current_ptr and path_below as the search is
// passed up to the base class node.
-
+template <bool use_strcmp>
bool __base_class_type_info::search_above_dst(
- __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below, bool use_strcmp) const {
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
if (__offset_flags & __virtual_mask) {
const char* vtable = strip_vtable(*static_cast<const char* const*>(current_ptr));
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
- return __base_type->search_above_dst(
+ return __base_type->search_above_dst<use_strcmp>(
info,
dst_ptr,
static_cast<const char*>(current_ptr) + offset_to_base,
- (__offset_flags & __public_mask) ? path_below : not_public_path,
- use_strcmp);
+ (__offset_flags & __public_mask) ? path_below : not_public_path);
}
+template <bool use_strcmp>
bool __base_class_type_info::search_below_dst(
- __dynamic_cast_info* info, const void* current_ptr, int path_below, bool use_strcmp) const {
+ __dynamic_cast_info* info, const void* current_ptr, int path_below) const {
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
if (__offset_flags & __virtual_mask) {
const char* vtable = strip_vtable(*static_cast<const char* const*>(current_ptr));
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
- return __base_type->search_below_dst(
+ return __base_type->search_below_dst<use_strcmp>(
info,
static_cast<const char*>(current_ptr) + offset_to_base,
- (__offset_flags & __public_mask) ? path_below : not_public_path,
- use_strcmp);
+ (__offset_flags & __public_mask) ? path_below : not_public_path);
}
} // namespace __cxxabiv1
diff --git a/libcxxabi/src/private_typeinfo.h b/libcxxabi/src/private_typeinfo.h
index 2b5dfa42a6521..a4f5915c1f49b 100644
--- a/libcxxabi/src/private_typeinfo.h
+++ b/libcxxabi/src/private_typeinfo.h
@@ -136,9 +136,65 @@ class _LIBCXXABI_TYPE_VIS __class_type_info : public __shim_type_info {
_LIBCXXABI_HIDDEN void process_static_type_below_dst(__dynamic_cast_info *,
const void *, int) const;
_LIBCXXABI_HIDDEN [[nodiscard]] bool process_found_base_class(catch_info*, void*, int) const;
+
+ template <bool use_strcmp>
+ [[nodiscard]] bool
+ search_above_dst(__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ if constexpr (use_strcmp)
+ return search_above_dst_strcmp(info, dst_ptr, current_ptr, path_below);
+ else
+ return search_above_dst(info, dst_ptr, current_ptr, path_below);
+#else
+ static_assert(!use_strcmp);
+ return search_above_dst(info, dst_ptr, current_ptr, path_below);
+#endif
+ }
+
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_below_dst(__dynamic_cast_info* info, const void* current_ptr, int path_below) const {
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ if constexpr (use_strcmp)
+ return search_below_dst_strcmp(info, current_ptr, path_below);
+ else
+ return search_below_dst(info, current_ptr, path_below);
+#else
+ static_assert(!use_strcmp);
+ return search_below_dst(info, current_ptr, path_below);
+#endif
+ }
+
+ template <bool use_strcmp>
+ bool
+ search_above_dst_impl(__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const;
+
+ _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool
+ search_above_dst(__dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
+ return search_above_dst_impl<false>(info, dst_ptr, current_ptr, path_below);
+ }
+
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool search_above_dst_strcmp(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const {
+ return search_above_dst_impl<true>(info, dst_ptr, current_ptr, path_below);
+ }
+#endif
+
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_below_dst_impl(__dynamic_cast_info* info, const void* current_ptr, int path_below) const;
+
+ _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool
+ search_below_dst(__dynamic_cast_info* catch_info, const void* current_ptr, int path_below) const {
+ return search_below_dst_impl<false>(catch_info, current_ptr, path_below);
+ }
+
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
_LIBCXXABI_HIDDEN [[nodiscard]] virtual bool
- search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const;
- _LIBCXXABI_HIDDEN [[nodiscard]] virtual bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const;
+ search_below_dst_strcmp(__dynamic_cast_info* info, const void* current_ptr, int path_below) const {
+ return search_below_dst_impl<true>(info, current_ptr, path_below);
+ }
+#endif
+
_LIBCXXABI_HIDDEN bool can_catch(const __shim_type_info*, void*&) const final;
_LIBCXXABI_HIDDEN [[nodiscard]] virtual bool has_unambiguous_public_base(catch_info*, void*, int) const;
};
@@ -150,9 +206,29 @@ class _LIBCXXABI_TYPE_VIS __si_class_type_info final : public __class_type_info
_LIBCXXABI_HIDDEN ~__si_class_type_info() final;
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_above_dst_impl(__dynamic_cast_info*, const void*, const void*, int) const;
+
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool search_above_dst(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const final {
+ return search_above_dst_impl<false>(info, dst_ptr, current_ptr, path_below);
+ }
+
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool search_above_dst_strcmp(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const final {
+ return search_above_dst_impl<true>(info, dst_ptr, current_ptr, path_below);
+ }
+#endif
+
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_below_dst_impl(__dynamic_cast_info*, const void*, int) const;
+
_LIBCXXABI_HIDDEN [[nodiscard]] bool
- search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const final;
- _LIBCXXABI_HIDDEN [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const final;
+ search_below_dst(__dynamic_cast_info* info, const void* current_ptr, int path_below) const final {
+ return search_below_dst_impl<false>(info, current_ptr, path_below);
+ }
+
_LIBCXXABI_HIDDEN [[nodiscard]] bool has_unambiguous_public_base(catch_info*, void*, int) const final;
};
@@ -169,8 +245,10 @@ struct _LIBCXXABI_HIDDEN __base_class_type_info
__offset_shift = 8
};
- [[nodiscard]] bool search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const;
- [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const;
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int) const;
[[nodiscard]] bool has_unambiguous_public_base(catch_info*, void*, int) const;
};
@@ -190,9 +268,32 @@ class _LIBCXXABI_TYPE_VIS __vmi_class_type_info final : public __class_type_info
_LIBCXXABI_HIDDEN ~__vmi_class_type_info() final;
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_above_dst_impl(__dynamic_cast_info*, const void*, const void*, int) const;
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool search_above_dst(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const final {
+ return search_above_dst_impl<false>(info, dst_ptr, current_ptr, path_below);
+ }
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool search_above_dst_strcmp(
+ __dynamic_cast_info* info, const void* dst_ptr, const void* current_ptr, int path_below) const final {
+ return search_above_dst_impl<true>(info, dst_ptr, current_ptr, path_below);
+ }
+#endif
+
+ template <bool use_strcmp>
+ [[nodiscard]] bool search_below_dst_impl(__dynamic_cast_info*, const void*, int) const;
+
+ _LIBCXXABI_HIDDEN [[nodiscard]] bool
+ search_below_dst(__dynamic_cast_info* info, const void* current_ptr, int path_below) const final {
+ return search_below_dst_impl<false>(info, current_ptr, path_below);
+ }
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
_LIBCXXABI_HIDDEN [[nodiscard]] bool
- search_above_dst(__dynamic_cast_info*, const void*, const void*, int, bool) const final;
- _LIBCXXABI_HIDDEN [[nodiscard]] bool search_below_dst(__dynamic_cast_info*, const void*, int, bool) const final;
+ search_below_dst_strcmp(__dynamic_cast_info* info, const void* current_ptr, int path_below) const final {
+ return search_below_dst_impl<true>(info, current_ptr, path_below);
+ }
+#endif
_LIBCXXABI_HIDDEN [[nodiscard]] bool has_unambiguous_public_base(catch_info*, void*, int) const final;
};
More information about the libcxx-commits
mailing list