1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // <memory>
10
11 // template <class T> constexpr T* __to_address(T* p) noexcept;
12 // template <class Ptr> constexpr auto __to_address(const Ptr& p) noexcept;
13
14 #include <memory>
15 #include <cassert>
16 #include "test_macros.h"
17
18 struct Irrelevant;
19
20 struct P1 {
21 using element_type = Irrelevant;
P1P122 TEST_CONSTEXPR explicit P1(int *p) : p_(p) { }
operator ->P123 TEST_CONSTEXPR int *operator->() const { return p_; }
24 int *p_;
25 };
26
27 struct P2 {
28 using element_type = Irrelevant;
P2P229 TEST_CONSTEXPR explicit P2(int *p) : p_(p) { }
operator ->P230 TEST_CONSTEXPR P1 operator->() const { return p_; }
31 P1 p_;
32 };
33
34 struct P3 {
P3P335 TEST_CONSTEXPR explicit P3(int *p) : p_(p) { }
36 int *p_;
37 };
38
39 template<>
40 struct std::pointer_traits<P3> {
to_addressstd::pointer_traits41 static TEST_CONSTEXPR int *to_address(const P3& p) { return p.p_; }
42 };
43
44 struct P4 {
P4P445 TEST_CONSTEXPR explicit P4(int *p) : p_(p) { }
46 int *operator->() const; // should never be called
47 int *p_;
48 };
49
50 template<>
51 struct std::pointer_traits<P4> {
to_addressstd::pointer_traits52 static TEST_CONSTEXPR int *to_address(const P4& p) { return p.p_; }
53 };
54
55 struct P5 {
56 using element_type = Irrelevant;
57 int const* const& operator->() const;
58 };
59
60 struct P6 {};
61
62 template<>
63 struct std::pointer_traits<P6> {
64 static int const* const& to_address(const P6&);
65 };
66
67 // Taken from a build breakage caused in Clang
68 namespace P7 {
69 template<typename T> struct CanProxy;
70 template<typename T>
71 struct CanQual {
operator ->P7::CanQual72 CanProxy<T> operator->() const { return CanProxy<T>(); }
73 };
74 template<typename T>
75 struct CanProxy {
operator ->P7::CanProxy76 const CanProxy<T> *operator->() const { return nullptr; }
77 };
78 } // namespace P7
79
80 namespace P8 {
81 template<class T>
82 struct FancyPtrA {
83 using element_type = Irrelevant;
84 T *p_;
FancyPtrAP8::FancyPtrA85 TEST_CONSTEXPR FancyPtrA(T *p) : p_(p) {}
86 T& operator*() const;
operator ->P8::FancyPtrA87 TEST_CONSTEXPR T *operator->() const { return p_; }
88 };
89 template<class T>
90 struct FancyPtrB {
91 T *p_;
FancyPtrBP8::FancyPtrB92 TEST_CONSTEXPR FancyPtrB(T *p) : p_(p) {}
93 T& operator*() const;
94 };
95 } // namespace P8
96
97 template<class T>
98 struct std::pointer_traits<P8::FancyPtrB<T> > {
to_addressstd::pointer_traits99 static TEST_CONSTEXPR T *to_address(const P8::FancyPtrB<T>& p) { return p.p_; }
100 };
101
102 struct Incomplete;
103 template<class T> struct Holder { T t; };
104
105
test()106 TEST_CONSTEXPR_CXX14 bool test() {
107 int i = 0;
108 ASSERT_NOEXCEPT(std::__to_address(&i));
109 assert(std::__to_address(&i) == &i);
110 P1 p1(&i);
111 ASSERT_NOEXCEPT(std::__to_address(p1));
112 assert(std::__to_address(p1) == &i);
113 P2 p2(&i);
114 ASSERT_NOEXCEPT(std::__to_address(p2));
115 assert(std::__to_address(p2) == &i);
116 P3 p3(&i);
117 ASSERT_NOEXCEPT(std::__to_address(p3));
118 assert(std::__to_address(p3) == &i);
119 P4 p4(&i);
120 ASSERT_NOEXCEPT(std::__to_address(p4));
121 assert(std::__to_address(p4) == &i);
122
123 ASSERT_SAME_TYPE(decltype(std::__to_address(std::declval<int const*>())), int const*);
124 ASSERT_SAME_TYPE(decltype(std::__to_address(std::declval<P5>())), int const*);
125 ASSERT_SAME_TYPE(decltype(std::__to_address(std::declval<P6>())), int const*);
126
127 P7::CanQual<int>* p7 = nullptr;
128 assert(std::__to_address(p7) == nullptr);
129 ASSERT_SAME_TYPE(decltype(std::__to_address(p7)), P7::CanQual<int>*);
130
131 Holder<Incomplete> *p8_nil = nullptr; // for C++03 compatibility
132 P8::FancyPtrA<Holder<Incomplete> > p8a = p8_nil;
133 assert(std::__to_address(p8a) == p8_nil);
134 ASSERT_SAME_TYPE(decltype(std::__to_address(p8a)), decltype(p8_nil));
135
136 P8::FancyPtrB<Holder<Incomplete> > p8b = p8_nil;
137 assert(std::__to_address(p8b) == p8_nil);
138 ASSERT_SAME_TYPE(decltype(std::__to_address(p8b)), decltype(p8_nil));
139
140 return true;
141 }
142
main(int,char **)143 int main(int, char**) {
144 test();
145 #if TEST_STD_VER >= 14
146 static_assert(test(), "");
147 #endif
148 return 0;
149 }
150