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 <utility>
19
20#include "test_macros.h"
21
22struct Irrelevant;
23
24struct P1 {
25 using element_type = Irrelevant;
26 constexpr explicit P1(int *p) : p_(p) { }
27 constexpr int *operator->() const { return p_; }
28 int *p_;
29};
30
31struct P2 {
32 using element_type = Irrelevant;
33 constexpr explicit P2(int *p) : p_(p) { }
34 constexpr P1 operator->() const { return p_; }
35 P1 p_;
36};
37
38struct P3 {
39 constexpr explicit P3(int *p) : p_(p) { }
40 int *p_;
41};
42
43template<>
44struct std::pointer_traits<P3> {
45 static constexpr int *to_address(const P3& p) { return p.p_; }
46};
47
48struct P4 {
49 constexpr explicit P4(int *p) : p_(p) { }
50 int *operator->() const; // should never be called
51 int *p_;
52};
53
54template<>
55struct std::pointer_traits<P4> {
56 static constexpr int *to_address(const P4& p) { return p.p_; }
57};
58
59struct P5 {
60 using element_type = Irrelevant;
61 int const* const& operator->() const;
62};
63
64struct P6 {};
65
66template<>
67struct std::pointer_traits<P6> {
68 static int const* const& to_address(const P6&);
69};
70
71// Taken from a build breakage caused in Clang
72namespace P7 {
73 template<typename T> struct CanProxy;
74 template<typename T>
75 struct CanQual {
76 CanProxy<T> operator->() const { return CanProxy<T>(); }
77 };
78 template<typename T>
79 struct CanProxy {
80 const CanProxy<T> *operator->() const { return nullptr; }
81 };
82} // namespace P7
83
84namespace P8 {
85 template<class T>
86 struct FancyPtrA {
87 using element_type = Irrelevant;
88 T *p_;
89 TEST_CONSTEXPR FancyPtrA(T *p) : p_(p) {}
90 T& operator*() const;
91 TEST_CONSTEXPR T *operator->() const { return p_; }
92 };
93 template<class T>
94 struct FancyPtrB {
95 T *p_;
96 TEST_CONSTEXPR FancyPtrB(T *p) : p_(p) {}
97 T& operator*() const;
98 };
99} // namespace P8
100
101template<class T>
102struct std::pointer_traits<P8::FancyPtrB<T> > {
103 static TEST_CONSTEXPR T *to_address(const P8::FancyPtrB<T>& p) { return p.p_; }
104};
105
106struct Incomplete;
107template<class T> struct Holder { T t; };
108
109
110constexpr bool test() {
111 int i = 0;
112 ASSERT_NOEXCEPT(std::to_address(&i));
113 assert(std::to_address(&i) == &i);
114 P1 p1(&i);
115 ASSERT_NOEXCEPT(std::to_address(p1));
116 assert(std::to_address(p1) == &i);
117 P2 p2(&i);
118 ASSERT_NOEXCEPT(std::to_address(p2));
119 assert(std::to_address(p2) == &i);
120 P3 p3(&i);
121 ASSERT_NOEXCEPT(std::to_address(p3));
122 assert(std::to_address(p3) == &i);
123 P4 p4(&i);
124 ASSERT_NOEXCEPT(std::to_address(p4));
125 assert(std::to_address(p4) == &i);
126
127 ASSERT_SAME_TYPE(decltype(std::to_address(std::declval<int const*>())), int const*);
128 ASSERT_SAME_TYPE(decltype(std::to_address(std::declval<P5>())), int const*);
129 ASSERT_SAME_TYPE(decltype(std::to_address(std::declval<P6>())), int const*);
130
131 P7::CanQual<int>* p7 = nullptr;
132 assert(std::to_address(p7) == nullptr);
133 ASSERT_SAME_TYPE(decltype(std::to_address(p7)), P7::CanQual<int>*);
134
135 Holder<Incomplete> *p8_nil = nullptr; // for C++03 compatibility
136 P8::FancyPtrA<Holder<Incomplete> > p8a = p8_nil;
137 assert(std::to_address(p8a) == p8_nil);
138 ASSERT_SAME_TYPE(decltype(std::to_address(p8a)), decltype(p8_nil));
139
140 P8::FancyPtrB<Holder<Incomplete> > p8b = p8_nil;
141 assert(std::to_address(p8b) == p8_nil);
142 ASSERT_SAME_TYPE(decltype(std::to_address(p8b)), decltype(p8_nil));
143
144 int p9[2] = {};
145 assert(std::to_address(p9) == p9);
146 ASSERT_SAME_TYPE(decltype(std::to_address(p9)), int*);
147
148 const int p10[2] = {};
149 assert(std::to_address(p10) == p10);
150 ASSERT_SAME_TYPE(decltype(std::to_address(p10)), const int*);
151
152 int (*p11)() = nullptr;
153 assert(std::to_address(&p11) == &p11);
154 ASSERT_SAME_TYPE(decltype(std::to_address(&p11)), int(**)());
155
156 // See https://github.com/llvm/llvm-project/issues/67449
157 {
158 struct S { };
159 S* p = nullptr;
160 assert(std::to_address<S>(p) == p);
161 ASSERT_SAME_TYPE(decltype(std::to_address<S>(p)), S*);
162 }
163
164 return true;
165}
166
167int main(int, char**) {
168 test();
169 static_assert(test());
170 return 0;
171}
172

source code of libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp