Message ID | m3wr8ijjo1.fsf@fleche.redhat.com |
---|---|
State | New |
Headers | show |
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 > } >
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
>>>>> "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" == 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
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 }