solaris-specific mangling for g++ compat

Greetings folks,

I just filed a bug on clang mangling:
  https://bugs.llvm.org/show_bug.cgi?id=33767

which is not clang's bug per se, but rather a bug-incompatibility
with gcc on Solaris (more details in bug report).

gcc deliberately chose to diverge from mangling as specified by C++ ABI
in order to keep binary compatibility
(see Rainer Orth - [c++] Keep tm, div_t, ldiv_t, lconv mangling on Solaris (PR libstdc++-v3
for discussion of that patch).

When clang on Solaris links with libstdc++ this binary compatibility
issue kicks in.

I wonder would the patch doing Solaris-only hack to the mangling
to maintain gcc binary compatibility be welcome here?
Unconditionally or under some flag?

regards,
  Fedor.

So, uh, why did solaris’s stdlib.h header move these four types in the first place? It sounds like there was some code in the system header that conditionally put them into either the global namespace, or into the std namespace, dependent on the value of __cplusplus, yet all C++ compilers ever used on solaris were setting __cplusplus to the version where they were in the global namespace.

So…I’m rather confused, then, as to why this mangling change was made in gcc in the first place, instead of just modifying the system header to not do that. Surely it’d have been saner to move the definitions back to the global namespace unconditionally? (And, I think that could even still be done?)

For comparison, on linux glibc, tm, div_t, ldiv_t, and lconv are all just defined in :: and imported into std:: with using…

So, uh, why did solaris's stdlib.h header move these four types in the first
place? It sounds like there was some code in the system header that
conditionally put them into either the global namespace, or into the std
namespace, dependent on the value of __cplusplus, yet all C++ compilers ever
used on solaris were setting __cplusplus to the version where they were in the
global namespace.
So...I'm rather confused, then, as to why this mangling change was made in gcc
in the first place, instead of just modifying the system header to not do
that. Surely it'd have been saner to move the definitions back to the global
namespace unconditionally? (And, I think that could even still be done?)

I really have no idea on what the full story was.
Probably Rainer can shed some light as he was quite involved in that discussion
(see Rainer Orth - [c++] Keep tm, div_t, ldiv_t, lconv mangling on Solaris (PR libstdc++-v3)

I was rather surprised to learn about this strange solution
when I hit it with Oracle Studio compiler couple years ago.

For comparison, on linux glibc, tm, div_t, ldiv_t, and lconv are all just
defined in :: and imported into std:: with using...

I'm going to ask around in Solaris, but if we ever manage to fix it in future Solaris versions,
headers on older ones will still trigger this incompatibility. :frowning:

regards,
  Fedor.

> So, uh, why did solaris's stdlib.h header move these four types in the first
> place? It sounds like there was some code in the system header that
> conditionally put them into either the global namespace, or into the std
> namespace, dependent on the value of __cplusplus, yet all C++ compilers ever
> used on solaris were setting __cplusplus to the version where they were in the
> global namespace.
> So...I'm rather confused, then, as to why this mangling change was made in gcc
> in the first place, instead of just modifying the system header to not do
> that. Surely it'd have been saner to move the definitions back to the global
> namespace unconditionally? (And, I think that could even still be done?)

I really have no idea on what the full story was.
Probably Rainer can shed some light as he was quite involved in that discussion
(see Rainer Orth - [c++] Keep tm, div_t, ldiv_t, lconv mangling on Solaris (PR libstdc++-v3)

Well, Rainer seems to be on vacation...

I was rather surprised to learn about this strange solution
when I hit it with Oracle Studio compiler couple years ago.

> For comparison, on linux glibc, tm, div_t, ldiv_t, and lconv are all just
> defined in :: and imported into std:: with using...

I'm going to ask around in Solaris, but if we ever manage to fix it in future Solaris versions,
headers on older ones will still trigger this incompatibility. :frowning:

Fixing this issue in the headers appears to be more problematic than it seems.
Solaris headers have to support both GCC and Studio C++ compilers, and as you might imagine
fixing for g++ (bringing, say, struct tm from std into global) will break Studio C++
mangling pretty much in the same manner.

And adding conditional guards that differentiate between ABIs into the headers would
just move the mess from compilers into the headers.

So given the status quo, I dont see a way for a clean solution when adding one more compiler
to the equation (Clang).

For now as my task is to get a functional Clang/LLVM on Solaris I would rather go with adding
a gcc'ish change to Clang's ItaniumMangle.cpp and then try to sort out that mess in Solaris headers
so at some time later it would be possible to phase this hack out.

regards,
  Fedor.