https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000
--- Comment #6 from Nikolas Klauser <nikolasklauser at berlin dot de> --- (In reply to Florian Weimer from comment #5) > How hard is this to use in practice? With current Clang, this: > > “ > template <class T> > class S { > __attribute__ ((visibility ("hidden"), > exclude_from_explicit_instantiation)) > int f1 (); > int f2 (); > }; > > template <class T> int > S<T>::f1 () > { > return 1; > } > > template <class T> int > S<T>::f2 () > { > return f1 (); > } > > template class S<int>; > ” > > still inlines S<int>::f1 into S<int>::f2. This may not threaten future > evolution of the implementation in this particular case, but it would > certainly be helpful to have some guides similar to > <https://community.kde.org/Policies/ > Binary_Compatibility_Issues_With_C%2B%2B>. Clang's attribute documentation > describes what happens, but it doesn't comment on the actual implications > for ABI compatibility. It doesn't have any inherent implications on ABI compatibility. Without other tricks you still have to stay ABI compatible between versions of your function. Some of the options are - always inlining (this doesn't require the new attribute, but has numerous drawbacks) - making the functions have internal linkage (this would require the new attribute, but note that clang's `internal_linkage` attribute seems to do this implicitly) - changing the mangling of the function whenever you change the ABI (this is what libc++ currently does, through `abi_tag`s which change with every release) I'm sure there are other ways to achieve this. These are the ways libc++ achieved this throughout it's history (that I know of). There might be better ways, but the only problem with the current approach I am aware of is that the ABI tag adds a few extra bytes per symbol. Compared to always inlining or having one instance of a function per translation unit, that solution seems pretty good to me. Essentially, to be able to do anything with a function you want, you have to add `__attribute__((visibility("hidden"), exclude_from_explicit_instantiation, abi_tag("some-versioning-scheme")))`, where - `visibility("hidden")` is to avoid exporting the symbol from any libraries - `exclude_from_explicit_instantiation` is to avoid problems when users try to explicitly instantiate a class template (or you want to provide an explicit instantiation, but only some functions should be part of the ABI) and - `abi_tag` is to avoid problems when users compile their code with different versions of the library (essentially duplicating functions which may not be ABI compatible) Does that make sense?