commit 6a3842ae658fe9693a0989a9aa5ea7b42d01fe28
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Jul 14 15:41:22 2014 +0100
* 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.
@@ -836,6 +836,142 @@ 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
+
+ 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:
+ if hasattr (self.visualizer, 'children'):
+ return self.visualizer.children ()
+ else:
+ return self._contained (self.contained_value)
+ return self._contained (None)
+
+ 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
+ valtype = gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(),
+ self.contained_type)
+ if not valtype:
+ valtype = self.contained_type.name or str(self.contained_type)
+ if self.contained_value is None:
+ return '%s containing %s with unknown value' % (self.typename, valtype)
+ desc = "%s containing " % self.typename
+ if hasattr (self.visualizer, 'children'):
+ return desc + self.visualizer.to_string ()
+ return desc + valtype
+
+class StdExpOptionalPrinter(SingleObjContainerPrinter):
+ "Print a std::experimental::optional"
+
+ def __init__ (self, typename, val):
+ valtype = val.type.template_argument(0)
+ valtype = gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(), valtype) or valtype
+ 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)
+
+ 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 to_string (self):
+ if not self.contained_value:
+ 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 +1001,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 +1350,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)
new file mode 100644
@@ -0,0 +1,61 @@
+// { 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<int> oi{5};
+// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
+ 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 ai(6);
+// { dg-final { note-test ai {std::experimental::any containing int = {[contained value] = 6}} } }
+ any as = *os;
+// { dg-final { note-test as {std::experimental::any containing std::string = {[contained value] = "stringy"}} } }
+ any ap("stringiest");
+// { dg-final { regexp-test ap {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 } }