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 // UNSUPPORTED: c++03, c++11, c++14, c++17
12
13 // template <class T> constexpr T* to_address(T* p) noexcept;
14 // template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
15
16 #include <memory>
17 #include <cassert>
18 #include "test_macros.h"
19
20 struct Irrelevant;
21
22 struct P1 {
23 using element_type = Irrelevant;
P1P124 constexpr explicit P1(int *p) : p_(p) { }
operator ->P125 constexpr int *operator->() const { return p_; }
26 int *p_;
27 };
28
29 struct P2 {
30 using element_type = Irrelevant;
P2P231 constexpr explicit P2(int *p) : p_(p) { }
operator ->P232 constexpr P1 operator->() const { return p_; }
33 P1 p_;
34 };
35
36 struct P3 {
P3P337 constexpr explicit P3(int *p) : p_(p) { }
38 int *p_;
39 };
40
41 template<>
42 struct std::pointer_traits<P3> {
to_addressstd::pointer_traits43 static constexpr int *to_address(const P3& p) { return p.p_; }
44 };
45
46 struct P4 {
P4P447 constexpr explicit P4(int *p) : p_(p) { }
48 int *operator->() const; // should never be called
49 int *p_;
50 };
51
52 template<>
53 struct std::pointer_traits<P4> {
to_addressstd::pointer_traits54 static constexpr int *to_address(const P4& p) { return p.p_; }
55 };
56
57 struct P5 {
58 using element_type = Irrelevant;
59 int const* const& operator->() const;
60 };
61
62 struct P6 {};
63
64 template<>
65 struct std::pointer_traits<P6> {
66 static int const* const& to_address(const P6&);
67 };
68
69 // Taken from a build breakage caused in Clang
70 namespace P7 {
71 template<typename T> struct CanProxy;
72 template<typename T>
73 struct CanQual {
operator ->P7::CanQual74 CanProxy<T> operator->() const { return CanProxy<T>(); }
75 };
76 template<typename T>
77 struct CanProxy {
operator ->P7::CanProxy78 const CanProxy<T> *operator->() const { return nullptr; }
79 };
80 } // namespace P7
81
82 namespace P8 {
83 template<class T>
84 struct FancyPtrA {
85 using element_type = Irrelevant;
86 T *p_;
FancyPtrAP8::FancyPtrA87 TEST_CONSTEXPR FancyPtrA(T *p) : p_(p) {}
88 T& operator*() const;
operator ->P8::FancyPtrA89 TEST_CONSTEXPR T *operator->() const { return p_; }
90 };
91 template<class T>
92 struct FancyPtrB {
93 T *p_;
FancyPtrBP8::FancyPtrB94 TEST_CONSTEXPR FancyPtrB(T *p) : p_(p) {}
95 T& operator*() const;
96 };
97 } // namespace P8
98
99 template<class T>
100 struct std::pointer_traits<P8::FancyPtrB<T> > {
to_addressstd::pointer_traits101 static TEST_CONSTEXPR T *to_address(const P8::FancyPtrB<T>& p) { return p.p_; }
102 };
103
104 struct Incomplete;
105 template<class T> struct Holder { T t; };
106
107
test()108 constexpr bool test() {
109 int i = 0;
110 ASSERT_NOEXCEPT(std::to_address(&i));
111 assert(std::to_address(&i) == &i);
112 P1 p1(&i);
113 ASSERT_NOEXCEPT(std::to_address(p1));
114 assert(std::to_address(p1) == &i);
115 P2 p2(&i);
116 ASSERT_NOEXCEPT(std::to_address(p2));
117 assert(std::to_address(p2) == &i);
118 P3 p3(&i);
119 ASSERT_NOEXCEPT(std::to_address(p3));
120 assert(std::to_address(p3) == &i);
121 P4 p4(&i);
122 ASSERT_NOEXCEPT(std::to_address(p4));
123 assert(std::to_address(p4) == &i);
124
125 ASSERT_SAME_TYPE(decltype(std::to_address(std::declval<int const*>())), int const*);
126 ASSERT_SAME_TYPE(decltype(std::to_address(std::declval<P5>())), int const*);
127 ASSERT_SAME_TYPE(decltype(std::to_address(std::declval<P6>())), int const*);
128
129 P7::CanQual<int>* p7 = nullptr;
130 assert(std::to_address(p7) == nullptr);
131 ASSERT_SAME_TYPE(decltype(std::to_address(p7)), P7::CanQual<int>*);
132
133 Holder<Incomplete> *p8_nil = nullptr; // for C++03 compatibility
134 P8::FancyPtrA<Holder<Incomplete> > p8a = p8_nil;
135 assert(std::to_address(p8a) == p8_nil);
136 ASSERT_SAME_TYPE(decltype(std::to_address(p8a)), decltype(p8_nil));
137
138 P8::FancyPtrB<Holder<Incomplete> > p8b = p8_nil;
139 assert(std::to_address(p8b) == p8_nil);
140 ASSERT_SAME_TYPE(decltype(std::to_address(p8b)), decltype(p8_nil));
141
142 int p9[2] = {};
143 assert(std::to_address(p9) == p9);
144 ASSERT_SAME_TYPE(decltype(std::to_address(p9)), int*);
145
146 const int p10[2] = {};
147 assert(std::to_address(p10) == p10);
148 ASSERT_SAME_TYPE(decltype(std::to_address(p10)), const int*);
149
150 int (*p11)() = nullptr;
151 assert(std::to_address(&p11) == &p11);
152 ASSERT_SAME_TYPE(decltype(std::to_address(&p11)), int(**)());
153
154 return true;
155 }
156
main(int,char **)157 int main(int, char**) {
158 test();
159 static_assert(test());
160 return 0;
161 }
162