The C++ ABI used by POSIX is the Itanium C++ ABI.
Reference document available here: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
One important (and tricky) part of the ABI is the substitutions being done,
in order to reduce the bloat introduced by long symbol names,
a typical issue when using templates heavily (of which D was not exempt).
There are 2 kinds of substitutions: component substitution and template parameter substitution.
Component substitution replaces repeated parts of the symbol with `S[X]_`,
template parameter substitution replaces occurences of template parameters with `T[X]_`.
`X` represents a base36 index into the array of components or
template parameters already encountered so far, respectively.
This substitution is done on an identity basis, which means that the templated function
`template<typename T> int foo()` instantiated with `int` will be mangled as `_Z3fooIiE*i*v`
(asterisks are emphasis and not part of the mangling) while it would be mangled as `_Z3fooIiE*T_*v`
if the definition was `template<typename T> T foo()`.
Moreover, experience with C++ compilers shows that component substitution is prefered over
template parameter substitution, such as `template<typename T> T foo(T)` is mangled as
`_Z3fooIiET_*S0_*` when instantiated with `int` and not `_Z3fooIiET_*T_*` as would be the case
if template substitution was prefered.
This is just brushing the surface of the problem, since only template type parameters have been
mentioned so far, but other kind (aliases, values) are also concerned.
Substitution also needs to happen if a template parameter is part of another type,
such as the `template<typename T> array<T>* foo (T, int)`, which, when instantiated with `int`,
is mangled as `_Z3fooIiEP5arrayIT_ES1_i`.
For more detailed test cases, see `test/compilable/cppmangle.d`.
The main issue encountered while implementing this in DMD is that there's no easy way to know
if a type (which is part of the function's type, e.g. parameters and return value)
was a template parameter or not, as DMD merges types, so in the previously mentioned
`template<typename T> int foo()` vs `template<typename T> T foo()` the template instantiation
will come with the same exact two pointer to the singleton `int` type.
Moreover, DMD does destructive semantic analysis, meaning that objects gets mutated,
pointers get replaced, aliases get resolved, and information gets lost.
After different approaches where taken, the most practical and reliable approach devised was to
provide a `visit` overload for non-resolved AST type `TypeIdentifier` and `TypeInstance`,
and compare the identifier to that of the template definition.
Fallback to post-semantic type when it isn't found.
Note that no attempt has been made whatsoever to handle the mess that would result from
expressions themselves being mangled. The reference doc for the ABI mentions that
"[...] this mangling is quite similar to the source token stream. (C++ Standard reference 14.5.5.1p5.)".
Original quote:
https://itanium-cxx-abi.github.io/cxx-abi/abi.html#expressions (5.1.6 Expressions)
DMD was just comparing the object by their reference instead of their string value.
Obviously when a namespace is declared in another module, the reference is different.
1. Removed ABI name fiddling from the front-end.
2. Removed `Target.prefixName` and C++ tests for matching `__Z`.
3. Prepend prefixes for C++ and D symbols in the backend only
for the targets that require it (Win32, OSX).
4. Removed `RTLSYM__DINVARIANT` runtime library symbol, name is now
the same on all targets.
5. Correctly set C++ mangling on `LINK.cpp` symbols, before they
were all being set as D mangled symbols.
6. Use System mangling as synonym for do not modify symbol.
7. Added workaround for `extern(D) ___tls_get_addr`.