This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH] [libstdc++/65839] whatis support for xmethods
- From: Doug Evans <dje at google dot com>
- To: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Cc: sivachandra at google dot com
- Date: Mon, 27 Apr 2015 15:44:50 -0700
- Subject: [PATCH] [libstdc++/65839] whatis support for xmethods
- Authentication-results: sourceware.org; auth=none
Hi.
This patch is the counterpart to this patch to fix
libstdc++/65839, gdb/18285.
https://sourceware.org/ml/gdb-patches/2015-04/msg00947.html
Regression tested on amd64-linux with/without a patched gdb.
Without a patched gdb the new tests fail, but that's good.
2015-04-27 Doug Evans <dje@google.com>
PR libstdc++/65839
* python/libstdcxx/v6/xmethods.py (get_bool_type): New function.
Replace all lookups of "bool" with this.
(get_std_size_type): New function. Replace all lookups of std::size_t
with this.
(ArrayWorkerBase): Rename arg valtype to elem_type for consistency,
and save it in self._elem_type.
(DequeWorkerBase): Save elemtype.
(ListWorkerBase): New arg elem_type.
(ListMethodsMatcher): Update call to method.worker_class.
(UniquePtrGetWorker.__init__): New arg ptr_type. Delete setting of
name, enabled.
(UniquePtrDerefWorker.__init__): New arg ptr_type. Delete setting of
name.
(UniquePtrMethodsMatcher): Rewrite for consistency with all other
libstdc++ xmethod matchers.
(*Worker): New method get_result_type.
* testsuite/libstdc++-xmethods/array.cc: Add whatis tests.
* testsuite/libstdc++-xmethods/associative-containers.cc: Ditto.
* testsuite/libstdc++-xmethods/deque.cc: Ditto.
* testsuite/libstdc++-xmethods/forwardlist.cc: Ditto.
* testsuite/libstdc++-xmethods/unique_ptr.cc: Ditto.
* testsuite/libstdc++-xmethods/vector.cc: Ditto.
* testsuite/libstdc++-xmethods/list.cc: Ditto.
Index: python/libstdcxx/v6/xmethods.py
===================================================================
--- python/libstdcxx/v6/xmethods.py (revision 222477)
+++ python/libstdcxx/v6/xmethods.py (working copy)
@@ -21,6 +21,12 @@ import re
matcher_name_prefix = 'libstdc++::'
+def get_bool_type():
+ return gdb.lookup_type('bool')
+
+def get_std_size_type():
+ return gdb.lookup_type('std::size_t')
+
class LibStdCxxXMethod(gdb.xmethod.XMethod):
def __init__(self, name, worker_class):
gdb.xmethod.XMethod.__init__(self, name)
@@ -29,13 +35,13 @@ class LibStdCxxXMethod(gdb.xmethod.XMethod):
# Xmethods for std::array
class ArrayWorkerBase(gdb.xmethod.XMethodWorker):
- def __init__(self, valtype, size):
- self._valtype = valtype
+ def __init__(self, elem_type, size):
+ self._elem_type = elem_type
self._size = size
def null_value(self):
nullptr = gdb.parse_and_eval('(void *) 0')
- return nullptr.cast(self._valtype.pointer()).dereference()
+ return nullptr.cast(self._elem_type.pointer()).dereference()
class ArraySizeWorker(ArrayWorkerBase):
def __init__(self, valtype, size):
@@ -44,6 +50,9 @@ class ArraySizeWorker(ArrayWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return get_std_size_type()
+
def __call__(self, obj):
return self._size
@@ -54,6 +63,9 @@ class ArrayEmptyWorker(ArrayWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return get_bool_type()
+
def __call__(self, obj):
return (int(self._size) == 0)
@@ -64,6 +76,9 @@ class ArrayFrontWorker(ArrayWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._elem_type
+
def __call__(self, obj):
if int(self._size) > 0:
return obj['_M_elems'][0]
@@ -77,6 +92,9 @@ class ArrayBackWorker(ArrayWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._elem_type
+
def __call__(self, obj):
if int(self._size) > 0:
return obj['_M_elems'][self._size - 1]
@@ -88,8 +106,11 @@ class ArrayAtWorker(ArrayWorkerBase):
ArrayWorkerBase.__init__(self, valtype, size)
def get_arg_types(self):
- return gdb.lookup_type('std::size_t')
+ return get_std_size_type()
+ def get_result_type(self, obj, index):
+ return self._elem_type
+
def __call__(self, obj, index):
if int(index) >= int(self._size):
raise IndexError('Array index "%d" should not be >= %d.' %
@@ -101,8 +122,11 @@ class ArraySubscriptWorker(ArrayWorkerBase):
ArrayWorkerBase.__init__(self, valtype, size)
def get_arg_types(self):
- return gdb.lookup_type('std::size_t')
+ return get_std_size_type()
+ def get_result_type(self, obj, index):
+ return self._elem_type
+
def __call__(self, obj, index):
if int(self._size) > 0:
return obj['_M_elems'][index]
@@ -140,6 +164,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatch
class DequeWorkerBase(gdb.xmethod.XMethodWorker):
def __init__(self, elemtype):
+ self._elemtype = elemtype
self._bufsize = (512 / elemtype.sizeof) or 1
def size(self, obj):
@@ -158,6 +183,9 @@ class DequeEmptyWorker(DequeWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return get_bool_type()
+
def __call__(self, obj):
return (obj['_M_impl']['_M_start']['_M_cur'] ==
obj['_M_impl']['_M_finish']['_M_cur'])
@@ -166,6 +194,9 @@ class DequeSizeWorker(DequeWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return get_std_size_type()
+
def __call__(self, obj):
return self.size(obj)
@@ -173,6 +204,9 @@ class DequeFrontWorker(DequeWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._elemtype
+
def __call__(self, obj):
return obj['_M_impl']['_M_start']['_M_cur'][0]
@@ -180,6 +214,9 @@ class DequeBackWorker(DequeWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._elemtype
+
def __call__(self, obj):
if (obj['_M_impl']['_M_finish']['_M_cur'] ==
obj['_M_impl']['_M_finish']['_M_first']):
@@ -190,15 +227,21 @@ class DequeBackWorker(DequeWorkerBase):
class DequeSubscriptWorker(DequeWorkerBase):
def get_arg_types(self):
- return gdb.lookup_type('std::size_t')
+ return get_std_size_type()
+ def get_result_type(self, obj, subscript):
+ return self._elemtype
+
def __call__(self, obj, subscript):
return self.index(obj, subscript)
class DequeAtWorker(DequeWorkerBase):
def get_arg_types(self):
- return gdb.lookup_type('std::size_t')
+ return get_std_size_type()
+ def get_result_type(self, obj, index):
+ return self._elemtype
+
def __call__(self, obj, index):
deque_size = int(self.size(obj))
if int(index) >= deque_size:
@@ -240,10 +283,16 @@ class ForwardListWorkerBase(gdb.xmethod.XMethodMat
return None
class ForwardListEmptyWorker(ForwardListWorkerBase):
+ def get_result_type(self, obj):
+ return get_bool_type()
+
def __call__(self, obj):
return obj['_M_impl']['_M_head']['_M_next'] == 0
class ForwardListFrontWorker(ForwardListWorkerBase):
+ def get_result_type(self, obj):
+ return self._elem_type
+
def __call__(self, obj):
node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type)
elem_address = node['_M_storage']['_M_storage'].address
@@ -272,7 +321,8 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMetho
# Xmethods for std::list
class ListWorkerBase(gdb.xmethod.XMethodWorker):
- def __init__(self, node_type):
+ def __init__(self, elem_type, node_type):
+ self._elem_type = elem_type
self._node_type = node_type
def get_arg_types(self):
@@ -279,6 +329,9 @@ class ListWorkerBase(gdb.xmethod.XMethodWorker):
return None
class ListEmptyWorker(ListWorkerBase):
+ def get_result_type(self, obj):
+ return get_bool_type()
+
def __call__(self, obj):
base_node = obj['_M_impl']['_M_node']
if base_node['_M_next'] == base_node.address:
@@ -287,6 +340,9 @@ class ListEmptyWorker(ListWorkerBase):
return False
class ListSizeWorker(ListWorkerBase):
+ def get_result_type(self, obj):
+ return get_std_size_type()
+
def __call__(self, obj):
begin_node = obj['_M_impl']['_M_node']['_M_next']
end_node = obj['_M_impl']['_M_node'].address
@@ -297,11 +353,17 @@ class ListSizeWorker(ListWorkerBase):
return size
class ListFrontWorker(ListWorkerBase):
+ def get_result_type(self, obj):
+ return self._elem_type
+
def __call__(self, obj):
node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type)
return node['_M_data']
class ListBackWorker(ListWorkerBase):
+ def get_result_type(self, obj):
+ return self._elem_type
+
def __call__(self, obj):
prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type)
return prev_node['_M_data']
@@ -324,8 +386,9 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatche
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
return None
+ elem_type = class_type.template_argument(0)
node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
- return method.worker_class(node_type)
+ return method.worker_class(elem_type, node_type)
# Xmethods for std::vector
@@ -357,6 +420,9 @@ class VectorEmptyWorker(VectorWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return get_bool_type()
+
def __call__(self, obj):
return int(self.size(obj)) == 0
@@ -364,6 +430,9 @@ class VectorSizeWorker(VectorWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return get_std_size_type()
+
def __call__(self, obj):
return self.size(obj)
@@ -371,6 +440,9 @@ class VectorFrontWorker(VectorWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._elemtype
+
def __call__(self, obj):
return self.get(obj, 0)
@@ -378,13 +450,19 @@ class VectorBackWorker(VectorWorkerBase):
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._elemtype
+
def __call__(self, obj):
return self.get(obj, int(self.size(obj)) - 1)
class VectorAtWorker(VectorWorkerBase):
def get_arg_types(self):
- return gdb.lookup_type('std::size_t')
+ return get_std_size_type()
+ def get_result_type(self, obj, index):
+ return self._elemtype
+
def __call__(self, obj, index):
size = int(self.size(obj))
if int(index) >= size:
@@ -394,8 +472,11 @@ class VectorAtWorker(VectorWorkerBase):
class VectorSubscriptWorker(VectorWorkerBase):
def get_arg_types(self):
- return gdb.lookup_type('std::size_t')
+ return get_std_size_type()
+ def get_result_type(self, obj, subscript):
+ return self._elemtype
+
def __call__(self, obj, subscript):
return self.get(obj, int(subscript))
@@ -438,10 +519,16 @@ class AssociativeContainerWorkerBase(gdb.xmethod.X
return None
class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase):
+ def get_result_type(self, obj):
+ return get_bool_type()
+
def __call__(self, obj):
return int(self.node_count(obj)) == 0
class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase):
+ def get_result_type(self, obj):
+ return get_std_size_type()
+
def __call__(self, obj):
return self.node_count(obj)
@@ -469,20 +556,21 @@ class AssociativeContainerMethodsMatcher(gdb.xmeth
# Xmethods for std::unique_ptr
class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
- def __init__(self):
- self.name = 'get'
- self.enabled = True
+ def __init__(self, ptr_type):
+ self._ptr_type = ptr_type
def get_arg_types(self):
return None
+ def get_result_type(self, obj):
+ return self._ptr_type
+
def __call__(self, obj):
return obj['_M_t']['_M_head_impl']
class UniquePtrDerefWorker(UniquePtrGetWorker):
- def __init__(self):
- UniquePtrGetWorker.__init__(self)
- self.name = 'operator*'
+ def __init__(self, ptr_type):
+ UniquePtrGetWorker.__init__(self, ptr_type)
def __call__(self, obj):
return UniquePtrGetWorker.__call__(self, obj).dereference()
@@ -491,17 +579,19 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodM
def __init__(self):
gdb.xmethod.XMethodMatcher.__init__(self,
matcher_name_prefix + 'unique_ptr')
- self._get_worker = UniquePtrGetWorker()
- self._deref_worker = UniquePtrDerefWorker()
- self.methods = [self._get_worker, self._deref_worker]
+ self._method_dict = {
+ 'get': LibStdCxxXMethod('get', UniquePtrGetWorker),
+ 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker),
+ }
+ self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
if not re.match('^std::unique_ptr<.*>$', class_type.tag):
return None
- if method_name == 'operator*' and self._deref_worker.enabled:
- return self._deref_worker
- elif method_name == 'get' and self._get_worker.enabled:
- return self._get_worker
+ method = self._method_dict.get(method_name)
+ if method is None or not method.enabled:
+ return None
+ return method.worker_class(class_type.template_argument(0))
def register_libstdcxx_xmethods(locus):
gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher())
Index: testsuite/libstdc++-xmethods/array.cc
===================================================================
--- testsuite/libstdc++-xmethods/array.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/array.cc (working copy)
@@ -40,6 +40,13 @@ main ()
// { dg-final { note-test a\[4\] 104 } }
// { dg-final { note-test a\[9\] 109 } }
+// { dg-final { whatis-test a.size() std::size_t } }
+// { dg-final { whatis-test a.empty() bool } }
+// { dg-final { whatis-test a.front() int } }
+// { dg-final { whatis-test a.back() int } }
+// { dg-final { whatis-test a.at(5) int } }
+// { dg-final { whatis-test a\[0\] int } }
+
return 0; // Mark SPOT
}
Index: testsuite/libstdc++-xmethods/associative-containers.cc
===================================================================
--- testsuite/libstdc++-xmethods/associative-containers.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/associative-containers.cc (working copy)
@@ -73,6 +73,9 @@ main ()
// { dg-final { note-test umm.empty() false } }
// { dg-final { note-test umm1.empty() true } }
+// { dg-final { whatis-test s.size() std::size_t } }
+// { dg-final { whatis-test s.empty() bool } }
+
return 0; // Mark SPOT
}
Index: testsuite/libstdc++-xmethods/deque.cc
===================================================================
--- testsuite/libstdc++-xmethods/deque.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/deque.cc (working copy)
@@ -61,6 +61,12 @@ main ()
// { dg-final { note-test q3\[q3_size/2\]==(300+q3_size/2) true } }
// { dg-final { note-test q3\[q3_size-1]==(300+q3_size-1) true } }
+// { dg-final { whatis-test q0.empty() bool } }
+// { dg-final { whatis-test q0.size() std::size_t } }
+// { dg-final { whatis-test q1.front() int } }
+// { dg-final { whatis-test q1.back() int } }
+// { dg-final { whatis-test q3\[0\] int } }
+
return 0; // Mark SPOT
}
Index: testsuite/libstdc++-xmethods/forwardlist.cc
===================================================================
--- testsuite/libstdc++-xmethods/forwardlist.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/forwardlist.cc (working copy)
@@ -34,6 +34,9 @@ main ()
// { dg-final { note-test l1.empty() false } }
// { dg-final { note-test l1.front() 11011 } }
+// { dg-final { whatis-test l1.empty() bool } }
+// { dg-final { whatis-test l1.front() int } }
+
return 0; // Mark SPOT
}
Index: testsuite/libstdc++-xmethods/list.cc
===================================================================
--- testsuite/libstdc++-xmethods/list.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/list.cc (working copy)
@@ -35,6 +38,10 @@ main ()
// { dg-final { note-test l1.front() 123 } }
// { dg-final { note-test l1.back() 789 } }
+// { dg-final { whatis-test l1.empty() bool } }
+// { dg-final { whatis-test l1.size() std::size_t } }
+// { dg-final { whatis-test l1.front() int } }
+// { dg-final { whatis-test l1.back() int } }
return 0; // Mark SPOT
}
Index: testsuite/libstdc++-xmethods/unique_ptr.cc
===================================================================
--- testsuite/libstdc++-xmethods/unique_ptr.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/unique_ptr.cc (working copy)
@@ -27,9 +27,13 @@ main ()
*i = 10;
std::unique_ptr<int> p(i);
+
// { dg-final { note-test *p 10 } }
// { dg-final { regexp-test p.get() 0x.* } }
+// { dg-final { whatis-test *p int } }
+// { dg-final { whatis-test p.get() int } }
+
return 0; // Mark SPOT
}
Index: testsuite/libstdc++-xmethods/vector.cc
===================================================================
--- testsuite/libstdc++-xmethods/vector.cc (revision 222477)
+++ testsuite/libstdc++-xmethods/vector.cc (working copy)
@@ -83,6 +83,19 @@ main ()
// { dg-final { note-test bv3.at(63) true } }
// { dg-final { note-test bv3.at(64) false } }
+// { dg-final { whatis-test v0.empty() bool } }
+// { dg-final { whatis-test v0.size() std::size_t } }
+// { dg-final { whatis-test v1.front() int } }
+// { dg-final { whatis-test v1.back() int } }
+// { dg-final { whatis-test v1\[0\] int } }
+// { dg-final { whatis-test v1.at(1) int } }
+// { dg-final { whatis-test bv0.empty() bool } }
+// { dg-final { whatis-test bv0.size() std::size_t } }
+// { dg-final { whatis-test bv1.front() bool } }
+// { dg-final { whatis-test bv1.back() bool } }
+// { dg-final { whatis-test bv1\[0\] bool } }
+// { dg-final { whatis-test bv1.at(1) bool } }
+
return 0; // Mark SPOT
}