// // Tests for // template // bounded_ptr& operator=(bounded_ptr const& other); // #include #include #include #include #include "test_utils.h" #define _assert(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__) struct Base { int i; }; struct Derived : Base { }; struct Base1 { int i; }; struct Base2 { long l; }; struct DerivedMultiple : Base1, Base2 { DerivedMultiple(int i) : Base1{i}, Base2{i + 10} { } }; struct Unrelated { }; struct dummy_policy1 { static constexpr void trap(char const*) { } }; struct dummy_policy2 { static constexpr void trap(char const*) { } }; template static void tests() { std::array array = {Stored{0}, Stored{1}, Stored{2}, Stored{3}, Stored{4}}; Stored* const ptr1 = array.begin() + 2; Stored* const ptr2 = array.begin() + 3; { test_bounded_ptr const from(ptr1, array.begin(), array.end()); test_bounded_ptr to; test_bounded_ptr& ref = (to = from); _assert(to.discard_bounds() == static_cast(ptr1)); _assert(&ref == &to); // make sure we return *this } // Test assigning to a non-null pointer { test_bounded_ptr const from(ptr1, array.begin(), array.end()); test_bounded_ptr to(ptr2, array.begin(), array.end()); _assert(to.discard_bounds() == static_cast(ptr2)); test_bounded_ptr& ref = (to = from); _assert(to.discard_bounds() == static_cast(ptr1)); _assert(&ref == &to); // make sure we return *this } // Test assigning from a null pointer { test_bounded_ptr const from = nullptr; test_bounded_ptr to; test_bounded_ptr& ref = (to = from); _assert(to.unsafe_discard_bounds() == nullptr); _assert(&ref == &to); // make sure we return *this } // Test with different policies { libkern::bounded_ptr from(ptr1, array.begin(), array.end()); libkern::bounded_ptr to; libkern::bounded_ptr& ref = (to = from); _assert(to.discard_bounds() == static_cast(ptr1)); _assert(&ref == &to); // make sure we return *this } // T{0} T{1} T{2} T{3} T{4} // ^ ^ ^ // | | | // from begin end { test_bounded_ptr const from(array.begin(), array.begin() + 1, array.end()); test_bounded_ptr to; to = from; _assert(to.unsafe_discard_bounds() == static_cast(array.begin())); } } T_DECL(assign_convert, "bounded_ptr.assign.convert", T_META_TAG_VM_PREFERRED) { tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); // Make sure downcasts are disabled static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); // Make sure const-casting away doesn't work static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); // Make sure casting to unrelated types doesn't work implicitly static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_assignable_v, /*from*/ test_bounded_ptr >); // Make sure we can't assign from raw pointers static_assert(!std::is_assignable_v, /*from*/ Derived*>); }