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