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