The fix for bug 59195: [C++ demangler handles conversion operator incorrectly] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195 unfortunately makes the demangler crash due to infinite recursion, in case of casts in template parameters. For example, with: template<int> struct A {}; template <typename Y> void function_temp(A<sizeof ((Y)(999))>) {} template void function_temp<int>(A<sizeof (int)>); The 'function_temp<int>' instantiation above mangles to: _Z13function_tempIiEv1AIXszcvT_Li999EEE The demangler parses this as: typed name template name 'function_temp' template argument list builtin type int function type builtin type void argument list template (*) name 'A' template argument list unary operator operator sizeof unary operator cast template parameter 0 (**) literal builtin type int name '999' And after the fix for 59195, due to: static void d_print_cast (struct d_print_info *dpi, int options, const struct demangle_component *dc) { ... /* For a cast operator, we need the template parameters from the enclosing template in scope for processing the type. */ if (dpi->current_template != NULL) { dpt.next = dpi->templates; dpi->templates = &dpt; dpt.template_decl = dpi->current_template; } when printing the template argument list of A (what should be "<sizeof (int)>"), the template parameter 0 (that is, "T_", the '**' above) now refers to the first parameter of the the template argument list of the 'A' template (the '*' above), exactly what we were already trying to print. This leads to infinite recursion, and stack exaustion. The template parameter 0 should actually refer to the first parameter of the 'function_temp' template. Where it reads "for the cast operator" in the comment in d_print_cast (above), it's really talking about a conversion operator, like: struct A { template <typename U> explicit operator U(); }; We don't want to inject the template parameters from the enclosing template in scope when processing a cast _expression_, only when handling a conversion operator. The problem is that DEMANGLE_COMPONENT_CAST is currently ambiguous, and means _both_ 'conversion operator' and 'cast expression'. Fix this by adding a new DEMANGLE_COMPONENT_CONVERSION component type, which does what DEMANGLE_COMPONENT_CAST does today, and making DEMANGLE_COMPONENT_CAST just simply print its component subtree. I think we could instead reuse DEMANGLE_COMPONENT_CAST and in d_print_comp_inner still do: @@ -5001,9 +5013,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_print_comp (dpi, options, dc->u.s_extended_operator.name); return; case DEMANGLE_COMPONENT_CAST: d_append_string (dpi, "operator "); - d_print_cast (dpi, options, dc); + d_print_conversion (dpi, options, dc); return; leaving the unary cast case below calling d_print_cast, but seems to me that spliting the component types makes it easier to reason about the code. g++'s testsuite actually generates three symbols that crash the demangler in the same way. I've added those as tests in the demangler testsuite as well. And then this fixes PR other/61233 too, which happens to be a demangler crash originally reported to GDB, at: https://sourceware.org/bugzilla/show_bug.cgi?id=16957 Bootstrapped and regtested on x86_64 Fedora 20. Also ran this through GDB's testsuite. GDB will require a small update to use DEMANGLE_COMPONENT_CONVERSION in one place it's using DEMANGLE_COMPONENT_CAST in its sources. libiberty/ 2015-11-27 Pedro Alves <palves@redhat.com> PR other/61321 PR other/61233 * demangle.h (enum demangle_component_type) <DEMANGLE_COMPONENT_CONVERSION>: New value. * cp-demangle.c (d_demangle_callback, d_make_comp): Handle DEMANGLE_COMPONENT_CONVERSION. (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION instead of DEMANGLE_COMPONENT_CAST. (d_operator_name): Return a DEMANGLE_COMPONENT_CONVERSION component if handling a conversion. (d_count_templates_scopes, d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION. (d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION instead of DEMANGLE_COMPONENT_CAST. (d_print_cast): Rename as ... (d_print_conversion): ... this. Adjust comments. (d_print_cast): Rewrite - simply print the left subcomponent. * cp-demint.c (cplus_demangle_fill_component): Handle DEMANGLE_COMPONENT_CONVERSION. * testsuite/demangle-expected: Add tests. From-SVN: r231020
Name |
Last commit
|
Last update |
---|---|---|
.. | ||
config | Loading commit data... | |
testsuite | Loading commit data... | |
.gitignore | Loading commit data... | |
COPYING.LIB | Loading commit data... | |
ChangeLog | Loading commit data... | |
ChangeLog.jit | Loading commit data... | |
Makefile.in | Loading commit data... | |
README | Loading commit data... | |
_doprnt.c | Loading commit data... | |
aclocal.m4 | Loading commit data... | |
alloca.c | Loading commit data... | |
argv.c | Loading commit data... | |
asprintf.c | Loading commit data... | |
at-file.texi | Loading commit data... | |
atexit.c | Loading commit data... | |
basename.c | Loading commit data... | |
bcmp.c | Loading commit data... | |
bcopy.c | Loading commit data... | |
bsearch.c | Loading commit data... | |
bzero.c | Loading commit data... | |
calloc.c | Loading commit data... | |
choose-temp.c | Loading commit data... | |
clock.c | Loading commit data... | |
concat.c | Loading commit data... | |
config.h-vms | Loading commit data... | |
config.in | Loading commit data... | |
configure | Loading commit data... | |
configure.ac | Loading commit data... | |
configure.com | Loading commit data... | |
copying-lib.texi | Loading commit data... | |
copysign.c | Loading commit data... | |
cp-demangle.c | Loading commit data... | |
cp-demangle.h | Loading commit data... | |
cp-demint.c | Loading commit data... | |
cplus-dem.c | Loading commit data... | |
crc32.c | Loading commit data... | |
d-demangle.c | Loading commit data... | |
dwarfnames.c | Loading commit data... | |
dyn-string.c | Loading commit data... | |
fdmatch.c | Loading commit data... | |
ffs.c | Loading commit data... | |
fibheap.c | Loading commit data... | |
filename_cmp.c | Loading commit data... | |
floatformat.c | Loading commit data... | |
fnmatch.c | Loading commit data... | |
fnmatch.txh | Loading commit data... | |
fopen_unlocked.c | Loading commit data... | |
functions.texi | Loading commit data... | |
gather-docs | Loading commit data... | |
getcwd.c | Loading commit data... | |
getopt.c | Loading commit data... | |
getopt1.c | Loading commit data... | |
getpagesize.c | Loading commit data... | |
getpwd.c | Loading commit data... | |
getruntime.c | Loading commit data... | |
gettimeofday.c | Loading commit data... | |
hashtab.c | Loading commit data... | |
hex.c | Loading commit data... | |
index.c | Loading commit data... | |
insque.c | Loading commit data... | |
lbasename.c | Loading commit data... | |
libiberty.texi | Loading commit data... | |
lrealpath.c | Loading commit data... | |
maint-tool | Loading commit data... | |
make-relative-prefix.c | Loading commit data... | |
make-temp-file.c | Loading commit data... | |
makefile.vms | Loading commit data... | |
md5.c | Loading commit data... | |
memchr.c | Loading commit data... | |
memcmp.c | Loading commit data... | |
memcpy.c | Loading commit data... | |
memmem.c | Loading commit data... | |
memmove.c | Loading commit data... | |
mempcpy.c | Loading commit data... | |
memset.c | Loading commit data... | |
mkstemps.c | Loading commit data... | |
msdos.c | Loading commit data... | |
objalloc.c | Loading commit data... | |
obstack.c | Loading commit data... | |
obstacks.texi | Loading commit data... | |
partition.c | Loading commit data... | |
pex-common.c | Loading commit data... | |
pex-common.h | Loading commit data... | |
pex-djgpp.c | Loading commit data... | |
pex-msdos.c | Loading commit data... | |
pex-one.c | Loading commit data... | |
pex-unix.c | Loading commit data... | |
pex-win32.c | Loading commit data... | |
pexecute.c | Loading commit data... | |
pexecute.txh | Loading commit data... | |
physmem.c | Loading commit data... | |
putenv.c | Loading commit data... | |
random.c | Loading commit data... | |
regex.c | Loading commit data... | |
rename.c | Loading commit data... | |
rindex.c | Loading commit data... | |
safe-ctype.c | Loading commit data... | |
setenv.c | Loading commit data... | |
setproctitle.c | Loading commit data... | |
sha1.c | Loading commit data... | |
sigsetmask.c | Loading commit data... | |
simple-object-coff.c | Loading commit data... | |
simple-object-common.h | Loading commit data... | |
simple-object-elf.c | Loading commit data... | |
simple-object-mach-o.c | Loading commit data... | |
simple-object-xcoff.c | Loading commit data... | |
simple-object.c | Loading commit data... | |
simple-object.txh | Loading commit data... | |
snprintf.c | Loading commit data... | |
sort.c | Loading commit data... | |
spaces.c | Loading commit data... | |
splay-tree.c | Loading commit data... | |
stack-limit.c | Loading commit data... | |
stpcpy.c | Loading commit data... | |
stpncpy.c | Loading commit data... | |
strcasecmp.c | Loading commit data... | |
strchr.c | Loading commit data... | |
strdup.c | Loading commit data... | |
strerror.c | Loading commit data... | |
strncasecmp.c | Loading commit data... | |
strncmp.c | Loading commit data... | |
strndup.c | Loading commit data... | |
strnlen.c | Loading commit data... | |
strrchr.c | Loading commit data... | |
strsignal.c | Loading commit data... | |
strstr.c | Loading commit data... | |
strtod.c | Loading commit data... | |
strtol.c | Loading commit data... | |
strtoll.c | Loading commit data... | |
strtoul.c | Loading commit data... | |
strtoull.c | Loading commit data... | |
strverscmp.c | Loading commit data... | |
timeval-utils.c | Loading commit data... | |
tmpnam.c | Loading commit data... | |
unlink-if-ordinary.c | Loading commit data... | |
vasprintf.c | Loading commit data... | |
vfork.c | Loading commit data... | |
vfprintf.c | Loading commit data... | |
vprintf-support.c | Loading commit data... | |
vprintf-support.h | Loading commit data... | |
vprintf.c | Loading commit data... | |
vsnprintf.c | Loading commit data... | |
vsprintf.c | Loading commit data... | |
waitpid.c | Loading commit data... | |
xasprintf.c | Loading commit data... | |
xatexit.c | Loading commit data... | |
xexit.c | Loading commit data... | |
xmalloc.c | Loading commit data... | |
xmemdup.c | Loading commit data... | |
xstrdup.c | Loading commit data... | |
xstrerror.c | Loading commit data... | |
xstrndup.c | Loading commit data... | |
xvasprintf.c | Loading commit data... |