172 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// <memory>10 11// UNSUPPORTED: c++03, c++11, c++14, c++1712 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 called51 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 Clang72namespace 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 P783 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 P8100 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 compatibility136 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://llvm.org/PR67449157 {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