[cfe-dev] _LIBCPP_INLINE_VISIBILITY and std::string::length

John McCall rjmccall at apple.com
Fri Mar 8 13:05:25 PST 2013

On Mar 8, 2013, at 12:18 PM, Howard Hinnant <hhinnant at apple.com> wrote:
> On Mar 8, 2013, at 2:09 PM, Alexey Kudinkin <alexey.kudinkin at gmail.com> wrote:
>> Hello!
>> I'm just curious about what are the reasons to forcing inlining of that sort of functions like std::string::length? Precluding them to be included into libc++ binary breaks linkage of the following snippet of code 
>>> int main(int ARGC, char *ARGV[])() {
>>>  std::vector<std::string>  pray = { "I", "will", "not", "aim", "for", "the", "head" };
>>>  std::vector<size_t>       lengths;
>>>  std::transform(pray.begin(), pray.end(), std::back_inserter(lengths), std::mem_fn(&std::string::size));

For what it's worth, IIRC this code is not required to work, because you are not generally allowed to take the address of functions from the standard library.

> I believe this is due to a poor interaction in the compiler between extern templates and __attribute__ ((__always_inline__)).  If std::string is not declared extern template, then the compiler will outline a size() member and you won't get this link error.

always_inline doesn't stop the dylib from exporting that function symbol.  It's the hidden visibility that does that.

> In my opinion, clang should not assume that extern templates have definitions for inlined members, especially those marked always_inline, and the fact that it does is a clang bug resulting in the link error you see.

Every member of a class template is implicitly inline.  We are not going to completely break explicit instantiation declarations.

We do already treat always_inline as a special case, and I'm not sure why it's not applying here.  That does seem like a bug.

> The rationale for the use of always_inline in libc++ is to control the ABI of libc++.  In the past I have watched compilers use different heuristics from release to release on making the inline/outline decision.  This can cause code to be silently added to and removed from a dylib.  With the use of always_inline, I am telling the compiler to never add that code to the libc++.dylib binary.

This is an incredibly brute-force way of accomplishing this goal, and it causes major problems downstream, e.g. with debugging programs that use libc++.

Have you considered only explicitly instantiating the functions you actually want to show up in the library instead of explicitly instantiating the entire class?


More information about the cfe-dev mailing list