#include <exception> #include <iostream> #include <cxxabi.h> struct empty { }; template <typename T, int N> struct bar { }; int main() { int status; char *realname; // exception classes not in <stdexcept>, thrown by the implementation // instead of the user std::bad_exception e; realname = abi::__cxa_demangle(e.what(), 0, 0, &status); std::cout << e.what() << "\t=> " << realname << "\t: " << status << '\n'; free(realname); // typeid bar<empty,17> u; const std::type_info &ti = typeid(u); realname = abi::__cxa_demangle(ti.name(), 0, 0, &status); std::cout << ti.name() << "\t=> " << realname << "\t: " << status << '\n'; free(realname); // typeid const std::type_info &tj = typeid(int); realname = abi::__cxa_demangle(tj.name(), 0, 0, &status); std::cout << tj.name() << "\t=> " << realname << "\t: " << status << '\n'; free(realname); return 0; } gets you: ~/ootbc/common/src$ a.out St13bad_exception => std::bad_exception : 0 3barI5emptyLi17EE => bar<empty, 17> : 0 i => ~/ootbc/common/src$ It works for some complicated types, but not for plain "int" Ivan
Here's the -v: Reading specs from /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/spec s Configured with: ../gcc/configure --prefix=/site Thread model: posix gcc version 3.4.0 /mnt/export/local/bin/../libexec/gcc/i686-pc-linux-gnu/3.4.0/cc1plus -quiet -v -iprefix /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/ -D_GNU_SOURCE foo.cc -quiet -dumpbase foo.cc -mtune=pentiumpro -auxbase foo -version -o /tmp/ ccDO2GVs.s ignoring nonexistent directory "/mnt/export/local/bin/../lib/gcc/i686-pc-linux-g nu/3.4.0/../../../../i686-pc-linux-gnu/include" ignoring duplicate directory "/site/lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../ include/c++/3.4.0" ignoring duplicate directory "/site/lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../ include/c++/3.4.0/i686-pc-linux-gnu" ignoring duplicate directory "/site/lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../ include/c++/3.4.0/backward" ignoring duplicate directory "/site/lib/gcc/i686-pc-linux-gnu/3.4.0/include" ignoring nonexistent directory "/site/lib/gcc/i686-pc-linux-gnu/3.4.0/../../../. ./i686-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../include/c+ +/3.4.0 /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../include/c+ +/3.4.0/i686-pc-linux-gnu /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../include/c+ +/3.4.0/backward /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/include /usr/local/include /site/include /usr/include End of search list. GNU C++ version 3.4.0 (i686-pc-linux-gnu) compiled by GNU C version 3.4.0. GGC heuristics: --param ggc-min-expand=38 --param ggc-min-heapsize=15744 as -V -Qy -o /tmp/ccKZ44yK.o /tmp/ccDO2GVs.s GNU assembler version 2.14.90.0.4 (i386-linux) using BFD version 2.14.90.0.4 200 30523 Debian GNU/Linux /mnt/export/local/bin/../libexec/gcc/i686-pc-linux-gnu/3.4.0/collect2 --eh-fram e-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/cr ti.o /mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/crtbegin.o -L/mnt/export/local/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0 -L/mnt/export/local/bin/../l ib/gcc -L/site/lib/gcc/i686-pc-linux-gnu/3.4.0 -L/mnt/export/local/bin/../lib/gc c/i686-pc-linux-gnu/3.4.0/../../.. -L/site/lib/gcc/i686-pc-linux-gnu/3.4.0/../.. /.. /tmp/ccKZ44yK.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /mnt/export/loc al/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/crtend.o /usr/lib/crtn.o
Ian, could you please have a look? Thanks in advance.
Some reference to why the current behavior is wrong or maybe right: http://www.codesourcery.com/archives/cxx-abi-dev/msg01787.html http://sources.redhat.com/ml/binutils/2003-12/msg00105.html http://gcc.gnu.org/ml/libstdc++/2002-12/msg00061.html
After reading the citations from pinskia, it seems that there is a bug here regardless of the semantics. Your ABI may require that "i" demangle as "i", although I'd be appalled that it would, or as "int", but if you look at the test case it demangles as nothing at all (and reports a -2 error). That has to be a bug. Three comments: 1) I understand that there must be a link/RTTI demangler for data names. However, the ability to print a typename (from "typeid(...).name()") is also important to those mere users who are not compiler implementers. If the demangling syntax is different across the two cases (and if it is I predict big trouble when the day comes that you need to support an "extern "C" typedef...") then the library should provide a means by which both are available. The demangler in 3.4.0 /ext/demangle.h does so, but appears to be otherwise hopelessly broken (I tried to use it as a workaround). 2) At least for use from c++, the demangler should be integrated with streams; then the desired semantics can be specified by a format effector, as is done with "bool". The demangler should not have an interface that invites buffer-overrun exploits. 3) IMO, RTTI type info improvement is desperately needed. You know what you have to do to print the name of an enum value? Ivan
I believe that the behaviour of __cxa_demangle conforms to the API. I also believe that the API is broken. The present code conforms to the broken API. The API is here: http://www.codesourcery.com/cxx-abi/abi.html#demangler It says 'Ambiguities are possible between extern "C" object names and internal built-in type names, e.g. "i" may be either an object named "i" or the built-in "int" type. Such ambiguities should be resolved to user names over built-in names.' All internal built-in type names are mangled as a single lower-case character. I interpret the API statement to mean that any string consisting of a single lower-case character should not be demangled. The API further says "If there is an error in demangling, the return value is a null pointer." Therefore, in this case, the function must return NULL. Of the options for a value to put in *status, -2 is the only reasonable choice. There is a mailing list thread which discusses this here: http://gcc.gnu.org/ml/libstdc++/2004-02/msg00333.html Others agree that my reading of the API is reasonable. I continue to think that it is the only reasonable reading. So I don't think there is a bug in __cxa_demangle. As the submitter notes, there is another demangler, written in C++, in ext/demangle.h. That demangler has many more features. For more general C++ usage, that is the demangler to use. The submitter says there is some problem with it, but in my (limited) experience it works fine. In closing, I repeat that I think that the API is broken, but I have had very limited response in my comments about this or about other broken aspects of the mangling scheme in general.
This original poster seems to be directed back to the ext/demangle.h which is asserted to be usable. So I'll file a new report on that. Ivan
*** Bug 19284 has been marked as a duplicate of this bug. ***