Fix PR17221 - can't catch virtual base classes when throwing derived NULL pointers. Specifically, libc++abi would crash when you tried it.

llvm-svn: 200904
This commit is contained in:
Marshall Clow 2014-02-06 04:47:02 +00:00
parent bf71a34eb9
commit d230a3d1f6
2 changed files with 53 additions and 14 deletions

View File

@ -301,17 +301,20 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
void* adjustedPtr,
int path_below) const
{
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
if (__offset_flags & __virtual_mask)
ptrdiff_t offset_to_base = 0;
if (adjustedPtr != nullptr)
{
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
offset_to_base = __offset_flags >> __offset_shift;
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
}
}
__base_type->has_unambiguous_public_base(info,
static_cast<char*>(adjustedPtr) + offset_to_base,
(__offset_flags & __public_mask) ?
path_below :
not_public_path);
__base_type->has_unambiguous_public_base(
info,
static_cast<char*>(adjustedPtr) + offset_to_base,
(__offset_flags & __public_mask) ? path_below : not_public_path);
}
void
@ -358,7 +361,8 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type,
void*& adjustedPtr) const
{
// Do the dereference adjustment
adjustedPtr = *static_cast<void**>(adjustedPtr);
if (adjustedPtr != NULL)
adjustedPtr = *static_cast<void**>(adjustedPtr);
// bullets 1 and 4
if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
return true;

View File

@ -130,17 +130,49 @@ void test7 ()
}
struct vA {};
struct vC : virtual public vA {};
struct vBase {};
struct vDerived : virtual public vBase {};
void test8 ()
{
try
{
throw (vC*)0;
throw new vDerived;
assert(false);
}
catch (vA *p) {
catch (vBase *p) {
assert(p != 0);
}
catch (...)
{
assert (false);
}
}
void test9 ()
{
try
{
throw nullptr;
assert(false);
}
catch (vBase *p) {
assert(p == 0);
}
catch (...)
{
assert (false);
}
}
void test10 ()
{
try
{
throw (vDerived*)0;
assert(false);
}
catch (vBase *p) {
assert(p == 0);
}
catch (...)
@ -158,4 +190,7 @@ int main()
test5();
test6();
test7();
test8();
test9();
test10();
}