This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Fix wrongly non-inline basic_string::shrink_to_fit
ClosedPublic

Authored by ldionne on Dec 13 2021, 11:23 AM.

Details

Summary

As explained in https://stackoverflow.com/a/70339311/627587, the fact
that shrink_to_fit wasn't defined as inline lead to issues when explicitly
instantiating basic_string. While explicit instantiations are always
somewhat brittle, this one was clearly a bug on our end.

Diff Detail

Event Timeline

ldionne requested review of this revision.Dec 13 2021, 11:23 AM
ldionne created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 13 2021, 11:23 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Quuxplusone added a subscriber: Quuxplusone.
Quuxplusone added inline comments.
libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.explicit_instantiation.sh.cpp
13

FYI, this link isn't reachable from outside Apple. (What ever happened to the rdar:// URL scheme, anyway? :))

Mordante added inline comments.
libcxx/include/string
3287

Just curious but there are more similar functions not marked as inline. Are they also an issue and should they be fixed?
It would be odd if all these functions are "broken".

I wonder whether this is really the proper fix. Looking at include/__string it contains
_Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
But no entry for shrink_to_fit.
Does adding shrink_to_fit to that list solve the issue.

(I didn't look for more omissions in include/__string.)

ldionne marked an inline comment as done.Dec 13 2021, 11:58 AM
ldionne added inline comments.
libcxx/include/string
3287

Just curious but there are more similar functions not marked as inline. Are they also an issue and should they be fixed?

These other non-inline functions are not marked with _LIBCPP_HIDE_FROM_ABI or _LIBCPP_INLINE_VISIBILITY AFAICT. Did you see some that were not inline but had _LIBCPP_HIDE_FROM_ABI?

I wonder whether this is really the proper fix. Looking at include/__string it contains

_Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \

But no entry for shrink_to_fit.

reserve is different, it is not marked with _LIBCPP_HIDE_FROM_ABI, so it doesn't get internal linkage. If we made it _LIBCPP_HIDE_FROM_ABI, we'd have the same issue.

Does adding shrink_to_fit to that list solve the issue?

No it doesn't, since we'd be explicitly instantiating a function with internal linkage, so it wouldn't be available from outside the string.cpp.o TU. And these lists are used only for the char and wchar_t explicit instantiations anyways, so that wouldn't solve Chromium's issue, which is with their own custom char16 type.

libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.explicit_instantiation.sh.cpp
13

Hmm, I was pretty sure this was publicly accessible if you have a developer account? This is supposed to be the public version of the radar link, which is private.

I'd be keen to leave the link there since I think it should be accessible if you have an Apple developer account. If not, it will probably become accessible after the Xcode open beta is done. In all cases, it should be no less accessible than a rdar:// link.

ldionne updated this revision to Diff 394238.Dec 14 2021, 6:45 AM
ldionne marked an inline comment as done.

Switch object files and link flags to fix GCC. GCC's linker is the most ridiculous thing.

ldionne accepted this revision.Dec 14 2021, 8:11 AM
This revision is now accepted and ready to land.Dec 14 2021, 8:11 AM

Cherry-picking this to release/13.x as f3394dc82c20feea943293eda162b5aff2930ac9 since this is affecting open source software.

Mordante added inline comments.Dec 14 2021, 9:01 AM
libcxx/include/string
3287

I see.
The current requirements for when using inline and when not feel quite error-prone.
I wonder whether we need to add a better way to tag these functions. WDYT?

ldionne added inline comments.Dec 14 2021, 9:10 AM
libcxx/include/string
3287

Indeed -- it's completely crazy.

IMO, we want all functions to be inline except when they are explicitly defined in and exported from the shared library. We've been moving towards that by defining functions in their class declarations more and more, and we should slowly keep moving towards that.

Instead of using internal_linkage, we could also look into using an inline namespace that gets bumped with every version of the library. That would reduce code bloat (due to internal_linkage functions being duplicated in each TU) and remove the need for using _LIBCPP_HIDE_FROM_ABI everywhere.