Patchwork RFA: fix PR 51649

login
register
mail settings
Submitter Tom Tromey
Date Jan. 23, 2012, 7:36 p.m.
Message ID <m3wr8ijjo1.fsf@fleche.redhat.com>
Download mbox | patch
Permalink /patch/137462/
State New
Headers show

Comments

Tom Tromey - Jan. 23, 2012, 7:36 p.m.
This patch fixes some pretty-printer bugs pointed out in PR 51649.

The bug in the PR is that the pretty-printers don't work if you build
with --enable-symvers=gnu-versioned-namespace.

This patch adds test cases for all the changes I made.

I derived most of the information here from reading c++config, then
going through the existing printers one-by-one to see how they are
implemented in the various modes.

Still missing are tests for parallel and profile modes.

I wasn't sure whether we need a printer for the stuff in vstring.h.
Anybody know?

The old code referred to a __norm namespace.  I only found a single
instance of this in the tree, which seemed to indicate it is a
compatibility thing.  So, I ignored it.  (I think that if there is a
problem here we should start with a test that shows it...)

I built and tested this with --enable-symvers=gnu-versioned-namespace
and with the default on x86-64 Fedora 15.

I'm sufficiently out of the loop gcc-wise that I will need some advice
as to whether this can go in immediately or whether it must wait for
some other stage.

Ok?

Tom

2012-01-23  Tom Tromey  <tromey@redhat.com>

	PR libstdc++/51649:
	* testsuite/libstdc++-prettyprinters/debug.cc: New file.
	* testsuite/lib/gdb-test.exp (regexp-test): New proc.
	(note-test): Update.
	(gdb-test): Handle regexp tests.  Add some logging.
	* testsuite/libstdc++-prettyprinters/simple.cc: Compile with -O0.
	(placeholder, use): Remove.
	(main): Add tests for deque, list, map, and set iterators.  Add
	tests for slist and slist iterator.
	* testsuite/libstdc++-prettyprinters/48362.cc (main): Handle __7
	namespace.
	* python/libstdcxx/v6/printers.py (StdListPrinter.children): Use
	the type's _Node typedef.
	(StdListIteratorPrinter.to_string): Change how node type is
	computed.
	(StdSlistPrinter.children): Use the type's _Node typedef.
	(StdSlistIteratorPrinter.to_string): Likewise.
	(StdRbtreeIteratorPrinter.to_string): Use the type's _Link_type
	typedef.
	(StdMapPrinter.children): Change how the node's type is computed.
	(StdSetPrinter.children): Likewise.
	(StdForwardListPrinter.children): Use the type's _Node typedef.
	(Printer.add_version): New method.
	(Printer.add_container): New method.
	(build_libstdcxx_dictionary): Handle __7 and __cxx1998
	namespaces.
	(find_type): New function.
Richard Guenther - Jan. 24, 2012, 10:29 a.m.
On Mon, Jan 23, 2012 at 8:36 PM, Tom Tromey <tromey@redhat.com> wrote:
> This patch fixes some pretty-printer bugs pointed out in PR 51649.
>
> The bug in the PR is that the pretty-printers don't work if you build
> with --enable-symvers=gnu-versioned-namespace.
>
> This patch adds test cases for all the changes I made.
>
> I derived most of the information here from reading c++config, then
> going through the existing printers one-by-one to see how they are
> implemented in the various modes.
>
> Still missing are tests for parallel and profile modes.
>
> I wasn't sure whether we need a printer for the stuff in vstring.h.
> Anybody know?
>
> The old code referred to a __norm namespace.  I only found a single
> instance of this in the tree, which seemed to indicate it is a
> compatibility thing.  So, I ignored it.  (I think that if there is a
> problem here we should start with a test that shows it...)
>
> I built and tested this with --enable-symvers=gnu-versioned-namespace
> and with the default on x86-64 Fedora 15.
>
> I'm sufficiently out of the loop gcc-wise that I will need some advice
> as to whether this can go in immediately or whether it must wait for
> some other stage.

We're technically in regression-fixes-only mode.  We give target/language
maintainers some extra freedom though - while C++/libstdc++ are considered
release critical and thus should not regress at this point I'm less sure
about all the pretty-printing stuff - it can't possibly break anything
but debugging
experience.

Richard.

> Ok?
>
> Tom
>
> 2012-01-23  Tom Tromey  <tromey@redhat.com>
>
>        PR libstdc++/51649:
>        * testsuite/libstdc++-prettyprinters/debug.cc: New file.
>        * testsuite/lib/gdb-test.exp (regexp-test): New proc.
>        (note-test): Update.
>        (gdb-test): Handle regexp tests.  Add some logging.
>        * testsuite/libstdc++-prettyprinters/simple.cc: Compile with -O0.
>        (placeholder, use): Remove.
>        (main): Add tests for deque, list, map, and set iterators.  Add
>        tests for slist and slist iterator.
>        * testsuite/libstdc++-prettyprinters/48362.cc (main): Handle __7
>        namespace.
>        * python/libstdcxx/v6/printers.py (StdListPrinter.children): Use
>        the type's _Node typedef.
>        (StdListIteratorPrinter.to_string): Change how node type is
>        computed.
>        (StdSlistPrinter.children): Use the type's _Node typedef.
>        (StdSlistIteratorPrinter.to_string): Likewise.
>        (StdRbtreeIteratorPrinter.to_string): Use the type's _Link_type
>        typedef.
>        (StdMapPrinter.children): Change how the node's type is computed.
>        (StdSetPrinter.children): Likewise.
>        (StdForwardListPrinter.children): Use the type's _Node typedef.
>        (Printer.add_version): New method.
>        (Printer.add_container): New method.
>        (build_libstdcxx_dictionary): Handle __7 and __cxx1998
>        namespaces.
>        (find_type): New function.
>
> Index: python/libstdcxx/v6/printers.py
> ===================================================================
> --- python/libstdcxx/v6/printers.py     (revision 183449)
> +++ python/libstdcxx/v6/printers.py     (working copy)
> @@ -1,6 +1,6 @@
>  # Pretty-printers for libstc++.
>
> -# Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
> +# Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
>
>  # This program is free software; you can redistribute it and/or modify
>  # it under the terms of the GNU General Public License as published by
> @@ -26,6 +26,25 @@
>  except ImportError:
>     _use_gdb_pp = False
>
> +# 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.
> +def find_type(orig, name):
> +    typ = orig.strip_typedefs()
> +    while True:
> +        search = str(typ) + '::' + name
> +        try:
> +            return gdb.lookup_type(search)
> +        except RuntimeError:
> +            pass
> +        # The type was not found, so try the superclass.  We only need
> +        # to check the first superclass, so we don't bother with
> +        # anything fancier here.
> +        field = typ.fields()[0]
> +        if not field.is_base_class:
> +            raise ValueError, "Cannot find type %s::%s" % (str(orig), name)
> +        typ = field.type
> +
>  class StdPointerPrinter:
>     "Print a smart pointer of some kind"
>
> @@ -76,15 +95,8 @@
>         self.val = val
>
>     def children(self):
> -        itype = self.val.type.template_argument(0)
> -        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
> -        # some of the internal implementation details change.
> -        if self.typename == "std::list":
> -            nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
> -        elif self.typename == "std::__debug::list":
> -            nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer()
> -        else:
> -            raise ValueError, "Cannot cast list node for list printer."
> +        nodetype = find_type(self.val.type, '_Node')
> +        nodetype = nodetype.strip_typedefs().pointer()
>         return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
>
>     def to_string(self):
> @@ -100,15 +112,8 @@
>         self.typename = typename
>
>     def to_string(self):
> -        itype = self.val.type.template_argument(0)
> -        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
> -        # some of the internal implementation details change.
> -        if self.typename == "std::_List_iterator" or self.typename == "std::_List_const_iterator":
> -            nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
> -        elif self.typename == "std::__norm::_List_iterator" or self.typename == "std::__norm::_List_const_iterator":
> -            nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer()
> -        else:
> -            raise ValueError, "Cannot cast list node for list iterator printer."
> +        nodetype = find_type(self.val.type, '_Node')
> +        nodetype = nodetype.strip_typedefs().pointer()
>         return self.val['_M_node'].cast(nodetype).dereference()['_M_data']
>
>  class StdSlistPrinter:
> @@ -136,8 +141,8 @@
>         self.val = val
>
>     def children(self):
> -        itype = self.val.type.template_argument(0)
> -        nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer()
> +        nodetype = find_type(self.val.type, '_Node')
> +        nodetype = nodetype.strip_typedefs().pointer()
>         return self._iterator(nodetype, self.val)
>
>     def to_string(self):
> @@ -152,8 +157,8 @@
>         self.val = val
>
>     def to_string(self):
> -        itype = self.val.type.template_argument(0)
> -        nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer()
> +        nodetype = find_type(self.val.type, '_Node')
> +        nodetype = nodetype.strip_typedefs().pointer()
>         return self.val['_M_node'].cast(nodetype).dereference()['_M_data']
>
>  class StdVectorPrinter:
> @@ -364,9 +369,8 @@
>         self.val = val
>
>     def to_string (self):
> -        valuetype = self.val.type.template_argument(0)
> -        nodetype = gdb.lookup_type('std::_Rb_tree_node < %s >' % valuetype)
> -        nodetype = nodetype.pointer()
> +        typename = str(self.val.type.strip_typedefs()) + '::_Link_type'
> +        nodetype = gdb.lookup_type(typename).strip_typedefs()
>         return self.val.cast(nodetype).dereference()['_M_value_field']
>
>  class StdDebugIteratorPrinter:
> @@ -415,11 +419,10 @@
>                                         len (RbtreeIterator (self.val)))
>
>     def children (self):
> -        keytype = self.val.type.template_argument(0).const()
> -        valuetype = self.val.type.template_argument(1)
> -        nodetype = gdb.lookup_type('std::_Rb_tree_node< std::pair< %s, %s > >' % (keytype, valuetype))
> -        nodetype = nodetype.pointer()
> -        return self._iter (RbtreeIterator (self.val), nodetype)
> +        rep_type = find_type(self.val.type, '_Rep_type')
> +        node = find_type(rep_type, '_Link_type')
> +        node = node.strip_typedefs()
> +        return self._iter (RbtreeIterator (self.val), node)
>
>     def display_hint (self):
>         return 'map'
> @@ -455,9 +458,10 @@
>                                         len (RbtreeIterator (self.val)))
>
>     def children (self):
> -        keytype = self.val.type.template_argument(0)
> -        nodetype = gdb.lookup_type('std::_Rb_tree_node< %s >' % keytype).pointer()
> -        return self._iter (RbtreeIterator (self.val), nodetype)
> +        rep_type = find_type(self.val.type, '_Rep_type')
> +        node = find_type(rep_type, '_Link_type')
> +        node = node.strip_typedefs()
> +        return self._iter (RbtreeIterator (self.val), node)
>
>  class StdBitsetPrinter:
>     "Print a std::bitset"
> @@ -713,15 +717,8 @@
>         self.typename = typename
>
>     def children(self):
> -        itype = self.val.type.template_argument(0)
> -        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
> -        # some of the internal implementation details change.
> -        if self.typename == "std::forward_list":
> -            nodetype = gdb.lookup_type('std::_Fwd_list_node<%s>' % itype).pointer()
> -        elif self.typename == "std::__debug::list":
> -            nodetype = gdb.lookup_type('std::__norm::_Fwd_list_node<%s>' % itype).pointer()
> -        else:
> -            raise ValueError, "Cannot cast forward_list node for forward_list printer."
> +        nodetype = find_type(self.val.type, '_Node')
> +        nodetype = nodetype.strip_typedefs().pointer()
>         return self._iterator(nodetype, self.val['_M_impl']['_M_head'])
>
>     def to_string(self):
> @@ -764,6 +761,16 @@
>         self.subprinters.append(printer)
>         self.lookup[name] = printer
>
> +    # 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)
> +
> +    # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
> +    def add_container(self, base, name, function):
> +        self.add_version(base, name, function)
> +        self.add_version(base + '__cxx1998::', name, function)
> +
>     @staticmethod
>     def get_basic_type(type):
>         # If it points to a reference, get the reference.
> @@ -813,23 +820,29 @@
>
>     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
> -    libstdcxx_printer.add('std::basic_string', StdStringPrinter)
> -    libstdcxx_printer.add('std::bitset', StdBitsetPrinter)
> -    libstdcxx_printer.add('std::deque', StdDequePrinter)
> -    libstdcxx_printer.add('std::list', StdListPrinter)
> -    libstdcxx_printer.add('std::map', StdMapPrinter)
> -    libstdcxx_printer.add('std::multimap', StdMapPrinter)
> -    libstdcxx_printer.add('std::multiset', StdSetPrinter)
> -    libstdcxx_printer.add('std::priority_queue', StdStackOrQueuePrinter)
> -    libstdcxx_printer.add('std::queue', StdStackOrQueuePrinter)
> -    libstdcxx_printer.add('std::tuple', StdTuplePrinter)
> -    libstdcxx_printer.add('std::set', StdSetPrinter)
> -    libstdcxx_printer.add('std::stack', StdStackOrQueuePrinter)
> -    libstdcxx_printer.add('std::unique_ptr', UniquePointerPrinter)
> -    libstdcxx_printer.add('std::vector', StdVectorPrinter)
> +    libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter)
> +    libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter)
> +    libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter)
> +    libstdcxx_printer.add_container('std::', 'list', StdListPrinter)
> +    libstdcxx_printer.add_container('std::', 'map', StdMapPrinter)
> +    libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter)
> +    libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter)
> +    libstdcxx_printer.add_version('std::', 'priority_queue',
> +                                  StdStackOrQueuePrinter)
> +    libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter)
> +    libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter)
> +    libstdcxx_printer.add_container('std::', 'set', StdSetPrinter)
> +    libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter)
> +    libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter)
> +    libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter)
>     # vector<bool>
>
>     # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG.
> @@ -849,22 +862,29 @@
>
>     # These are the TR1 and C++0x printers.
>     # For array - the default GDB pretty-printer seems reasonable.
> -    libstdcxx_printer.add('std::shared_ptr', StdPointerPrinter)
> -    libstdcxx_printer.add('std::weak_ptr', StdPointerPrinter)
> -    libstdcxx_printer.add('std::unordered_map', Tr1UnorderedMapPrinter)
> -    libstdcxx_printer.add('std::unordered_set', Tr1UnorderedSetPrinter)
> -    libstdcxx_printer.add('std::unordered_multimap', Tr1UnorderedMapPrinter)
> -    libstdcxx_printer.add('std::unordered_multiset', Tr1UnorderedSetPrinter)
> -    libstdcxx_printer.add('std::forward_list', StdForwardListPrinter)
> +    libstdcxx_printer.add_version('std::', 'shared_ptr', StdPointerPrinter)
> +    libstdcxx_printer.add_version('std::', 'weak_ptr', StdPointerPrinter)
> +    libstdcxx_printer.add_container('std::', 'unordered_map',
> +                                    Tr1UnorderedMapPrinter)
> +    libstdcxx_printer.add_container('std::', 'unordered_set',
> +                                    Tr1UnorderedSetPrinter)
> +    libstdcxx_printer.add_container('std::', 'unordered_multimap',
> +                                    Tr1UnorderedMapPrinter)
> +    libstdcxx_printer.add_container('std::', 'unordered_multiset',
> +                                    Tr1UnorderedSetPrinter)
> +    libstdcxx_printer.add_container('std::', 'forward_list',
> +                                    StdForwardListPrinter)
>
> -    libstdcxx_printer.add('std::tr1::shared_ptr', StdPointerPrinter)
> -    libstdcxx_printer.add('std::tr1::weak_ptr', StdPointerPrinter)
> -    libstdcxx_printer.add('std::tr1::unordered_map', Tr1UnorderedMapPrinter)
> -    libstdcxx_printer.add('std::tr1::unordered_set', Tr1UnorderedSetPrinter)
> -    libstdcxx_printer.add('std::tr1::unordered_multimap',
> -                          Tr1UnorderedMapPrinter)
> -    libstdcxx_printer.add('std::tr1::unordered_multiset',
> -                          Tr1UnorderedSetPrinter)
> +    libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', StdPointerPrinter)
> +    libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', StdPointerPrinter)
> +    libstdcxx_printer.add_version('std::tr1::', 'unordered_map',
> +                                  Tr1UnorderedMapPrinter)
> +    libstdcxx_printer.add_version('std::tr1::', 'unordered_set',
> +                                  Tr1UnorderedSetPrinter)
> +    libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap',
> +                                  Tr1UnorderedMapPrinter)
> +    libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
> +                                  Tr1UnorderedSetPrinter)
>
>     # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases.
>     # The tr1 namespace printers do not seem to have any debug
> @@ -882,25 +902,27 @@
>
>
>     # Extensions.
> -    libstdcxx_printer.add('__gnu_cxx::slist', StdSlistPrinter)
> +    libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
>
>     if True:
>         # These shouldn't be necessary, if GDB "print *i" worked.
>         # But it often doesn't, so here they are.
> -        libstdcxx_printer.add('std::_List_iterator', StdListIteratorPrinter)
> -        libstdcxx_printer.add('std::_List_const_iterator',
> -                              StdListIteratorPrinter)
> -        libstdcxx_printer.add('std::_Rb_tree_iterator',
> -                              StdRbtreeIteratorPrinter)
> -        libstdcxx_printer.add('std::_Rb_tree_const_iterator',
> -                              StdRbtreeIteratorPrinter)
> -        libstdcxx_printer.add('std::_Deque_iterator', StdDequeIteratorPrinter)
> -        libstdcxx_printer.add('std::_Deque_const_iterator',
> -                              StdDequeIteratorPrinter)
> -        libstdcxx_printer.add('__gnu_cxx::__normal_iterator',
> -                              StdVectorIteratorPrinter)
> -        libstdcxx_printer.add('__gnu_cxx::_Slist_iterator',
> -                              StdSlistIteratorPrinter)
> +        libstdcxx_printer.add_container('std::', '_List_iterator',
> +                                        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_container('std::', '_Deque_iterator',
> +                                        StdDequeIteratorPrinter)
> +        libstdcxx_printer.add_container('std::', '_Deque_const_iterator',
> +                                        StdDequeIteratorPrinter)
> +        libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator',
> +                                      StdVectorIteratorPrinter)
> +        libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator',
> +                                      StdSlistIteratorPrinter)
>
>         # Debug (compiled with -D_GLIBCXX_DEBUG) printer
>         # registrations.  The Rb_tree debug iterator when unwrapped
> Index: testsuite/libstdc++-prettyprinters/48362.cc
> ===================================================================
> --- testsuite/libstdc++-prettyprinters/48362.cc (revision 183449)
> +++ testsuite/libstdc++-prettyprinters/48362.cc (working copy)
> @@ -1,7 +1,7 @@
>  // { dg-do run }
>  // { dg-options "-g -std=gnu++11 -O0" }
>
> -// Copyright (C) 2011 Free Software Foundation, Inc.
> +// Copyright (C) 2011, 2012 Free Software Foundation, Inc.
>  //
>  // This file is part of the GNU ISO C++ Library.  This library is free
>  // software; you can redistribute it and/or modify it under the
> @@ -25,10 +25,10 @@
>  main()
>  {
>   std::tuple<> t1;
> -// { dg-final { note-test t1 {empty std::tuple} } }
> +// { dg-final { regexp-test t1 {empty std::(__7::)?tuple} } }
>
>   std::tuple<std::string, int, std::tuple<>> t2{ "Johnny", 5, {} };
> -// { dg-final { note-test t2 {std::tuple containing = {[1] = "Johnny", [2] = 5, [3] = {<std::tuple<>> = empty std::tuple, <No data fields>}}} } }
> +// { dg-final { regexp-test t2 {std::(__7::)?tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::(__7::)?tuple, <No data fields>}}} } }
>
>   return 0; // Mark SPOT
>  }
> Index: testsuite/libstdc++-prettyprinters/debug.cc
> ===================================================================
> --- testsuite/libstdc++-prettyprinters/debug.cc (revision 0)
> +++ testsuite/libstdc++-prettyprinters/debug.cc (revision 0)
> @@ -0,0 +1,92 @@
> +// { dg-do run }
> +// { dg-options "-g -O0" }
> +
> +// Copyright (C) 2011, 2012 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYING3.  If not see
> +// <http://www.gnu.org/licenses/>.
> +
> +#define _GLIBCXX_DEBUG
> +
> +#include <string>
> +#include <deque>
> +#include <bitset>
> +#include <iostream>
> +#include <list>
> +#include <map>
> +#include <set>
> +#include <ext/slist>
> +
> +int
> +main()
> +{
> +  std::string tem;
> +  std::string str = "zardoz";
> +// { dg-final { note-test str "\"zardoz\"" } }
> +
> +  std::bitset<10> bs;
> +  bs[0] = 1;
> +  bs[5] = 1;
> +  bs[7] = 1;
> +// { dg-final { note-test bs {std::__debug::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::__debug::deque with 2 elements = {"one", "two"}} } }
> +
> +  std::deque<std::string>::iterator deqiter = deq.begin();
> +// { dg-final { note-test deqiter {"one"} } }
> +
> +  std::list<std::string> lst;
> +  lst.push_back("one");
> +  lst.push_back("two");
> +// { dg-final { note-test lst {std::__debug::list = {[0] = "one", [1] = "two"}} } }
> +
> +  std::list<std::string>::iterator lstiter = lst.begin();
> +  tem = *lstiter;
> +// { dg-final { note-test lstiter {"one"}} }
> +
> +  std::list<std::string>::const_iterator lstciter = lst.begin();
> +  tem = *lstciter;
> +// { dg-final { note-test lstciter {"one"}} }
> +
> +  std::map<std::string, int> mp;
> +  mp["zardoz"] = 23;
> +// { dg-final { note-test mp {std::__debug::map with 1 elements = {["zardoz"] = 23}} } }
> +
> +  std::map<std::string, int>::iterator mpiter = mp.begin();
> +// { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
> +
> +  std::set<std::string> sp;
> +  sp.insert("clownfish");
> +  sp.insert("barrel");
> +// { dg-final { note-test sp {std::__debug::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
> +
> +  std::set<std::string>::const_iterator spciter = sp.begin();
> +// { dg-final { note-test spciter {"barrel"} } }
> +
> +  __gnu_cxx::slist<int> sll;
> +  sll.push_front(23);
> +  sll.push_front(47);
> +// { dg-final { note-test sll {__gnu_cxx::slist = {[0] = 47, [1] = 23}} } }
> +
> +  __gnu_cxx::slist<int>::iterator slliter = sll.begin();
> +// { dg-final { note-test slliter {47} } }
> +
> +  return 0;                    // Mark SPOT
> +}
> +
> +// { dg-final { gdb-test SPOT } }
> Index: testsuite/libstdc++-prettyprinters/simple.cc
> ===================================================================
> --- testsuite/libstdc++-prettyprinters/simple.cc        (revision 183449)
> +++ testsuite/libstdc++-prettyprinters/simple.cc        (working copy)
> @@ -1,7 +1,9 @@
> +// If you modify this, please update debug.cc as well.
> +
>  // { dg-do run }
> -// { dg-options "-g" }
> +// { dg-options "-g -O0" }
>
> -// Copyright (C) 2011 Free Software Foundation, Inc.
> +// Copyright (C) 2011, 2012 Free Software Foundation, Inc.
>  //
>  // This file is part of the GNU ISO C++ Library.  This library is free
>  // software; you can redistribute it and/or modify it under the
> @@ -24,34 +26,13 @@
>  #include <iostream>
>  #include <list>
>  #include <map>
> +#include <set>
> +#include <ext/slist>
>
> -template<class T>
> -void
> -placeholder(const T &s)
> -{
> -  std::cout << s;
> -}
> -
> -template<class T, class S>
> -void
> -placeholder(const std::pair<T,S> &s)
> -{
> -  std::cout << s.first;
> -}
> -
> -template<class T>
> -void
> -use(const T &container)
> -{
> -  for (typename T::const_iterator i = container.begin();
> -       i != container.end();
> -       ++i)
> -    placeholder(*i);
> -}
> -
>  int
>  main()
>  {
> +  std::string tem;
>   std::string str = "zardoz";
>  // { dg-final { note-test str "\"zardoz\"" } }
>
> @@ -66,22 +47,46 @@
>   deq.push_back("two");
>  // { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
>
> +  std::deque<std::string>::iterator deqiter = deq.begin();
> +// { dg-final { note-test deqiter {"one"} } }
> +
>   std::list<std::string> lst;
>   lst.push_back("one");
>   lst.push_back("two");
>  // { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
>
> +  std::list<std::string>::iterator lstiter = lst.begin();
> +  tem = *lstiter;
> +// { dg-final { note-test lstiter {"one"}} }
> +
> +  std::list<std::string>::const_iterator lstciter = lst.begin();
> +  tem = *lstciter;
> +// { dg-final { note-test lstciter {"one"}} }
> +
>   std::map<std::string, int> mp;
>   mp["zardoz"] = 23;
>  // { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
>
> -  placeholder(str); // Mark SPOT
> -  std::cout << bs;
> -  use(deq);
> -  use(lst);
> -  use(mp);
> +  std::map<std::string, int>::iterator mpiter = mp.begin();
> +// { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
>
> -  return 0;
> +  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"}} } }
> +
> +  std::set<std::string>::const_iterator spciter = sp.begin();
> +// { dg-final { note-test spciter {"barrel"} } }
> +
> +  __gnu_cxx::slist<int> sll;
> +  sll.push_front(23);
> +  sll.push_front(47);
> +// { dg-final { note-test sll {__gnu_cxx::slist = {[0] = 47, [1] = 23}} } }
> +
> +  __gnu_cxx::slist<int>::iterator slliter = sll.begin();
> +// { dg-final { note-test slliter {47} } }
> +
> +  return 0;                    // Mark SPOT
>  }
>
>  // { dg-final { gdb-test SPOT } }
> Index: testsuite/lib/gdb-test.exp
> ===================================================================
> --- testsuite/lib/gdb-test.exp  (revision 183449)
> +++ testsuite/lib/gdb-test.exp  (working copy)
> @@ -1,4 +1,4 @@
> -#   Copyright (C) 2009, 2011 Free Software Foundation, Inc.
> +#   Copyright (C) 2009, 2011, 2012 Free Software Foundation, Inc.
>
>  # This program is free software; you can redistribute it and/or modify
>  # it under the terms of the GNU General Public License as published by
> @@ -55,11 +55,20 @@
>  proc note-test {var result} {
>     global gdb_tests
>
> -    lappend gdb_tests $var $result
> +    lappend gdb_tests $var $result 0
>  }
>
> +# A test that uses a regular expression.  This is like note-test, but
> +# the result is a regular expression that is matched against the
> +# output.
> +proc regexp-test {var result} {
> +    global gdb_tests
> +
> +    lappend gdb_tests $var $result 1
> +}
> +
>  # Utility for testing variable values using gdb, invoked via dg-final.
> -# Tests all tests indicated by note-test.
> +# Tests all tests indicated by note-test and regexp-test.
>  #
>  # Argument 0 is the marker on which to put a breakpoint
>  # Argument 2 handles expected failures and the like
> @@ -100,11 +109,12 @@
>     puts $fd "run"
>
>     set count 0
> -    foreach {var result} $gdb_tests {
> +    foreach {var result is_regexp} $gdb_tests {
>        puts $fd "print $var"
>        incr count
>        set gdb_var($count) $var
>        set gdb_expected($count) $result
> +       set gdb_is_regexp($count) $is_regexp
>     }
>     set gdb_tests {}
>
> @@ -120,9 +130,18 @@
>
>     remote_expect target [timeout_value] {
>        -re {^\$([0-9]+) = ([^\n\r]*)[\n\r]+} {
> +           send_log "got: $expect_out(buffer)"
> +
>            set num $expect_out(1,string)
>            set first $expect_out(2,string)
> -           if { ![string compare $first $gdb_expected($num)] } {
> +
> +           if {$gdb_is_regexp($num)} {
> +               set match [regexp -- $gdb_expected($num) $first]
> +           } else {
> +               set match [expr {![string compare $first $gdb_expected($num)]}]
> +           }
> +
> +           if {$match} {
>                pass "$testname print $gdb_var($num)"
>            } else {
>                fail "$testname print $gdb_var($num)"
> @@ -145,7 +164,7 @@
>        }
>
>        -re {^[^$][^\n\r]*[\n\r]+} {
> -           verbose "skipping: $expect_out(buffer)"
> +           send_log "skipping: $expect_out(buffer)"
>            exp_continue
>        }
>
Jakub Jelinek - Jan. 24, 2012, 10:35 a.m.
On Tue, Jan 24, 2012 at 11:29:12AM +0100, Richard Guenther wrote:
> We're technically in regression-fixes-only mode.  We give target/language
> maintainers some extra freedom though - while C++/libstdc++ are considered
> release critical and thus should not regress at this point I'm less sure
> about all the pretty-printing stuff - it can't possibly break anything
> but debugging experience.

Well, even bad debugging experience problems would be very undesirable
if we generated wrong debug info and everybody compiled it into their
sources.  But pretty-printers stay on the side, it is just a matter of
updating the python scripts and there is no need to recompile already
compiled/linked programs/libraries.  So if properly tested, I think
this could go in.

	Jakub
Tom Tromey - Jan. 25, 2012, 7:03 p.m.
>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:

Jakub> Well, even bad debugging experience problems would be very undesirable
Jakub> if we generated wrong debug info and everybody compiled it into their
Jakub> sources.  But pretty-printers stay on the side, it is just a matter of
Jakub> updating the python scripts and there is no need to recompile already
Jakub> compiled/linked programs/libraries.  So if properly tested, I think
Jakub> this could go in.

I tested them against gdb 7.3, 7.4 and trunk; configured both ways (with
--enable-symvers=gnu-versioned-namespace and the other way).

I also hacked the test suite so I could try gdb 7.2 (normally this is
rejected) and this worked as well as could be expected (7.2 had some
formatting issues leading to test suite failures -- but really it still
worked ok).

This patch also adds some test cases.

Unless you have other tests to suggest, I am going to say that it has
been sufficiently tested and check it in on Friday.

thanks,
Tom
Tom Tromey - Jan. 30, 2012, 4:23 p.m.
>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> Unless you have other tests to suggest, I am going to say that it has
Tom> been sufficiently tested and check it in on Friday.

Jakub said on irc that he thought I had done sufficient testing.
So, I am checking this patch in now.

thanks,
Tom

Patch

Index: python/libstdcxx/v6/printers.py
===================================================================
--- python/libstdcxx/v6/printers.py	(revision 183449)
+++ python/libstdcxx/v6/printers.py	(working copy)
@@ -1,6 +1,6 @@ 
 # Pretty-printers for libstc++.
 
-# Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -26,6 +26,25 @@ 
 except ImportError:
     _use_gdb_pp = False
 
+# 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.
+def find_type(orig, name):
+    typ = orig.strip_typedefs()
+    while True:
+        search = str(typ) + '::' + name
+        try:
+            return gdb.lookup_type(search)
+        except RuntimeError:
+            pass
+        # The type was not found, so try the superclass.  We only need
+        # to check the first superclass, so we don't bother with
+        # anything fancier here.
+        field = typ.fields()[0]
+        if not field.is_base_class:
+            raise ValueError, "Cannot find type %s::%s" % (str(orig), name)
+        typ = field.type
+
 class StdPointerPrinter:
     "Print a smart pointer of some kind"
 
@@ -76,15 +95,8 @@ 
         self.val = val
 
     def children(self):
-        itype = self.val.type.template_argument(0)
-        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
-        # some of the internal implementation details change.
-        if self.typename == "std::list":
-            nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
-        elif self.typename == "std::__debug::list":
-            nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer()
-        else:
-            raise ValueError, "Cannot cast list node for list printer."
+        nodetype = find_type(self.val.type, '_Node')
+        nodetype = nodetype.strip_typedefs().pointer()
         return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
 
     def to_string(self):
@@ -100,15 +112,8 @@ 
         self.typename = typename
 
     def to_string(self):
-        itype = self.val.type.template_argument(0)
-        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
-        # some of the internal implementation details change.
-        if self.typename == "std::_List_iterator" or self.typename == "std::_List_const_iterator":
-            nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer()
-        elif self.typename == "std::__norm::_List_iterator" or self.typename == "std::__norm::_List_const_iterator":
-            nodetype = gdb.lookup_type('std::__norm::_List_node<%s>' % itype).pointer()
-        else:
-            raise ValueError, "Cannot cast list node for list iterator printer."
+        nodetype = find_type(self.val.type, '_Node')
+        nodetype = nodetype.strip_typedefs().pointer()
         return self.val['_M_node'].cast(nodetype).dereference()['_M_data']
 
 class StdSlistPrinter:
@@ -136,8 +141,8 @@ 
         self.val = val
 
     def children(self):
-        itype = self.val.type.template_argument(0)
-        nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer()
+        nodetype = find_type(self.val.type, '_Node')
+        nodetype = nodetype.strip_typedefs().pointer()
         return self._iterator(nodetype, self.val)
 
     def to_string(self):
@@ -152,8 +157,8 @@ 
         self.val = val
 
     def to_string(self):
-        itype = self.val.type.template_argument(0)
-        nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer()
+        nodetype = find_type(self.val.type, '_Node')
+        nodetype = nodetype.strip_typedefs().pointer()
         return self.val['_M_node'].cast(nodetype).dereference()['_M_data']
 
 class StdVectorPrinter:
@@ -364,9 +369,8 @@ 
         self.val = val
 
     def to_string (self):
-        valuetype = self.val.type.template_argument(0)
-        nodetype = gdb.lookup_type('std::_Rb_tree_node < %s >' % valuetype)
-        nodetype = nodetype.pointer()
+        typename = str(self.val.type.strip_typedefs()) + '::_Link_type'
+        nodetype = gdb.lookup_type(typename).strip_typedefs()
         return self.val.cast(nodetype).dereference()['_M_value_field']
 
 class StdDebugIteratorPrinter:
@@ -415,11 +419,10 @@ 
                                         len (RbtreeIterator (self.val)))
 
     def children (self):
-        keytype = self.val.type.template_argument(0).const()
-        valuetype = self.val.type.template_argument(1)
-        nodetype = gdb.lookup_type('std::_Rb_tree_node< std::pair< %s, %s > >' % (keytype, valuetype))
-        nodetype = nodetype.pointer()
-        return self._iter (RbtreeIterator (self.val), nodetype)
+        rep_type = find_type(self.val.type, '_Rep_type')
+        node = find_type(rep_type, '_Link_type')
+        node = node.strip_typedefs()
+        return self._iter (RbtreeIterator (self.val), node)
 
     def display_hint (self):
         return 'map'
@@ -455,9 +458,10 @@ 
                                         len (RbtreeIterator (self.val)))
 
     def children (self):
-        keytype = self.val.type.template_argument(0)
-        nodetype = gdb.lookup_type('std::_Rb_tree_node< %s >' % keytype).pointer()
-        return self._iter (RbtreeIterator (self.val), nodetype)
+        rep_type = find_type(self.val.type, '_Rep_type')
+        node = find_type(rep_type, '_Link_type')
+        node = node.strip_typedefs()
+        return self._iter (RbtreeIterator (self.val), node)
 
 class StdBitsetPrinter:
     "Print a std::bitset"
@@ -713,15 +717,8 @@ 
         self.typename = typename
 
     def children(self):
-        itype = self.val.type.template_argument(0)
-        # If the inferior program is compiled with -D_GLIBCXX_DEBUG
-        # some of the internal implementation details change.
-        if self.typename == "std::forward_list":
-            nodetype = gdb.lookup_type('std::_Fwd_list_node<%s>' % itype).pointer()
-        elif self.typename == "std::__debug::list":
-            nodetype = gdb.lookup_type('std::__norm::_Fwd_list_node<%s>' % itype).pointer()
-        else:
-            raise ValueError, "Cannot cast forward_list node for forward_list printer."
+        nodetype = find_type(self.val.type, '_Node')
+        nodetype = nodetype.strip_typedefs().pointer()
         return self._iterator(nodetype, self.val['_M_impl']['_M_head'])
 
     def to_string(self):
@@ -764,6 +761,16 @@ 
         self.subprinters.append(printer)
         self.lookup[name] = printer
 
+    # 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)
+
+    # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
+    def add_container(self, base, name, function):
+        self.add_version(base, name, function)
+        self.add_version(base + '__cxx1998::', name, function)
+
     @staticmethod
     def get_basic_type(type):
         # If it points to a reference, get the reference.
@@ -813,23 +820,29 @@ 
 
     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
-    libstdcxx_printer.add('std::basic_string', StdStringPrinter)
-    libstdcxx_printer.add('std::bitset', StdBitsetPrinter)
-    libstdcxx_printer.add('std::deque', StdDequePrinter)
-    libstdcxx_printer.add('std::list', StdListPrinter)
-    libstdcxx_printer.add('std::map', StdMapPrinter)
-    libstdcxx_printer.add('std::multimap', StdMapPrinter)
-    libstdcxx_printer.add('std::multiset', StdSetPrinter)
-    libstdcxx_printer.add('std::priority_queue', StdStackOrQueuePrinter)
-    libstdcxx_printer.add('std::queue', StdStackOrQueuePrinter)
-    libstdcxx_printer.add('std::tuple', StdTuplePrinter)
-    libstdcxx_printer.add('std::set', StdSetPrinter)
-    libstdcxx_printer.add('std::stack', StdStackOrQueuePrinter)
-    libstdcxx_printer.add('std::unique_ptr', UniquePointerPrinter)
-    libstdcxx_printer.add('std::vector', StdVectorPrinter)
+    libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter)
+    libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter)
+    libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter)
+    libstdcxx_printer.add_container('std::', 'list', StdListPrinter)
+    libstdcxx_printer.add_container('std::', 'map', StdMapPrinter)
+    libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter)
+    libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter)
+    libstdcxx_printer.add_version('std::', 'priority_queue',
+                                  StdStackOrQueuePrinter)
+    libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter)
+    libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter)
+    libstdcxx_printer.add_container('std::', 'set', StdSetPrinter)
+    libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter)
+    libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter)
+    libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter)
     # vector<bool>
 
     # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG.
@@ -849,22 +862,29 @@ 
 
     # These are the TR1 and C++0x printers.
     # For array - the default GDB pretty-printer seems reasonable.
-    libstdcxx_printer.add('std::shared_ptr', StdPointerPrinter)
-    libstdcxx_printer.add('std::weak_ptr', StdPointerPrinter)
-    libstdcxx_printer.add('std::unordered_map', Tr1UnorderedMapPrinter)
-    libstdcxx_printer.add('std::unordered_set', Tr1UnorderedSetPrinter)
-    libstdcxx_printer.add('std::unordered_multimap', Tr1UnorderedMapPrinter)
-    libstdcxx_printer.add('std::unordered_multiset', Tr1UnorderedSetPrinter)
-    libstdcxx_printer.add('std::forward_list', StdForwardListPrinter)
+    libstdcxx_printer.add_version('std::', 'shared_ptr', StdPointerPrinter)
+    libstdcxx_printer.add_version('std::', 'weak_ptr', StdPointerPrinter)
+    libstdcxx_printer.add_container('std::', 'unordered_map',
+                                    Tr1UnorderedMapPrinter)
+    libstdcxx_printer.add_container('std::', 'unordered_set',
+                                    Tr1UnorderedSetPrinter)
+    libstdcxx_printer.add_container('std::', 'unordered_multimap',
+                                    Tr1UnorderedMapPrinter)
+    libstdcxx_printer.add_container('std::', 'unordered_multiset',
+                                    Tr1UnorderedSetPrinter)
+    libstdcxx_printer.add_container('std::', 'forward_list',
+                                    StdForwardListPrinter)
 
-    libstdcxx_printer.add('std::tr1::shared_ptr', StdPointerPrinter)
-    libstdcxx_printer.add('std::tr1::weak_ptr', StdPointerPrinter)
-    libstdcxx_printer.add('std::tr1::unordered_map', Tr1UnorderedMapPrinter)
-    libstdcxx_printer.add('std::tr1::unordered_set', Tr1UnorderedSetPrinter)
-    libstdcxx_printer.add('std::tr1::unordered_multimap',
-                          Tr1UnorderedMapPrinter)
-    libstdcxx_printer.add('std::tr1::unordered_multiset',
-                          Tr1UnorderedSetPrinter)
+    libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', StdPointerPrinter)
+    libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', StdPointerPrinter)
+    libstdcxx_printer.add_version('std::tr1::', 'unordered_map',
+                                  Tr1UnorderedMapPrinter)
+    libstdcxx_printer.add_version('std::tr1::', 'unordered_set',
+                                  Tr1UnorderedSetPrinter)
+    libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap',
+                                  Tr1UnorderedMapPrinter)
+    libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
+                                  Tr1UnorderedSetPrinter)
 
     # These are the C++0x printer registrations for -D_GLIBCXX_DEBUG cases.
     # The tr1 namespace printers do not seem to have any debug
@@ -882,25 +902,27 @@ 
 
 
     # Extensions.
-    libstdcxx_printer.add('__gnu_cxx::slist', StdSlistPrinter)
+    libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
 
     if True:
         # These shouldn't be necessary, if GDB "print *i" worked.
         # But it often doesn't, so here they are.
-        libstdcxx_printer.add('std::_List_iterator', StdListIteratorPrinter)
-        libstdcxx_printer.add('std::_List_const_iterator',
-                              StdListIteratorPrinter)
-        libstdcxx_printer.add('std::_Rb_tree_iterator',
-                              StdRbtreeIteratorPrinter)
-        libstdcxx_printer.add('std::_Rb_tree_const_iterator',
-                              StdRbtreeIteratorPrinter)
-        libstdcxx_printer.add('std::_Deque_iterator', StdDequeIteratorPrinter)
-        libstdcxx_printer.add('std::_Deque_const_iterator',
-                              StdDequeIteratorPrinter)
-        libstdcxx_printer.add('__gnu_cxx::__normal_iterator',
-                              StdVectorIteratorPrinter)
-        libstdcxx_printer.add('__gnu_cxx::_Slist_iterator',
-                              StdSlistIteratorPrinter)
+        libstdcxx_printer.add_container('std::', '_List_iterator',
+                                        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_container('std::', '_Deque_iterator',
+                                        StdDequeIteratorPrinter)
+        libstdcxx_printer.add_container('std::', '_Deque_const_iterator',
+                                        StdDequeIteratorPrinter)
+        libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator',
+                                      StdVectorIteratorPrinter)
+        libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator',
+                                      StdSlistIteratorPrinter)
 
         # Debug (compiled with -D_GLIBCXX_DEBUG) printer
         # registrations.  The Rb_tree debug iterator when unwrapped
Index: testsuite/libstdc++-prettyprinters/48362.cc
===================================================================
--- testsuite/libstdc++-prettyprinters/48362.cc	(revision 183449)
+++ testsuite/libstdc++-prettyprinters/48362.cc	(working copy)
@@ -1,7 +1,7 @@ 
 // { dg-do run }
 // { dg-options "-g -std=gnu++11 -O0" }
 
-// Copyright (C) 2011 Free Software Foundation, Inc.
+// Copyright (C) 2011, 2012 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -25,10 +25,10 @@ 
 main()
 {
   std::tuple<> t1;
-// { dg-final { note-test t1 {empty std::tuple} } }
+// { dg-final { regexp-test t1 {empty std::(__7::)?tuple} } }
 
   std::tuple<std::string, int, std::tuple<>> t2{ "Johnny", 5, {} };
-// { dg-final { note-test t2 {std::tuple containing = {[1] = "Johnny", [2] = 5, [3] = {<std::tuple<>> = empty std::tuple, <No data fields>}}} } }
+// { dg-final { regexp-test t2 {std::(__7::)?tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::(__7::)?tuple, <No data fields>}}} } }
 
   return 0; // Mark SPOT
 }
Index: testsuite/libstdc++-prettyprinters/debug.cc
===================================================================
--- testsuite/libstdc++-prettyprinters/debug.cc	(revision 0)
+++ testsuite/libstdc++-prettyprinters/debug.cc	(revision 0)
@@ -0,0 +1,92 @@ 
+// { dg-do run }
+// { dg-options "-g -O0" }
+
+// Copyright (C) 2011, 2012 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_DEBUG
+
+#include <string>
+#include <deque>
+#include <bitset>
+#include <iostream>
+#include <list>
+#include <map>
+#include <set>
+#include <ext/slist>
+
+int
+main()
+{
+  std::string tem;
+  std::string str = "zardoz";
+// { dg-final { note-test str "\"zardoz\"" } }
+
+  std::bitset<10> bs;
+  bs[0] = 1;
+  bs[5] = 1;
+  bs[7] = 1;
+// { dg-final { note-test bs {std::__debug::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::__debug::deque with 2 elements = {"one", "two"}} } }
+
+  std::deque<std::string>::iterator deqiter = deq.begin();
+// { dg-final { note-test deqiter {"one"} } }
+
+  std::list<std::string> lst;
+  lst.push_back("one");
+  lst.push_back("two");
+// { dg-final { note-test lst {std::__debug::list = {[0] = "one", [1] = "two"}} } }
+
+  std::list<std::string>::iterator lstiter = lst.begin();
+  tem = *lstiter;
+// { dg-final { note-test lstiter {"one"}} }
+
+  std::list<std::string>::const_iterator lstciter = lst.begin();
+  tem = *lstciter;
+// { dg-final { note-test lstciter {"one"}} }
+
+  std::map<std::string, int> mp;
+  mp["zardoz"] = 23;
+// { dg-final { note-test mp {std::__debug::map with 1 elements = {["zardoz"] = 23}} } }
+
+  std::map<std::string, int>::iterator mpiter = mp.begin();
+// { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
+
+  std::set<std::string> sp;
+  sp.insert("clownfish");
+  sp.insert("barrel");
+// { dg-final { note-test sp {std::__debug::set with 2 elements = {[0] = "barrel", [1] = "clownfish"}} } }
+
+  std::set<std::string>::const_iterator spciter = sp.begin();
+// { dg-final { note-test spciter {"barrel"} } }
+
+  __gnu_cxx::slist<int> sll;
+  sll.push_front(23);
+  sll.push_front(47);
+// { dg-final { note-test sll {__gnu_cxx::slist = {[0] = 47, [1] = 23}} } }
+
+  __gnu_cxx::slist<int>::iterator slliter = sll.begin();
+// { dg-final { note-test slliter {47} } }
+
+  return 0;			// Mark SPOT
+}
+
+// { dg-final { gdb-test SPOT } }
Index: testsuite/libstdc++-prettyprinters/simple.cc
===================================================================
--- testsuite/libstdc++-prettyprinters/simple.cc	(revision 183449)
+++ testsuite/libstdc++-prettyprinters/simple.cc	(working copy)
@@ -1,7 +1,9 @@ 
+// If you modify this, please update debug.cc as well.
+
 // { dg-do run }
-// { dg-options "-g" }
+// { dg-options "-g -O0" }
 
-// Copyright (C) 2011 Free Software Foundation, Inc.
+// Copyright (C) 2011, 2012 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -24,34 +26,13 @@ 
 #include <iostream>
 #include <list>
 #include <map>
+#include <set>
+#include <ext/slist>
 
-template<class T>
-void
-placeholder(const T &s)
-{
-  std::cout << s;
-}
-
-template<class T, class S>
-void
-placeholder(const std::pair<T,S> &s)
-{
-  std::cout << s.first;
-}
-
-template<class T>
-void
-use(const T &container)
-{
-  for (typename T::const_iterator i = container.begin();
-       i != container.end();
-       ++i)
-    placeholder(*i);
-}
-
 int
 main()
 {
+  std::string tem;
   std::string str = "zardoz";
 // { dg-final { note-test str "\"zardoz\"" } }
 
@@ -66,22 +47,46 @@ 
   deq.push_back("two");
 // { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
 
+  std::deque<std::string>::iterator deqiter = deq.begin();
+// { dg-final { note-test deqiter {"one"} } }
+
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
 // { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
 
+  std::list<std::string>::iterator lstiter = lst.begin();
+  tem = *lstiter;
+// { dg-final { note-test lstiter {"one"}} }
+
+  std::list<std::string>::const_iterator lstciter = lst.begin();
+  tem = *lstciter;
+// { dg-final { note-test lstciter {"one"}} }
+
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
 // { dg-final { note-test mp {std::map with 1 elements = {["zardoz"] = 23}} } }
 
-  placeholder(str); // Mark SPOT
-  std::cout << bs;
-  use(deq);
-  use(lst);
-  use(mp);
+  std::map<std::string, int>::iterator mpiter = mp.begin();
+// { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
-  return 0;
+  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"}} } }
+
+  std::set<std::string>::const_iterator spciter = sp.begin();
+// { dg-final { note-test spciter {"barrel"} } }
+
+  __gnu_cxx::slist<int> sll;
+  sll.push_front(23);
+  sll.push_front(47);
+// { dg-final { note-test sll {__gnu_cxx::slist = {[0] = 47, [1] = 23}} } }
+
+  __gnu_cxx::slist<int>::iterator slliter = sll.begin();
+// { dg-final { note-test slliter {47} } }
+
+  return 0;			// Mark SPOT
 }
 
 // { dg-final { gdb-test SPOT } }
Index: testsuite/lib/gdb-test.exp
===================================================================
--- testsuite/lib/gdb-test.exp	(revision 183449)
+++ testsuite/lib/gdb-test.exp	(working copy)
@@ -1,4 +1,4 @@ 
-#   Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+#   Copyright (C) 2009, 2011, 2012 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -55,11 +55,20 @@ 
 proc note-test {var result} {
     global gdb_tests
 
-    lappend gdb_tests $var $result
+    lappend gdb_tests $var $result 0
 }
 
+# A test that uses a regular expression.  This is like note-test, but
+# the result is a regular expression that is matched against the
+# output.
+proc regexp-test {var result} {
+    global gdb_tests
+
+    lappend gdb_tests $var $result 1
+}
+
 # Utility for testing variable values using gdb, invoked via dg-final.
-# Tests all tests indicated by note-test.
+# Tests all tests indicated by note-test and regexp-test.
 #
 # Argument 0 is the marker on which to put a breakpoint
 # Argument 2 handles expected failures and the like
@@ -100,11 +109,12 @@ 
     puts $fd "run"
 
     set count 0
-    foreach {var result} $gdb_tests {
+    foreach {var result is_regexp} $gdb_tests {
 	puts $fd "print $var"
 	incr count
 	set gdb_var($count) $var
 	set gdb_expected($count) $result
+	set gdb_is_regexp($count) $is_regexp
     }
     set gdb_tests {}
 
@@ -120,9 +130,18 @@ 
 
     remote_expect target [timeout_value] {
 	-re {^\$([0-9]+) = ([^\n\r]*)[\n\r]+} {
+	    send_log "got: $expect_out(buffer)"
+
 	    set num $expect_out(1,string)
 	    set first $expect_out(2,string)
-	    if { ![string compare $first $gdb_expected($num)] } {
+
+	    if {$gdb_is_regexp($num)} {
+		set match [regexp -- $gdb_expected($num) $first]
+	    } else {
+		set match [expr {![string compare $first $gdb_expected($num)]}]
+	    }
+
+	    if {$match} {
 		pass "$testname print $gdb_var($num)"
 	    } else {
 		fail "$testname print $gdb_var($num)"
@@ -145,7 +164,7 @@ 
 	}
 
 	-re {^[^$][^\n\r]*[\n\r]+} {
-	    verbose "skipping: $expect_out(buffer)"
+	    send_log "skipping: $expect_out(buffer)"
 	    exp_continue
 	}