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
This commit is contained in:
parent
a5aa934d0f
commit
0376e86bfc
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 } }
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue