diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-05-14 12:17:18 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-05-14 12:17:18 +0100 |
commit | e25f488d603a6bd7570c1ffdfd9572e4b8a645de (patch) | |
tree | ff1a79dec41d39f4ee7792d10c198606b8877d59 | |
parent | 1b18663e0fbd6e253feca9e1f29e6f5b5538408d (diff) | |
download | gcc-e25f488d603a6bd7570c1ffdfd9572e4b8a645de.zip gcc-e25f488d603a6bd7570c1ffdfd9572e4b8a645de.tar.gz gcc-e25f488d603a6bd7570c1ffdfd9572e4b8a645de.tar.bz2 |
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/python/libstdcxx/v6/printers.py | 11 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc | 24 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc | 20 |
4 files changed, 57 insertions, 5 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 440a1df..b6061f4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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. diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index eae06f9..162b007 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -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) diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc index 7bfc3c6..28b0c21 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc @@ -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>> diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc index 7d0a9a2..cc58812 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc @@ -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; |