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
This commit is contained in:
Jonathan Wakely 2018-01-15 11:13:53 +00:00 committed by Jonathan Wakely
parent ed99ae13bb
commit bab0a26de5
5 changed files with 581 additions and 162 deletions

View File

@ -1,3 +1,25 @@
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>
PR libstdc++/81092

View File

@ -101,8 +101,8 @@ def find_type(orig, name):
_versioned_namespace = '__8::'
# Test if a type is a given template instantiation.
def is_specialization_of(type, template_name):
"Test if a type is a given template instantiation."
global _versioned_namespace
if _versioned_namespace:
return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), type) is not None
@ -114,6 +114,28 @@ def strip_versioned_namespace(typename):
return typename.replace(_versioned_namespace, '')
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):
"An iterator for smart pointer types with a single 'child' value"
@ -1063,7 +1085,7 @@ class StdVariantPrinter(SingleObjContainerPrinter):
"Print a std::variant"
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 = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives]))
self.index = val['_M_index']
@ -1078,17 +1100,6 @@ class StdVariantPrinter(SingleObjContainerPrinter):
visualizer = gdb.default_visualizer(contained_value)
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):
if self.contained_value is None:
return "%s [no contained value]" % self.typename
@ -1294,84 +1305,168 @@ libstdcxx_printer = None
class TemplateTypePrinter(object):
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.
Replaces them with a formatted string which can use replacement field
{N} to refer to the \N subgroup of the regex match.
Type printers are recusively applied to the subgroups.
Recognizes specializations of class templates and prints them without
any template arguments that use a default template argument.
Type printers are recursively applied to the template arguments.
This allows recognizing e.g. "std::vector<(.*), std::allocator<\\1> >"
and replacing it with "std::vector<{1}>", omitting the template argument
that uses the default type.
e.g. replace "std::vector<T, std::allocator<T> >" with "std::vector<T>".
"""
def __init__(self, name, pattern, subst):
def __init__(self, name, defargs):
self.name = name
self.pattern = re.compile(pattern)
self.subst = subst
self.defargs = defargs
self.enabled = True
class _recognizer(object):
def __init__(self, pattern, subst):
self.pattern = pattern
self.subst = subst
self.type_obj = None
"The recognizer class for TemplateTypePrinter."
def __init__(self, name, defargs):
self.name = name
self.defargs = defargs
# self.type_obj = None
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:
return None
m = self.pattern.match(type_obj.tag)
if m:
subs = list(m.groups())
for i, sub in enumerate(subs):
if ('{%d}' % (i+1)) in self.subst:
# apply recognizers to subgroup
try:
subtype = gdb.lookup_type(sub)
except gdb.error:
continue
rep = gdb.types.apply_type_recognizers(
gdb.types.get_type_recognizers(),
subtype)
if rep:
subs[i] = rep
subs = [None] + subs
return self.subst.format(*subs)
return None
if not type_obj.tag.startswith(self.name):
return None
template_args = get_template_arg_list(type_obj)
displayed_args = []
require_defaulted = False
for n in range(len(template_args)):
# The actual template argument in the type:
targ = template_args[n]
# The default template argument for the class template:
defarg = self.defargs.get(n)
if defarg is not None:
# Substitute other template arguments into the default:
defarg = defarg.format(*template_args)
# Fail to recognize the type (by returning None)
# unless the actual argument is the same as the default.
try:
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):
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):
match = '^std::' + match + '$'
printer = TemplateTypePrinter(name, match, 'std::' + subst)
def add_one_template_type_printer(obj, name, defargs):
r"""
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)
if _versioned_namespace:
# Add second type printer for same type in versioned namespace:
match = match.replace('std::', 'std::' + _versioned_namespace)
printer = TemplateTypePrinter(name, match, 'std::' + subst)
ns = 'std::' + _versioned_namespace
defargs = { n: d.replace('std::', ns) for n,d in defargs.items() }
printer = TemplateTypePrinter(ns+name, defargs)
gdb.types.register_type_printer(obj, printer)
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):
self.match = match
self.name = name
self.enabled = True
class _recognizer(object):
"The recognizer class for TemplateTypePrinter."
def __init__(self, match, name):
self.match = match
self.name = name
self.type_obj = None
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:
return 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.
return None
try:
@ -1379,17 +1474,19 @@ class FilteringTypePrinter(object):
except:
pass
if self.type_obj == type_obj:
return strip_versioned_namespace(self.name)
return strip_inline_namespaces(self.name)
return None
def instantiate(self):
"Return a recognizer object for this type printer."
return self._recognizer(self.match, self.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)
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)
def register_type_printers(obj):
@ -1398,50 +1495,43 @@ def register_type_printers(obj):
if not _use_type_printing:
return
for pfx in ('', 'w'):
add_one_type_printer(obj, 'basic_string', pfx + 'string')
add_one_type_printer(obj, 'basic_string_view', pfx + 'string_view')
add_one_type_printer(obj, 'basic_ios', pfx + 'ios')
add_one_type_printer(obj, 'basic_streambuf', pfx + 'streambuf')
add_one_type_printer(obj, 'basic_istream', pfx + 'istream')
add_one_type_printer(obj, 'basic_ostream', pfx + 'ostream')
add_one_type_printer(obj, 'basic_iostream', pfx + 'iostream')
add_one_type_printer(obj, 'basic_stringbuf', pfx + 'stringbuf')
add_one_type_printer(obj, 'basic_istringstream',
pfx + 'istringstream')
add_one_type_printer(obj, 'basic_ostringstream',
pfx + 'ostringstream')
add_one_type_printer(obj, 'basic_stringstream',
pfx + 'stringstream')
add_one_type_printer(obj, 'basic_filebuf', pfx + 'filebuf')
add_one_type_printer(obj, 'basic_ifstream', pfx + 'ifstream')
add_one_type_printer(obj, 'basic_ofstream', pfx + 'ofstream')
add_one_type_printer(obj, 'basic_fstream', pfx + 'fstream')
add_one_type_printer(obj, 'basic_regex', pfx + 'regex')
add_one_type_printer(obj, 'sub_match', pfx + 'csub_match')
add_one_type_printer(obj, 'sub_match', pfx + 'ssub_match')
add_one_type_printer(obj, 'match_results', pfx + 'cmatch')
add_one_type_printer(obj, 'match_results', pfx + 'smatch')
add_one_type_printer(obj, 'regex_iterator', pfx + 'cregex_iterator')
add_one_type_printer(obj, 'regex_iterator', pfx + 'sregex_iterator')
add_one_type_printer(obj, 'regex_token_iterator',
pfx + 'cregex_token_iterator')
add_one_type_printer(obj, 'regex_token_iterator',
pfx + 'sregex_token_iterator')
# Add type printers for typedefs std::string, std::wstring etc.
for ch in ('', 'w', 'u16', 'u32'):
add_one_type_printer(obj, 'basic_string', ch + 'string')
add_one_type_printer(obj, '__cxx11::basic_string',
'__cxx11::' + ch + 'string')
add_one_type_printer(obj, 'basic_string_view', ch + 'string_view')
# Add type printers for typedefs std::istream, std::wistream etc.
for ch in ('', 'w'):
for x in ('ios', 'streambuf', 'istream', 'ostream', 'iostream',
'filebuf', 'ifstream', 'ofstream', 'fstream'):
add_one_type_printer(obj, 'basic_' + x, ch + x)
for x in ('stringbuf', 'istringstream', 'ostringstream',
'stringstream'):
add_one_type_printer(obj, 'basic_' + x, ch + x)
# <sstream> types are in __cxx11 namespace, but typedefs aren'x:
add_one_type_printer(obj, '__cxx11::basic_' + x, ch + x)
# Add type printers for typedefs regex, wregex, cmatch, wcmatch etc.
for abi in ('', '__cxx11::'):
for ch in ('', 'w'):
add_one_type_printer(obj, abi + 'basic_regex', abi + ch + 'regex')
for ch in ('c', 's', 'wc', 'ws'):
add_one_type_printer(obj, abi + 'match_results', abi + ch + 'match')
for x in ('sub_match', 'regex_iterator', 'regex_token_iterator'):
add_one_type_printer(obj, abi + x, abi + ch + x)
# 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, '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')
# Add type printers for <chrono> typedefs.
for dur in ('nanoseconds', 'microseconds', 'milliseconds',
'seconds', 'minutes', 'hours'):
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_rand')
add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
@ -1452,62 +1542,46 @@ def register_type_printers(obj):
add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
# 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}>')
# Add type printers for experimental::basic_string_view typedefs.
ns = 'experimental::fundamentals_v1::'
for ch in ('', 'w', 'u16', 'u32'):
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 ?> >',
'basic_string<{1}>')
add_one_template_type_printer(obj, 'deque<T>',
'deque<(.*), std::allocator<\\1 ?> >',
'deque<{1}>')
add_one_template_type_printer(obj, 'forward_list<T>',
'forward_list<(.*), std::allocator<\\1 ?> >',
'forward_list<{1}>')
add_one_template_type_printer(obj, 'list<T>',
'list<(.*), std::allocator<\\1 ?> >',
'list<{1}>')
add_one_template_type_printer(obj, 'vector<T>',
'vector<(.*), std::allocator<\\1 ?> >',
'vector<{1}>')
add_one_template_type_printer(obj, 'map<Key, T>',
'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
'map<{1}, {2}>')
add_one_template_type_printer(obj, 'multimap<Key, T>',
'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
'multimap<{1}, {2}>')
add_one_template_type_printer(obj, 'set<T>',
'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
'set<{1}>')
add_one_template_type_printer(obj, 'multiset<T>',
'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
'multiset<{1}>')
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}>')
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}>')
add_one_template_type_printer(obj, 'unordered_set<T>',
'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>')
# Do not show defaulted template arguments in class templates.
add_one_template_type_printer(obj, 'unique_ptr',
{ 1: 'std::default_delete<{0}>' })
add_one_template_type_printer(obj, 'deque', { 1: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'forward_list', { 1: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'list', { 1: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, '__cxx11::list', { 1: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'vector', { 1: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'map',
{ 2: 'std::less<{0}>',
3: 'std::allocator<std::pair<{0} const, {1}>>' })
add_one_template_type_printer(obj, 'multimap',
{ 2: 'std::less<{0}>',
3: 'std::allocator<std::pair<{0} const, {1}>>' })
add_one_template_type_printer(obj, 'set',
{ 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
add_one_template_type_printer(obj, 'multiset',
{ 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
add_one_template_type_printer(obj, 'unordered_map',
{ 2: 'std::hash<{0}>',
3: 'std::equal_to<{0}>',
4: 'std::allocator<std::pair<{0} const, {1}>>'})
add_one_template_type_printer(obj, 'unordered_multimap',
{ 2: 'std::hash<{0}>',
3: 'std::equal_to<{0}>',
4: 'std::allocator<std::pair<{0} const, {1}>>'})
add_one_template_type_printer(obj, 'unordered_set',
{ 1: 'std::hash<{0}>',
2: 'std::equal_to<{0}>',
3: 'std::allocator<{0}>'})
add_one_template_type_printer(obj, 'unordered_multiset',
{ 1: 'std::hash<{0}>',
2: 'std::equal_to<{0}>',
3: 'std::allocator<{0}>'})
def register_libstdcxx_printers (obj):
"Register libstdc++ pretty-printers with objfile Obj."

View File

@ -0,0 +1,58 @@
// { 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 } }

View File

@ -19,7 +19,8 @@
// with this library; see the file COPYING3. If not see
// <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
#include <string>
@ -49,8 +50,6 @@ struct holder
T *f;
};
typedef std::basic_string<unsigned char> ustring;
// 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
@ -165,14 +164,6 @@ std::knuth_b *knuth_b_ptr;
holder<std::knuth_b> knuth_b_holder;
// { 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;
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>>> >" } }
@ -271,10 +262,6 @@ main()
placeholder(&ranlux48_holder);
placeholder(&knuth_b_ptr);
placeholder(&knuth_b_holder);
placeholder(&ustring_ptr);
placeholder(&ustring_holder);
placeholder(&sstring_ptr);
placeholder(&sstring_holder);
placeholder(&seq1_ptr);
placeholder(&seq1_holder);
placeholder(&seq2_ptr);

View File

@ -0,0 +1,278 @@
// { 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 } }