forked from OSchip/llvm-project
private_typeinfo: limit is_dst_type_derived_from_static_type optimization
Patch by Ryan Prichard If the destination type does not derive from the static type, we can skip the search_above_dst call, but we still need to run the !does_dst_type_point_to_our_static_type block of code. That block of code will increment info->number_to_dst_ptr to 2, and because dest isn't derived from static, the cast will ultimately fail. Fixes PR33439 Reviewed as https://reviews.llvm.org/D36447 llvm-svn: 332767
This commit is contained in:
parent
401b5ecfea
commit
29e0265732
|
@ -859,13 +859,14 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
|||
// 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;
|
||||
bool does_dst_type_point_to_our_static_type = false;
|
||||
|
||||
// We've found a dst_type with a potentially public path to here.
|
||||
// We have to assume the path is public because it may become
|
||||
// public later (if we get back to here with a public path).
|
||||
|
@ -909,21 +910,6 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
|||
}
|
||||
}
|
||||
}
|
||||
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,
|
||||
// so stop search.
|
||||
if (info->number_to_static_ptr == 1 &&
|
||||
info->path_dst_ptr_to_static_ptr == not_public_path)
|
||||
info->search_done = 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
|
||||
|
@ -932,7 +918,22 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
|||
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,
|
||||
// so stop search.
|
||||
if (info->number_to_static_ptr == 1 &&
|
||||
info->path_dst_ptr_to_static_ptr == not_public_path)
|
||||
info->search_done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1030,13 +1031,13 @@ __si_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
|||
// 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;
|
||||
bool does_dst_type_point_to_our_static_type = false;
|
||||
// Zero out found flags
|
||||
info->found_our_static_ptr = false;
|
||||
info->found_any_static_type = false;
|
||||
|
@ -1047,20 +1048,6 @@ __si_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
|||
if (info->found_our_static_ptr)
|
||||
does_dst_type_point_to_our_static_type = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
// 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
|
||||
|
@ -1070,6 +1057,20 @@ __si_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
|||
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
|
||||
|
|
|
@ -95,9 +95,60 @@ void test()
|
|||
|
||||
} // t3
|
||||
|
||||
namespace t4
|
||||
{
|
||||
|
||||
// PR33439
|
||||
struct C2 { virtual ~C2() {} Pad1 _; };
|
||||
struct C3 { virtual ~C3() {} Pad2 _; };
|
||||
struct C4 : C3 { Pad3 _; };
|
||||
struct C8 : C2, virtual C4 { Pad4 _; };
|
||||
struct C9 : C4, C8 { Pad5 _; };
|
||||
|
||||
C9 c9;
|
||||
C2 *c2 = &c9;
|
||||
|
||||
void test()
|
||||
{
|
||||
assert(dynamic_cast<C2*>(c2) == static_cast<C2*>(&c9));
|
||||
assert(dynamic_cast<C3*>(c2) == 0);
|
||||
assert(dynamic_cast<C4*>(c2) == 0);
|
||||
assert(dynamic_cast<C8*>(c2) == static_cast<C8*>(&c9));
|
||||
assert(dynamic_cast<C9*>(c2) == static_cast<C9*>(&c9));
|
||||
}
|
||||
|
||||
} // t4
|
||||
|
||||
namespace t5
|
||||
{
|
||||
|
||||
// PR33439
|
||||
struct Dummy { virtual ~Dummy() {} Pad1 _; };
|
||||
struct Src { virtual ~Src() {} Pad2 _; };
|
||||
struct Dest : Dummy { Pad3 _; };
|
||||
struct A1 : Dest { Pad4 _; };
|
||||
struct A2 : Dest { Pad5 _; };
|
||||
struct Root : Src, A1, A2 { Pad6 _; };
|
||||
|
||||
Root root;
|
||||
Src *src = &root;
|
||||
|
||||
void test()
|
||||
{
|
||||
assert(dynamic_cast<Dummy*>(src) == 0);
|
||||
assert(dynamic_cast<Src*>(src) == static_cast<Src*>(&root));
|
||||
assert(dynamic_cast<Dest*>(src) == 0);
|
||||
assert(dynamic_cast<A1*>(src) == static_cast<A1*>(&root));
|
||||
assert(dynamic_cast<A2*>(src) == static_cast<A2*>(&root));
|
||||
}
|
||||
|
||||
} // t5
|
||||
|
||||
int main()
|
||||
{
|
||||
t1::test();
|
||||
t2::test();
|
||||
t3::test();
|
||||
t4::test();
|
||||
t5::test();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue