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; 24 constexpr explicit P1(int *p) : p_(p) { } 25 constexpr int *operator->() const { return p_; } 26 int *p_; 27 }; 28 29 struct P2 { 30 using element_type = Irrelevant; 31 constexpr explicit P2(int *p) : p_(p) { } 32 constexpr P1 operator->() const { return p_; } 33 P1 p_; 34 }; 35 36 struct P3 { 37 constexpr explicit P3(int *p) : p_(p) { } 38 int *p_; 39 }; 40 41 template<> 42 struct std::pointer_traits<P3> { 43 static constexpr int *to_address(const P3& p) { return p.p_; } 44 }; 45 46 struct P4 { 47 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> { 54 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 { 74 CanProxy<T> operator->() const { return CanProxy<T>(); } 75 }; 76 template<typename T> 77 struct CanProxy { 78 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_; 87 TEST_CONSTEXPR FancyPtrA(T *p) : p_(p) {} 88 T& operator*() const; 89 TEST_CONSTEXPR T *operator->() const { return p_; } 90 }; 91 template<class T> 92 struct FancyPtrB { 93 T *p_; 94 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> > { 101 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 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 157 int main(int, char**) { 158 test(); 159 static_assert(test()); 160 return 0; 161 } 162