public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* add typedef printers to libstdc++
@ 2012-09-21 21:08 Tom Tromey
  2012-09-22 10:55 ` Magnus Fromreide
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2012-09-21 21:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc

This patch adds some typedef printers to libstdc++.

This relies on a gdb patch that hasn't yet gone in (pending on the list).
If the gdb patch changes, I'll change these printers as well.

The basic idea is that you can now have gdb substitute a name of your
choice when printing a type's name.  This lets a library pretend that
some typedefs are canonical.

This includes a fairly comprehensive test case for the new type
printers.

Tom

b/libstdc++-v3/ChangeLog:
2012-09-21  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.

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 0eac413..5b11cb0 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.
@@ -789,6 +798,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."
 
@@ -802,6 +902,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 b9d4742..9457cfe 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,21 @@ 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 {
+	    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 +150,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 +210,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 +221,7 @@ proc gdb_version_check {} {
     }
 
     remote_expect target [timeout_value] {
-	-re "<built-in function lookup_global_symbol>" {
+	-re $pattern {
 	    return 1
 	}
 
@@ -215,3 +239,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 0000000..259694d
--- /dev/null
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -0,0 +1,229 @@
+// { 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;
+};
+
+// 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>" } }
+
+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);
+
+  return 0;
+}
+
+// { dg-final { gdb-test SPOT } }

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

* Re: add typedef printers to libstdc++
  2012-09-21 21:08 add typedef printers to libstdc++ Tom Tromey
@ 2012-09-22 10:55 ` Magnus Fromreide
  2012-09-25 21:30   ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Magnus Fromreide @ 2012-09-22 10:55 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches, libstdc

On Fri, 2012-09-21 at 14:59 -0600, Tom Tromey wrote:
> This patch adds some typedef printers to libstdc++.
> 
> This relies on a gdb patch that hasn't yet gone in (pending on the list).
> If the gdb patch changes, I'll change these printers as well.
> 
> The basic idea is that you can now have gdb substitute a name of your
> choice when printing a type's name.  This lets a library pretend that
> some typedefs are canonical.
> 
> This includes a fairly comprehensive test case for the new type
> printers.

I have not tested it, but when looking at the test case and also on the
code I couldn't help but ask myself how it handles other derivations.

How does it display the types of the variables us, s and ss in the
following code:
---
#include <string>

typedef std::basic_string<unsigned char> ustring;

ustring us;
std::string s;
std::basic_string<signed char> ss;
---

I would expect it to say std::basic_string<unsigned char,...>,
std::string and std::basic_string<signed char,...>, but I thought a test
case here couldn't hurt?

/MF

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

* Re: add typedef printers to libstdc++
  2012-09-22 10:55 ` Magnus Fromreide
@ 2012-09-25 21:30   ` Tom Tromey
  2012-09-26  4:29     ` Paolo Carlini
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2012-09-25 21:30 UTC (permalink / raw)
  To: Magnus Fromreide; +Cc: gcc-patches, libstdc

>>>>> "Magnus" == Magnus Fromreide <magfr@lysator.liu.se> writes:

Magnus> How does it display the types of the variables us, s and ss in the
Magnus> following code:

It does what you'd expect.

Magnus> I would expect it to say std::basic_string<unsigned char,...>,
Magnus> std::string and std::basic_string<signed char,...>, but I thought a test
Magnus> case here couldn't hurt?

Here's an updated patch with the new tests.

Tom

2012-09-25  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.

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 0eac413..5b11cb0 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.
@@ -789,6 +798,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."
 
@@ -802,6 +902,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 b9d4742..9457cfe 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,21 @@ 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 {
+	    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 +150,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 +210,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 +221,7 @@ proc gdb_version_check {} {
     }
 
     remote_expect target [timeout_value] {
-	-re "<built-in function lookup_global_symbol>" {
+	-re $pattern {
 	    return 1
 	}
 
@@ -215,3 +239,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 0000000..c22246c
--- /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 } }

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

* Re: add typedef printers to libstdc++
  2012-09-25 21:30   ` Tom Tromey
@ 2012-09-26  4:29     ` Paolo Carlini
       [not found]       ` <CAH6eHdRc=KgbqHJV5_oKFv5_x9nS18E-yLZaA0fApVa1VqDM0g@mail.gmail.com>
  0 siblings, 1 reply; 7+ messages in thread
From: Paolo Carlini @ 2012-09-26  4:29 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Magnus Fromreide, gcc-patches, libstdc

Hi Tom,

On 09/25/2012 10:53 PM, Tom Tromey wrote:
>>>>>> "Magnus" == Magnus Fromreide <magfr@lysator.liu.se> writes:
> Magnus> How does it display the types of the variables us, s and ss in the
> Magnus> following code:
>
> It does what you'd expect.
>
> Magnus> I would expect it to say std::basic_string<unsigned char,...>,
> Magnus> std::string and std::basic_string<signed char,...>, but I thought a test
> Magnus> case here couldn't hurt?
>
> Here's an updated patch with the new tests.
Jon knows the prettyprinters much better than me, but he is currently 
traveling. I guess, unless he has something to add over the next couple 
of days or so, let's go ahead.

Thanks!
Paolo.

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

* Re: add typedef printers to libstdc++
       [not found]       ` <CAH6eHdRc=KgbqHJV5_oKFv5_x9nS18E-yLZaA0fApVa1VqDM0g@mail.gmail.com>
@ 2012-09-27 18:08         ` Tom Tromey
  2012-11-16 18:05           ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2012-09-27 18:08 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Paolo Carlini, gcc-patches, libstdc, Magnus Fromreide

Jonathan> Please go ahead and commit, thanks, Tom!

Thanks.  The needed gdb patches are still pending, so I plan to wait
until those go in before committing to libstdc++.  I hope it will be
next week sometime.

Tom

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

* Re: add typedef printers to libstdc++
  2012-09-27 18:08         ` Tom Tromey
@ 2012-11-16 18:05           ` Tom Tromey
  2012-11-16 18:12             ` Jonathan Wakely
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2012-11-16 18:05 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Paolo Carlini, gcc-patches, libstdc, Magnus Fromreide

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Jonathan> Please go ahead and commit, thanks, Tom!

Tom> Thanks.  The needed gdb patches are still pending, so I plan to wait
Tom> until those go in before committing to libstdc++.  I hope it will be
Tom> next week sometime.

Hahaha, "next week".  The patches went in this week.

I rebased and re-tested my libstdc++ patch.  While testing it with an
older gdb, I noticed a Tcl error from the test suite, so here is a new
version that correctly reports "unsupported" for the new tests.

The change from the last version is this addition in proc gdb-test:

+	    } else {
+	        unsupported "$testname"
+	        close $fd
+	        return
+	    }

Ok?

Tom

b/libstdc++-v3/ChangeLog:
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.

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 5197284..294ec4c 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 b9d4742..3434ef2 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 0000000..c22246c
--- /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 } }

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

* Re: add typedef printers to libstdc++
  2012-11-16 18:05           ` Tom Tromey
@ 2012-11-16 18:12             ` Jonathan Wakely
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Wakely @ 2012-11-16 18:12 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Paolo Carlini, gcc-patches, libstdc, Magnus Fromreide

On 16 November 2012 18:05, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
>
> Jonathan> Please go ahead and commit, thanks, Tom!
>
> Tom> Thanks.  The needed gdb patches are still pending, so I plan to wait
> Tom> until those go in before committing to libstdc++.  I hope it will be
> Tom> next week sometime.
>
> Hahaha, "next week".  The patches went in this week.
>
> I rebased and re-tested my libstdc++ patch.  While testing it with an
> older gdb, I noticed a Tcl error from the test suite, so here is a new
> version that correctly reports "unsupported" for the new tests.
>
> The change from the last version is this addition in proc gdb-test:
>
> +           } else {
> +               unsupported "$testname"
> +               close $fd
> +               return
> +           }
>
> Ok?

Yes, thanks

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

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

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-21 21:08 add typedef printers to libstdc++ Tom Tromey
2012-09-22 10:55 ` Magnus Fromreide
2012-09-25 21:30   ` Tom Tromey
2012-09-26  4:29     ` Paolo Carlini
     [not found]       ` <CAH6eHdRc=KgbqHJV5_oKFv5_x9nS18E-yLZaA0fApVa1VqDM0g@mail.gmail.com>
2012-09-27 18:08         ` Tom Tromey
2012-11-16 18:05           ` Tom Tromey
2012-11-16 18:12             ` Jonathan Wakely

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