diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-12-15 12:45:42 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-12-15 12:45:42 +0000 |
commit | 0376e86bfc9cbf1fe7b15be65d4f8e183da6484a (patch) | |
tree | ae1599078d94ec2e2137bc68e7a9105f160f8870 | |
parent | a5aa934d0f22c06e4e2d2316aa6d48bd8a727243 (diff) | |
download | gcc-0376e86bfc9cbf1fe7b15be65d4f8e183da6484a.zip gcc-0376e86bfc9cbf1fe7b15be65d4f8e183da6484a.tar.gz gcc-0376e86bfc9cbf1fe7b15be65d4f8e183da6484a.tar.bz2 |
Add GDB XMethods for shared_ptr and unique_ptr<T[]>
* python/libstdcxx/v6/xmethods.py (UniquePtrGetWorker.__init__): Use
correct element type for unique_ptr<T[]>.
(UniquePtrGetWorker._supports, UniquePtrDerefWorker._supports): New
functions to disable unsupported operators for unique_ptr<T[]>.
(UniquePtrSubscriptWorker): New worker for operator[].
(UniquePtrMethodsMatcher.__init__): Register UniquePtrSubscriptWorker.
(UniquePtrMethodsMatcher.match): Call _supports on the chosen worker.
(SharedPtrGetWorker, SharedPtrDerefWorker, SharedPtrSubscriptWorker)
(SharedPtrUseCountWorker, SharedPtrUniqueWorker): New workers.
(SharedPtrMethodsMatcher): New matcher for shared_ptr.
(register_libstdcxx_xmethods): Register SharedPtrMethodsMatcher.
* testsuite/libstdc++-xmethods/unique_ptr.cc: Test arrays.
* testsuite/libstdc++-xmethods/shared_ptr.cc: New test.
From-SVN: r243688
-rw-r--r-- | libstdc++-v3/ChangeLog | 16 | ||||
-rw-r--r-- | libstdc++-v3/python/libstdcxx/v6/xmethods.py | 162 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/libstdc++-xmethods/shared_ptr.cc | 72 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/libstdc++-xmethods/unique_ptr.cc | 19 |
4 files changed, 261 insertions, 8 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 20af4af..a881ee6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2016-12-15 Jonathan Wakely <jwakely@redhat.com> + + * python/libstdcxx/v6/xmethods.py (UniquePtrGetWorker.__init__): Use + correct element type for unique_ptr<T[]>. + (UniquePtrGetWorker._supports, UniquePtrDerefWorker._supports): New + functions to disable unsupported operators for unique_ptr<T[]>. + (UniquePtrSubscriptWorker): New worker for operator[]. + (UniquePtrMethodsMatcher.__init__): Register UniquePtrSubscriptWorker. + (UniquePtrMethodsMatcher.match): Call _supports on the chosen worker. + (SharedPtrGetWorker, SharedPtrDerefWorker, SharedPtrSubscriptWorker) + (SharedPtrUseCountWorker, SharedPtrUniqueWorker): New workers. + (SharedPtrMethodsMatcher): New matcher for shared_ptr. + (register_libstdcxx_xmethods): Register SharedPtrMethodsMatcher. + * testsuite/libstdc++-xmethods/unique_ptr.cc: Test arrays. + * testsuite/libstdc++-xmethods/shared_ptr.cc: New test. + 2016-12-14 François Dumont <fdumont@gcc.gnu.org> * include/bits/stl_tree.h diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py index 045b661..1c9bf3a 100644 --- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py +++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py @@ -565,8 +565,14 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): # Xmethods for std::unique_ptr class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): + "Implements std::unique_ptr<T>::get() and std::unique_ptr<T>::operator->()" + def __init__(self, elem_type): - self._elem_type = elem_type + self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY + if self._is_array: + self._elem_type = elem_type.target() + else: + self._elem_type = elem_type def get_arg_types(self): return None @@ -574,6 +580,10 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): def get_result_type(self, obj): return self._elem_type.pointer() + def _supports(self, method_name): + "operator-> is not supported for unique_ptr<T[]>" + return method_name == 'get' or not self._is_array + def __call__(self, obj): impl_type = obj.dereference().type.fields()[0].type.tag if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation @@ -583,15 +593,40 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): return None class UniquePtrDerefWorker(UniquePtrGetWorker): + "Implements std::unique_ptr<T>::operator*()" + def __init__(self, elem_type): UniquePtrGetWorker.__init__(self, elem_type) def get_result_type(self, obj): return self._elem_type + def _supports(self, method_name): + "operator* is not supported for unique_ptr<T[]>" + return not self._is_array + def __call__(self, obj): return UniquePtrGetWorker.__call__(self, obj).dereference() +class UniquePtrSubscriptWorker(UniquePtrGetWorker): + "Implements std::unique_ptr<T>::operator[](size_t)" + + def __init__(self, elem_type): + UniquePtrGetWorker.__init__(self, elem_type) + + def get_arg_types(self): + return get_std_size_type() + + def get_result_type(self, obj, index): + return self._elem_type + + def _supports(self, method_name): + "operator[] is only supported for unique_ptr<T[]>" + return self._is_array + + def __call__(self, obj, index): + return UniquePtrGetWorker.__call__(self, obj)[index] + class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, @@ -600,6 +635,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): 'get': LibStdCxxXMethod('get', UniquePtrGetWorker), 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker), 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker), + 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker), } self.methods = [self._method_dict[m] for m in self._method_dict] @@ -609,7 +645,128 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): method = self._method_dict.get(method_name) if method is None or not method.enabled: return None - return method.worker_class(class_type.template_argument(0)) + worker = method.worker_class(class_type.template_argument(0)) + if worker._supports(method_name): + return worker + return None + +# Xmethods for std::shared_ptr + +class SharedPtrGetWorker(gdb.xmethod.XMethodWorker): + "Implements std::shared_ptr<T>::get() and std::shared_ptr<T>::operator->()" + + def __init__(self, elem_type): + self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY + if self._is_array: + self._elem_type = elem_type.target() + else: + self._elem_type = elem_type + + def get_arg_types(self): + return None + + def get_result_type(self, obj): + return self._elem_type.pointer() + + def _supports(self, method_name): + "operator-> is not supported for shared_ptr<T[]>" + return method_name == 'get' or not self._is_array + + def __call__(self, obj): + return obj['_M_ptr'] + +class SharedPtrDerefWorker(SharedPtrGetWorker): + "Implements std::shared_ptr<T>::operator*()" + + def __init__(self, elem_type): + SharedPtrGetWorker.__init__(self, elem_type) + + def get_result_type(self, obj): + return self._elem_type + + def _supports(self, method_name): + "operator* is not supported for shared_ptr<T[]>" + return not self._is_array + + def __call__(self, obj): + return SharedPtrGetWorker.__call__(self, obj).dereference() + +class SharedPtrSubscriptWorker(SharedPtrGetWorker): + "Implements std::shared_ptr<T>::operator[](size_t)" + + def __init__(self, elem_type): + SharedPtrGetWorker.__init__(self, elem_type) + + def get_arg_types(self): + return get_std_size_type() + + def get_result_type(self, obj, index): + return self._elem_type + + def _supports(self, method_name): + "operator[] is only supported for shared_ptr<T[]>" + return self._is_array + + def __call__(self, obj, index): + # Check bounds if _elem_type is an array of known bound + m = re.match('.*\[(\d+)]$', str(self._elem_type)) + if m and index >= int(m.group(1)): + raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' % + (self._elem_type, int(index), int(m.group(1)))) + return SharedPtrGetWorker.__call__(self, obj)[index] + +class SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker): + "Implements std::shared_ptr<T>::use_count()" + + def __init__(self, elem_type): + SharedPtrUseCountWorker.__init__(self, elem_type) + + def get_arg_types(self): + return None + + def get_result_type(self, obj): + return gdb.lookup_type('long') + + def __call__(self, obj): + refcounts = ['_M_refcount']['_M_pi'] + return refcounts['_M_use_count'] if refcounts else 0 + +class SharedPtrUniqueWorker(SharedPtrUseCountWorker): + "Implements std::shared_ptr<T>::unique()" + + def __init__(self, elem_type): + SharedPtrUseCountWorker.__init__(self, elem_type) + + def get_result_type(self, obj): + return gdb.lookup_type('bool') + + def __call__(self, obj): + return SharedPtrUseCountWorker.__call__(self, obj) == 1 + +class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher): + def __init__(self): + gdb.xmethod.XMethodMatcher.__init__(self, + matcher_name_prefix + 'shared_ptr') + self._method_dict = { + 'get': LibStdCxxXMethod('get', SharedPtrGetWorker), + 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker), + 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker), + 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker), + 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker), + 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker), + } + self.methods = [self._method_dict[m] for m in self._method_dict] + + def match(self, class_type, method_name): + if not re.match('^std::shared_ptr<.*>$', class_type.tag): + return None + method = self._method_dict.get(method_name) + if method is None or not method.enabled: + return None + worker = method.worker_class(class_type.template_argument(0)) + if worker._supports(method_name): + return worker + return None def register_libstdcxx_xmethods(locus): gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher()) @@ -634,3 +791,4 @@ def register_libstdcxx_xmethods(locus): gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('unordered_multimap')) gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher()) + gdb.xmethod.register_xmethod_matcher(locus, SharedPtrMethodsMatcher()) diff --git a/libstdc++-v3/testsuite/libstdc++-xmethods/shared_ptr.cc b/libstdc++-v3/testsuite/libstdc++-xmethods/shared_ptr.cc new file mode 100644 index 0000000..c90dd01 --- /dev/null +++ b/libstdc++-v3/testsuite/libstdc++-xmethods/shared_ptr.cc @@ -0,0 +1,72 @@ +// { dg-do run { target c++11 } } +// { dg-options "-g -O0" } + +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <memory> + +struct x_struct +{ + int y; +}; + +int +main () +{ + std::shared_ptr<int> p(new int(10)); + + std::shared_ptr<x_struct> q(new x_struct{23}); + + std::shared_ptr<x_struct[]> r(new x_struct[2]{ {46}, {69} }); + + std::shared_ptr<x_struct[3]> s(new x_struct[2]{ {92}, {115} }); + +// { dg-final { note-test *p 10 } } +// { dg-final { regexp-test p.get() 0x.* } } + +// { dg-final { whatis-test *p int } } +// { dg-final { whatis-test p.get() "int \*" } } + +// { dg-final { note-test *q {\{y = 23\}} } } +// { dg-final { regexp-test q.get() 0x.* } } +// { dg-final { note-test q->y 23 } } + +// { dg-final { whatis-test *q x_struct } } +// { dg-final { whatis-test q.get() "x_struct \*" } } +// { dg-final { whatis-test q->y int } } + +// { dg-final { note-test r\[1] {\{y = 69\}} } } +// { dg-final { regexp-test r.get() 0x.* } } +// { dg-final { note-test r\[1].y 69 } } + +// { dg-final { whatis-test r\[1] x_struct } } +// { dg-final { whatis-test r.get() "x_struct \*" } } +// { dg-final { whatis-test r\[1].y int } } + +// { dg-final { note-test s\[1] {\{y = 115\}} } } +// { dg-final { regexp-test s.get() 0x.* } } +// { dg-final { note-test s\[1].y 115 } } + +// { dg-final { whatis-test s\[1] x_struct } } +// { dg-final { whatis-test s.get() "x_struct \*" } } +// { dg-final { whatis-test s\[1].y int } } + + return 0; // Mark SPOT +} + +// { dg-final { gdb-test SPOT {} 1 } } diff --git a/libstdc++-v3/testsuite/libstdc++-xmethods/unique_ptr.cc b/libstdc++-v3/testsuite/libstdc++-xmethods/unique_ptr.cc index bb303a2..5559e27 100644 --- a/libstdc++-v3/testsuite/libstdc++-xmethods/unique_ptr.cc +++ b/libstdc++-v3/testsuite/libstdc++-xmethods/unique_ptr.cc @@ -28,13 +28,11 @@ struct x_struct int main () { - int *i = new int; - *i = 10; - std::unique_ptr<int> p(i); + std::unique_ptr<int> p(new int(10)); - x_struct *x = new x_struct; - x->y = 23; - std::unique_ptr<x_struct> q(x); + std::unique_ptr<x_struct> q(new x_struct{23}); + + std::unique_ptr<x_struct[]> r(new x_struct[2]{ {46}, {69} }); // { dg-final { note-test *p 10 } } // { dg-final { regexp-test p.get() 0x.* } } @@ -50,6 +48,15 @@ main () // { dg-final { whatis-test q.get() "x_struct \*" } } // { dg-final { whatis-test q->y int } } +// { dg-final { note-test r\[1] {\{y = 69\}} } } +// { dg-final { regexp-test r.get() 0x.* } } +// { dg-final { note-test r\[1].y 69 } } + +// { dg-final { whatis-test r\[1] x_struct } } +// { dg-final { whatis-test r.get() "x_struct \*" } } +// { dg-final { whatis-test r\[1].y int } } + + return 0; // Mark SPOT } |