aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-05-14 12:17:18 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-05-14 12:17:18 +0100
commite25f488d603a6bd7570c1ffdfd9572e4b8a645de (patch)
treeff1a79dec41d39f4ee7792d10c198606b8877d59
parent1b18663e0fbd6e253feca9e1f29e6f5b5538408d (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py11
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc24
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc20
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;