This is an archive of the discontinued LLVM Phabricator instance.

[libc++][NFC] Inline the definition of ~basic_ios()
AbandonedPublic

Authored by ayzhao on May 31 2022, 5:52 PM.

Details

Reviewers
thakis
hans
philnik
ldionne
Group Reviewers
Restricted Project
Summary

This is causing ODR violations in Chrome that is preventing it from
being built with libc++ debug symbols and ThinLTO[0].

[0]: https://crbug.com/1327706#c13

Diff Detail

Event Timeline

ayzhao created this revision.May 31 2022, 5:52 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 31 2022, 5:52 PM
ayzhao requested review of this revision.May 31 2022, 5:52 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 31 2022, 5:52 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript
ayzhao added a reviewer: hans.May 31 2022, 5:55 PM
ayzhao added inline comments.
libcxx/include/ios
696–697

I'm not sure if I should specify _LIBCPP_INLINE_VISIBILITY here - does anyone have any ideas?

jloser added a subscriber: jloser.May 31 2022, 5:56 PM
jloser added inline comments.
libcxx/include/ios
696–697

Should we use inline _LIBCPP_INLINE_VISIBILITY instead like the neighboring code currently does?

jloser added inline comments.May 31 2022, 6:00 PM
libcxx/include/ios
696–697

So, _LIBCPP_INLINE_VISIBILITY is a historical predecessor to _LIBCPP_HIDE_FROM_ABI. In newer code, we've been updating to _LIBCPP_HIDE_FROM_ABI.

With that being said, we definitely want inline there and also either _LIBCPP_HIDE_FROM_ABI or _LIBCPP_INLINE_VISIBILITY. There's an argument to be made for both. Using _LIBCPP_HIDE_FROM_ABI is the "new de-facto standard", whereas the latter is locally consistent in this neighborhood of code. I don't feel strongly.

It's a bit surprising this destructor wasn't hidden from being an exported symbol in the ABI!

ayzhao updated this revision to Diff 433255.May 31 2022, 6:05 PM

add _LIBCPP_INLINE_VISIBILITY

ayzhao marked 2 inline comments as done.May 31 2022, 6:06 PM
philnik added a subscriber: philnik.Jun 1 2022, 1:07 AM
philnik added inline comments.
libcxx/include/ios
696–697

I think nobody would have a problem if we just remove the out-of-line definition and change line 642 to _LIBCPP_HIDE_FROM_ABI virtual ~basic_ios() = default;. I think it should be fine to make it = default, because all copy- and move constructors are deleted.

ayzhao updated this revision to Diff 433430.Jun 1 2022, 9:30 AM

default destructor

ayzhao retitled this revision from [libc++][NFC] Mark the definition of ~basic_ios::basic_ios() as inline to [libc++][NFC] Inline the definition of ~basic_ios().Jun 1 2022, 9:30 AM
ayzhao marked an inline comment as done.
philnik accepted this revision as: philnik.Jun 1 2022, 9:35 AM

LGTM assuming CI passes, but please wait for a second #libc reviewer before landing the patch.

LGTM assuming CI passes, but please wait for a second #libc reviewer before landing the patch.

I'm pretty sure CI is going to fail during check-cxx-abilist.

As-is, this patch is an ABI break for any user of iostream because it removes std::__1::basic_ios<wchar_t, std::__1::char_traits<wchar_t> >::~basic_ios() and std::__1::basic_ios<char, std::__1::char_traits<char> >::~basic_ios() from the dylib. Furthermore, I believe there was probably an intent of this destructor acting as a key function so that the vtable and RTTI of basic_ios<char|wchar_t> ends up in the dylib, and in the dylib only. I'm not 100% sure about that, but that's the most likely explanation for this strange definition in the first place.

After reading https://crbug.com/1327706#c13, it seems like the issue comes up when enabling libc++'s debug mode, right? If so, then I think this must be tackled via D122941 or something like it, instead.

ldionne requested changes to this revision.Jun 1 2022, 10:54 AM

(requesting changes until I have more info)

This revision now requires changes to proceed.Jun 1 2022, 10:54 AM
EricWF added a subscriber: EricWF.Jun 3 2022, 10:36 AM
This comment was removed by EricWF.

(requesting changes until I have more info)

I would also like to ensure that we're not inlining the key function. It seems less than ideal to emit the vtable inline in every TU.

Is there a reason -Wweak-vtables isn't enabled?

ayzhao added a subscriber: cjdb.Jun 3 2022, 1:20 PM
ayzhao added a comment.Jun 3 2022, 1:23 PM

LGTM assuming CI passes, but please wait for a second #libc reviewer before landing the patch.

I'm pretty sure CI is going to fail during check-cxx-abilist.

As-is, this patch is an ABI break for any user of iostream because it removes std::__1::basic_ios<wchar_t, std::__1::char_traits<wchar_t> >::~basic_ios() and std::__1::basic_ios<char, std::__1::char_traits<char> >::~basic_ios() from the dylib. Furthermore, I believe there was probably an intent of this destructor acting as a key function so that the vtable and RTTI of basic_ios<char|wchar_t> ends up in the dylib, and in the dylib only. I'm not 100% sure about that, but that's the most likely explanation for this strange definition in the first place.

After reading https://crbug.com/1327706#c13, it seems like the issue comes up when enabling libc++'s debug mode, right? If so, then I think this must be tackled via D122941 or something like it, instead.

I spoke with cjdb@ offline and it seems that we can maintain ABI compatibility by defining an empty destructor (i.e. ~basic_ios() {}) instead of using = default: https://godbolt.org/z/r73v1oE6n. WDYT?

I spoke with cjdb@ offline and it seems that we can maintain ABI compatibility by defining an empty destructor (i.e. ~basic_ios() {}) instead of using = default: https://godbolt.org/z/r73v1oE6n. WDYT?

The problem isn't the triviality of basic_ios. The problem is that there isn't a key function anymore, so the vtable and destructor aren't emitted in the dylib anymore.

ayzhao added a comment.Jun 6 2022, 9:39 AM

I spoke with cjdb@ offline and it seems that we can maintain ABI compatibility by defining an empty destructor (i.e. ~basic_ios() {}) instead of using = default: https://godbolt.org/z/r73v1oE6n. WDYT?

The problem isn't the triviality of basic_ios. The problem is that there isn't a key function anymore, so the vtable and destructor aren't emitted in the dylib anymore.

Apologies for the dumb question, but could we resolve the issue by moving the definition of the destructor to ios.cpp? The destructor would still be a key function, and this should resolve the ODR issue.

ayzhao added a comment.Jun 6 2022, 9:46 AM

I spoke with cjdb@ offline and it seems that we can maintain ABI compatibility by defining an empty destructor (i.e. ~basic_ios() {}) instead of using = default: https://godbolt.org/z/r73v1oE6n. WDYT?

The problem isn't the triviality of basic_ios. The problem is that there isn't a key function anymore, so the vtable and destructor aren't emitted in the dylib anymore.

Apologies for the dumb question, but could we resolve the issue by moving the definition of the destructor to ios.cpp? The destructor would still be a key function, and this should resolve the ODR issue.

NVM, I just realized that this isn't possible because of the template parameters.

@ayzhao I think using virtual ~basic_ios() {} should work. I think I'm missing something in how [[gnu::visibility("hidden")]], [[clang::exclude_from_explicit_instantiation]] and = default interact. Sorry for the confusion.

ayzhao updated this revision to Diff 434933.Jun 7 2022, 1:31 PM

Try an empty destructor instead of = default

ayzhao added a comment.Jun 7 2022, 1:32 PM

@ayzhao I think using virtual ~basic_ios() {} should work. I think I'm missing something in how [[gnu::visibility("hidden")]], [[clang::exclude_from_explicit_instantiation]] and = default interact. Sorry for the confusion.

Done. Let's see what happens with the CI

I just landed D122941 -- I think you should check whether this is still an issue for you.

ayzhao added a comment.Jun 7 2022, 1:58 PM

I just landed D122941 -- I think you should check whether this is still an issue for you.

So far, your patch does seem to work, but I'll need to wait to see if our bots are green when we roll libc++. Thanks!

I just landed D122941 -- I think you should check whether this is still an issue for you.

So far, your patch does seem to work, but I'll need to wait to see if our bots are green when we roll libc++. Thanks!

Any news? If it works, let's abandon this patch to clear the review queue.

ayzhao abandoned this revision.Jun 21 2022, 1:05 PM

I just landed D122941 -- I think you should check whether this is still an issue for you.

So far, your patch does seem to work, but I'll need to wait to see if our bots are green when we roll libc++. Thanks!

Any news? If it works, let's abandon this patch to clear the review queue.

I'll abandon this patch.