[libcxx-commits] [libcxx] [libc++] Implement LWG3545: std::pointer_traits should be SFINAE-friendly. (PR #65177)
Daniel Cheng via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 14 17:35:27 PDT 2023
https://github.com/zetafunction updated https://github.com/llvm/llvm-project/pull/65177:
>From a47d0c6daba5f73794e11848f2bfb19e612ef6dd Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Fri, 25 Aug 2023 23:46:50 -0700
Subject: [PATCH 1/9] [libc++] Implement LWG3545: std::pointer_traits should be
SFINAE-friendly.
See https://wg21.link/LWG3545 for background and details.
Differential Revision: https://reviews.llvm.org/D158922
---
libcxx/docs/Status/Cxx23Issues.csv | 2 +-
libcxx/include/__memory/pointer_traits.h | 17 +-
.../contiguous_iterator.verify.cpp | 54 ------
.../pointer_traits.pass.cpp | 176 ++++++++++++++++++
.../pointer.conversion/to_address.verify.cpp | 23 +++
...to_address_without_pointer_traits.pass.cpp | 66 +++++++
6 files changed, 277 insertions(+), 61 deletions(-)
delete mode 100644 libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp
create mode 100644 libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp
create mode 100644 libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp
create mode 100644 libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 2a00289af376924..a0d4b22e20d037b 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -190,7 +190,7 @@
"`3118 <https://wg21.link/LWG3118>`__","``fpos`` equality comparison unspecified", "November 2022","","",""
"`3177 <https://wg21.link/LWG3177>`__","Limit permission to specialize variable templates to program-defined types", "November 2022","|Nothing to do|","",""
"`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","",""
-"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","","",""
+"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0",""
"`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|"
"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","","",""
"`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|"
diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index c33e7bd43f29f7d..7617948ed76bd66 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -35,7 +35,7 @@ template <class _Tp>
struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {};
template <class _Ptr, bool = __has_element_type<_Ptr>::value>
-struct __pointer_traits_element_type;
+struct __pointer_traits_element_type {};
template <class _Ptr>
struct __pointer_traits_element_type<_Ptr, true>
@@ -111,12 +111,14 @@ struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
typedef _Sp<_Up, _Args...> type;
};
+template <class _Ptr, class = void>
+struct __pointer_traits_impl {};
+
template <class _Ptr>
-struct _LIBCPP_TEMPLATE_VIS pointer_traits
-{
- typedef _Ptr pointer;
- typedef typename __pointer_traits_element_type<pointer>::type element_type;
- typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
+struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {
+ typedef _Ptr pointer;
+ typedef typename __pointer_traits_element_type<pointer>::type element_type;
+ typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
#ifndef _LIBCPP_CXX03_LANG
template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
@@ -133,6 +135,9 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits
{return pointer::pointer_to(__r);}
};
+template <class _Ptr>
+struct _LIBCPP_TEMPLATE_VIS pointer_traits : __pointer_traits_impl<_Ptr> {};
+
template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*>
{
diff --git a/libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp b/libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp
deleted file mode 100644
index 37c5ad9610a60cb..000000000000000
--- a/libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// This test checks that std::contiguous_iterator uses std::to_address, which is not SFINAE-friendly
-// when the type is missing the `T::element_type` typedef.
-
-#include <iterator>
-
-#include <compare>
-#include <cstddef>
-
-struct no_element_type {
- typedef std::contiguous_iterator_tag iterator_category;
- typedef int value_type;
- typedef std::ptrdiff_t difference_type;
- typedef int* pointer;
- typedef int& reference;
- typedef no_element_type self;
-
- no_element_type();
-
- reference operator*() const;
- pointer operator->() const;
- auto operator<=>(const self&) const = default;
-
- self& operator++();
- self operator++(int);
-
- self& operator--();
- self operator--(int);
-
- self& operator+=(difference_type n);
- self operator+(difference_type n) const;
- friend self operator+(difference_type n, self x);
-
- self& operator-=(difference_type n);
- self operator-(difference_type n) const;
- difference_type operator-(const self& n) const;
-
- reference operator[](difference_type n) const;
-};
-
-void test() {
- (void) std::contiguous_iterator<no_element_type>;
- // expected-error@*:* {{implicit instantiation of undefined template}}
- // expected-note@*:* {{to_address}}
-}
diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp
new file mode 100644
index 000000000000000..33316a36ada9c33
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp
@@ -0,0 +1,176 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// Tests that pointer_traits has the expected members.
+
+#include <memory>
+#include <cassert>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class T, class = void>
+struct HasElementType : std::false_type {};
+
+template <class T>
+struct HasElementType<T, std::void_t<typename std::pointer_traits<T>::element_type>> : std::true_type {};
+
+template <class T, class = void>
+struct HasPointerType : std::false_type {};
+
+template <class T>
+struct HasPointerType<T, std::void_t<typename std::pointer_traits<T>::pointer>> : std::true_type {};
+
+template <class T, class = void>
+struct HasDifferenceType : std::false_type {};
+
+template <class T>
+struct HasDifferenceType<T, std::void_t<typename std::pointer_traits<T>::difference_type>> : std::true_type {};
+
+template <class T, class U, class = void>
+struct HasRebind : std::false_type {};
+
+template <class T, class U>
+struct HasRebind<T, U, std::void_t<typename std::pointer_traits<T>::template rebind<U>>> : std::true_type {};
+
+template <class T, class = void>
+struct HasPointerTo : std::false_type {};
+
+template <class T>
+struct HasPointerTo<T,
+ std::void_t<decltype(std::pointer_traits<T>::pointer_to(
+ std::declval<std::add_lvalue_reference_t<typename std::pointer_traits<T>::element_type>>()))>>
+ : std::true_type {};
+
+struct Irrelevant;
+
+struct NotAPtr {};
+
+struct LongPtr;
+
+int global_int;
+
+template <class T, class Arg>
+struct TemplatedPtr;
+
+struct PtrWithElementType {
+ using element_type = int;
+ template <typename U>
+ using rebind = TemplatedPtr<U, Irrelevant>;
+ static constexpr auto pointer_to(element_type&) { return PtrWithElementType{&global_int}; }
+
+ int* ptr;
+};
+
+template <class T, class Arg>
+struct TemplatedPtr {
+ template <typename U, typename = std::enable_if_t<std::is_same_v<long, U>>>
+ using rebind = LongPtr;
+ static constexpr auto pointer_to(T&) { return TemplatedPtr{&global_int}; }
+
+ T* ptr;
+};
+
+template <class T, class Arg>
+struct TemplatedPtrWithElementType {
+ using element_type = int;
+ template <typename U, typename = std::enable_if_t<std::is_same_v<long, U>>>
+ using rebind = LongPtr;
+ static constexpr auto pointer_to(element_type&) { return TemplatedPtrWithElementType{&global_int}; }
+
+ element_type* ptr;
+};
+
+constexpr bool test() {
+ {
+ using Ptr = NotAPtr;
+ assert(!HasElementType<Ptr>::value);
+ assert(!HasPointerType<Ptr>::value);
+ assert(!HasDifferenceType<Ptr>::value);
+ assert((!HasRebind<Ptr, long>::value));
+ assert(!HasPointerTo<Ptr>::value);
+ }
+
+ {
+ using Ptr = PtrWithElementType;
+
+ assert(HasElementType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+ assert(HasPointerType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+ assert(HasDifferenceType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
+
+ // TODO: Consider supporting SFINAE testing of std::pointer_traits<Ptr>.
+ assert((HasRebind<Ptr, long>::value));
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, TemplatedPtr<long, Irrelevant>);
+
+ assert(HasPointerTo<Ptr>::value);
+ int ignored;
+ assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ }
+
+ {
+ using Ptr = TemplatedPtr<int, Irrelevant>;
+
+ assert(HasElementType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+ assert(HasPointerType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+ assert(HasDifferenceType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
+
+ assert((HasRebind<Ptr, long>::value));
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
+ assert((HasRebind<Ptr, long long>::value));
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtr<long long, Irrelevant>);
+
+ assert(HasPointerTo<Ptr>::value);
+ int ignored;
+ assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ }
+
+ {
+ using Ptr = TemplatedPtrWithElementType<Irrelevant, Irrelevant>;
+
+ assert(HasElementType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+ assert(HasPointerType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+ assert(HasDifferenceType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
+
+ assert((HasRebind<Ptr, long>::value));
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
+ assert((HasRebind<Ptr, long long>::value));
+ ASSERT_SAME_TYPE(
+ typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtrWithElementType<long long, Irrelevant>);
+
+ assert(HasPointerTo<Ptr>::value);
+ int ignored;
+ assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp
new file mode 100644
index 000000000000000..8eddbe4c137190e
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
+// Mandates: one of pointer_traits<Ptr>::to_address() or Ptr::operator->()
+// is present.
+
+#include <memory>
+
+struct NotPtr {};
+
+void test() {
+ (void)std::to_address(NotPtr()); // expected-error@*:* {{no matching function for call to 'to_address'}}
+}
diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp
new file mode 100644
index 000000000000000..4d05c10e0fbdc95
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
+// Should not require a specialization of pointer_traits for Ptr.
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+struct IntPtr {
+ constexpr int* operator->() const { return ptr; }
+
+ int* ptr;
+};
+
+template <class T, bool>
+struct TemplatedPtr {
+ constexpr T* operator->() const { return ptr; }
+
+ T* ptr;
+};
+
+template <template <class...> class Templ, class Ignore, class... Args>
+struct is_valid_expansion_impl : std::false_type {};
+
+template <template <class...> class Templ, class... Args>
+struct is_valid_expansion_impl<Templ, decltype((void)Templ<Args...>{}, 0), Args...> : std::true_type {};
+
+template <template <class...> class Templ, class... Args>
+using is_valid_expansion = is_valid_expansion_impl<Templ, int, Args...>;
+
+template <class Ptr>
+using TestToAddressCall = decltype(std::to_address(std::declval<Ptr>()));
+
+constexpr bool test() {
+ int i = 0;
+
+ static_assert(std::to_address(IntPtr{nullptr}) == nullptr);
+ static_assert(std::to_address(IntPtr{&i}) == &i);
+
+ bool b = false;
+
+ static_assert(std::to_address(TemplatedPtr<bool, true>{nullptr}) == nullptr);
+ static_assert(std::to_address(TemplatedPtr<bool, true>{&b}) == &b);
+
+ static_assert(!is_valid_expansion<TestToAddressCall, int>::value);
+ static_assert(is_valid_expansion<TestToAddressCall, IntPtr>::value);
+ static_assert(is_valid_expansion<TestToAddressCall, TemplatedPtr<bool, true>>::value);
+
+ return true;
+}
+
+int main(int, char**) {
+ static_assert(test());
+ return 0;
+}
>From 57702c7574bfaf4a67d3419aadd56ae75a85c7b8 Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Tue, 12 Sep 2023 15:10:06 -0700
Subject: [PATCH 2/9] Consolidate tests and add better coverage of T*
specialization.
---
.../pointer.traits/difference_type.pass.cpp | 28 ---------
.../pointer.traits/element_type.pass.cpp | 28 ---------
.../memory/pointer.traits/pointer.pass.cpp | 35 -----------
.../memory/pointer.traits/rebind.pass.cpp | 32 ----------
.../types.pass.cpp} | 62 ++++++++++++++++++-
5 files changed, 61 insertions(+), 124 deletions(-)
delete mode 100644 libcxx/test/std/utilities/memory/pointer.traits/difference_type.pass.cpp
delete mode 100644 libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp
delete mode 100644 libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp
delete mode 100644 libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp
rename libcxx/test/std/utilities/memory/{pointer.conversion/pointer_traits.pass.cpp => pointer.traits/types.pass.cpp} (72%)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/difference_type.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/difference_type.pass.cpp
deleted file mode 100644
index 7546df902882065..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/difference_type.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class T>
-// struct pointer_traits<T*>
-// {
-// typedef ptrdiff_t difference_type;
-// ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
- static_assert((std::is_same<std::pointer_traits<double*>::difference_type, std::ptrdiff_t>::value), "");
-
- return 0;
-}
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp
deleted file mode 100644
index e4f11c28e29be6b..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class T>
-// struct pointer_traits<T*>
-// {
-// typedef T element_type;
-// ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
- static_assert((std::is_same<std::pointer_traits<const short*>::element_type, const short>::value), "");
-
- return 0;
-}
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp
deleted file mode 100644
index 14054b3c4f65bc4..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class Ptr>
-// struct pointer_traits
-// {
-// typedef Ptr pointer;
-// ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-struct A
-{
- typedef short element_type;
- typedef char difference_type;
-};
-
-int main(int, char**)
-{
- static_assert((std::is_same<std::pointer_traits<A>::pointer, A>::value), "");
- static_assert((std::is_same<std::pointer_traits<int*>::pointer, int*>::value), "");
-
- return 0;
-}
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp
deleted file mode 100644
index f64213c9b887ceb..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class T>
-// struct pointer_traits<T*>
-// {
-// template <class U> using rebind = U*;
-// ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
-#if TEST_STD_VER >= 11
- static_assert((std::is_same<std::pointer_traits<int*>::rebind<double>, double*>::value), "");
-#else
- static_assert((std::is_same<std::pointer_traits<int*>::rebind<double>::other, double*>::value), "");
-#endif
-
- return 0;
-}
diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
similarity index 72%
rename from libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp
rename to libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
index 33316a36ada9c33..1626e82f4ce8ddd 100644
--- a/libcxx/test/std/utilities/memory/pointer.conversion/pointer_traits.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
@@ -10,7 +10,22 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
-// Tests that pointer_traits has the expected members.
+// template <class Ptr>
+// struct pointer_traits
+// {
+// <details>
+// };
+//
+// template <class T>
+// struct pointer_traits<T*>
+// {
+// using pointer = T*;
+// using element_type = T;
+// using difference_type = ptrdiff_t;
+// template <class U> using rebind = U*;
+// static constexpr pointer pointer_to(<details>) noexcept;
+// ...
+// };
#include <memory>
#include <cassert>
@@ -100,6 +115,51 @@ constexpr bool test() {
assert(!HasPointerTo<Ptr>::value);
}
+ {
+ using Ptr = int*;
+
+ assert(HasElementType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+ assert(HasPointerType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+ assert(HasDifferenceType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
+
+ assert((HasRebind<Ptr, long>::value));
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
+
+ assert(HasPointerTo<Ptr>::value);
+ int variable;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), int*);
+ assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
+ }
+
+ {
+ using Ptr = const int*;
+
+ assert(HasElementType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, const int);
+
+ assert(HasPointerType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+ assert(HasDifferenceType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
+
+ assert((HasRebind<Ptr, long>::value));
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
+
+ assert(HasPointerTo<Ptr>::value);
+ const int const_variable = 0;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(const_variable)), const int*);
+ assert(std::pointer_traits<Ptr>::pointer_to(const_variable) == &const_variable);
+ int variable = 0;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), const int*);
+ assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
+ }
+
{
using Ptr = PtrWithElementType;
>From df24dad34563a6fa3490baa5dea0d0c9c8024657 Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Tue, 12 Sep 2023 16:09:21 -0700
Subject: [PATCH 3/9] Test pre-C++20 pointer_traits.
---
.../memory/pointer.traits/types.pass.cpp | 59 ++++++++++++++-----
1 file changed, 43 insertions(+), 16 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
index 1626e82f4ce8ddd..52844aa0ffa0ec7 100644
--- a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
@@ -8,8 +8,6 @@
// <memory>
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
// template <class Ptr>
// struct pointer_traits
// {
@@ -131,9 +129,13 @@ constexpr bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
assert(HasPointerTo<Ptr>::value);
- int variable;
- ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), int*);
- assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
+ int variable = 0;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), Ptr);
+#if TEST_STD_VER >= 17
+ if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
+ assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
+ }
+#endif
}
{
@@ -153,11 +155,19 @@ constexpr bool test() {
assert(HasPointerTo<Ptr>::value);
const int const_variable = 0;
- ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(const_variable)), const int*);
- assert(std::pointer_traits<Ptr>::pointer_to(const_variable) == &const_variable);
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(const_variable)), Ptr);
+#if TEST_STD_VER >= 17
+ if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
+ assert(std::pointer_traits<Ptr>::pointer_to(const_variable) == &const_variable);
+ }
+#endif
int variable = 0;
- ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), const int*);
- assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), Ptr);
+#if TEST_STD_VER >= 17
+ if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
+ assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
+ }
+#endif
}
{
@@ -177,8 +187,13 @@ constexpr bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, TemplatedPtr<long, Irrelevant>);
assert(HasPointerTo<Ptr>::value);
- int ignored;
- assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ int ignored = 0;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
+#if TEST_STD_VER >= 17
+ if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
+ assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ }
+#endif
}
{
@@ -199,8 +214,13 @@ constexpr bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtr<long long, Irrelevant>);
assert(HasPointerTo<Ptr>::value);
- int ignored;
- assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ int ignored = 0;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
+#if TEST_STD_VER >= 17
+ if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
+ assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ }
+#endif
}
{
@@ -222,8 +242,13 @@ constexpr bool test() {
typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtrWithElementType<long long, Irrelevant>);
assert(HasPointerTo<Ptr>::value);
- int ignored;
- assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ int ignored = 0;
+ ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
+#if TEST_STD_VER >= 17
+ if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
+ assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
+ }
+#endif
}
return true;
@@ -231,6 +256,8 @@ constexpr bool test() {
int main(int, char**) {
test();
- static_assert(test());
+#if TEST_STD_VER >= 11
+ static_assert(test(), "");
+#endif
return 0;
}
>From 9506efcb79649f3df9b2a14ddcf9b13884a8c32e Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Tue, 12 Sep 2023 16:26:34 -0700
Subject: [PATCH 4/9] Support pointer_traits tests through C++14.
---
.../memory/pointer.traits/types.pass.cpp | 22 ++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
index 52844aa0ffa0ec7..237c673d88461cb 100644
--- a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
@@ -31,36 +31,42 @@
#include "test_macros.h"
+template <typename... Ts>
+struct VoidifyImpl { using type = void; };
+
+template <typename... Ts>
+using Voidify = typename VoidifyImpl<Ts...>::type;
+
template <class T, class = void>
struct HasElementType : std::false_type {};
template <class T>
-struct HasElementType<T, std::void_t<typename std::pointer_traits<T>::element_type>> : std::true_type {};
+struct HasElementType<T, Voidify<typename std::pointer_traits<T>::element_type>> : std::true_type {};
template <class T, class = void>
struct HasPointerType : std::false_type {};
template <class T>
-struct HasPointerType<T, std::void_t<typename std::pointer_traits<T>::pointer>> : std::true_type {};
+struct HasPointerType<T, Voidify<typename std::pointer_traits<T>::pointer>> : std::true_type {};
template <class T, class = void>
struct HasDifferenceType : std::false_type {};
template <class T>
-struct HasDifferenceType<T, std::void_t<typename std::pointer_traits<T>::difference_type>> : std::true_type {};
+struct HasDifferenceType<T, Voidify<typename std::pointer_traits<T>::difference_type>> : std::true_type {};
template <class T, class U, class = void>
struct HasRebind : std::false_type {};
template <class T, class U>
-struct HasRebind<T, U, std::void_t<typename std::pointer_traits<T>::template rebind<U>>> : std::true_type {};
+struct HasRebind<T, U, Voidify<typename std::pointer_traits<T>::template rebind<U>>> : std::true_type {};
template <class T, class = void>
struct HasPointerTo : std::false_type {};
template <class T>
struct HasPointerTo<T,
- std::void_t<decltype(std::pointer_traits<T>::pointer_to(
+ Voidify<decltype(std::pointer_traits<T>::pointer_to(
std::declval<std::add_lvalue_reference_t<typename std::pointer_traits<T>::element_type>>()))>>
: std::true_type {};
@@ -86,7 +92,7 @@ struct PtrWithElementType {
template <class T, class Arg>
struct TemplatedPtr {
- template <typename U, typename = std::enable_if_t<std::is_same_v<long, U>>>
+ template <typename U, typename = typename std::enable_if<std::is_same<long, U>::value>::type>
using rebind = LongPtr;
static constexpr auto pointer_to(T&) { return TemplatedPtr{&global_int}; }
@@ -96,7 +102,7 @@ struct TemplatedPtr {
template <class T, class Arg>
struct TemplatedPtrWithElementType {
using element_type = int;
- template <typename U, typename = std::enable_if_t<std::is_same_v<long, U>>>
+ template <typename U, typename = typename std::enable_if<std::is_same<long, U>::value>::type>
using rebind = LongPtr;
static constexpr auto pointer_to(element_type&) { return TemplatedPtrWithElementType{&global_int}; }
@@ -256,7 +262,7 @@ constexpr bool test() {
int main(int, char**) {
test();
-#if TEST_STD_VER >= 11
+#if TEST_STD_VER >= 14
static_assert(test(), "");
#endif
return 0;
>From 3226bdcc48e7f4988ac39f305afefc724af9db58 Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Tue, 12 Sep 2023 16:36:49 -0700
Subject: [PATCH 5/9] Support pointer_traits tests through C++11.
---
.../utilities/memory/pointer.traits/types.pass.cpp | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
index 237c673d88461cb..2cc0aff8f867770 100644
--- a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
@@ -67,7 +67,7 @@ struct HasPointerTo : std::false_type {};
template <class T>
struct HasPointerTo<T,
Voidify<decltype(std::pointer_traits<T>::pointer_to(
- std::declval<std::add_lvalue_reference_t<typename std::pointer_traits<T>::element_type>>()))>>
+ std::declval<typename std::add_lvalue_reference<typename std::pointer_traits<T>::element_type>::type>()))>>
: std::true_type {};
struct Irrelevant;
@@ -85,7 +85,7 @@ struct PtrWithElementType {
using element_type = int;
template <typename U>
using rebind = TemplatedPtr<U, Irrelevant>;
- static constexpr auto pointer_to(element_type&) { return PtrWithElementType{&global_int}; }
+ static constexpr PtrWithElementType pointer_to(element_type&) { return PtrWithElementType{&global_int}; }
int* ptr;
};
@@ -94,7 +94,7 @@ template <class T, class Arg>
struct TemplatedPtr {
template <typename U, typename = typename std::enable_if<std::is_same<long, U>::value>::type>
using rebind = LongPtr;
- static constexpr auto pointer_to(T&) { return TemplatedPtr{&global_int}; }
+ static constexpr TemplatedPtr pointer_to(T&) { return TemplatedPtr{&global_int}; }
T* ptr;
};
@@ -104,12 +104,15 @@ struct TemplatedPtrWithElementType {
using element_type = int;
template <typename U, typename = typename std::enable_if<std::is_same<long, U>::value>::type>
using rebind = LongPtr;
- static constexpr auto pointer_to(element_type&) { return TemplatedPtrWithElementType{&global_int}; }
+ static constexpr TemplatedPtrWithElementType pointer_to(element_type&) { return TemplatedPtrWithElementType{&global_int}; }
element_type* ptr;
};
-constexpr bool test() {
+#if TEST_STD_VER >= 14
+constexpr
+#endif
+bool test() {
{
using Ptr = NotAPtr;
assert(!HasElementType<Ptr>::value);
>From a72c5ff22a743ac982f4fadfc2bd5a08f009aab6 Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Tue, 12 Sep 2023 16:39:49 -0700
Subject: [PATCH 6/9] Remove unneeded test.
---
.../pointer.conversion/to_address.verify.cpp | 23 -------------------
1 file changed, 23 deletions(-)
delete mode 100644 libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp
diff --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp
deleted file mode 100644
index 8eddbe4c137190e..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.conversion/to_address.verify.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
-// Mandates: one of pointer_traits<Ptr>::to_address() or Ptr::operator->()
-// is present.
-
-#include <memory>
-
-struct NotPtr {};
-
-void test() {
- (void)std::to_address(NotPtr()); // expected-error@*:* {{no matching function for call to 'to_address'}}
-}
>From 81a6bdd8e130990aab4b299b302c41ec720995d7 Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Tue, 12 Sep 2023 16:41:39 -0700
Subject: [PATCH 7/9] Clarify comment about SFINAE testing of pointer_traits
members.
---
libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
index 2cc0aff8f867770..f33f2cb3cea563c 100644
--- a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
@@ -191,7 +191,8 @@ bool test() {
assert(HasDifferenceType<Ptr>::value);
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
- // TODO: Consider supporting SFINAE testing of std::pointer_traits<Ptr>.
+ // TODO: Maybe support SFINAE testing of std::pointer_traits<Ptr>::rebind
+ // and std::pointer_traits<Ptr>::pointer_to.
assert((HasRebind<Ptr, long>::value));
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, TemplatedPtr<long, Irrelevant>);
>From ab7364eba6656ebdcac3f061feff35922d002d7d Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Wed, 13 Sep 2023 08:03:08 -0700
Subject: [PATCH 8/9] Support C++03 in this test as well.
The standard doesn't define pointer_traits until C++11, but there are
some existing tests that seem to test in C++03 mode... so try to
preserve that behavior in the updated tests.
---
.../memory/pointer.traits/types.pass.cpp | 88 +++++++++++++++----
1 file changed, 70 insertions(+), 18 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
index f33f2cb3cea563c..aad14c2a0f4855f 100644
--- a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
@@ -32,7 +32,9 @@
#include "test_macros.h"
template <typename... Ts>
-struct VoidifyImpl { using type = void; };
+struct VoidifyImpl {
+ using type = void;
+};
template <typename... Ts>
using Voidify = typename VoidifyImpl<Ts...>::type;
@@ -41,60 +43,79 @@ template <class T, class = void>
struct HasElementType : std::false_type {};
template <class T>
-struct HasElementType<T, Voidify<typename std::pointer_traits<T>::element_type>> : std::true_type {};
+struct HasElementType<T, Voidify<typename std::pointer_traits<T>::element_type> > : std::true_type {};
template <class T, class = void>
struct HasPointerType : std::false_type {};
template <class T>
-struct HasPointerType<T, Voidify<typename std::pointer_traits<T>::pointer>> : std::true_type {};
+struct HasPointerType<T, Voidify<typename std::pointer_traits<T>::pointer> > : std::true_type {};
template <class T, class = void>
struct HasDifferenceType : std::false_type {};
template <class T>
-struct HasDifferenceType<T, Voidify<typename std::pointer_traits<T>::difference_type>> : std::true_type {};
+struct HasDifferenceType<T, Voidify<typename std::pointer_traits<T>::difference_type> > : std::true_type {};
template <class T, class U, class = void>
struct HasRebind : std::false_type {};
template <class T, class U>
-struct HasRebind<T, U, Voidify<typename std::pointer_traits<T>::template rebind<U>>> : std::true_type {};
+struct HasRebind<T, U, Voidify<typename std::pointer_traits<T>::template rebind<U> > > : std::true_type {};
template <class T, class = void>
struct HasPointerTo : std::false_type {};
template <class T>
-struct HasPointerTo<T,
- Voidify<decltype(std::pointer_traits<T>::pointer_to(
- std::declval<typename std::add_lvalue_reference<typename std::pointer_traits<T>::element_type>::type>()))>>
+struct HasPointerTo<
+ T,
+ Voidify<decltype(std::pointer_traits<T>::pointer_to(
+ std::declval<typename std::add_lvalue_reference<typename std::pointer_traits<T>::element_type>::type>()))> >
: std::true_type {};
struct Irrelevant;
struct NotAPtr {};
-struct LongPtr;
+struct LongPtr {};
int global_int;
template <class T, class Arg>
struct TemplatedPtr;
+#if TEST_STD_VER >= 11
+# define CONSTEXPR_IF_SUPPORTED constexpr
+#else
+# define CONSTEXPR_IF_SUPPORTED
+#endif
+
struct PtrWithElementType {
using element_type = int;
- template <typename U>
+ template <class U>
+#if TEST_STD_VER >= 11
using rebind = TemplatedPtr<U, Irrelevant>;
- static constexpr PtrWithElementType pointer_to(element_type&) { return PtrWithElementType{&global_int}; }
+#else
+ struct rebind {
+ using other = TemplatedPtr<U, Irrelevant>;
+ };
+#endif
+ static CONSTEXPR_IF_SUPPORTED PtrWithElementType pointer_to(element_type&) { return {&global_int}; }
int* ptr;
};
template <class T, class Arg>
struct TemplatedPtr {
- template <typename U, typename = typename std::enable_if<std::is_same<long, U>::value>::type>
+ template <class U, class = typename std::enable_if<std::is_same<long, U>::value>::type>
+#if TEST_STD_VER >= 11
using rebind = LongPtr;
- static constexpr TemplatedPtr pointer_to(T&) { return TemplatedPtr{&global_int}; }
+#else
+ struct rebind {
+ using other = LongPtr;
+ };
+#endif
+ static CONSTEXPR_IF_SUPPORTED TemplatedPtr pointer_to(T&) { return {&global_int}; }
T* ptr;
};
@@ -102,9 +123,16 @@ struct TemplatedPtr {
template <class T, class Arg>
struct TemplatedPtrWithElementType {
using element_type = int;
- template <typename U, typename = typename std::enable_if<std::is_same<long, U>::value>::type>
+#if TEST_STD_VER >= 11
+ template <class U, class = typename std::enable_if<std::is_same<long, U>::value>::type>
using rebind = LongPtr;
- static constexpr TemplatedPtrWithElementType pointer_to(element_type&) { return TemplatedPtrWithElementType{&global_int}; }
+#else
+ template <class U, class = typename std::enable_if<std::is_same<long, U>::value>::type>
+ struct rebind {
+ using other = LongPtr;
+ };
+#endif
+ static CONSTEXPR_IF_SUPPORTED TemplatedPtrWithElementType pointer_to(element_type&) { return {&global_int}; }
element_type* ptr;
};
@@ -112,7 +140,8 @@ struct TemplatedPtrWithElementType {
#if TEST_STD_VER >= 14
constexpr
#endif
-bool test() {
+ bool
+ test() {
{
using Ptr = NotAPtr;
assert(!HasElementType<Ptr>::value);
@@ -135,7 +164,11 @@ bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
assert((HasRebind<Ptr, long>::value));
+#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
+#else
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, long*);
+#endif
assert(HasPointerTo<Ptr>::value);
int variable = 0;
@@ -160,7 +193,11 @@ bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
assert((HasRebind<Ptr, long>::value));
+#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
+#else
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, long*);
+#endif
assert(HasPointerTo<Ptr>::value);
const int const_variable = 0;
@@ -194,7 +231,11 @@ bool test() {
// TODO: Maybe support SFINAE testing of std::pointer_traits<Ptr>::rebind
// and std::pointer_traits<Ptr>::pointer_to.
assert((HasRebind<Ptr, long>::value));
+#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, TemplatedPtr<long, Irrelevant>);
+#else
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, TemplatedPtr<long, Irrelevant>);
+#endif
assert(HasPointerTo<Ptr>::value);
int ignored = 0;
@@ -219,9 +260,14 @@ bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
assert((HasRebind<Ptr, long>::value));
- ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
assert((HasRebind<Ptr, long long>::value));
+#if TEST_STD_VER >= 11
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtr<long long, Irrelevant>);
+#else
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, LongPtr);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>::other, TemplatedPtr<long long, Irrelevant>);
+#endif
assert(HasPointerTo<Ptr>::value);
int ignored = 0;
@@ -246,10 +292,16 @@ bool test() {
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
assert((HasRebind<Ptr, long>::value));
- ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
assert((HasRebind<Ptr, long long>::value));
+#if TEST_STD_VER >= 11
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
ASSERT_SAME_TYPE(
typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtrWithElementType<long long, Irrelevant>);
+#else
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, LongPtr);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>::other,
+ TemplatedPtrWithElementType<long long, Irrelevant>);
+#endif
assert(HasPointerTo<Ptr>::value);
int ignored = 0;
>From a5d34970850862e075c256b566b0dd578e570f43 Mon Sep 17 00:00:00 2001
From: Daniel Cheng <zetafunction at gmail.com>
Date: Thu, 14 Sep 2023 17:35:09 -0700
Subject: [PATCH 9/9] Convert everything to use static_assert.
---
...{types.pass.cpp => types.compile.pass.cpp} | 132 +++++++-----------
1 file changed, 48 insertions(+), 84 deletions(-)
rename libcxx/test/std/utilities/memory/pointer.traits/{types.pass.cpp => types.compile.pass.cpp} (68%)
diff --git a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp
similarity index 68%
rename from libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
rename to libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp
index aad14c2a0f4855f..19461508ca0f328 100644
--- a/libcxx/test/std/utilities/memory/pointer.traits/types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp
@@ -26,7 +26,6 @@
// };
#include <memory>
-#include <cassert>
#include <type_traits>
#include "test_macros.h"
@@ -84,12 +83,6 @@ int global_int;
template <class T, class Arg>
struct TemplatedPtr;
-#if TEST_STD_VER >= 11
-# define CONSTEXPR_IF_SUPPORTED constexpr
-#else
-# define CONSTEXPR_IF_SUPPORTED
-#endif
-
struct PtrWithElementType {
using element_type = int;
template <class U>
@@ -100,8 +93,7 @@ struct PtrWithElementType {
using other = TemplatedPtr<U, Irrelevant>;
};
#endif
- static CONSTEXPR_IF_SUPPORTED PtrWithElementType pointer_to(element_type&) { return {&global_int}; }
-
+ static TEST_CONSTEXPR_CXX14 PtrWithElementType pointer_to(element_type&) { return {&global_int}; }
int* ptr;
};
@@ -115,7 +107,7 @@ struct TemplatedPtr {
using other = LongPtr;
};
#endif
- static CONSTEXPR_IF_SUPPORTED TemplatedPtr pointer_to(T&) { return {&global_int}; }
+ static TEST_CONSTEXPR_CXX14 TemplatedPtr pointer_to(T&) { return {&global_int}; }
T* ptr;
};
@@ -132,135 +124,121 @@ struct TemplatedPtrWithElementType {
using other = LongPtr;
};
#endif
- static CONSTEXPR_IF_SUPPORTED TemplatedPtrWithElementType pointer_to(element_type&) { return {&global_int}; }
+ static TEST_CONSTEXPR_CXX14 TemplatedPtrWithElementType pointer_to(element_type&) { return {&global_int}; }
element_type* ptr;
};
-#if TEST_STD_VER >= 14
-constexpr
-#endif
- bool
- test() {
+int main() {
{
using Ptr = NotAPtr;
- assert(!HasElementType<Ptr>::value);
- assert(!HasPointerType<Ptr>::value);
- assert(!HasDifferenceType<Ptr>::value);
- assert((!HasRebind<Ptr, long>::value));
- assert(!HasPointerTo<Ptr>::value);
+ static_assert(!HasElementType<Ptr>::value, "");
+ static_assert(!HasPointerType<Ptr>::value, "");
+ static_assert(!HasDifferenceType<Ptr>::value, "");
+ static_assert(!HasRebind<Ptr, long>::value, "");
+ static_assert(!HasPointerTo<Ptr>::value, "");
}
{
using Ptr = int*;
- assert(HasElementType<Ptr>::value);
+ static_assert(HasElementType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
- assert(HasPointerType<Ptr>::value);
+ static_assert(HasPointerType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
- assert(HasDifferenceType<Ptr>::value);
+ static_assert(HasDifferenceType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
- assert((HasRebind<Ptr, long>::value));
+ static_assert(HasRebind<Ptr, long>::value, "");
#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
#else
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, long*);
#endif
- assert(HasPointerTo<Ptr>::value);
+ static_assert(HasPointerTo<Ptr>::value, "");
int variable = 0;
ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), Ptr);
-#if TEST_STD_VER >= 17
- if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
- assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
- }
+#if TEST_STD_VER >= 20
+ static_assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable, "");
#endif
}
{
using Ptr = const int*;
- assert(HasElementType<Ptr>::value);
+ static_assert(HasElementType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, const int);
- assert(HasPointerType<Ptr>::value);
+ static_assert(HasPointerType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
- assert(HasDifferenceType<Ptr>::value);
+ static_assert(HasDifferenceType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
- assert((HasRebind<Ptr, long>::value));
+ static_assert(HasRebind<Ptr, long>::value, "");
#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
#else
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, long*);
#endif
- assert(HasPointerTo<Ptr>::value);
+ static_assert(HasPointerTo<Ptr>::value, "");
const int const_variable = 0;
ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(const_variable)), Ptr);
-#if TEST_STD_VER >= 17
- if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
- assert(std::pointer_traits<Ptr>::pointer_to(const_variable) == &const_variable);
- }
+#if TEST_STD_VER >= 20
+ static_assert(std::pointer_traits<Ptr>::pointer_to(const_variable) == &const_variable, "");
#endif
int variable = 0;
ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), Ptr);
-#if TEST_STD_VER >= 17
- if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
- assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable);
- }
+#if TEST_STD_VER >= 20
+ static_assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable, "");
#endif
}
{
using Ptr = PtrWithElementType;
- assert(HasElementType<Ptr>::value);
+ static_assert(HasElementType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
- assert(HasPointerType<Ptr>::value);
+ static_assert(HasPointerType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
- assert(HasDifferenceType<Ptr>::value);
+ static_assert(HasDifferenceType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
- // TODO: Maybe support SFINAE testing of std::pointer_traits<Ptr>::rebind
- // and std::pointer_traits<Ptr>::pointer_to.
- assert((HasRebind<Ptr, long>::value));
+ static_assert(HasRebind<Ptr, long>::value, "");
#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, TemplatedPtr<long, Irrelevant>);
#else
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, TemplatedPtr<long, Irrelevant>);
#endif
- assert(HasPointerTo<Ptr>::value);
+ static_assert(HasPointerTo<Ptr>::value, "");
int ignored = 0;
ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
-#if TEST_STD_VER >= 17
- if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
- assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
- }
+#if TEST_STD_VER >= 20
+ static_assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int, "");
#endif
}
{
using Ptr = TemplatedPtr<int, Irrelevant>;
- assert(HasElementType<Ptr>::value);
+ static_assert(HasElementType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
- assert(HasPointerType<Ptr>::value);
+ static_assert(HasPointerType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
- assert(HasDifferenceType<Ptr>::value);
+ static_assert(HasDifferenceType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
- assert((HasRebind<Ptr, long>::value));
- assert((HasRebind<Ptr, long long>::value));
+ static_assert(HasRebind<Ptr, long>::value, "");
+ static_assert(HasRebind<Ptr, long long>::value, "");
#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtr<long long, Irrelevant>);
@@ -269,30 +247,28 @@ constexpr
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>::other, TemplatedPtr<long long, Irrelevant>);
#endif
- assert(HasPointerTo<Ptr>::value);
+ static_assert(HasPointerTo<Ptr>::value, "");
int ignored = 0;
ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
-#if TEST_STD_VER >= 17
- if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
- assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
- }
+#if TEST_STD_VER >= 20
+ static_assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int, "");
#endif
}
{
using Ptr = TemplatedPtrWithElementType<Irrelevant, Irrelevant>;
- assert(HasElementType<Ptr>::value);
+ static_assert(HasElementType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
- assert(HasPointerType<Ptr>::value);
+ static_assert(HasPointerType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
- assert(HasDifferenceType<Ptr>::value);
+ static_assert(HasDifferenceType<Ptr>::value, "");
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
- assert((HasRebind<Ptr, long>::value));
- assert((HasRebind<Ptr, long long>::value));
+ static_assert(HasRebind<Ptr, long>::value, "");
+ static_assert(HasRebind<Ptr, long long>::value, "");
#if TEST_STD_VER >= 11
ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
ASSERT_SAME_TYPE(
@@ -303,23 +279,11 @@ constexpr
TemplatedPtrWithElementType<long long, Irrelevant>);
#endif
- assert(HasPointerTo<Ptr>::value);
+ static_assert(HasPointerTo<Ptr>::value, "");
int ignored = 0;
ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
-#if TEST_STD_VER >= 17
- if constexpr (std::__libcpp_is_constant_evaluated() && TEST_STD_VER >= 20) {
- assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int);
- }
+#if TEST_STD_VER >= 20
+ static_assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int, "");
#endif
}
-
- return true;
-}
-
-int main(int, char**) {
- test();
-#if TEST_STD_VER >= 14
- static_assert(test(), "");
-#endif
- return 0;
}
More information about the libcxx-commits
mailing list