Fix unique_ptr pretty printer for empty classes
The printer was confused when unique_ptr<T,D>::pointer is an empty class, or the deleter is not empty. Instead of assuming the tuple has a single _M_head_impl member manually inspect the tuple base classes to get the first element. * 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 implementation more accurate. * testsuite/libstdc++-prettyprinters/cxx11.cc: Check unique_ptr with empty pointer type and non-empty deleter. From-SVN: r271159
This commit is contained in:
parent
1b18663e0f
commit
e25f488d60
4 changed files with 57 additions and 5 deletions
|
@ -1,5 +1,12 @@
|
|||
2019-05-14 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* 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
|
||||
implementation more accurate.
|
||||
* testsuite/libstdc++-prettyprinters/cxx11.cc: Check unique_ptr with
|
||||
empty pointer type and non-empty deleter.
|
||||
|
||||
LWG 2899 - Make is_move_constructible correct for unique_ptr
|
||||
* include/bits/unique_ptr.h (__uniq_ptr_impl): Add move constructor,
|
||||
move assignment operator.
|
||||
|
|
|
@ -185,11 +185,18 @@ class UniquePointerPrinter:
|
|||
# Check for new implementations first:
|
||||
if is_specialization_of(impl_type, '__uniq_ptr_data') \
|
||||
or is_specialization_of(impl_type, '__uniq_ptr_impl'):
|
||||
self.pointer = val['_M_t']['_M_t']['_M_head_impl']
|
||||
tuple_member = val['_M_t']['_M_t']
|
||||
elif is_specialization_of(impl_type, 'tuple'):
|
||||
self.pointer = val['_M_t']['_M_head_impl']
|
||||
tuple_member = val['_M_t']
|
||||
else:
|
||||
raise ValueError("Unsupported implementation for unique_ptr: %s" % impl_type)
|
||||
tuple_impl_type = tuple_member.type.fields()[0].type # _Tuple_impl
|
||||
tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base
|
||||
head_field = tuple_head_type.fields()[0]
|
||||
if head_field.name == '_M_head_impl':
|
||||
self.pointer = tuple_member['_M_head_impl']
|
||||
elif head_field.is_base_class:
|
||||
self.pointer = tuple_member.cast(head_field.type)
|
||||
|
||||
def children (self):
|
||||
return SmartPtrIterator(self.pointer)
|
||||
|
|
|
@ -22,12 +22,30 @@
|
|||
|
||||
namespace std
|
||||
{
|
||||
template<typename T, typename U>
|
||||
struct tuple
|
||||
template<typename T>
|
||||
struct _Head_base : T
|
||||
{ };
|
||||
|
||||
template<typename T>
|
||||
struct _Head_base<T*>
|
||||
{
|
||||
T _M_head_impl;
|
||||
T* _M_head_impl;
|
||||
};
|
||||
|
||||
template<unsigned long, typename ...> struct _Tuple_impl;
|
||||
|
||||
template<typename T, typename U>
|
||||
struct _Tuple_impl<0, T, U> : _Tuple_impl<1, U>, _Head_base<T>
|
||||
{ };
|
||||
|
||||
template<typename U>
|
||||
struct _Tuple_impl<1, U> : _Head_base<U>
|
||||
{ };
|
||||
|
||||
template<typename T, typename U>
|
||||
struct tuple : _Tuple_impl<0, T, U>
|
||||
{ };
|
||||
|
||||
template<typename T> struct default_delete { };
|
||||
|
||||
template<typename T, typename D = default_delete<T>>
|
||||
|
|
|
@ -59,6 +59,21 @@ struct datum
|
|||
|
||||
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
|
||||
main()
|
||||
{
|
||||
|
@ -136,6 +151,11 @@ main()
|
|||
std::unique_ptr<data>& rarrptr = arrptr;
|
||||
// { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } }
|
||||
|
||||
std::unique_ptr<int, Deleter> empty_ptr;
|
||||
// { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr;
|
||||
// { dg-final { note-test rempty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
|
||||
|
||||
ExTuple tpl(6,7);
|
||||
// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }
|
||||
ExTuple &rtpl = tpl;
|
||||
|
|
Loading…
Add table
Reference in a new issue