Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | // // Tests for // template <typename U, typename Policy> // bounded_ptr& operator=(bounded_ptr<U, Policy> const& other); // #include <libkern/c++/bounded_ptr.h> #include <array> #include <darwintest.h> #include <darwintest_utils.h> #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 <typename Stored, typename From, typename To> static void tests() { std::array<Stored, 5> 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<From> const from(ptr1, array.begin(), array.end()); test_bounded_ptr<To> to; test_bounded_ptr<To>& ref = (to = from); _assert(to.discard_bounds() == static_cast<To const*>(ptr1)); _assert(&ref == &to); // make sure we return *this } // Test assigning to a non-null pointer { test_bounded_ptr<From> const from(ptr1, array.begin(), array.end()); test_bounded_ptr<To> to(ptr2, array.begin(), array.end()); _assert(to.discard_bounds() == static_cast<To const*>(ptr2)); test_bounded_ptr<To>& ref = (to = from); _assert(to.discard_bounds() == static_cast<To const*>(ptr1)); _assert(&ref == &to); // make sure we return *this } // Test assigning from a null pointer { test_bounded_ptr<From> const from = nullptr; test_bounded_ptr<To> to; test_bounded_ptr<To>& 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, dummy_policy1> from(ptr1, array.begin(), array.end()); libkern::bounded_ptr<To, dummy_policy2> to; libkern::bounded_ptr<To, dummy_policy2>& ref = (to = from); _assert(to.discard_bounds() == static_cast<To const*>(ptr1)); _assert(&ref == &to); // make sure we return *this } // T{0} T{1} T{2} T{3} T{4} <one-past-last> // ^ ^ ^ // | | | // from begin end { test_bounded_ptr<From> const from(array.begin(), array.begin() + 1, array.end()); test_bounded_ptr<To> to; to = from; _assert(to.unsafe_discard_bounds() == static_cast<To const*>(array.begin())); } } T_DECL(assign_convert, "bounded_ptr.assign.convert", T_META_TAG_VM_PREFERRED) { tests</*stored*/ Derived, /*from*/ Derived, /*to*/ Derived>(); tests</*stored*/ Derived, /*from*/ Derived const, /*to*/ Derived const>(); tests</*stored*/ Derived, /*from*/ Derived volatile, /*to*/ Derived volatile>(); tests</*stored*/ Derived, /*from*/ Derived const volatile, /*to*/ Derived const volatile>(); tests</*stored*/ Derived, /*from*/ Derived, /*to*/ Base>(); tests</*stored*/ Derived, /*from*/ Derived const, /*to*/ Base const>(); tests</*stored*/ Derived, /*from*/ Derived volatile, /*to*/ Base volatile>(); tests</*stored*/ Derived, /*from*/ Derived const volatile, /*to*/ Base const volatile>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple, /*to*/ Base1>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple const, /*to*/ Base1 const>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple volatile, /*to*/ Base1 volatile>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple const volatile, /*to*/ Base1 const volatile>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple, /*to*/ Base2>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple const, /*to*/ Base2 const>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple volatile, /*to*/ Base2 volatile>(); tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple const volatile, /*to*/ Base2 const volatile>(); tests</*stored*/ Derived, /*from*/ Derived, /*to*/ void>(); tests</*stored*/ Derived, /*from*/ Derived const, /*to*/ void const>(); tests</*stored*/ Derived, /*from*/ Derived volatile, /*to*/ void volatile>(); tests</*stored*/ Derived, /*from*/ Derived const volatile, /*to*/ void const volatile>(); // Make sure downcasts are disabled static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<Derived>, /*from*/ test_bounded_ptr<Base> >); static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<DerivedMultiple>, /*from*/ test_bounded_ptr<Base1> >); static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<DerivedMultiple>, /*from*/ test_bounded_ptr<Base2> >); static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<Base2>, /*from*/ test_bounded_ptr<Base1> >); // Make sure const-casting away doesn't work static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<Derived>, /*from*/ test_bounded_ptr<Derived const> >); // Make sure casting to unrelated types doesn't work implicitly static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<char>, /*from*/ test_bounded_ptr<Derived> >); static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<Unrelated>, /*from*/ test_bounded_ptr<Derived> >); static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<Base2>, /*from*/ test_bounded_ptr<Base1> >); // Make sure we can't assign from raw pointers static_assert(!std::is_assignable_v</*to*/ test_bounded_ptr<Derived>, /*from*/ Derived*>); } |