public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Pretty printers for versioned namespace
@ 2016-11-28 21:19 François Dumont
  2016-11-29 20:17 ` Jonathan Wakely
  0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2016-11-28 21:19 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1148 bytes --]

Hi

     Here is a patch to fix pretty printers when versioned namespace is 
activated.

     You will see that I have hesitated in making the fix independant of 
the version being used. In source files you will find (__7::)? patterns 
while in xmethods.py I chose (__\d+::)? making it ready for __8 and 
forward. Do you want to generalize one option ? If so which one ?

     At the moment version namespace is visible within gdb, it displays 
for instance 'std::__7::string'. I am pretty sure we could hide it, is 
it preferable ? I would need some time to do so as I am neither a python 
nor regex expert.

     I am not fully happy with the replication in printers.py of 
StdRbtreeIteratorPrinter and StdExpAnyPrinter(SingleObjContainerPrinter 
in respectively StdVersionedRbtreeIteratorPrinter and 
StdExpVerAnyPrinter(SingleObjContainerPrinter just to adapt 2 lines 
where regex is not an option. We could surely keep only one and pass it 
'' or '__7'. But as I said I am not a python expert so any help would be 
appreciated.

     I still need to run it with versioned namespace disabled to make 
sure there is no regression.

François


[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 58807 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index bad42b4..3a6f004 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -36,6 +36,8 @@ import sys
 # We probably can't do much about this until this GDB PR is addressed:
 # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
 
+vers_nsp = '__7::'
+
 if sys.version_info[0] > 2:
     ### Python 3 stuff
     Iterator = object
@@ -127,9 +129,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(' + vers_nsp + ')?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(' + vers_nsp + ')?tuple<.*>$', impl_type):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -492,6 +494,19 @@ class StdRbtreeIteratorPrinter:
         node = self.val['_M_node'].cast(self.link_type).dereference()
         return get_value_from_Rb_tree_node(node)
 
+class StdVersionedRbtreeIteratorPrinter:
+    "Print std::" + vers_nsp + "map::iterator"
+
+    def __init__ (self, typename, val):
+        self.val = val
+        valtype = self.val.type.template_argument(0).strip_typedefs()
+        nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+        self.link_type = nodetype.strip_typedefs().pointer()
+
+    def to_string (self):
+        node = self.val['_M_node'].cast(self.link_type).dereference()
+        return get_value_from_Rb_tree_node(node)
+
 class StdDebugIteratorPrinter:
     "Print a debug enabled version of an iterator"
 
@@ -927,7 +942,6 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
@@ -971,6 +985,49 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
         valtype = self._recognize (self.contained_type)
         return desc + valtype
 
+class StdExpVerAnyPrinter(SingleObjContainerPrinter):
+    "Print a std::__7::any or std::experimental::__7::any"
+
+    def __init__ (self, typename, val):
+        self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1)
+        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 %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 %s" % self.typename)
+
+            # FIXME need to expand 'std::string' so that gdb.lookup_type works
+            mgrname = re.sub("std::" + vers_nsp + "string(?!\w)", str(gdb.lookup_type('std::' + vers_nsp + 'string').strip_typedefs()), 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']
+            else:
+                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(StdExpVerAnyPrinter, 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::optional or std::experimental::optional"
 
@@ -1031,7 +1088,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = re.match('^std::(' + vers_nsp + ')?_Rb_tree_node.$', nodetype.name)
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1176,7 +1233,7 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        self.add(base + vers_nsp + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1311,7 +1368,7 @@ def register_type_printers(obj):
     if not _use_type_printing:
         return
 
-    for pfx in ('', 'w'):
+    for pfx in ('', 'w', vers_nsp, vers_nsp + 'w'):
         add_one_type_printer(obj, 'basic_string', pfx + 'string')
         add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view')
         add_one_type_printer(obj, 'basic_ios', pfx + 'ios')
@@ -1342,70 +1399,70 @@ def register_type_printers(obj):
         add_one_type_printer(obj, 'regex_token_iterator',
                                  pfx + 'sregex_token_iterator')
 
-    # Note that we can't have a printer for std::wstreampos, because
-    # it shares the same underlying type as std::streampos.
-    add_one_type_printer(obj, 'fpos', 'streampos')
-    add_one_type_printer(obj, 'basic_string', 'u16string')
-    add_one_type_printer(obj, 'basic_string', 'u32string')
-
-    add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
-    add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
-
-    for dur in ('nanoseconds', 'microseconds', 'milliseconds',
-                'seconds', 'minutes', 'hours'):
-        add_one_type_printer(obj, 'duration', dur)
-
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
-    add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
-
-    # Do not show defaulted template arguments in class templates
-    add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
-
-    add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
-    add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
-    add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
-    add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
-    add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
-    add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
-    add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
-    add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+    for vers in ('', vers_nsp):
+        # Note that we can't have a printer for std::wstreampos, because
+        # it shares the same underlying type as std::streampos.
+        add_one_type_printer(obj, 'fpos', vers + 'streampos')
+        add_one_type_printer(obj, 'basic_string', vers + 'u16string')
+        add_one_type_printer(obj, 'basic_string', vers + 'u32string')
+        add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
+        add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
+
+        for dur in ('nanoseconds', 'microseconds', 'milliseconds',
+                    'seconds', 'minutes', 'hours'):
+            add_one_type_printer(obj, 'duration', vers + dur)
+
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand0')
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937_64')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux24_base')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux48_base')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux24')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux48')
+        add_one_type_printer(obj, 'shuffle_order_engine', vers + 'knuth_b')
+
+        # Do not show defaulted template arguments in class templates
+        add_one_template_type_printer(obj, 'unique_ptr<T>',
+            '%sunique_ptr<(.*), std::%sdefault_delete<\\1 ?> >' % (vers, vers),
+            '%sunique_ptr<{1}>' % vers)
+
+        add_one_template_type_printer(obj, 'deque<T>',
+            '%sdeque<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%sdeque<{1}>' % vers)
+        add_one_template_type_printer(obj, 'forward_list<T>',
+            '%sforward_list<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%sforward_list<{1}>' % vers)
+        add_one_template_type_printer(obj, 'list<T>',
+            '%slist<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%slist<{1}>' % vers)
+        add_one_template_type_printer(obj, 'vector<T>',
+            '%svector<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%svector<{1}>' % vers)
+        add_one_template_type_printer(obj, 'map<Key, T>',
+            '%smap<(.*), (.*), std::%sless<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers),
+            '%smap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'multimap<Key, T>',
+            '%smultimap<(.*), (.*), std::%sless<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers),
+            '%smultimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'set<T>',
+            '%sset<(.*), std::%sless<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers),
+            '%sset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'multiset<T>',
+            '%smultiset<(.*), std::%sless<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers),
+            '%smultiset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_map<Key, T>',
+            '%sunordered_map<(.*), (.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers, vers),
+            '%sunordered_map<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
+            '%sunordered_multimap<(.*), (.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers, vers),
+            '%sunordered_multimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_set<T>',
+            '%sunordered_set<(.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers, vers),
+            '%sunordered_set<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multiset<T>',
+            '%sunordered_multiset<(.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers, vers),
+            '%sunordered_multiset<{1}>' % vers)
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
@@ -1439,7 +1496,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer = Printer("libstdc++-v6")
 
     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
+    vers = '(' + vers_nsp + ')?'
     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     container = '(__cxx1998::' + vers + ')?'
 
@@ -1521,8 +1578,10 @@ def build_libstdcxx_dictionary ():
                           StdForwardListPrinter)
 
     # Library Fundamentals TS components
-    libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
-                                  'any', StdExpAnyPrinter)
+    libstdcxx_printer.add('std::experimental::fundamentals_v1::any',
+                          StdExpAnyPrinter)
+    libstdcxx_printer.add('std::experimental::fundamentals_v1::' + vers_nsp + 'any',
+                          StdExpVerAnyPrinter)
     libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
                                   'optional', StdExpOptionalPrinter)
     libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
@@ -1534,8 +1593,9 @@ def build_libstdcxx_dictionary ():
                                   'path', StdExpPathPrinter)
 
     # C++17 components
-    libstdcxx_printer.add_version('std::',
-                                  'any', StdExpAnyPrinter)
+    libstdcxx_printer.add('std::any', StdExpAnyPrinter)
+    libstdcxx_printer.add('std::' + vers_nsp + 'any',
+                          StdExpVerAnyPrinter)
     libstdcxx_printer.add_version('std::',
                                   'optional', StdExpOptionalPrinter)
     libstdcxx_printer.add_version('std::',
@@ -1555,10 +1615,14 @@ def build_libstdcxx_dictionary ():
                                         StdListIteratorPrinter)
         libstdcxx_printer.add_container('std::', '_List_const_iterator',
                                         StdListIteratorPrinter)
-        libstdcxx_printer.add_version('std::', '_Rb_tree_iterator',
-                                      StdRbtreeIteratorPrinter)
-        libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator',
-                                      StdRbtreeIteratorPrinter)
+        libstdcxx_printer.add('std::_Rb_tree_iterator',
+                              StdRbtreeIteratorPrinter)
+        libstdcxx_printer.add('std::' + vers_nsp + '_Rb_tree_iterator',
+                              StdVersionedRbtreeIteratorPrinter)
+        libstdcxx_printer.add('std::_Rb_tree_const_iterator',
+                              StdRbtreeIteratorPrinter)
+        libstdcxx_printer.add('std::' + vers_nsp + '_Rb_tree_const_iterator',
+                              StdVersionedRbtreeIteratorPrinter)
         libstdcxx_printer.add_container('std::', '_Deque_iterator',
                                         StdDequeIteratorPrinter)
         libstdcxx_printer.add_container('std::', '_Deque_const_iterator',
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index 045b661..4d58663 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -576,9 +576,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -604,7 +604,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
diff --git a/libstdc++-v3/testsuite/lib/gdb-test.exp b/libstdc++-v3/testsuite/lib/gdb-test.exp
index 3ebbf6b..ec97ac3 100644
--- a/libstdc++-v3/testsuite/lib/gdb-test.exp
+++ b/libstdc++-v3/testsuite/lib/gdb-test.exp
@@ -74,6 +74,14 @@ proc whatis-test {var result} {
     lappend gdb_tests $var $result whatis
 }
 
+# A test of 'whatis'.  This tests a type rather than a variable through a
+# regexp.
+proc whatis-regexp-test {var result} {
+    global gdb_tests
+
+    lappend gdb_tests $var $result whatisrexp
+}
+
 # Utility for testing variable values using gdb, invoked via dg-final.
 # Tests all tests indicated by note-test and regexp-test.
 #
@@ -140,10 +148,15 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 	incr count
 	set gdb_var($count) $var
 	set gdb_expected($count) $result
-	if {$kind == "whatis"} {
+	if {$kind == "whatis" || $kind == "whatisrexp"} {
 	    if {$do_whatis_tests} {
 		set gdb_is_type($count) 1
 		set gdb_command($count) "whatis $var"
+		if {$kind == "whatis"} {
+		    set gdb_is_regexp($count) 0
+		} else {
+		    set gdb_is_regexp($count) 1
+		}
 	    } else {
 	        unsupported "$testname"
 	        close $fd
@@ -179,13 +192,13 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 		if {$expect_out(1,string) != "type"} {
 		    error "gdb failure"
 		}
-		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
-	    } elseif {$gdb_is_regexp($test_counter)} {
+	    }
+
+	    if {$gdb_is_regexp($test_counter)} {
 		set match [regexp -- $gdb_expected($test_counter) $first]
 	    } else {
 		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
+				       $gdb_expected($test_counter)]}]
 	    }
 
 	    if {$match} {
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index 780a4e4..aa3b63b 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -63,77 +63,77 @@ int
 main()
 {
   std::forward_list<int> efl;
-// { dg-final { note-test efl "empty std::forward_list" } }
+// { dg-final { regexp-test efl "empty std::(__7::)?forward_list" } }
 
   std::forward_list<int> &refl = efl;
-// { dg-final { note-test refl "empty std::forward_list" } }
+// { dg-final { regexp-test refl "empty std::(__7::)?forward_list" } }
 
   std::forward_list<int> fl;
   fl.push_front(2);
   fl.push_front(1);
-// { dg-final { note-test fl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test fl {std::(__7::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::forward_list<int> &rfl = fl;
-// { dg-final { note-test rfl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test rfl {std::(__7::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::(__7::)?unordered_map with 0 elements" } }
   std::unordered_map<int, std::string> &reum = eum;
-// { dg-final { note-test reum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test reum "std::(__7::)?unordered_map with 0 elements" } }
 
   std::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::(__7::)?unordered_multimap with 0 elements" } }
   std::unordered_multimap<int, std::string> &reumm = eumm;
-// { dg-final { note-test reumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test reumm "std::(__7::)?unordered_multimap with 0 elements" } }
 
   std::unordered_set<int> eus;
-// { dg-final { note-test eus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::(__7::)?unordered_set with 0 elements" } }
   std::unordered_set<int> &reus = eus;
-// { dg-final { note-test reus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test reus "std::(__7::)?unordered_set with 0 elements" } }
 
   std::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::(__7::)?unordered_multiset with 0 elements" } }
   std::unordered_multiset<int> &reums = eums;
-// { dg-final { note-test reums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test reums "std::(__7::)?unordered_multiset with 0 elements" } }
 
   std::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_map<int, std::string> &ruom = uom;
-// { dg-final { note-test ruom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruom {std::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uomm {std::(__7::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
   std::unordered_multimap<int, std::string> &ruomm = uomm;
-// { dg-final { note-test ruomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruomm {std::(__7::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::(__7::)?unordered_set with 1 elements = {\[0\] = 5}} } }
   std::unordered_set<int> &ruos = uos;
-// { dg-final { note-test ruos {std::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test ruos {std::(__7::)?unordered_set with 1 elements = {\[0\] = 5}} } }
 
   std::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::(__7::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
   std::unordered_multiset<int> &ruoms = uoms;
-// { dg-final { note-test ruoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test ruoms {std::(__7::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
 
   std::unique_ptr<datum> uptr (new datum);
   uptr->s = "hi bob";
   uptr->i = 23;
-// { dg-final { regexp-test uptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test uptr {std::(__7::)?unique_ptr.datum. containing 0x.*} } }
   std::unique_ptr<datum> &ruptr = uptr;
-// { dg-final { regexp-test ruptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test ruptr {std::(__7::)?unique_ptr.datum. containing 0x.*} } }
 
   ExTuple tpl(6,7);
-// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }  
+// { dg-final { regexp-test tpl {std::(__7::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   ExTuple &rtpl = tpl;
-// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } }   
+// { dg-final { regexp-test rtpl {std::(__7::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   placeholder(""); // Mark SPOT
   use(efl);
   use(fl);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
index 96be8c7..c85edc3 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
@@ -44,50 +44,50 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::(__7::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::(__7::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::(__7::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::(__7::)?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::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test om {std::(__7::)?optional<std::(__7::)?map<int, double>> containing std::(__7::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
   optional<std::string> os{ "stringy" };
-// { dg-final { note-test os {std::optional<std::string> = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test os {std::(__7::)?optional<std::(__7::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::any [no contained value]} } }
+// { dg-final { regexp-test a {std::(__7::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::(__7::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::(__7::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::(__7::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::(__7::)?any containing std::(__7::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::(__7::)?any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
   any am = *om;
-// { dg-final { note-test am {std::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test am {std::(__7::)?any containing std::(__7::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   struct S { operator int() { throw 42; }};
   variant<float, int, string_view> v0;
-// { dg-final { note-test v0 {std::variant<float, int, std::string_view> [index 0] = {0}} } }
+// { dg-final { regexp-test v0 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 0\] = {0}} } }
   variant<float, int, string_view> v1{ 0.5f };
-// { dg-final { note-test v1 {std::variant<float, int, std::string_view> [index 0] = {0.5}} } }
+// { dg-final { regexp-test v1 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 0\] = [{]0.5[}]} } }
   variant<float, int, string_view> v2;
   try {
     v2.emplace<1>(S());
   } catch (int) { }
-// { dg-final { note-test v2 {std::variant<float, int, std::string_view> [no contained value]} } }
+// { dg-final { regexp-test v2 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[no contained value\]} } }
   variant<float, int, string_view> v3{ 3 };
-// { dg-final { note-test v3 {std::variant<float, int, std::string_view> [index 1] = {3}} } }
+// { dg-final { regexp-test v3 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 1\] = [{]3[}]} } }
   variant<float, int, string_view> v4{ str };
-// { dg-final { note-test v4 {std::variant<float, int, std::string_view> [index 2] = {"string"}} } }
+// { dg-final { regexp-test v4 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 2\] = {"string"}} } }
   variant<string_view> vref{str};
-// { dg-final { note-test vref {std::variant<std::string_view> [index 0] = {"string"}} } }
+// { dg-final { regexp-test vref {std::(__7::)?variant<std::(__7::)?string_view> \[index 0\] = {"string"}} } }
 
   map<int, string_view> m{ {1, "one"} };
   map<int, string_view>::node_type n0;
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
index 534c55f..18580c7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
@@ -39,33 +39,33 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::experimental::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::experimental::(__7::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::experimental::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::experimental::(__7::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::experimental::(__7::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::experimental::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::experimental::(__7::)?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}} } }
+// { dg-final { regexp-test om {std::experimental::(__7::)?optional<std::(__7::)?map<int, double>> containing std::(__7::)?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"}} } }
+// { dg-final { regexp-test os {std::experimental::(__7::)?optional<std::(__7::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::experimental::any [no contained value]} } }
+// { dg-final { regexp-test a {std::experimental::(__7::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::experimental::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::experimental::(__7::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::experimental::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::experimental::(__7::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::experimental::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::experimental::(__7::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::experimental::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::experimental::(__7::)?any containing std::(__7::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::experimental::(__7::)?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}} } }
+// { dg-final { regexp-test am {std::experimental::(__7::)?any containing std::(__7::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   std::cout << "\n";
   return 0;			// Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
index 9528860..ab9baf9 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
@@ -49,25 +49,25 @@ main()
   typedef std::weak_ptr<int> weak;
 
   shared esp;
-// { dg-final { note-test esp "std::shared_ptr (empty) 0x0" } }
+// { dg-final { regexp-test esp {std::(__7::)?shared_ptr \(empty\) 0x0} } }
   weak ewp1;
-// { dg-final { note-test ewp1 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp1 {std::(__7::)?weak_ptr \(empty\) 0x0} } }
   weak ewp2 = esp;
-// { dg-final { note-test ewp2 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp2 {std::(__7::)?weak_ptr \(empty\) 0x0} } }
 
   shared sp1 = make(0x12345678);
   shared sp2 = sp1;
-// { dg-final { note-test sp1 "std::shared_ptr (count 2, weak 0) 0x12345678" } }
+// { dg-final { regexp-test sp1 {std::(__7::)?shared_ptr \(count 2, weak 0\) 0x12345678} } }
 
   shared sp3 = make(0x12344321);
   weak sp4 = sp3;
   weak wp1 = sp3;
-// { dg-final { note-test wp1 "std::weak_ptr (count 1, weak 2) 0x12344321" } }
+// { dg-final { regexp-test wp1 {std::(__7::)?weak_ptr \(count 1, weak 2\) 0x12344321} } }
 
   shared sp5 = make(0x56788765);
   weak wp2 = sp5;
   sp5.reset();
-// { dg-final { note-test wp2 "std::weak_ptr (expired, weak 1) 0x56788765" } }
+// { dg-final { regexp-test wp2 {std::(__7::)?weak_ptr \(expired, weak 1\) 0x56788765} } }
 
   placeholder(""); // Mark SPOT
   use(esp);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
index 5f98b25..edf1735 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__7::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__7::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__7::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,7 +68,7 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__7::)?map with 1 elements = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
@@ -78,12 +78,12 @@ main()
   intset.insert(2);
   intset.insert(3);
   const std::set<int> const_intset = intset;
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__7::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__7::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
index 97a57ef..fa3e36d 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__7::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__7::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__7::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,19 +68,19 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__7::)?map with 1 elements = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
   // PR 67440
   const std::set<int> const_intset = {2, 3};
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__7::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__7::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
index 52dca4d..0a87dd9 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
@@ -51,31 +51,31 @@ int
 main()
 {
   std::tr1::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::tr1::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::tr1::(__7::)?unordered_map with 0 elements" } }
   std::tr1::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::tr1::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::tr1::(__7::)?unordered_multimap with 0 elements" } }
   std::tr1::unordered_set<int> eus;
-// { dg-final { note-test eus "std::tr1::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::tr1::(__7::)?unordered_set with 0 elements" } }
   std::tr1::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::tr1::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::tr1::(__7::)?unordered_multiset with 0 elements" } }
 
   std::tr1::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::tr1::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::tr1::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::tr1::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::tr1::unordered_multimap with 2 elements = {[5] = "three", [5] = "seven"}} } }
+// { dg-final { regexp-test uomm {std::tr1::(__7::)?unordered_multimap with 2 elements = {\[5\] = "three", \[5\] = "seven"}} } }
 
   std::tr1::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::tr1::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::tr1::(__7::)?unordered_set with 1 elements = {\[0\] = 5}} } }
 
   std::tr1::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::tr1::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::tr1::(__7::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
 
   placeholder(""); // Mark SPOT
   use(eum);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 3f79f92..f440692 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -60,141 +60,141 @@ typedef std::basic_string<unsigned char> ustring;
 
 std::string *string_ptr;
 holder<std::string> string_holder;
-// { dg-final { whatis-test string_holder "holder<std::string>" } }
+// { dg-final { whatis-regexp-test string_holder "holder<std::(__7::)?string>" } }
 std::ios *ios_ptr;
 holder<std::ios> ios_holder;
-// { dg-final { whatis-test ios_holder "holder<std::ios>" } }
+// { dg-final { whatis-regexp-test ios_holder "holder<std::(__7::)?ios>" } }
 std::streambuf *streambuf_ptr;
 holder<std::streambuf> streambuf_holder;
-// { dg-final { whatis-test streambuf_holder "holder<std::streambuf>" } }
+// { dg-final { whatis-regexp-test streambuf_holder "holder<std::(__7::)?streambuf>" } }
 std::istream *istream_ptr;
 holder<std::istream> istream_holder;
-// { dg-final { whatis-test istream_holder "holder<std::istream>" } }
+// { dg-final { whatis-regexp-test istream_holder "holder<std::(__7::)?istream>" } }
 std::ostream *ostream_ptr;
 holder<std::ostream> ostream_holder;
-// { dg-final { whatis-test ostream_holder "holder<std::ostream>" } }
+// { dg-final { whatis-regexp-test ostream_holder "holder<std::(__7::)?ostream>" } }
 std::iostream *iostream_ptr;
 holder<std::iostream> iostream_holder;
-// { dg-final { whatis-test iostream_holder "holder<std::iostream>" } }
+// { dg-final { whatis-regexp-test iostream_holder "holder<std::(__7::)?iostream>" } }
 std::stringbuf *stringbuf_ptr;
 holder<std::stringbuf> stringbuf_holder;
-// { dg-final { whatis-test stringbuf_holder "holder<std::stringbuf>" } }
+// { dg-final { whatis-regexp-test stringbuf_holder "holder<std::(__7::)?stringbuf>" } }
 std::istringstream *istringstream_ptr;
 holder<std::istringstream> istringstream_holder;
-// { dg-final { whatis-test istringstream_holder "holder<std::istringstream>" } }
+// { dg-final { whatis-regexp-test istringstream_holder "holder<std::(__7::)?istringstream>" } }
 std::ostringstream *ostringstream_ptr;
 holder<std::ostringstream> ostringstream_holder;
-// { dg-final { whatis-test ostringstream_holder "holder<std::ostringstream>" } }
+// { dg-final { whatis-regexp-test ostringstream_holder "holder<std::(__7::)?ostringstream>" } }
 std::stringstream *stringstream_ptr;
 holder<std::stringstream> stringstream_holder;
-// { dg-final { whatis-test stringstream_holder "holder<std::stringstream>" } }
+// { dg-final { whatis-regexp-test stringstream_holder "holder<std::(__7::)?stringstream>" } }
 std::filebuf *filebuf_ptr;
 holder<std::filebuf> filebuf_holder;
-// { dg-final { whatis-test filebuf_holder "holder<std::filebuf>" } }
+// { dg-final { whatis-regexp-test filebuf_holder "holder<std::(__7::)?filebuf>" } }
 std::ifstream *ifstream_ptr;
 holder<std::ifstream> ifstream_holder;
-// { dg-final { whatis-test ifstream_holder "holder<std::ifstream>" } }
+// { dg-final { whatis-regexp-test ifstream_holder "holder<std::(__7::)?ifstream>" } }
 std::ofstream *ofstream_ptr;
 holder<std::ofstream> ofstream_holder;
-// { dg-final { whatis-test ofstream_holder "holder<std::ofstream>" } }
+// { dg-final { whatis-regexp-test ofstream_holder "holder<std::(__7::)?ofstream>" } }
 std::fstream *fstream_ptr;
 holder<std::fstream> fstream_holder;
-// { dg-final { whatis-test fstream_holder "holder<std::fstream>" } }
+// { dg-final { whatis-regexp-test fstream_holder "holder<std::(__7::)?fstream>" } }
 std::streampos *streampos_ptr;
 holder<std::streampos> streampos_holder;
-// { dg-final { whatis-test streampos_holder "holder<std::streampos>" } }
+// { dg-final { whatis-regexp-test streampos_holder "holder<std::(__7::)?streampos>" } }
 std::regex *regex_ptr;
 holder<std::regex> regex_holder;
-// { dg-final { whatis-test regex_holder "holder<std::regex>" } }
+// { dg-final { whatis-regexp-test regex_holder "holder<std::(__7::)?regex>" } }
 std::csub_match *csub_match_ptr;
 holder<std::csub_match> csub_match_holder;
-// { dg-final { whatis-test csub_match_holder "holder<std::csub_match>" } }
+// { dg-final { whatis-regexp-test csub_match_holder "holder<std::(__7::)?csub_match>" } }
 std::ssub_match *ssub_match_ptr;
 holder<std::ssub_match> ssub_match_holder;
-// { dg-final { whatis-test ssub_match_holder "holder<std::ssub_match>" } }
+// { dg-final { whatis-regexp-test ssub_match_holder "holder<std::(__7::)?ssub_match>" } }
 std::cmatch *cmatch_ptr;
 holder<std::cmatch> cmatch_holder;
-// { dg-final { whatis-test cmatch_holder "holder<std::cmatch>" } }
+// { dg-final { whatis-regexp-test cmatch_holder "holder<std::(__7::)?cmatch>" } }
 std::smatch *smatch_ptr;
 holder<std::smatch> smatch_holder;
-// { dg-final { whatis-test smatch_holder "holder<std::smatch>" } }
+// { dg-final { whatis-regexp-test smatch_holder "holder<std::(__7::)?smatch>" } }
 std::cregex_iterator *cregex_iterator_ptr;
 holder<std::cregex_iterator> cregex_iterator_holder;
-// { dg-final { whatis-test cregex_iterator_holder "holder<std::cregex_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_iterator_holder "holder<std::(__7::)?cregex_iterator>" } }
 std::sregex_iterator *sregex_iterator_ptr;
 holder<std::sregex_iterator> sregex_iterator_holder;
-// { dg-final { whatis-test sregex_iterator_holder "holder<std::sregex_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_iterator_holder "holder<std::(__7::)?sregex_iterator>" } }
 std::cregex_token_iterator *cregex_token_iterator_ptr;
 holder<std::cregex_token_iterator> cregex_token_iterator_holder;
-// { dg-final { whatis-test cregex_token_iterator_holder "holder<std::cregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_token_iterator_holder "holder<std::(__7::)?cregex_token_iterator>" } }
 std::sregex_token_iterator *sregex_token_iterator_ptr;
 holder<std::sregex_token_iterator> sregex_token_iterator_holder;
-// { dg-final { whatis-test sregex_token_iterator_holder "holder<std::sregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_token_iterator_holder "holder<std::(__7::)?sregex_token_iterator>" } }
 std::u16string *u16string_ptr;
 holder<std::u16string> u16string_holder;
-// { dg-final { whatis-test u16string_holder "holder<std::u16string>" } }
+// { dg-final { whatis-regexp-test u16string_holder "holder<std::(__7::)?u16string>" } }
 std::u32string *u32string_ptr;
 holder<std::u32string> u32string_holder;
-// { dg-final { whatis-test u32string_holder "holder<std::u32string>" } }
+// { dg-final { whatis-regexp-test u32string_holder "holder<std::(__7::)?u32string>" } }
 std::minstd_rand0 *minstd_rand0_ptr;
 holder<std::minstd_rand0> minstd_rand0_holder;
-// { dg-final { whatis-test minstd_rand0_holder "holder<std::minstd_rand0>" } }
+// { dg-final { whatis-regexp-test minstd_rand0_holder "holder<std::(__7::)?minstd_rand0>" } }
 std::minstd_rand *minstd_rand_ptr;
 holder<std::minstd_rand> minstd_rand_holder;
-// { dg-final { whatis-test minstd_rand_holder "holder<std::minstd_rand>" } }
+// { dg-final { whatis-regexp-test minstd_rand_holder "holder<std::(__7::)?minstd_rand>" } }
 std::mt19937 *mt19937_ptr;
 holder<std::mt19937> mt19937_holder;
-// { dg-final { whatis-test mt19937_holder "holder<std::mt19937>" } }
+// { dg-final { whatis-regexp-test mt19937_holder "holder<std::(__7::)?mt19937>" } }
 std::mt19937_64 *mt19937_64_ptr;
 holder<std::mt19937_64> mt19937_64_holder;
-// { dg-final { whatis-test mt19937_64_holder "holder<std::mt19937_64>" } }
+// { dg-final { whatis-regexp-test mt19937_64_holder "holder<std::(__7::)?mt19937_64>" } }
 std::ranlux24_base *ranlux24_base_ptr;
 holder<std::ranlux24_base> ranlux24_base_holder;
-// { dg-final { whatis-test ranlux24_base_holder "holder<std::ranlux24_base>" } }
+// { dg-final { whatis-regexp-test ranlux24_base_holder "holder<std::(__7::)?ranlux24_base>" } }
 std::ranlux48_base *ranlux48_base_ptr;
 holder<std::ranlux48_base> ranlux48_base_holder;
-// { dg-final { whatis-test ranlux48_base_holder "holder<std::ranlux48_base>" } }
+// { dg-final { whatis-regexp-test ranlux48_base_holder "holder<std::(__7::)?ranlux48_base>" } }
 std::ranlux24 *ranlux24_ptr;
 holder<std::ranlux24> ranlux24_holder;
-// { dg-final { whatis-test ranlux24_holder "holder<std::ranlux24>" } }
+// { dg-final { whatis-regexp-test ranlux24_holder "holder<std::(__7::)?ranlux24>" } }
 std::ranlux48 *ranlux48_ptr;
 holder<std::ranlux48> ranlux48_holder;
-// { dg-final { whatis-test ranlux48_holder "holder<std::ranlux48>" } }
+// { dg-final { whatis-regexp-test ranlux48_holder "holder<std::(__7::)?ranlux48>" } }
 std::knuth_b *knuth_b_ptr;
 holder<std::knuth_b> knuth_b_holder;
-// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
+// { dg-final { whatis-regexp-test knuth_b_holder "holder<std::(__7::)?knuth_b>" } }
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-regexp-test ustring_holder "holder<std::(__7::)?basic_string<unsigned char, std::(__7::)?char_traits<unsigned char>, std::(__7::)?allocator<unsigned char> > >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-regexp-test sstring_holder "holder<std::(__7::)?basic_string<signed char, std::(__7::)?char_traits<signed char>, std::(__7::)?allocator<signed char> > >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
-// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq1_holder "holder<std::(__7::)?vector<std::(__7::)?deque<std::(__7::)?unique_ptr<char>>> >" } }
 
 std::list<std::forward_list<std::unique_ptr<char>>> *seq2_ptr;
 holder< std::list<std::forward_list<std::unique_ptr<char>>> > seq2_holder;
-// { dg-final { whatis-test seq2_holder "holder<std::list<std::forward_list<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq2_holder "holder<std::(__7::)?list<std::(__7::)?forward_list<std::(__7::)?unique_ptr<char>>> >" } }
 
 std::map<int, std::set<int>> *assoc1_ptr;
 holder< std::map<int, std::set<int>> > assoc1_holder;
-// { dg-final { whatis-test assoc1_holder "holder<std::map<int, std::set<int>> >" } }
+// { dg-final { whatis-regexp-test assoc1_holder "holder<std::(__7::)?map<int, std::(__7::)?set<int>> >" } }
 
 std::multimap<int, std::multiset<int>> *assoc2_ptr;
 holder< std::multimap<int, std::multiset<int>> > assoc2_holder;
-// { dg-final { whatis-test assoc2_holder "holder<std::multimap<int, std::multiset<int>> >" } }
+// { dg-final { whatis-regexp-test assoc2_holder "holder<std::(__7::)?multimap<int, std::(__7::)?multiset<int>> >" } }
 
 std::unordered_map<int, std::unordered_set<int>> *unord1_ptr;
 holder< std::unordered_map<int, std::unordered_set<int>> > unord1_holder;
-// { dg-final { whatis-test unord1_holder "holder<std::unordered_map<int, std::unordered_set<int>> >" } }
+// { dg-final { whatis-regexp-test unord1_holder "holder<std::(__7::)?unordered_map<int, std::(__7::)?unordered_set<int>> >" } }
 
 std::unordered_multimap<int, std::unordered_multiset<int>> *unord2_ptr;
 holder< std::unordered_multimap<int, std::unordered_multiset<int>> > unord2_holder;
-// { dg-final { whatis-test unord2_holder "holder<std::unordered_multimap<int, std::unordered_multiset<int>> >" } }
+// { dg-final { whatis-regexp-test unord2_holder "holder<std::(__7::)?unordered_multimap<int, std::(__7::)?unordered_multiset<int>> >" } }
 
 
 int



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-11-28 21:19 Pretty printers for versioned namespace François Dumont
@ 2016-11-29 20:17 ` Jonathan Wakely
  2016-12-01 21:51   ` François Dumont
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2016-11-29 20:17 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 28/11/16 22:19 +0100, François Dumont wrote:
>Hi
>
>    Here is a patch to fix pretty printers when versioned namespace is 
>activated.
>
>    You will see that I have hesitated in making the fix independant 
>of the version being used. In source files you will find (__7::)? 
>patterns while in xmethods.py I chose (__\d+::)? making it ready for 
>__8 and forward. Do you want to generalize one option ? If so which 
>one ?

I don't really mind, but I note that the point of the path
libstdcxx/v6/printers.py was that we'd have different printers for v7,
v8 etc. ... I think it's simpler to keep everything in one place
though. 

>    At the moment version namespace is visible within gdb, it displays 
>for instance 'std::__7::string'. I am pretty sure we could hide it, is 
>it preferable ? I would need some time to do so as I am neither a 
>python nor regex expert.

It's fine to display it.

>    I am not fully happy with the replication in printers.py of 
>StdRbtreeIteratorPrinter and 
>StdExpAnyPrinter(SingleObjContainerPrinter in respectively 
>StdVersionedRbtreeIteratorPrinter and 
>StdExpVerAnyPrinter(SingleObjContainerPrinter just to adapt 2 lines 
>where regex is not an option. We could surely keep only one and pass 
>it '' or '__7'. But as I said I am not a python expert so any help 
>would be appreciated.

We definitely want to avoid that duplication. For
StdRbtreeIteratorPrinter you can just look at 'typename' and see
whether it starts with "std::__7" or not. If it does, you need to lookup
std::__7::_Rb_tree_node<...>, otherwise you need to lookup
std::_Rb_tree_node<...> instead.

For StdExpAnyPrinter just do two replacements: first replace
std::string with the result of gdb.lookup_type('std::string') and then
replace std::__7::string with the result of looking that up. Are you
sure that's even needed though? Does std::__7::string actually appear
in the manager function's name? I would expect it to appear as
std::__7::basic_string<char, std::__7::char_traits<char>, std::__7::allocator<char> > >
which doesn't need to be expanded anyway. So I think you can just
remove your StdExpVerAnyPrinter.


>--- a/libstdc++-v3/testsuite/lib/gdb-test.exp
>+++ b/libstdc++-v3/testsuite/lib/gdb-test.exp
>@@ -74,6 +74,14 @@ proc whatis-test {var result} {
>     lappend gdb_tests $var $result whatis
> }
> 
>+# A test of 'whatis'.  This tests a type rather than a variable through a
>+# regexp.

Please use "regular expression" here rather than "regexp".

>+proc whatis-regexp-test {var result} {
>+    global gdb_tests
>+
>+    lappend gdb_tests $var $result whatisrexp
>+}
>+

And something other than "whatisrexp" e.g. "whatis_regexp" would be
OK, but "rexp" is not a conventional abbreviation.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-11-29 20:17 ` Jonathan Wakely
@ 2016-12-01 21:51   ` François Dumont
  2016-12-02  0:42     ` Jonathan Wakely
  0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2016-12-01 21:51 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2611 bytes --]

On 29/11/2016 21:17, Jonathan Wakely wrote:
> On 28/11/16 22:19 +0100, François Dumont wrote:
>> Hi
>>
>>    Here is a patch to fix pretty printers when versioned namespace is 
>> activated.
>>
>>    You will see that I have hesitated in making the fix independant 
>> of the version being used. In source files you will find (__7::)? 
>> patterns while in xmethods.py I chose (__\d+::)? making it ready for 
>> __8 and forward. Do you want to generalize one option ? If so which 
>> one ?
>
> I don't really mind, but I note that the point of the path
> libstdcxx/v6/printers.py was that we'd have different printers for v7,
> v8 etc. ... I think it's simpler to keep everything in one place
> though.

Ok, I think the folder v6 depends more on a potential gdb api change.

>>    At the moment version namespace is visible within gdb, it displays 
>> for instance 'std::__7::string'. I am pretty sure we could hide it, 
>> is it preferable ? I would need some time to do so as I am neither a 
>> python nor regex expert.
>
> It's fine to display it.
>
>>    I am not fully happy with the replication in printers.py of 
>> StdRbtreeIteratorPrinter and 
>> StdExpAnyPrinter(SingleObjContainerPrinter in respectively 
>> StdVersionedRbtreeIteratorPrinter and 
>> StdExpVerAnyPrinter(SingleObjContainerPrinter just to adapt 2 lines 
>> where regex is not an option. We could surely keep only one and pass 
>> it '' or '__7'. But as I said I am not a python expert so any help 
>> would be appreciated.
>
> We definitely want to avoid that duplication. For
> StdRbtreeIteratorPrinter you can just look at 'typename' and see
> whether it starts with "std::__7" or not. If it does, you need to lookup
> std::__7::_Rb_tree_node<...>, otherwise you need to lookup
> std::_Rb_tree_node<...> instead.
>
> For StdExpAnyPrinter just do two replacements: first replace
> std::string with the result of gdb.lookup_type('std::string') and then
> replace std::__7::string with the result of looking that up. Are you
> sure that's even needed though? Does std::__7::string actually appear
> in the manager function's name? I would expect it to appear as
> std::__7::basic_string<char, std::__7::char_traits<char>, 
> std::__7::allocator<char> > >
> which doesn't need to be expanded anyway. So I think you can just
> remove your StdExpVerAnyPrinter.

We needed the StdExpVerAnyPrinter just because of the loopkup for 
'std::string' which has to be 'std::__7::string'. But I used similar 
technique exposed previously to get rid of it.

So here is the simplified version I plan to test without versioned 
namespace.

François


[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 54356 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index bad42b4..a7c92a6 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -36,6 +36,8 @@ import sys
 # We probably can't do much about this until this GDB PR is addressed:
 # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
 
+vers_nsp = '__7::'
+
 if sys.version_info[0] > 2:
     ### Python 3 stuff
     Iterator = object
@@ -127,9 +129,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(' + vers_nsp + ')?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(' + vers_nsp + ')?tuple<.*>$', impl_type):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -485,7 +487,10 @@ class StdRbtreeIteratorPrinter:
     def __init__ (self, typename, val):
         self.val = val
         valtype = self.val.type.template_argument(0).strip_typedefs()
-        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        if typename.startswith('std::' + vers_nsp):
+            nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+        else:
+            nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
@@ -927,7 +932,6 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
@@ -948,7 +952,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
                 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))
+            if re.match('std::(experimental::)?' + vers_nsp + '.*$', self.typename):
+                strt = gdb.lookup_type('std::' + vers_nsp + 'string')
+            else:
+                strt = gdb.lookup_type('std::string')
+            mgrname = re.sub("std::string(?!\w)", str(strt.strip_typedefs()), m.group(1))
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None
@@ -1031,7 +1039,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = re.match('^std::(' + vers_nsp + ')?_Rb_tree_node.*$', nodetype.name)
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1176,7 +1184,7 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        self.add(base + vers_nsp + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1311,7 +1319,7 @@ def register_type_printers(obj):
     if not _use_type_printing:
         return
 
-    for pfx in ('', 'w'):
+    for pfx in ('', 'w', vers_nsp, vers_nsp + 'w'):
         add_one_type_printer(obj, 'basic_string', pfx + 'string')
         add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view')
         add_one_type_printer(obj, 'basic_ios', pfx + 'ios')
@@ -1342,70 +1350,70 @@ def register_type_printers(obj):
         add_one_type_printer(obj, 'regex_token_iterator',
                                  pfx + 'sregex_token_iterator')
 
-    # Note that we can't have a printer for std::wstreampos, because
-    # it shares the same underlying type as std::streampos.
-    add_one_type_printer(obj, 'fpos', 'streampos')
-    add_one_type_printer(obj, 'basic_string', 'u16string')
-    add_one_type_printer(obj, 'basic_string', 'u32string')
-
-    add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
-    add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
-
-    for dur in ('nanoseconds', 'microseconds', 'milliseconds',
-                'seconds', 'minutes', 'hours'):
-        add_one_type_printer(obj, 'duration', dur)
-
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
-    add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
-
-    # Do not show defaulted template arguments in class templates
-    add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
-
-    add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
-    add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
-    add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
-    add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
-    add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
-    add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
-    add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
-    add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+    for vers in ('', vers_nsp):
+        # Note that we can't have a printer for std::wstreampos, because
+        # it shares the same underlying type as std::streampos.
+        add_one_type_printer(obj, 'fpos', vers + 'streampos')
+        add_one_type_printer(obj, 'basic_string', vers + 'u16string')
+        add_one_type_printer(obj, 'basic_string', vers + 'u32string')
+        add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
+        add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
+
+        for dur in ('nanoseconds', 'microseconds', 'milliseconds',
+                    'seconds', 'minutes', 'hours'):
+            add_one_type_printer(obj, 'duration', vers + dur)
+
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand0')
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937_64')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux24_base')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux48_base')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux24')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux48')
+        add_one_type_printer(obj, 'shuffle_order_engine', vers + 'knuth_b')
+
+        # Do not show defaulted template arguments in class templates
+        add_one_template_type_printer(obj, 'unique_ptr<T>',
+            '%sunique_ptr<(.*), std::%sdefault_delete<\\1 ?> >' % (vers, vers),
+            '%sunique_ptr<{1}>' % vers)
+
+        add_one_template_type_printer(obj, 'deque<T>',
+            '%sdeque<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%sdeque<{1}>' % vers)
+        add_one_template_type_printer(obj, 'forward_list<T>',
+            '%sforward_list<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%sforward_list<{1}>' % vers)
+        add_one_template_type_printer(obj, 'list<T>',
+            '%slist<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%slist<{1}>' % vers)
+        add_one_template_type_printer(obj, 'vector<T>',
+            '%svector<(.*), std::%sallocator<\\1 ?> >' % (vers, vers),
+            '%svector<{1}>' % vers)
+        add_one_template_type_printer(obj, 'map<Key, T>',
+            '%smap<(.*), (.*), std::%sless<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers),
+            '%smap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'multimap<Key, T>',
+            '%smultimap<(.*), (.*), std::%sless<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers),
+            '%smultimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'set<T>',
+            '%sset<(.*), std::%sless<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers),
+            '%sset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'multiset<T>',
+            '%smultiset<(.*), std::%sless<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers),
+            '%smultiset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_map<Key, T>',
+            '%sunordered_map<(.*), (.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers, vers),
+            '%sunordered_map<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
+            '%sunordered_multimap<(.*), (.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<std::%spair<\\1 const, \\2 ?> > >' % (vers, vers, vers, vers, vers),
+            '%sunordered_multimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_set<T>',
+            '%sunordered_set<(.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers, vers),
+            '%sunordered_set<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multiset<T>',
+            '%sunordered_multiset<(.*), std::%shash<\\1 ?>, std::%sequal_to<\\1 ?>, std::%sallocator<\\1 ?> >' % (vers, vers, vers, vers),
+            '%sunordered_multiset<{1}>' % vers)
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
@@ -1439,7 +1447,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer = Printer("libstdc++-v6")
 
     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
+    vers = '(' + vers_nsp + ')?'
     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     container = '(__cxx1998::' + vers + ')?'
 
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index 045b661..4d58663 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -576,9 +576,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -604,7 +604,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
diff --git a/libstdc++-v3/testsuite/lib/gdb-test.exp b/libstdc++-v3/testsuite/lib/gdb-test.exp
index 3ebbf6b..5e1bdf7 100644
--- a/libstdc++-v3/testsuite/lib/gdb-test.exp
+++ b/libstdc++-v3/testsuite/lib/gdb-test.exp
@@ -74,6 +74,14 @@ proc whatis-test {var result} {
     lappend gdb_tests $var $result whatis
 }
 
+# A test of 'whatis'.  This tests a type rather than a variable through a
+# regular expression.
+proc whatis-regexp-test {var result} {
+    global gdb_tests
+
+    lappend gdb_tests $var $result whatis_regexp
+}
+
 # Utility for testing variable values using gdb, invoked via dg-final.
 # Tests all tests indicated by note-test and regexp-test.
 #
@@ -140,10 +148,15 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 	incr count
 	set gdb_var($count) $var
 	set gdb_expected($count) $result
-	if {$kind == "whatis"} {
+	if {$kind == "whatis" || $kind == "whatis_regexp"} {
 	    if {$do_whatis_tests} {
 		set gdb_is_type($count) 1
 		set gdb_command($count) "whatis $var"
+		if {$kind == "whatis"} {
+		    set gdb_is_regexp($count) 0
+		} else {
+		    set gdb_is_regexp($count) 1
+		}
 	    } else {
 	        unsupported "$testname"
 	        close $fd
@@ -179,13 +192,13 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 		if {$expect_out(1,string) != "type"} {
 		    error "gdb failure"
 		}
-		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
-	    } elseif {$gdb_is_regexp($test_counter)} {
+	    }
+
+	    if {$gdb_is_regexp($test_counter)} {
 		set match [regexp -- $gdb_expected($test_counter) $first]
 	    } else {
 		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
+				       $gdb_expected($test_counter)]}]
 	    }
 
 	    if {$match} {
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index 780a4e4..aa3b63b 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -63,77 +63,77 @@ int
 main()
 {
   std::forward_list<int> efl;
-// { dg-final { note-test efl "empty std::forward_list" } }
+// { dg-final { regexp-test efl "empty std::(__7::)?forward_list" } }
 
   std::forward_list<int> &refl = efl;
-// { dg-final { note-test refl "empty std::forward_list" } }
+// { dg-final { regexp-test refl "empty std::(__7::)?forward_list" } }
 
   std::forward_list<int> fl;
   fl.push_front(2);
   fl.push_front(1);
-// { dg-final { note-test fl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test fl {std::(__7::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::forward_list<int> &rfl = fl;
-// { dg-final { note-test rfl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test rfl {std::(__7::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::(__7::)?unordered_map with 0 elements" } }
   std::unordered_map<int, std::string> &reum = eum;
-// { dg-final { note-test reum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test reum "std::(__7::)?unordered_map with 0 elements" } }
 
   std::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::(__7::)?unordered_multimap with 0 elements" } }
   std::unordered_multimap<int, std::string> &reumm = eumm;
-// { dg-final { note-test reumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test reumm "std::(__7::)?unordered_multimap with 0 elements" } }
 
   std::unordered_set<int> eus;
-// { dg-final { note-test eus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::(__7::)?unordered_set with 0 elements" } }
   std::unordered_set<int> &reus = eus;
-// { dg-final { note-test reus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test reus "std::(__7::)?unordered_set with 0 elements" } }
 
   std::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::(__7::)?unordered_multiset with 0 elements" } }
   std::unordered_multiset<int> &reums = eums;
-// { dg-final { note-test reums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test reums "std::(__7::)?unordered_multiset with 0 elements" } }
 
   std::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_map<int, std::string> &ruom = uom;
-// { dg-final { note-test ruom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruom {std::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uomm {std::(__7::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
   std::unordered_multimap<int, std::string> &ruomm = uomm;
-// { dg-final { note-test ruomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruomm {std::(__7::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::(__7::)?unordered_set with 1 elements = {\[0\] = 5}} } }
   std::unordered_set<int> &ruos = uos;
-// { dg-final { note-test ruos {std::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test ruos {std::(__7::)?unordered_set with 1 elements = {\[0\] = 5}} } }
 
   std::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::(__7::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
   std::unordered_multiset<int> &ruoms = uoms;
-// { dg-final { note-test ruoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test ruoms {std::(__7::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
 
   std::unique_ptr<datum> uptr (new datum);
   uptr->s = "hi bob";
   uptr->i = 23;
-// { dg-final { regexp-test uptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test uptr {std::(__7::)?unique_ptr.datum. containing 0x.*} } }
   std::unique_ptr<datum> &ruptr = uptr;
-// { dg-final { regexp-test ruptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test ruptr {std::(__7::)?unique_ptr.datum. containing 0x.*} } }
 
   ExTuple tpl(6,7);
-// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }  
+// { dg-final { regexp-test tpl {std::(__7::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   ExTuple &rtpl = tpl;
-// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } }   
+// { dg-final { regexp-test rtpl {std::(__7::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   placeholder(""); // Mark SPOT
   use(efl);
   use(fl);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
index 96be8c7..c85edc3 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
@@ -44,50 +44,50 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::(__7::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::(__7::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::(__7::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::(__7::)?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::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test om {std::(__7::)?optional<std::(__7::)?map<int, double>> containing std::(__7::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
   optional<std::string> os{ "stringy" };
-// { dg-final { note-test os {std::optional<std::string> = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test os {std::(__7::)?optional<std::(__7::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::any [no contained value]} } }
+// { dg-final { regexp-test a {std::(__7::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::(__7::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::(__7::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::(__7::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::(__7::)?any containing std::(__7::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::(__7::)?any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
   any am = *om;
-// { dg-final { note-test am {std::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test am {std::(__7::)?any containing std::(__7::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   struct S { operator int() { throw 42; }};
   variant<float, int, string_view> v0;
-// { dg-final { note-test v0 {std::variant<float, int, std::string_view> [index 0] = {0}} } }
+// { dg-final { regexp-test v0 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 0\] = {0}} } }
   variant<float, int, string_view> v1{ 0.5f };
-// { dg-final { note-test v1 {std::variant<float, int, std::string_view> [index 0] = {0.5}} } }
+// { dg-final { regexp-test v1 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 0\] = [{]0.5[}]} } }
   variant<float, int, string_view> v2;
   try {
     v2.emplace<1>(S());
   } catch (int) { }
-// { dg-final { note-test v2 {std::variant<float, int, std::string_view> [no contained value]} } }
+// { dg-final { regexp-test v2 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[no contained value\]} } }
   variant<float, int, string_view> v3{ 3 };
-// { dg-final { note-test v3 {std::variant<float, int, std::string_view> [index 1] = {3}} } }
+// { dg-final { regexp-test v3 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 1\] = [{]3[}]} } }
   variant<float, int, string_view> v4{ str };
-// { dg-final { note-test v4 {std::variant<float, int, std::string_view> [index 2] = {"string"}} } }
+// { dg-final { regexp-test v4 {std::(__7::)?variant<float, int, std::(__7::)?string_view> \[index 2\] = {"string"}} } }
   variant<string_view> vref{str};
-// { dg-final { note-test vref {std::variant<std::string_view> [index 0] = {"string"}} } }
+// { dg-final { regexp-test vref {std::(__7::)?variant<std::(__7::)?string_view> \[index 0\] = {"string"}} } }
 
   map<int, string_view> m{ {1, "one"} };
   map<int, string_view>::node_type n0;
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
index 534c55f..18580c7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
@@ -39,33 +39,33 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::experimental::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::experimental::(__7::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::experimental::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::experimental::(__7::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::experimental::(__7::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::experimental::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::experimental::(__7::)?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}} } }
+// { dg-final { regexp-test om {std::experimental::(__7::)?optional<std::(__7::)?map<int, double>> containing std::(__7::)?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"}} } }
+// { dg-final { regexp-test os {std::experimental::(__7::)?optional<std::(__7::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::experimental::any [no contained value]} } }
+// { dg-final { regexp-test a {std::experimental::(__7::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::experimental::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::experimental::(__7::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::experimental::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::experimental::(__7::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::experimental::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::experimental::(__7::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::experimental::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::experimental::(__7::)?any containing std::(__7::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::experimental::(__7::)?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}} } }
+// { dg-final { regexp-test am {std::experimental::(__7::)?any containing std::(__7::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   std::cout << "\n";
   return 0;			// Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
index 9528860..ab9baf9 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
@@ -49,25 +49,25 @@ main()
   typedef std::weak_ptr<int> weak;
 
   shared esp;
-// { dg-final { note-test esp "std::shared_ptr (empty) 0x0" } }
+// { dg-final { regexp-test esp {std::(__7::)?shared_ptr \(empty\) 0x0} } }
   weak ewp1;
-// { dg-final { note-test ewp1 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp1 {std::(__7::)?weak_ptr \(empty\) 0x0} } }
   weak ewp2 = esp;
-// { dg-final { note-test ewp2 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp2 {std::(__7::)?weak_ptr \(empty\) 0x0} } }
 
   shared sp1 = make(0x12345678);
   shared sp2 = sp1;
-// { dg-final { note-test sp1 "std::shared_ptr (count 2, weak 0) 0x12345678" } }
+// { dg-final { regexp-test sp1 {std::(__7::)?shared_ptr \(count 2, weak 0\) 0x12345678} } }
 
   shared sp3 = make(0x12344321);
   weak sp4 = sp3;
   weak wp1 = sp3;
-// { dg-final { note-test wp1 "std::weak_ptr (count 1, weak 2) 0x12344321" } }
+// { dg-final { regexp-test wp1 {std::(__7::)?weak_ptr \(count 1, weak 2\) 0x12344321} } }
 
   shared sp5 = make(0x56788765);
   weak wp2 = sp5;
   sp5.reset();
-// { dg-final { note-test wp2 "std::weak_ptr (expired, weak 1) 0x56788765" } }
+// { dg-final { regexp-test wp2 {std::(__7::)?weak_ptr \(expired, weak 1\) 0x56788765} } }
 
   placeholder(""); // Mark SPOT
   use(esp);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
index 5f98b25..edf1735 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__7::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__7::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__7::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,7 +68,7 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__7::)?map with 1 elements = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
@@ -78,12 +78,12 @@ main()
   intset.insert(2);
   intset.insert(3);
   const std::set<int> const_intset = intset;
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__7::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__7::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
index 97a57ef..fa3e36d 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__7::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__7::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__7::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,19 +68,19 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__7::)?map with 1 elements = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
   // PR 67440
   const std::set<int> const_intset = {2, 3};
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__7::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__7::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
index 52dca4d..0a87dd9 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
@@ -51,31 +51,31 @@ int
 main()
 {
   std::tr1::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::tr1::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::tr1::(__7::)?unordered_map with 0 elements" } }
   std::tr1::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::tr1::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::tr1::(__7::)?unordered_multimap with 0 elements" } }
   std::tr1::unordered_set<int> eus;
-// { dg-final { note-test eus "std::tr1::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::tr1::(__7::)?unordered_set with 0 elements" } }
   std::tr1::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::tr1::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::tr1::(__7::)?unordered_multiset with 0 elements" } }
 
   std::tr1::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::tr1::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::tr1::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::tr1::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::tr1::unordered_multimap with 2 elements = {[5] = "three", [5] = "seven"}} } }
+// { dg-final { regexp-test uomm {std::tr1::(__7::)?unordered_multimap with 2 elements = {\[5\] = "three", \[5\] = "seven"}} } }
 
   std::tr1::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::tr1::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::tr1::(__7::)?unordered_set with 1 elements = {\[0\] = 5}} } }
 
   std::tr1::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::tr1::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::tr1::(__7::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
 
   placeholder(""); // Mark SPOT
   use(eum);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 3f79f92..f440692 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -60,141 +60,141 @@ typedef std::basic_string<unsigned char> ustring;
 
 std::string *string_ptr;
 holder<std::string> string_holder;
-// { dg-final { whatis-test string_holder "holder<std::string>" } }
+// { dg-final { whatis-regexp-test string_holder "holder<std::(__7::)?string>" } }
 std::ios *ios_ptr;
 holder<std::ios> ios_holder;
-// { dg-final { whatis-test ios_holder "holder<std::ios>" } }
+// { dg-final { whatis-regexp-test ios_holder "holder<std::(__7::)?ios>" } }
 std::streambuf *streambuf_ptr;
 holder<std::streambuf> streambuf_holder;
-// { dg-final { whatis-test streambuf_holder "holder<std::streambuf>" } }
+// { dg-final { whatis-regexp-test streambuf_holder "holder<std::(__7::)?streambuf>" } }
 std::istream *istream_ptr;
 holder<std::istream> istream_holder;
-// { dg-final { whatis-test istream_holder "holder<std::istream>" } }
+// { dg-final { whatis-regexp-test istream_holder "holder<std::(__7::)?istream>" } }
 std::ostream *ostream_ptr;
 holder<std::ostream> ostream_holder;
-// { dg-final { whatis-test ostream_holder "holder<std::ostream>" } }
+// { dg-final { whatis-regexp-test ostream_holder "holder<std::(__7::)?ostream>" } }
 std::iostream *iostream_ptr;
 holder<std::iostream> iostream_holder;
-// { dg-final { whatis-test iostream_holder "holder<std::iostream>" } }
+// { dg-final { whatis-regexp-test iostream_holder "holder<std::(__7::)?iostream>" } }
 std::stringbuf *stringbuf_ptr;
 holder<std::stringbuf> stringbuf_holder;
-// { dg-final { whatis-test stringbuf_holder "holder<std::stringbuf>" } }
+// { dg-final { whatis-regexp-test stringbuf_holder "holder<std::(__7::)?stringbuf>" } }
 std::istringstream *istringstream_ptr;
 holder<std::istringstream> istringstream_holder;
-// { dg-final { whatis-test istringstream_holder "holder<std::istringstream>" } }
+// { dg-final { whatis-regexp-test istringstream_holder "holder<std::(__7::)?istringstream>" } }
 std::ostringstream *ostringstream_ptr;
 holder<std::ostringstream> ostringstream_holder;
-// { dg-final { whatis-test ostringstream_holder "holder<std::ostringstream>" } }
+// { dg-final { whatis-regexp-test ostringstream_holder "holder<std::(__7::)?ostringstream>" } }
 std::stringstream *stringstream_ptr;
 holder<std::stringstream> stringstream_holder;
-// { dg-final { whatis-test stringstream_holder "holder<std::stringstream>" } }
+// { dg-final { whatis-regexp-test stringstream_holder "holder<std::(__7::)?stringstream>" } }
 std::filebuf *filebuf_ptr;
 holder<std::filebuf> filebuf_holder;
-// { dg-final { whatis-test filebuf_holder "holder<std::filebuf>" } }
+// { dg-final { whatis-regexp-test filebuf_holder "holder<std::(__7::)?filebuf>" } }
 std::ifstream *ifstream_ptr;
 holder<std::ifstream> ifstream_holder;
-// { dg-final { whatis-test ifstream_holder "holder<std::ifstream>" } }
+// { dg-final { whatis-regexp-test ifstream_holder "holder<std::(__7::)?ifstream>" } }
 std::ofstream *ofstream_ptr;
 holder<std::ofstream> ofstream_holder;
-// { dg-final { whatis-test ofstream_holder "holder<std::ofstream>" } }
+// { dg-final { whatis-regexp-test ofstream_holder "holder<std::(__7::)?ofstream>" } }
 std::fstream *fstream_ptr;
 holder<std::fstream> fstream_holder;
-// { dg-final { whatis-test fstream_holder "holder<std::fstream>" } }
+// { dg-final { whatis-regexp-test fstream_holder "holder<std::(__7::)?fstream>" } }
 std::streampos *streampos_ptr;
 holder<std::streampos> streampos_holder;
-// { dg-final { whatis-test streampos_holder "holder<std::streampos>" } }
+// { dg-final { whatis-regexp-test streampos_holder "holder<std::(__7::)?streampos>" } }
 std::regex *regex_ptr;
 holder<std::regex> regex_holder;
-// { dg-final { whatis-test regex_holder "holder<std::regex>" } }
+// { dg-final { whatis-regexp-test regex_holder "holder<std::(__7::)?regex>" } }
 std::csub_match *csub_match_ptr;
 holder<std::csub_match> csub_match_holder;
-// { dg-final { whatis-test csub_match_holder "holder<std::csub_match>" } }
+// { dg-final { whatis-regexp-test csub_match_holder "holder<std::(__7::)?csub_match>" } }
 std::ssub_match *ssub_match_ptr;
 holder<std::ssub_match> ssub_match_holder;
-// { dg-final { whatis-test ssub_match_holder "holder<std::ssub_match>" } }
+// { dg-final { whatis-regexp-test ssub_match_holder "holder<std::(__7::)?ssub_match>" } }
 std::cmatch *cmatch_ptr;
 holder<std::cmatch> cmatch_holder;
-// { dg-final { whatis-test cmatch_holder "holder<std::cmatch>" } }
+// { dg-final { whatis-regexp-test cmatch_holder "holder<std::(__7::)?cmatch>" } }
 std::smatch *smatch_ptr;
 holder<std::smatch> smatch_holder;
-// { dg-final { whatis-test smatch_holder "holder<std::smatch>" } }
+// { dg-final { whatis-regexp-test smatch_holder "holder<std::(__7::)?smatch>" } }
 std::cregex_iterator *cregex_iterator_ptr;
 holder<std::cregex_iterator> cregex_iterator_holder;
-// { dg-final { whatis-test cregex_iterator_holder "holder<std::cregex_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_iterator_holder "holder<std::(__7::)?cregex_iterator>" } }
 std::sregex_iterator *sregex_iterator_ptr;
 holder<std::sregex_iterator> sregex_iterator_holder;
-// { dg-final { whatis-test sregex_iterator_holder "holder<std::sregex_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_iterator_holder "holder<std::(__7::)?sregex_iterator>" } }
 std::cregex_token_iterator *cregex_token_iterator_ptr;
 holder<std::cregex_token_iterator> cregex_token_iterator_holder;
-// { dg-final { whatis-test cregex_token_iterator_holder "holder<std::cregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_token_iterator_holder "holder<std::(__7::)?cregex_token_iterator>" } }
 std::sregex_token_iterator *sregex_token_iterator_ptr;
 holder<std::sregex_token_iterator> sregex_token_iterator_holder;
-// { dg-final { whatis-test sregex_token_iterator_holder "holder<std::sregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_token_iterator_holder "holder<std::(__7::)?sregex_token_iterator>" } }
 std::u16string *u16string_ptr;
 holder<std::u16string> u16string_holder;
-// { dg-final { whatis-test u16string_holder "holder<std::u16string>" } }
+// { dg-final { whatis-regexp-test u16string_holder "holder<std::(__7::)?u16string>" } }
 std::u32string *u32string_ptr;
 holder<std::u32string> u32string_holder;
-// { dg-final { whatis-test u32string_holder "holder<std::u32string>" } }
+// { dg-final { whatis-regexp-test u32string_holder "holder<std::(__7::)?u32string>" } }
 std::minstd_rand0 *minstd_rand0_ptr;
 holder<std::minstd_rand0> minstd_rand0_holder;
-// { dg-final { whatis-test minstd_rand0_holder "holder<std::minstd_rand0>" } }
+// { dg-final { whatis-regexp-test minstd_rand0_holder "holder<std::(__7::)?minstd_rand0>" } }
 std::minstd_rand *minstd_rand_ptr;
 holder<std::minstd_rand> minstd_rand_holder;
-// { dg-final { whatis-test minstd_rand_holder "holder<std::minstd_rand>" } }
+// { dg-final { whatis-regexp-test minstd_rand_holder "holder<std::(__7::)?minstd_rand>" } }
 std::mt19937 *mt19937_ptr;
 holder<std::mt19937> mt19937_holder;
-// { dg-final { whatis-test mt19937_holder "holder<std::mt19937>" } }
+// { dg-final { whatis-regexp-test mt19937_holder "holder<std::(__7::)?mt19937>" } }
 std::mt19937_64 *mt19937_64_ptr;
 holder<std::mt19937_64> mt19937_64_holder;
-// { dg-final { whatis-test mt19937_64_holder "holder<std::mt19937_64>" } }
+// { dg-final { whatis-regexp-test mt19937_64_holder "holder<std::(__7::)?mt19937_64>" } }
 std::ranlux24_base *ranlux24_base_ptr;
 holder<std::ranlux24_base> ranlux24_base_holder;
-// { dg-final { whatis-test ranlux24_base_holder "holder<std::ranlux24_base>" } }
+// { dg-final { whatis-regexp-test ranlux24_base_holder "holder<std::(__7::)?ranlux24_base>" } }
 std::ranlux48_base *ranlux48_base_ptr;
 holder<std::ranlux48_base> ranlux48_base_holder;
-// { dg-final { whatis-test ranlux48_base_holder "holder<std::ranlux48_base>" } }
+// { dg-final { whatis-regexp-test ranlux48_base_holder "holder<std::(__7::)?ranlux48_base>" } }
 std::ranlux24 *ranlux24_ptr;
 holder<std::ranlux24> ranlux24_holder;
-// { dg-final { whatis-test ranlux24_holder "holder<std::ranlux24>" } }
+// { dg-final { whatis-regexp-test ranlux24_holder "holder<std::(__7::)?ranlux24>" } }
 std::ranlux48 *ranlux48_ptr;
 holder<std::ranlux48> ranlux48_holder;
-// { dg-final { whatis-test ranlux48_holder "holder<std::ranlux48>" } }
+// { dg-final { whatis-regexp-test ranlux48_holder "holder<std::(__7::)?ranlux48>" } }
 std::knuth_b *knuth_b_ptr;
 holder<std::knuth_b> knuth_b_holder;
-// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
+// { dg-final { whatis-regexp-test knuth_b_holder "holder<std::(__7::)?knuth_b>" } }
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-regexp-test ustring_holder "holder<std::(__7::)?basic_string<unsigned char, std::(__7::)?char_traits<unsigned char>, std::(__7::)?allocator<unsigned char> > >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-regexp-test sstring_holder "holder<std::(__7::)?basic_string<signed char, std::(__7::)?char_traits<signed char>, std::(__7::)?allocator<signed char> > >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
-// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq1_holder "holder<std::(__7::)?vector<std::(__7::)?deque<std::(__7::)?unique_ptr<char>>> >" } }
 
 std::list<std::forward_list<std::unique_ptr<char>>> *seq2_ptr;
 holder< std::list<std::forward_list<std::unique_ptr<char>>> > seq2_holder;
-// { dg-final { whatis-test seq2_holder "holder<std::list<std::forward_list<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq2_holder "holder<std::(__7::)?list<std::(__7::)?forward_list<std::(__7::)?unique_ptr<char>>> >" } }
 
 std::map<int, std::set<int>> *assoc1_ptr;
 holder< std::map<int, std::set<int>> > assoc1_holder;
-// { dg-final { whatis-test assoc1_holder "holder<std::map<int, std::set<int>> >" } }
+// { dg-final { whatis-regexp-test assoc1_holder "holder<std::(__7::)?map<int, std::(__7::)?set<int>> >" } }
 
 std::multimap<int, std::multiset<int>> *assoc2_ptr;
 holder< std::multimap<int, std::multiset<int>> > assoc2_holder;
-// { dg-final { whatis-test assoc2_holder "holder<std::multimap<int, std::multiset<int>> >" } }
+// { dg-final { whatis-regexp-test assoc2_holder "holder<std::(__7::)?multimap<int, std::(__7::)?multiset<int>> >" } }
 
 std::unordered_map<int, std::unordered_set<int>> *unord1_ptr;
 holder< std::unordered_map<int, std::unordered_set<int>> > unord1_holder;
-// { dg-final { whatis-test unord1_holder "holder<std::unordered_map<int, std::unordered_set<int>> >" } }
+// { dg-final { whatis-regexp-test unord1_holder "holder<std::(__7::)?unordered_map<int, std::(__7::)?unordered_set<int>> >" } }
 
 std::unordered_multimap<int, std::unordered_multiset<int>> *unord2_ptr;
 holder< std::unordered_multimap<int, std::unordered_multiset<int>> > unord2_holder;
-// { dg-final { whatis-test unord2_holder "holder<std::unordered_multimap<int, std::unordered_multiset<int>> >" } }
+// { dg-final { whatis-regexp-test unord2_holder "holder<std::(__7::)?unordered_multimap<int, std::(__7::)?unordered_multiset<int>> >" } }
 
 
 int

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-01 21:51   ` François Dumont
@ 2016-12-02  0:42     ` Jonathan Wakely
  2016-12-09 12:56       ` François Dumont
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2016-12-02  0:42 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 01/12/16 22:51 +0100, François Dumont wrote:
>On 29/11/2016 21:17, Jonathan Wakely wrote:
>>On 28/11/16 22:19 +0100, François Dumont wrote:
>>>   I am not fully happy with the replication in printers.py of 
>>>StdRbtreeIteratorPrinter and 
>>>StdExpAnyPrinter(SingleObjContainerPrinter in respectively 
>>>StdVersionedRbtreeIteratorPrinter and 
>>>StdExpVerAnyPrinter(SingleObjContainerPrinter just to adapt 2 
>>>lines where regex is not an option. We could surely keep only one 
>>>and pass it '' or '__7'. But as I said I am not a python expert so 
>>>any help would be appreciated.
>>
>>We definitely want to avoid that duplication. For
>>StdRbtreeIteratorPrinter you can just look at 'typename' and see
>>whether it starts with "std::__7" or not. If it does, you need to lookup
>>std::__7::_Rb_tree_node<...>, otherwise you need to lookup
>>std::_Rb_tree_node<...> instead.
>>
>>For StdExpAnyPrinter just do two replacements: first replace
>>std::string with the result of gdb.lookup_type('std::string') and then
>>replace std::__7::string with the result of looking that up. Are you
>>sure that's even needed though? Does std::__7::string actually appear
>>in the manager function's name? I would expect it to appear as
>>std::__7::basic_string<char, std::__7::char_traits<char>, 
>>std::__7::allocator<char> > >
>>which doesn't need to be expanded anyway. So I think you can just
>>remove your StdExpVerAnyPrinter.
>
>We needed the StdExpVerAnyPrinter just because of the loopkup for 
>'std::string' which has to be 'std::__7::string'. But I used similar 
>technique exposed previously to get rid of it.

But I don't see any std::__7::string in the relevant symbols.  Here's
the manager function for an std:experimental::__7::any storing a
std::__7::string:

std::experimental::fundamentals_v1::__7::any::_Manager_internal<std::__7::basic_string<char, std::__7::char_traits<char>, std::__7::allocator<char> > >::_S_manage(std::experimental::fundamentals_v1::__7::any::_Op, >std::experimental::fundamentals_v1::__7::any const*, >std::experimental::fundamentals_v1::__7::any::_Arg*)

Since this has no std::__7::string it doesn't need to be substituted.

Do any tests fail without the change to StdExpAnyPrinter? Which ones?

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-02  0:42     ` Jonathan Wakely
@ 2016-12-09 12:56       ` François Dumont
  2016-12-09 15:18         ` Jonathan Wakely
  0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2016-12-09 12:56 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2256 bytes --]

On 02/12/2016 01:41, Jonathan Wakely wrote:
> On 01/12/16 22:51 +0100, François Dumont wrote:
>> We needed the StdExpVerAnyPrinter just because of the loopkup for 
>> 'std::string' which has to be 'std::__7::string'. But I used similar 
>> technique exposed previously to get rid of it.
>
> But I don't see any std::__7::string in the relevant symbols. Here's
> the manager function for an std:experimental::__7::any storing a
> std::__7::string:
>
> std::experimental::fundamentals_v1::__7::any::_Manager_internal<std::__7::basic_string<char, 
> std::__7::char_traits<char>, std::__7::allocator<char> > 
> >::_S_manage(std::experimental::fundamentals_v1::__7::any::_Op, 
> >std::experimental::fundamentals_v1::__7::any const*, 
> >std::experimental::fundamentals_v1::__7::any::_Arg*)
>
> Since this has no std::__7::string it doesn't need to be substituted.
>
> Do any tests fail without the change to StdExpAnyPrinter? Which ones?
>
>
Yes, tests involving std::any are failing because of the std::string lookup:

Python Exception <class 'gdb.error'> No type named std::string.:
skipping: Python Exception <class 'gdb.error'> No type named std::string.:
Python Exception <class 'gdb.error'> No type named std::string.:
$9 = {_M_manager = 0x4046f4 
<std::__7::any::_Manager_internal<bool>::_S_manage(std::__7::any::_Op, 
std::__7::any const*, std::__7::any::_Arg*)>, _M_storage = {_M_ptr = 
0x0skipping:
Python Exception <class 'gdb.error'> No type named std::string.:
, _M_buffer = {__data = "\000\000\000\000\000\000\000", __align = {<No 
data fields>}}}}
got: $9 = {_M_manager = 0x4046f4 
<std::__7::any::_Manager_internal<bool>::_S_manage(std::__7::any::_Op, 
std::__7::any const*, std::__7::any::_Arg*)>, _M_storage = {_M_ptr = 
0x0, _M_
buffer = {__data = "\000\000\000\000\000\000\000", __align = {<No data 
fields>}}}}
FAIL: libstdc++-prettyprinters/cxx17.cc print ab

This lookup is needed to correctly handle std::any<std::string>. As 
stated in the comment:

             # FIXME need to expand 'std::string' so that 
gdb.lookup_type works

But I don't know how to fix this so for the moment I just adapt it to 
correctly handle std::__7::string.

Here is my latest version tested with an without version namespace.

Ok to commit ?

François


[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 54310 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index ff428e8..f2d5632 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -36,6 +36,8 @@ import sys
 # We probably can't do much about this until this GDB PR is addressed:
 # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
 
+vers_nsp = '__7::'
+
 if sys.version_info[0] > 2:
     ### Python 3 stuff
     Iterator = object
@@ -127,9 +129,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(' + vers_nsp + ')?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(' + vers_nsp + ')?tuple<.*>$', impl_type):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -485,7 +487,10 @@ class StdRbtreeIteratorPrinter:
     def __init__ (self, typename, val):
         self.val = val
         valtype = self.val.type.template_argument(0).strip_typedefs()
-        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        if typename.startswith('std::' + vers_nsp):
+            nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+        else:
+            nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
@@ -927,7 +932,6 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
@@ -948,7 +952,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
                 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))
+            if typename.startswith('std::' + vers_nsp):
+                strt = gdb.lookup_type('std::' + vers_nsp + 'string')
+            else:
+                strt = gdb.lookup_type('std::string')
+            mgrname = re.sub("std::string(?!\w)", str(strt.strip_typedefs()), m.group(1))
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None
@@ -1031,7 +1039,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = re.match('^std::(' + vers_nsp + ')?_Rb_tree_node.*$', nodetype.name)
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1176,7 +1184,7 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        self.add(base + vers_nsp + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1311,7 +1319,7 @@ def register_type_printers(obj):
     if not _use_type_printing:
         return
 
-    for pfx in ('', 'w'):
+    for pfx in ('', 'w', vers_nsp, vers_nsp + 'w'):
         add_one_type_printer(obj, 'basic_string', pfx + 'string')
         add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view')
         add_one_type_printer(obj, 'basic_ios', pfx + 'ios')
@@ -1342,70 +1350,70 @@ def register_type_printers(obj):
         add_one_type_printer(obj, 'regex_token_iterator',
                                  pfx + 'sregex_token_iterator')
 
-    # Note that we can't have a printer for std::wstreampos, because
-    # it shares the same underlying type as std::streampos.
-    add_one_type_printer(obj, 'fpos', 'streampos')
-    add_one_type_printer(obj, 'basic_string', 'u16string')
-    add_one_type_printer(obj, 'basic_string', 'u32string')
-
-    add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
-    add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
-
-    for dur in ('nanoseconds', 'microseconds', 'milliseconds',
-                'seconds', 'minutes', 'hours'):
-        add_one_type_printer(obj, 'duration', dur)
-
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
-    add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
-
-    # Do not show defaulted template arguments in class templates
-    add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
-
-    add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
-    add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
-    add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
-    add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
-    add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
-    add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
-    add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
-    add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+    for vers in ('', vers_nsp):
+        # Note that we can't have a printer for std::wstreampos, because
+        # it shares the same underlying type as std::streampos.
+        add_one_type_printer(obj, 'fpos', vers + 'streampos')
+        add_one_type_printer(obj, 'basic_string', vers + 'u16string')
+        add_one_type_printer(obj, 'basic_string', vers + 'u32string')
+        add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
+        add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
+
+        for dur in ('nanoseconds', 'microseconds', 'milliseconds',
+                    'seconds', 'minutes', 'hours'):
+            add_one_type_printer(obj, 'duration', vers + dur)
+
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand0')
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937_64')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux24_base')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux48_base')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux24')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux48')
+        add_one_type_printer(obj, 'shuffle_order_engine', vers + 'knuth_b')
+
+        # Do not show defaulted template arguments in class templates
+        add_one_template_type_printer(obj, 'unique_ptr<T>',
+            '{0}unique_ptr<(.*), std::{0}default_delete<\\1 ?> >'.format(vers),
+            '%sunique_ptr<{1}>' % vers)
+
+        add_one_template_type_printer(obj, 'deque<T>',
+            '{0}deque<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sdeque<{1}>' % vers)
+        add_one_template_type_printer(obj, 'forward_list<T>',
+            '{0}forward_list<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sforward_list<{1}>' % vers)
+        add_one_template_type_printer(obj, 'list<T>',
+            '{0}list<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%slist<{1}>' % vers)
+        add_one_template_type_printer(obj, 'vector<T>',
+            '{0}vector<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%svector<{1}>' % vers)
+        add_one_template_type_printer(obj, 'map<Key, T>',
+            '{0}map<(.*), (.*), std::{0}less<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%smap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'multimap<Key, T>',
+            '{0}multimap<(.*), (.*), std::{0}less<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%smultimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'set<T>',
+            '{0}set<(.*), std::{0}less<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'multiset<T>',
+            '{0}multiset<(.*), std::{0}less<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%smultiset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_map<Key, T>',
+            '{0}unordered_map<(.*), (.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%sunordered_map<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
+            '{0}unordered_multimap<(.*), (.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%sunordered_multimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_set<T>',
+            '{0}unordered_set<(.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sunordered_set<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multiset<T>',
+            '{0}unordered_multiset<(.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sunordered_multiset<{1}>' % vers)
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
@@ -1439,7 +1447,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer = Printer("libstdc++-v6")
 
     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
+    vers = '(' + vers_nsp + ')?'
     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     container = '(__cxx1998::' + vers + ')?'
 
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index 045b661..4d58663 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -576,9 +576,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -604,7 +604,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
diff --git a/libstdc++-v3/testsuite/lib/gdb-test.exp b/libstdc++-v3/testsuite/lib/gdb-test.exp
index 3ebbf6b..5e1bdf7 100644
--- a/libstdc++-v3/testsuite/lib/gdb-test.exp
+++ b/libstdc++-v3/testsuite/lib/gdb-test.exp
@@ -74,6 +74,14 @@ proc whatis-test {var result} {
     lappend gdb_tests $var $result whatis
 }
 
+# A test of 'whatis'.  This tests a type rather than a variable through a
+# regular expression.
+proc whatis-regexp-test {var result} {
+    global gdb_tests
+
+    lappend gdb_tests $var $result whatis_regexp
+}
+
 # Utility for testing variable values using gdb, invoked via dg-final.
 # Tests all tests indicated by note-test and regexp-test.
 #
@@ -140,10 +148,15 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 	incr count
 	set gdb_var($count) $var
 	set gdb_expected($count) $result
-	if {$kind == "whatis"} {
+	if {$kind == "whatis" || $kind == "whatis_regexp"} {
 	    if {$do_whatis_tests} {
 		set gdb_is_type($count) 1
 		set gdb_command($count) "whatis $var"
+		if {$kind == "whatis"} {
+		    set gdb_is_regexp($count) 0
+		} else {
+		    set gdb_is_regexp($count) 1
+		}
 	    } else {
 	        unsupported "$testname"
 	        close $fd
@@ -179,13 +192,13 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 		if {$expect_out(1,string) != "type"} {
 		    error "gdb failure"
 		}
-		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
-	    } elseif {$gdb_is_regexp($test_counter)} {
+	    }
+
+	    if {$gdb_is_regexp($test_counter)} {
 		set match [regexp -- $gdb_expected($test_counter) $first]
 	    } else {
 		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
+				       $gdb_expected($test_counter)]}]
 	    }
 
 	    if {$match} {
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index 780a4e4..a63f426 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -63,77 +63,77 @@ int
 main()
 {
   std::forward_list<int> efl;
-// { dg-final { note-test efl "empty std::forward_list" } }
+// { dg-final { regexp-test efl "empty std::(__\d+::)?forward_list" } }
 
   std::forward_list<int> &refl = efl;
-// { dg-final { note-test refl "empty std::forward_list" } }
+// { dg-final { regexp-test refl "empty std::(__\d+::)?forward_list" } }
 
   std::forward_list<int> fl;
   fl.push_front(2);
   fl.push_front(1);
-// { dg-final { note-test fl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test fl {std::(__\d+::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::forward_list<int> &rfl = fl;
-// { dg-final { note-test rfl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test rfl {std::(__\d+::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::(__\d+::)?unordered_map with 0 elements" } }
   std::unordered_map<int, std::string> &reum = eum;
-// { dg-final { note-test reum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test reum "std::(__\d+::)?unordered_map with 0 elements" } }
 
   std::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::(__\d+::)?unordered_multimap with 0 elements" } }
   std::unordered_multimap<int, std::string> &reumm = eumm;
-// { dg-final { note-test reumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test reumm "std::(__\d+::)?unordered_multimap with 0 elements" } }
 
   std::unordered_set<int> eus;
-// { dg-final { note-test eus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::(__\d+::)?unordered_set with 0 elements" } }
   std::unordered_set<int> &reus = eus;
-// { dg-final { note-test reus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test reus "std::(__\d+::)?unordered_set with 0 elements" } }
 
   std::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::(__\d+::)?unordered_multiset with 0 elements" } }
   std::unordered_multiset<int> &reums = eums;
-// { dg-final { note-test reums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test reums "std::(__\d+::)?unordered_multiset with 0 elements" } }
 
   std::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::(__\d+::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_map<int, std::string> &ruom = uom;
-// { dg-final { note-test ruom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruom {std::(__\d+::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uomm {std::(__\d+::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
   std::unordered_multimap<int, std::string> &ruomm = uomm;
-// { dg-final { note-test ruomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruomm {std::(__\d+::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::(__\d+::)?unordered_set with 1 elements = {\[0\] = 5}} } }
   std::unordered_set<int> &ruos = uos;
-// { dg-final { note-test ruos {std::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test ruos {std::(__\d+::)?unordered_set with 1 elements = {\[0\] = 5}} } }
 
   std::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::(__\d+::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
   std::unordered_multiset<int> &ruoms = uoms;
-// { dg-final { note-test ruoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test ruoms {std::(__\d+::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
 
   std::unique_ptr<datum> uptr (new datum);
   uptr->s = "hi bob";
   uptr->i = 23;
-// { dg-final { regexp-test uptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test uptr {std::(__\d+::)?unique_ptr.datum. containing 0x.*} } }
   std::unique_ptr<datum> &ruptr = uptr;
-// { dg-final { regexp-test ruptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test ruptr {std::(__\d+::)?unique_ptr.datum. containing 0x.*} } }
 
   ExTuple tpl(6,7);
-// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }  
+// { dg-final { regexp-test tpl {std::(__\d+::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   ExTuple &rtpl = tpl;
-// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } }   
+// { dg-final { regexp-test rtpl {std::(__\d+::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   placeholder(""); // Mark SPOT
   use(efl);
   use(fl);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
index 69c16c1..bc72893 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
@@ -44,48 +44,48 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::(__\d+::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::(__\d+::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::(__\d+::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::(__\d+::)?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::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test om {std::(__\d+::)?optional<std::(__\d+::)?map<int, double>> containing std::(__\d+::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
   optional<std::string> os{ "stringy" };
-// { dg-final { note-test os {std::optional<std::string> = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test os {std::(__\d+::)?optional<std::(__\d+::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::any [no contained value]} } }
+// { dg-final { regexp-test a {std::(__\d+::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::(__\d+::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::(__\d+::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::(__\d+::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::(__\d+::)?any containing std::(__\d+::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::(__\d+::)?any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
   any am = *om;
-// { dg-final { note-test am {std::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test am {std::(__\d+::)?any containing std::(__\d+::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   struct S { operator int() { throw 42; }};
   variant<float, int, string_view> v0;
-// { dg-final { note-test v0 {std::variant<float, int, std::string_view> [index 0] = {0}} } }
+// { dg-final { regexp-test v0 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 0\] = {0}} } }
   variant<float, int, string_view> v1{ 0.5f };
-// { dg-final { note-test v1 {std::variant<float, int, std::string_view> [index 0] = {0.5}} } }
+// { dg-final { regexp-test v1 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 0\] = [{]0.5[}]} } }
   variant<float, int, string_view> v2;
   try {
     v2.emplace<1>(S());
   } catch (int) { }
-// { dg-final { note-test v2 {std::variant<float, int, std::string_view> [no contained value]} } }
+// { dg-final { regexp-test v2 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[no contained value\]} } }
   variant<float, int, string_view> v3{ 3 };
-// { dg-final { note-test v3 {std::variant<float, int, std::string_view> [index 1] = {3}} } }
+// { dg-final { regexp-test v3 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 1\] = [{]3[}]} } }
   variant<float, int, string_view> v4{ str };
-// { dg-final { note-test v4 {std::variant<float, int, std::string_view> [index 2] = {"string"}} } }
+// { dg-final { regexp-test v4 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 2\] = {"string"}} } }
 
   map<int, string_view> m{ {1, "one"} };
   map<int, string_view>::node_type n0;
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
index 534c55f..774c708 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
@@ -39,33 +39,33 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::experimental::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::experimental::(__\d+::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::experimental::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::experimental::(__\d+::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::experimental::(__\d+::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::experimental::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::experimental::(__\d+::)?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}} } }
+// { dg-final { regexp-test om {std::experimental::(__\d+::)?optional<std::(__\d+::)?map<int, double>> containing std::(__\d+::)?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"}} } }
+// { dg-final { regexp-test os {std::experimental::(__\d+::)?optional<std::(__\d+::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::experimental::any [no contained value]} } }
+// { dg-final { regexp-test a {std::experimental::(__\d+::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::experimental::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::experimental::(__\d+::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::experimental::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::experimental::(__\d+::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::experimental::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::experimental::(__\d+::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::experimental::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::experimental::(__\d+::)?any containing std::(__\d+::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::experimental::(__\d+::)?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}} } }
+// { dg-final { regexp-test am {std::experimental::(__\d+::)?any containing std::(__\d+::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   std::cout << "\n";
   return 0;			// Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
index 9528860..4e0e8c7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
@@ -49,25 +49,25 @@ main()
   typedef std::weak_ptr<int> weak;
 
   shared esp;
-// { dg-final { note-test esp "std::shared_ptr (empty) 0x0" } }
+// { dg-final { regexp-test esp {std::(__\d+::)?shared_ptr \(empty\) 0x0} } }
   weak ewp1;
-// { dg-final { note-test ewp1 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp1 {std::(__\d+::)?weak_ptr \(empty\) 0x0} } }
   weak ewp2 = esp;
-// { dg-final { note-test ewp2 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp2 {std::(__\d+::)?weak_ptr \(empty\) 0x0} } }
 
   shared sp1 = make(0x12345678);
   shared sp2 = sp1;
-// { dg-final { note-test sp1 "std::shared_ptr (count 2, weak 0) 0x12345678" } }
+// { dg-final { regexp-test sp1 {std::(__\d+::)?shared_ptr \(count 2, weak 0\) 0x12345678} } }
 
   shared sp3 = make(0x12344321);
   weak sp4 = sp3;
   weak wp1 = sp3;
-// { dg-final { note-test wp1 "std::weak_ptr (count 1, weak 2) 0x12344321" } }
+// { dg-final { regexp-test wp1 {std::(__\d+::)?weak_ptr \(count 1, weak 2\) 0x12344321} } }
 
   shared sp5 = make(0x56788765);
   weak wp2 = sp5;
   sp5.reset();
-// { dg-final { note-test wp2 "std::weak_ptr (expired, weak 1) 0x56788765" } }
+// { dg-final { regexp-test wp2 {std::(__\d+::)?weak_ptr \(expired, weak 1\) 0x56788765} } }
 
   placeholder(""); // Mark SPOT
   use(esp);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
index 5f98b25..53a54bd 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__\d+::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__\d+::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__\d+::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,7 +68,7 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__\d+::)?map with 1 elements = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
@@ -78,12 +78,12 @@ main()
   intset.insert(2);
   intset.insert(3);
   const std::set<int> const_intset = intset;
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__\d+::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__\d+::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
index 97a57ef..5b64a97 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__\d+::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__\d+::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__\d+::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,19 +68,19 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__\d+::)?map with 1 elements = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
   // PR 67440
   const std::set<int> const_intset = {2, 3};
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__\d+::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__\d+::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
index 52dca4d..515f7ba 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
@@ -51,31 +51,31 @@ int
 main()
 {
   std::tr1::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::tr1::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::tr1::(__\d+::)?unordered_map with 0 elements" } }
   std::tr1::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::tr1::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::tr1::(__\d+::)?unordered_multimap with 0 elements" } }
   std::tr1::unordered_set<int> eus;
-// { dg-final { note-test eus "std::tr1::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::tr1::(__\d+::)?unordered_set with 0 elements" } }
   std::tr1::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::tr1::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::tr1::(__\d+::)?unordered_multiset with 0 elements" } }
 
   std::tr1::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::tr1::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::tr1::(__\d+::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::tr1::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::tr1::unordered_multimap with 2 elements = {[5] = "three", [5] = "seven"}} } }
+// { dg-final { regexp-test uomm {std::tr1::(__\d+::)?unordered_multimap with 2 elements = {\[5\] = "three", \[5\] = "seven"}} } }
 
   std::tr1::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::tr1::unordered_set with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::tr1::(__\d+::)?unordered_set with 1 elements = {\[0\] = 5}} } }
 
   std::tr1::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::tr1::unordered_multiset with 1 elements = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::tr1::(__\d+::)?unordered_multiset with 1 elements = {\[0\] = 5}} } }
 
   placeholder(""); // Mark SPOT
   use(eum);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 3f79f92..08da1d6 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -60,141 +60,141 @@ typedef std::basic_string<unsigned char> ustring;
 
 std::string *string_ptr;
 holder<std::string> string_holder;
-// { dg-final { whatis-test string_holder "holder<std::string>" } }
+// { dg-final { whatis-regexp-test string_holder "holder<std::(__\d+::)?string>" } }
 std::ios *ios_ptr;
 holder<std::ios> ios_holder;
-// { dg-final { whatis-test ios_holder "holder<std::ios>" } }
+// { dg-final { whatis-regexp-test ios_holder "holder<std::(__\d+::)?ios>" } }
 std::streambuf *streambuf_ptr;
 holder<std::streambuf> streambuf_holder;
-// { dg-final { whatis-test streambuf_holder "holder<std::streambuf>" } }
+// { dg-final { whatis-regexp-test streambuf_holder "holder<std::(__\d+::)?streambuf>" } }
 std::istream *istream_ptr;
 holder<std::istream> istream_holder;
-// { dg-final { whatis-test istream_holder "holder<std::istream>" } }
+// { dg-final { whatis-regexp-test istream_holder "holder<std::(__\d+::)?istream>" } }
 std::ostream *ostream_ptr;
 holder<std::ostream> ostream_holder;
-// { dg-final { whatis-test ostream_holder "holder<std::ostream>" } }
+// { dg-final { whatis-regexp-test ostream_holder "holder<std::(__\d+::)?ostream>" } }
 std::iostream *iostream_ptr;
 holder<std::iostream> iostream_holder;
-// { dg-final { whatis-test iostream_holder "holder<std::iostream>" } }
+// { dg-final { whatis-regexp-test iostream_holder "holder<std::(__\d+::)?iostream>" } }
 std::stringbuf *stringbuf_ptr;
 holder<std::stringbuf> stringbuf_holder;
-// { dg-final { whatis-test stringbuf_holder "holder<std::stringbuf>" } }
+// { dg-final { whatis-regexp-test stringbuf_holder "holder<std::(__\d+::)?stringbuf>" } }
 std::istringstream *istringstream_ptr;
 holder<std::istringstream> istringstream_holder;
-// { dg-final { whatis-test istringstream_holder "holder<std::istringstream>" } }
+// { dg-final { whatis-regexp-test istringstream_holder "holder<std::(__\d+::)?istringstream>" } }
 std::ostringstream *ostringstream_ptr;
 holder<std::ostringstream> ostringstream_holder;
-// { dg-final { whatis-test ostringstream_holder "holder<std::ostringstream>" } }
+// { dg-final { whatis-regexp-test ostringstream_holder "holder<std::(__\d+::)?ostringstream>" } }
 std::stringstream *stringstream_ptr;
 holder<std::stringstream> stringstream_holder;
-// { dg-final { whatis-test stringstream_holder "holder<std::stringstream>" } }
+// { dg-final { whatis-regexp-test stringstream_holder "holder<std::(__\d+::)?stringstream>" } }
 std::filebuf *filebuf_ptr;
 holder<std::filebuf> filebuf_holder;
-// { dg-final { whatis-test filebuf_holder "holder<std::filebuf>" } }
+// { dg-final { whatis-regexp-test filebuf_holder "holder<std::(__\d+::)?filebuf>" } }
 std::ifstream *ifstream_ptr;
 holder<std::ifstream> ifstream_holder;
-// { dg-final { whatis-test ifstream_holder "holder<std::ifstream>" } }
+// { dg-final { whatis-regexp-test ifstream_holder "holder<std::(__\d+::)?ifstream>" } }
 std::ofstream *ofstream_ptr;
 holder<std::ofstream> ofstream_holder;
-// { dg-final { whatis-test ofstream_holder "holder<std::ofstream>" } }
+// { dg-final { whatis-regexp-test ofstream_holder "holder<std::(__\d+::)?ofstream>" } }
 std::fstream *fstream_ptr;
 holder<std::fstream> fstream_holder;
-// { dg-final { whatis-test fstream_holder "holder<std::fstream>" } }
+// { dg-final { whatis-regexp-test fstream_holder "holder<std::(__\d+::)?fstream>" } }
 std::streampos *streampos_ptr;
 holder<std::streampos> streampos_holder;
-// { dg-final { whatis-test streampos_holder "holder<std::streampos>" } }
+// { dg-final { whatis-regexp-test streampos_holder "holder<std::(__\d+::)?streampos>" } }
 std::regex *regex_ptr;
 holder<std::regex> regex_holder;
-// { dg-final { whatis-test regex_holder "holder<std::regex>" } }
+// { dg-final { whatis-regexp-test regex_holder "holder<std::(__\d+::)?regex>" } }
 std::csub_match *csub_match_ptr;
 holder<std::csub_match> csub_match_holder;
-// { dg-final { whatis-test csub_match_holder "holder<std::csub_match>" } }
+// { dg-final { whatis-regexp-test csub_match_holder "holder<std::(__\d+::)?csub_match>" } }
 std::ssub_match *ssub_match_ptr;
 holder<std::ssub_match> ssub_match_holder;
-// { dg-final { whatis-test ssub_match_holder "holder<std::ssub_match>" } }
+// { dg-final { whatis-regexp-test ssub_match_holder "holder<std::(__\d+::)?ssub_match>" } }
 std::cmatch *cmatch_ptr;
 holder<std::cmatch> cmatch_holder;
-// { dg-final { whatis-test cmatch_holder "holder<std::cmatch>" } }
+// { dg-final { whatis-regexp-test cmatch_holder "holder<std::(__\d+::)?cmatch>" } }
 std::smatch *smatch_ptr;
 holder<std::smatch> smatch_holder;
-// { dg-final { whatis-test smatch_holder "holder<std::smatch>" } }
+// { dg-final { whatis-regexp-test smatch_holder "holder<std::(__\d+::)?smatch>" } }
 std::cregex_iterator *cregex_iterator_ptr;
 holder<std::cregex_iterator> cregex_iterator_holder;
-// { dg-final { whatis-test cregex_iterator_holder "holder<std::cregex_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_iterator_holder "holder<std::(__\d+::)?cregex_iterator>" } }
 std::sregex_iterator *sregex_iterator_ptr;
 holder<std::sregex_iterator> sregex_iterator_holder;
-// { dg-final { whatis-test sregex_iterator_holder "holder<std::sregex_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_iterator_holder "holder<std::(__\d+::)?sregex_iterator>" } }
 std::cregex_token_iterator *cregex_token_iterator_ptr;
 holder<std::cregex_token_iterator> cregex_token_iterator_holder;
-// { dg-final { whatis-test cregex_token_iterator_holder "holder<std::cregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_token_iterator_holder "holder<std::(__\d+::)?cregex_token_iterator>" } }
 std::sregex_token_iterator *sregex_token_iterator_ptr;
 holder<std::sregex_token_iterator> sregex_token_iterator_holder;
-// { dg-final { whatis-test sregex_token_iterator_holder "holder<std::sregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_token_iterator_holder "holder<std::(__\d+::)?sregex_token_iterator>" } }
 std::u16string *u16string_ptr;
 holder<std::u16string> u16string_holder;
-// { dg-final { whatis-test u16string_holder "holder<std::u16string>" } }
+// { dg-final { whatis-regexp-test u16string_holder "holder<std::(__\d+::)?u16string>" } }
 std::u32string *u32string_ptr;
 holder<std::u32string> u32string_holder;
-// { dg-final { whatis-test u32string_holder "holder<std::u32string>" } }
+// { dg-final { whatis-regexp-test u32string_holder "holder<std::(__\d+::)?u32string>" } }
 std::minstd_rand0 *minstd_rand0_ptr;
 holder<std::minstd_rand0> minstd_rand0_holder;
-// { dg-final { whatis-test minstd_rand0_holder "holder<std::minstd_rand0>" } }
+// { dg-final { whatis-regexp-test minstd_rand0_holder "holder<std::(__\d+::)?minstd_rand0>" } }
 std::minstd_rand *minstd_rand_ptr;
 holder<std::minstd_rand> minstd_rand_holder;
-// { dg-final { whatis-test minstd_rand_holder "holder<std::minstd_rand>" } }
+// { dg-final { whatis-regexp-test minstd_rand_holder "holder<std::(__\d+::)?minstd_rand>" } }
 std::mt19937 *mt19937_ptr;
 holder<std::mt19937> mt19937_holder;
-// { dg-final { whatis-test mt19937_holder "holder<std::mt19937>" } }
+// { dg-final { whatis-regexp-test mt19937_holder "holder<std::(__\d+::)?mt19937>" } }
 std::mt19937_64 *mt19937_64_ptr;
 holder<std::mt19937_64> mt19937_64_holder;
-// { dg-final { whatis-test mt19937_64_holder "holder<std::mt19937_64>" } }
+// { dg-final { whatis-regexp-test mt19937_64_holder "holder<std::(__\d+::)?mt19937_64>" } }
 std::ranlux24_base *ranlux24_base_ptr;
 holder<std::ranlux24_base> ranlux24_base_holder;
-// { dg-final { whatis-test ranlux24_base_holder "holder<std::ranlux24_base>" } }
+// { dg-final { whatis-regexp-test ranlux24_base_holder "holder<std::(__\d+::)?ranlux24_base>" } }
 std::ranlux48_base *ranlux48_base_ptr;
 holder<std::ranlux48_base> ranlux48_base_holder;
-// { dg-final { whatis-test ranlux48_base_holder "holder<std::ranlux48_base>" } }
+// { dg-final { whatis-regexp-test ranlux48_base_holder "holder<std::(__\d+::)?ranlux48_base>" } }
 std::ranlux24 *ranlux24_ptr;
 holder<std::ranlux24> ranlux24_holder;
-// { dg-final { whatis-test ranlux24_holder "holder<std::ranlux24>" } }
+// { dg-final { whatis-regexp-test ranlux24_holder "holder<std::(__\d+::)?ranlux24>" } }
 std::ranlux48 *ranlux48_ptr;
 holder<std::ranlux48> ranlux48_holder;
-// { dg-final { whatis-test ranlux48_holder "holder<std::ranlux48>" } }
+// { dg-final { whatis-regexp-test ranlux48_holder "holder<std::(__\d+::)?ranlux48>" } }
 std::knuth_b *knuth_b_ptr;
 holder<std::knuth_b> knuth_b_holder;
-// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
+// { dg-final { whatis-regexp-test knuth_b_holder "holder<std::(__\d+::)?knuth_b>" } }
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-regexp-test ustring_holder "holder<std::(__\d+::)?basic_string<unsigned char, std::(__\d+::)?char_traits<unsigned char>, std::(__\d+::)?allocator<unsigned char> > >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-regexp-test sstring_holder "holder<std::(__\d+::)?basic_string<signed char, std::(__\d+::)?char_traits<signed char>, std::(__\d+::)?allocator<signed char> > >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
-// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq1_holder "holder<std::(__\d+::)?vector<std::(__\d+::)?deque<std::(__\d+::)?unique_ptr<char>>> >" } }
 
 std::list<std::forward_list<std::unique_ptr<char>>> *seq2_ptr;
 holder< std::list<std::forward_list<std::unique_ptr<char>>> > seq2_holder;
-// { dg-final { whatis-test seq2_holder "holder<std::list<std::forward_list<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq2_holder "holder<std::(__\d+::)?list<std::(__\d+::)?forward_list<std::(__\d+::)?unique_ptr<char>>> >" } }
 
 std::map<int, std::set<int>> *assoc1_ptr;
 holder< std::map<int, std::set<int>> > assoc1_holder;
-// { dg-final { whatis-test assoc1_holder "holder<std::map<int, std::set<int>> >" } }
+// { dg-final { whatis-regexp-test assoc1_holder "holder<std::(__\d+::)?map<int, std::(__\d+::)?set<int>> >" } }
 
 std::multimap<int, std::multiset<int>> *assoc2_ptr;
 holder< std::multimap<int, std::multiset<int>> > assoc2_holder;
-// { dg-final { whatis-test assoc2_holder "holder<std::multimap<int, std::multiset<int>> >" } }
+// { dg-final { whatis-regexp-test assoc2_holder "holder<std::(__\d+::)?multimap<int, std::(__\d+::)?multiset<int>> >" } }
 
 std::unordered_map<int, std::unordered_set<int>> *unord1_ptr;
 holder< std::unordered_map<int, std::unordered_set<int>> > unord1_holder;
-// { dg-final { whatis-test unord1_holder "holder<std::unordered_map<int, std::unordered_set<int>> >" } }
+// { dg-final { whatis-regexp-test unord1_holder "holder<std::(__\d+::)?unordered_map<int, std::(__\d+::)?unordered_set<int>> >" } }
 
 std::unordered_multimap<int, std::unordered_multiset<int>> *unord2_ptr;
 holder< std::unordered_multimap<int, std::unordered_multiset<int>> > unord2_holder;
-// { dg-final { whatis-test unord2_holder "holder<std::unordered_multimap<int, std::unordered_multiset<int>> >" } }
+// { dg-final { whatis-regexp-test unord2_holder "holder<std::(__\d+::)?unordered_multimap<int, std::(__\d+::)?unordered_multiset<int>> >" } }
 
 
 int

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-09 12:56       ` François Dumont
@ 2016-12-09 15:18         ` Jonathan Wakely
  2016-12-14 21:53           ` François Dumont
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2016-12-09 15:18 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 09/12/16 13:55 +0100, François Dumont wrote:
>On 02/12/2016 01:41, Jonathan Wakely wrote:
>>On 01/12/16 22:51 +0100, François Dumont wrote:
>>>We needed the StdExpVerAnyPrinter just because of the loopkup for 
>>>'std::string' which has to be 'std::__7::string'. But I used 
>>>similar technique exposed previously to get rid of it.
>>
>>But I don't see any std::__7::string in the relevant symbols. Here's
>>the manager function for an std:experimental::__7::any storing a
>>std::__7::string:
>>
>>std::experimental::fundamentals_v1::__7::any::_Manager_internal<std::__7::basic_string<char, 
>>std::__7::char_traits<char>, std::__7::allocator<char> > 
>>>::_S_manage(std::experimental::fundamentals_v1::__7::any::_Op, 
>>>std::experimental::fundamentals_v1::__7::any const*, 
>>>std::experimental::fundamentals_v1::__7::any::_Arg*)
>>
>>Since this has no std::__7::string it doesn't need to be substituted.
>>
>>Do any tests fail without the change to StdExpAnyPrinter? Which ones?
>>
>>
>Yes, tests involving std::any are failing because of the std::string lookup:
>
>Python Exception <class 'gdb.error'> No type named std::string.:
>skipping: Python Exception <class 'gdb.error'> No type named std::string.:
>Python Exception <class 'gdb.error'> No type named std::string.:
>$9 = {_M_manager = 0x4046f4 
><std::__7::any::_Manager_internal<bool>::_S_manage(std::__7::any::_Op, 
>std::__7::any const*, std::__7::any::_Arg*)>, _M_storage = {_M_ptr = 
>0x0skipping:
>Python Exception <class 'gdb.error'> No type named std::string.:
>, _M_buffer = {__data = "\000\000\000\000\000\000\000", __align = {<No 
>data fields>}}}}
>got: $9 = {_M_manager = 0x4046f4 
><std::__7::any::_Manager_internal<bool>::_S_manage(std::__7::any::_Op, 
>std::__7::any const*, std::__7::any::_Arg*)>, _M_storage = {_M_ptr = 
>0x0, _M_
>buffer = {__data = "\000\000\000\000\000\000\000", __align = {<No data 
>fields>}}}}
>FAIL: libstdc++-prettyprinters/cxx17.cc print ab
>
>This lookup is needed to correctly handle std::any<std::string>. As 
>stated in the comment:
>
>            # FIXME need to expand 'std::string' so that 
>gdb.lookup_type works

Right, it's needed to handle std::any<std::string>.

If you're using the versioned namespace then you're not using that
type, you're using std::__7::any<std::__7::string> instead.

So you don't need to expand std::string, because it isn't there.

And you also don't need to expand std::__7::string, because that isn't
there either.

>But I don't know how to fix this so for the moment I just adapt it to 
>correctly handle std::__7::string.

But that's not correct. Please try to understand the point I'm making:
The name "std::__7::string" does not appear in a symbol name.  So your
change to replace occurrences of that name is WRONG. We don't need to
replace something that isn't there!

The problem is that lookup for std::string fails in the versioned
namespace mode, so the solution is to not do the lookup.

Doing lookup for a different type and replacing a string that doesn't
need replacing is wrong.

This works for me:

@@ -946,9 +950,10 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
             m = re.match(rx, func.function.name)
             if not m:
                 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))
+            mgrname = m.group(1)
+            if not typename.startswith('std::' + vers_nsp):
+                # 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()), mgrname)
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-09 15:18         ` Jonathan Wakely
@ 2016-12-14 21:53           ` François Dumont
  2016-12-15 11:15             ` Jonathan Wakely
                               ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: François Dumont @ 2016-12-14 21:53 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1883 bytes --]

On 09/12/2016 16:18, Jonathan Wakely wrote:
>
>> But I don't know how to fix this so for the moment I just adapt it to 
>> correctly handle std::__7::string.
>
> But that's not correct. Please try to understand the point I'm making:
> The name "std::__7::string" does not appear in a symbol name.
Ok, the only point I don't get yet is why std::string is a symbol but 
std::__7::string is not. It seems inconsistent.

>
> This works for me:
>
> @@ -946,9 +950,10 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
>             m = re.match(rx, func.function.name)
>             if not m:
>                 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))
> +            mgrname = m.group(1)
> +            if not typename.startswith('std::' + vers_nsp):
> +                # 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()), mgrname)
>
I think it doesn't work in all situations as this code is also used for 
std::experimental::any so typename doesn't start with std::__7:: but 
there is still no std::string symbol.

So I propose:

             mgrname = m.group(1)
             if 'std::string' in mgrname:
                 # 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))

as you will see in attach patch.

I eventually use '__7' explicitely in some pretty printers tests because 
'__\d+' was not working, don't know.

Ok to commit once tests have completed ?

François


[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 54133 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 3a111d7..9aba69a 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -36,6 +36,8 @@ import sys
 # We probably can't do much about this until this GDB PR is addressed:
 # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
 
+vers_nsp = '__7::'
+
 if sys.version_info[0] > 2:
     ### Python 3 stuff
     Iterator = object
@@ -127,9 +129,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(' + vers_nsp + ')?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(' + vers_nsp + ')?tuple<.*>$', impl_type):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -485,7 +487,10 @@ class StdRbtreeIteratorPrinter:
     def __init__ (self, typename, val):
         self.val = val
         valtype = self.val.type.template_argument(0).strip_typedefs()
-        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        if typename.startswith('std::' + vers_nsp):
+            nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+        else:
+            nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
@@ -937,7 +942,6 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
@@ -957,8 +961,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
             if not m:
                 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))
+            mgrname = m.group(1)
+            if 'std::string' in mgrname:
+                # 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))
+
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None
@@ -1041,7 +1048,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = re.match('^std::(' + vers_nsp + ')?_Rb_tree_node.*$', nodetype.name)
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1186,7 +1193,7 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        self.add(base + vers_nsp + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1321,7 +1328,7 @@ def register_type_printers(obj):
     if not _use_type_printing:
         return
 
-    for pfx in ('', 'w'):
+    for pfx in ('', 'w', vers_nsp, vers_nsp + 'w'):
         add_one_type_printer(obj, 'basic_string', pfx + 'string')
         add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view')
         add_one_type_printer(obj, 'basic_ios', pfx + 'ios')
@@ -1352,70 +1359,70 @@ def register_type_printers(obj):
         add_one_type_printer(obj, 'regex_token_iterator',
                                  pfx + 'sregex_token_iterator')
 
-    # Note that we can't have a printer for std::wstreampos, because
-    # it shares the same underlying type as std::streampos.
-    add_one_type_printer(obj, 'fpos', 'streampos')
-    add_one_type_printer(obj, 'basic_string', 'u16string')
-    add_one_type_printer(obj, 'basic_string', 'u32string')
-
-    add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
-    add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
-
-    for dur in ('nanoseconds', 'microseconds', 'milliseconds',
-                'seconds', 'minutes', 'hours'):
-        add_one_type_printer(obj, 'duration', dur)
-
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
-    add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
-    add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
-    add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
-    add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
-    add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
-
-    # Do not show defaulted template arguments in class templates
-    add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
-
-    add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
-    add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
-    add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
-    add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
-    add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
-    add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
-    add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
-    add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+    for vers in ('', vers_nsp):
+        # Note that we can't have a printer for std::wstreampos, because
+        # it shares the same underlying type as std::streampos.
+        add_one_type_printer(obj, 'fpos', vers + 'streampos')
+        add_one_type_printer(obj, 'basic_string', vers + 'u16string')
+        add_one_type_printer(obj, 'basic_string', vers + 'u32string')
+        add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
+        add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
+
+        for dur in ('nanoseconds', 'microseconds', 'milliseconds',
+                    'seconds', 'minutes', 'hours'):
+            add_one_type_printer(obj, 'duration', vers + dur)
+
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand0')
+        add_one_type_printer(obj, 'linear_congruential_engine', vers + 'minstd_rand')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937')
+        add_one_type_printer(obj, 'mersenne_twister_engine', vers + 'mt19937_64')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux24_base')
+        add_one_type_printer(obj, 'subtract_with_carry_engine', vers + 'ranlux48_base')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux24')
+        add_one_type_printer(obj, 'discard_block_engine', vers + 'ranlux48')
+        add_one_type_printer(obj, 'shuffle_order_engine', vers + 'knuth_b')
+
+        # Do not show defaulted template arguments in class templates
+        add_one_template_type_printer(obj, 'unique_ptr<T>',
+            '{0}unique_ptr<(.*), std::{0}default_delete<\\1 ?> >'.format(vers),
+            '%sunique_ptr<{1}>' % vers)
+
+        add_one_template_type_printer(obj, 'deque<T>',
+            '{0}deque<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sdeque<{1}>' % vers)
+        add_one_template_type_printer(obj, 'forward_list<T>',
+            '{0}forward_list<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sforward_list<{1}>' % vers)
+        add_one_template_type_printer(obj, 'list<T>',
+            '{0}list<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%slist<{1}>' % vers)
+        add_one_template_type_printer(obj, 'vector<T>',
+            '{0}vector<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
+            '%svector<{1}>' % vers)
+        add_one_template_type_printer(obj, 'map<Key, T>',
+            '{0}map<(.*), (.*), std::{0}less<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%smap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'multimap<Key, T>',
+            '{0}multimap<(.*), (.*), std::{0}less<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%smultimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'set<T>',
+            '{0}set<(.*), std::{0}less<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'multiset<T>',
+            '{0}multiset<(.*), std::{0}less<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%smultiset<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_map<Key, T>',
+            '{0}unordered_map<(.*), (.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%sunordered_map<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
+            '{0}unordered_multimap<(.*), (.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
+            '%sunordered_multimap<{1}, {2}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_set<T>',
+            '{0}unordered_set<(.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sunordered_set<{1}>' % vers)
+        add_one_template_type_printer(obj, 'unordered_multiset<T>',
+            '{0}unordered_multiset<(.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
+            '%sunordered_multiset<{1}>' % vers)
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
@@ -1449,7 +1456,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer = Printer("libstdc++-v6")
 
     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
+    vers = '(' + vers_nsp + ')?'
     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     container = '(__cxx1998::' + vers + ')?'
 
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index 045b661..4d58663 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -576,9 +576,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -604,7 +604,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
diff --git a/libstdc++-v3/testsuite/lib/gdb-test.exp b/libstdc++-v3/testsuite/lib/gdb-test.exp
index 3ebbf6b..5e1bdf7 100644
--- a/libstdc++-v3/testsuite/lib/gdb-test.exp
+++ b/libstdc++-v3/testsuite/lib/gdb-test.exp
@@ -74,6 +74,14 @@ proc whatis-test {var result} {
     lappend gdb_tests $var $result whatis
 }
 
+# A test of 'whatis'.  This tests a type rather than a variable through a
+# regular expression.
+proc whatis-regexp-test {var result} {
+    global gdb_tests
+
+    lappend gdb_tests $var $result whatis_regexp
+}
+
 # Utility for testing variable values using gdb, invoked via dg-final.
 # Tests all tests indicated by note-test and regexp-test.
 #
@@ -140,10 +148,15 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 	incr count
 	set gdb_var($count) $var
 	set gdb_expected($count) $result
-	if {$kind == "whatis"} {
+	if {$kind == "whatis" || $kind == "whatis_regexp"} {
 	    if {$do_whatis_tests} {
 		set gdb_is_type($count) 1
 		set gdb_command($count) "whatis $var"
+		if {$kind == "whatis"} {
+		    set gdb_is_regexp($count) 0
+		} else {
+		    set gdb_is_regexp($count) 1
+		}
 	    } else {
 	        unsupported "$testname"
 	        close $fd
@@ -179,13 +192,13 @@ proc gdb-test { marker {selector {}} {load_xmethods 0} } {
 		if {$expect_out(1,string) != "type"} {
 		    error "gdb failure"
 		}
-		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
-	    } elseif {$gdb_is_regexp($test_counter)} {
+	    }
+
+	    if {$gdb_is_regexp($test_counter)} {
 		set match [regexp -- $gdb_expected($test_counter) $first]
 	    } else {
 		set match [expr {![string compare $first \
-				     $gdb_expected($test_counter)]}]
+				       $gdb_expected($test_counter)]}]
 	    }
 
 	    if {$match} {
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index e02997a..2c2d07e 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -63,77 +63,77 @@ int
 main()
 {
   std::forward_list<int> efl;
-// { dg-final { note-test efl "empty std::forward_list" } }
+// { dg-final { regexp-test efl "empty std::(__7::)?forward_list" } }
 
   std::forward_list<int> &refl = efl;
-// { dg-final { note-test refl "empty std::forward_list" } }
+// { dg-final { regexp-test refl "empty std::(__7::)?forward_list" } }
 
   std::forward_list<int> fl;
   fl.push_front(2);
   fl.push_front(1);
-// { dg-final { note-test fl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test fl {std::(__7::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::forward_list<int> &rfl = fl;
-// { dg-final { note-test rfl {std::forward_list = {[0] = 1, [1] = 2}} } }
+// { dg-final { regexp-test rfl {std::(__7::)?forward_list = {\[0\] = 1, \[1\] = 2}} } }
 
   std::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::(__7::)?unordered_map with 0 elements" } }
   std::unordered_map<int, std::string> &reum = eum;
-// { dg-final { note-test reum "std::unordered_map with 0 elements" } }
+// { dg-final { regexp-test reum "std::(__7::)?unordered_map with 0 elements" } }
 
   std::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::(__7::)?unordered_multimap with 0 elements" } }
   std::unordered_multimap<int, std::string> &reumm = eumm;
-// { dg-final { note-test reumm "std::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test reumm "std::(__7::)?unordered_multimap with 0 elements" } }
 
   std::unordered_set<int> eus;
-// { dg-final { note-test eus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::(__7::)?unordered_set with 0 elements" } }
   std::unordered_set<int> &reus = eus;
-// { dg-final { note-test reus "std::unordered_set with 0 elements" } }
+// { dg-final { regexp-test reus "std::(__7::)?unordered_set with 0 elements" } }
 
   std::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::(__7::)?unordered_multiset with 0 elements" } }
   std::unordered_multiset<int> &reums = eums;
-// { dg-final { note-test reums "std::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test reums "std::(__7::)?unordered_multiset with 0 elements" } }
 
   std::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_map<int, std::string> &ruom = uom;
-// { dg-final { note-test ruom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruom {std::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uomm {std::(__7::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
   std::unordered_multimap<int, std::string> &ruomm = uomm;
-// { dg-final { note-test ruomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test ruomm {std::(__7::)?unordered_multimap with 2 elements = {\[5\] = "seven", \[5\] = "three"}} } }
 
   std::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::unordered_set with 1 element = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::(__7::)?unordered_set with 1 element = {\[0\] = 5}} } }
   std::unordered_set<int> &ruos = uos;
-// { dg-final { note-test ruos {std::unordered_set with 1 element = {[0] = 5}} } }
+// { dg-final { regexp-test ruos {std::(__7::)?unordered_set with 1 element = {\[0\] = 5}} } }
 
   std::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::unordered_multiset with 1 element = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::(__7::)?unordered_multiset with 1 element = {\[0\] = 5}} } }
   std::unordered_multiset<int> &ruoms = uoms;
-// { dg-final { note-test ruoms {std::unordered_multiset with 1 element = {[0] = 5}} } }
+// { dg-final { regexp-test ruoms {std::(__7::)?unordered_multiset with 1 element = {\[0\] = 5}} } }
 
   std::unique_ptr<datum> uptr (new datum);
   uptr->s = "hi bob";
   uptr->i = 23;
-// { dg-final { regexp-test uptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test uptr {std::(__7::)?unique_ptr.datum. containing 0x.*} } }
   std::unique_ptr<datum> &ruptr = uptr;
-// { dg-final { regexp-test ruptr {std::unique_ptr.datum. containing 0x.*} } }
+// { dg-final { regexp-test ruptr {std::(__7::)?unique_ptr.datum. containing 0x.*} } }
 
   ExTuple tpl(6,7);
-// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }  
+// { dg-final { regexp-test tpl {std::(__7::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   ExTuple &rtpl = tpl;
-// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } }   
+// { dg-final { regexp-test rtpl {std::(__7::)?tuple containing = {\[1\] = 6, \[2\] = 7}} } }
   placeholder(""); // Mark SPOT
   use(efl);
   use(fl);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
index 69c16c1..bc72893 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc
@@ -44,48 +44,48 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::(__\d+::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::(__\d+::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::(__\d+::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::(__\d+::)?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::optional<std::map<int, double>> containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test om {std::(__\d+::)?optional<std::(__\d+::)?map<int, double>> containing std::(__\d+::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
   optional<std::string> os{ "stringy" };
-// { dg-final { note-test os {std::optional<std::string> = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test os {std::(__\d+::)?optional<std::(__\d+::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::any [no contained value]} } }
+// { dg-final { regexp-test a {std::(__\d+::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::(__\d+::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::(__\d+::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::(__\d+::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::(__\d+::)?any containing std::(__\d+::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::(__\d+::)?any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
   any am = *om;
-// { dg-final { note-test am {std::any containing std::map with 3 elements = {[1] = 2, [3] = 4, [5] = 6}} } }
+// { dg-final { regexp-test am {std::(__\d+::)?any containing std::(__\d+::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   struct S { operator int() { throw 42; }};
   variant<float, int, string_view> v0;
-// { dg-final { note-test v0 {std::variant<float, int, std::string_view> [index 0] = {0}} } }
+// { dg-final { regexp-test v0 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 0\] = {0}} } }
   variant<float, int, string_view> v1{ 0.5f };
-// { dg-final { note-test v1 {std::variant<float, int, std::string_view> [index 0] = {0.5}} } }
+// { dg-final { regexp-test v1 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 0\] = [{]0.5[}]} } }
   variant<float, int, string_view> v2;
   try {
     v2.emplace<1>(S());
   } catch (int) { }
-// { dg-final { note-test v2 {std::variant<float, int, std::string_view> [no contained value]} } }
+// { dg-final { regexp-test v2 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[no contained value\]} } }
   variant<float, int, string_view> v3{ 3 };
-// { dg-final { note-test v3 {std::variant<float, int, std::string_view> [index 1] = {3}} } }
+// { dg-final { regexp-test v3 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 1\] = [{]3[}]} } }
   variant<float, int, string_view> v4{ str };
-// { dg-final { note-test v4 {std::variant<float, int, std::string_view> [index 2] = {"string"}} } }
+// { dg-final { regexp-test v4 {std::(__\d+::)?variant<float, int, std::(__\d+::)?string_view> \[index 2\] = {"string"}} } }
 
   map<int, string_view> m{ {1, "one"} };
   map<int, string_view>::node_type n0;
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
index 534c55f..774c708 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/libfundts.cc
@@ -39,33 +39,33 @@ main()
 // { dg-final { note-test str "\"string\"" } }
 
   optional<int> o;
-// { dg-final { note-test o {std::experimental::optional<int> [no contained value]} } }
+// { dg-final { regexp-test o {std::experimental::(__\d+::)?optional<int> \[no contained value\]} } }
   optional<bool> ob{false};
-// { dg-final { note-test ob {std::experimental::optional<bool> = {[contained value] = false}} } }
+// { dg-final { regexp-test ob {std::experimental::(__\d+::)?optional<bool> = {\[contained value\] = false}} } }
   optional<int> oi{5};
-// { dg-final { note-test oi {std::experimental::optional<int> = {[contained value] = 5}} } }
+// { dg-final { regexp-test oi {std::experimental::(__\d+::)?optional<int> = {\[contained value\] = 5}} } }
   optional<void*> op{nullptr};
-// { dg-final { note-test op {std::experimental::optional<void *> = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test op {std::experimental::(__\d+::)?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}} } }
+// { dg-final { regexp-test om {std::experimental::(__\d+::)?optional<std::(__\d+::)?map<int, double>> containing std::(__\d+::)?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"}} } }
+// { dg-final { regexp-test os {std::experimental::(__\d+::)?optional<std::(__\d+::)?string> = {\[contained value\] = "stringy"}} } }
 
   any a;
-// { dg-final { note-test a {std::experimental::any [no contained value]} } }
+// { dg-final { regexp-test a {std::experimental::(__\d+::)?any \[no contained value\]} } }
   any ab(false);
-// { dg-final { note-test ab {std::experimental::any containing bool = {[contained value] = false}} } }
+// { dg-final { regexp-test ab {std::experimental::(__\d+::)?any containing bool = {\[contained value\] = false}} } }
   any ai(6);
-// { dg-final { note-test ai {std::experimental::any containing int = {[contained value] = 6}} } }
+// { dg-final { regexp-test ai {std::experimental::(__\d+::)?any containing int = {\[contained value\] = 6}} } }
   any ap = (void*)nullptr;
-// { dg-final { note-test ap {std::experimental::any containing void * = {[contained value] = 0x0}} } }
+// { dg-final { regexp-test ap {std::experimental::(__\d+::)?any containing void \* = {\[contained value\] = 0x0}} } }
   any as = *os;
-// { dg-final { note-test as {std::experimental::any containing std::string = {[contained value] = "stringy"}} } }
+// { dg-final { regexp-test as {std::experimental::(__\d+::)?any containing std::(__\d+::)?string = {\[contained value\] = "stringy"}} } }
   any as2("stringiest");
-// { dg-final { regexp-test as2 {std::experimental::any containing const char \* = {\[contained value\] = 0x[[:xdigit:]]+ "stringiest"}} } }
+// { dg-final { regexp-test as2 {std::experimental::(__\d+::)?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}} } }
+// { dg-final { regexp-test am {std::experimental::(__\d+::)?any containing std::(__\d+::)?map with 3 elements = {\[1\] = 2, \[3\] = 4, \[5\] = 6}} } }
 
   std::cout << "\n";
   return 0;			// Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
index 9528860..4e0e8c7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/shared_ptr.cc
@@ -49,25 +49,25 @@ main()
   typedef std::weak_ptr<int> weak;
 
   shared esp;
-// { dg-final { note-test esp "std::shared_ptr (empty) 0x0" } }
+// { dg-final { regexp-test esp {std::(__\d+::)?shared_ptr \(empty\) 0x0} } }
   weak ewp1;
-// { dg-final { note-test ewp1 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp1 {std::(__\d+::)?weak_ptr \(empty\) 0x0} } }
   weak ewp2 = esp;
-// { dg-final { note-test ewp2 "std::weak_ptr (empty) 0x0" } }
+// { dg-final { regexp-test ewp2 {std::(__\d+::)?weak_ptr \(empty\) 0x0} } }
 
   shared sp1 = make(0x12345678);
   shared sp2 = sp1;
-// { dg-final { note-test sp1 "std::shared_ptr (count 2, weak 0) 0x12345678" } }
+// { dg-final { regexp-test sp1 {std::(__\d+::)?shared_ptr \(count 2, weak 0\) 0x12345678} } }
 
   shared sp3 = make(0x12344321);
   weak sp4 = sp3;
   weak wp1 = sp3;
-// { dg-final { note-test wp1 "std::weak_ptr (count 1, weak 2) 0x12344321" } }
+// { dg-final { regexp-test wp1 {std::(__\d+::)?weak_ptr \(count 1, weak 2\) 0x12344321} } }
 
   shared sp5 = make(0x56788765);
   weak wp2 = sp5;
   sp5.reset();
-// { dg-final { note-test wp2 "std::weak_ptr (expired, weak 1) 0x56788765" } }
+// { dg-final { regexp-test wp2 {std::(__\d+::)?weak_ptr \(expired, weak 1\) 0x56788765} } }
 
   placeholder(""); // Mark SPOT
   use(esp);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
index fb8e0d7..09bbbf4 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__\d+::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__\d+::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__\d+::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,7 +68,7 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 element = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__\d+::)?map with 1 element = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
@@ -78,12 +78,12 @@ main()
   intset.insert(2);
   intset.insert(3);
   const std::set<int> const_intset = intset;
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__\d+::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__\d+::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
index 9e230e3..1e5d922 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
@@ -43,12 +43,12 @@ main()
   bs[0] = 1;
   bs[5] = 1;
   bs[7] = 1;
-// { dg-final { note-test bs {std::bitset = {[0] = 1, [5] = 1, [7] = 1}} } }
+// { dg-final { regexp-test bs {std::(__\d+::)?bitset = {\[0\] = 1, \[5\] = 1, \[7\] = 1}} } }
 
   std::deque<std::string> deq;
   deq.push_back("one");
   deq.push_back("two");
-// { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
+// { dg-final { regexp-test deq {std::(__\d+::)?deque with 2 elements = {"one", "two"}} } }
 
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
@@ -56,7 +56,7 @@ main()
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
-// { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
+// { dg-final { regexp-test lst {std::(__\d+::)?list = {\[0\] = "one", \[1\] = "two"}} } }
 
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
@@ -68,19 +68,19 @@ main()
 
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
-// { dg-final { note-test mp {std::map with 1 element = {["zardoz"] = 23}} } }
+// { dg-final { regexp-test mp {std::(__\d+::)?map with 1 element = {\["zardoz"\] = 23}} } }
 
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
   // PR 67440
   const std::set<int> const_intset = {2, 3};
-// { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, [1] = 3}} } }
+// { dg-final { regexp-test const_intset {std::(__\d+::)?set with 2 elements = {\[0\] = 2, \[1\] = 3}} } }
 
   std::set<std::string> sp;
   sp.insert("clownfish");
   sp.insert("barrel");
-// { dg-final { note-test sp {std::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+// { dg-final { regexp-test sp {std::(__\d+::)?set with 2 elements = {\[0\] = "barrel", \[1\] = "clownfish"}} } }
 
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
index 609b1f0..0e18cd2 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/tr1.cc
@@ -51,31 +51,31 @@ int
 main()
 {
   std::tr1::unordered_map<int, std::string> eum;
-// { dg-final { note-test eum "std::tr1::unordered_map with 0 elements" } }
+// { dg-final { regexp-test eum "std::tr1::(__7::)?unordered_map with 0 elements" } }
   std::tr1::unordered_multimap<int, std::string> eumm;
-// { dg-final { note-test eumm "std::tr1::unordered_multimap with 0 elements" } }
+// { dg-final { regexp-test eumm "std::tr1::(__7::)?unordered_multimap with 0 elements" } }
   std::tr1::unordered_set<int> eus;
-// { dg-final { note-test eus "std::tr1::unordered_set with 0 elements" } }
+// { dg-final { regexp-test eus "std::tr1::(__7::)?unordered_set with 0 elements" } }
   std::tr1::unordered_multiset<int> eums;
-// { dg-final { note-test eums "std::tr1::unordered_multiset with 0 elements" } }
+// { dg-final { regexp-test eums "std::tr1::(__7::)?unordered_multiset with 0 elements" } }
 
   std::tr1::unordered_map<int, std::string> uom;
   uom[5] = "three";
   uom[3] = "seven";
-// { dg-final { note-test uom {std::tr1::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+// { dg-final { regexp-test uom {std::tr1::(__7::)?unordered_map with 2 elements = {\[3\] = "seven", \[5\] = "three"}} } }
 
   std::tr1::unordered_multimap<int, std::string> uomm;
   uomm.insert(std::pair<int, std::string> (5, "three"));
   uomm.insert(std::pair<int, std::string> (5, "seven"));
-// { dg-final { note-test uomm {std::tr1::unordered_multimap with 2 elements = {[5] = "three", [5] = "seven"}} } }
+// { dg-final { regexp-test uomm {std::tr1::(__7::)?unordered_multimap with 2 elements = {\[5\] = "three", \[5\] = "seven"}} } }
 
   std::tr1::unordered_set<int> uos;
   uos.insert(5);
-// { dg-final { note-test uos {std::tr1::unordered_set with 1 element = {[0] = 5}} } }
+// { dg-final { regexp-test uos {std::tr1::(__7::)?unordered_set with 1 element = {\[0\] = 5}} } }
 
   std::tr1::unordered_multiset<int> uoms;
   uoms.insert(5);
-// { dg-final { note-test uoms {std::tr1::unordered_multiset with 1 element = {[0] = 5}} } }
+// { dg-final { regexp-test uoms {std::tr1::(__7::)?unordered_multiset with 1 element = {\[0\] = 5}} } }
 
   placeholder(""); // Mark SPOT
   use(eum);
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 3f79f92..f440692 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -60,141 +60,141 @@ typedef std::basic_string<unsigned char> ustring;
 
 std::string *string_ptr;
 holder<std::string> string_holder;
-// { dg-final { whatis-test string_holder "holder<std::string>" } }
+// { dg-final { whatis-regexp-test string_holder "holder<std::(__7::)?string>" } }
 std::ios *ios_ptr;
 holder<std::ios> ios_holder;
-// { dg-final { whatis-test ios_holder "holder<std::ios>" } }
+// { dg-final { whatis-regexp-test ios_holder "holder<std::(__7::)?ios>" } }
 std::streambuf *streambuf_ptr;
 holder<std::streambuf> streambuf_holder;
-// { dg-final { whatis-test streambuf_holder "holder<std::streambuf>" } }
+// { dg-final { whatis-regexp-test streambuf_holder "holder<std::(__7::)?streambuf>" } }
 std::istream *istream_ptr;
 holder<std::istream> istream_holder;
-// { dg-final { whatis-test istream_holder "holder<std::istream>" } }
+// { dg-final { whatis-regexp-test istream_holder "holder<std::(__7::)?istream>" } }
 std::ostream *ostream_ptr;
 holder<std::ostream> ostream_holder;
-// { dg-final { whatis-test ostream_holder "holder<std::ostream>" } }
+// { dg-final { whatis-regexp-test ostream_holder "holder<std::(__7::)?ostream>" } }
 std::iostream *iostream_ptr;
 holder<std::iostream> iostream_holder;
-// { dg-final { whatis-test iostream_holder "holder<std::iostream>" } }
+// { dg-final { whatis-regexp-test iostream_holder "holder<std::(__7::)?iostream>" } }
 std::stringbuf *stringbuf_ptr;
 holder<std::stringbuf> stringbuf_holder;
-// { dg-final { whatis-test stringbuf_holder "holder<std::stringbuf>" } }
+// { dg-final { whatis-regexp-test stringbuf_holder "holder<std::(__7::)?stringbuf>" } }
 std::istringstream *istringstream_ptr;
 holder<std::istringstream> istringstream_holder;
-// { dg-final { whatis-test istringstream_holder "holder<std::istringstream>" } }
+// { dg-final { whatis-regexp-test istringstream_holder "holder<std::(__7::)?istringstream>" } }
 std::ostringstream *ostringstream_ptr;
 holder<std::ostringstream> ostringstream_holder;
-// { dg-final { whatis-test ostringstream_holder "holder<std::ostringstream>" } }
+// { dg-final { whatis-regexp-test ostringstream_holder "holder<std::(__7::)?ostringstream>" } }
 std::stringstream *stringstream_ptr;
 holder<std::stringstream> stringstream_holder;
-// { dg-final { whatis-test stringstream_holder "holder<std::stringstream>" } }
+// { dg-final { whatis-regexp-test stringstream_holder "holder<std::(__7::)?stringstream>" } }
 std::filebuf *filebuf_ptr;
 holder<std::filebuf> filebuf_holder;
-// { dg-final { whatis-test filebuf_holder "holder<std::filebuf>" } }
+// { dg-final { whatis-regexp-test filebuf_holder "holder<std::(__7::)?filebuf>" } }
 std::ifstream *ifstream_ptr;
 holder<std::ifstream> ifstream_holder;
-// { dg-final { whatis-test ifstream_holder "holder<std::ifstream>" } }
+// { dg-final { whatis-regexp-test ifstream_holder "holder<std::(__7::)?ifstream>" } }
 std::ofstream *ofstream_ptr;
 holder<std::ofstream> ofstream_holder;
-// { dg-final { whatis-test ofstream_holder "holder<std::ofstream>" } }
+// { dg-final { whatis-regexp-test ofstream_holder "holder<std::(__7::)?ofstream>" } }
 std::fstream *fstream_ptr;
 holder<std::fstream> fstream_holder;
-// { dg-final { whatis-test fstream_holder "holder<std::fstream>" } }
+// { dg-final { whatis-regexp-test fstream_holder "holder<std::(__7::)?fstream>" } }
 std::streampos *streampos_ptr;
 holder<std::streampos> streampos_holder;
-// { dg-final { whatis-test streampos_holder "holder<std::streampos>" } }
+// { dg-final { whatis-regexp-test streampos_holder "holder<std::(__7::)?streampos>" } }
 std::regex *regex_ptr;
 holder<std::regex> regex_holder;
-// { dg-final { whatis-test regex_holder "holder<std::regex>" } }
+// { dg-final { whatis-regexp-test regex_holder "holder<std::(__7::)?regex>" } }
 std::csub_match *csub_match_ptr;
 holder<std::csub_match> csub_match_holder;
-// { dg-final { whatis-test csub_match_holder "holder<std::csub_match>" } }
+// { dg-final { whatis-regexp-test csub_match_holder "holder<std::(__7::)?csub_match>" } }
 std::ssub_match *ssub_match_ptr;
 holder<std::ssub_match> ssub_match_holder;
-// { dg-final { whatis-test ssub_match_holder "holder<std::ssub_match>" } }
+// { dg-final { whatis-regexp-test ssub_match_holder "holder<std::(__7::)?ssub_match>" } }
 std::cmatch *cmatch_ptr;
 holder<std::cmatch> cmatch_holder;
-// { dg-final { whatis-test cmatch_holder "holder<std::cmatch>" } }
+// { dg-final { whatis-regexp-test cmatch_holder "holder<std::(__7::)?cmatch>" } }
 std::smatch *smatch_ptr;
 holder<std::smatch> smatch_holder;
-// { dg-final { whatis-test smatch_holder "holder<std::smatch>" } }
+// { dg-final { whatis-regexp-test smatch_holder "holder<std::(__7::)?smatch>" } }
 std::cregex_iterator *cregex_iterator_ptr;
 holder<std::cregex_iterator> cregex_iterator_holder;
-// { dg-final { whatis-test cregex_iterator_holder "holder<std::cregex_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_iterator_holder "holder<std::(__7::)?cregex_iterator>" } }
 std::sregex_iterator *sregex_iterator_ptr;
 holder<std::sregex_iterator> sregex_iterator_holder;
-// { dg-final { whatis-test sregex_iterator_holder "holder<std::sregex_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_iterator_holder "holder<std::(__7::)?sregex_iterator>" } }
 std::cregex_token_iterator *cregex_token_iterator_ptr;
 holder<std::cregex_token_iterator> cregex_token_iterator_holder;
-// { dg-final { whatis-test cregex_token_iterator_holder "holder<std::cregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test cregex_token_iterator_holder "holder<std::(__7::)?cregex_token_iterator>" } }
 std::sregex_token_iterator *sregex_token_iterator_ptr;
 holder<std::sregex_token_iterator> sregex_token_iterator_holder;
-// { dg-final { whatis-test sregex_token_iterator_holder "holder<std::sregex_token_iterator>" } }
+// { dg-final { whatis-regexp-test sregex_token_iterator_holder "holder<std::(__7::)?sregex_token_iterator>" } }
 std::u16string *u16string_ptr;
 holder<std::u16string> u16string_holder;
-// { dg-final { whatis-test u16string_holder "holder<std::u16string>" } }
+// { dg-final { whatis-regexp-test u16string_holder "holder<std::(__7::)?u16string>" } }
 std::u32string *u32string_ptr;
 holder<std::u32string> u32string_holder;
-// { dg-final { whatis-test u32string_holder "holder<std::u32string>" } }
+// { dg-final { whatis-regexp-test u32string_holder "holder<std::(__7::)?u32string>" } }
 std::minstd_rand0 *minstd_rand0_ptr;
 holder<std::minstd_rand0> minstd_rand0_holder;
-// { dg-final { whatis-test minstd_rand0_holder "holder<std::minstd_rand0>" } }
+// { dg-final { whatis-regexp-test minstd_rand0_holder "holder<std::(__7::)?minstd_rand0>" } }
 std::minstd_rand *minstd_rand_ptr;
 holder<std::minstd_rand> minstd_rand_holder;
-// { dg-final { whatis-test minstd_rand_holder "holder<std::minstd_rand>" } }
+// { dg-final { whatis-regexp-test minstd_rand_holder "holder<std::(__7::)?minstd_rand>" } }
 std::mt19937 *mt19937_ptr;
 holder<std::mt19937> mt19937_holder;
-// { dg-final { whatis-test mt19937_holder "holder<std::mt19937>" } }
+// { dg-final { whatis-regexp-test mt19937_holder "holder<std::(__7::)?mt19937>" } }
 std::mt19937_64 *mt19937_64_ptr;
 holder<std::mt19937_64> mt19937_64_holder;
-// { dg-final { whatis-test mt19937_64_holder "holder<std::mt19937_64>" } }
+// { dg-final { whatis-regexp-test mt19937_64_holder "holder<std::(__7::)?mt19937_64>" } }
 std::ranlux24_base *ranlux24_base_ptr;
 holder<std::ranlux24_base> ranlux24_base_holder;
-// { dg-final { whatis-test ranlux24_base_holder "holder<std::ranlux24_base>" } }
+// { dg-final { whatis-regexp-test ranlux24_base_holder "holder<std::(__7::)?ranlux24_base>" } }
 std::ranlux48_base *ranlux48_base_ptr;
 holder<std::ranlux48_base> ranlux48_base_holder;
-// { dg-final { whatis-test ranlux48_base_holder "holder<std::ranlux48_base>" } }
+// { dg-final { whatis-regexp-test ranlux48_base_holder "holder<std::(__7::)?ranlux48_base>" } }
 std::ranlux24 *ranlux24_ptr;
 holder<std::ranlux24> ranlux24_holder;
-// { dg-final { whatis-test ranlux24_holder "holder<std::ranlux24>" } }
+// { dg-final { whatis-regexp-test ranlux24_holder "holder<std::(__7::)?ranlux24>" } }
 std::ranlux48 *ranlux48_ptr;
 holder<std::ranlux48> ranlux48_holder;
-// { dg-final { whatis-test ranlux48_holder "holder<std::ranlux48>" } }
+// { dg-final { whatis-regexp-test ranlux48_holder "holder<std::(__7::)?ranlux48>" } }
 std::knuth_b *knuth_b_ptr;
 holder<std::knuth_b> knuth_b_holder;
-// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
+// { dg-final { whatis-regexp-test knuth_b_holder "holder<std::(__7::)?knuth_b>" } }
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-regexp-test ustring_holder "holder<std::(__7::)?basic_string<unsigned char, std::(__7::)?char_traits<unsigned char>, std::(__7::)?allocator<unsigned char> > >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-regexp-test sstring_holder "holder<std::(__7::)?basic_string<signed char, std::(__7::)?char_traits<signed char>, std::(__7::)?allocator<signed char> > >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
-// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq1_holder "holder<std::(__7::)?vector<std::(__7::)?deque<std::(__7::)?unique_ptr<char>>> >" } }
 
 std::list<std::forward_list<std::unique_ptr<char>>> *seq2_ptr;
 holder< std::list<std::forward_list<std::unique_ptr<char>>> > seq2_holder;
-// { dg-final { whatis-test seq2_holder "holder<std::list<std::forward_list<std::unique_ptr<char>>> >" } }
+// { dg-final { whatis-regexp-test seq2_holder "holder<std::(__7::)?list<std::(__7::)?forward_list<std::(__7::)?unique_ptr<char>>> >" } }
 
 std::map<int, std::set<int>> *assoc1_ptr;
 holder< std::map<int, std::set<int>> > assoc1_holder;
-// { dg-final { whatis-test assoc1_holder "holder<std::map<int, std::set<int>> >" } }
+// { dg-final { whatis-regexp-test assoc1_holder "holder<std::(__7::)?map<int, std::(__7::)?set<int>> >" } }
 
 std::multimap<int, std::multiset<int>> *assoc2_ptr;
 holder< std::multimap<int, std::multiset<int>> > assoc2_holder;
-// { dg-final { whatis-test assoc2_holder "holder<std::multimap<int, std::multiset<int>> >" } }
+// { dg-final { whatis-regexp-test assoc2_holder "holder<std::(__7::)?multimap<int, std::(__7::)?multiset<int>> >" } }
 
 std::unordered_map<int, std::unordered_set<int>> *unord1_ptr;
 holder< std::unordered_map<int, std::unordered_set<int>> > unord1_holder;
-// { dg-final { whatis-test unord1_holder "holder<std::unordered_map<int, std::unordered_set<int>> >" } }
+// { dg-final { whatis-regexp-test unord1_holder "holder<std::(__7::)?unordered_map<int, std::(__7::)?unordered_set<int>> >" } }
 
 std::unordered_multimap<int, std::unordered_multiset<int>> *unord2_ptr;
 holder< std::unordered_multimap<int, std::unordered_multiset<int>> > unord2_holder;
-// { dg-final { whatis-test unord2_holder "holder<std::unordered_multimap<int, std::unordered_multiset<int>> >" } }
+// { dg-final { whatis-regexp-test unord2_holder "holder<std::(__7::)?unordered_multimap<int, std::(__7::)?unordered_multiset<int>> >" } }
 
 
 int

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-14 21:53           ` François Dumont
@ 2016-12-15 11:15             ` Jonathan Wakely
  2016-12-15 14:51             ` Jonathan Wakely
  2016-12-15 15:52             ` Jonathan Wakely
  2 siblings, 0 replies; 17+ messages in thread
From: Jonathan Wakely @ 2016-12-15 11:15 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 14/12/16 22:49 +0100, François Dumont wrote:
>On 09/12/2016 16:18, Jonathan Wakely wrote:
>>
>>>But I don't know how to fix this so for the moment I just adapt it 
>>>to correctly handle std::__7::string.
>>
>>But that's not correct. Please try to understand the point I'm making:
>>The name "std::__7::string" does not appear in a symbol name.
>Ok, the only point I don't get yet is why std::string is a symbol but 
>std::__7::string is not. It seems inconsistent.

The demangler has special handling for std::basic_string<char,
std::char_traits<char>, std::allocator<char>> to treat it as
std::string, because that's much more user-friendly. But when it sees
a different symbol, like foo::basic_string<bar>, or std::__7::... it
doesn't match and doesn't get special handling.

Being consistent doesn't matter, the point is to be user-friendly.

Users want to see std::string, not std::basic_string<char, ..., ...>.

Looking at all the ugly changes needed to the tests, I'm wondering if
we actually want to strip the __7:: namespace out of the typenames
displayed by printers. That would mean we don't need to change the
tests, but more importantly, it would mean the users see "std::vector"
not "std::__7::vector". The versioned namespace is an implementation
detail, not something they write explicitly in their code.

Your change makes the printer tests pass for the versioned namespace,
but does it make the printers useful for users? We want the printers
to be useful, not just pass our testsuite.


>>
>>This works for me:
>>
>>@@ -946,9 +950,10 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
>>            m = re.match(rx, func.function.name)
>>            if not m:
>>                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))
>>+            mgrname = m.group(1)
>>+            if not typename.startswith('std::' + vers_nsp):
>>+                # 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()), mgrname)
>>
>I think it doesn't work in all situations as this code is also used 
>for std::experimental::any so typename doesn't start with std::__7:: 
>but there is still no std::string symbol.

Ah yes, I forgot about the experimental one.

>So I propose:
>
>            mgrname = m.group(1)
>            if 'std::string' in mgrname:
>                # 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))
>
>as you will see in attach patch.

Looks good.

>I eventually use '__7' explicitely in some pretty printers tests 
>because '__\d+' was not working, don't know.

Yes, I also found that wasn't working. Presumably Tcl doesn't support
that syntax.

>Ok to commit once tests have completed ?

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-14 21:53           ` François Dumont
  2016-12-15 11:15             ` Jonathan Wakely
@ 2016-12-15 14:51             ` Jonathan Wakely
  2016-12-15 15:52             ` Jonathan Wakely
  2 siblings, 0 replies; 17+ messages in thread
From: Jonathan Wakely @ 2016-12-15 14:51 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 14/12/16 22:49 +0100, François Dumont wrote:
>@@ -1321,7 +1328,7 @@ def register_type_printers(obj):
>     if not _use_type_printing:
>         return
> 
>-    for pfx in ('', 'w'):
>+    for pfx in ('', 'w', vers_nsp, vers_nsp + 'w'):
>         add_one_type_printer(obj, 'basic_string', pfx + 'string')
>         add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view')
>         add_one_type_printer(obj, 'basic_ios', pfx + 'ios')

Looking at this part again, can't we handle the std::__7:: cases
inside add_one_type_printer instead of here?

The "pfx" prefixes here are intended for names that are imilar, like
std::string and std::wstring. If we want to handle both with an
alternative namespace then the place to do that is where we prepend
the namespace, surely?

 def add_one_type_printer(obj, match, name):
     printer = FilteringTypePrinter(match, 'std::' + name)
     gdb.types.register_type_printer(obj, printer)
+    printer = FilteringTypePrinter(match, 'std::__7::' + name)
+    gdb.types.register_type_printer(obj, printer)

That will make the patch *much* smaller, and the logic is easier to
follow.

For the template type printers I think we just want to add (__7::)? to
the regular expressions. If we get a type like

  std::__7::vector<T, std::__7::allocator<T> >

Then I think we want to print that as std::vector<T>, without __7::.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-14 21:53           ` François Dumont
  2016-12-15 11:15             ` Jonathan Wakely
  2016-12-15 14:51             ` Jonathan Wakely
@ 2016-12-15 15:52             ` Jonathan Wakely
  2016-12-24 16:29               ` François Dumont
  2 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2016-12-15 15:52 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 14/12/16 22:49 +0100, François Dumont wrote:
>On 09/12/2016 16:18, Jonathan Wakely wrote:
>>
>>>But I don't know how to fix this so for the moment I just adapt it 
>>>to correctly handle std::__7::string.
>>
>>But that's not correct. Please try to understand the point I'm making:
>>The name "std::__7::string" does not appear in a symbol name.
>Ok, the only point I don't get yet is why std::string is a symbol but 
>std::__7::string is not. It seems inconsistent.
>
>>
>>This works for me:
>>
>>@@ -946,9 +950,10 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
>>            m = re.match(rx, func.function.name)
>>            if not m:
>>                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))
>>+            mgrname = m.group(1)
>>+            if not typename.startswith('std::' + vers_nsp):
>>+                # 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()), mgrname)
>>
>I think it doesn't work in all situations as this code is also used 
>for std::experimental::any so typename doesn't start with std::__7:: 
>but there is still no std::string symbol.
>
>So I propose:
>
>            mgrname = m.group(1)
>            if 'std::string' in mgrname:
>                # 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))
>
>as you will see in attach patch.
>
>I eventually use '__7' explicitely in some pretty printers tests 
>because '__\d+' was not working, don't know.
>
>Ok to commit once tests have completed ?
>
>François
>

>diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
>index 3a111d7..9aba69a 100644
>--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
>+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
>@@ -36,6 +36,8 @@ import sys
> # We probably can't do much about this until this GDB PR is addressed:
> # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
> 
>+vers_nsp = '__7::'
>+
> if sys.version_info[0] > 2:
>     ### Python 3 stuff
>     Iterator = object
>@@ -127,9 +129,9 @@ class UniquePointerPrinter:
> 
>     def to_string (self):
>         impl_type = self.val.type.fields()[0].type.tag
>-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
>+        if re.match('^std::(' + vers_nsp + ')?__uniq_ptr_impl<.*>$', impl_type): # New implementation
>             v = self.val['_M_t']['_M_t']['_M_head_impl']
>-        elif impl_type.startswith('std::tuple<'):
>+        elif re.match('^std::(' + vers_nsp + ')?tuple<.*>$', impl_type):
>             v = self.val['_M_t']['_M_head_impl']
>         else:
>             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)

And we could avoid three re.match expressions with complicated regular
expressions by creating a helper function to do the "startswith"
checks:

def is_specialization_of(type, template_name):
    return re.match('^std::(%s)?%s<.*>$' % (vers_nsp, template_name), type) is not None

Then replace impl_type.startswith('std::__uniq_ptr_impl<') with
is_specialization_of(impl_type, '__uniq_ptr_impl')

And replace impl_type.startswith('std::tuple<') with
is_specialization_of(impl_type, 'tuple')

And replace nodetype.name.startswith('std::_Rb_tree_node') with
is_specialization_of(nodetype.name, '_Rb_tree_node')

That makes the code much easier to read.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-15 15:52             ` Jonathan Wakely
@ 2016-12-24 16:29               ` François Dumont
  2017-01-04 12:52                 ` Jonathan Wakely
  0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2016-12-24 16:29 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1909 bytes --]

On 15/12/2016 15:57, Jonathan Wakely wrote:
>
> And we could avoid three re.match expressions with complicated regular
> expressions by creating a helper function to do the "startswith"
> checks:
>
> def is_specialization_of(type, template_name):
>    return re.match('^std::(%s)?%s<.*>$' % (vers_nsp, template_name), 
> type) is not None
>
> Then replace impl_type.startswith('std::__uniq_ptr_impl<') with
> is_specialization_of(impl_type, '__uniq_ptr_impl')
>
> And replace impl_type.startswith('std::tuple<') with
> is_specialization_of(impl_type, 'tuple')
>
> And replace nodetype.name.startswith('std::_Rb_tree_node') with
> is_specialization_of(nodetype.name, '_Rb_tree_node')
>
> That makes the code much easier to read.
>
>
I agree that hiding the version namespace will be nicer. I just hope it 
is possible. I don't think we can really dictate gdb to hide this 
namespace during the rendering. In the attached path you will see what I 
tried to do. Problem is that I am not sure that printers.py is 
intercepting rendering of all types so version namespace will stay 
visible in those cases.

I think the 2 failures that I have with this patch are reflecting this 
problem:

type = holder<std::__7::basic_string<unsigned char, 
std::__7::char_traits<unsigned char>, std::__7::allocator<unsigned char> > >
got: type = holder<std::__7::basic_string<unsigned char, 
std::__7::char_traits<unsigned char>, std::__7::allocator<unsigned char> > >
FAIL: libstdc++-prettyprinters/whatis.cc whatis ustring_holder
type = holder<std::__7::basic_string<signed char, 
std::__7::char_traits<signed char>, std::__7::allocator<signed char> > >
got: type = holder<std::__7::basic_string<signed char, 
std::__7::char_traits<signed char>, std::__7::allocator<signed char> > >
FAIL: libstdc++-prettyprinters/whatis.cc whatis sstring_holder

Shall I simply use regex in those cases and adopt this approach ?

François



[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 19600 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 86de1ca..55bdee9 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -36,6 +36,8 @@ import sys
 # We probably can't do much about this until this GDB PR is addressed:
 # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
 
+vers_nsp = '__7::'
+
 if sys.version_info[0] > 2:
     ### Python 3 stuff
     Iterator = object
@@ -100,11 +102,15 @@ def find_type(orig, name):
             raise ValueError("Cannot find type %s::%s" % (str(orig), name))
         typ = field.type
 
+# Test if a type is a given template instantiation.
+def is_specialization_of(type, template_name):
+   return re.match('^std::(%s)?%s<.*>$' % (vers_nsp, template_name), type) is not None
+
 class SharedPointerPrinter:
     "Print a shared_ptr or weak_ptr"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -127,9 +133,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif is_specialization_of(impl_type, 'tuple'):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -179,7 +185,7 @@ class StdListPrinter:
             return ('[%d]' % count, val)
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def children(self):
@@ -299,7 +305,7 @@ class StdVectorPrinter:
                 return ('[%d]' % count, elt)
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
         self.is_bool = val.type.template_argument(0).code  == gdb.TYPE_CODE_BOOL
 
@@ -403,7 +409,7 @@ class StdTuplePrinter:
                 return ('[%d]' % self.count, impl['_M_head_impl'])
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val;
 
     def children (self):
@@ -418,7 +424,7 @@ class StdStackOrQueuePrinter:
     "Print a std::stack or std::queue"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.visualizer = gdb.default_visualizer(val['c'])
 
     def children (self):
@@ -496,7 +502,10 @@ class StdRbtreeIteratorPrinter:
     def __init__ (self, typename, val):
         self.val = val
         valtype = self.val.type.template_argument(0).strip_typedefs()
-        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        if typename.startswith('std::' + vers_nsp):
+            nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+        else:
+            nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
@@ -552,7 +561,7 @@ class StdMapPrinter:
             return result
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -592,7 +601,7 @@ class StdSetPrinter:
             return result
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -609,7 +618,7 @@ class StdBitsetPrinter:
     "Print a std::bitset"
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -679,7 +688,7 @@ class StdDequePrinter:
             return result
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
         self.elttype = val.type.template_argument(0)
         size = self.elttype.sizeof
@@ -805,7 +814,7 @@ class Tr1UnorderedSetPrinter:
     "Print a tr1::unordered_set"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def hashtable (self):
@@ -831,7 +840,7 @@ class Tr1UnorderedMapPrinter:
     "Print a tr1::unordered_map"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def hashtable (self):
@@ -897,7 +906,7 @@ class StdForwardListPrinter:
 
     def __init__(self, typename, val):
         self.val = val
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
 
     def children(self):
         nodetype = find_type(self.val.type, '_Node')
@@ -952,12 +961,11 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
     def __init__ (self, typename, val):
-        self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1)
+        self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1).replace(vers_nsp, '')
         self.val = val
         self.contained_type = None
         contained_value = None
@@ -972,8 +980,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
             if not m:
                 raise ValueError("Unknown manager function in %s" % self.typename)
 
+            mgrname = m.group(1)
             # 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))
+            if 'std::string' in mgrname:
+                mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
+
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None
@@ -994,14 +1005,14 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
         if hasattr (self.visualizer, 'children'):
             return desc + self.visualizer.to_string ()
         valtype = self._recognize (self.contained_type)
-        return desc + valtype
+        return desc + str(valtype).replace(vers_nsp, '')
 
 class StdExpOptionalPrinter(SingleObjContainerPrinter):
     "Print a std::optional or std::experimental::optional"
 
     def __init__ (self, typename, val):
         valtype = self._recognize (val.type.template_argument(0))
-        self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1)
+        self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1).replace(vers_nsp, '')
         self.val = val
         contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
         visualizer = gdb.default_visualizer (val['_M_payload'])
@@ -1021,6 +1032,7 @@ class StdVariantPrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         alternatives = self._template_args(val)
         self.typename = "%s<%s>" % (typename, ', '.join([self._recognize(alt) for alt in alternatives]))
+        self.typename = self.typename.replace(vers_nsp, '')
         self.index = val['_M_index']
         if self.index >= len(alternatives):
             self.contained_type = None
@@ -1058,7 +1070,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node')
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1202,7 +1214,7 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        self.add(base + vers_nsp + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1322,7 +1334,7 @@ class FilteringTypePrinter(object):
                 except:
                     pass
             if self.type_obj == type_obj:
-                return self.name
+                return self.name.replace(vers_nsp, '')
             return None
 
     def instantiate(self):
@@ -1331,6 +1343,8 @@ class FilteringTypePrinter(object):
 def add_one_type_printer(obj, match, name):
     printer = FilteringTypePrinter(match, 'std::' + name)
     gdb.types.register_type_printer(obj, printer)
+    printer = FilteringTypePrinter(match, 'std::' + vers_nsp + name)
+    gdb.types.register_type_printer(obj, printer)
 
 def register_type_printers(obj):
     global _use_type_printing
@@ -1374,7 +1388,6 @@ def register_type_printers(obj):
     add_one_type_printer(obj, 'fpos', 'streampos')
     add_one_type_printer(obj, 'basic_string', 'u16string')
     add_one_type_printer(obj, 'basic_string', 'u32string')
-
     add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
     add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
 
@@ -1392,46 +1405,47 @@ def register_type_printers(obj):
     add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
     add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
 
-    # Do not show defaulted template arguments in class templates
-    add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
+    for vers in ('', vers_nsp):
+        # Do not show defaulted template arguments in class templates
+        add_one_template_type_printer(obj, 'unique_ptr<T>',
+            '{0}unique_ptr<(.*), std::{0}default_delete<\\1 ?> >'.format(vers),
             'unique_ptr<{1}>')
 
-    add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'deque<T>',
+            '{0}deque<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
             'deque<{1}>')
-    add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'forward_list<T>',
+            '{0}forward_list<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
             'forward_list<{1}>')
-    add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'list<T>',
+            '{0}list<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
             'list<{1}>')
-    add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'vector<T>',
+            '{0}vector<(.*), std::{0}allocator<\\1 ?> >'.format(vers),
             'vector<{1}>')
-    add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        add_one_template_type_printer(obj, 'map<Key, T>',
+            '{0}map<(.*), (.*), std::{0}less<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
             'map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        add_one_template_type_printer(obj, 'multimap<Key, T>',
+            '{0}multimap<(.*), (.*), std::{0}less<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
             'multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'set<T>',
+            '{0}set<(.*), std::{0}less<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
             'set<{1}>')
-    add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'multiset<T>',
+            '{0}multiset<(.*), std::{0}less<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
             'multiset<{1}>')
-    add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        add_one_template_type_printer(obj, 'unordered_map<Key, T>',
+            '{0}unordered_map<(.*), (.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
             'unordered_map<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
+            '{0}unordered_multimap<(.*), (.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<std::{0}pair<\\1 const, \\2 ?> > >'.format(vers),
             'unordered_multimap<{1}, {2}>')
-    add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'unordered_set<T>',
+            '{0}unordered_set<(.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
             'unordered_set<{1}>')
-    add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+        add_one_template_type_printer(obj, 'unordered_multiset<T>',
+            '{0}unordered_multiset<(.*), std::{0}hash<\\1 ?>, std::{0}equal_to<\\1 ?>, std::{0}allocator<\\1 ?> >'.format(vers),
             'unordered_multiset<{1}>')
 
     # strip the "fundamentals_v1" inline namespace from these types
@@ -1466,7 +1480,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer = Printer("libstdc++-v6")
 
     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
+    vers = '(' + vers_nsp + ')?'
     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     container = '(__cxx1998::' + vers + ')?'
 
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index 1c9bf3a..ae576d8 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -586,9 +586,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -640,7 +640,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2016-12-24 16:29               ` François Dumont
@ 2017-01-04 12:52                 ` Jonathan Wakely
  2017-01-09 20:25                   ` François Dumont
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2017-01-04 12:52 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2568 bytes --]

On 24/12/16 14:47 +0100, François Dumont wrote:
>On 15/12/2016 15:57, Jonathan Wakely wrote:
>>
>>And we could avoid three re.match expressions with complicated regular
>>expressions by creating a helper function to do the "startswith"
>>checks:
>>
>>def is_specialization_of(type, template_name):
>>   return re.match('^std::(%s)?%s<.*>$' % (vers_nsp, template_name), 
>>type) is not None
>>
>>Then replace impl_type.startswith('std::__uniq_ptr_impl<') with
>>is_specialization_of(impl_type, '__uniq_ptr_impl')
>>
>>And replace impl_type.startswith('std::tuple<') with
>>is_specialization_of(impl_type, 'tuple')
>>
>>And replace nodetype.name.startswith('std::_Rb_tree_node') with
>>is_specialization_of(nodetype.name, '_Rb_tree_node')
>>
>>That makes the code much easier to read.
>>
>>
>I agree that hiding the version namespace will be nicer. I just hope 
>it is possible. I don't think we can really dictate gdb to hide this 
>namespace during the rendering. In the attached path you will see what 
>I tried to do. Problem is that I am not sure that printers.py is 
>intercepting rendering of all types so version namespace will stay 
>visible in those cases.
>
>I think the 2 failures that I have with this patch are reflecting this 
>problem:
>
>type = holder<std::__7::basic_string<unsigned char, 
>std::__7::char_traits<unsigned char>, std::__7::allocator<unsigned 
>char> > >
>got: type = holder<std::__7::basic_string<unsigned char, 
>std::__7::char_traits<unsigned char>, std::__7::allocator<unsigned 
>char> > >
>FAIL: libstdc++-prettyprinters/whatis.cc whatis ustring_holder
>type = holder<std::__7::basic_string<signed char, 
>std::__7::char_traits<signed char>, std::__7::allocator<signed char> > 
>>
>got: type = holder<std::__7::basic_string<signed char, 
>std::__7::char_traits<signed char>, std::__7::allocator<signed char> > 
>>
>FAIL: libstdc++-prettyprinters/whatis.cc whatis sstring_holder
>
>Shall I simply use regex in those cases and adopt this approach ?

I'd prefer not to have to use the regex matches in libstdc++.exp as
they complicate things.

For the two examples above, the whatis results are bad even for the
non-versioned namespace. For specializations of basic_string we only
have type printers that recognize the standard typedefs like
std::u16string, but not other specializations. We really want it to
show std::basic_string<unsigned char> not the full name. That would
require a TemplateTypePrinter for basic_string. The attached patch
works, and should be easy to incorporate into your changes for the
versioned namespace.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 2209 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 7690a6b..fd63a5c 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1372,6 +1372,7 @@ def register_type_printers(obj):
     # Note that we can't have a printer for std::wstreampos, because
     # it shares the same underlying type as std::streampos.
     add_one_type_printer(obj, 'fpos', 'streampos')
+
     add_one_type_printer(obj, 'basic_string', 'u16string')
     add_one_type_printer(obj, 'basic_string', 'u32string')
 
@@ -1397,6 +1398,10 @@ def register_type_printers(obj):
             'unique_ptr<(.*), std::default_delete<\\1 ?> >',
             'unique_ptr<{1}>')
 
+    add_one_template_type_printer(obj, 'basic_string<T>',
+            'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
+            'basic_string<{1}>')
+
     add_one_template_type_printer(obj, 'deque<T>',
             'deque<(.*), std::allocator<\\1 ?> >',
             'deque<{1}>')
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 31ded8b..7a55bb7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -166,11 +166,11 @@ holder<std::knuth_b> knuth_b_holder;
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char> >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char> >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2017-01-04 12:52                 ` Jonathan Wakely
@ 2017-01-09 20:25                   ` François Dumont
  2017-01-10 12:39                     ` Jonathan Wakely
  0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2017-01-09 20:25 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1622 bytes --]

On 04/01/2017 13:52, Jonathan Wakely wrote:
> On 24/12/16 14:47 +0100, François Dumont wrote:
>
> I'd prefer not to have to use the regex matches in libstdc++.exp as
> they complicate things.
>
> For the two examples above, the whatis results are bad even for the
> non-versioned namespace. For specializations of basic_string we only
> have type printers that recognize the standard typedefs like
> std::u16string, but not other specializations. We really want it to
> show std::basic_string<unsigned char> not the full name. That would
> require a TemplateTypePrinter for basic_string. The attached patch
> works, and should be easy to incorporate into your changes for the
> versioned namespace.
>
+    add_one_template_type_printer(obj, 'basic_string<T>',
+            'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
+            'basic_string<{1}>')
+

I had consider a similar approach but more generic like:

+    add_one_template_type_printer(obj, 'basic_string<T>',
+            'basic_string<(.*)?, std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
+            'basic_string<{1}>')
+


but it had bad effect on rendering of std::string type so I give up on this approach. Your version is indeed enough to cover not too exotic instantiations of std::basic_string.

I also updated 48362.cc test case as this test was already adapted for versioned namespace. But I had to keep one occurence of '__7' when displaying types inside a tuple. I think it is ok.

Tested with versioned namespace. Is it ok to commit after I completed tests without versioned namespace ?

François


[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 21587 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 7690a6b..9de1a96 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -36,6 +36,8 @@ import sys
 # We probably can't do much about this until this GDB PR is addressed:
 # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
 
+vers_nsp = '__7::'
+
 if sys.version_info[0] > 2:
     ### Python 3 stuff
     Iterator = object
@@ -100,11 +102,15 @@ def find_type(orig, name):
             raise ValueError("Cannot find type %s::%s" % (str(orig), name))
         typ = field.type
 
+# Test if a type is a given template instantiation.
+def is_specialization_of(type, template_name):
+   return re.match('^std::(%s)?%s<.*>$' % (vers_nsp, template_name), type) is not None
+
 class SharedPointerPrinter:
     "Print a shared_ptr or weak_ptr"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -127,9 +133,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif is_specialization_of(impl_type, 'tuple'):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -179,7 +185,7 @@ class StdListPrinter:
             return ('[%d]' % count, val)
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def children(self):
@@ -299,7 +305,7 @@ class StdVectorPrinter:
                 return ('[%d]' % count, elt)
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
         self.is_bool = val.type.template_argument(0).code  == gdb.TYPE_CODE_BOOL
 
@@ -403,7 +409,7 @@ class StdTuplePrinter:
                 return ('[%d]' % self.count, impl['_M_head_impl'])
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val;
 
     def children (self):
@@ -418,7 +424,7 @@ class StdStackOrQueuePrinter:
     "Print a std::stack or std::queue"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.visualizer = gdb.default_visualizer(val['c'])
 
     def children (self):
@@ -496,7 +502,10 @@ class StdRbtreeIteratorPrinter:
     def __init__ (self, typename, val):
         self.val = val
         valtype = self.val.type.template_argument(0).strip_typedefs()
-        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        if typename.startswith('std::' + vers_nsp):
+            nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+        else:
+            nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
@@ -552,7 +561,7 @@ class StdMapPrinter:
             return result
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -592,7 +601,7 @@ class StdSetPrinter:
             return result
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -609,7 +618,7 @@ class StdBitsetPrinter:
     "Print a std::bitset"
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def to_string (self):
@@ -679,7 +688,7 @@ class StdDequePrinter:
             return result
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
         self.elttype = val.type.template_argument(0)
         size = self.elttype.sizeof
@@ -805,7 +814,7 @@ class Tr1UnorderedSetPrinter:
     "Print a tr1::unordered_set"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def hashtable (self):
@@ -831,7 +840,7 @@ class Tr1UnorderedMapPrinter:
     "Print a tr1::unordered_map"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
         self.val = val
 
     def hashtable (self):
@@ -897,7 +906,7 @@ class StdForwardListPrinter:
 
     def __init__(self, typename, val):
         self.val = val
-        self.typename = typename
+        self.typename = typename.replace(vers_nsp, '')
 
     def children(self):
         nodetype = find_type(self.val.type, '_Node')
@@ -952,12 +961,11 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
     def __init__ (self, typename, val):
-        self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1)
+        self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1).replace(vers_nsp, '')
         self.val = val
         self.contained_type = None
         contained_value = None
@@ -972,8 +980,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
             if not m:
                 raise ValueError("Unknown manager function in %s" % self.typename)
 
+            mgrname = m.group(1)
             # 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))
+            if 'std::string' in mgrname:
+                mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
+
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None
@@ -994,14 +1005,14 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
         if hasattr (self.visualizer, 'children'):
             return desc + self.visualizer.to_string ()
         valtype = self._recognize (self.contained_type)
-        return desc + valtype
+        return desc + str(valtype).replace(vers_nsp, '')
 
 class StdExpOptionalPrinter(SingleObjContainerPrinter):
     "Print a std::optional or std::experimental::optional"
 
     def __init__ (self, typename, val):
         valtype = self._recognize (val.type.template_argument(0))
-        self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1)
+        self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1).replace(vers_nsp, '')
         self.val = val
         contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
         visualizer = gdb.default_visualizer (val['_M_payload'])
@@ -1021,6 +1032,7 @@ class StdVariantPrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         alternatives = self._template_args(val)
         self.typename = "%s<%s>" % (typename, ', '.join([self._recognize(alt) for alt in alternatives]))
+        self.typename = self.typename.replace(vers_nsp, '')
         self.index = val['_M_index']
         if self.index >= len(alternatives):
             self.contained_type = None
@@ -1058,7 +1070,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node')
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1202,7 +1214,7 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        self.add(base + vers_nsp + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1322,7 +1334,7 @@ class FilteringTypePrinter(object):
                 except:
                     pass
             if self.type_obj == type_obj:
-                return self.name
+                return self.name.replace(vers_nsp, '')
             return None
 
     def instantiate(self):
@@ -1331,6 +1343,8 @@ class FilteringTypePrinter(object):
 def add_one_type_printer(obj, match, name):
     printer = FilteringTypePrinter(match, 'std::' + name)
     gdb.types.register_type_printer(obj, printer)
+    printer = FilteringTypePrinter(match, 'std::' + vers_nsp + name)
+    gdb.types.register_type_printer(obj, printer)
 
 def register_type_printers(obj):
     global _use_type_printing
@@ -1372,9 +1386,9 @@ def register_type_printers(obj):
     # Note that we can't have a printer for std::wstreampos, because
     # it shares the same underlying type as std::streampos.
     add_one_type_printer(obj, 'fpos', 'streampos')
+
     add_one_type_printer(obj, 'basic_string', 'u16string')
     add_one_type_printer(obj, 'basic_string', 'u32string')
-
     add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
     add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
 
@@ -1392,47 +1406,54 @@ def register_type_printers(obj):
     add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
     add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
 
+    # Consider optional versioned namespace
+    opt_nsp = '(' + vers_nsp + ')?'
+
     # Do not show defaulted template arguments in class templates
     add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
+        '{0}unique_ptr<(.*), std::{0}default_delete<\\2 ?> >'.format(opt_nsp),
+        'unique_ptr<{2}>')
+
+    add_one_template_type_printer(obj, 'basic_string<T>',
+        '{0}basic_string<((un)?signed char), std::{0}char_traits<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'basic_string<{2}>')
 
     add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
+        '{0}deque<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'deque<{2}>')
     add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
+        '{0}forward_list<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'forward_list<{2}>')
     add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
+        '{0}list<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'list<{2}>')
     add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
+        '{0}vector<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'vector<{2}>')
     add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
+        '{0}map<(.*), (.*), std::{0}less<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+        'map<{2}, {3}>')
     add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
+        '{0}multimap<(.*), (.*), std::{0}less<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+        'multimap<{2}, {3}>')
     add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
+        '{0}set<(.*), std::{0}less<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'set<{2}>')
     add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
+        '{0}multiset<(.*), std::{0}less<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'multiset<{2}>')
     add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
+        '{0}unordered_map<(.*), (.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+        'unordered_map<{2}, {3}>')
     add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
+        '{0}unordered_multimap<(.*), (.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+        'unordered_multimap<{2}, {3}>')
     add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
+        '{0}unordered_set<(.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'unordered_set<{2}>')
     add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+        '{0}unordered_multiset<(.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+        'unordered_multiset<{2}>')
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
@@ -1466,7 +1487,7 @@ def build_libstdcxx_dictionary ():
     libstdcxx_printer = Printer("libstdc++-v6")
 
     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
+    vers = '(' + vers_nsp + ')?'
     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     container = '(__cxx1998::' + vers + ')?'
 
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index def72b0..29eb339 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -586,9 +586,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -640,7 +640,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
index 16ef07b..998b6d5 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
@@ -26,10 +26,10 @@ int
 main()
 {
   std::tuple<> t1;
-// { dg-final { regexp-test t1 {empty std::(__7::)?tuple} } }
+// { dg-final { regexp-test t1 {empty std::tuple} } }
 
   std::tuple<std::string, int, std::tuple<>> t2{ "Johnny", 5, {} };
-// { dg-final { regexp-test t2 {std::(__7::)?tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::(__7::)?tuple, <No data fields>}}} } }
+// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::tuple, <No data fields>}}} } }
 
   std::cout << "\n";
   return 0; // Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 31ded8b..7a55bb7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -166,11 +166,11 @@ holder<std::knuth_b> knuth_b_holder;
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char> >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char> >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2017-01-09 20:25                   ` François Dumont
@ 2017-01-10 12:39                     ` Jonathan Wakely
  2017-01-19 21:22                       ` François Dumont
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2017-01-10 12:39 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3791 bytes --]

On 09/01/17 21:25 +0100, François Dumont wrote:
>On 04/01/2017 13:52, Jonathan Wakely wrote:
>>On 24/12/16 14:47 +0100, François Dumont wrote:
>>
>>I'd prefer not to have to use the regex matches in libstdc++.exp as
>>they complicate things.
>>
>>For the two examples above, the whatis results are bad even for the
>>non-versioned namespace. For specializations of basic_string we only
>>have type printers that recognize the standard typedefs like
>>std::u16string, but not other specializations. We really want it to
>>show std::basic_string<unsigned char> not the full name. That would
>>require a TemplateTypePrinter for basic_string. The attached patch
>>works, and should be easy to incorporate into your changes for the
>>versioned namespace.
>>
>+    add_one_template_type_printer(obj, 'basic_string<T>',
>+            'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
>+            'basic_string<{1}>')
>+
>
>I had consider a similar approach but more generic like:
>
>+    add_one_template_type_printer(obj, 'basic_string<T>',
>+            'basic_string<(.*)?, std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
>+            'basic_string<{1}>')
>+
>
>
>but it had bad effect on rendering of std::string type so I give up on this approach. Your version is indeed enough to cover not too exotic instantiations of std::basic_string.

Yes, I tried that first as well.

>I also updated 48362.cc test case as this test was already adapted for versioned namespace. But I had to keep one occurence of '__7' when displaying types inside a tuple. I think it is ok.

Yes, I think so too.

>Tested with versioned namespace. Is it ok to commit after I completed tests without versioned namespace ?

I've committed the attached patch, which passes the tests for the
default configuration and the versioned namespace configuration.

I added another helper function, strip_versioned_namespace, which is
more expressive than doing typename.replace(vers_nsp, '') everywhere.
I've also renamed vers_nsp to _versioned_namespace (using the naming
convention for global variables private to the module). I've added
checks so that if that variable is None then the extra printers and
special cases for the versioned namespace are skipped. That's not
currently used, but it would allow us to optimise things later if
needed.

I also needed to update the new SharedPtrMethodsMatcher to add
"(__\d+)?" to the regular expression.


>@@ -1392,47 +1406,54 @@ def register_type_printers(obj):
>     add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
>     add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
> 
>+    # Consider optional versioned namespace
>+    opt_nsp = '(' + vers_nsp + ')?'
>+
>     # Do not show defaulted template arguments in class templates
>     add_one_template_type_printer(obj, 'unique_ptr<T>',
>-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
>-            'unique_ptr<{1}>')
>+        '{0}unique_ptr<(.*), std::{0}default_delete<\\2 ?> >'.format(opt_nsp),
>+        'unique_ptr<{2}>')

This is ugly. Mixing python string formatting with regular expressions
makes it harder to read, and is inconsistent with how the versioned
namespace is handled elsewhere. In Printer.add_version and
add_one_type_printer we just register two names, one using std:: and
one using std::__7::. We can do the same for the template type
printers.

>@@ -1466,7 +1487,7 @@ def build_libstdcxx_dictionary ():
>     libstdcxx_printer = Printer("libstdc++-v6")
> 
>     # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
>-    vers = '(__7::)?'
>+    vers = '(' + vers_nsp + ')?'
>     # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
>     container = '(__cxx1998::' + vers + ')?'
> 

These variables don't seem to be used, so can just be removed.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 20052 bytes --]

commit 6238b856776f1a86626f626009d28f4d29c119d8
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Jan 10 12:31:31 2017 +0000

    Make Python printers and xmethods work with versioned namespace
    
    2017-01-10  Fran??ois Dumont  <fdumont@gcc.gnu.org>
    	    Jonathan Wakely  <jwakely@redhat.com>
    
    	* python/libstdcxx/v6/printers.py (_versioned_namespace): Define.
    	(is_specialization, strip_versioned_namespace): New helpers functions
    	to work with symbols in the versioned namespace.
    	(Printer.add_version): Add second name using versioned namespace.
    	(add_one_template_type_printer, add_one_type_printer): Add second
    	type printers using versioned namespace.
    	(register_type_printers): Add template type printer for basic_string.
    	(build_libstdcxx_dictionary): Remove dead code.
    	* python/libstdcxx/v6/xmethods.py: Make all matchers look for
    	versioned namespace.
    	* testsuite/libstdc++-prettyprinters/48362.cc: Adjust expected
    	results.
    	* testsuite/libstdc++-prettyprinters/whatis.cc: Likewise.

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 7690a6b..36dd81d 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -100,11 +100,26 @@ def find_type(orig, name):
             raise ValueError("Cannot find type %s::%s" % (str(orig), name))
         typ = field.type
 
+_versioned_namespace = '__7::'
+
+# Test if a type is a given template instantiation.
+def is_specialization_of(type, template_name):
+    global _versioned_namespace
+    if _versioned_namespace:
+        return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), type) is not None
+    return re.match('^std::%s<.*>$' % template_name, type) is not None
+
+def strip_versioned_namespace(typename):
+    global _versioned_namespace
+    if _versioned_namespace:
+        return typename.replace(_versioned_namespace, '')
+    return typename
+
 class SharedPointerPrinter:
     "Print a shared_ptr or weak_ptr"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def to_string (self):
@@ -127,9 +142,9 @@ class UniquePointerPrinter:
 
     def to_string (self):
         impl_type = self.val.type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation
             v = self.val['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif is_specialization_of(impl_type, 'tuple'):
             v = self.val['_M_t']['_M_head_impl']
         else:
             raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -179,7 +194,7 @@ class StdListPrinter:
             return ('[%d]' % count, val)
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def children(self):
@@ -299,7 +314,7 @@ class StdVectorPrinter:
                 return ('[%d]' % count, elt)
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
         self.is_bool = val.type.template_argument(0).code  == gdb.TYPE_CODE_BOOL
 
@@ -403,7 +418,7 @@ class StdTuplePrinter:
                 return ('[%d]' % self.count, impl['_M_head_impl'])
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val;
 
     def children (self):
@@ -418,7 +433,7 @@ class StdStackOrQueuePrinter:
     "Print a std::stack or std::queue"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.visualizer = gdb.default_visualizer(val['c'])
 
     def children (self):
@@ -496,7 +511,10 @@ class StdRbtreeIteratorPrinter:
     def __init__ (self, typename, val):
         self.val = val
         valtype = self.val.type.template_argument(0).strip_typedefs()
-        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        nodetype = '_Rb_tree_node<' + str(valtype) + '>'
+        if _versioned_namespace and typename.startswith('std::' + _versioned_namespace):
+            nodetype = _versioned_namespace + nodetype
+        nodetype = gdb.lookup_type('std::' + nodetype)
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
@@ -552,7 +570,7 @@ class StdMapPrinter:
             return result
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def to_string (self):
@@ -592,7 +610,7 @@ class StdSetPrinter:
             return result
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def to_string (self):
@@ -609,7 +627,7 @@ class StdBitsetPrinter:
     "Print a std::bitset"
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def to_string (self):
@@ -679,7 +697,7 @@ class StdDequePrinter:
             return result
 
     def __init__(self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
         self.elttype = val.type.template_argument(0)
         size = self.elttype.sizeof
@@ -805,7 +823,7 @@ class Tr1UnorderedSetPrinter:
     "Print a tr1::unordered_set"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def hashtable (self):
@@ -831,7 +849,7 @@ class Tr1UnorderedMapPrinter:
     "Print a tr1::unordered_map"
 
     def __init__ (self, typename, val):
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
         self.val = val
 
     def hashtable (self):
@@ -897,7 +915,7 @@ class StdForwardListPrinter:
 
     def __init__(self, typename, val):
         self.val = val
-        self.typename = typename
+        self.typename = strip_versioned_namespace(typename)
 
     def children(self):
         nodetype = find_type(self.val.type, '_Node')
@@ -952,12 +970,12 @@ class SingleObjContainerPrinter(object):
             return self.visualizer.display_hint ()
         return self.hint
 
-
 class StdExpAnyPrinter(SingleObjContainerPrinter):
     "Print a std::any or std::experimental::any"
 
     def __init__ (self, typename, val):
         self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1)
+        self.typename = strip_versioned_namespace(self.typename)
         self.val = val
         self.contained_type = None
         contained_value = None
@@ -972,8 +990,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
             if not m:
                 raise ValueError("Unknown manager function in %s" % self.typename)
 
+            mgrname = m.group(1)
             # 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))
+            if 'std::string' in mgrname:
+                mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
+
             mgrtype = gdb.lookup_type(mgrname)
             self.contained_type = mgrtype.template_argument(0)
             valptr = None
@@ -994,7 +1015,7 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
         if hasattr (self.visualizer, 'children'):
             return desc + self.visualizer.to_string ()
         valtype = self._recognize (self.contained_type)
-        return desc + valtype
+        return desc + strip_versioned_namespace(str(valtype))
 
 class StdExpOptionalPrinter(SingleObjContainerPrinter):
     "Print a std::optional or std::experimental::optional"
@@ -1002,6 +1023,7 @@ class StdExpOptionalPrinter(SingleObjContainerPrinter):
     def __init__ (self, typename, val):
         valtype = self._recognize (val.type.template_argument(0))
         self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1)
+        self.typename = strip_versioned_namespace(self.typename)
         self.val = val
         contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
         visualizer = gdb.default_visualizer (val['_M_payload'])
@@ -1021,6 +1043,7 @@ class StdVariantPrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         alternatives = self._template_args(val)
         self.typename = "%s<%s>" % (typename, ', '.join([self._recognize(alt) for alt in alternatives]))
+        self.typename = strip_versioned_namespace(self.typename)
         self.index = val['_M_index']
         if self.index >= len(alternatives):
             self.contained_type = None
@@ -1058,7 +1081,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
     def __init__(self, typename, val):
         self.value_type = val.type.template_argument(1)
         nodetype = val.type.template_argument(2).template_argument(0)
-        self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+        self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node')
         self.is_map_node = val.type.template_argument(0) != self.value_type
         nodeptr = val['_M_ptr']
         if nodeptr:
@@ -1202,7 +1225,8 @@ class Printer(object):
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
     def add_version(self, base, name, function):
         self.add(base + name, function)
-        self.add(base + '__7::' + name, function)
+        if _versioned_namespace:
+            self.add(base + _versioned_namespace + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1294,8 +1318,14 @@ class TemplateTypePrinter(object):
         return self._recognizer(self.pattern, self.subst)
 
 def add_one_template_type_printer(obj, name, match, subst):
-    printer = TemplateTypePrinter(name, '^std::' + match + '$', 'std::' + subst)
+    match = '^std::' + match + '$'
+    printer = TemplateTypePrinter(name, match, 'std::' + subst)
     gdb.types.register_type_printer(obj, printer)
+    if _versioned_namespace:
+        # Add second type printer for same type in versioned namespace:
+        match = match.replace('std::', 'std::' + _versioned_namespace)
+        printer = TemplateTypePrinter(name, match, 'std::' + subst)
+        gdb.types.register_type_printer(obj, printer)
 
 class FilteringTypePrinter(object):
     def __init__(self, match, name):
@@ -1322,7 +1352,7 @@ class FilteringTypePrinter(object):
                 except:
                     pass
             if self.type_obj == type_obj:
-                return self.name
+                return strip_versioned_namespace(self.name)
             return None
 
     def instantiate(self):
@@ -1331,6 +1361,9 @@ class FilteringTypePrinter(object):
 def add_one_type_printer(obj, match, name):
     printer = FilteringTypePrinter(match, 'std::' + name)
     gdb.types.register_type_printer(obj, printer)
+    if _versioned_namespace:
+        printer = FilteringTypePrinter(match, 'std::' + _versioned_namespace + name)
+        gdb.types.register_type_printer(obj, printer)
 
 def register_type_printers(obj):
     global _use_type_printing
@@ -1372,9 +1405,9 @@ def register_type_printers(obj):
     # Note that we can't have a printer for std::wstreampos, because
     # it shares the same underlying type as std::streampos.
     add_one_type_printer(obj, 'fpos', 'streampos')
+
     add_one_type_printer(obj, 'basic_string', 'u16string')
     add_one_type_printer(obj, 'basic_string', 'u32string')
-
     add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
     add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
 
@@ -1397,6 +1430,10 @@ def register_type_printers(obj):
             'unique_ptr<(.*), std::default_delete<\\1 ?> >',
             'unique_ptr<{1}>')
 
+    add_one_template_type_printer(obj, 'basic_string<T>',
+            'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
+            'basic_string<{1}>')
+
     add_one_template_type_printer(obj, 'deque<T>',
             'deque<(.*), std::allocator<\\1 ?> >',
             'deque<{1}>')
@@ -1465,11 +1502,6 @@ def build_libstdcxx_dictionary ():
 
     libstdcxx_printer = Printer("libstdc++-v6")
 
-    # For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
-    vers = '(__7::)?'
-    # For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
-    container = '(__cxx1998::' + vers + ')?'
-
     # libstdc++ objects requiring pretty-printing.
     # In order from:
     # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
index def72b0..02feab6 100644
--- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py
+++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::array<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::deque<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::forward_list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::vector<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::%s<.*>$' % self._name, class_type.tag):
+        if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -586,9 +586,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
 
     def __call__(self, obj):
         impl_type = obj.dereference().type.fields()[0].type.tag
-        if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+        if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
             return obj['_M_t']['_M_t']['_M_head_impl']
-        elif impl_type.startswith('std::tuple<'):
+        elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
             return obj['_M_t']['_M_head_impl']
         return None
 
@@ -640,7 +640,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
@@ -758,7 +758,7 @@ class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
         self.methods = [self._method_dict[m] for m in self._method_dict]
 
     def match(self, class_type, method_name):
-        if not re.match('^std::shared_ptr<.*>$', class_type.tag):
+        if not re.match('^std::(__\d+::)?shared_ptr<.*>$', class_type.tag):
             return None
         method = self._method_dict.get(method_name)
         if method is None or not method.enabled:
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
index 16ef07b..998b6d5 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
@@ -26,10 +26,10 @@ int
 main()
 {
   std::tuple<> t1;
-// { dg-final { regexp-test t1 {empty std::(__7::)?tuple} } }
+// { dg-final { regexp-test t1 {empty std::tuple} } }
 
   std::tuple<std::string, int, std::tuple<>> t2{ "Johnny", 5, {} };
-// { dg-final { regexp-test t2 {std::(__7::)?tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::(__7::)?tuple, <No data fields>}}} } }
+// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::tuple, <No data fields>}}} } }
 
   std::cout << "\n";
   return 0; // Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index 31ded8b..7a55bb7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -166,11 +166,11 @@ holder<std::knuth_b> knuth_b_holder;
 
 ustring *ustring_ptr;
 holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char> >" } }
 
 std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char> >" } }
 
 std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
 holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2017-01-10 12:39                     ` Jonathan Wakely
@ 2017-01-19 21:22                       ` François Dumont
  2017-01-19 21:42                         ` Jonathan Wakely
  0 siblings, 1 reply; 17+ messages in thread
From: François Dumont @ 2017-01-19 21:22 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2213 bytes --]

On 10/01/2017 13:39, Jonathan Wakely wrote:
> I've committed the attached patch, which passes the tests for the
> default configuration and the versioned namespace configuration.
>
> I added another helper function, strip_versioned_namespace, which is
> more expressive than doing typename.replace(vers_nsp, '') everywhere.
> I've also renamed vers_nsp to _versioned_namespace (using the naming
> convention for global variables private to the module). I've added
> checks so that if that variable is None then the extra printers and
> special cases for the versioned namespace are skipped. That's not
> currently used, but it would allow us to optimise things later if
> needed.

Very nice feature indeed, see below.

>
> I also needed to update the new SharedPtrMethodsMatcher to add
> "(__\d+)?" to the regular expression.
>
>
>> @@ -1392,47 +1406,54 @@ def register_type_printers(obj):
>>     add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
>>     add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
>>
>> +    # Consider optional versioned namespace
>> +    opt_nsp = '(' + vers_nsp + ')?'
>> +
>>     # Do not show defaulted template arguments in class templates
>>     add_one_template_type_printer(obj, 'unique_ptr<T>',
>> -            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
>> -            'unique_ptr<{1}>')
>> +        '{0}unique_ptr<(.*), std::{0}default_delete<\\2 ?> 
>> >'.format(opt_nsp),
>> +        'unique_ptr<{2}>')
>
> This is ugly. Mixing python string formatting with regular expressions
> makes it harder to read, and is inconsistent with how the versioned
> namespace is handled elsewhere. In Printer.add_version and
> add_one_type_printer we just register two names, one using std:: and
> one using std::__7::. We can do the same for the template type
> printers.

     Yes, your approach is much nicer even if it results in more type 
printer registered.

     My plan was to submit the attached patch but this doesn't work as 
the python module seems to be loaded before libstdc++.so. If you know a 
way to test for versioned namespace before starting registering printers 
this patch might still be useful. Otherwise I will just forget it.

François

[-- Attachment #2: prettyprinters.patch --]
[-- Type: text/x-patch, Size: 8313 bytes --]

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 36dd81d..5e42988 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -79,6 +79,15 @@ try:
 except ImportError:
     pass
 
+_versioned_namespace = None
+
+# Use std::string to find out if versioned namespace has been activated.
+try:
+    gdb.lookup_type('std::string')
+except RuntimeError:
+    _versioned_namespace = '__7::'
+    pass
+
 # Starting with the type ORIG, search for the member type NAME.  This
 # handles searching upward through superclasses.  This is needed to
 # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615.
@@ -100,8 +109,6 @@ def find_type(orig, name):
             raise ValueError("Cannot find type %s::%s" % (str(orig), name))
         typ = field.type
 
-_versioned_namespace = '__7::'
-
 # Test if a type is a given template instantiation.
 def is_specialization_of(type, template_name):
     global _versioned_namespace
@@ -1222,11 +1229,12 @@ class Printer(object):
         self.subprinters.append(printer)
         self.lookup[name] = printer
 
-    # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
+    # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION if needed.
     def add_version(self, base, name, function):
-        self.add(base + name, function)
         if _versioned_namespace:
             self.add(base + _versioned_namespace + name, function)
+        else:
+            self.add(base + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1319,13 +1327,11 @@ class TemplateTypePrinter(object):
 
 def add_one_template_type_printer(obj, name, match, subst):
     match = '^std::' + match + '$'
-    printer = TemplateTypePrinter(name, match, 'std::' + subst)
-    gdb.types.register_type_printer(obj, printer)
     if _versioned_namespace:
-        # Add second type printer for same type in versioned namespace:
+        # Add type printer in versioned namespace:
         match = match.replace('std::', 'std::' + _versioned_namespace)
-        printer = TemplateTypePrinter(name, match, 'std::' + subst)
-        gdb.types.register_type_printer(obj, printer)
+    printer = TemplateTypePrinter(name, match, 'std::' + subst)
+    gdb.types.register_type_printer(obj, printer)
 
 class FilteringTypePrinter(object):
     def __init__(self, match, name):
@@ -1359,11 +1365,11 @@ class FilteringTypePrinter(object):
         return self._recognizer(self.match, self.name)
 
 def add_one_type_printer(obj, match, name):
-    printer = FilteringTypePrinter(match, 'std::' + name)
-    gdb.types.register_type_printer(obj, printer)
+    namespace = 'std::'
     if _versioned_namespace:
-        printer = FilteringTypePrinter(match, 'std::' + _versioned_namespace + name)
-        gdb.types.register_type_printer(obj, printer)
+        namespace += _versioned_namespace
+    printer = FilteringTypePrinter(match, namespace + name)
+    gdb.types.register_type_printer(obj, printer)
 
 def register_type_printers(obj):
     global _use_type_printing
@@ -1427,60 +1433,60 @@ def register_type_printers(obj):
 
     # Do not show defaulted template arguments in class templates
     add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
+        'unique_ptr<(.*), std::default_delete<\\1 ?> >',
+        'unique_ptr<{1}>')
 
     add_one_template_type_printer(obj, 'basic_string<T>',
-            'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
-            'basic_string<{1}>')
+        'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
+        'basic_string<{1}>')
 
     add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
+        'deque<(.*), std::allocator<\\1 ?> >',
+        'deque<{1}>')
     add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
+        'forward_list<(.*), std::allocator<\\1 ?> >',
+        'forward_list<{1}>')
     add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
+        'list<(.*), std::allocator<\\1 ?> >',
+        'list<{1}>')
     add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
+        'vector<(.*), std::allocator<\\1 ?> >',
+        'vector<{1}>')
     add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
+        'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'map<{1}, {2}>')
     add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
+        'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'multimap<{1}, {2}>')
     add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
+        'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+        'set<{1}>')
     add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
+        'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+        'multiset<{1}>')
     add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
+        'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'unordered_map<{1}, {2}>')
     add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
+        'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'unordered_multimap<{1}, {2}>')
     add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
+        'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+        'unordered_set<{1}>')
     add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+        'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+        'unordered_multiset<{1}>')
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
-            'experimental::fundamentals_v\d::any<(.*)>',
-            'experimental::any<\\1>')
+        'experimental::fundamentals_v\d::any<(.*)>',
+        'experimental::any<\\1>')
     add_one_template_type_printer(obj, 'optional<T>',
-            'experimental::fundamentals_v\d::optional<(.*)>',
-            'experimental::optional<\\1>')
+        'experimental::fundamentals_v\d::optional<(.*)>',
+        'experimental::optional<\\1>')
     add_one_template_type_printer(obj, 'basic_string_view<C>',
-            'experimental::fundamentals_v\d::basic_string_view<(.*), std::char_traits<\\1> >',
-            'experimental::basic_string_view<\\1>')
+        'experimental::fundamentals_v\d::basic_string_view<(.*), std::char_traits<\\1> >',
+        'experimental::basic_string_view<\\1>')
 
 def register_libstdcxx_printers (obj):
     "Register libstdc++ pretty-printers with objfile Obj."



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
  2017-01-19 21:22                       ` François Dumont
@ 2017-01-19 21:42                         ` Jonathan Wakely
       [not found]                           ` <b26a2ed4-ac83-ede4-ed9c-f3b328d7bc4a@gmail.com>
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Wakely @ 2017-01-19 21:42 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2416 bytes --]

On 19/01/17 22:01 +0100, François Dumont wrote:
>On 10/01/2017 13:39, Jonathan Wakely wrote:
>>I've committed the attached patch, which passes the tests for the
>>default configuration and the versioned namespace configuration.
>>
>>I added another helper function, strip_versioned_namespace, which is
>>more expressive than doing typename.replace(vers_nsp, '') everywhere.
>>I've also renamed vers_nsp to _versioned_namespace (using the naming
>>convention for global variables private to the module). I've added
>>checks so that if that variable is None then the extra printers and
>>special cases for the versioned namespace are skipped. That's not
>>currently used, but it would allow us to optimise things later if
>>needed.
>
>Very nice feature indeed, see below.
>
>>
>>I also needed to update the new SharedPtrMethodsMatcher to add
>>"(__\d+)?" to the regular expression.
>>
>>
>>>@@ -1392,47 +1406,54 @@ def register_type_printers(obj):
>>>    add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
>>>    add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
>>>
>>>+    # Consider optional versioned namespace
>>>+    opt_nsp = '(' + vers_nsp + ')?'
>>>+
>>>    # Do not show defaulted template arguments in class templates
>>>    add_one_template_type_printer(obj, 'unique_ptr<T>',
>>>-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
>>>-            'unique_ptr<{1}>')
>>>+        '{0}unique_ptr<(.*), std::{0}default_delete<\\2 ?> 
>>>>'.format(opt_nsp),
>>>+        'unique_ptr<{2}>')
>>
>>This is ugly. Mixing python string formatting with regular expressions
>>makes it harder to read, and is inconsistent with how the versioned
>>namespace is handled elsewhere. In Printer.add_version and
>>add_one_type_printer we just register two names, one using std:: and
>>one using std::__7::. We can do the same for the template type
>>printers.
>
>    Yes, your approach is much nicer even if it results in more type 
>printer registered.
>
>    My plan was to submit the attached patch but this doesn't work as 
>the python module seems to be loaded before libstdc++.so. If you know 
>a way to test for versioned namespace before starting registering 
>printers this patch might still be useful. Otherwise I will just 
>forget it.

See the attached patch, which decides at configure-time whether to
enable the versioned namespace printers or not. This is what I had in
mind.




[-- Attachment #2: versioned.patch --]
[-- Type: text/plain, Size: 2301 bytes --]

diff --git a/libstdc++-v3/python/Makefile.am b/libstdc++-v3/python/Makefile.am
index 80790e2..5d19d3d 100644
--- a/libstdc++-v3/python/Makefile.am
+++ b/libstdc++-v3/python/Makefile.am
@@ -29,6 +29,12 @@ else
 pythondir = $(datadir)/gcc-$(gcc_version)/python
 endif
 
+if ENABLE_SYMVERS_GNU_NAMESPACE
+use_versioned_namespace = True
+else
+use_versioned_namespace = False
+endif
+
 all-local: gdb.py
 
 nobase_python_DATA = \
@@ -39,7 +45,9 @@ nobase_python_DATA = \
 
 gdb.py: hook.in Makefile
 	sed -e 's,@pythondir@,$(pythondir),' \
-	    -e 's,@toolexeclibdir@,$(toolexeclibdir),' < $(srcdir)/hook.in > $@
+	    -e 's,@toolexeclibdir@,$(toolexeclibdir),' \
+	    -e 's,@use_versioned_namespace@,$(use_versioned_namespace),' \
+	    < $(srcdir)/hook.in > $@
 
 install-data-local: gdb.py
 	@$(mkdir_p) $(DESTDIR)$(toolexeclibdir)
diff --git a/libstdc++-v3/python/hook.in b/libstdc++-v3/python/hook.in
index b82604a6c..1b3a577 100644
--- a/libstdc++-v3/python/hook.in
+++ b/libstdc++-v3/python/hook.in
@@ -58,4 +58,4 @@ if gdb.current_objfile () is not None:
 # Call a function as a plain import would not execute body of the included file
 # on repeated reloads of this object file.
 from libstdcxx.v6 import register_libstdcxx_printers
-register_libstdcxx_printers(gdb.current_objfile())
+register_libstdcxx_printers(gdb.current_objfile(), @use_versioned_namespace@)
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 36dd81d..4a7d117 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1482,7 +1482,7 @@ def register_type_printers(obj):
             'experimental::fundamentals_v\d::basic_string_view<(.*), std::char_traits<\\1> >',
             'experimental::basic_string_view<\\1>')
 
-def register_libstdcxx_printers (obj):
+def register_libstdcxx_printers (obj, use_versioned_namespace = False):
     "Register libstdc++ pretty-printers with objfile Obj."
 
     global _use_gdb_pp
@@ -1495,6 +1495,9 @@ def register_libstdcxx_printers (obj):
             obj = gdb
         obj.pretty_printers.append(libstdcxx_printer)
 
+    if not use_versioned_namespace:
+        _versioned_namespace = None
+
     register_type_printers(obj)
 
 def build_libstdcxx_dictionary ():

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Pretty printers for versioned namespace
       [not found]                                   ` <a6f4717a-1d63-beb6-6a93-c111969ce4fa@gmail.com>
@ 2017-02-16 12:26                                     ` Jonathan Wakely
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Wakely @ 2017-02-16 12:26 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 15/02/17 22:44 +0100, François Dumont wrote:
>Hi
>
>    Here is the end result. I eventually chose to detect usage of 
>versioned namespace while generating the .gdb file. I haven't use any 
>caching mecanism considering the limited number of test cases.
>
>    Tested under Linux x86_64 with and without versioned namespace.
>
>    * python/Makefile.am (use_versioned_namespace): New.
>    (gdb.py): Subst use_versioned_namespace.
>    * python/Makefile.in: Regenerate.
>    * python/hook.in: Adapt.
>    * python/libstdcxx/v6/printers.py (Printer.add_version): Add name
>    versioned namespace if _versioned_namespace is defined.
>    (Printer.add_one_template_type_printer): Likewise
>    (add_one_type_printer): Likewise.
>    (register_libstdcxx_printers): Add parameter to indicate if versioned
>    namespace is active.
>    * testsuite/lib/gdb-test.exp (get_use_versioned_namespace): New.
>    (gdb-test): Use latter.
>    * testsuite/libstdc++-prettyprinters/48362.cc: Prefer note-test to
>    regexp-test.
>
>Ok to commit to trunk ?

No, I thought the point of the use_versioned_namespace parameter was
to optimise thigns later, if needed. Do we need to do it?

We certainly don't need to do it during stage 4, as it's not actually
fixing any bug.

Let's reconsider during stage 1.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2017-02-16 12:11 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-28 21:19 Pretty printers for versioned namespace François Dumont
2016-11-29 20:17 ` Jonathan Wakely
2016-12-01 21:51   ` François Dumont
2016-12-02  0:42     ` Jonathan Wakely
2016-12-09 12:56       ` François Dumont
2016-12-09 15:18         ` Jonathan Wakely
2016-12-14 21:53           ` François Dumont
2016-12-15 11:15             ` Jonathan Wakely
2016-12-15 14:51             ` Jonathan Wakely
2016-12-15 15:52             ` Jonathan Wakely
2016-12-24 16:29               ` François Dumont
2017-01-04 12:52                 ` Jonathan Wakely
2017-01-09 20:25                   ` François Dumont
2017-01-10 12:39                     ` Jonathan Wakely
2017-01-19 21:22                       ` François Dumont
2017-01-19 21:42                         ` Jonathan Wakely
     [not found]                           ` <b26a2ed4-ac83-ede4-ed9c-f3b328d7bc4a@gmail.com>
     [not found]                             ` <20170131144204.GX3093@redhat.com>
     [not found]                               ` <2c905325-8839-bb5d-4885-0103801a6264@gmail.com>
     [not found]                                 ` <20170213223132.GV4602@redhat.com>
     [not found]                                   ` <a6f4717a-1d63-beb6-6a93-c111969ce4fa@gmail.com>
2017-02-16 12:26                                     ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).