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
This commit is contained in:
Jonathan Wakely 2014-07-15 13:00:18 +01:00 committed by Jonathan Wakely
parent 077aa95ec7
commit 6f440cceb4
3 changed files with 204 additions and 2 deletions

View File

@ -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 <timshen@google.com>
PR libstdc++/61720

View File

@ -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)

View File

@ -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
// <http://www.gnu.org/licenses/>.
#include <experimental/any>
#include <experimental/optional>
#include <experimental/string_view>
#include <string>
#include <map>
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<int> o;
// { dg-final { note-test o {std::experimental::optional<int> [no contained value]} } }
optional<bool> ob{false};
// { dg-final { note-test ob {std::experimental::optional<bool> = {[contained value] = false}} } }
optional<int> oi{5};
// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
optional<void*> op{nullptr};
// { dg-final { note-test op {std::experimental::optional<void *> = {[contained value] = 0x0}} } }
optional<std::map<int, double>> om;
om = std::map<int, double>{ {1, 2.}, {3, 4.}, {5, 6.} };
// { dg-final { note-test om {std::experimental::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
optional<std::string> os{ "stringy" };
// { dg-final { note-test os {std::experimental::optional<std::string> = {[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 } }