Patchwork Patch: fix std::unordered_map (et al) pretty printer

login
register
mail settings
Submitter Tom Tromey
Date Feb. 14, 2012, 8:16 p.m.
Message ID <8739adp3vt.fsf@fleche.redhat.com>
Download mbox | patch
Permalink /patch/141181/
State New
Headers show

Comments

Tom Tromey - Feb. 14, 2012, 8:16 p.m.
Jakub mentioned a while back that the std::unordered_map pretty printer
in libstdc++ was not working properly.

This patch fixes the problems with this printer (and other printers
using Tr1HashtableIterator).

The problem was incorrect iteration of the hash table; I think all the
nodes in the hash table are linked together via their _M_nxt fields, so
I have simplified the iterator to just do this.

I've included some new test cases.

Tested on x86-64 Fedora 16.

Ok?

Tom

2012-02-14  Tom Tromey  <tromey@redhat.com>

	* testsuite/libstdc++-prettyprinters/cxx11.cc (main): Add new
	tests.
	* python/libstdcxx/v6/printers.py (Tr1HashtableIterator.__init__):
	Rewrite.
	(Tr1HashtableIterator.update): Remove.
	(Tr1HashtableIterator.next): Rewrite.
Jonathan Wakely - Feb. 14, 2012, 8:20 p.m.
On 14 February 2012 20:16, Tom Tromey wrote:
>
> Ok?

OK, thanks!

Patch

Index: python/libstdcxx/v6/printers.py
===================================================================
--- python/libstdcxx/v6/printers.py	(revision 184215)
+++ python/libstdcxx/v6/printers.py	(working copy)
@@ -610,38 +610,18 @@ 
 
 class Tr1HashtableIterator:
     def __init__ (self, hash):
-        self.count = 0
-        self.n_buckets = hash['_M_element_count']
-        if self.n_buckets == 0:
-            self.node = False
-        else:
-            self.bucket = hash['_M_buckets']
-            self.node = self.bucket[0]
-            self.update ()
+        self.node = hash['_M_before_begin']['_M_nxt']
+        self.node_type = find_type(hash.type, '_Node').pointer()
 
     def __iter__ (self):
         return self
 
-    def update (self):
-        # If we advanced off the end of the chain, move to the next
-        # bucket.
-        while self.node == 0:
-            self.bucket = self.bucket + 1
-            self.node = self.bucket[0]
-
-       # If we advanced off the end of the bucket array, then
-       # we're done.
-        if self.count == self.n_buckets:
-            self.node = False
-        else:
-            self.count = self.count + 1
-
     def next (self):
-        if not self.node:
+        if self.node == 0:
             raise StopIteration
-        result = self.node.dereference()['_M_v']
-        self.node = self.node.dereference()['_M_next']
-        self.update ()
+        node = self.node.cast(self.node_type)
+        result = node.dereference()['_M_v']
+        self.node = node.dereference()['_M_nxt']
         return result
 
 class Tr1UnorderedSetPrinter:
Index: testsuite/libstdc++-prettyprinters/cxx11.cc
===================================================================
--- testsuite/libstdc++-prettyprinters/cxx11.cc	(revision 184215)
+++ testsuite/libstdc++-prettyprinters/cxx11.cc	(working copy)
@@ -1,7 +1,7 @@ 
 // { dg-do run }
 // { dg-options "-std=gnu++11 -g" }
 
-// 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
@@ -68,6 +68,24 @@ 
   std::unordered_multiset<int> eums;
 // { dg-final { note-test eums "std::unordered_multiset with 0 elements" } }
 
+  std::unordered_map<int, std::string> uom;
+  uom[5] = "three";
+  uom[3] = "seven";
+// { dg-final { note-test uom {std::unordered_map with 2 elements = {[3] = "seven", [5] = "three"}} } }
+
+  std::unordered_multimap<int, std::string> uomm;
+  uomm.insert(std::pair<int, std::string> (5, "three"));
+  uomm.insert(std::pair<int, std::string> (5, "seven"));
+// { dg-final { note-test uomm {std::unordered_multimap with 2 elements = {[5] = "seven", [5] = "three"}} } }
+
+  std::unordered_set<int> uos;
+  uos.insert(5);
+// { dg-final { note-test uos {std::unordered_set with 1 elements = {[0] = 5}} } }
+
+  std::unordered_multiset<int> uoms;
+  uoms.insert(5);
+// { dg-final { note-test uoms {std::unordered_multiset with 1 elements = {[0] = 5}} } }
+
   placeholder(""); // Mark SPOT
   use(efl);
   use(fl);