1 # Xmethods for libstdc++.
3 # Copyright (C) 2014-2022 Free Software Foundation, Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 matcher_name_prefix
= 'libstdc++::'
26 return gdb
.lookup_type('bool')
28 def get_std_size_type():
29 return gdb
.lookup_type('std::size_t')
31 _versioned_namespace
= '__8::'
33 def is_specialization_of(x
, template_name
):
35 Test whether a type is a specialization of the named class template.
36 The type can be specified as a string or a gdb.Type object.
37 The template should be the name of a class template as a string,
38 without any 'std' qualification.
40 if isinstance(x
, gdb
.Type
):
42 template_name
= '(%s)?%s' % (_versioned_namespace
, template_name
)
43 return re
.match(r
'^std::(__\d::)?%s<.*>$' % template_name
, x
) is not None
45 class LibStdCxxXMethod(gdb
.xmethod
.XMethod
):
46 def __init__(self
, name
, worker_class
):
47 gdb
.xmethod
.XMethod
.__init
__(self
, name
)
48 self
.worker_class
= worker_class
50 # Xmethods for std::array
53 class ArrayWorkerBase(gdb
.xmethod
.XMethodWorker
):
54 def __init__(self
, val_type
, size
):
55 self
._val
_type
= val_type
59 nullptr
= gdb
.parse_and_eval('(void *) 0')
60 return nullptr
.cast(self
._val
_type
.pointer()).dereference()
63 class ArraySizeWorker(ArrayWorkerBase
):
64 def __init__(self
, val_type
, size
):
65 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
67 def get_arg_types(self
):
70 def get_result_type(self
, obj
):
71 return get_std_size_type()
73 def __call__(self
, obj
):
77 class ArrayEmptyWorker(ArrayWorkerBase
):
78 def __init__(self
, val_type
, size
):
79 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
81 def get_arg_types(self
):
84 def get_result_type(self
, obj
):
85 return get_bool_type()
87 def __call__(self
, obj
):
88 return (int(self
._size
) == 0)
91 class ArrayFrontWorker(ArrayWorkerBase
):
92 def __init__(self
, val_type
, size
):
93 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
95 def get_arg_types(self
):
98 def get_result_type(self
, obj
):
101 def __call__(self
, obj
):
102 if int(self
._size
) > 0:
103 return obj
['_M_elems'][0]
105 return self
.null_value()
108 class ArrayBackWorker(ArrayWorkerBase
):
109 def __init__(self
, val_type
, size
):
110 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
112 def get_arg_types(self
):
115 def get_result_type(self
, obj
):
116 return self
._val
_type
118 def __call__(self
, obj
):
119 if int(self
._size
) > 0:
120 return obj
['_M_elems'][self
._size
- 1]
122 return self
.null_value()
125 class ArrayAtWorker(ArrayWorkerBase
):
126 def __init__(self
, val_type
, size
):
127 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
129 def get_arg_types(self
):
130 return get_std_size_type()
132 def get_result_type(self
, obj
, index
):
133 return self
._val
_type
135 def __call__(self
, obj
, index
):
136 if int(index
) >= int(self
._size
):
137 raise IndexError('Array index "%d" should not be >= %d.' %
138 ((int(index
), self
._size
)))
139 return obj
['_M_elems'][index
]
142 class ArraySubscriptWorker(ArrayWorkerBase
):
143 def __init__(self
, val_type
, size
):
144 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
146 def get_arg_types(self
):
147 return get_std_size_type()
149 def get_result_type(self
, obj
, index
):
150 return self
._val
_type
152 def __call__(self
, obj
, index
):
153 if int(self
._size
) > 0:
154 return obj
['_M_elems'][index
]
156 return self
.null_value()
159 class ArrayMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
161 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
162 matcher_name_prefix
+ 'array')
163 self
._method
_dict
= {
164 'size': LibStdCxxXMethod('size', ArraySizeWorker
),
165 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker
),
166 'front': LibStdCxxXMethod('front', ArrayFrontWorker
),
167 'back': LibStdCxxXMethod('back', ArrayBackWorker
),
168 'at': LibStdCxxXMethod('at', ArrayAtWorker
),
169 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker
),
171 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
173 def match(self
, class_type
, method_name
):
174 if not is_specialization_of(class_type
, 'array'):
176 method
= self
._method
_dict
.get(method_name
)
177 if method
is None or not method
.enabled
:
180 value_type
= class_type
.template_argument(0)
181 size
= class_type
.template_argument(1)
184 return method
.worker_class(value_type
, size
)
187 # Xmethods for std::deque
190 class DequeWorkerBase(gdb
.xmethod
.XMethodWorker
):
191 def __init__(self
, val_type
):
192 self
._val
_type
= val_type
193 self
._bufsize
= 512 // val_type
.sizeof
or 1
196 start
= obj
['_M_impl']['_M_start']
197 finish
= obj
['_M_impl']['_M_finish']
198 if not start
['_M_node']:
200 return (self
._bufsize
201 * (finish
['_M_node'] - start
['_M_node'] - 1)
202 + (finish
['_M_cur'] - finish
['_M_first'])
203 + (start
['_M_last'] - start
['_M_cur']))
205 def index(self
, obj
, idx
):
206 first_node
= obj
['_M_impl']['_M_start']['_M_node']
207 index_node
= first_node
+ int(idx
) // self
._bufsize
208 return index_node
[0][idx
% self
._bufsize
]
211 class DequeEmptyWorker(DequeWorkerBase
):
212 def get_arg_types(self
):
215 def get_result_type(self
, obj
):
216 return get_bool_type()
218 def __call__(self
, obj
):
219 return (obj
['_M_impl']['_M_start']['_M_cur'] ==
220 obj
['_M_impl']['_M_finish']['_M_cur'])
223 class DequeSizeWorker(DequeWorkerBase
):
224 def get_arg_types(self
):
227 def get_result_type(self
, obj
):
228 return get_std_size_type()
230 def __call__(self
, obj
):
231 return self
.size(obj
)
234 class DequeFrontWorker(DequeWorkerBase
):
235 def get_arg_types(self
):
238 def get_result_type(self
, obj
):
239 return self
._val
_type
241 def __call__(self
, obj
):
242 return obj
['_M_impl']['_M_start']['_M_cur'][0]
245 class DequeBackWorker(DequeWorkerBase
):
246 def get_arg_types(self
):
249 def get_result_type(self
, obj
):
250 return self
._val
_type
252 def __call__(self
, obj
):
253 if (obj
['_M_impl']['_M_finish']['_M_cur'] ==
254 obj
['_M_impl']['_M_finish']['_M_first']):
255 prev_node
= obj
['_M_impl']['_M_finish']['_M_node'] - 1
256 return prev_node
[0][self
._bufsize
- 1]
258 return obj
['_M_impl']['_M_finish']['_M_cur'][-1]
261 class DequeSubscriptWorker(DequeWorkerBase
):
262 def get_arg_types(self
):
263 return get_std_size_type()
265 def get_result_type(self
, obj
, subscript
):
266 return self
._val
_type
268 def __call__(self
, obj
, subscript
):
269 return self
.index(obj
, subscript
)
272 class DequeAtWorker(DequeWorkerBase
):
273 def get_arg_types(self
):
274 return get_std_size_type()
276 def get_result_type(self
, obj
, index
):
277 return self
._val
_type
279 def __call__(self
, obj
, index
):
280 deque_size
= int(self
.size(obj
))
281 if int(index
) >= deque_size
:
282 raise IndexError('Deque index "%d" should not be >= %d.' %
283 (int(index
), deque_size
))
285 return self
.index(obj
, index
)
288 class DequeMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
290 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
291 matcher_name_prefix
+ 'deque')
292 self
._method
_dict
= {
293 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker
),
294 'size': LibStdCxxXMethod('size', DequeSizeWorker
),
295 'front': LibStdCxxXMethod('front', DequeFrontWorker
),
296 'back': LibStdCxxXMethod('back', DequeBackWorker
),
297 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker
),
298 'at': LibStdCxxXMethod('at', DequeAtWorker
)
300 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
302 def match(self
, class_type
, method_name
):
303 if not is_specialization_of(class_type
, 'deque'):
305 method
= self
._method
_dict
.get(method_name
)
306 if method
is None or not method
.enabled
:
308 return method
.worker_class(class_type
.template_argument(0))
310 # Xmethods for std::forward_list
313 class ForwardListWorkerBase(gdb
.xmethod
.XMethodMatcher
):
314 def __init__(self
, val_type
, node_type
):
315 self
._val
_type
= val_type
316 self
._node
_type
= node_type
318 def get_arg_types(self
):
322 class ForwardListEmptyWorker(ForwardListWorkerBase
):
323 def get_result_type(self
, obj
):
324 return get_bool_type()
326 def __call__(self
, obj
):
327 return obj
['_M_impl']['_M_head']['_M_next'] == 0
330 class ForwardListFrontWorker(ForwardListWorkerBase
):
331 def get_result_type(self
, obj
):
332 return self
._val
_type
334 def __call__(self
, obj
):
335 node
= obj
['_M_impl']['_M_head']['_M_next'].cast(self
._node
_type
)
336 val_address
= node
['_M_storage']['_M_storage'].address
337 return val_address
.cast(self
._val
_type
.pointer()).dereference()
340 class ForwardListMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
342 matcher_name
= matcher_name_prefix
+ 'forward_list'
343 gdb
.xmethod
.XMethodMatcher
.__init
__(self
, matcher_name
)
344 self
._method
_dict
= {
345 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker
),
346 'front': LibStdCxxXMethod('front', ForwardListFrontWorker
)
348 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
350 def match(self
, class_type
, method_name
):
351 if not is_specialization_of(class_type
, 'forward_list'):
353 method
= self
._method
_dict
.get(method_name
)
354 if method
is None or not method
.enabled
:
356 val_type
= class_type
.template_argument(0)
357 node_type
= gdb
.lookup_type(str(class_type
) + '::_Node').pointer()
358 return method
.worker_class(val_type
, node_type
)
360 # Xmethods for std::list
363 class ListWorkerBase(gdb
.xmethod
.XMethodWorker
):
364 def __init__(self
, val_type
, node_type
):
365 self
._val
_type
= val_type
366 self
._node
_type
= node_type
368 def get_arg_types(self
):
371 def get_value_from_node(self
, node
):
372 node
= node
.dereference()
373 if node
.type.fields()[1].name
== '_M_data':
374 # C++03 implementation, node contains the value as a member
375 return node
['_M_data']
376 # C++11 implementation, node stores value in __aligned_membuf
377 addr
= node
['_M_storage'].address
378 return addr
.cast(self
._val
_type
.pointer()).dereference()
381 class ListEmptyWorker(ListWorkerBase
):
382 def get_result_type(self
, obj
):
383 return get_bool_type()
385 def __call__(self
, obj
):
386 base_node
= obj
['_M_impl']['_M_node']
387 if base_node
['_M_next'] == base_node
.address
:
393 class ListSizeWorker(ListWorkerBase
):
394 def get_result_type(self
, obj
):
395 return get_std_size_type()
397 def __call__(self
, obj
):
398 begin_node
= obj
['_M_impl']['_M_node']['_M_next']
399 end_node
= obj
['_M_impl']['_M_node'].address
401 while begin_node
!= end_node
:
402 begin_node
= begin_node
['_M_next']
407 class ListFrontWorker(ListWorkerBase
):
408 def get_result_type(self
, obj
):
409 return self
._val
_type
411 def __call__(self
, obj
):
412 node
= obj
['_M_impl']['_M_node']['_M_next'].cast(self
._node
_type
)
413 return self
.get_value_from_node(node
)
416 class ListBackWorker(ListWorkerBase
):
417 def get_result_type(self
, obj
):
418 return self
._val
_type
420 def __call__(self
, obj
):
421 prev_node
= obj
['_M_impl']['_M_node']['_M_prev'].cast(self
._node
_type
)
422 return self
.get_value_from_node(prev_node
)
425 class ListMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
427 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
428 matcher_name_prefix
+ 'list')
429 self
._method
_dict
= {
430 'empty': LibStdCxxXMethod('empty', ListEmptyWorker
),
431 'size': LibStdCxxXMethod('size', ListSizeWorker
),
432 'front': LibStdCxxXMethod('front', ListFrontWorker
),
433 'back': LibStdCxxXMethod('back', ListBackWorker
)
435 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
437 def match(self
, class_type
, method_name
):
438 if not is_specialization_of(class_type
, '(__cxx11::)?list'):
440 method
= self
._method
_dict
.get(method_name
)
441 if method
is None or not method
.enabled
:
443 val_type
= class_type
.template_argument(0)
444 node_type
= gdb
.lookup_type(str(class_type
) + '::_Node').pointer()
445 return method
.worker_class(val_type
, node_type
)
447 # Xmethods for std::vector
450 class VectorWorkerBase(gdb
.xmethod
.XMethodWorker
):
451 def __init__(self
, val_type
):
452 self
._val
_type
= val_type
455 if self
._val
_type
.code
== gdb
.TYPE_CODE_BOOL
:
456 start
= obj
['_M_impl']['_M_start']['_M_p']
457 finish
= obj
['_M_impl']['_M_finish']['_M_p']
458 finish_offset
= obj
['_M_impl']['_M_finish']['_M_offset']
459 bit_size
= start
.dereference().type.sizeof
* 8
460 return (finish
- start
) * bit_size
+ finish_offset
462 return obj
['_M_impl']['_M_finish'] - obj
['_M_impl']['_M_start']
464 def get(self
, obj
, index
):
465 if self
._val
_type
.code
== gdb
.TYPE_CODE_BOOL
:
466 start
= obj
['_M_impl']['_M_start']['_M_p']
467 bit_size
= start
.dereference().type.sizeof
* 8
468 valp
= start
+ index
// bit_size
469 offset
= index
% bit_size
470 return (valp
.dereference() & (1 << offset
)) > 0
472 return obj
['_M_impl']['_M_start'][index
]
475 class VectorEmptyWorker(VectorWorkerBase
):
476 def get_arg_types(self
):
479 def get_result_type(self
, obj
):
480 return get_bool_type()
482 def __call__(self
, obj
):
483 return int(self
.size(obj
)) == 0
486 class VectorSizeWorker(VectorWorkerBase
):
487 def get_arg_types(self
):
490 def get_result_type(self
, obj
):
491 return get_std_size_type()
493 def __call__(self
, obj
):
494 return self
.size(obj
)
497 class VectorFrontWorker(VectorWorkerBase
):
498 def get_arg_types(self
):
501 def get_result_type(self
, obj
):
502 return self
._val
_type
504 def __call__(self
, obj
):
505 return self
.get(obj
, 0)
508 class VectorBackWorker(VectorWorkerBase
):
509 def get_arg_types(self
):
512 def get_result_type(self
, obj
):
513 return self
._val
_type
515 def __call__(self
, obj
):
516 return self
.get(obj
, int(self
.size(obj
)) - 1)
519 class VectorAtWorker(VectorWorkerBase
):
520 def get_arg_types(self
):
521 return get_std_size_type()
523 def get_result_type(self
, obj
, index
):
524 return self
._val
_type
526 def __call__(self
, obj
, index
):
527 size
= int(self
.size(obj
))
528 if int(index
) >= size
:
529 raise IndexError('Vector index "%d" should not be >= %d.' %
530 ((int(index
), size
)))
531 return self
.get(obj
, int(index
))
534 class VectorSubscriptWorker(VectorWorkerBase
):
535 def get_arg_types(self
):
536 return get_std_size_type()
538 def get_result_type(self
, obj
, subscript
):
539 return self
._val
_type
541 def __call__(self
, obj
, subscript
):
542 return self
.get(obj
, int(subscript
))
545 class VectorMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
547 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
548 matcher_name_prefix
+ 'vector')
549 self
._method
_dict
= {
550 'size': LibStdCxxXMethod('size', VectorSizeWorker
),
551 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker
),
552 'front': LibStdCxxXMethod('front', VectorFrontWorker
),
553 'back': LibStdCxxXMethod('back', VectorBackWorker
),
554 'at': LibStdCxxXMethod('at', VectorAtWorker
),
555 'operator[]': LibStdCxxXMethod('operator[]',
556 VectorSubscriptWorker
),
558 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
560 def match(self
, class_type
, method_name
):
561 if not is_specialization_of(class_type
, 'vector'):
563 method
= self
._method
_dict
.get(method_name
)
564 if method
is None or not method
.enabled
:
566 return method
.worker_class(class_type
.template_argument(0))
568 # Xmethods for associative containers
571 class AssociativeContainerWorkerBase(gdb
.xmethod
.XMethodWorker
):
572 def __init__(self
, unordered
):
573 self
._unordered
= unordered
575 def node_count(self
, obj
):
577 return obj
['_M_h']['_M_element_count']
579 return obj
['_M_t']['_M_impl']['_M_node_count']
581 def get_arg_types(self
):
585 class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase
):
586 def get_result_type(self
, obj
):
587 return get_bool_type()
589 def __call__(self
, obj
):
590 return int(self
.node_count(obj
)) == 0
593 class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase
):
594 def get_result_type(self
, obj
):
595 return get_std_size_type()
597 def __call__(self
, obj
):
598 return self
.node_count(obj
)
601 class AssociativeContainerMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
602 def __init__(self
, name
):
603 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
604 matcher_name_prefix
+ name
)
606 self
._method
_dict
= {
607 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker
),
608 'empty': LibStdCxxXMethod('empty',
609 AssociativeContainerEmptyWorker
),
611 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
613 def match(self
, class_type
, method_name
):
614 if not is_specialization_of(class_type
, self
._name
):
616 method
= self
._method
_dict
.get(method_name
)
617 if method
is None or not method
.enabled
:
619 unordered
= 'unordered' in self
._name
620 return method
.worker_class(unordered
)
622 # Xmethods for std::unique_ptr
625 class UniquePtrGetWorker(gdb
.xmethod
.XMethodWorker
):
627 Implement std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->().
630 def __init__(self
, elem_type
):
631 self
._is
_array
= elem_type
.code
== gdb
.TYPE_CODE_ARRAY
633 self
._elem
_type
= elem_type
.target()
635 self
._elem
_type
= elem_type
637 def get_arg_types(self
):
640 def get_result_type(self
, obj
):
641 return self
._elem
_type
.pointer()
643 def _supports(self
, method_name
):
644 # operator-> is not supported for unique_ptr<T[]>
645 return method_name
== 'get' or not self
._is
_array
647 def __call__(self
, obj
):
648 impl_type
= obj
.dereference().type.fields()[0].type.tag
649 # Check for new implementations first:
650 if is_specialization_of(impl_type
, '__uniq_ptr_(data|impl)'):
651 tuple_member
= obj
['_M_t']['_M_t']
652 elif is_specialization_of(impl_type
, 'tuple'):
653 tuple_member
= obj
['_M_t']
656 tuple_impl_type
= tuple_member
.type.fields()[0].type # _Tuple_impl
657 tuple_head_type
= tuple_impl_type
.fields()[1].type # _Head_base
658 head_field
= tuple_head_type
.fields()[0]
659 if head_field
.name
== '_M_head_impl':
660 return tuple_member
.cast(tuple_head_type
)['_M_head_impl']
661 elif head_field
.is_base_class
:
662 return tuple_member
.cast(head_field
.type)
667 class UniquePtrDerefWorker(UniquePtrGetWorker
):
668 """Implement std::unique_ptr<T>::operator*()."""
670 def __init__(self
, elem_type
):
671 UniquePtrGetWorker
.__init
__(self
, elem_type
)
673 def get_result_type(self
, obj
):
674 return self
._elem
_type
676 def _supports(self
, method_name
):
677 # operator* is not supported for unique_ptr<T[]>
678 return not self
._is
_array
680 def __call__(self
, obj
):
681 return UniquePtrGetWorker
.__call
__(self
, obj
).dereference()
684 class UniquePtrSubscriptWorker(UniquePtrGetWorker
):
685 """Implement std::unique_ptr<T>::operator[](size_t)."""
687 def __init__(self
, elem_type
):
688 UniquePtrGetWorker
.__init
__(self
, elem_type
)
690 def get_arg_types(self
):
691 return get_std_size_type()
693 def get_result_type(self
, obj
, index
):
694 return self
._elem
_type
696 def _supports(self
, method_name
):
697 # operator[] is only supported for unique_ptr<T[]>
698 return self
._is
_array
700 def __call__(self
, obj
, index
):
701 return UniquePtrGetWorker
.__call
__(self
, obj
)[index
]
704 class UniquePtrMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
706 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
707 matcher_name_prefix
+ 'unique_ptr')
708 self
._method
_dict
= {
709 'get': LibStdCxxXMethod('get', UniquePtrGetWorker
),
710 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker
),
711 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker
),
712 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker
),
714 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
716 def match(self
, class_type
, method_name
):
717 if not is_specialization_of(class_type
, 'unique_ptr'):
719 method
= self
._method
_dict
.get(method_name
)
720 if method
is None or not method
.enabled
:
722 worker
= method
.worker_class(class_type
.template_argument(0))
723 if worker
._supports
(method_name
):
727 # Xmethods for std::shared_ptr
730 class SharedPtrGetWorker(gdb
.xmethod
.XMethodWorker
):
732 Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->().
735 def __init__(self
, elem_type
):
736 self
._is
_array
= elem_type
.code
== gdb
.TYPE_CODE_ARRAY
738 self
._elem
_type
= elem_type
.target()
740 self
._elem
_type
= elem_type
742 def get_arg_types(self
):
745 def get_result_type(self
, obj
):
746 return self
._elem
_type
.pointer()
748 def _supports(self
, method_name
):
749 # operator-> is not supported for shared_ptr<T[]>
750 return method_name
== 'get' or not self
._is
_array
752 def __call__(self
, obj
):
756 class SharedPtrDerefWorker(SharedPtrGetWorker
):
757 """Implement std::shared_ptr<T>::operator*()."""
759 def __init__(self
, elem_type
):
760 SharedPtrGetWorker
.__init
__(self
, elem_type
)
762 def get_result_type(self
, obj
):
763 return self
._elem
_type
765 def _supports(self
, method_name
):
766 # operator* is not supported for shared_ptr<T[]>
767 return not self
._is
_array
769 def __call__(self
, obj
):
770 return SharedPtrGetWorker
.__call
__(self
, obj
).dereference()
773 class SharedPtrSubscriptWorker(SharedPtrGetWorker
):
774 """Implement std::shared_ptr<T>::operator[](size_t)."""
776 def __init__(self
, elem_type
):
777 SharedPtrGetWorker
.__init
__(self
, elem_type
)
779 def get_arg_types(self
):
780 return get_std_size_type()
782 def get_result_type(self
, obj
, index
):
783 return self
._elem
_type
785 def _supports(self
, method_name
):
786 # operator[] is only supported for shared_ptr<T[]>
787 return self
._is
_array
789 def __call__(self
, obj
, index
):
790 # Check bounds if _elem_type is an array of known bound
791 m
= re
.match(r
'.*\[(\d+)]$', str(self
._elem
_type
))
792 if m
and index
>= int(m
.group(1)):
793 raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' %
794 (self
._elem
_type
, int(index
), int(m
.group(1))))
795 return SharedPtrGetWorker
.__call
__(self
, obj
)[index
]
798 class SharedPtrUseCountWorker(gdb
.xmethod
.XMethodWorker
):
799 """Implement std::shared_ptr<T>::use_count()."""
801 def __init__(self
, elem_type
):
804 def get_arg_types(self
):
807 def get_result_type(self
, obj
):
808 return gdb
.lookup_type('long')
810 def _supports(self
, method_name
):
813 def __call__(self
, obj
):
814 refcounts
= obj
['_M_refcount']['_M_pi']
815 return refcounts
['_M_use_count'] if refcounts
else 0
818 class SharedPtrUniqueWorker(SharedPtrUseCountWorker
):
819 """Implement std::shared_ptr<T>::unique()."""
821 def __init__(self
, elem_type
):
822 SharedPtrUseCountWorker
.__init
__(self
, elem_type
)
824 def get_result_type(self
, obj
):
825 return gdb
.lookup_type('bool')
827 def __call__(self
, obj
):
828 return SharedPtrUseCountWorker
.__call
__(self
, obj
) == 1
831 class SharedPtrMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
833 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
834 matcher_name_prefix
+ 'shared_ptr')
835 self
._method
_dict
= {
836 'get': LibStdCxxXMethod('get', SharedPtrGetWorker
),
837 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker
),
838 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker
),
839 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker
),
840 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker
),
841 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker
),
843 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
845 def match(self
, class_type
, method_name
):
846 if not is_specialization_of(class_type
, 'shared_ptr'):
848 method
= self
._method
_dict
.get(method_name
)
849 if method
is None or not method
.enabled
:
851 worker
= method
.worker_class(class_type
.template_argument(0))
852 if worker
._supports
(method_name
):
857 def register_libstdcxx_xmethods(locus
):
858 gdb
.xmethod
.register_xmethod_matcher(locus
, ArrayMethodsMatcher())
859 gdb
.xmethod
.register_xmethod_matcher(locus
, ForwardListMethodsMatcher())
860 gdb
.xmethod
.register_xmethod_matcher(locus
, DequeMethodsMatcher())
861 gdb
.xmethod
.register_xmethod_matcher(locus
, ListMethodsMatcher())
862 gdb
.xmethod
.register_xmethod_matcher(locus
, VectorMethodsMatcher())
863 gdb
.xmethod
.register_xmethod_matcher(
864 locus
, AssociativeContainerMethodsMatcher('set'))
865 gdb
.xmethod
.register_xmethod_matcher(
866 locus
, AssociativeContainerMethodsMatcher('map'))
867 gdb
.xmethod
.register_xmethod_matcher(
868 locus
, AssociativeContainerMethodsMatcher('multiset'))
869 gdb
.xmethod
.register_xmethod_matcher(
870 locus
, AssociativeContainerMethodsMatcher('multimap'))
871 gdb
.xmethod
.register_xmethod_matcher(
872 locus
, AssociativeContainerMethodsMatcher('unordered_set'))
873 gdb
.xmethod
.register_xmethod_matcher(
874 locus
, AssociativeContainerMethodsMatcher('unordered_map'))
875 gdb
.xmethod
.register_xmethod_matcher(
876 locus
, AssociativeContainerMethodsMatcher('unordered_multiset'))
877 gdb
.xmethod
.register_xmethod_matcher(
878 locus
, AssociativeContainerMethodsMatcher('unordered_multimap'))
879 gdb
.xmethod
.register_xmethod_matcher(locus
, UniquePtrMethodsMatcher())
880 gdb
.xmethod
.register_xmethod_matcher(locus
, SharedPtrMethodsMatcher())