diff mbox

Pretty printers for versioned namespace

Message ID 1a5de3bf-9cfc-3569-6dc8-7ffcd99c286f@gmail.com
State New
Headers show

Commit Message

François Dumont Dec. 9, 2016, 12:55 p.m. UTC
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

Comments

Jonathan Wakely Dec. 9, 2016, 3:18 p.m. UTC | #1
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
diff mbox

Patch

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