Hello, Attached is a patch which adds xmethods for the associative containers (set, map, multiset and multimap) and their unordered versions. I think the GDB Python API is not rich enough to implement xmethods for the more interesting methods like find, count etc. The attached patch only implements xmethods for size and empty. That way, it is a fairly straightforward patch.
libstdc++-v3/ChangeLog: 2014-11-09 Siva Chandra Reddy <sivachan...@google.com> * python/libstdcxx/v6/xmethods.py: Add xmethods for associative containers. * testsuite/libstdc++-xmethods/associative-containers.cc: New file.
diff --git a/libstdc++-v3/python/libstdcxx/v6/xmethods.py b/libstdc++-v3/python/libstdcxx/v6/xmethods.py index 6af1c95..2198411 100644 --- a/libstdc++-v3/python/libstdcxx/v6/xmethods.py +++ b/libstdc++-v3/python/libstdcxx/v6/xmethods.py @@ -422,6 +422,50 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): return None return method.worker_class(class_type.template_argument(0)) +# Xmethods for associative containers + +class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker): + def __init__(self, unordered): + self._unordered = unordered + + def node_count(self, obj): + if self._unordered: + return obj['_M_h']['_M_element_count'] + else: + return obj['_M_t']['_M_impl']['_M_node_count'] + + def get_arg_types(self): + return None + +class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase): + def __call__(self, obj): + return int(self.node_count(obj)) == 0 + +class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase): + def __call__(self, obj): + return self.node_count(obj) + +class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): + def __init__(self, name): + gdb.xmethod.XMethodMatcher.__init__(self, + matcher_name_prefix + name) + self._name = name + self._method_dict = { + 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker), + 'empty': LibStdCxxXMethod('empty', + AssociativeContainerEmptyWorker), + } + self.methods = [self._method_dict[m] for m in self._method_dict] + + def match(self, class_type, method_name): + if not re.match('^std::%s<.*>$' % self._name, class_type.tag): + return None + method = self._method_dict.get(method_name) + if method is None or not method.enabled: + return None + unordered = 'unordered' in self._name + return method.worker_class(unordered) + # Xmethods for std::unique_ptr class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): @@ -465,4 +509,20 @@ def register_libstdcxx_xmethods(locus): gdb.xmethod.register_xmethod_matcher(locus, DequeMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, ListMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher()) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('set')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('map')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('multiset')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('multimap')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('unordered_set')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('unordered_map')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('unordered_multiset')) + gdb.xmethod.register_xmethod_matcher( + locus, AssociativeContainerMethodsMatcher('unordered_multimap')) gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher()) diff --git a/libstdc++-v3/testsuite/libstdc++-xmethods/associative-containers.cc b/libstdc++-v3/testsuite/libstdc++-xmethods/associative-containers.cc new file mode 100644 index 0000000..7949f22 --- /dev/null +++ b/libstdc++-v3/testsuite/libstdc++-xmethods/associative-containers.cc @@ -0,0 +1,79 @@ +// { dg-do run } +// { dg-options "-std=gnu++11 -g -O0" } + +// Copyright (C) 2014 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 <set> +#include <map> +#include <unordered_set> +#include <unordered_map> + +int +main () +{ + std::set<int> s, s1; + std::multiset<int> ms, ms1; + std::unordered_set<int> us, us1; + std::unordered_multiset<int> ums, ums1; + std::map<char, int> m, m1; + std::multimap<char, int> mm, mm1; + std::unordered_map<char, int> um, um1; + std::unordered_multimap<char, int> umm, umm1; + + for (int i = 0; i < 100; i++) + { + s.insert (i % 5); + ms.insert (i % 5); + us.insert (i % 7); + ums.insert (i % 7); + + m.insert(std::pair<char, int> ('a' + i % 5, i)); + mm.insert(std::pair<char, int> ('a' + i % 5, i)); + um.insert(std::pair<char, int> ('a' + i % 7, i)); + umm.insert(std::pair<char, int> ('a' + i % 7, i)); + } + +// { dg-final { note-test s.size() 5 } } +// { dg-final { note-test s.empty() false } } +// { dg-final { note-test s1.empty() true } } +// { dg-final { note-test ms.size() 100 } } +// { dg-final { note-test ms.empty() false } } +// { dg-final { note-test ms1.empty() true } } +// { dg-final { note-test us.size() 7 } } +// { dg-final { note-test us.empty() false } } +// { dg-final { note-test us1.empty() true } } +// { dg-final { note-test ums.size() 100 } } +// { dg-final { note-test ums.empty() false } } +// { dg-final { note-test ums1.empty() true } } +// { dg-final { note-test m.size() 5 } } +// { dg-final { note-test m.empty() false } } +// { dg-final { note-test m1.empty() true } } +// { dg-final { note-test mm.size() 100 } } +// { dg-final { note-test mm.empty() false } } +// { dg-final { note-test mm1.empty() true } } +// { dg-final { note-test um.size() 7 } } +// { dg-final { note-test um.empty() false } } +// { dg-final { note-test um1.empty() true } } +// { dg-final { note-test umm.size() 100 } } +// { dg-final { note-test umm.empty() false } } +// { dg-final { note-test umm1.empty() true } } + + return 0; // Mark SPOT +} + +// { dg-final { gdb-test SPOT {} 1 } }