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