Commit 066f9ea2 by Jonathan Wakely Committed by Jonathan Wakely

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
parent e25f488d
2019-05-14 Jonathan Wakely <jwakely@redhat.com> 2019-05-14 Jonathan Wakely <jwakely@redhat.com>
* 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 * python/libstdcxx/v6/printers.py (UniquePointerPrinter.__init__): Do
not assume field called _M_head_impl is the first tuple element. not assume field called _M_head_impl is the first tuple element.
* testsuite/libstdc++-prettyprinters/compat.cc: Make tuple * testsuite/libstdc++-prettyprinters/compat.cc: Make tuple
......
...@@ -45,7 +45,7 @@ struct Alloc ...@@ -45,7 +45,7 @@ struct Alloc
{ return pointer(std::allocator<T>().allocate(n)); } { return pointer(std::allocator<T>().allocate(n)); }
void deallocate(pointer p, std::size_t n) void deallocate(pointer p, std::size_t n)
{ std::allocator<T>().deallocate(p.value, n); } { std::allocator<T>().deallocate(p.operator->(), n); }
}; };
template<typename T> template<typename T>
......
...@@ -51,7 +51,7 @@ struct Alloc ...@@ -51,7 +51,7 @@ struct Alloc
{ return pointer(std::allocator<T>().allocate(n)); } { return pointer(std::allocator<T>().allocate(n)); }
void deallocate(pointer p, std::size_t n) void deallocate(pointer p, std::size_t n)
{ std::allocator<T>().deallocate(p.value, n); } { std::allocator<T>().deallocate(p.operator->(), n); }
}; };
template<typename T> template<typename T>
......
...@@ -59,7 +59,7 @@ struct Alloc ...@@ -59,7 +59,7 @@ struct Alloc
void deallocate(pointer p, std::size_t n) void deallocate(pointer p, std::size_t n)
{ {
if (n) if (n)
std::allocator<T>().deallocate(p.value, n); std::allocator<T>().deallocate(p.operator->(), n);
} }
}; };
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <iostream> #include <iostream>
#include "../util/testsuite_allocator.h" // NullablePointer
typedef std::tuple<int, int> ExTuple; typedef std::tuple<int, int> ExTuple;
...@@ -59,21 +60,6 @@ struct datum ...@@ -59,21 +60,6 @@ struct datum
std::unique_ptr<datum> global; std::unique_ptr<datum> 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 int
main() main()
{ {
...@@ -151,6 +137,15 @@ main() ...@@ -151,6 +137,15 @@ main()
std::unique_ptr<data>& rarrptr = arrptr; std::unique_ptr<data>& rarrptr = arrptr;
// { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } } // { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } }
struct Deleter
{
int deleter_member = -1;
using pointer = __gnu_test::NullablePointer<void>;
void operator()(pointer) const noexcept { }
};
static_assert( !std::is_empty<Deleter>(), "Deleter is not empty" );
static_assert( std::is_empty<Deleter::pointer>(), "but pointer is empty" );
std::unique_ptr<int, Deleter> empty_ptr; std::unique_ptr<int, Deleter> empty_ptr;
// { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } } // { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr; std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr;
......
...@@ -589,9 +589,54 @@ namespace __gnu_test ...@@ -589,9 +589,54 @@ namespace __gnu_test
{ std::allocator<Tp>::deallocate(std::addressof(*p), n); } { std::allocator<Tp>::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<typename Ptr>
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<void> is an empty type that models Cpp17NullablePointer.
template<>
struct NullablePointer<void>
{
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 // Utility for use as CRTP base class of custom pointer types
template<typename Derived, typename T> template<typename Derived, typename T>
struct PointerBase struct PointerBase : NullablePointer<T*>
{ {
typedef T element_type; typedef T element_type;
...@@ -602,29 +647,38 @@ namespace __gnu_test ...@@ -602,29 +647,38 @@ namespace __gnu_test
typedef Derived pointer; typedef Derived pointer;
typedef T& reference; typedef T& reference;
T* value; using NullablePointer<T*>::NullablePointer;
explicit PointerBase(T* p = nullptr) : value(p) { } // Public (but explicit) constructor from raw pointer:
explicit PointerBase(T* p) noexcept : NullablePointer<T*>(p) { }
PointerBase(std::nullptr_t) : value(nullptr) { }
template<typename D, typename U, template<typename D, typename U,
typename = decltype(static_cast<T*>(std::declval<U*>()))> typename = decltype(static_cast<T*>(std::declval<U*>()))>
PointerBase(const PointerBase<D, U>& p) : value(p.value) { } PointerBase(const PointerBase<D, U>& p)
: NullablePointer<T*>(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; } Derived& operator++() { ++this->value; return derived(); }
T* operator->() const { return value; } Derived& operator--() { --this->value; return derived(); }
T& operator[](difference_type n) const { return value[n]; }
Derived& operator++() { ++value; return derived(); } Derived operator++(int) { return Derived(this->value++); }
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+=(difference_type n) { value += n; return derived(); } Derived operator--(int) { return Derived(this->value--); }
Derived& operator-=(difference_type n) { value -= n; return derived(); }
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 Derived
operator+(difference_type n) const operator+(difference_type n) const
...@@ -641,6 +695,9 @@ namespace __gnu_test ...@@ -641,6 +695,9 @@ namespace __gnu_test
} }
private: private:
friend std::ptrdiff_t operator-(PointerBase l, PointerBase r)
{ return l.value - r.value; }
Derived& Derived&
derived() { return static_cast<Derived&>(*this); } derived() { return static_cast<Derived&>(*this); }
...@@ -648,21 +705,9 @@ namespace __gnu_test ...@@ -648,21 +705,9 @@ namespace __gnu_test
derived() const { return static_cast<const Derived&>(*this); } derived() const { return static_cast<const Derived&>(*this); }
}; };
template<typename D, typename T> // implementation for pointer-to-void specializations
std::ptrdiff_t operator-(PointerBase<D, T> l, PointerBase<D, T> r) template<typename T>
{ return l.value - r.value; } struct PointerBase_void : NullablePointer<T*>
template<typename D, typename T>
bool operator==(PointerBase<D, T> l, PointerBase<D, T> r)
{ return l.value == r.value; }
template<typename D, typename T>
bool operator!=(PointerBase<D, T> l, PointerBase<D, T> r)
{ return l.value != r.value; }
// implementation for void specializations
template<typename T>
struct PointerBase_void
{ {
typedef T element_type; typedef T element_type;
...@@ -671,25 +716,24 @@ namespace __gnu_test ...@@ -671,25 +716,24 @@ namespace __gnu_test
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
T* value; using NullablePointer<T*>::NullablePointer;
explicit PointerBase_void(T* p = nullptr) : value(p) { } T* operator->() const { return this->value; }
template<typename D, typename U, template<typename D, typename U,
typename = decltype(static_cast<T*>(std::declval<U*>()))> typename = decltype(static_cast<T*>(std::declval<U*>()))>
PointerBase_void(const PointerBase<D, U>& p) : value(p.value) { } PointerBase_void(const PointerBase<D, U>& p)
: NullablePointer<T*>(p.operator->()) { }
explicit operator bool() const { return value != nullptr; }
}; };
template<typename Derived> template<typename Derived>
struct PointerBase<Derived, void> : PointerBase_void<void> struct PointerBase<Derived, void> : PointerBase_void<void>
{ {
using PointerBase_void::PointerBase_void; using PointerBase_void::PointerBase_void;
typedef Derived pointer; typedef Derived pointer;
}; };
template<typename Derived> template<typename Derived>
struct PointerBase<Derived, const void> : PointerBase_void<const void> struct PointerBase<Derived, const void> : PointerBase_void<const void>
{ {
using PointerBase_void::PointerBase_void; using PointerBase_void::PointerBase_void;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment