This makes the Xmethods work for unique_ptr<T[]>, including
conditionally enabling operator* and operator-> only for non-arrays,
and enabling operator[] only for arrays. And then adds similar
Xmethods for shared_ptr.

        * 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.

Tested x86_64-linux, committed to trunk.


commit 15de524115a74e9415d6a13378c1cc608d018459
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Thu Dec 15 11:46:15 2016 +0000

    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.

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
 }
 

Reply via email to