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... |