heretoinfinity
heretoinfinity

Reputation: 1746

Any way of getting more info from c++filt demangled output

I just ran c++filt to demangle when I had a duplicate symbol error:

$ c++filt __ZN4uiuclsERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEERKNS_5StackE

uiuc::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, uiuc::Stack const&)

but the actual function looks like this [within the uiuc namespace]:

std::ostream & operator<<(std::ostream & os, const Stack & stack)

How can I get the demangled output to

  1. show the return type: std::ostream &
  2. show std::ostream instead of std::__1::basic_ostream<char, std::__1::char_traits<char> >&. There is the __ right after std:: that I don't get and the template-like input. Is ostream implemented as a template?

I ask because there are other return turn types that I won't be able to easily map. I am dealing with a small file for practice.

I am running on macOS and tried the different c++filt --format options for the compiler but didn't see any that gave me a different output.

Upvotes: 1

Views: 168

Answers (1)

walnut
walnut

Reputation: 22162

  1. show the return type: std::ostream &

Return types of ordinary functions are not part of their signature or their mangled name. There is no way to obtain the return type from a mangled name. To do this you need to lookup the header file which declares the function.

This is different for function templates, though.

  1. show std::ostream instead of std::__1::basic_ostream<char, std::__1::char_traits<char> >&. There is the __ right after std:: that I don't get and the template-like input. Is ostream implemented as a template?

The standard defines that std::ostream is a type alias for std::basic_ostream<char, std::char_traits<char>>, which is a template specialization of the class template std::basic_ostream. There are specializations of this for every character type that the stream could use, e.g. std::basic_ostream<wchar_t, std::char_traits<wchar_t>> (aliased as std::wostream) for wide character streams.

Type aliases are resolved during compilation to the actual type name they refer to, so the mangled name does not contain any information about the alias that was used in the declaration. It would also make no sense to have a differentiation, because the function should be the same, no matter what alias was used, so the symbol name cannot differ on it.

You could in principle run a search-and-replace for the standard library's common aliases. I don't know any tool that does that at the top of my head. You get used to the non-alias names quickly anyway.

::__1 is an inline namespace used by the standard library to be able to define multiple versions of standard library symbols transparently. Names in the inline namespace can be looked up as if they were declared in the enclosing namespace, so when you use e.g. std::ostream, the library may actually declare ostream not in the std namespace, but in std::__1, which will still be found if __1 is an inline namespace.

This is an implementation detail that you should simply ignore. The double underscore in the name is a good indicator that it is an implementation detail that you don't need to care about, because identifiers with a double underscore are reserved for use by the language implementation.

Again, you could probably search-and-replace such inline namespaces from the standard library namespace, but I am not aware whether any tool does that and again, one gets used to it quickly.

Upvotes: 1

Related Questions