From 066f9ea27960c21b73be820f2bcd62d0c2f3d6b8 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 14 May 2019 12:17:23 +0100 Subject: [PATCH] Add __gnu_test::NullablePointer utility to testsuite * testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc: Use operator-> to access raw pointer member. * testsuite/23_containers/vector/59829.cc: Likewise. * testsuite/23_containers/vector/bool/80893.cc: Likewise. * testsuite/libstdc++-prettyprinters/cxx11.cc: Use NullablePointer. * testsuite/util/testsuite_allocator.h (NullablePointer): New utility for tests. (PointerBase, PointerBase_void): Derive from NullablePointer and use its constructors and equality operators. Change converting constructors to use operator-> to access private member of the other pointer type. (PointerBase_void::operator->()): Add, for access to private member. (operator-(PointerBase, PointerBase)): Change to hidden friend. (operator==(PointerBase, PointerBase)): Remove. (operator!=(PointerBase, PointerBase)): Remove. From-SVN: r271160 --- libstdc++-v3/ChangeLog | 16 +++ .../members/allocate_hint_nonpod.cc | 2 +- .../testsuite/23_containers/vector/59829.cc | 2 +- .../23_containers/vector/bool/80893.cc | 2 +- .../libstdc++-prettyprinters/cxx11.cc | 25 ++-- .../testsuite/util/testsuite_allocator.h | 120 ++++++++++++------ 6 files changed, 111 insertions(+), 56 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b6061f406cb..6578a337b9e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,21 @@ 2019-05-14 Jonathan Wakely + * testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc: + Use operator-> to access raw pointer member. + * testsuite/23_containers/vector/59829.cc: Likewise. + * testsuite/23_containers/vector/bool/80893.cc: Likewise. + * testsuite/libstdc++-prettyprinters/cxx11.cc: Use NullablePointer. + * testsuite/util/testsuite_allocator.h (NullablePointer): New utility + for tests. + (PointerBase, PointerBase_void): Derive from NullablePointer and use + its constructors and equality operators. Change converting + constructors to use operator-> to access private member of the other + pointer type. + (PointerBase_void::operator->()): Add, for access to private member. + (operator-(PointerBase, PointerBase)): Change to hidden friend. + (operator==(PointerBase, PointerBase)): Remove. + (operator!=(PointerBase, PointerBase)): Remove. + * python/libstdcxx/v6/printers.py (UniquePointerPrinter.__init__): Do not assume field called _M_head_impl is the first tuple element. * testsuite/libstdc++-prettyprinters/compat.cc: Make tuple diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc index a5e2a269a15..f9193e83e94 100644 --- a/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc +++ b/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc @@ -45,7 +45,7 @@ struct Alloc { return pointer(std::allocator().allocate(n)); } void deallocate(pointer p, std::size_t n) - { std::allocator().deallocate(p.value, n); } + { std::allocator().deallocate(p.operator->(), n); } }; template diff --git a/libstdc++-v3/testsuite/23_containers/vector/59829.cc b/libstdc++-v3/testsuite/23_containers/vector/59829.cc index 0e053fa6627..892b9055eb4 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/59829.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/59829.cc @@ -51,7 +51,7 @@ struct Alloc { return pointer(std::allocator().allocate(n)); } void deallocate(pointer p, std::size_t n) - { std::allocator().deallocate(p.value, n); } + { std::allocator().deallocate(p.operator->(), n); } }; template diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc index f44cdc4a75e..08b15c8d2da 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc @@ -59,7 +59,7 @@ struct Alloc void deallocate(pointer p, std::size_t n) { if (n) - std::allocator().deallocate(p.value, n); + std::allocator().deallocate(p.operator->(), n); } }; diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc index cc588125bdc..c87c8035c45 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc @@ -24,6 +24,7 @@ #include #include #include +#include "../util/testsuite_allocator.h" // NullablePointer typedef std::tuple ExTuple; @@ -59,21 +60,6 @@ struct datum std::unique_ptr global; -struct Deleter -{ - // Deleter is not an empty class: - int deleter_member = -1; - // But pointer is an empty class: - struct pointer - { - pointer(const void* = nullptr) { } - explicit operator bool() const noexcept { return false; } - friend bool operator==(pointer, pointer) noexcept { return true; } - friend bool operator!=(pointer, pointer) noexcept { return false; } - }; - void operator()(pointer) const noexcept { } -}; - int main() { @@ -151,6 +137,15 @@ main() std::unique_ptr& rarrptr = arrptr; // { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } } + struct Deleter + { + int deleter_member = -1; + using pointer = __gnu_test::NullablePointer; + void operator()(pointer) const noexcept { } + }; + static_assert( !std::is_empty(), "Deleter is not empty" ); + static_assert( std::is_empty(), "but pointer is empty" ); + std::unique_ptr empty_ptr; // { dg-final { note-test empty_ptr {std::unique_ptr = {get() = {}}} } } std::unique_ptr& rempty_ptr = empty_ptr; diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 0392421ca04..428c0823395 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -589,9 +589,54 @@ namespace __gnu_test { std::allocator::deallocate(std::addressof(*p), n); } }; + // A class type meeting *only* the Cpp17NullablePointer requirements. + // Can be used as a base class for fancy pointers (like PointerBase, below) + // or to wrap a built-in pointer type to remove operations not required + // by the Cpp17NullablePointer requirements (dereference, increment etc.) + template + struct NullablePointer + { + // N.B. default constructor does not initialize value + NullablePointer() = default; + NullablePointer(std::nullptr_t) noexcept : value() { } + + explicit operator bool() const noexcept { return value == nullptr; } + + friend inline bool + operator==(NullablePointer lhs, NullablePointer rhs) noexcept + { return lhs.value == rhs.value; } + + friend inline bool + operator!=(NullablePointer lhs, NullablePointer rhs) noexcept + { return lhs.value != rhs.value; } + + protected: + explicit NullablePointer(Ptr p) noexcept : value(p) { } + Ptr value; + }; + + // NullablePointer is an empty type that models Cpp17NullablePointer. + template<> + struct NullablePointer + { + NullablePointer() = default; + NullablePointer(std::nullptr_t) noexcept { } + explicit NullablePointer(const volatile void*) noexcept { } + + explicit operator bool() const noexcept { return false; } + + friend inline bool + operator==(NullablePointer, NullablePointer) noexcept + { return true; } + + friend inline bool + operator!=(NullablePointer, NullablePointer) noexcept + { return false; } + }; + // Utility for use as CRTP base class of custom pointer types template - struct PointerBase + struct PointerBase : NullablePointer { typedef T element_type; @@ -602,29 +647,38 @@ namespace __gnu_test typedef Derived pointer; typedef T& reference; - T* value; + using NullablePointer::NullablePointer; - explicit PointerBase(T* p = nullptr) : value(p) { } - - PointerBase(std::nullptr_t) : value(nullptr) { } + // Public (but explicit) constructor from raw pointer: + explicit PointerBase(T* p) noexcept : NullablePointer(p) { } template(std::declval()))> - PointerBase(const PointerBase& p) : value(p.value) { } + PointerBase(const PointerBase& p) + : NullablePointer(p.operator->()) { } + + T& operator*() const { return *this->value; } + T* operator->() const { return this->value; } + T& operator[](difference_type n) const { return this->value[n]; } - T& operator*() const { return *value; } - T* operator->() const { return value; } - T& operator[](difference_type n) const { return value[n]; } + Derived& operator++() { ++this->value; return derived(); } + Derived& operator--() { --this->value; return derived(); } - Derived& operator++() { ++value; return derived(); } - Derived operator++(int) { Derived tmp(derived()); ++value; return tmp; } - Derived& operator--() { --value; return derived(); } - Derived operator--(int) { Derived tmp(derived()); --value; return tmp; } + Derived operator++(int) { return Derived(this->value++); } - Derived& operator+=(difference_type n) { value += n; return derived(); } - Derived& operator-=(difference_type n) { value -= n; return derived(); } + Derived operator--(int) { return Derived(this->value--); } - explicit operator bool() const { return value != nullptr; } + Derived& operator+=(difference_type n) + { + this->value += n; + return derived(); + } + + Derived& operator-=(difference_type n) + { + this->value -= n; + return derived(); + } Derived operator+(difference_type n) const @@ -641,6 +695,9 @@ namespace __gnu_test } private: + friend std::ptrdiff_t operator-(PointerBase l, PointerBase r) + { return l.value - r.value; } + Derived& derived() { return static_cast(*this); } @@ -648,21 +705,9 @@ namespace __gnu_test derived() const { return static_cast(*this); } }; - template - std::ptrdiff_t operator-(PointerBase l, PointerBase r) - { return l.value - r.value; } - - template - bool operator==(PointerBase l, PointerBase r) - { return l.value == r.value; } - - template - bool operator!=(PointerBase l, PointerBase r) - { return l.value != r.value; } - - // implementation for void specializations - template - struct PointerBase_void + // implementation for pointer-to-void specializations + template + struct PointerBase_void : NullablePointer { typedef T element_type; @@ -671,25 +716,24 @@ namespace __gnu_test typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; - T* value; + using NullablePointer::NullablePointer; - explicit PointerBase_void(T* p = nullptr) : value(p) { } + T* operator->() const { return this->value; } template(std::declval()))> - PointerBase_void(const PointerBase& p) : value(p.value) { } - - explicit operator bool() const { return value != nullptr; } + PointerBase_void(const PointerBase& p) + : NullablePointer(p.operator->()) { } }; - template + template struct PointerBase : PointerBase_void { using PointerBase_void::PointerBase_void; typedef Derived pointer; }; - template + template struct PointerBase : PointerBase_void { using PointerBase_void::PointerBase_void; -- 2.30.2