Commit bab0a26d by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/80276 fix template argument handling in type printers

	PR libstdc++/80276
	* python/libstdcxx/v6/printers.py (strip_inline_namespaces): New.
	(get_template_arg_list): New.
	(StdVariantPrinter._template_args): Remove, use get_template_arg_list
	instead.
	(TemplateTypePrinter): Rewrite to work with gdb.Type objects instead
	of strings and regular expressions.
	(add_one_template_type_printer): Adapt to new TemplateTypePrinter.
	(FilteringTypePrinter): Add docstring. Match using startswith. Use
	strip_inline_namespaces instead of strip_versioned_namespace.
	(add_one_type_printer): Prepend namespace to match argument.
	(register_type_printers): Add type printers for char16_t and char32_t
	string types and for types using cxx11 ABI. Update calls to
	add_one_template_type_printer to provide default argument dicts.
	* testsuite/libstdc++-prettyprinters/80276.cc: New test.
	* testsuite/libstdc++-prettyprinters/whatis.cc: Remove tests for
	basic_string<unsigned char> and basic_string<signed char>.
	* testsuite/libstdc++-prettyprinters/whatis2.cc: Duplicate whatis.cc
	to test local variables, without overriding _GLIBCXX_USE_CXX11_ABI.

From-SVN: r256689
parent ed99ae13
2018-01-15 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/80276
* python/libstdcxx/v6/printers.py (strip_inline_namespaces): New.
(get_template_arg_list): New.
(StdVariantPrinter._template_args): Remove, use get_template_arg_list
instead.
(TemplateTypePrinter): Rewrite to work with gdb.Type objects instead
of strings and regular expressions.
(add_one_template_type_printer): Adapt to new TemplateTypePrinter.
(FilteringTypePrinter): Add docstring. Match using startswith. Use
strip_inline_namespaces instead of strip_versioned_namespace.
(add_one_type_printer): Prepend namespace to match argument.
(register_type_printers): Add type printers for char16_t and char32_t
string types and for types using cxx11 ABI. Update calls to
add_one_template_type_printer to provide default argument dicts.
* testsuite/libstdc++-prettyprinters/80276.cc: New test.
* testsuite/libstdc++-prettyprinters/whatis.cc: Remove tests for
basic_string<unsigned char> and basic_string<signed char>.
* testsuite/libstdc++-prettyprinters/whatis2.cc: Duplicate whatis.cc
to test local variables, without overriding _GLIBCXX_USE_CXX11_ABI.
2018-01-14 Andreas Schwab <schwab@linux-m68k.org> 2018-01-14 Andreas Schwab <schwab@linux-m68k.org>
PR libstdc++/81092 PR libstdc++/81092
......
...@@ -101,8 +101,8 @@ def find_type(orig, name): ...@@ -101,8 +101,8 @@ def find_type(orig, name):
_versioned_namespace = '__8::' _versioned_namespace = '__8::'
# Test if a type is a given template instantiation.
def is_specialization_of(type, template_name): def is_specialization_of(type, template_name):
"Test if a type is a given template instantiation."
global _versioned_namespace global _versioned_namespace
if _versioned_namespace: if _versioned_namespace:
return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), type) is not None return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), type) is not None
...@@ -114,6 +114,28 @@ def strip_versioned_namespace(typename): ...@@ -114,6 +114,28 @@ def strip_versioned_namespace(typename):
return typename.replace(_versioned_namespace, '') return typename.replace(_versioned_namespace, '')
return typename return typename
def strip_inline_namespaces(type_str):
"Remove known inline namespaces from the canonical name of a type."
type_str = strip_versioned_namespace(type_str)
type_str = type_str.replace('std::__cxx11::', 'std::')
expt_ns = 'std::experimental::'
for lfts_ns in ('fundamentals_v1', 'fundamentals_v2'):
type_str = type_str.replace(expt_ns+lfts_ns+'::', expt_ns)
fs_ns = expt_ns + 'filesystem::'
type_str = type_str.replace(fs_ns+'v1::', fs_ns)
return type_str
def get_template_arg_list(type_obj):
"Return a type's template arguments as a list"
n = 0
template_args = []
while True:
try:
template_args.append(type_obj.template_argument(n))
except:
return template_args
n += 1
class SmartPtrIterator(Iterator): class SmartPtrIterator(Iterator):
"An iterator for smart pointer types with a single 'child' value" "An iterator for smart pointer types with a single 'child' value"
...@@ -1063,7 +1085,7 @@ class StdVariantPrinter(SingleObjContainerPrinter): ...@@ -1063,7 +1085,7 @@ class StdVariantPrinter(SingleObjContainerPrinter):
"Print a std::variant" "Print a std::variant"
def __init__(self, typename, val): def __init__(self, typename, val):
alternatives = self._template_args(val) alternatives = get_template_arg_list(val.type)
self.typename = strip_versioned_namespace(typename) self.typename = strip_versioned_namespace(typename)
self.typename = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives])) self.typename = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives]))
self.index = val['_M_index'] self.index = val['_M_index']
...@@ -1078,17 +1100,6 @@ class StdVariantPrinter(SingleObjContainerPrinter): ...@@ -1078,17 +1100,6 @@ class StdVariantPrinter(SingleObjContainerPrinter):
visualizer = gdb.default_visualizer(contained_value) visualizer = gdb.default_visualizer(contained_value)
super (StdVariantPrinter, self).__init__(contained_value, visualizer, 'array') super (StdVariantPrinter, self).__init__(contained_value, visualizer, 'array')
@staticmethod
def _template_args(val):
n = 0
args = []
while True:
try:
args.append(val.type.template_argument(n))
except:
return args
n += 1
def to_string(self): def to_string(self):
if self.contained_value is None: if self.contained_value is None:
return "%s [no contained value]" % self.typename return "%s [no contained value]" % self.typename
...@@ -1294,84 +1305,168 @@ libstdcxx_printer = None ...@@ -1294,84 +1305,168 @@ libstdcxx_printer = None
class TemplateTypePrinter(object): class TemplateTypePrinter(object):
r""" r"""
A type printer for class templates. A type printer for class templates with default template arguments.
Recognizes type names that match a regular expression. Recognizes specializations of class templates and prints them without
Replaces them with a formatted string which can use replacement field any template arguments that use a default template argument.
{N} to refer to the \N subgroup of the regex match. Type printers are recursively applied to the template arguments.
Type printers are recusively applied to the subgroups.
This allows recognizing e.g. "std::vector<(.*), std::allocator<\\1> >" e.g. replace "std::vector<T, std::allocator<T> >" with "std::vector<T>".
and replacing it with "std::vector<{1}>", omitting the template argument
that uses the default type.
""" """
def __init__(self, name, pattern, subst): def __init__(self, name, defargs):
self.name = name self.name = name
self.pattern = re.compile(pattern) self.defargs = defargs
self.subst = subst
self.enabled = True self.enabled = True
class _recognizer(object): class _recognizer(object):
def __init__(self, pattern, subst): "The recognizer class for TemplateTypePrinter."
self.pattern = pattern
self.subst = subst def __init__(self, name, defargs):
self.type_obj = None self.name = name
self.defargs = defargs
# self.type_obj = None
def recognize(self, type_obj): def recognize(self, type_obj):
"""
If type_obj is a specialization of self.name that uses all the
default template arguments for the class template, then return
a string representation of the type without default arguments.
Otherwise, return None.
"""
if type_obj.tag is None: if type_obj.tag is None:
return None return None
m = self.pattern.match(type_obj.tag) if not type_obj.tag.startswith(self.name):
if m: return None
subs = list(m.groups())
for i, sub in enumerate(subs): template_args = get_template_arg_list(type_obj)
if ('{%d}' % (i+1)) in self.subst: displayed_args = []
# apply recognizers to subgroup require_defaulted = False
try: for n in range(len(template_args)):
subtype = gdb.lookup_type(sub) # The actual template argument in the type:
except gdb.error: targ = template_args[n]
continue # The default template argument for the class template:
rep = gdb.types.apply_type_recognizers( defarg = self.defargs.get(n)
gdb.types.get_type_recognizers(), if defarg is not None:
subtype) # Substitute other template arguments into the default:
if rep: defarg = defarg.format(*template_args)
subs[i] = rep # Fail to recognize the type (by returning None)
subs = [None] + subs # unless the actual argument is the same as the default.
return self.subst.format(*subs) try:
return None if targ != gdb.lookup_type(defarg):
return None
except gdb.error:
# Type lookup failed, just use string comparison:
if targ.tag != defarg:
return None
# All subsequent args must have defaults:
require_defaulted = True
elif require_defaulted:
return None
else:
# Recursively apply recognizers to the template argument
# and add it to the arguments that will be displayed:
displayed_args.append(self._recognize_subtype(targ))
# This assumes no class templates in the nested-name-specifier:
template_name = type_obj.tag[0:type_obj.tag.find('<')]
template_name = strip_inline_namespaces(template_name)
return template_name + '<' + ', '.join(displayed_args) + '>'
def _recognize_subtype(self, type_obj):
"""Convert a gdb.Type to a string by applying recognizers,
or if that fails then simply converting to a string."""
if type_obj.code == gdb.TYPE_CODE_PTR:
return self._recognize_subtype(type_obj.target()) + '*'
if type_obj.code == gdb.TYPE_CODE_ARRAY:
type_str = self._recognize_subtype(type_obj.target())
if str(type_obj.strip_typedefs()).endswith('[]'):
return type_str + '[]' # array of unknown bound
return "%s[%d]" % (type_str, type_obj.range()[1] + 1)
if type_obj.code == gdb.TYPE_CODE_REF:
return self._recognize_subtype(type_obj.target()) + '&'
if hasattr(gdb, 'TYPE_CODE_RVALUE_REF'):
if type_obj.code == gdb.TYPE_CODE_RVALUE_REF:
return self._recognize_subtype(type_obj.target()) + '&&'
type_str = gdb.types.apply_type_recognizers(
gdb.types.get_type_recognizers(), type_obj)
if type_str:
return type_str
return str(type_obj)
def instantiate(self): def instantiate(self):
return self._recognizer(self.pattern, self.subst) "Return a recognizer object for this type printer."
return self._recognizer(self.name, self.defargs)
def add_one_template_type_printer(obj, name, match, subst): def add_one_template_type_printer(obj, name, defargs):
match = '^std::' + match + '$' r"""
printer = TemplateTypePrinter(name, match, 'std::' + subst) Add a type printer for a class template with default template arguments.
Args:
name (str): The template-name of the class template.
defargs (dict int:string) The default template arguments.
Types in defargs can refer to the Nth template-argument using {N}
(with zero-based indices).
e.g. 'unordered_map' has these defargs:
{ 2: 'std::hash<{0}>',
3: 'std::equal_to<{0}>',
4: 'std::allocator<std::pair<const {0}, {1}> >' }
"""
printer = TemplateTypePrinter('std::'+name, defargs)
gdb.types.register_type_printer(obj, printer) gdb.types.register_type_printer(obj, printer)
if _versioned_namespace: if _versioned_namespace:
# Add second type printer for same type in versioned namespace: # Add second type printer for same type in versioned namespace:
match = match.replace('std::', 'std::' + _versioned_namespace) ns = 'std::' + _versioned_namespace
printer = TemplateTypePrinter(name, match, 'std::' + subst) defargs = { n: d.replace('std::', ns) for n,d in defargs.items() }
printer = TemplateTypePrinter(ns+name, defargs)
gdb.types.register_type_printer(obj, printer) gdb.types.register_type_printer(obj, printer)
class FilteringTypePrinter(object): class FilteringTypePrinter(object):
r"""
A type printer that uses typedef names for common template specializations.
Args:
match (str): The class template to recognize.
name (str): The typedef-name that will be used instead.
Checks if a specialization of the class template 'match' is the same type
as the typedef 'name', and prints it as 'name' instead.
e.g. if an instantiation of std::basic_istream<C, T> is the same type as
std::istream then print it as std::istream.
"""
def __init__(self, match, name): def __init__(self, match, name):
self.match = match self.match = match
self.name = name self.name = name
self.enabled = True self.enabled = True
class _recognizer(object): class _recognizer(object):
"The recognizer class for TemplateTypePrinter."
def __init__(self, match, name): def __init__(self, match, name):
self.match = match self.match = match
self.name = name self.name = name
self.type_obj = None self.type_obj = None
def recognize(self, type_obj): def recognize(self, type_obj):
"""
If type_obj starts with self.match and is the same type as
self.name then return self.name, otherwise None.
"""
if type_obj.tag is None: if type_obj.tag is None:
return None return None
if self.type_obj is None: if self.type_obj is None:
if not self.match in type_obj.tag: if not type_obj.tag.startswith(self.match):
# Filter didn't match. # Filter didn't match.
return None return None
try: try:
...@@ -1379,17 +1474,19 @@ class FilteringTypePrinter(object): ...@@ -1379,17 +1474,19 @@ class FilteringTypePrinter(object):
except: except:
pass pass
if self.type_obj == type_obj: if self.type_obj == type_obj:
return strip_versioned_namespace(self.name) return strip_inline_namespaces(self.name)
return None return None
def instantiate(self): def instantiate(self):
"Return a recognizer object for this type printer."
return self._recognizer(self.match, self.name) return self._recognizer(self.match, self.name)
def add_one_type_printer(obj, match, name): def add_one_type_printer(obj, match, name):
printer = FilteringTypePrinter(match, 'std::' + name) printer = FilteringTypePrinter('std::' + match, 'std::' + name)
gdb.types.register_type_printer(obj, printer) gdb.types.register_type_printer(obj, printer)
if _versioned_namespace: if _versioned_namespace:
printer = FilteringTypePrinter(match, 'std::' + _versioned_namespace + name) ns = 'std::' + _versioned_namespace
printer = FilteringTypePrinter(ns + match, ns + name)
gdb.types.register_type_printer(obj, printer) gdb.types.register_type_printer(obj, printer)
def register_type_printers(obj): def register_type_printers(obj):
...@@ -1398,50 +1495,43 @@ def register_type_printers(obj): ...@@ -1398,50 +1495,43 @@ def register_type_printers(obj):
if not _use_type_printing: if not _use_type_printing:
return return
for pfx in ('', 'w'): # Add type printers for typedefs std::string, std::wstring etc.
add_one_type_printer(obj, 'basic_string', pfx + 'string') for ch in ('', 'w', 'u16', 'u32'):
add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view') add_one_type_printer(obj, 'basic_string', ch + 'string')
add_one_type_printer(obj, 'basic_ios', pfx + 'ios') add_one_type_printer(obj, '__cxx11::basic_string',
add_one_type_printer(obj, 'basic_streambuf', pfx + 'streambuf') '__cxx11::' + ch + 'string')
add_one_type_printer(obj, 'basic_istream', pfx + 'istream') add_one_type_printer(obj, 'basic_string_view', ch + 'string_view')
add_one_type_printer(obj, 'basic_ostream', pfx + 'ostream')
add_one_type_printer(obj, 'basic_iostream', pfx + 'iostream') # Add type printers for typedefs std::istream, std::wistream etc.
add_one_type_printer(obj, 'basic_stringbuf', pfx + 'stringbuf') for ch in ('', 'w'):
add_one_type_printer(obj, 'basic_istringstream', for x in ('ios', 'streambuf', 'istream', 'ostream', 'iostream',
pfx + 'istringstream') 'filebuf', 'ifstream', 'ofstream', 'fstream'):
add_one_type_printer(obj, 'basic_ostringstream', add_one_type_printer(obj, 'basic_' + x, ch + x)
pfx + 'ostringstream') for x in ('stringbuf', 'istringstream', 'ostringstream',
add_one_type_printer(obj, 'basic_stringstream', 'stringstream'):
pfx + 'stringstream') add_one_type_printer(obj, 'basic_' + x, ch + x)
add_one_type_printer(obj, 'basic_filebuf', pfx + 'filebuf') # <sstream> types are in __cxx11 namespace, but typedefs aren'x:
add_one_type_printer(obj, 'basic_ifstream', pfx + 'ifstream') add_one_type_printer(obj, '__cxx11::basic_' + x, ch + x)
add_one_type_printer(obj, 'basic_ofstream', pfx + 'ofstream')
add_one_type_printer(obj, 'basic_fstream', pfx + 'fstream') # Add type printers for typedefs regex, wregex, cmatch, wcmatch etc.
add_one_type_printer(obj, 'basic_regex', pfx + 'regex') for abi in ('', '__cxx11::'):
add_one_type_printer(obj, 'sub_match', pfx + 'csub_match') for ch in ('', 'w'):
add_one_type_printer(obj, 'sub_match', pfx + 'ssub_match') add_one_type_printer(obj, abi + 'basic_regex', abi + ch + 'regex')
add_one_type_printer(obj, 'match_results', pfx + 'cmatch') for ch in ('c', 's', 'wc', 'ws'):
add_one_type_printer(obj, 'match_results', pfx + 'smatch') add_one_type_printer(obj, abi + 'match_results', abi + ch + 'match')
add_one_type_printer(obj, 'regex_iterator', pfx + 'cregex_iterator') for x in ('sub_match', 'regex_iterator', 'regex_token_iterator'):
add_one_type_printer(obj, 'regex_iterator', pfx + 'sregex_iterator') add_one_type_printer(obj, abi + x, abi + ch + x)
add_one_type_printer(obj, 'regex_token_iterator',
pfx + 'cregex_token_iterator')
add_one_type_printer(obj, 'regex_token_iterator',
pfx + 'sregex_token_iterator')
# Note that we can't have a printer for std::wstreampos, because # Note that we can't have a printer for std::wstreampos, because
# it shares the same underlying type as std::streampos. # it is the same type as std::streampos.
add_one_type_printer(obj, 'fpos', 'streampos') add_one_type_printer(obj, 'fpos', 'streampos')
add_one_type_printer(obj, 'basic_string', 'u16string') # Add type printers for <chrono> typedefs.
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')
for dur in ('nanoseconds', 'microseconds', 'milliseconds', for dur in ('nanoseconds', 'microseconds', 'milliseconds',
'seconds', 'minutes', 'hours'): 'seconds', 'minutes', 'hours'):
add_one_type_printer(obj, 'duration', dur) add_one_type_printer(obj, 'duration', dur)
# Add type printers for <random> typedefs.
add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0') add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand') add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937') add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
...@@ -1452,62 +1542,46 @@ def register_type_printers(obj): ...@@ -1452,62 +1542,46 @@ def register_type_printers(obj):
add_one_type_printer(obj, 'discard_block_engine', 'ranlux48') add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b') add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
# Do not show defaulted template arguments in class templates # Add type printers for experimental::basic_string_view typedefs.
add_one_template_type_printer(obj, 'unique_ptr<T>', ns = 'experimental::fundamentals_v1::'
'unique_ptr<(.*), std::default_delete<\\1 ?> >', for ch in ('', 'w', 'u16', 'u32'):
'unique_ptr<{1}>') add_one_type_printer(obj, ns + 'basic_string_view',
ns + ch + 'string_view')
add_one_template_type_printer(obj, 'basic_string<T>',
'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >', # Do not show defaulted template arguments in class templates.
'basic_string<{1}>') add_one_template_type_printer(obj, 'unique_ptr',
{ 1: 'std::default_delete<{0}>' })
add_one_template_type_printer(obj, 'deque<T>', add_one_template_type_printer(obj, 'deque', { 1: 'std::allocator<{0}>'})
'deque<(.*), std::allocator<\\1 ?> >', add_one_template_type_printer(obj, 'forward_list', { 1: 'std::allocator<{0}>'})
'deque<{1}>') add_one_template_type_printer(obj, 'list', { 1: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'forward_list<T>', add_one_template_type_printer(obj, '__cxx11::list', { 1: 'std::allocator<{0}>'})
'forward_list<(.*), std::allocator<\\1 ?> >', add_one_template_type_printer(obj, 'vector', { 1: 'std::allocator<{0}>'})
'forward_list<{1}>') add_one_template_type_printer(obj, 'map',
add_one_template_type_printer(obj, 'list<T>', { 2: 'std::less<{0}>',
'list<(.*), std::allocator<\\1 ?> >', 3: 'std::allocator<std::pair<{0} const, {1}>>' })
'list<{1}>') add_one_template_type_printer(obj, 'multimap',
add_one_template_type_printer(obj, 'vector<T>', { 2: 'std::less<{0}>',
'vector<(.*), std::allocator<\\1 ?> >', 3: 'std::allocator<std::pair<{0} const, {1}>>' })
'vector<{1}>') add_one_template_type_printer(obj, 'set',
add_one_template_type_printer(obj, 'map<Key, T>', { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', add_one_template_type_printer(obj, 'multiset',
'map<{1}, {2}>') { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
add_one_template_type_printer(obj, 'multimap<Key, T>', add_one_template_type_printer(obj, 'unordered_map',
'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', { 2: 'std::hash<{0}>',
'multimap<{1}, {2}>') 3: 'std::equal_to<{0}>',
add_one_template_type_printer(obj, 'set<T>', 4: 'std::allocator<std::pair<{0} const, {1}>>'})
'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >', add_one_template_type_printer(obj, 'unordered_multimap',
'set<{1}>') { 2: 'std::hash<{0}>',
add_one_template_type_printer(obj, 'multiset<T>', 3: 'std::equal_to<{0}>',
'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >', 4: 'std::allocator<std::pair<{0} const, {1}>>'})
'multiset<{1}>') add_one_template_type_printer(obj, 'unordered_set',
add_one_template_type_printer(obj, 'unordered_map<Key, T>', { 1: 'std::hash<{0}>',
'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', 2: 'std::equal_to<{0}>',
'unordered_map<{1}, {2}>') 3: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'unordered_multimap<Key, T>', add_one_template_type_printer(obj, 'unordered_multiset',
'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >', { 1: 'std::hash<{0}>',
'unordered_multimap<{1}, {2}>') 2: 'std::equal_to<{0}>',
add_one_template_type_printer(obj, 'unordered_set<T>', 3: 'std::allocator<{0}>'})
'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
'unordered_set<{1}>')
add_one_template_type_printer(obj, 'unordered_multiset<T>',
'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
'unordered_multiset<{1}>')
# strip the "fundamentals_v1" inline namespace from these types
add_one_template_type_printer(obj, 'any<T>',
'experimental::fundamentals_v\d::any<(.*)>',
'experimental::any<\\1>')
add_one_template_type_printer(obj, 'optional<T>',
'experimental::fundamentals_v\d::optional<(.*)>',
'experimental::optional<\\1>')
add_one_template_type_printer(obj, 'basic_string_view<C>',
'experimental::fundamentals_v\d::basic_string_view<(.*), std::char_traits<\\1> >',
'experimental::basic_string_view<\\1>')
def register_libstdcxx_printers (obj): def register_libstdcxx_printers (obj):
"Register libstdc++ pretty-printers with objfile Obj." "Register libstdc++ pretty-printers with objfile Obj."
......
// { dg-do run { target c++11 } }
// { dg-options "-g -O0" }
// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } }
// Copyright (C) 2018 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 <iostream>
#include <list>
#include <memory>
#include <set>
#include <string>
#include <vector>
template<class T>
void
placeholder(const T *s)
{
std::cout << (void *) s;
}
int
main()
{
using namespace std;
unique_ptr<vector<unique_ptr<vector<int>*>>> p1;
unique_ptr<vector<unique_ptr<set<int>*>>[]> p2;
unique_ptr<set<unique_ptr<vector<int>*>>[10]> p3;
unique_ptr<vector<unique_ptr<list<std::string>[]>>[99]> p4;
// { dg-final { whatis-test p1 "std::unique_ptr<std::vector<std::unique_ptr<std::vector<int>*>>>" } }
// { dg-final { whatis-test p2 "std::unique_ptr<std::vector<std::unique_ptr<std::set<int>*>>\[\]>" } }
// { dg-final { whatis-test p3 "std::unique_ptr<std::set<std::unique_ptr<std::vector<int>*>>\[10\]>" } }
// { dg-final { whatis-test p4 "std::unique_ptr<std::vector<std::unique_ptr<std::list<std::string>\[\]>>\[99\]>" } }
placeholder(&p1); // Mark SPOT
placeholder(&p2);
placeholder(&p3);
placeholder(&p4);
std::cout << "\n";
return 0;
}
// { dg-final { gdb-test SPOT } }
...@@ -19,7 +19,8 @@ ...@@ -19,7 +19,8 @@
// with this library; see the file COPYING3. If not see // with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// Type printers only recognize the old std::string for now. // GDB can't find global variables using the abi_tag attribute.
// https://sourceware.org/bugzilla/show_bug.cgi?id=19436
#define _GLIBCXX_USE_CXX11_ABI 0 #define _GLIBCXX_USE_CXX11_ABI 0
#include <string> #include <string>
...@@ -49,8 +50,6 @@ struct holder ...@@ -49,8 +50,6 @@ struct holder
T *f; T *f;
}; };
typedef std::basic_string<unsigned char> ustring;
// This test is written in a somewhat funny way. // This test is written in a somewhat funny way.
// Each type under test is used twice: first, to form a pointer type, // Each type under test is used twice: first, to form a pointer type,
// and second, as a template parameter. This is done to work around // and second, as a template parameter. This is done to work around
...@@ -165,14 +164,6 @@ std::knuth_b *knuth_b_ptr; ...@@ -165,14 +164,6 @@ std::knuth_b *knuth_b_ptr;
holder<std::knuth_b> knuth_b_holder; holder<std::knuth_b> knuth_b_holder;
// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } } // { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
ustring *ustring_ptr;
holder<ustring> ustring_holder;
// { 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::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr; std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder; holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } } // { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
...@@ -271,10 +262,6 @@ main() ...@@ -271,10 +262,6 @@ main()
placeholder(&ranlux48_holder); placeholder(&ranlux48_holder);
placeholder(&knuth_b_ptr); placeholder(&knuth_b_ptr);
placeholder(&knuth_b_holder); placeholder(&knuth_b_holder);
placeholder(&ustring_ptr);
placeholder(&ustring_holder);
placeholder(&sstring_ptr);
placeholder(&sstring_holder);
placeholder(&seq1_ptr); placeholder(&seq1_ptr);
placeholder(&seq1_holder); placeholder(&seq1_holder);
placeholder(&seq2_ptr); placeholder(&seq2_ptr);
......
// { dg-do run { target c++11 } }
// { dg-options "-g -O0" }
// { dg-skip-if "" { *-*-* } { "-D_GLIBCXX_PROFILE" } }
// Copyright (C) 2011-2018 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 <string>
#include <iostream>
#include <regex>
#include <memory>
#include <deque>
#include <forward_list>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <random>
template<class T>
void
placeholder(const T *s)
{
std::cout << (void *) s;
}
template<class T>
struct holder
{
T *f;
};
// This test is written in a somewhat funny way.
// Each type under test is used twice: first, to form a pointer type,
// and second, as a template parameter. This is done to work around
// apparent GCC oddities. The pointer type is needed to ensure that
// the typedef in question ends up in the debuginfo; while the
// template type is used to ensure that a typedef-less variant is
// presented to gdb.
int
main()
{
std::string *string_ptr;
holder<std::string> string_holder;
// { dg-final { whatis-test string_holder "holder<std::string>" } }
std::ios *ios_ptr;
holder<std::ios> ios_holder;
// { dg-final { whatis-test ios_holder "holder<std::ios>" } }
std::streambuf *streambuf_ptr;
holder<std::streambuf> streambuf_holder;
// { dg-final { whatis-test streambuf_holder "holder<std::streambuf>" } }
std::istream *istream_ptr;
holder<std::istream> istream_holder;
// { dg-final { whatis-test istream_holder "holder<std::istream>" } }
std::ostream *ostream_ptr;
holder<std::ostream> ostream_holder;
// { dg-final { whatis-test ostream_holder "holder<std::ostream>" } }
std::iostream *iostream_ptr;
holder<std::iostream> iostream_holder;
// { dg-final { whatis-test iostream_holder "holder<std::iostream>" } }
std::stringbuf *stringbuf_ptr;
holder<std::stringbuf> stringbuf_holder;
// { dg-final { whatis-test stringbuf_holder "holder<std::stringbuf>" } }
std::istringstream *istringstream_ptr;
holder<std::istringstream> istringstream_holder;
// { dg-final { whatis-test istringstream_holder "holder<std::istringstream>" } }
std::ostringstream *ostringstream_ptr;
holder<std::ostringstream> ostringstream_holder;
// { dg-final { whatis-test ostringstream_holder "holder<std::ostringstream>" } }
std::stringstream *stringstream_ptr;
holder<std::stringstream> stringstream_holder;
// { dg-final { whatis-test stringstream_holder "holder<std::stringstream>" } }
std::filebuf *filebuf_ptr;
holder<std::filebuf> filebuf_holder;
// { dg-final { whatis-test filebuf_holder "holder<std::filebuf>" } }
std::ifstream *ifstream_ptr;
holder<std::ifstream> ifstream_holder;
// { dg-final { whatis-test ifstream_holder "holder<std::ifstream>" } }
std::ofstream *ofstream_ptr;
holder<std::ofstream> ofstream_holder;
// { dg-final { whatis-test ofstream_holder "holder<std::ofstream>" } }
std::fstream *fstream_ptr;
holder<std::fstream> fstream_holder;
// { dg-final { whatis-test fstream_holder "holder<std::fstream>" } }
std::streampos *streampos_ptr;
holder<std::streampos> streampos_holder;
// { dg-final { whatis-test streampos_holder "holder<std::streampos>" } }
std::regex *regex_ptr;
holder<std::regex> regex_holder;
// { dg-final { whatis-test regex_holder "holder<std::regex>" } }
std::csub_match *csub_match_ptr;
holder<std::csub_match> csub_match_holder;
// { dg-final { whatis-test csub_match_holder "holder<std::csub_match>" } }
std::ssub_match *ssub_match_ptr;
holder<std::ssub_match> ssub_match_holder;
// { dg-final { whatis-test ssub_match_holder "holder<std::ssub_match>" } }
std::cmatch *cmatch_ptr;
holder<std::cmatch> cmatch_holder;
// { dg-final { whatis-test cmatch_holder "holder<std::cmatch>" } }
std::smatch *smatch_ptr;
holder<std::smatch> smatch_holder;
// { dg-final { whatis-test smatch_holder "holder<std::smatch>" } }
std::cregex_iterator *cregex_iterator_ptr;
holder<std::cregex_iterator> cregex_iterator_holder;
// { dg-final { whatis-test cregex_iterator_holder "holder<std::cregex_iterator>" } }
std::sregex_iterator *sregex_iterator_ptr;
holder<std::sregex_iterator> sregex_iterator_holder;
// { dg-final { whatis-test sregex_iterator_holder "holder<std::sregex_iterator>" } }
std::cregex_token_iterator *cregex_token_iterator_ptr;
holder<std::cregex_token_iterator> cregex_token_iterator_holder;
// { dg-final { whatis-test cregex_token_iterator_holder "holder<std::cregex_token_iterator>" } }
std::sregex_token_iterator *sregex_token_iterator_ptr;
holder<std::sregex_token_iterator> sregex_token_iterator_holder;
// { dg-final { whatis-test sregex_token_iterator_holder "holder<std::sregex_token_iterator>" } }
std::u16string *u16string_ptr;
holder<std::u16string> u16string_holder;
// { dg-final { whatis-test u16string_holder "holder<std::u16string>" } }
std::u32string *u32string_ptr;
holder<std::u32string> u32string_holder;
// { dg-final { whatis-test u32string_holder "holder<std::u32string>" } }
std::minstd_rand0 *minstd_rand0_ptr;
holder<std::minstd_rand0> minstd_rand0_holder;
// { dg-final { whatis-test minstd_rand0_holder "holder<std::minstd_rand0>" } }
std::minstd_rand *minstd_rand_ptr;
holder<std::minstd_rand> minstd_rand_holder;
// { dg-final { whatis-test minstd_rand_holder "holder<std::minstd_rand>" } }
std::mt19937 *mt19937_ptr;
holder<std::mt19937> mt19937_holder;
// { dg-final { whatis-test mt19937_holder "holder<std::mt19937>" } }
std::mt19937_64 *mt19937_64_ptr;
holder<std::mt19937_64> mt19937_64_holder;
// { dg-final { whatis-test mt19937_64_holder "holder<std::mt19937_64>" } }
std::ranlux24_base *ranlux24_base_ptr;
holder<std::ranlux24_base> ranlux24_base_holder;
// { dg-final { whatis-test ranlux24_base_holder "holder<std::ranlux24_base>" } }
std::ranlux48_base *ranlux48_base_ptr;
holder<std::ranlux48_base> ranlux48_base_holder;
// { dg-final { whatis-test ranlux48_base_holder "holder<std::ranlux48_base>" } }
std::ranlux24 *ranlux24_ptr;
holder<std::ranlux24> ranlux24_holder;
// { dg-final { whatis-test ranlux24_holder "holder<std::ranlux24>" } }
std::ranlux48 *ranlux48_ptr;
holder<std::ranlux48> ranlux48_holder;
// { dg-final { whatis-test ranlux48_holder "holder<std::ranlux48>" } }
std::knuth_b *knuth_b_ptr;
holder<std::knuth_b> knuth_b_holder;
// { dg-final { whatis-test knuth_b_holder "holder<std::knuth_b>" } }
std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
std::list<std::forward_list<std::unique_ptr<char>>> *seq2_ptr;
holder< std::list<std::forward_list<std::unique_ptr<char>>> > seq2_holder;
// { dg-final { whatis-test seq2_holder "holder<std::list<std::forward_list<std::unique_ptr<char>>> >" } }
std::map<int, std::set<int>> *assoc1_ptr;
holder< std::map<int, std::set<int>> > assoc1_holder;
// { dg-final { whatis-test assoc1_holder "holder<std::map<int, std::set<int>> >" } }
std::multimap<int, std::multiset<int>> *assoc2_ptr;
holder< std::multimap<int, std::multiset<int>> > assoc2_holder;
// { dg-final { whatis-test assoc2_holder "holder<std::multimap<int, std::multiset<int>> >" } }
std::unordered_map<int, std::unordered_set<int>> *unord1_ptr;
holder< std::unordered_map<int, std::unordered_set<int>> > unord1_holder;
// { dg-final { whatis-test unord1_holder "holder<std::unordered_map<int, std::unordered_set<int>> >" } }
std::unordered_multimap<int, std::unordered_multiset<int>> *unord2_ptr;
holder< std::unordered_multimap<int, std::unordered_multiset<int>> > unord2_holder;
// { dg-final { whatis-test unord2_holder "holder<std::unordered_multimap<int, std::unordered_multiset<int>> >" } }
placeholder(&ios_ptr); // Mark SPOT
placeholder(&ios_holder);
placeholder(&string_ptr);
placeholder(&string_holder);
placeholder(&streambuf_ptr);
placeholder(&streambuf_holder);
placeholder(&istream_ptr);
placeholder(&istream_holder);
placeholder(&ostream_ptr);
placeholder(&ostream_holder);
placeholder(&iostream_ptr);
placeholder(&iostream_holder);
placeholder(&stringbuf_ptr);
placeholder(&stringbuf_holder);
placeholder(&istringstream_ptr);
placeholder(&istringstream_holder);
placeholder(&ostringstream_ptr);
placeholder(&ostringstream_holder);
placeholder(&stringstream_ptr);
placeholder(&stringstream_holder);
placeholder(&filebuf_ptr);
placeholder(&filebuf_holder);
placeholder(&ifstream_ptr);
placeholder(&ifstream_holder);
placeholder(&ofstream_ptr);
placeholder(&ofstream_holder);
placeholder(&fstream_ptr);
placeholder(&fstream_holder);
placeholder(&streampos_ptr);
placeholder(&streampos_holder);
placeholder(&regex_ptr);
placeholder(&regex_holder);
placeholder(&csub_match_ptr);
placeholder(&csub_match_holder);
placeholder(&ssub_match_ptr);
placeholder(&ssub_match_holder);
placeholder(&cmatch_ptr);
placeholder(&cmatch_holder);
placeholder(&smatch_ptr);
placeholder(&smatch_holder);
placeholder(&cregex_iterator_ptr);
placeholder(&cregex_iterator_holder);
placeholder(&sregex_iterator_ptr);
placeholder(&sregex_iterator_holder);
placeholder(&cregex_token_iterator_ptr);
placeholder(&cregex_token_iterator_holder);
placeholder(&sregex_token_iterator_ptr);
placeholder(&sregex_token_iterator_holder);
placeholder(&u16string_ptr);
placeholder(&u16string_holder);
placeholder(&u32string_ptr);
placeholder(&u32string_holder);
placeholder(&minstd_rand0_ptr);
placeholder(&minstd_rand0_holder);
placeholder(&minstd_rand_ptr);
placeholder(&minstd_rand_holder);
placeholder(&mt19937_ptr);
placeholder(&mt19937_holder);
placeholder(&mt19937_64_ptr);
placeholder(&mt19937_64_holder);
placeholder(&ranlux24_base_ptr);
placeholder(&ranlux24_base_holder);
placeholder(&ranlux48_base_ptr);
placeholder(&ranlux48_base_holder);
placeholder(&ranlux24_ptr);
placeholder(&ranlux24_holder);
placeholder(&ranlux48_ptr);
placeholder(&ranlux48_holder);
placeholder(&knuth_b_ptr);
placeholder(&knuth_b_holder);
placeholder(&seq1_ptr);
placeholder(&seq1_holder);
placeholder(&seq2_ptr);
placeholder(&seq2_holder);
placeholder(&assoc1_ptr);
placeholder(&assoc1_holder);
placeholder(&assoc2_ptr);
placeholder(&assoc2_holder);
placeholder(&unord1_ptr);
placeholder(&unord1_holder);
placeholder(&unord2_ptr);
placeholder(&unord2_holder);
std::cout << "\n";
return 0;
}
// { dg-final { gdb-test SPOT } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment