From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id 10EE43A77041; Fri, 23 Apr 2021 10:37:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 10EE43A77041 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/redhat/heads/gcc-8-branch)] libstdc++: Fix unique_ptr pretty printer for empty classes X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/vendors/redhat/heads/gcc-8-branch X-Git-Oldrev: 9563eee9beb10f0236bf622b2cfd04593844c6dc X-Git-Newrev: a3ae177e245fcaba5390a87481414abc3c3de28d Message-Id: <20210423103724.10EE43A77041@sourceware.org> Date: Fri, 23 Apr 2021 10:37:24 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Apr 2021 10:37:24 -0000 https://gcc.gnu.org/g:a3ae177e245fcaba5390a87481414abc3c3de28d commit a3ae177e245fcaba5390a87481414abc3c3de28d Author: Jonathan Wakely Date: Tue May 14 12:17:18 2019 +0100 libstdc++: Fix unique_ptr pretty printer for empty classes The printer was confused when unique_ptr::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: Copy from gcc-9 branch. * testsuite/libstdc++-prettyprinters/cxx11.cc: Check unique_ptr with empty pointer type and non-empty deleter. (cherry picked from commit e25f488d603a6bd7570c1ffdfd9572e4b8a645de) Diff: --- libstdc++-v3/python/libstdcxx/v6/printers.py | 11 +- .../testsuite/libstdc++-prettyprinters/compat.cc | 116 +++++++++++++++++++++ .../testsuite/libstdc++-prettyprinters/cxx11.cc | 20 ++++ 3 files changed, 145 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 37b8173435d..36352b8d0a8 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -181,11 +181,18 @@ class UniquePointerPrinter: self.val = val impl_type = val.type.fields()[0].type.tag if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation - 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 new file mode 100644 index 00000000000..1555ba8e798 --- /dev/null +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/compat.cc @@ -0,0 +1,116 @@ +// { dg-options "-g -O0" } +// { dg-do run { target c++11 } } +// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } } + +// Copyright (C) 2014-2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// Test that current printers still support old definitions of types. + +namespace std +{ + template + struct _Head_base : T + { }; + + template + struct _Head_base + { + T* _M_head_impl; + }; + + template struct _Tuple_impl; + + template + struct _Tuple_impl<0, T, U> : _Tuple_impl<1, U>, _Head_base + { }; + + template + struct _Tuple_impl<1, U> : _Head_base + { }; + + template + struct tuple : _Tuple_impl<0, T, U> + { }; + + template struct default_delete { }; + + template> + struct unique_ptr + { + unique_ptr(T* p) { _M_t._M_head_impl = p; } + + tuple _M_t; + }; + + // Old representation of std::optional, before GCC 9 + template + struct _Optional_payload + { + _Optional_payload() : _M_empty(), _M_engaged(false) { } + struct _Empty_byte { }; + union { + _Empty_byte _M_empty; + T _M_payload; + }; + bool _M_engaged; + }; + + template + struct _Optional_base + { + _Optional_payload _M_payload; + }; + + template + struct optional : _Optional_base + { + optional() { } + + optional(T t) + { + this->_M_payload._M_payload = t; + this->_M_payload._M_engaged = true; + } + }; +} // namespace std + +int +main() +{ + struct datum { }; + std::unique_ptr uptr (new datum); +// { dg-final { regexp-test uptr {std::unique_ptr.datum. = {get\(\) = 0x.*}} } } + std::unique_ptr &ruptr = uptr; +// { dg-final { regexp-test ruptr {std::unique_ptr.datum. = {get\(\) = 0x.*}} } } + + using std::optional; + + optional o; +// { dg-final { note-test o {std::optional [no contained value]} } } + optional ob{false}; +// { dg-final { note-test ob {std::optional = {[contained value] = false}} } } + optional oi{5}; +// { dg-final { note-test oi {std::optional = {[contained value] = 5}} } } + optional op{nullptr}; +// { dg-final { note-test op {std::optional = {[contained value] = 0x0}} } } + + __builtin_puts(""); + return 0; // Mark SPOT +} + +// { dg-final { gdb-test SPOT } } diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc index 0ecc3771351..9a90d8d91db 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc @@ -60,6 +60,21 @@ 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() { @@ -137,6 +152,11 @@ main() std::unique_ptr& rarrptr = arrptr; // { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } } + std::unique_ptr empty_ptr; +// { dg-final { note-test empty_ptr {std::unique_ptr = {get() = {}}} } } + std::unique_ptr& rempty_ptr = empty_ptr; +// { dg-final { note-test rempty_ptr {std::unique_ptr = {get() = {}}} } } + ExTuple tpl(6,7); // { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } } ExTuple &rtpl = tpl;