+cfe-dev, bcc:llvm-dev (added back the wrong list I think?)
The status quo isn't "linkonce_odr + visibility_hidden". The status quo is "linkonce_odr + visibility_hidden + always_inline". I guess you're suggesting removing the always_inline?
I believe the "always_inline" is protecting against some objects being built separately from (and with a slightly different libc++ than) others, which is common in the case of static archives. Using "internal" gives the same protection.
Aside from address-taken functions (where the address of functions will depend on the translation unit, instead of causing a link error
By splitting _LIBCPP_INLINE_VISIBILITY, I think we can work around this.
1. Leave _LIBCPP_INLINE_VISIBILITY unchanged.
2. #define _LIBCPP_INTERNAL_VISIBILITY __attribute__((internal_linkage))
3. Leave externally callable free functions marked with _LIBCPP_INLINE_VISIBILITY (no change). These functions rarely have significant code.
4. Change non-external API (i.e., starting with `__`) to use _LIBCPP_INTERNAL_VISIBILITY.
- Now the external API calls are the same as the status quo (always_inline + hidden). If you don't take their address, they'll (most likely) be inlined. If you do take their address, they'll get coalesced and address comparisons will work within the same linkage-unit.
- The internal functions will only get inlined if the optimizer thinks it's a good idea. Taking their address from two different translation units will give you a different answer... but users aren't allowed to call internal API anyway.
- Assuming an all-knowing, benevolent inliner, code size and performance should strictly improve over the status quo, with no C++ fragility regressions.
- We can consider, as a follow-up, replacing all uses of _LIBCPP_INLINE_VISIBILITY with _LIBCPP_HIDDEN_VISIBILITY. (I.e., do we need "always_inline" on external API? Or do we just need to protect against C++ fragility of internal functions?)
- If that follow-up is rejected, then: if an external API function is non-trivial, we can change it to a wrapper of an internal function to effectively outline it.
- Long term, if an internal function is never inlined because of large code size (and a copy-per-translation unit is big), we can consider designing a stable interface and moving it to the dylib. Also, we can try to convince linker/object-file owners to de-dup `local_unnamed_addr` functions with internal linkage.