]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/python/libstdcxx/v6/xmethods.py
libstdc++: Format Python code according to PEP8
[thirdparty/gcc.git] / libstdc++-v3 / python / libstdcxx / v6 / xmethods.py
1 # Xmethods for libstdc++.
2
3 # Copyright (C) 2014-2023 Free Software Foundation, Inc.
4
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.
9 #
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.
14 #
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/>.
17
18 import gdb
19 import gdb.xmethod
20 import re
21
22 matcher_name_prefix = 'libstdc++::'
23
24
25 def get_bool_type():
26 return gdb.lookup_type('bool')
27
28
29 def get_std_size_type():
30 return gdb.lookup_type('std::size_t')
31
32
33 class LibStdCxxXMethod(gdb.xmethod.XMethod):
34 def __init__(self, name, worker_class):
35 gdb.xmethod.XMethod.__init__(self, name)
36 self.worker_class = worker_class
37
38 # Xmethods for std::array
39
40
41 class ArrayWorkerBase(gdb.xmethod.XMethodWorker):
42 def __init__(self, val_type, size):
43 self._val_type = val_type
44 self._size = size
45
46 def null_value(self):
47 nullptr = gdb.parse_and_eval('(void *) 0')
48 return nullptr.cast(self._val_type.pointer()).dereference()
49
50
51 class ArraySizeWorker(ArrayWorkerBase):
52 def __init__(self, val_type, size):
53 ArrayWorkerBase.__init__(self, val_type, size)
54
55 def get_arg_types(self):
56 return None
57
58 def get_result_type(self, obj):
59 return get_std_size_type()
60
61 def __call__(self, obj):
62 return self._size
63
64
65 class ArrayEmptyWorker(ArrayWorkerBase):
66 def __init__(self, val_type, size):
67 ArrayWorkerBase.__init__(self, val_type, size)
68
69 def get_arg_types(self):
70 return None
71
72 def get_result_type(self, obj):
73 return get_bool_type()
74
75 def __call__(self, obj):
76 return (int(self._size) == 0)
77
78
79 class ArrayFrontWorker(ArrayWorkerBase):
80 def __init__(self, val_type, size):
81 ArrayWorkerBase.__init__(self, val_type, size)
82
83 def get_arg_types(self):
84 return None
85
86 def get_result_type(self, obj):
87 return self._val_type
88
89 def __call__(self, obj):
90 if int(self._size) > 0:
91 return obj['_M_elems'][0]
92 else:
93 return self.null_value()
94
95
96 class ArrayBackWorker(ArrayWorkerBase):
97 def __init__(self, val_type, size):
98 ArrayWorkerBase.__init__(self, val_type, size)
99
100 def get_arg_types(self):
101 return None
102
103 def get_result_type(self, obj):
104 return self._val_type
105
106 def __call__(self, obj):
107 if int(self._size) > 0:
108 return obj['_M_elems'][self._size - 1]
109 else:
110 return self.null_value()
111
112
113 class ArrayAtWorker(ArrayWorkerBase):
114 def __init__(self, val_type, size):
115 ArrayWorkerBase.__init__(self, val_type, size)
116
117 def get_arg_types(self):
118 return get_std_size_type()
119
120 def get_result_type(self, obj, index):
121 return self._val_type
122
123 def __call__(self, obj, index):
124 if int(index) >= int(self._size):
125 raise IndexError('Array index "%d" should not be >= %d.' %
126 ((int(index), self._size)))
127 return obj['_M_elems'][index]
128
129
130 class ArraySubscriptWorker(ArrayWorkerBase):
131 def __init__(self, val_type, size):
132 ArrayWorkerBase.__init__(self, val_type, size)
133
134 def get_arg_types(self):
135 return get_std_size_type()
136
137 def get_result_type(self, obj, index):
138 return self._val_type
139
140 def __call__(self, obj, index):
141 if int(self._size) > 0:
142 return obj['_M_elems'][index]
143 else:
144 return self.null_value()
145
146
147 class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
148 def __init__(self):
149 gdb.xmethod.XMethodMatcher.__init__(self,
150 matcher_name_prefix + 'array')
151 self._method_dict = {
152 'size': LibStdCxxXMethod('size', ArraySizeWorker),
153 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker),
154 'front': LibStdCxxXMethod('front', ArrayFrontWorker),
155 'back': LibStdCxxXMethod('back', ArrayBackWorker),
156 'at': LibStdCxxXMethod('at', ArrayAtWorker),
157 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker),
158 }
159 self.methods = [self._method_dict[m] for m in self._method_dict]
160
161 def match(self, class_type, method_name):
162 if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
163 return None
164 method = self._method_dict.get(method_name)
165 if method is None or not method.enabled:
166 return None
167 try:
168 value_type = class_type.template_argument(0)
169 size = class_type.template_argument(1)
170 except:
171 return None
172 return method.worker_class(value_type, size)
173
174 # Xmethods for std::deque
175
176
177 class DequeWorkerBase(gdb.xmethod.XMethodWorker):
178 def __init__(self, val_type):
179 self._val_type = val_type
180 self._bufsize = 512 // val_type.sizeof or 1
181
182 def size(self, obj):
183 first_node = obj['_M_impl']['_M_start']['_M_node']
184 last_node = obj['_M_impl']['_M_finish']['_M_node']
185 cur = obj['_M_impl']['_M_finish']['_M_cur']
186 first = obj['_M_impl']['_M_finish']['_M_first']
187 return (last_node - first_node) * self._bufsize + (cur - first)
188
189 def index(self, obj, idx):
190 first_node = obj['_M_impl']['_M_start']['_M_node']
191 index_node = first_node + int(idx) // self._bufsize
192 return index_node[0][idx % self._bufsize]
193
194
195 class DequeEmptyWorker(DequeWorkerBase):
196 def get_arg_types(self):
197 return None
198
199 def get_result_type(self, obj):
200 return get_bool_type()
201
202 def __call__(self, obj):
203 return (obj['_M_impl']['_M_start']['_M_cur'] ==
204 obj['_M_impl']['_M_finish']['_M_cur'])
205
206
207 class DequeSizeWorker(DequeWorkerBase):
208 def get_arg_types(self):
209 return None
210
211 def get_result_type(self, obj):
212 return get_std_size_type()
213
214 def __call__(self, obj):
215 return self.size(obj)
216
217
218 class DequeFrontWorker(DequeWorkerBase):
219 def get_arg_types(self):
220 return None
221
222 def get_result_type(self, obj):
223 return self._val_type
224
225 def __call__(self, obj):
226 return obj['_M_impl']['_M_start']['_M_cur'][0]
227
228
229 class DequeBackWorker(DequeWorkerBase):
230 def get_arg_types(self):
231 return None
232
233 def get_result_type(self, obj):
234 return self._val_type
235
236 def __call__(self, obj):
237 if (obj['_M_impl']['_M_finish']['_M_cur'] ==
238 obj['_M_impl']['_M_finish']['_M_first']):
239 prev_node = obj['_M_impl']['_M_finish']['_M_node'] - 1
240 return prev_node[0][self._bufsize - 1]
241 else:
242 return obj['_M_impl']['_M_finish']['_M_cur'][-1]
243
244
245 class DequeSubscriptWorker(DequeWorkerBase):
246 def get_arg_types(self):
247 return get_std_size_type()
248
249 def get_result_type(self, obj, subscript):
250 return self._val_type
251
252 def __call__(self, obj, subscript):
253 return self.index(obj, subscript)
254
255
256 class DequeAtWorker(DequeWorkerBase):
257 def get_arg_types(self):
258 return get_std_size_type()
259
260 def get_result_type(self, obj, index):
261 return self._val_type
262
263 def __call__(self, obj, index):
264 deque_size = int(self.size(obj))
265 if int(index) >= deque_size:
266 raise IndexError('Deque index "%d" should not be >= %d.' %
267 (int(index), deque_size))
268 else:
269 return self.index(obj, index)
270
271
272 class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
273 def __init__(self):
274 gdb.xmethod.XMethodMatcher.__init__(self,
275 matcher_name_prefix + 'deque')
276 self._method_dict = {
277 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker),
278 'size': LibStdCxxXMethod('size', DequeSizeWorker),
279 'front': LibStdCxxXMethod('front', DequeFrontWorker),
280 'back': LibStdCxxXMethod('back', DequeBackWorker),
281 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker),
282 'at': LibStdCxxXMethod('at', DequeAtWorker)
283 }
284 self.methods = [self._method_dict[m] for m in self._method_dict]
285
286 def match(self, class_type, method_name):
287 if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
288 return None
289 method = self._method_dict.get(method_name)
290 if method is None or not method.enabled:
291 return None
292 return method.worker_class(class_type.template_argument(0))
293
294 # Xmethods for std::forward_list
295
296
297 class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher):
298 def __init__(self, val_type, node_type):
299 self._val_type = val_type
300 self._node_type = node_type
301
302 def get_arg_types(self):
303 return None
304
305
306 class ForwardListEmptyWorker(ForwardListWorkerBase):
307 def get_result_type(self, obj):
308 return get_bool_type()
309
310 def __call__(self, obj):
311 return obj['_M_impl']['_M_head']['_M_next'] == 0
312
313
314 class ForwardListFrontWorker(ForwardListWorkerBase):
315 def get_result_type(self, obj):
316 return self._val_type
317
318 def __call__(self, obj):
319 node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type)
320 val_address = node['_M_storage']['_M_storage'].address
321 return val_address.cast(self._val_type.pointer()).dereference()
322
323
324 class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
325 def __init__(self):
326 matcher_name = matcher_name_prefix + 'forward_list'
327 gdb.xmethod.XMethodMatcher.__init__(self, matcher_name)
328 self._method_dict = {
329 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker),
330 'front': LibStdCxxXMethod('front', ForwardListFrontWorker)
331 }
332 self.methods = [self._method_dict[m] for m in self._method_dict]
333
334 def match(self, class_type, method_name):
335 if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
336 return None
337 method = self._method_dict.get(method_name)
338 if method is None or not method.enabled:
339 return None
340 val_type = class_type.template_argument(0)
341 node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
342 return method.worker_class(val_type, node_type)
343
344 # Xmethods for std::list
345
346
347 class ListWorkerBase(gdb.xmethod.XMethodWorker):
348 def __init__(self, val_type, node_type):
349 self._val_type = val_type
350 self._node_type = node_type
351
352 def get_arg_types(self):
353 return None
354
355 def get_value_from_node(self, node):
356 node = node.dereference()
357 if node.type.fields()[1].name == '_M_data':
358 # C++03 implementation, node contains the value as a member
359 return node['_M_data']
360 # C++11 implementation, node stores value in __aligned_membuf
361 addr = node['_M_storage'].address
362 return addr.cast(self._val_type.pointer()).dereference()
363
364
365 class ListEmptyWorker(ListWorkerBase):
366 def get_result_type(self, obj):
367 return get_bool_type()
368
369 def __call__(self, obj):
370 base_node = obj['_M_impl']['_M_node']
371 if base_node['_M_next'] == base_node.address:
372 return True
373 else:
374 return False
375
376
377 class ListSizeWorker(ListWorkerBase):
378 def get_result_type(self, obj):
379 return get_std_size_type()
380
381 def __call__(self, obj):
382 begin_node = obj['_M_impl']['_M_node']['_M_next']
383 end_node = obj['_M_impl']['_M_node'].address
384 size = 0
385 while begin_node != end_node:
386 begin_node = begin_node['_M_next']
387 size += 1
388 return size
389
390
391 class ListFrontWorker(ListWorkerBase):
392 def get_result_type(self, obj):
393 return self._val_type
394
395 def __call__(self, obj):
396 node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type)
397 return self.get_value_from_node(node)
398
399
400 class ListBackWorker(ListWorkerBase):
401 def get_result_type(self, obj):
402 return self._val_type
403
404 def __call__(self, obj):
405 prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type)
406 return self.get_value_from_node(prev_node)
407
408
409 class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
410 def __init__(self):
411 gdb.xmethod.XMethodMatcher.__init__(self,
412 matcher_name_prefix + 'list')
413 self._method_dict = {
414 'empty': LibStdCxxXMethod('empty', ListEmptyWorker),
415 'size': LibStdCxxXMethod('size', ListSizeWorker),
416 'front': LibStdCxxXMethod('front', ListFrontWorker),
417 'back': LibStdCxxXMethod('back', ListBackWorker)
418 }
419 self.methods = [self._method_dict[m] for m in self._method_dict]
420
421 def match(self, class_type, method_name):
422 if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
423 return None
424 method = self._method_dict.get(method_name)
425 if method is None or not method.enabled:
426 return None
427 val_type = class_type.template_argument(0)
428 node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
429 return method.worker_class(val_type, node_type)
430
431 # Xmethods for std::vector
432
433
434 class VectorWorkerBase(gdb.xmethod.XMethodWorker):
435 def __init__(self, val_type):
436 self._val_type = val_type
437
438 def size(self, obj):
439 if self._val_type.code == gdb.TYPE_CODE_BOOL:
440 start = obj['_M_impl']['_M_start']['_M_p']
441 finish = obj['_M_impl']['_M_finish']['_M_p']
442 finish_offset = obj['_M_impl']['_M_finish']['_M_offset']
443 bit_size = start.dereference().type.sizeof * 8
444 return (finish - start) * bit_size + finish_offset
445 else:
446 return obj['_M_impl']['_M_finish'] - obj['_M_impl']['_M_start']
447
448 def get(self, obj, index):
449 if self._val_type.code == gdb.TYPE_CODE_BOOL:
450 start = obj['_M_impl']['_M_start']['_M_p']
451 bit_size = start.dereference().type.sizeof * 8
452 valp = start + index // bit_size
453 offset = index % bit_size
454 return (valp.dereference() & (1 << offset)) > 0
455 else:
456 return obj['_M_impl']['_M_start'][index]
457
458
459 class VectorEmptyWorker(VectorWorkerBase):
460 def get_arg_types(self):
461 return None
462
463 def get_result_type(self, obj):
464 return get_bool_type()
465
466 def __call__(self, obj):
467 return int(self.size(obj)) == 0
468
469
470 class VectorSizeWorker(VectorWorkerBase):
471 def get_arg_types(self):
472 return None
473
474 def get_result_type(self, obj):
475 return get_std_size_type()
476
477 def __call__(self, obj):
478 return self.size(obj)
479
480
481 class VectorFrontWorker(VectorWorkerBase):
482 def get_arg_types(self):
483 return None
484
485 def get_result_type(self, obj):
486 return self._val_type
487
488 def __call__(self, obj):
489 return self.get(obj, 0)
490
491
492 class VectorBackWorker(VectorWorkerBase):
493 def get_arg_types(self):
494 return None
495
496 def get_result_type(self, obj):
497 return self._val_type
498
499 def __call__(self, obj):
500 return self.get(obj, int(self.size(obj)) - 1)
501
502
503 class VectorAtWorker(VectorWorkerBase):
504 def get_arg_types(self):
505 return get_std_size_type()
506
507 def get_result_type(self, obj, index):
508 return self._val_type
509
510 def __call__(self, obj, index):
511 size = int(self.size(obj))
512 if int(index) >= size:
513 raise IndexError('Vector index "%d" should not be >= %d.' %
514 ((int(index), size)))
515 return self.get(obj, int(index))
516
517
518 class VectorSubscriptWorker(VectorWorkerBase):
519 def get_arg_types(self):
520 return get_std_size_type()
521
522 def get_result_type(self, obj, subscript):
523 return self._val_type
524
525 def __call__(self, obj, subscript):
526 return self.get(obj, int(subscript))
527
528
529 class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
530 def __init__(self):
531 gdb.xmethod.XMethodMatcher.__init__(self,
532 matcher_name_prefix + 'vector')
533 self._method_dict = {
534 'size': LibStdCxxXMethod('size', VectorSizeWorker),
535 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker),
536 'front': LibStdCxxXMethod('front', VectorFrontWorker),
537 'back': LibStdCxxXMethod('back', VectorBackWorker),
538 'at': LibStdCxxXMethod('at', VectorAtWorker),
539 'operator[]': LibStdCxxXMethod('operator[]',
540 VectorSubscriptWorker),
541 }
542 self.methods = [self._method_dict[m] for m in self._method_dict]
543
544 def match(self, class_type, method_name):
545 if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
546 return None
547 method = self._method_dict.get(method_name)
548 if method is None or not method.enabled:
549 return None
550 return method.worker_class(class_type.template_argument(0))
551
552 # Xmethods for associative containers
553
554
555 class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker):
556 def __init__(self, unordered):
557 self._unordered = unordered
558
559 def node_count(self, obj):
560 if self._unordered:
561 return obj['_M_h']['_M_element_count']
562 else:
563 return obj['_M_t']['_M_impl']['_M_node_count']
564
565 def get_arg_types(self):
566 return None
567
568
569 class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase):
570 def get_result_type(self, obj):
571 return get_bool_type()
572
573 def __call__(self, obj):
574 return int(self.node_count(obj)) == 0
575
576
577 class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase):
578 def get_result_type(self, obj):
579 return get_std_size_type()
580
581 def __call__(self, obj):
582 return self.node_count(obj)
583
584
585 class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
586 def __init__(self, name):
587 gdb.xmethod.XMethodMatcher.__init__(self,
588 matcher_name_prefix + name)
589 self._name = name
590 self._method_dict = {
591 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker),
592 'empty': LibStdCxxXMethod('empty',
593 AssociativeContainerEmptyWorker),
594 }
595 self.methods = [self._method_dict[m] for m in self._method_dict]
596
597 def match(self, class_type, method_name):
598 if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
599 return None
600 method = self._method_dict.get(method_name)
601 if method is None or not method.enabled:
602 return None
603 unordered = 'unordered' in self._name
604 return method.worker_class(unordered)
605
606 # Xmethods for std::unique_ptr
607
608
609 class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
610 "Implements std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->()"
611
612 def __init__(self, elem_type):
613 self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY
614 if self._is_array:
615 self._elem_type = elem_type.target()
616 else:
617 self._elem_type = elem_type
618
619 def get_arg_types(self):
620 return None
621
622 def get_result_type(self, obj):
623 return self._elem_type.pointer()
624
625 def _supports(self, method_name):
626 "operator-> is not supported for unique_ptr<T[]>"
627 return method_name == 'get' or not self._is_array
628
629 def __call__(self, obj):
630 impl_type = obj.dereference().type.fields()[0].type.tag
631 # Check for new implementations first:
632 if re.match('^std::(__\d+::)?__uniq_ptr_(data|impl)<.*>$', impl_type):
633 tuple_member = obj['_M_t']['_M_t']
634 elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
635 tuple_member = obj['_M_t']
636 else:
637 return None
638 tuple_impl_type = tuple_member.type.fields()[0].type # _Tuple_impl
639 tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base
640 head_field = tuple_head_type.fields()[0]
641 if head_field.name == '_M_head_impl':
642 return tuple_member.cast(tuple_head_type)['_M_head_impl']
643 elif head_field.is_base_class:
644 return tuple_member.cast(head_field.type)
645 else:
646 return None
647
648
649 class UniquePtrDerefWorker(UniquePtrGetWorker):
650 "Implements std::unique_ptr<T>::operator*()"
651
652 def __init__(self, elem_type):
653 UniquePtrGetWorker.__init__(self, elem_type)
654
655 def get_result_type(self, obj):
656 return self._elem_type
657
658 def _supports(self, method_name):
659 "operator* is not supported for unique_ptr<T[]>"
660 return not self._is_array
661
662 def __call__(self, obj):
663 return UniquePtrGetWorker.__call__(self, obj).dereference()
664
665
666 class UniquePtrSubscriptWorker(UniquePtrGetWorker):
667 "Implements std::unique_ptr<T>::operator[](size_t)"
668
669 def __init__(self, elem_type):
670 UniquePtrGetWorker.__init__(self, elem_type)
671
672 def get_arg_types(self):
673 return get_std_size_type()
674
675 def get_result_type(self, obj, index):
676 return self._elem_type
677
678 def _supports(self, method_name):
679 "operator[] is only supported for unique_ptr<T[]>"
680 return self._is_array
681
682 def __call__(self, obj, index):
683 return UniquePtrGetWorker.__call__(self, obj)[index]
684
685
686 class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
687 def __init__(self):
688 gdb.xmethod.XMethodMatcher.__init__(self,
689 matcher_name_prefix + 'unique_ptr')
690 self._method_dict = {
691 'get': LibStdCxxXMethod('get', UniquePtrGetWorker),
692 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker),
693 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker),
694 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker),
695 }
696 self.methods = [self._method_dict[m] for m in self._method_dict]
697
698 def match(self, class_type, method_name):
699 if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
700 return None
701 method = self._method_dict.get(method_name)
702 if method is None or not method.enabled:
703 return None
704 worker = method.worker_class(class_type.template_argument(0))
705 if worker._supports(method_name):
706 return worker
707 return None
708
709 # Xmethods for std::shared_ptr
710
711
712 class SharedPtrGetWorker(gdb.xmethod.XMethodWorker):
713 "Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->()"
714
715 def __init__(self, elem_type):
716 self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY
717 if self._is_array:
718 self._elem_type = elem_type.target()
719 else:
720 self._elem_type = elem_type
721
722 def get_arg_types(self):
723 return None
724
725 def get_result_type(self, obj):
726 return self._elem_type.pointer()
727
728 def _supports(self, method_name):
729 "operator-> is not supported for shared_ptr<T[]>"
730 return method_name == 'get' or not self._is_array
731
732 def __call__(self, obj):
733 return obj['_M_ptr']
734
735
736 class SharedPtrDerefWorker(SharedPtrGetWorker):
737 "Implements std::shared_ptr<T>::operator*()"
738
739 def __init__(self, elem_type):
740 SharedPtrGetWorker.__init__(self, elem_type)
741
742 def get_result_type(self, obj):
743 return self._elem_type
744
745 def _supports(self, method_name):
746 "operator* is not supported for shared_ptr<T[]>"
747 return not self._is_array
748
749 def __call__(self, obj):
750 return SharedPtrGetWorker.__call__(self, obj).dereference()
751
752
753 class SharedPtrSubscriptWorker(SharedPtrGetWorker):
754 "Implements std::shared_ptr<T>::operator[](size_t)"
755
756 def __init__(self, elem_type):
757 SharedPtrGetWorker.__init__(self, elem_type)
758
759 def get_arg_types(self):
760 return get_std_size_type()
761
762 def get_result_type(self, obj, index):
763 return self._elem_type
764
765 def _supports(self, method_name):
766 "operator[] is only supported for shared_ptr<T[]>"
767 return self._is_array
768
769 def __call__(self, obj, index):
770 # Check bounds if _elem_type is an array of known bound
771 m = re.match('.*\[(\d+)]$', str(self._elem_type))
772 if m and index >= int(m.group(1)):
773 raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' %
774 (self._elem_type, int(index), int(m.group(1))))
775 return SharedPtrGetWorker.__call__(self, obj)[index]
776
777
778 class SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker):
779 "Implements std::shared_ptr<T>::use_count()"
780
781 def __init__(self, elem_type):
782 pass
783
784 def get_arg_types(self):
785 return None
786
787 def get_result_type(self, obj):
788 return gdb.lookup_type('long')
789
790 def _supports(self, method_name):
791 return True
792
793 def __call__(self, obj):
794 refcounts = obj['_M_refcount']['_M_pi']
795 return refcounts['_M_use_count'] if refcounts else 0
796
797
798 class SharedPtrUniqueWorker(SharedPtrUseCountWorker):
799 "Implements std::shared_ptr<T>::unique()"
800
801 def __init__(self, elem_type):
802 SharedPtrUseCountWorker.__init__(self, elem_type)
803
804 def get_result_type(self, obj):
805 return gdb.lookup_type('bool')
806
807 def __call__(self, obj):
808 return SharedPtrUseCountWorker.__call__(self, obj) == 1
809
810
811 class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
812 def __init__(self):
813 gdb.xmethod.XMethodMatcher.__init__(self,
814 matcher_name_prefix + 'shared_ptr')
815 self._method_dict = {
816 'get': LibStdCxxXMethod('get', SharedPtrGetWorker),
817 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker),
818 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker),
819 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker),
820 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker),
821 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker),
822 }
823 self.methods = [self._method_dict[m] for m in self._method_dict]
824
825 def match(self, class_type, method_name):
826 if not re.match('^std::(__\d+::)?shared_ptr<.*>$', class_type.tag):
827 return None
828 method = self._method_dict.get(method_name)
829 if method is None or not method.enabled:
830 return None
831 worker = method.worker_class(class_type.template_argument(0))
832 if worker._supports(method_name):
833 return worker
834 return None
835 \f
836
837 def register_libstdcxx_xmethods(locus):
838 gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher())
839 gdb.xmethod.register_xmethod_matcher(locus, ForwardListMethodsMatcher())
840 gdb.xmethod.register_xmethod_matcher(locus, DequeMethodsMatcher())
841 gdb.xmethod.register_xmethod_matcher(locus, ListMethodsMatcher())
842 gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher())
843 gdb.xmethod.register_xmethod_matcher(
844 locus, AssociativeContainerMethodsMatcher('set'))
845 gdb.xmethod.register_xmethod_matcher(
846 locus, AssociativeContainerMethodsMatcher('map'))
847 gdb.xmethod.register_xmethod_matcher(
848 locus, AssociativeContainerMethodsMatcher('multiset'))
849 gdb.xmethod.register_xmethod_matcher(
850 locus, AssociativeContainerMethodsMatcher('multimap'))
851 gdb.xmethod.register_xmethod_matcher(
852 locus, AssociativeContainerMethodsMatcher('unordered_set'))
853 gdb.xmethod.register_xmethod_matcher(
854 locus, AssociativeContainerMethodsMatcher('unordered_map'))
855 gdb.xmethod.register_xmethod_matcher(
856 locus, AssociativeContainerMethodsMatcher('unordered_multiset'))
857 gdb.xmethod.register_xmethod_matcher(
858 locus, AssociativeContainerMethodsMatcher('unordered_multimap'))
859 gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher())
860 gdb.xmethod.register_xmethod_matcher(locus, SharedPtrMethodsMatcher())