From patchwork Tue Jul 15 12:03:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 369976 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 50C77140170 for ; Tue, 15 Jul 2014 22:03:47 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=UwgUuT/J6TAmC41Id +jBv5Ey4ENptHE8iWgIy/8lighV1BzMW6kz3SOssj88hwhmfZrwQwDOlq2kV8O1P 5h2yDY3dv8Hjo8tbkomP48SqRt6Z/zBS4Ossb6qVRfOlYAMZVuzQY07Ow/DFcWFA +FCiVt7JMA8olXZy3H1QSPwA0A= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=default; bh=uuv14KLJ0AaXJ3o7Meetc42 aY2g=; b=h9jtm+5CITCq3KNt+auVIgQC5qWHlKrLOULO3XOVXjcfcFq4o1ABz8k /3+K1a5ft/9gYuR/z2iOX3qcsb1koOMErYUYJXp1+kR6vDr0YP34EMT5o8nSsvsq 7HeEmuRGQQD4nISvZnP2Iq3OR7/OF1duwRhvjhU/zy+BhfRJsWR0= Received: (qmail 18917 invoked by alias); 15 Jul 2014 12:03:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 18899 invoked by uid 89); 15 Jul 2014 12:03:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 15 Jul 2014 12:03:26 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s6FC3OeA015525 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 15 Jul 2014 08:03:24 -0400 Received: from localhost (ovpn-116-72.ams2.redhat.com [10.36.116.72]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s6FC3MB1027644; Tue, 15 Jul 2014 08:03:23 -0400 Date: Tue, 15 Jul 2014 13:03:22 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: tromey@redhat.com, pmuldoon@redhat.com Subject: Re: [patch] Add libstdc++ pretty printers for Library Fundamentals TS types Message-ID: <20140715120322.GM4871@redhat.com> References: <20140714193130.GH4871@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20140714193130.GH4871@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) On 14/07/14 20:31 +0100, Jonathan Wakely wrote: >This adds printers for the types in the std::experimental namespace. I've committed this slightly improved patch, which removes the duplicate _contained method from StdExpOptionalPrinter (it was meant to be using the base class version) and fixes some conditions to compare to None, so that integers, booleans and pointers with zero values don't get interpreted as no value. commit f29d6b5d809df660a989dd19b8afe68d08934d9f Author: redi Date: Tue Jul 15 12:00:18 2014 +0000 * python/libstdcxx/v6/printers.py (SingleObjContainerPrinter): New base class for experimental::any and experimental::optional printers. (StdExpAnyPrinter, StdExpOptionalPrinter, StdExpStringViewPrinter): New printers for Fundamentals TS types. * testsuite/libstdc++-prettyprinters/libfundts.cc: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@212556 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index ea34f22..af41f1f 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -836,6 +836,126 @@ class StdForwardListPrinter: return 'empty %s' % (self.typename) return '%s' % (self.typename) +class SingleObjContainerPrinter(object): + "Base class for printers of containers of single objects" + + def __init__ (self, val, viz): + self.contained_value = val + self.visualizer = viz + + def _recognize(self, type): + """Return TYPE as a string after applying type printers""" + return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(), + type) or str(type) + + class _contained: + def __init__ (self, val): + self.val = val + + def __iter__ (self): + return self + + def next (self): + if self.val is None: + raise StopIteration + retval = self.val + self.val = None + return ('[contained value]', retval) + + def children (self): + if self.contained_value is None: + return self._contained (None) + if hasattr (self.visualizer, 'children'): + return self.visualizer.children () + return self._contained (self.contained_value) + + def display_hint (self): + # if contained value is a map we want to display in the same way + if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'): + return self.visualizer.display_hint () + return None + + +class StdExpAnyPrinter(SingleObjContainerPrinter): + "Print a std::experimental::any" + + def __init__ (self, typename, val): + self.typename = 'std::experimental::any' + self.val = val + self.contained_type = None + contained_value = None + visualizer = None + mgr = self.val['_M_manager'] + if mgr != 0: + func = gdb.block_for_pc(int(mgr.cast(gdb.lookup_type('intptr_t')))) + if not func: + raise ValueError("Invalid function pointer in std::experimental::any") + rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\({0}::_Op, {0} const\*, {0}::_Arg\*\)""".format(typename) + m = re.match(rx, func.function.name) + if not m: + raise ValueError("Unknown manager function in std::experimental::any") + + # FIXME need to expand 'std::string' so that gdb.lookup_type works + mgrname = re.sub("std::string(?!\w)", gdb.lookup_type('std::string').strip_typedefs().name, m.group(1)) + mgrtype = gdb.lookup_type(mgrname) + self.contained_type = mgrtype.template_argument(0) + valptr = None + if '::_Manager_internal' in mgrname: + valptr = self.val['_M_storage']['_M_buffer'].address + elif '::_Manager_external' in mgrname: + valptr = self.val['_M_storage']['_M_ptr'] + elif '::_Manager_alloc' in mgrname: + datatype = gdb.lookup_type(mgrname + '::_Data') + valptr = self.val['_M_storage']['_M_ptr'].cast(datatype.pointer()) + valptr = valptr.dereference()['_M_data'].address + else: + raise ValueError("Unknown manager function in std::experimental::any") + contained_value = valptr.cast(self.contained_type.pointer()).dereference() + visualizer = gdb.default_visualizer(contained_value) + super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer) + + def to_string (self): + if self.contained_type is None: + return '%s [no contained value]' % self.typename + desc = "%s containing " % self.typename + if hasattr (self.visualizer, 'children'): + return desc + self.visualizer.to_string () + valtype = self._recognize (self.contained_type) + return desc + valtype + +class StdExpOptionalPrinter(SingleObjContainerPrinter): + "Print a std::experimental::optional" + + def __init__ (self, typename, val): + valtype = self._recognize (val.type.template_argument(0)) + self.typename = "std::experimental::optional<%s>" % valtype + self.val = val + contained_value = val['_M_payload'] if self.val['_M_engaged'] else None + visualizer = gdb.default_visualizer (val['_M_payload']) + super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer) + + def to_string (self): + if self.contained_value is None: + return self.typename + " [no contained value]" + if hasattr (self.visualizer, 'children'): + return self.typename + " containing " + self.visualizer.to_string () + return self.typename + +class StdExpStringViewPrinter: + "Print a std::experimental::basic_string_view" + + def __init__ (self, typename, val): + self.val = val + + def to_string (self): + ptr = self.val['_M_str'] + len = self.val['_M_len'] + if hasattr (ptr, "lazy_string"): + return ptr.lazy_string (length = len) + return ptr.string (length = len) + + def display_hint (self): + return 'string' # A "regular expression" printer which conforms to the # "SubPrettyPrinter" protocol from gdb.printing. @@ -865,12 +985,12 @@ class Printer(object): self.subprinters = [] self.lookup = {} self.enabled = True - self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$') + self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') def add(self, name, function): # A small sanity check. # FIXME - if not self.compiled_rx.match(name + '<>'): + if not self.compiled_rx.match(name): raise ValueError('libstdc++ programming error: "%s" does not match' % name) printer = RxPrinter(name, function) self.subprinters.append(printer) @@ -1214,6 +1334,13 @@ def build_libstdcxx_dictionary (): libstdcxx_printer.add('std::__debug::forward_list', StdForwardListPrinter) + # Library Fundamentals TS components + libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', + 'any', StdExpAnyPrinter) + libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', + 'optional', StdExpOptionalPrinter) + libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', + 'basic_string_view', StdExpStringViewPrinter) # Extensions. libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc new file mode 100644 index 0000000..e2f99a1 --- /dev/null +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc @@ -0,0 +1,69 @@ +// { dg-do run } +// { dg-options "-g -O0 -std=gnu++14" } + +// Copyright (C) 2014 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 +// . + +#include +#include +#include +#include +#include + +using std::experimental::any; +using std::experimental::optional; +using std::experimental::string_view; + +int +main() +{ + string_view str = "string"; +// { dg-final { note-test str "\"string\"" } } + + optional o; +// { dg-final { note-test o {std::experimental::optional [no contained value]} } } + optional ob{false}; +// { dg-final { note-test ob {std::experimental::optional = {[contained value] = false}} } } + optional oi{5}; +// { dg-final { note-test oi {std::experimental::optional = {[contained value] = 5}} } } + optional op{nullptr}; +// { dg-final { note-test op {std::experimental::optional = {[contained value] = 0x0}} } } + optional> om; + om = std::map{ {1, 2.}, {3, 4.}, {5, 6.} }; +// { dg-final { note-test om {std::experimental::optional> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } } + optional os{ "stringy" }; +// { dg-final { note-test os {std::experimental::optional = {[contained value] = "stringy"}} } } + + any a; +// { dg-final { note-test a {std::experimental::any [no contained value]} } } + any ab(false); +// { dg-final { note-test ab {std::experimental::any containing bool = {[contained value] = false}} } } + any ai(6); +// { dg-final { note-test ai {std::experimental::any containing int = {[contained value] = 6}} } } + any ap = (void*)nullptr; +// { dg-final { note-test ap {std::experimental::any containing void * = {[contained value] = 0x0}} } } + any as = *os; +// { dg-final { note-test as {std::experimental::any containing std::string = {[contained value] = "stringy"}} } } + any as2("stringiest"); +// { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } } + any am = *om; +// { dg-final { note-test am {std::experimental::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } } + + return 0; // Mark SPOT +} + +// { dg-final { gdb-test SPOT } }