]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/python/libstdcxx/v6/xmethods.py
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / python / libstdcxx / v6 / xmethods.py
CommitLineData
e96d4167 1# Xmethods for libstdc++.
3ef8d391 2
fbd26352 3# Copyright (C) 2014-2019 Free Software Foundation, Inc.
3ef8d391 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
18import gdb
19import gdb.xmethod
20import re
21
22matcher_name_prefix = 'libstdc++::'
23
d3a75429 24def get_bool_type():
25 return gdb.lookup_type('bool')
26
27def get_std_size_type():
28 return gdb.lookup_type('std::size_t')
29
e96d4167 30class LibStdCxxXMethod(gdb.xmethod.XMethod):
31 def __init__(self, name, worker_class):
32 gdb.xmethod.XMethod.__init__(self, name)
33 self.worker_class = worker_class
34
35# Xmethods for std::array
36
37class ArrayWorkerBase(gdb.xmethod.XMethodWorker):
c8b1b26c 38 def __init__(self, val_type, size):
39 self._val_type = val_type
e96d4167 40 self._size = size
41
42 def null_value(self):
43 nullptr = gdb.parse_and_eval('(void *) 0')
c8b1b26c 44 return nullptr.cast(self._val_type.pointer()).dereference()
e96d4167 45
46class ArraySizeWorker(ArrayWorkerBase):
c8b1b26c 47 def __init__(self, val_type, size):
48 ArrayWorkerBase.__init__(self, val_type, size)
e96d4167 49
50 def get_arg_types(self):
51 return None
52
d3a75429 53 def get_result_type(self, obj):
54 return get_std_size_type()
55
e96d4167 56 def __call__(self, obj):
57 return self._size
58
59class ArrayEmptyWorker(ArrayWorkerBase):
c8b1b26c 60 def __init__(self, val_type, size):
61 ArrayWorkerBase.__init__(self, val_type, size)
e96d4167 62
63 def get_arg_types(self):
64 return None
65
d3a75429 66 def get_result_type(self, obj):
67 return get_bool_type()
68
e96d4167 69 def __call__(self, obj):
70 return (int(self._size) == 0)
71
72class ArrayFrontWorker(ArrayWorkerBase):
c8b1b26c 73 def __init__(self, val_type, size):
74 ArrayWorkerBase.__init__(self, val_type, size)
e96d4167 75
76 def get_arg_types(self):
77 return None
78
d3a75429 79 def get_result_type(self, obj):
80 return self._val_type
81
e96d4167 82 def __call__(self, obj):
83 if int(self._size) > 0:
84 return obj['_M_elems'][0]
85 else:
86 return self.null_value()
87
88class ArrayBackWorker(ArrayWorkerBase):
c8b1b26c 89 def __init__(self, val_type, size):
90 ArrayWorkerBase.__init__(self, val_type, size)
e96d4167 91
92 def get_arg_types(self):
93 return None
94
d3a75429 95 def get_result_type(self, obj):
96 return self._val_type
97
e96d4167 98 def __call__(self, obj):
99 if int(self._size) > 0:
100 return obj['_M_elems'][self._size - 1]
101 else:
102 return self.null_value()
103
104class ArrayAtWorker(ArrayWorkerBase):
c8b1b26c 105 def __init__(self, val_type, size):
106 ArrayWorkerBase.__init__(self, val_type, size)
e96d4167 107
108 def get_arg_types(self):
d3a75429 109 return get_std_size_type()
110
111 def get_result_type(self, obj, index):
112 return self._val_type
e96d4167 113
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]
119
120class ArraySubscriptWorker(ArrayWorkerBase):
c8b1b26c 121 def __init__(self, val_type, size):
122 ArrayWorkerBase.__init__(self, val_type, size)
e96d4167 123
124 def get_arg_types(self):
d3a75429 125 return get_std_size_type()
126
127 def get_result_type(self, obj, index):
128 return self._val_type
e96d4167 129
130 def __call__(self, obj, index):
131 if int(self._size) > 0:
132 return obj['_M_elems'][index]
133 else:
134 return self.null_value()
3ef8d391 135
e96d4167 136class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
3ef8d391 137 def __init__(self):
e96d4167 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),
147 }
148 self.methods = [self._method_dict[m] for m in self._method_dict]
149
150 def match(self, class_type, method_name):
d813c3cd 151 if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
e96d4167 152 return None
153 method = self._method_dict.get(method_name)
154 if method is None or not method.enabled:
155 return None
156 try:
157 value_type = class_type.template_argument(0)
158 size = class_type.template_argument(1)
159 except:
160 return None
161 return method.worker_class(value_type, size)
162
163# Xmethods for std::deque
164
165class DequeWorkerBase(gdb.xmethod.XMethodWorker):
c8b1b26c 166 def __init__(self, val_type):
d3a75429 167 self._val_type = val_type
50c1af91 168 self._bufsize = 512 // val_type.sizeof or 1
e96d4167 169
170 def size(self, obj):
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)
176
8c77b933 177 def index(self, obj, idx):
e96d4167 178 first_node = obj['_M_impl']['_M_start']['_M_node']
50c1af91 179 index_node = first_node + int(idx) // self._bufsize
8c77b933 180 return index_node[0][idx % self._bufsize]
e96d4167 181
182class DequeEmptyWorker(DequeWorkerBase):
183 def get_arg_types(self):
184 return None
185
d3a75429 186 def get_result_type(self, obj):
187 return get_bool_type()
188
e96d4167 189 def __call__(self, obj):
190 return (obj['_M_impl']['_M_start']['_M_cur'] ==
191 obj['_M_impl']['_M_finish']['_M_cur'])
192
193class DequeSizeWorker(DequeWorkerBase):
194 def get_arg_types(self):
195 return None
196
d3a75429 197 def get_result_type(self, obj):
198 return get_std_size_type()
199
e96d4167 200 def __call__(self, obj):
201 return self.size(obj)
202
203class DequeFrontWorker(DequeWorkerBase):
204 def get_arg_types(self):
205 return None
206
d3a75429 207 def get_result_type(self, obj):
208 return self._val_type
209
e96d4167 210 def __call__(self, obj):
211 return obj['_M_impl']['_M_start']['_M_cur'][0]
212
213class DequeBackWorker(DequeWorkerBase):
214 def get_arg_types(self):
215 return None
216
d3a75429 217 def get_result_type(self, obj):
218 return self._val_type
219
e96d4167 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]
225 else:
226 return obj['_M_impl']['_M_finish']['_M_cur'][-1]
227
228class DequeSubscriptWorker(DequeWorkerBase):
229 def get_arg_types(self):
d3a75429 230 return get_std_size_type()
231
232 def get_result_type(self, obj, subscript):
233 return self._val_type
e96d4167 234
235 def __call__(self, obj, subscript):
236 return self.index(obj, subscript)
237
238class DequeAtWorker(DequeWorkerBase):
239 def get_arg_types(self):
d3a75429 240 return get_std_size_type()
241
242 def get_result_type(self, obj, index):
243 return self._val_type
e96d4167 244
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))
250 else:
251 return self.index(obj, index)
252
253class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
254 def __init__(self):
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)
264 }
265 self.methods = [self._method_dict[m] for m in self._method_dict]
266
267 def match(self, class_type, method_name):
d813c3cd 268 if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
e96d4167 269 return None
270 method = self._method_dict.get(method_name)
271 if method is None or not method.enabled:
272 return None
273 return method.worker_class(class_type.template_argument(0))
274
275# Xmethods for std::forward_list
276
277class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher):
c8b1b26c 278 def __init__(self, val_type, node_type):
279 self._val_type = val_type
e96d4167 280 self._node_type = node_type
3ef8d391 281
282 def get_arg_types(self):
283 return None
284
e96d4167 285class ForwardListEmptyWorker(ForwardListWorkerBase):
d3a75429 286 def get_result_type(self, obj):
287 return get_bool_type()
288
e96d4167 289 def __call__(self, obj):
290 return obj['_M_impl']['_M_head']['_M_next'] == 0
291
292class ForwardListFrontWorker(ForwardListWorkerBase):
d3a75429 293 def get_result_type(self, obj):
294 return self._val_type
295
3ef8d391 296 def __call__(self, obj):
e96d4167 297 node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type)
c8b1b26c 298 val_address = node['_M_storage']['_M_storage'].address
299 return val_address.cast(self._val_type.pointer()).dereference()
3ef8d391 300
e96d4167 301class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
3ef8d391 302 def __init__(self):
e96d4167 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)
308 }
309 self.methods = [self._method_dict[m] for m in self._method_dict]
310
311 def match(self, class_type, method_name):
d813c3cd 312 if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
e96d4167 313 return None
314 method = self._method_dict.get(method_name)
315 if method is None or not method.enabled:
316 return None
c8b1b26c 317 val_type = class_type.template_argument(0)
e96d4167 318 node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
c8b1b26c 319 return method.worker_class(val_type, node_type)
e96d4167 320
321# Xmethods for std::list
322
323class ListWorkerBase(gdb.xmethod.XMethodWorker):
d3a75429 324 def __init__(self, val_type, node_type):
325 self._val_type = val_type
e96d4167 326 self._node_type = node_type
327
328 def get_arg_types(self):
329 return None
330
8c77b933 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()
339
e96d4167 340class ListEmptyWorker(ListWorkerBase):
d3a75429 341 def get_result_type(self, obj):
342 return get_bool_type()
343
e96d4167 344 def __call__(self, obj):
345 base_node = obj['_M_impl']['_M_node']
346 if base_node['_M_next'] == base_node.address:
347 return True
348 else:
349 return False
350
351class ListSizeWorker(ListWorkerBase):
d3a75429 352 def get_result_type(self, obj):
353 return get_std_size_type()
354
e96d4167 355 def __call__(self, obj):
356 begin_node = obj['_M_impl']['_M_node']['_M_next']
357 end_node = obj['_M_impl']['_M_node'].address
358 size = 0
359 while begin_node != end_node:
360 begin_node = begin_node['_M_next']
361 size += 1
362 return size
363
364class ListFrontWorker(ListWorkerBase):
d3a75429 365 def get_result_type(self, obj):
366 return self._val_type
367
e96d4167 368 def __call__(self, obj):
369 node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type)
8c77b933 370 return self.get_value_from_node(node)
e96d4167 371
372class ListBackWorker(ListWorkerBase):
d3a75429 373 def get_result_type(self, obj):
374 return self._val_type
375
e96d4167 376 def __call__(self, obj):
377 prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type)
8c77b933 378 return self.get_value_from_node(prev_node)
e96d4167 379
380class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
381 def __init__(self):
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)
389 }
390 self.methods = [self._method_dict[m] for m in self._method_dict]
391
392 def match(self, class_type, method_name):
d813c3cd 393 if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
e96d4167 394 return None
395 method = self._method_dict.get(method_name)
396 if method is None or not method.enabled:
397 return None
d3a75429 398 val_type = class_type.template_argument(0)
e96d4167 399 node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer()
d3a75429 400 return method.worker_class(val_type, node_type)
e96d4167 401
402# Xmethods for std::vector
403
404class VectorWorkerBase(gdb.xmethod.XMethodWorker):
c8b1b26c 405 def __init__(self, val_type):
406 self._val_type = val_type
e96d4167 407
408 def size(self, obj):
c8b1b26c 409 if self._val_type.code == gdb.TYPE_CODE_BOOL:
e96d4167 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
415 else:
416 return obj['_M_impl']['_M_finish'] - obj['_M_impl']['_M_start']
417
418 def get(self, obj, index):
c8b1b26c 419 if self._val_type.code == gdb.TYPE_CODE_BOOL:
e96d4167 420 start = obj['_M_impl']['_M_start']['_M_p']
421 bit_size = start.dereference().type.sizeof * 8
50c1af91 422 valp = start + index // bit_size
e96d4167 423 offset = index % bit_size
424 return (valp.dereference() & (1 << offset)) > 0
425 else:
426 return obj['_M_impl']['_M_start'][index]
427
428class VectorEmptyWorker(VectorWorkerBase):
429 def get_arg_types(self):
430 return None
431
d3a75429 432 def get_result_type(self, obj):
433 return get_bool_type()
434
e96d4167 435 def __call__(self, obj):
436 return int(self.size(obj)) == 0
437
438class VectorSizeWorker(VectorWorkerBase):
439 def get_arg_types(self):
440 return None
441
d3a75429 442 def get_result_type(self, obj):
443 return get_std_size_type()
444
e96d4167 445 def __call__(self, obj):
446 return self.size(obj)
447
448class VectorFrontWorker(VectorWorkerBase):
449 def get_arg_types(self):
450 return None
451
d3a75429 452 def get_result_type(self, obj):
453 return self._val_type
454
e96d4167 455 def __call__(self, obj):
456 return self.get(obj, 0)
457
458class VectorBackWorker(VectorWorkerBase):
459 def get_arg_types(self):
460 return None
3ef8d391 461
d3a75429 462 def get_result_type(self, obj):
463 return self._val_type
464
e96d4167 465 def __call__(self, obj):
466 return self.get(obj, int(self.size(obj)) - 1)
467
468class VectorAtWorker(VectorWorkerBase):
469 def get_arg_types(self):
d3a75429 470 return get_std_size_type()
471
472 def get_result_type(self, obj, index):
473 return self._val_type
e96d4167 474
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))
481
482class VectorSubscriptWorker(VectorWorkerBase):
3ef8d391 483 def get_arg_types(self):
d3a75429 484 return get_std_size_type()
485
486 def get_result_type(self, obj, subscript):
487 return self._val_type
3ef8d391 488
489 def __call__(self, obj, subscript):
e96d4167 490 return self.get(obj, int(subscript))
3ef8d391 491
492class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
493 def __init__(self):
494 gdb.xmethod.XMethodMatcher.__init__(self,
495 matcher_name_prefix + 'vector')
e96d4167 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),
504 }
505 self.methods = [self._method_dict[m] for m in self._method_dict]
3ef8d391 506
507 def match(self, class_type, method_name):
d813c3cd 508 if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
3ef8d391 509 return None
e96d4167 510 method = self._method_dict.get(method_name)
511 if method is None or not method.enabled:
512 return None
513 return method.worker_class(class_type.template_argument(0))
3ef8d391 514
3090ad0a 515# Xmethods for associative containers
516
517class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker):
518 def __init__(self, unordered):
519 self._unordered = unordered
520
521 def node_count(self, obj):
522 if self._unordered:
523 return obj['_M_h']['_M_element_count']
524 else:
525 return obj['_M_t']['_M_impl']['_M_node_count']
526
527 def get_arg_types(self):
528 return None
529
530class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase):
d3a75429 531 def get_result_type(self, obj):
532 return get_bool_type()
533
3090ad0a 534 def __call__(self, obj):
535 return int(self.node_count(obj)) == 0
536
537class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase):
d3a75429 538 def get_result_type(self, obj):
539 return get_std_size_type()
540
3090ad0a 541 def __call__(self, obj):
542 return self.node_count(obj)
543
544class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
545 def __init__(self, name):
546 gdb.xmethod.XMethodMatcher.__init__(self,
547 matcher_name_prefix + name)
548 self._name = name
549 self._method_dict = {
550 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker),
551 'empty': LibStdCxxXMethod('empty',
552 AssociativeContainerEmptyWorker),
553 }
554 self.methods = [self._method_dict[m] for m in self._method_dict]
555
556 def match(self, class_type, method_name):
d813c3cd 557 if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
3090ad0a 558 return None
559 method = self._method_dict.get(method_name)
560 if method is None or not method.enabled:
561 return None
562 unordered = 'unordered' in self._name
563 return method.worker_class(unordered)
564
3ef8d391 565# Xmethods for std::unique_ptr
566
567class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
ac98398d 568 "Implements std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->()"
569
d3a75429 570 def __init__(self, elem_type):
ac98398d 571 self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY
572 if self._is_array:
573 self._elem_type = elem_type.target()
574 else:
575 self._elem_type = elem_type
3ef8d391 576
577 def get_arg_types(self):
578 return None
579
d3a75429 580 def get_result_type(self, obj):
581 return self._elem_type.pointer()
582
ac98398d 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
586
3ef8d391 587 def __call__(self, obj):
bc8a7bf0 588 impl_type = obj.dereference().type.fields()[0].type.tag
d813c3cd 589 if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
bc8a7bf0 590 return obj['_M_t']['_M_t']['_M_head_impl']
d813c3cd 591 elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
bc8a7bf0 592 return obj['_M_t']['_M_head_impl']
593 return None
3ef8d391 594
595class UniquePtrDerefWorker(UniquePtrGetWorker):
ac98398d 596 "Implements std::unique_ptr<T>::operator*()"
597
d3a75429 598 def __init__(self, elem_type):
599 UniquePtrGetWorker.__init__(self, elem_type)
600
601 def get_result_type(self, obj):
602 return self._elem_type
3ef8d391 603
ac98398d 604 def _supports(self, method_name):
605 "operator* is not supported for unique_ptr<T[]>"
606 return not self._is_array
607
3ef8d391 608 def __call__(self, obj):
609 return UniquePtrGetWorker.__call__(self, obj).dereference()
610
ac98398d 611class UniquePtrSubscriptWorker(UniquePtrGetWorker):
612 "Implements std::unique_ptr<T>::operator[](size_t)"
613
614 def __init__(self, elem_type):
615 UniquePtrGetWorker.__init__(self, elem_type)
616
617 def get_arg_types(self):
618 return get_std_size_type()
619
620 def get_result_type(self, obj, index):
621 return self._elem_type
622
623 def _supports(self, method_name):
624 "operator[] is only supported for unique_ptr<T[]>"
625 return self._is_array
626
627 def __call__(self, obj, index):
628 return UniquePtrGetWorker.__call__(self, obj)[index]
629
3ef8d391 630class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
631 def __init__(self):
632 gdb.xmethod.XMethodMatcher.__init__(self,
633 matcher_name_prefix + 'unique_ptr')
d3a75429 634 self._method_dict = {
635 'get': LibStdCxxXMethod('get', UniquePtrGetWorker),
a3c0438d 636 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker),
d3a75429 637 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker),
ac98398d 638 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker),
d3a75429 639 }
640 self.methods = [self._method_dict[m] for m in self._method_dict]
3ef8d391 641
642 def match(self, class_type, method_name):
d813c3cd 643 if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
3ef8d391 644 return None
d3a75429 645 method = self._method_dict.get(method_name)
646 if method is None or not method.enabled:
647 return None
ac98398d 648 worker = method.worker_class(class_type.template_argument(0))
649 if worker._supports(method_name):
650 return worker
651 return None
652
653# Xmethods for std::shared_ptr
654
655class SharedPtrGetWorker(gdb.xmethod.XMethodWorker):
656 "Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->()"
657
658 def __init__(self, elem_type):
659 self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY
660 if self._is_array:
661 self._elem_type = elem_type.target()
662 else:
663 self._elem_type = elem_type
664
665 def get_arg_types(self):
666 return None
667
668 def get_result_type(self, obj):
669 return self._elem_type.pointer()
670
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
674
675 def __call__(self, obj):
676 return obj['_M_ptr']
677
678class SharedPtrDerefWorker(SharedPtrGetWorker):
679 "Implements std::shared_ptr<T>::operator*()"
680
681 def __init__(self, elem_type):
682 SharedPtrGetWorker.__init__(self, elem_type)
683
684 def get_result_type(self, obj):
685 return self._elem_type
686
687 def _supports(self, method_name):
688 "operator* is not supported for shared_ptr<T[]>"
689 return not self._is_array
690
691 def __call__(self, obj):
692 return SharedPtrGetWorker.__call__(self, obj).dereference()
693
694class SharedPtrSubscriptWorker(SharedPtrGetWorker):
695 "Implements std::shared_ptr<T>::operator[](size_t)"
696
697 def __init__(self, elem_type):
698 SharedPtrGetWorker.__init__(self, elem_type)
699
700 def get_arg_types(self):
701 return get_std_size_type()
702
703 def get_result_type(self, obj, index):
704 return self._elem_type
705
706 def _supports(self, method_name):
707 "operator[] is only supported for shared_ptr<T[]>"
708 return self._is_array
709
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]
717
718class SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker):
719 "Implements std::shared_ptr<T>::use_count()"
720
721 def __init__(self, elem_type):
722 SharedPtrUseCountWorker.__init__(self, elem_type)
723
724 def get_arg_types(self):
725 return None
726
727 def get_result_type(self, obj):
728 return gdb.lookup_type('long')
729
730 def __call__(self, obj):
731 refcounts = ['_M_refcount']['_M_pi']
732 return refcounts['_M_use_count'] if refcounts else 0
733
734class SharedPtrUniqueWorker(SharedPtrUseCountWorker):
735 "Implements std::shared_ptr<T>::unique()"
736
737 def __init__(self, elem_type):
738 SharedPtrUseCountWorker.__init__(self, elem_type)
739
740 def get_result_type(self, obj):
741 return gdb.lookup_type('bool')
742
743 def __call__(self, obj):
744 return SharedPtrUseCountWorker.__call__(self, obj) == 1
745
746class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
747 def __init__(self):
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),
757 }
758 self.methods = [self._method_dict[m] for m in self._method_dict]
759
760 def match(self, class_type, method_name):
d813c3cd 761 if not re.match('^std::(__\d+::)?shared_ptr<.*>$', class_type.tag):
ac98398d 762 return None
763 method = self._method_dict.get(method_name)
764 if method is None or not method.enabled:
765 return None
766 worker = method.worker_class(class_type.template_argument(0))
767 if worker._supports(method_name):
768 return worker
769 return None
3ef8d391 770\f
771def register_libstdcxx_xmethods(locus):
e96d4167 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())
3ef8d391 776 gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher())
3090ad0a 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'))
3ef8d391 793 gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher())
ac98398d 794 gdb.xmethod.register_xmethod_matcher(locus, SharedPtrMethodsMatcher())