diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -173,7 +173,9 @@ } // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers -template ::value> > +template ::value && !is_array<_Pointer>::value && !is_function<_Pointer>::value +> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename decay::__call(declval()))>::type __to_address(const _Pointer& __p) _NOEXCEPT { @@ -199,6 +201,12 @@ }; #if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +auto to_address(_Tp *__p) noexcept { + return _VSTD::__to_address(__p); +} + template inline _LIBCPP_INLINE_VISIBILITY constexpr auto to_address(const _Pointer& __p) noexcept { diff --git a/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address.pass.cpp b/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address.pass.cpp --- a/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address.pass.cpp +++ b/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address.pass.cpp @@ -137,6 +137,14 @@ assert(std::__to_address(p8b) == p8_nil); ASSERT_SAME_TYPE(decltype(std::__to_address(p8b)), decltype(p8_nil)); + int p9[2] = {}; + assert(std::__to_address(p9) == p9); + ASSERT_SAME_TYPE(decltype(std::__to_address(p9)), int*); + + const int p10[2] = {}; + assert(std::__to_address(p10) == p10); + ASSERT_SAME_TYPE(decltype(std::__to_address(p10)), const int*); + return true; } diff --git a/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address_on_funcptr.verify.cpp b/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address_on_funcptr.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address_on_funcptr.verify.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// template constexpr T* __to_address(T* p) noexcept; +// Mandates: T is not a function type. + +#include + +int (*pf)(); + +void test() { + (void)std::__to_address(pf); // expected-error@*:* {{is a function type}} +} diff --git a/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address_on_function.verify.cpp b/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address_on_function.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/memory/pointer.conversion/to_address_on_function.verify.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// template constexpr T* __to_address(T* p) noexcept; +// Mandates: T is not a function type. + +#include + +int f(); + +void test() { + (void)std::__to_address(f); // expected-error@*:* {{is a function type}} +} diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp --- a/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp +++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.pass.cpp @@ -139,6 +139,18 @@ assert(std::to_address(p8b) == p8_nil); ASSERT_SAME_TYPE(decltype(std::to_address(p8b)), decltype(p8_nil)); + int p9[2] = {}; + assert(std::to_address(p9) == p9); + ASSERT_SAME_TYPE(decltype(std::to_address(p9)), int*); + + const int p10[2] = {}; + assert(std::to_address(p10) == p10); + ASSERT_SAME_TYPE(decltype(std::to_address(p10)), const int*); + + int (*p11)() = nullptr; + assert(std::to_address(&p11) == &p11); + ASSERT_SAME_TYPE(decltype(std::to_address(&p11)), int(**)()); + return true; } diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address_on_funcptr.verify.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_on_funcptr.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_on_funcptr.verify.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// template constexpr T* to_address(T* p) noexcept; +// Mandates: T is not a function type. + +#include + +int (*pf)(); + +void test() { + (void)std::to_address(pf); // expected-error@*:* {{is a function type}} +} diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address_on_function.verify.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_on_function.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_on_function.verify.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// template constexpr T* to_address(T* p) noexcept; +// Mandates: T is not a function type. + +#include + +int f(); + +void test() { + (void)std::to_address(f); // expected-error@*:* {{is a function type}} +}