This is another partial fix for PR 59170, this time adding checks for
normal mode iterators that are default-constructed, so we don't try to
dereference null pointers.

We still auto-dereference past-the-end iterators, and iterators that
have been invalidated by container mutation. The former can be
detected in debug mode (with some work to teach each iterator type how
to compare itself to the container's end()) and the latter is already
handled for debug mode. Neither case can be derected in normal mode.

I feel quite strongly that we should disable the printers for
iterators (the ones that make "print iter" automatically dereference
the iterator and print what it points to ... or garbage ... or crash).
I'm going to add Xmethods for all our iterator types so that it will
always be possible to do "print *iter", so if GDB supports Xmethods
then we don't need to register the iterator printers.

        PR libstdc++/59170
        * python/libstdcxx/v6/printers.py (StdListIteratorPrinter.to_string)
        (StdSlistIteratorPrinter.to_string, StdVectorIteratorPrinter.to_string)
        (StdRbtreeIteratorPrinter.to_string)
        (StdDequeIteratorPrinter.to_string): Add check for value-initialized
        iterators.
        * testsuite/libstdc++-prettyprinters/simple.cc: Test them.
        * testsuite/libstdc++-prettyprinters/simple11.cc: Likewise.

Tested x86_64-linux, committed to trunk.
commit 7b73bc563a5b4828b80e18d34cc06c0cbdae12ef
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Thu Dec 15 14:05:24 2016 +0000

    PR59170 make pretty printers check for singular iterators
    
        PR libstdc++/59170
        * python/libstdcxx/v6/printers.py (StdListIteratorPrinter.to_string)
        (StdSlistIteratorPrinter.to_string, StdVectorIteratorPrinter.to_string)
        (StdRbtreeIteratorPrinter.to_string)
        (StdDequeIteratorPrinter.to_string): Add check for value-initialized
        iterators.
        * testsuite/libstdc++-prettyprinters/simple.cc: Test them.
        * testsuite/libstdc++-prettyprinters/simple11.cc: Likewise.

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py 
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index ab3592a..86de1ca 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -200,6 +200,8 @@ class StdListIteratorPrinter:
         self.typename = typename
 
     def to_string(self):
+        if not self.val['_M_node']:
+            return 'non-dereferenceable iterator for std::list'
         nodetype = find_type(self.val.type, '_Node')
         nodetype = nodetype.strip_typedefs().pointer()
         node = self.val['_M_node'].cast(nodetype).dereference()
@@ -246,6 +248,8 @@ class StdSlistIteratorPrinter:
         self.val = val
 
     def to_string(self):
+        if not self.val['_M_node']:
+            return 'non-dereferenceable iterator for __gnu_cxx::slist'
         nodetype = find_type(self.val.type, '_Node')
         nodetype = nodetype.strip_typedefs().pointer()
         return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data'])
@@ -333,6 +337,8 @@ class StdVectorIteratorPrinter:
         self.val = val
 
     def to_string(self):
+        if not self.val['_M_current']:
+            return 'non-dereferenceable iterator for std::vector'
         return str(self.val['_M_current'].dereference())
 
 class StdTuplePrinter:
@@ -494,6 +500,8 @@ class StdRbtreeIteratorPrinter:
         self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
+        if not self.val['_M_node']:
+            return 'non-dereferenceable iterator for associative container'
         node = self.val['_M_node'].cast(self.link_type).dereference()
         return str(get_value_from_Rb_tree_node(node))
 
@@ -708,6 +716,8 @@ class StdDequeIteratorPrinter:
         self.val = val
 
     def to_string(self):
+        if not self.val['_M_cur']:
+            return 'non-dereferenceable iterator for std::deque'
         return str(self.val['_M_cur'].dereference())
 
 class StdStringPrinter:
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
index fb8e0d7..35fbb90 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
@@ -30,6 +30,7 @@
 #include <list>
 #include <map>
 #include <set>
+#include <vector>
 #include <ext/slist>
 
 int
@@ -50,6 +51,9 @@ main()
   deq.push_back("two");
 // { dg-final { note-test deq {std::deque with 2 elements = {"one", "two"}} } }
 
+  std::deque<int>::iterator deqiter0;
+// { dg-final { note-test deqiter0 {non-dereferenceable iterator for 
std::deque} } }
+
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
 
@@ -58,6 +62,9 @@ main()
   lst.push_back("two");
 // { dg-final { note-test lst {std::list = {[0] = "one", [1] = "two"}} } }
 
+  std::list<int>::iterator lstiter0;
+// { dg-final { note-test lstiter0 {non-dereferenceable iterator for 
std::list} } }
+
   std::list<std::string>::iterator lstiter = lst.begin();
   tem = *lstiter;
 // { dg-final { note-test lstiter {"one"}} }
@@ -73,6 +80,9 @@ main()
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
+  std::map<std::string, int>::iterator mpiter0;
+// { dg-final { note-test mpiter0 {non-dereferenceable iterator for 
associative container} } }
+
   // PR 67440
   std::set<int> intset;
   intset.insert(2);
@@ -88,6 +98,20 @@ main()
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
 
+  std::set<int>::iterator spiter0;
+// { dg-final { note-test spiter0 {non-dereferenceable iterator for 
associative container} } }
+
+  std::vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  v.erase(v.begin());
+// { dg-final { note-test v {std::vector of length 1, capacity 2 = {2}} } }
+  std::vector<int>::iterator viter3 = v.begin();
+// { dg-final { note-test viter3 {2} } }
+
+  std::vector<int>::iterator viter0;
+// { dg-final { note-test viter0 {non-dereferenceable iterator for 
std::vector} } }
+
   __gnu_cxx::slist<int> sll;
   sll.push_front(23);
   sll.push_front(47);
@@ -96,6 +120,9 @@ main()
   __gnu_cxx::slist<int>::iterator slliter = sll.begin();
 // { dg-final { note-test slliter {47} } }
 
+  __gnu_cxx::slist<int>::iterator slliter0;
+// { dg-final { note-test slliter0 {non-dereferenceable iterator for 
__gnu_cxx::slist} } }
+
   std::cout << "\n";
   return 0;                    // Mark SPOT
 }
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
index 9e230e3..8efe00e 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
@@ -30,6 +30,7 @@
 #include <list>
 #include <map>
 #include <set>
+#include <vector>
 #include <ext/slist>
 
 int
@@ -53,6 +54,9 @@ main()
   std::deque<std::string>::iterator deqiter = deq.begin();
 // { dg-final { note-test deqiter {"one"} } }
 
+  std::deque<int>::iterator deqiter0;
+// { dg-final { note-test deqiter0 {non-dereferenceable iterator for 
std::deque} } }
+
   std::list<std::string> lst;
   lst.push_back("one");
   lst.push_back("two");
@@ -66,6 +70,9 @@ main()
   tem = *lstciter;
 // { dg-final { note-test lstciter {"one"}} }
 
+  std::list<int>::iterator lstiter0;
+// { dg-final { note-test lstiter0 {non-dereferenceable iterator for 
std::list} } }
+
   std::map<std::string, int> mp;
   mp["zardoz"] = 23;
 // { dg-final { note-test mp {std::map with 1 element = {["zardoz"] = 23}} } }
@@ -73,6 +80,9 @@ main()
   std::map<std::string, int>::iterator mpiter = mp.begin();
 // { dg-final { note-test mpiter {{first = "zardoz", second = 23}} } }
 
+  std::map<std::string, int>::iterator mpiter0;
+// { dg-final { note-test mpiter0 {non-dereferenceable iterator for 
associative container} } }
+
   // PR 67440
   const std::set<int> const_intset = {2, 3};
 // { dg-final { note-test const_intset {std::set with 2 elements = {[0] = 2, 
[1] = 3}} } }
@@ -85,6 +95,20 @@ main()
   std::set<std::string>::const_iterator spciter = sp.begin();
 // { dg-final { note-test spciter {"barrel"} } }
 
+  std::set<int>::iterator spiter0;
+// { dg-final { note-test spiter0 {non-dereferenceable iterator for 
associative container} } }
+
+  std::vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  v.erase(v.begin());
+// { dg-final { note-test v {std::vector of length 1, capacity 2 = {2}} } }
+  std::vector<int>::iterator viter3 = v.begin();
+// { dg-final { note-test viter3 {2} } }
+
+  std::vector<int>::iterator viter0;
+// { dg-final { note-test viter0 {non-dereferenceable iterator for 
std::vector} } }
+
   __gnu_cxx::slist<int> sll;
   sll.push_front(23);
   sll.push_front(47);
@@ -93,6 +117,9 @@ main()
   __gnu_cxx::slist<int>::iterator slliter = sll.begin();
 // { dg-final { note-test slliter {47} } }
 
+  __gnu_cxx::slist<int>::iterator slliter0;
+// { dg-final { note-test slliter0 {non-dereferenceable iterator for 
__gnu_cxx::slist} } }
+
   std::cout << "\n";
   return 0;                    // Mark SPOT
 }

Reply via email to