1 # Xmethods for libstdc++.
3 # Copyright (C) 2014-2016 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++::'
25 return gdb
.lookup_type('bool')
27 def get_std_size_type():
28 return gdb
.lookup_type('std::size_t')
30 class LibStdCxxXMethod(gdb
.xmethod
.XMethod
):
31 def __init__(self
, name
, worker_class
):
32 gdb
.xmethod
.XMethod
.__init
__(self
, name
)
33 self
.worker_class
= worker_class
35 # Xmethods for std::array
37 class ArrayWorkerBase(gdb
.xmethod
.XMethodWorker
):
38 def __init__(self
, val_type
, size
):
39 self
._val
_type
= val_type
43 nullptr
= gdb
.parse_and_eval('(void *) 0')
44 return nullptr
.cast(self
._val
_type
.pointer()).dereference()
46 class ArraySizeWorker(ArrayWorkerBase
):
47 def __init__(self
, val_type
, size
):
48 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
50 def get_arg_types(self
):
53 def get_result_type(self
, obj
):
54 return get_std_size_type()
56 def __call__(self
, obj
):
59 class ArrayEmptyWorker(ArrayWorkerBase
):
60 def __init__(self
, val_type
, size
):
61 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
63 def get_arg_types(self
):
66 def get_result_type(self
, obj
):
67 return get_bool_type()
69 def __call__(self
, obj
):
70 return (int(self
._size
) == 0)
72 class ArrayFrontWorker(ArrayWorkerBase
):
73 def __init__(self
, val_type
, size
):
74 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
76 def get_arg_types(self
):
79 def get_result_type(self
, obj
):
82 def __call__(self
, obj
):
83 if int(self
._size
) > 0:
84 return obj
['_M_elems'][0]
86 return self
.null_value()
88 class ArrayBackWorker(ArrayWorkerBase
):
89 def __init__(self
, val_type
, size
):
90 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
92 def get_arg_types(self
):
95 def get_result_type(self
, obj
):
98 def __call__(self
, obj
):
99 if int(self
._size
) > 0:
100 return obj
['_M_elems'][self
._size
- 1]
102 return self
.null_value()
104 class ArrayAtWorker(ArrayWorkerBase
):
105 def __init__(self
, val_type
, size
):
106 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
108 def get_arg_types(self
):
109 return get_std_size_type()
111 def get_result_type(self
, obj
, index
):
112 return self
._val
_type
114 def __call__(self
, obj
, index
):
115 if int(index
) >= int(self
._size
):
116 raise IndexError('Array index "%d" should not be >= %d.' %
117 ((int(index
), self
._size
)))
118 return obj
['_M_elems'][index
]
120 class ArraySubscriptWorker(ArrayWorkerBase
):
121 def __init__(self
, val_type
, size
):
122 ArrayWorkerBase
.__init
__(self
, val_type
, size
)
124 def get_arg_types(self
):
125 return get_std_size_type()
127 def get_result_type(self
, obj
, index
):
128 return self
._val
_type
130 def __call__(self
, obj
, index
):
131 if int(self
._size
) > 0:
132 return obj
['_M_elems'][index
]
134 return self
.null_value()
136 class ArrayMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
138 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
139 matcher_name_prefix
+ 'array')
140 self
._method
_dict
= {
141 'size': LibStdCxxXMethod('size', ArraySizeWorker
),
142 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker
),
143 'front': LibStdCxxXMethod('front', ArrayFrontWorker
),
144 'back': LibStdCxxXMethod('back', ArrayBackWorker
),
145 'at': LibStdCxxXMethod('at', ArrayAtWorker
),
146 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker
),
148 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
150 def match(self
, class_type
, method_name
):
151 if not re
.match('^std::array<.*>$', class_type
.tag
):
153 method
= self
._method
_dict
.get(method_name
)
154 if method
is None or not method
.enabled
:
157 value_type
= class_type
.template_argument(0)
158 size
= class_type
.template_argument(1)
161 return method
.worker_class(value_type
, size
)
163 # Xmethods for std::deque
165 class DequeWorkerBase(gdb
.xmethod
.XMethodWorker
):
166 def __init__(self
, val_type
):
167 self
._val
_type
= val_type
168 self
._bufsize
= 512 // val_type
.sizeof
or 1
171 first_node
= obj
['_M_impl']['_M_start']['_M_node']
172 last_node
= obj
['_M_impl']['_M_finish']['_M_node']
173 cur
= obj
['_M_impl']['_M_finish']['_M_cur']
174 first
= obj
['_M_impl']['_M_finish']['_M_first']
175 return (last_node
- first_node
) * self
._bufsize
+ (cur
- first
)
177 def index(self
, obj
, idx
):
178 first_node
= obj
['_M_impl']['_M_start']['_M_node']
179 index_node
= first_node
+ int(idx
) // self
._bufsize
180 return index_node
[0][idx
% self
._bufsize
]
182 class DequeEmptyWorker(DequeWorkerBase
):
183 def get_arg_types(self
):
186 def get_result_type(self
, obj
):
187 return get_bool_type()
189 def __call__(self
, obj
):
190 return (obj
['_M_impl']['_M_start']['_M_cur'] ==
191 obj
['_M_impl']['_M_finish']['_M_cur'])
193 class DequeSizeWorker(DequeWorkerBase
):
194 def get_arg_types(self
):
197 def get_result_type(self
, obj
):
198 return get_std_size_type()
200 def __call__(self
, obj
):
201 return self
.size(obj
)
203 class DequeFrontWorker(DequeWorkerBase
):
204 def get_arg_types(self
):
207 def get_result_type(self
, obj
):
208 return self
._val
_type
210 def __call__(self
, obj
):
211 return obj
['_M_impl']['_M_start']['_M_cur'][0]
213 class DequeBackWorker(DequeWorkerBase
):
214 def get_arg_types(self
):
217 def get_result_type(self
, obj
):
218 return self
._val
_type
220 def __call__(self
, obj
):
221 if (obj
['_M_impl']['_M_finish']['_M_cur'] ==
222 obj
['_M_impl']['_M_finish']['_M_first']):
223 prev_node
= obj
['_M_impl']['_M_finish']['_M_node'] - 1
224 return prev_node
[0][self
._bufsize
- 1]
226 return obj
['_M_impl']['_M_finish']['_M_cur'][-1]
228 class DequeSubscriptWorker(DequeWorkerBase
):
229 def get_arg_types(self
):
230 return get_std_size_type()
232 def get_result_type(self
, obj
, subscript
):
233 return self
._val
_type
235 def __call__(self
, obj
, subscript
):
236 return self
.index(obj
, subscript
)
238 class DequeAtWorker(DequeWorkerBase
):
239 def get_arg_types(self
):
240 return get_std_size_type()
242 def get_result_type(self
, obj
, index
):
243 return self
._val
_type
245 def __call__(self
, obj
, index
):
246 deque_size
= int(self
.size(obj
))
247 if int(index
) >= deque_size
:
248 raise IndexError('Deque index "%d" should not be >= %d.' %
249 (int(index
), deque_size
))
251 return self
.index(obj
, index
)
253 class DequeMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
255 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
256 matcher_name_prefix
+ 'deque')
257 self
._method
_dict
= {
258 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker
),
259 'size': LibStdCxxXMethod('size', DequeSizeWorker
),
260 'front': LibStdCxxXMethod('front', DequeFrontWorker
),
261 'back': LibStdCxxXMethod('back', DequeBackWorker
),
262 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker
),
263 'at': LibStdCxxXMethod('at', DequeAtWorker
)
265 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
267 def match(self
, class_type
, method_name
):
268 if not re
.match('^std::deque<.*>$', class_type
.tag
):
270 method
= self
._method
_dict
.get(method_name
)
271 if method
is None or not method
.enabled
:
273 return method
.worker_class(class_type
.template_argument(0))
275 # Xmethods for std::forward_list
277 class ForwardListWorkerBase(gdb
.xmethod
.XMethodMatcher
):
278 def __init__(self
, val_type
, node_type
):
279 self
._val
_type
= val_type
280 self
._node
_type
= node_type
282 def get_arg_types(self
):
285 class ForwardListEmptyWorker(ForwardListWorkerBase
):
286 def get_result_type(self
, obj
):
287 return get_bool_type()
289 def __call__(self
, obj
):
290 return obj
['_M_impl']['_M_head']['_M_next'] == 0
292 class ForwardListFrontWorker(ForwardListWorkerBase
):
293 def get_result_type(self
, obj
):
294 return self
._val
_type
296 def __call__(self
, obj
):
297 node
= obj
['_M_impl']['_M_head']['_M_next'].cast(self
._node
_type
)
298 val_address
= node
['_M_storage']['_M_storage'].address
299 return val_address
.cast(self
._val
_type
.pointer()).dereference()
301 class ForwardListMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
303 matcher_name
= matcher_name_prefix
+ 'forward_list'
304 gdb
.xmethod
.XMethodMatcher
.__init
__(self
, matcher_name
)
305 self
._method
_dict
= {
306 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker
),
307 'front': LibStdCxxXMethod('front', ForwardListFrontWorker
)
309 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
311 def match(self
, class_type
, method_name
):
312 if not re
.match('^std::forward_list<.*>$', class_type
.tag
):
314 method
= self
._method
_dict
.get(method_name
)
315 if method
is None or not method
.enabled
:
317 val_type
= class_type
.template_argument(0)
318 node_type
= gdb
.lookup_type(str(class_type
) + '::_Node').pointer()
319 return method
.worker_class(val_type
, node_type
)
321 # Xmethods for std::list
323 class ListWorkerBase(gdb
.xmethod
.XMethodWorker
):
324 def __init__(self
, val_type
, node_type
):
325 self
._val
_type
= val_type
326 self
._node
_type
= node_type
328 def get_arg_types(self
):
331 def get_value_from_node(self
, node
):
332 node
= node
.dereference()
333 if node
.type.fields()[1].name
== '_M_data':
334 # C++03 implementation, node contains the value as a member
335 return node
['_M_data']
336 # C++11 implementation, node stores value in __aligned_membuf
337 addr
= node
['_M_storage'].address
338 return addr
.cast(self
._val
_type
.pointer()).dereference()
340 class ListEmptyWorker(ListWorkerBase
):
341 def get_result_type(self
, obj
):
342 return get_bool_type()
344 def __call__(self
, obj
):
345 base_node
= obj
['_M_impl']['_M_node']
346 if base_node
['_M_next'] == base_node
.address
:
351 class ListSizeWorker(ListWorkerBase
):
352 def get_result_type(self
, obj
):
353 return get_std_size_type()
355 def __call__(self
, obj
):
356 begin_node
= obj
['_M_impl']['_M_node']['_M_next']
357 end_node
= obj
['_M_impl']['_M_node'].address
359 while begin_node
!= end_node
:
360 begin_node
= begin_node
['_M_next']
364 class ListFrontWorker(ListWorkerBase
):
365 def get_result_type(self
, obj
):
366 return self
._val
_type
368 def __call__(self
, obj
):
369 node
= obj
['_M_impl']['_M_node']['_M_next'].cast(self
._node
_type
)
370 return self
.get_value_from_node(node
)
372 class ListBackWorker(ListWorkerBase
):
373 def get_result_type(self
, obj
):
374 return self
._val
_type
376 def __call__(self
, obj
):
377 prev_node
= obj
['_M_impl']['_M_node']['_M_prev'].cast(self
._node
_type
)
378 return self
.get_value_from_node(prev_node
)
380 class ListMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
382 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
383 matcher_name_prefix
+ 'list')
384 self
._method
_dict
= {
385 'empty': LibStdCxxXMethod('empty', ListEmptyWorker
),
386 'size': LibStdCxxXMethod('size', ListSizeWorker
),
387 'front': LibStdCxxXMethod('front', ListFrontWorker
),
388 'back': LibStdCxxXMethod('back', ListBackWorker
)
390 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
392 def match(self
, class_type
, method_name
):
393 if not re
.match('^std::(__cxx11::)?list<.*>$', class_type
.tag
):
395 method
= self
._method
_dict
.get(method_name
)
396 if method
is None or not method
.enabled
:
398 val_type
= class_type
.template_argument(0)
399 node_type
= gdb
.lookup_type(str(class_type
) + '::_Node').pointer()
400 return method
.worker_class(val_type
, node_type
)
402 # Xmethods for std::vector
404 class VectorWorkerBase(gdb
.xmethod
.XMethodWorker
):
405 def __init__(self
, val_type
):
406 self
._val
_type
= val_type
409 if self
._val
_type
.code
== gdb
.TYPE_CODE_BOOL
:
410 start
= obj
['_M_impl']['_M_start']['_M_p']
411 finish
= obj
['_M_impl']['_M_finish']['_M_p']
412 finish_offset
= obj
['_M_impl']['_M_finish']['_M_offset']
413 bit_size
= start
.dereference().type.sizeof
* 8
414 return (finish
- start
) * bit_size
+ finish_offset
416 return obj
['_M_impl']['_M_finish'] - obj
['_M_impl']['_M_start']
418 def get(self
, obj
, index
):
419 if self
._val
_type
.code
== gdb
.TYPE_CODE_BOOL
:
420 start
= obj
['_M_impl']['_M_start']['_M_p']
421 bit_size
= start
.dereference().type.sizeof
* 8
422 valp
= start
+ index
// bit_size
423 offset
= index
% bit_size
424 return (valp
.dereference() & (1 << offset
)) > 0
426 return obj
['_M_impl']['_M_start'][index
]
428 class VectorEmptyWorker(VectorWorkerBase
):
429 def get_arg_types(self
):
432 def get_result_type(self
, obj
):
433 return get_bool_type()
435 def __call__(self
, obj
):
436 return int(self
.size(obj
)) == 0
438 class VectorSizeWorker(VectorWorkerBase
):
439 def get_arg_types(self
):
442 def get_result_type(self
, obj
):
443 return get_std_size_type()
445 def __call__(self
, obj
):
446 return self
.size(obj
)
448 class VectorFrontWorker(VectorWorkerBase
):
449 def get_arg_types(self
):
452 def get_result_type(self
, obj
):
453 return self
._val
_type
455 def __call__(self
, obj
):
456 return self
.get(obj
, 0)
458 class VectorBackWorker(VectorWorkerBase
):
459 def get_arg_types(self
):
462 def get_result_type(self
, obj
):
463 return self
._val
_type
465 def __call__(self
, obj
):
466 return self
.get(obj
, int(self
.size(obj
)) - 1)
468 class VectorAtWorker(VectorWorkerBase
):
469 def get_arg_types(self
):
470 return get_std_size_type()
472 def get_result_type(self
, obj
, index
):
473 return self
._val
_type
475 def __call__(self
, obj
, index
):
476 size
= int(self
.size(obj
))
477 if int(index
) >= size
:
478 raise IndexError('Vector index "%d" should not be >= %d.' %
479 ((int(index
), size
)))
480 return self
.get(obj
, int(index
))
482 class VectorSubscriptWorker(VectorWorkerBase
):
483 def get_arg_types(self
):
484 return get_std_size_type()
486 def get_result_type(self
, obj
, subscript
):
487 return self
._val
_type
489 def __call__(self
, obj
, subscript
):
490 return self
.get(obj
, int(subscript
))
492 class VectorMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
494 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
495 matcher_name_prefix
+ 'vector')
496 self
._method
_dict
= {
497 'size': LibStdCxxXMethod('size', VectorSizeWorker
),
498 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker
),
499 'front': LibStdCxxXMethod('front', VectorFrontWorker
),
500 'back': LibStdCxxXMethod('back', VectorBackWorker
),
501 'at': LibStdCxxXMethod('at', VectorAtWorker
),
502 'operator[]': LibStdCxxXMethod('operator[]',
503 VectorSubscriptWorker
),
505 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
507 def match(self
, class_type
, method_name
):
508 if not re
.match('^std::vector<.*>$', class_type
.tag
):
510 method
= self
._method
_dict
.get(method_name
)
511 if method
is None or not method
.enabled
:
513 return method
.worker_class(class_type
.template_argument(0))
515 # Xmethods for associative containers
517 class AssociativeContainerWorkerBase(gdb
.xmethod
.XMethodWorker
):
518 def __init__(self
, unordered
):
519 self
._unordered
= unordered
521 def node_count(self
, obj
):
523 return obj
['_M_h']['_M_element_count']
525 return obj
['_M_t']['_M_impl']['_M_node_count']
527 def get_arg_types(self
):
530 class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase
):
531 def get_result_type(self
, obj
):
532 return get_bool_type()
534 def __call__(self
, obj
):
535 return int(self
.node_count(obj
)) == 0
537 class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase
):
538 def get_result_type(self
, obj
):
539 return get_std_size_type()
541 def __call__(self
, obj
):
542 return self
.node_count(obj
)
544 class AssociativeContainerMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
545 def __init__(self
, name
):
546 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
547 matcher_name_prefix
+ name
)
549 self
._method
_dict
= {
550 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker
),
551 'empty': LibStdCxxXMethod('empty',
552 AssociativeContainerEmptyWorker
),
554 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
556 def match(self
, class_type
, method_name
):
557 if not re
.match('^std::%s<.*>$' % self
._name
, class_type
.tag
):
559 method
= self
._method
_dict
.get(method_name
)
560 if method
is None or not method
.enabled
:
562 unordered
= 'unordered' in self
._name
563 return method
.worker_class(unordered
)
565 # Xmethods for std::unique_ptr
567 class UniquePtrGetWorker(gdb
.xmethod
.XMethodWorker
):
568 "Implements std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->()"
570 def __init__(self
, elem_type
):
571 self
._is
_array
= elem_type
.code
== gdb
.TYPE_CODE_ARRAY
573 self
._elem
_type
= elem_type
.target()
575 self
._elem
_type
= elem_type
577 def get_arg_types(self
):
580 def get_result_type(self
, obj
):
581 return self
._elem
_type
.pointer()
583 def _supports(self
, method_name
):
584 "operator-> is not supported for unique_ptr<T[]>"
585 return method_name
== 'get' or not self
._is
_array
587 def __call__(self
, obj
):
588 impl_type
= obj
.dereference().type.fields()[0].type.tag
589 if impl_type
.startswith('std::__uniq_ptr_impl<'): # New implementation
590 return obj
['_M_t']['_M_t']['_M_head_impl']
591 elif impl_type
.startswith('std::tuple<'):
592 return obj
['_M_t']['_M_head_impl']
595 class UniquePtrDerefWorker(UniquePtrGetWorker
):
596 "Implements std::unique_ptr<T>::operator*()"
598 def __init__(self
, elem_type
):
599 UniquePtrGetWorker
.__init
__(self
, elem_type
)
601 def get_result_type(self
, obj
):
602 return self
._elem
_type
604 def _supports(self
, method_name
):
605 "operator* is not supported for unique_ptr<T[]>"
606 return not self
._is
_array
608 def __call__(self
, obj
):
609 return UniquePtrGetWorker
.__call
__(self
, obj
).dereference()
611 class UniquePtrSubscriptWorker(UniquePtrGetWorker
):
612 "Implements std::unique_ptr<T>::operator[](size_t)"
614 def __init__(self
, elem_type
):
615 UniquePtrGetWorker
.__init
__(self
, elem_type
)
617 def get_arg_types(self
):
618 return get_std_size_type()
620 def get_result_type(self
, obj
, index
):
621 return self
._elem
_type
623 def _supports(self
, method_name
):
624 "operator[] is only supported for unique_ptr<T[]>"
625 return self
._is
_array
627 def __call__(self
, obj
, index
):
628 return UniquePtrGetWorker
.__call
__(self
, obj
)[index
]
630 class UniquePtrMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
632 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
633 matcher_name_prefix
+ 'unique_ptr')
634 self
._method
_dict
= {
635 'get': LibStdCxxXMethod('get', UniquePtrGetWorker
),
636 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker
),
637 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker
),
638 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker
),
640 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
642 def match(self
, class_type
, method_name
):
643 if not re
.match('^std::unique_ptr<.*>$', class_type
.tag
):
645 method
= self
._method
_dict
.get(method_name
)
646 if method
is None or not method
.enabled
:
648 worker
= method
.worker_class(class_type
.template_argument(0))
649 if worker
._supports
(method_name
):
653 # Xmethods for std::shared_ptr
655 class SharedPtrGetWorker(gdb
.xmethod
.XMethodWorker
):
656 "Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->()"
658 def __init__(self
, elem_type
):
659 self
._is
_array
= elem_type
.code
== gdb
.TYPE_CODE_ARRAY
661 self
._elem
_type
= elem_type
.target()
663 self
._elem
_type
= elem_type
665 def get_arg_types(self
):
668 def get_result_type(self
, obj
):
669 return self
._elem
_type
.pointer()
671 def _supports(self
, method_name
):
672 "operator-> is not supported for shared_ptr<T[]>"
673 return method_name
== 'get' or not self
._is
_array
675 def __call__(self
, obj
):
678 class SharedPtrDerefWorker(SharedPtrGetWorker
):
679 "Implements std::shared_ptr<T>::operator*()"
681 def __init__(self
, elem_type
):
682 SharedPtrGetWorker
.__init
__(self
, elem_type
)
684 def get_result_type(self
, obj
):
685 return self
._elem
_type
687 def _supports(self
, method_name
):
688 "operator* is not supported for shared_ptr<T[]>"
689 return not self
._is
_array
691 def __call__(self
, obj
):
692 return SharedPtrGetWorker
.__call
__(self
, obj
).dereference()
694 class SharedPtrSubscriptWorker(SharedPtrGetWorker
):
695 "Implements std::shared_ptr<T>::operator[](size_t)"
697 def __init__(self
, elem_type
):
698 SharedPtrGetWorker
.__init
__(self
, elem_type
)
700 def get_arg_types(self
):
701 return get_std_size_type()
703 def get_result_type(self
, obj
, index
):
704 return self
._elem
_type
706 def _supports(self
, method_name
):
707 "operator[] is only supported for shared_ptr<T[]>"
708 return self
._is
_array
710 def __call__(self
, obj
, index
):
711 # Check bounds if _elem_type is an array of known bound
712 m
= re
.match('.*\[(\d+)]$', str(self
._elem
_type
))
713 if m
and index
>= int(m
.group(1)):
714 raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' %
715 (self
._elem
_type
, int(index
), int(m
.group(1))))
716 return SharedPtrGetWorker
.__call
__(self
, obj
)[index
]
718 class SharedPtrUseCountWorker(gdb
.xmethod
.XMethodWorker
):
719 "Implements std::shared_ptr<T>::use_count()"
721 def __init__(self
, elem_type
):
722 SharedPtrUseCountWorker
.__init
__(self
, elem_type
)
724 def get_arg_types(self
):
727 def get_result_type(self
, obj
):
728 return gdb
.lookup_type('long')
730 def __call__(self
, obj
):
731 refcounts
= ['_M_refcount']['_M_pi']
732 return refcounts
['_M_use_count'] if refcounts
else 0
734 class SharedPtrUniqueWorker(SharedPtrUseCountWorker
):
735 "Implements std::shared_ptr<T>::unique()"
737 def __init__(self
, elem_type
):
738 SharedPtrUseCountWorker
.__init
__(self
, elem_type
)
740 def get_result_type(self
, obj
):
741 return gdb
.lookup_type('bool')
743 def __call__(self
, obj
):
744 return SharedPtrUseCountWorker
.__call
__(self
, obj
) == 1
746 class SharedPtrMethodsMatcher(gdb
.xmethod
.XMethodMatcher
):
748 gdb
.xmethod
.XMethodMatcher
.__init
__(self
,
749 matcher_name_prefix
+ 'shared_ptr')
750 self
._method
_dict
= {
751 'get': LibStdCxxXMethod('get', SharedPtrGetWorker
),
752 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker
),
753 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker
),
754 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker
),
755 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker
),
756 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker
),
758 self
.methods
= [self
._method
_dict
[m
] for m
in self
._method
_dict
]
760 def match(self
, class_type
, method_name
):
761 if not re
.match('^std::shared_ptr<.*>$', class_type
.tag
):
763 method
= self
._method
_dict
.get(method_name
)
764 if method
is None or not method
.enabled
:
766 worker
= method
.worker_class(class_type
.template_argument(0))
767 if worker
._supports
(method_name
):
771 def register_libstdcxx_xmethods(locus
):
772 gdb
.xmethod
.register_xmethod_matcher(locus
, ArrayMethodsMatcher())
773 gdb
.xmethod
.register_xmethod_matcher(locus
, ForwardListMethodsMatcher())
774 gdb
.xmethod
.register_xmethod_matcher(locus
, DequeMethodsMatcher())
775 gdb
.xmethod
.register_xmethod_matcher(locus
, ListMethodsMatcher())
776 gdb
.xmethod
.register_xmethod_matcher(locus
, VectorMethodsMatcher())
777 gdb
.xmethod
.register_xmethod_matcher(
778 locus
, AssociativeContainerMethodsMatcher('set'))
779 gdb
.xmethod
.register_xmethod_matcher(
780 locus
, AssociativeContainerMethodsMatcher('map'))
781 gdb
.xmethod
.register_xmethod_matcher(
782 locus
, AssociativeContainerMethodsMatcher('multiset'))
783 gdb
.xmethod
.register_xmethod_matcher(
784 locus
, AssociativeContainerMethodsMatcher('multimap'))
785 gdb
.xmethod
.register_xmethod_matcher(
786 locus
, AssociativeContainerMethodsMatcher('unordered_set'))
787 gdb
.xmethod
.register_xmethod_matcher(
788 locus
, AssociativeContainerMethodsMatcher('unordered_map'))
789 gdb
.xmethod
.register_xmethod_matcher(
790 locus
, AssociativeContainerMethodsMatcher('unordered_multiset'))
791 gdb
.xmethod
.register_xmethod_matcher(
792 locus
, AssociativeContainerMethodsMatcher('unordered_multimap'))
793 gdb
.xmethod
.register_xmethod_matcher(locus
, UniquePtrMethodsMatcher())
794 gdb
.xmethod
.register_xmethod_matcher(locus
, SharedPtrMethodsMatcher())