diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2015-05-08 15:34:21 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2015-05-08 15:34:21 +0000 |
commit | de42153eb2007a09c2a068a52a81e5b647b2954d (patch) | |
tree | b85651b06ad289c17d09d7b7644dcf9f7eec240a | |
parent | 84c765b2be625c33f608fe9903fe12534e34b969 (diff) | |
download | llvm-de42153eb2007a09c2a068a52a81e5b647b2954d.zip llvm-de42153eb2007a09c2a068a52a81e5b647b2954d.tar.gz llvm-de42153eb2007a09c2a068a52a81e5b647b2954d.tar.bz2 |
Merging r234254:
------------------------------------------------------------------------
r234254 | ericwf | 2015-04-06 16:03:01 -0700 (Mon, 06 Apr 2015) | 25 lines
[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: 236866
-rw-r--r-- | libcxxabi/src/private_typeinfo.cpp | 8 | ||||
-rw-r--r-- | libcxxabi/test/catch_member_data_pointer_01.cpp | 15 | ||||
-rw-r--r-- | libcxxabi/test/catch_member_function_pointer_01.cpp | 110 | ||||
-rw-r--r-- | libcxxabi/test/catch_multi_level_pointer.pass.cpp | 2 |
4 files changed, 118 insertions, 17 deletions
diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp index e7b49b9..576d3bf 100644 --- a/libcxxabi/src/private_typeinfo.cpp +++ b/libcxxabi/src/private_typeinfo.cpp @@ -473,11 +473,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; } diff --git a/libcxxabi/test/catch_member_data_pointer_01.cpp b/libcxxabi/test/catch_member_data_pointer_01.cpp index 298a1c0..28bf4b5 100644 --- a/libcxxabi/test/catch_member_data_pointer_01.cpp +++ b/libcxxabi/test/catch_member_data_pointer_01.cpp @@ -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 + catch (der1) { - throw &A::j; assert(false); } - catch (der1) + catch (md2) { } catch (...) diff --git a/libcxxabi/test/catch_member_function_pointer_01.cpp b/libcxxabi/test/catch_member_function_pointer_01.cpp index 4503d88..28b13cc 100644 --- a/libcxxabi/test/catch_member_function_pointer_01.cpp +++ b/libcxxabi/test/catch_member_function_pointer_01.cpp @@ -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(); } diff --git a/libcxxabi/test/catch_multi_level_pointer.pass.cpp b/libcxxabi/test/catch_multi_level_pointer.pass.cpp index d722ea0..3246099 100644 --- a/libcxxabi/test/catch_multi_level_pointer.pass.cpp +++ b/libcxxabi/test/catch_multi_level_pointer.pass.cpp @@ -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>()(); } |