@@ -36,6 +36,8 @@ import sys
# We probably can't do much about this until this GDB PR is addressed:
# <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
+vers_nsp = '__7::'
+
if sys.version_info[0] > 2:
### Python 3 stuff
Iterator = object
@@ -100,11 +102,15 @@ def find_type(orig, name):
raise ValueError("Cannot find type %s::%s" % (str(orig), name))
typ = field.type
+# Test if a type is a given template instantiation.
+def is_specialization_of(type, template_name):
+ return re.match('^std::(%s)?%s<.*>$' % (vers_nsp, template_name), type) is not None
+
class SharedPointerPrinter:
"Print a shared_ptr or weak_ptr"
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def to_string (self):
@@ -127,9 +133,9 @@ class UniquePointerPrinter:
def to_string (self):
impl_type = self.val.type.fields()[0].type.tag
- if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+ if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation
v = self.val['_M_t']['_M_t']['_M_head_impl']
- elif impl_type.startswith('std::tuple<'):
+ elif is_specialization_of(impl_type, 'tuple'):
v = self.val['_M_t']['_M_head_impl']
else:
raise ValueError("Unsupported implementation for unique_ptr: %s" % self.val.type.fields()[0].type.tag)
@@ -179,7 +185,7 @@ class StdListPrinter:
return ('[%d]' % count, val)
def __init__(self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def children(self):
@@ -299,7 +305,7 @@ class StdVectorPrinter:
return ('[%d]' % count, elt)
def __init__(self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL
@@ -403,7 +409,7 @@ class StdTuplePrinter:
return ('[%d]' % self.count, impl['_M_head_impl'])
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val;
def children (self):
@@ -418,7 +424,7 @@ class StdStackOrQueuePrinter:
"Print a std::stack or std::queue"
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.visualizer = gdb.default_visualizer(val['c'])
def children (self):
@@ -496,7 +502,10 @@ class StdRbtreeIteratorPrinter:
def __init__ (self, typename, val):
self.val = val
valtype = self.val.type.template_argument(0).strip_typedefs()
- nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+ if typename.startswith('std::' + vers_nsp):
+ nodetype = gdb.lookup_type('std::' + vers_nsp + '_Rb_tree_node<' + str(valtype) + '>')
+ else:
+ nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
self.link_type = nodetype.strip_typedefs().pointer()
def to_string (self):
@@ -552,7 +561,7 @@ class StdMapPrinter:
return result
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def to_string (self):
@@ -592,7 +601,7 @@ class StdSetPrinter:
return result
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def to_string (self):
@@ -609,7 +618,7 @@ class StdBitsetPrinter:
"Print a std::bitset"
def __init__(self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def to_string (self):
@@ -679,7 +688,7 @@ class StdDequePrinter:
return result
def __init__(self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
self.elttype = val.type.template_argument(0)
size = self.elttype.sizeof
@@ -805,7 +814,7 @@ class Tr1UnorderedSetPrinter:
"Print a tr1::unordered_set"
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def hashtable (self):
@@ -831,7 +840,7 @@ class Tr1UnorderedMapPrinter:
"Print a tr1::unordered_map"
def __init__ (self, typename, val):
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
self.val = val
def hashtable (self):
@@ -897,7 +906,7 @@ class StdForwardListPrinter:
def __init__(self, typename, val):
self.val = val
- self.typename = typename
+ self.typename = typename.replace(vers_nsp, '')
def children(self):
nodetype = find_type(self.val.type, '_Node')
@@ -952,12 +961,11 @@ class SingleObjContainerPrinter(object):
return self.visualizer.display_hint ()
return self.hint
-
class StdExpAnyPrinter(SingleObjContainerPrinter):
"Print a std::any or std::experimental::any"
def __init__ (self, typename, val):
- self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1)
+ self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', typename, 1).replace(vers_nsp, '')
self.val = val
self.contained_type = None
contained_value = None
@@ -972,8 +980,11 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
if not m:
raise ValueError("Unknown manager function in %s" % self.typename)
+ mgrname = m.group(1)
# FIXME need to expand 'std::string' so that gdb.lookup_type works
- mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
+ if 'std::string' in mgrname:
+ mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
+
mgrtype = gdb.lookup_type(mgrname)
self.contained_type = mgrtype.template_argument(0)
valptr = None
@@ -994,14 +1005,14 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
if hasattr (self.visualizer, 'children'):
return desc + self.visualizer.to_string ()
valtype = self._recognize (self.contained_type)
- return desc + valtype
+ return desc + str(valtype).replace(vers_nsp, '')
class StdExpOptionalPrinter(SingleObjContainerPrinter):
"Print a std::optional or std::experimental::optional"
def __init__ (self, typename, val):
valtype = self._recognize (val.type.template_argument(0))
- self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1)
+ self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, typename, 1).replace(vers_nsp, '')
self.val = val
contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
visualizer = gdb.default_visualizer (val['_M_payload'])
@@ -1021,6 +1032,7 @@ class StdVariantPrinter(SingleObjContainerPrinter):
def __init__(self, typename, val):
alternatives = self._template_args(val)
self.typename = "%s<%s>" % (typename, ', '.join([self._recognize(alt) for alt in alternatives]))
+ self.typename = self.typename.replace(vers_nsp, '')
self.index = val['_M_index']
if self.index >= len(alternatives):
self.contained_type = None
@@ -1058,7 +1070,7 @@ class StdNodeHandlePrinter(SingleObjContainerPrinter):
def __init__(self, typename, val):
self.value_type = val.type.template_argument(1)
nodetype = val.type.template_argument(2).template_argument(0)
- self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
+ self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node')
self.is_map_node = val.type.template_argument(0) != self.value_type
nodeptr = val['_M_ptr']
if nodeptr:
@@ -1202,7 +1214,7 @@ class Printer(object):
# Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
def add_version(self, base, name, function):
self.add(base + name, function)
- self.add(base + '__7::' + name, function)
+ self.add(base + vers_nsp + name, function)
# Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
def add_container(self, base, name, function):
@@ -1322,7 +1334,7 @@ class FilteringTypePrinter(object):
except:
pass
if self.type_obj == type_obj:
- return self.name
+ return self.name.replace(vers_nsp, '')
return None
def instantiate(self):
@@ -1331,6 +1343,8 @@ class FilteringTypePrinter(object):
def add_one_type_printer(obj, match, name):
printer = FilteringTypePrinter(match, 'std::' + name)
gdb.types.register_type_printer(obj, printer)
+ printer = FilteringTypePrinter(match, 'std::' + vers_nsp + name)
+ gdb.types.register_type_printer(obj, printer)
def register_type_printers(obj):
global _use_type_printing
@@ -1372,9 +1386,9 @@ def register_type_printers(obj):
# Note that we can't have a printer for std::wstreampos, because
# it shares the same underlying type as std::streampos.
add_one_type_printer(obj, 'fpos', 'streampos')
+
add_one_type_printer(obj, 'basic_string', 'u16string')
add_one_type_printer(obj, 'basic_string', 'u32string')
-
add_one_type_printer(obj, 'basic_string_view', 'u16string_view')
add_one_type_printer(obj, 'basic_string_view', 'u32string_view')
@@ -1392,47 +1406,54 @@ def register_type_printers(obj):
add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
+ # Consider optional versioned namespace
+ opt_nsp = '(' + vers_nsp + ')?'
+
# Do not show defaulted template arguments in class templates
add_one_template_type_printer(obj, 'unique_ptr<T>',
- 'unique_ptr<(.*), std::default_delete<\\1 ?> >',
- 'unique_ptr<{1}>')
+ '{0}unique_ptr<(.*), std::{0}default_delete<\\2 ?> >'.format(opt_nsp),
+ 'unique_ptr<{2}>')
+
+ add_one_template_type_printer(obj, 'basic_string<T>',
+ '{0}basic_string<((un)?signed char), std::{0}char_traits<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'basic_string<{2}>')
add_one_template_type_printer(obj, 'deque<T>',
- 'deque<(.*), std::allocator<\\1 ?> >',
- 'deque<{1}>')
+ '{0}deque<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'deque<{2}>')
add_one_template_type_printer(obj, 'forward_list<T>',
- 'forward_list<(.*), std::allocator<\\1 ?> >',
- 'forward_list<{1}>')
+ '{0}forward_list<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'forward_list<{2}>')
add_one_template_type_printer(obj, 'list<T>',
- 'list<(.*), std::allocator<\\1 ?> >',
- 'list<{1}>')
+ '{0}list<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'list<{2}>')
add_one_template_type_printer(obj, 'vector<T>',
- 'vector<(.*), std::allocator<\\1 ?> >',
- 'vector<{1}>')
+ '{0}vector<(.*), std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'vector<{2}>')
add_one_template_type_printer(obj, 'map<Key, T>',
- 'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
- 'map<{1}, {2}>')
+ '{0}map<(.*), (.*), std::{0}less<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+ 'map<{2}, {3}>')
add_one_template_type_printer(obj, 'multimap<Key, T>',
- 'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
- 'multimap<{1}, {2}>')
+ '{0}multimap<(.*), (.*), std::{0}less<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+ 'multimap<{2}, {3}>')
add_one_template_type_printer(obj, 'set<T>',
- 'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
- 'set<{1}>')
+ '{0}set<(.*), std::{0}less<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'set<{2}>')
add_one_template_type_printer(obj, 'multiset<T>',
- 'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
- 'multiset<{1}>')
+ '{0}multiset<(.*), std::{0}less<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'multiset<{2}>')
add_one_template_type_printer(obj, 'unordered_map<Key, T>',
- 'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
- 'unordered_map<{1}, {2}>')
+ '{0}unordered_map<(.*), (.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+ 'unordered_map<{2}, {3}>')
add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
- 'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
- 'unordered_multimap<{1}, {2}>')
+ '{0}unordered_multimap<(.*), (.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<std::{0}pair<\\2 const, \\3 ?> > >'.format(opt_nsp),
+ 'unordered_multimap<{2}, {3}>')
add_one_template_type_printer(obj, 'unordered_set<T>',
- 'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
- 'unordered_set<{1}>')
+ '{0}unordered_set<(.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'unordered_set<{2}>')
add_one_template_type_printer(obj, 'unordered_multiset<T>',
- 'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
- 'unordered_multiset<{1}>')
+ '{0}unordered_multiset<(.*), std::{0}hash<\\2 ?>, std::{0}equal_to<\\2 ?>, std::{0}allocator<\\2 ?> >'.format(opt_nsp),
+ 'unordered_multiset<{2}>')
# strip the "fundamentals_v1" inline namespace from these types
add_one_template_type_printer(obj, 'any<T>',
@@ -1466,7 +1487,7 @@ def build_libstdcxx_dictionary ():
libstdcxx_printer = Printer("libstdc++-v6")
# For _GLIBCXX_BEGIN_NAMESPACE_VERSION.
- vers = '(__7::)?'
+ vers = '(' + vers_nsp + ')?'
# For _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
container = '(__cxx1998::' + vers + ')?'
@@ -148,7 +148,7 @@ class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher):
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
- if not re.match('^std::array<.*>$', class_type.tag):
+ if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -265,7 +265,7 @@ class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher):
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
- if not re.match('^std::deque<.*>$', class_type.tag):
+ if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -309,7 +309,7 @@ class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher):
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
- if not re.match('^std::forward_list<.*>$', class_type.tag):
+ if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -390,7 +390,7 @@ class ListMethodsMatcher(gdb.xmethod.XMethodMatcher):
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
- if not re.match('^std::(__cxx11::)?list<.*>$', class_type.tag):
+ if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -505,7 +505,7 @@ class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher):
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
- if not re.match('^std::vector<.*>$', class_type.tag):
+ if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -554,7 +554,7 @@ class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher):
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):
+ if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -586,9 +586,9 @@ class UniquePtrGetWorker(gdb.xmethod.XMethodWorker):
def __call__(self, obj):
impl_type = obj.dereference().type.fields()[0].type.tag
- if impl_type.startswith('std::__uniq_ptr_impl<'): # New implementation
+ if re.match('^std::(__\d+::)?__uniq_ptr_impl<.*>$', impl_type): # New implementation
return obj['_M_t']['_M_t']['_M_head_impl']
- elif impl_type.startswith('std::tuple<'):
+ elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type):
return obj['_M_t']['_M_head_impl']
return None
@@ -640,7 +640,7 @@ class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher):
self.methods = [self._method_dict[m] for m in self._method_dict]
def match(self, class_type, method_name):
- if not re.match('^std::unique_ptr<.*>$', class_type.tag):
+ if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag):
return None
method = self._method_dict.get(method_name)
if method is None or not method.enabled:
@@ -26,10 +26,10 @@ int
main()
{
std::tuple<> t1;
-// { dg-final { regexp-test t1 {empty std::(__7::)?tuple} } }
+// { dg-final { regexp-test t1 {empty std::tuple} } }
std::tuple<std::string, int, std::tuple<>> t2{ "Johnny", 5, {} };
-// { dg-final { regexp-test t2 {std::(__7::)?tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::(__7::)?tuple, <No data fields>}}} } }
+// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {<std::(__7::)?tuple<>> = empty std::tuple, <No data fields>}}} } }
std::cout << "\n";
return 0; // Mark SPOT
@@ -166,11 +166,11 @@ holder<std::knuth_b> knuth_b_holder;
ustring *ustring_ptr;
holder<ustring> ustring_holder;
-// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> > >" } }
+// { dg-final { whatis-test ustring_holder "holder<std::basic_string<unsigned char> >" } }
std::basic_string<signed char> *sstring_ptr;
holder< std::basic_string<signed char> > sstring_holder;
-// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
+// { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char> >" } }
std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;