Define pretty printers for C++17 library components
authorJonathan Wakely <jwakely@redhat.com>
Sat, 17 Sep 2016 15:20:23 +0000 (16:20 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Sat, 17 Sep 2016 15:20:23 +0000 (16:20 +0100)
* python/libstdcxx/v6/printers.py (StdVariantPrinter): Define.
(StdExpAnyPrinter, StdExpOptionalPrinter, StdExpStringViewPrinter):
Register for C++17 components in namespace std. Strip inline namespace
from typename.

From-SVN: r240215

libstdc++-v3/ChangeLog
libstdc++-v3/python/libstdcxx/v6/printers.py

index 765460b3f8b887846fa945bc3c87bee9ba9c96e5..70ff276beb47fa64a59058e7316cb852c1124fb8 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-17  Jonathan Wakely  <jwakely@redhat.com>
+
+       * python/libstdcxx/v6/printers.py (StdVariantPrinter): Define.
+       (StdExpAnyPrinter, StdExpOptionalPrinter, StdExpStringViewPrinter):
+       Register for C++17 components in namespace std. Strip inline namespace
+       from typename.
+
 2016-09-16  Jonathan Wakely  <jwakely@redhat.com>
 
        * doc/xml/manual/profile_mode.xml: Fix typo.
index 977e63fff4744c4f9d79936a0b2bf29a4d9e3f09..8c29760e01c36224bab45cbb1f6d6b6a8384f5ed 100644 (file)
@@ -920,10 +920,10 @@ class SingleObjContainerPrinter(object):
 
 
 class StdExpAnyPrinter(SingleObjContainerPrinter):
-    "Print a std::experimental::any"
+    "Print a std::any or std::experimental::any"
 
     def __init__ (self, typename, val):
-        self.typename = 'std::experimental::any'
+        self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1)
         self.val = val
         self.contained_type = None
         contained_value = None
@@ -932,11 +932,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
         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")
+                raise ValueError("Invalid function pointer in %s" % self.typename)
             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")
+                raise ValueError("Unknown manager function in %s" % self.typename)
 
             # FIXME need to expand 'std::string' so that gdb.lookup_type works
             mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
@@ -948,7 +948,7 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
             elif '::_Manager_external' in mgrname:
                 valptr = self.val['_M_storage']['_M_ptr']
             else:
-                raise ValueError("Unknown manager function in std::experimental::any")
+                raise ValueError("Unknown manager function in %s" % self.typename)
             contained_value = valptr.cast(self.contained_type.pointer()).dereference()
             visualizer = gdb.default_visualizer(contained_value)
         super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer)
@@ -963,11 +963,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
         return desc + valtype
 
 class StdExpOptionalPrinter(SingleObjContainerPrinter):
-    "Print a std::experimental::optional"
+    "Print a std::optional or std::experimental::optional"
 
     def __init__ (self, typename, val):
         valtype = self._recognize (val.type.template_argument(0))
-        self.typename = "std::experimental::optional<%s>" % valtype
+        self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1)
         self.val = val
         contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
         visualizer = gdb.default_visualizer (val['_M_payload'])
@@ -980,8 +980,44 @@ class StdExpOptionalPrinter(SingleObjContainerPrinter):
             return self.typename + " containing " + self.visualizer.to_string ()
         return self.typename
 
+class StdVariantPrinter(SingleObjContainerPrinter):
+    "Print a std::variant"
+
+    def __init__(self, typename, val):
+        alternatives = self._template_args(val)
+        self.alts = alternatives
+        self.typename = "%s<%s>" % (typename, ', '.join([self._recognize(alt) for alt in alternatives]))
+        self.index = val['_M_index']
+        if self.index >= len(alternatives):
+            self.contained_type = None
+            contained_value = None
+            visualizer = None
+        else:
+            self.contained_type = alternatives[int(self.index)]
+            addr = val['_M_first']['_M_storage'].address
+            contained_value = addr.cast(self.contained_type.pointer()).dereference()
+            visualizer = gdb.default_visualizer(contained_value)
+        super (StdVariantPrinter, self).__init__(contained_value, visualizer)
+
+    def _template_args(self, val):
+        n = 0
+        args = ()
+        while True:
+            try:
+                args += (val.type.template_argument(n),)
+            except:
+                return args
+            n += 1
+
+    def to_string(self):
+        if self.contained_value is None:
+            return "%s [no value]" % self.typename
+        if hasattr(self.visualizer, 'children'):
+            return "%s [alternative %d] %s" % (self.typename, self.index, self.visualizer.to_string())
+        return self.typename
+
 class StdExpStringViewPrinter:
-    "Print a std::experimental::basic_string_view"
+    "Print a std::basic_string_view or std::experimental::basic_string_view"
 
     def __init__ (self, typename, val):
         self.val = val
@@ -1385,7 +1421,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter)
     libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter)
 
-    # These are the TR1 and C++0x printers.
+    # These are the TR1 and C++11 printers.
     # For array - the default GDB pretty-printer seems reasonable.
     libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter)
     libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter)
@@ -1411,7 +1447,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
                                   Tr1UnorderedSetPrinter)
 
-    # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases.
+    # These are the C++11 printer registrations for -D_GLIBCXX_DEBUG cases.
     # The tr1 namespace printers do not seem to have any debug
     # equivalents, so do no register them.
     libstdcxx_printer.add('std::__debug::unordered_map',
@@ -1438,6 +1474,16 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::',
                                   'path', StdExpPathPrinter)
 
+    # C++17 components
+    libstdcxx_printer.add_version('std::',
+                                  'any', StdExpAnyPrinter)
+    libstdcxx_printer.add_version('std::',
+                                  'optional', StdExpOptionalPrinter)
+    libstdcxx_printer.add_version('std::',
+                                  'basic_string_view', StdExpStringViewPrinter)
+    libstdcxx_printer.add_version('std::',
+                                  'variant', StdVariantPrinter)
+
     # Extensions.
     libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)