From 6f440cceb403312f76a610b26cee52541e9cf3e7 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 15 Jul 2014 13:00:18 +0100 Subject: [PATCH] printers.py (SingleObjContainerPrinter): New base class for experimental::any and experimental::optional printers. * 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. From-SVN: r212556 --- libstdc++-v3/ChangeLog | 6 + libstdc++-v3/python/libstdcxx/v6/printers.py | 131 +++++++++++++++++- .../libstdc++-prettyprinters/libfundts.cc | 69 +++++++++ 3 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c59c25453e1..32de8825ae5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -6,6 +6,12 @@ and other class templates with default template arguments. * testsuite/libstdc++-prettyprinters/whatis.cc: Test new recognizers. + * 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. + 2014-07-15 Tim Shen PR libstdc++/61720 diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index ea34f222cdf..af41f1ffaeb 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 00000000000..e2f99a1bd6d --- /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 } }