summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/ChangeLog12
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py102
-rw-r--r--libstdc++-v3/testsuite/lib/gdb-test.exp86
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc243
4 files changed, 419 insertions, 24 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index a75e97a0166..3744f944ebb 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,15 @@
+2012-11-16 Tom Tromey <tromey@redhat.com>
+
+ * testsuite/libstdc++-prettyprinters/whatis.cc: New file.
+ * testsuite/lib/gdb-test.exp (whatis-test): New proc.
+ (gdb-test): Handle 'whatis' tests.
+ (gdb_batch_check): New proc.
+ (gdb_version_check): Rewrite to use gdb_batch_check.
+ * python/libstdcxx/v6/printers.py: Import gdb.types.
+ (FilteringTypePrinter): New class.
+ (add_one_type_printer, register_type_printers): New functions.
+ (register_libstdcxx_printers): Call register_type_printers.
+
2012-11-15 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/53841
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 5197284b017..294ec4cf3c9 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -26,6 +26,15 @@ try:
except ImportError:
_use_gdb_pp = False
+# Try to install type-printers.
+_use_type_printing = False
+try:
+ import gdb.types
+ if hasattr(gdb.types, 'TypePrinter'):
+ _use_type_printing = True
+except ImportError:
+ pass
+
# Starting with the type ORIG, search for the member type NAME. This
# handles searching upward through superclasses. This is needed to
# work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615.
@@ -801,6 +810,97 @@ class Printer(object):
libstdcxx_printer = None
+class FilteringTypePrinter(object):
+ def __init__(self, match, name):
+ self.match = match
+ self.name = name
+ self.enabled = True
+
+ class _recognizer(object):
+ def __init__(self, match, name):
+ self.match = match
+ self.name = name
+ self.type_obj = None
+
+ def recognize(self, type_obj):
+ if type_obj.tag is None:
+ return None
+
+ if self.type_obj is None:
+ if not self.match in type_obj.tag:
+ # Filter didn't match.
+ return None
+ try:
+ self.type_obj = gdb.lookup_type(self.name).strip_typedefs()
+ except:
+ pass
+ if self.type_obj == type_obj:
+ return self.name
+ return None
+
+ def instantiate(self):
+ return self._recognizer(self.match, self.name)
+
+def add_one_type_printer(obj, match, name):
+ printer = FilteringTypePrinter(match, 'std::' + name)
+ gdb.types.register_type_printer(obj, printer)
+
+def register_type_printers(obj):
+ global _use_type_printing
+
+ if not _use_type_printing:
+ return
+
+ for pfx in ('', 'w'):
+ add_one_type_printer(obj, 'basic_string', pfx + 'string')
+ add_one_type_printer(obj, 'basic_ios', pfx + 'ios')
+ add_one_type_printer(obj, 'basic_streambuf', pfx + 'streambuf')
+ add_one_type_printer(obj, 'basic_istream', pfx + 'istream')
+ add_one_type_printer(obj, 'basic_ostream', pfx + 'ostream')
+ add_one_type_printer(obj, 'basic_iostream', pfx + 'iostream')
+ add_one_type_printer(obj, 'basic_stringbuf', pfx + 'stringbuf')
+ add_one_type_printer(obj, 'basic_istringstream',
+ pfx + 'istringstream')
+ add_one_type_printer(obj, 'basic_ostringstream',
+ pfx + 'ostringstream')
+ add_one_type_printer(obj, 'basic_stringstream',
+ pfx + 'stringstream')
+ add_one_type_printer(obj, 'basic_filebuf', pfx + 'filebuf')
+ add_one_type_printer(obj, 'basic_ifstream', pfx + 'ifstream')
+ add_one_type_printer(obj, 'basic_ofstream', pfx + 'ofstream')
+ add_one_type_printer(obj, 'basic_fstream', pfx + 'fstream')
+ add_one_type_printer(obj, 'basic_regex', pfx + 'regex')
+ add_one_type_printer(obj, 'sub_match', pfx + 'csub_match')
+ add_one_type_printer(obj, 'sub_match', pfx + 'ssub_match')
+ add_one_type_printer(obj, 'match_results', pfx + 'cmatch')
+ add_one_type_printer(obj, 'match_results', pfx + 'smatch')
+ add_one_type_printer(obj, 'regex_iterator', pfx + 'cregex_iterator')
+ add_one_type_printer(obj, 'regex_iterator', pfx + 'sregex_iterator')
+ add_one_type_printer(obj, 'regex_token_iterator',
+ pfx + 'cregex_token_iterator')
+ add_one_type_printer(obj, 'regex_token_iterator',
+ pfx + 'sregex_token_iterator')
+
+ # Note that we can't have a printer for std::wstreampos, because
+ # it shares the same underlying type as std::streampos.
+ add_one_type_printer(obj, 'fpos', 'streampos')
+ add_one_type_printer(obj, 'basic_string', 'u16string')
+ add_one_type_printer(obj, 'basic_string', 'u32string')
+
+ for dur in ('nanoseconds', 'microseconds', 'milliseconds',
+ 'seconds', 'minutes', 'hours'):
+ add_one_type_printer(obj, 'duration', dur)
+
+ add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
+ add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
+ add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
+ add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
+ add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
+ add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
+ add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
+ add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
+ add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
+
def register_libstdcxx_printers (obj):
"Register libstdc++ pretty-printers with objfile Obj."
@@ -814,6 +914,8 @@ def register_libstdcxx_printers (obj):
obj = gdb
obj.pretty_printers.append(libstdcxx_printer)
+ register_type_printers(obj)
+
def build_libstdcxx_dictionary ():
global libstdcxx_printer
diff --git a/libstdc++-v3/testsuite/lib/gdb-test.exp b/libstdc++-v3/testsuite/lib/gdb-test.exp
index b9d4742d393..3434ef2a7ac 100644
--- a/libstdc++-v3/testsuite/lib/gdb-test.exp
+++ b/libstdc++-v3/testsuite/lib/gdb-test.exp
@@ -67,6 +67,13 @@ proc regexp-test {var result} {
lappend gdb_tests $var $result 1
}
+# A test of 'whatis'. This tests a type rather than a variable.
+proc whatis-test {var result} {
+ global gdb_tests
+
+ lappend gdb_tests $var $result whatis
+}
+
# Utility for testing variable values using gdb, invoked via dg-final.
# Tests all tests indicated by note-test and regexp-test.
#
@@ -84,6 +91,12 @@ proc gdb-test { marker {selector {}} } {
}
}
+ set do_whatis_tests [gdb_batch_check "python print gdb.type_printers" \
+ "\\\[\\\]"]
+ if {!$do_whatis_tests} {
+ send_log "skipping 'whatis' tests - gdb too old"
+ }
+
# This assumes that we are three frames down from dg-test, and that
# it still stores the filename of the testcase in a local variable "name".
# A cleaner solution would require a new DejaGnu release.
@@ -109,12 +122,25 @@ proc gdb-test { marker {selector {}} } {
puts $fd "run"
set count 0
- foreach {var result is_regexp} $gdb_tests {
- puts $fd "print $var"
+ foreach {var result kind} $gdb_tests {
incr count
set gdb_var($count) $var
set gdb_expected($count) $result
- set gdb_is_regexp($count) $is_regexp
+ if {$kind == "whatis"} {
+ if {$do_whatis_tests} {
+ set gdb_is_type($count) 1
+ set gdb_command($count) "whatis $var"
+ } else {
+ unsupported "$testname"
+ close $fd
+ return
+ }
+ } else {
+ set gdb_is_type($count) 0
+ set gdb_is_regexp($count) $kind
+ set gdb_command($count) "print $var"
+ }
+ puts $fd $gdb_command($count)
}
set gdb_tests {}
@@ -128,28 +154,36 @@ proc gdb-test { marker {selector {}} } {
return
}
+ set test_counter 0
remote_expect target [timeout_value] {
- -re {^\$([0-9]+) = ([^\n\r]*)[\n\r]+} {
+ -re {^(type|\$([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 {$gdb_is_regexp($num)} {
- set match [regexp -- $gdb_expected($num) $first]
+ incr test_counter
+ set first $expect_out(3,string)
+
+ if {$gdb_is_type($test_counter)} {
+ if {$expect_out(1,string) != "type"} {
+ error "gdb failure"
+ }
+ set match [expr {![string compare $first \
+ $gdb_expected($test_counter)]}]
+ } elseif {$gdb_is_regexp($test_counter)} {
+ set match [regexp -- $gdb_expected($test_counter) $first]
} else {
- set match [expr {![string compare $first $gdb_expected($num)]}]
+ set match [expr {![string compare $first \
+ $gdb_expected($test_counter)]}]
}
if {$match} {
- pass "$testname print $gdb_var($num)"
+ pass "$testname $gdb_command($test_counter)"
} else {
- fail "$testname print $gdb_var($num)"
+ fail "$testname $gdb_command($test_counter)"
verbose " got =>$first<="
- verbose "expected =>$gdb_expected($num)<="
+ verbose "expected =>$gdb_expected($test_counter)<="
}
- if {$num == $count} {
+ if {$test_counter == $count} {
remote_close target
return
} else {
@@ -180,16 +214,10 @@ proc gdb-test { marker {selector {}} } {
return
}
-# Check for a new-enough version of gdb. The pretty-printer tests
-# require gdb 7.3, but we don't want to test versions, so instead we
-# check for the python "lookup_global_symbol" method, which is in 7.3
-# but not earlier versions.
-# Return 1 if the version is ok, 0 otherwise.
-proc gdb_version_check {} {
- global gdb_version
-
+# Invoke gdb with a command and pattern-match the output.
+proc gdb_batch_check {command pattern} {
set gdb_name $::env(GUALITY_GDB_NAME)
- set cmd "$gdb_name -nw -nx -quiet -batch -ex \"python print gdb.lookup_global_symbol\""
+ set cmd "$gdb_name -nw -nx -quiet -batch -ex \"$command\""
send_log "Spawning: $cmd\n"
set res [remote_spawn target "$cmd"]
if { $res < 0 || $res == "" } {
@@ -197,7 +225,7 @@ proc gdb_version_check {} {
}
remote_expect target [timeout_value] {
- -re "<built-in function lookup_global_symbol>" {
+ -re $pattern {
return 1
}
@@ -215,3 +243,13 @@ proc gdb_version_check {} {
remote_close target
return 0
}
+
+# Check for a new-enough version of gdb. The pretty-printer tests
+# require gdb 7.3, but we don't want to test versions, so instead we
+# check for the python "lookup_global_symbol" method, which is in 7.3
+# but not earlier versions.
+# Return 1 if the version is ok, 0 otherwise.
+proc gdb_version_check {} {
+ return [gdb_batch_check "python print gdb.lookup_global_symbol" \
+ "<built-in function lookup_global_symbol>"]
+}
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
new file mode 100644
index 00000000000..c22246c978d
--- /dev/null
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -0,0 +1,243 @@
+// { dg-do run }
+// { dg-options "-g -O0 -std=gnu++11" }
+
+// 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/>.
+
+#include <string>
+#include <iostream>
+#include <regex>
+
+template<class T>
+void
+placeholder(const T *s)
+{
+ std::cout << (void *) s;
+}
+
+template<class T>
+struct holder
+{
+ T *f;
+};
+
+typedef std::basic_string<unsigned char> ustring;
+
+// This test is written in a somewhat funny way.
+// Each type under test is used twice: first, to form a pointer type,
+// and second, as a template parameter. This is done to work around
+// apparent GCC oddities. The pointer type is needed to ensure that
+// the typedef in question ends up in the debuginfo; while the
+// template type is used to ensure that a typedef-less variant is
+// presented to gdb.
+
+std::string *string_ptr;
+holder<std::string> string_holder;
+// { dg-final { whatis-test string_holder "holder<std::string>" } }
+std::ios *ios_ptr;
+holder<std::ios> ios_holder;
+// { dg-final { whatis-test ios_holder "holder<std::ios>" } }
+std::streambuf *streambuf_ptr;
+holder<std::streambuf> streambuf_holder;
+// { dg-final { whatis-test streambuf_holder "holder<std::streambuf>" } }
+std::istream *istream_ptr;
+holder<std::istream> istream_holder;
+// { dg-final { whatis-test istream_holder "holder<std::istream>" } }
+std::ostream *ostream_ptr;
+holder<std::ostream> ostream_holder;
+// { dg-final { whatis-test ostream_holder "holder<std::ostream>" } }
+std::iostream *iostream_ptr;
+holder<std::iostream> iostream_holder;
+// { dg-final { whatis-test iostream_holder "holder<std::iostream>" } }
+std::stringbuf *stringbuf_ptr;
+holder<std::stringbuf> stringbuf_holder;
+// { dg-final { whatis-test stringbuf_holder "holder<std::stringbuf>" } }
+std::istringstream *istringstream_ptr;
+holder<std::istringstream> istringstream_holder;
+// { dg-final { whatis-test istringstream_holder "holder<std::istringstream>" } }
+std::ostringstream *ostringstream_ptr;
+holder<std::ostringstream> ostringstream_holder;
+// { dg-final { whatis-test ostringstream_holder "holder<std::ostringstream>" } }
+std::stringstream *stringstream_ptr;
+holder<std::stringstream> stringstream_holder;
+// { dg-final { whatis-test stringstream_holder "holder<std::stringstream>" } }
+std::filebuf *filebuf_ptr;
+holder<std::filebuf> filebuf_holder;
+// { dg-final { whatis-test filebuf_holder "holder<std::filebuf>" } }
+std::ifstream *ifstream_ptr;
+holder<std::ifstream> ifstream_holder;
+// { dg-final { whatis-test ifstream_holder "holder<std::ifstream>" } }
+std::ofstream *ofstream_ptr;
+holder<std::ofstream> ofstream_holder;
+// { dg-final { whatis-test ofstream_holder "holder<std::ofstream>" } }
+std::fstream *fstream_ptr;
+holder<std::fstream> fstream_holder;
+// { dg-final { whatis-test fstream_holder "holder<std::fstream>" } }
+std::streampos *streampos_ptr;
+holder<std::streampos> streampos_holder;
+// { dg-final { whatis-test streampos_holder "holder<std::streampos>" } }
+std::regex *regex_ptr;
+holder<std::regex> regex_holder;
+// { dg-final { whatis-test regex_holder "holder<std::regex>" } }
+std::csub_match *csub_match_ptr;
+holder<std::csub_match> csub_match_holder;
+// { dg-final { whatis-test csub_match_holder "holder<std::csub_match>" } }
+std::ssub_match *ssub_match_ptr;
+holder<std::ssub_match> ssub_match_holder;
+// { dg-final { whatis-test ssub_match_holder "holder<std::ssub_match>" } }
+std::cmatch *cmatch_ptr;
+holder<std::cmatch> cmatch_holder;
+// { dg-final { whatis-test cmatch_holder "holder<std::cmatch>" } }
+std::smatch *smatch_ptr;
+holder<std::smatch> smatch_holder;
+// { dg-final { whatis-test smatch_holder "holder<std::smatch>" } }
+std::cregex_iterator *cregex_iterator_ptr;
+holder<std::cregex_iterator> cregex_iterator_holder;
+// { dg-final { whatis-test cregex_iterator_holder "holder<std::cregex_iterator>" } }
+std::sregex_iterator *sregex_iterator_ptr;
+holder<std::sregex_iterator> sregex_iterator_holder;
+// { dg-final { whatis-test sregex_iterator_holder "holder<std::sregex_iterator>" } }
+std::cregex_token_iterator *cregex_token_iterator_ptr;
+holder<std::cregex_token_iterator> cregex_token_iterator_holder;
+// { dg-final { whatis-test cregex_token_iterator_holder "holder<std::cregex_token_iterator>" } }
+std::sregex_token_iterator *sregex_token_iterator_ptr;
+holder<std::sregex_token_iterator> sregex_token_iterator_holder;
+// { dg-final { whatis-test sregex_token_iterator_holder "holder<std::sregex_token_iterator>" } }
+std::u16string *u16string_ptr;
+holder<std::u16string> u16string_holder;
+// { dg-final { whatis-test u16string_holder "holder<std::u16string>" } }
+std::u32string *u32string_ptr;
+holder<std::u32string> u32string_holder;
+// { dg-final { whatis-test u32string_holder "holder<std::u32string>" } }
+std::minstd_rand0 *minstd_rand0_ptr;
+holder<std::minstd_rand0> minstd_rand0_holder;
+// { dg-final { whatis-test minstd_rand0_holder "holder<std::minstd_rand0>" } }
+std::minstd_rand *minstd_rand_ptr;
+holder<std::minstd_rand> minstd_rand_holder;
+// { dg-final { whatis-test minstd_rand_holder "holder<std::minstd_rand>" } }
+std::mt19937 *mt19937_ptr;
+holder<std::mt19937> mt19937_holder;
+// { dg-final { whatis-test mt19937_holder "holder<std::mt19937>" } }
+std::mt19937_64 *mt19937_64_ptr;
+holder<std::mt19937_64> mt19937_64_holder;
+// { dg-final { whatis-test mt19937_64_holder "holder<std::mt19937_64>" } }
+std::ranlux24_base *ranlux24_base_ptr;
+holder<std::ranlux24_base> ranlux24_base_holder;
+// { dg-final { whatis-test ranlux24_base_holder "holder<std::ranlux24_base>" } }
+std::ranlux48_base *ranlux48_base_ptr;
+holder<std::ranlux48_base> ranlux48_base_holder;
+// { dg-final { whatis-test ranlux48_base_holder "holder<std::ranlux48_base>" } }
+std::ranlux24 *ranlux24_ptr;
+holder<std::ranlux24> ranlux24_holder;
+// { dg-final { whatis-test ranlux24_holder "holder<std::ranlux24>" } }
+std::ranlux48 *ranlux48_ptr;
+holder<std::ranlux48> ranlux48_holder;
+// { dg-final { whatis-test ranlux48_holder "holder<std::ranlux48>" } }
+std::knuth_b *knuth_b_ptr;
+holder<std::knuth_b> knuth_b_holder;
+// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
+
+ustring *ustring_ptr;
+holder<ustring> ustring_holder;
+// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+
+std::basic_string<signed char> *sstring_ptr;
+holder< std::basic_string<signed char> > sstring_holder;
+// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+
+int
+main()
+{
+ placeholder(&ios_ptr); // Mark SPOT
+ placeholder(&ios_holder);
+ placeholder(&string_ptr);
+ placeholder(&string_holder);
+ placeholder(&streambuf_ptr);
+ placeholder(&streambuf_holder);
+ placeholder(&istream_ptr);
+ placeholder(&istream_holder);
+ placeholder(&ostream_ptr);
+ placeholder(&ostream_holder);
+ placeholder(&iostream_ptr);
+ placeholder(&iostream_holder);
+ placeholder(&stringbuf_ptr);
+ placeholder(&stringbuf_holder);
+ placeholder(&istringstream_ptr);
+ placeholder(&istringstream_holder);
+ placeholder(&ostringstream_ptr);
+ placeholder(&ostringstream_holder);
+ placeholder(&stringstream_ptr);
+ placeholder(&stringstream_holder);
+ placeholder(&filebuf_ptr);
+ placeholder(&filebuf_holder);
+ placeholder(&ifstream_ptr);
+ placeholder(&ifstream_holder);
+ placeholder(&ofstream_ptr);
+ placeholder(&ofstream_holder);
+ placeholder(&fstream_ptr);
+ placeholder(&fstream_holder);
+ placeholder(&streampos_ptr);
+ placeholder(&streampos_holder);
+ placeholder(&regex_ptr);
+ placeholder(&regex_holder);
+ placeholder(&csub_match_ptr);
+ placeholder(&csub_match_holder);
+ placeholder(&ssub_match_ptr);
+ placeholder(&ssub_match_holder);
+ placeholder(&cmatch_ptr);
+ placeholder(&cmatch_holder);
+ placeholder(&smatch_ptr);
+ placeholder(&smatch_holder);
+ placeholder(&cregex_iterator_ptr);
+ placeholder(&cregex_iterator_holder);
+ placeholder(&sregex_iterator_ptr);
+ placeholder(&sregex_iterator_holder);
+ placeholder(&cregex_token_iterator_ptr);
+ placeholder(&cregex_token_iterator_holder);
+ placeholder(&sregex_token_iterator_ptr);
+ placeholder(&sregex_token_iterator_holder);
+ placeholder(&u16string_ptr);
+ placeholder(&u16string_holder);
+ placeholder(&u32string_ptr);
+ placeholder(&u32string_holder);
+ placeholder(&minstd_rand0_ptr);
+ placeholder(&minstd_rand0_holder);
+ placeholder(&minstd_rand_ptr);
+ placeholder(&minstd_rand_holder);
+ placeholder(&mt19937_ptr);
+ placeholder(&mt19937_holder);
+ placeholder(&mt19937_64_ptr);
+ placeholder(&mt19937_64_holder);
+ placeholder(&ranlux24_base_ptr);
+ placeholder(&ranlux24_base_holder);
+ placeholder(&ranlux48_base_ptr);
+ placeholder(&ranlux48_base_holder);
+ placeholder(&ranlux24_ptr);
+ placeholder(&ranlux24_holder);
+ placeholder(&ranlux48_ptr);
+ placeholder(&ranlux48_holder);
+ placeholder(&knuth_b_ptr);
+ placeholder(&knuth_b_holder);
+ placeholder(&ustring_ptr);
+ placeholder(&ustring_holder);
+ placeholder(&sstring_ptr);
+ placeholder(&sstring_holder);
+
+ return 0;
+}
+
+// { dg-final { gdb-test SPOT } }