forked from OSchip/llvm-project
[libcxxabi] Disallow Base to Derived conversions for catching pointers to members.
Summary: I accidentally implemented the 4.11 [conv.mem] conversions for libc++abi in a recent patch. @majnemer pointed out that 5.13 [except.handle] only allows the pointer conversions in 4.10 and not those is 4.11. This patch no longer allows the following example code: ```c++ struct A {}; struct B : public A {}; int main() { try { throw (int A::*)0; } catch (int B::*) { // exception caught here. } } ``` Reviewers: mclow.lists, jroelofs, majnemer Reviewed By: majnemer Subscribers: majnemer, cfe-commits Differential Revision: http://reviews.llvm.org/D8845 llvm-svn: 234254
This commit is contained in:
parent
7c869e4821
commit
b6030b9dbf
|
@ -479,11 +479,9 @@ bool __pointer_to_member_type_info::can_catch(
|
|||
if (is_equal(__context, thrown_pointer_type->__context, false))
|
||||
return true;
|
||||
|
||||
__dynamic_cast_info info = {__context, 0, thrown_pointer_type->__context, -1, 0};
|
||||
info.number_of_dst_type = 1;
|
||||
__context->has_unambiguous_public_base(&info, adjustedPtr, public_path);
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path)
|
||||
return true;
|
||||
// [except.handle] does not allow the pointer-to-member conversions mentioned
|
||||
// in [mem.conv] to take place. For this reason we don't check Derived->Base
|
||||
// for Derived->Base conversions.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ void test2()
|
|||
}
|
||||
}
|
||||
|
||||
// Check that Base -> Derived conversions are allowed.
|
||||
// Check that Base -> Derived conversions are NOT allowed.
|
||||
void test3()
|
||||
{
|
||||
try
|
||||
|
@ -90,14 +90,14 @@ void test3()
|
|||
}
|
||||
catch (der1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (md1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that Base -> Derived conversions are allowed with different cv
|
||||
// Check that Base -> Derived conversions NOT are allowed with different cv
|
||||
// qualifiers.
|
||||
void test4()
|
||||
{
|
||||
|
@ -108,18 +108,13 @@ void test4()
|
|||
}
|
||||
catch (der2)
|
||||
{
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
throw &A::j;
|
||||
assert(false);
|
||||
}
|
||||
catch (der1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (md2)
|
||||
{
|
||||
}
|
||||
catch (...)
|
||||
|
|
|
@ -18,6 +18,20 @@ struct A
|
|||
typedef void (A::*mf1)();
|
||||
typedef void (A::*mf2)() const;
|
||||
|
||||
struct B : public A
|
||||
{
|
||||
};
|
||||
|
||||
typedef void (B::*dmf1)();
|
||||
typedef void (B::*dmf2)() const;
|
||||
|
||||
template <class Tp>
|
||||
bool can_convert(Tp) { return true; }
|
||||
|
||||
template <class>
|
||||
bool can_convert(...) { return false; }
|
||||
|
||||
|
||||
void test1()
|
||||
{
|
||||
try
|
||||
|
@ -50,8 +64,104 @@ void test2()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void test_derived()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw (mf1)0;
|
||||
assert(false);
|
||||
}
|
||||
catch (dmf2)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (dmf1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (mf1)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
throw (mf2)0;
|
||||
assert(false);
|
||||
}
|
||||
catch (dmf1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (dmf2)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (mf2)
|
||||
{
|
||||
}
|
||||
|
||||
assert(!can_convert<mf1>((dmf1)0));
|
||||
assert(!can_convert<mf2>((dmf1)0));
|
||||
try
|
||||
{
|
||||
throw (dmf1)0;
|
||||
assert(false);
|
||||
}
|
||||
catch (mf2)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (mf1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
assert(!can_convert<mf1>((dmf2)0));
|
||||
assert(!can_convert<mf2>((dmf2)0));
|
||||
try
|
||||
{
|
||||
throw (dmf2)0;
|
||||
assert(false);
|
||||
}
|
||||
catch (mf2)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (mf1)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void test_void()
|
||||
{
|
||||
assert(!can_convert<void*>(&A::foo));
|
||||
try
|
||||
{
|
||||
throw &A::foo;
|
||||
assert(false);
|
||||
}
|
||||
catch (void*)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test_derived();
|
||||
test_void();
|
||||
}
|
||||
|
|
|
@ -140,6 +140,4 @@ int main()
|
|||
generate_tests<int A::*, int A::*, 3>()();
|
||||
generate_tests<int A::*, void, 2>()();
|
||||
generate_tests<void, int A::*, 2>()();
|
||||
generate_tests<int Base::*, int Derived::*, 2>()();
|
||||
generate_tests<int Derived::*, int Base::*, 2>()();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue