This is an archive of the discontinued LLVM Phabricator instance.

Fix EBO on std::optional and std::variant when targeting the MSVC ABI
ClosedPublic

Authored by davidben on Mar 15 2023, 8:54 PM.

Details

Reviewers
jdoerrie
ldionne
EricWF
philnik
Mordante
Group Reviewers
Restricted Project
Summary

Patch originally by Jan Dörrie in https://reviews.llvm.org/D120064. I've just updated it to include tests, and update documentation that MSVC ABI is not stable.

In the current implementation both std::optional and std::variant don't perform the EBO on MSVC's ABI. This is because both classes inherit from multiple empty base classes, which breaks the EBO for MSVC. This patch fixes this issue by applying the empty_bases declspec attribute, which is already used to fix a similar issue for std::tuple.

See https://reviews.llvm.org/D120064 for discussion on MSVC ABI stability. From the discussion, libc++ doesn't have users that expect a stable ABI on MSVC. The fix is thus applied unconditionally to benefit more users. Documentation has been updated to reflect this.

Fixes https://github.com/llvm/llvm-project/issues/61095.

Diff Detail

Event Timeline

davidben created this revision.Mar 15 2023, 8:54 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2023, 8:54 PM
davidben requested review of this revision.Mar 15 2023, 8:54 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2023, 8:54 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript

Thanks for the patch!

I'm not really fond of declaring the MSVC ABI as unstable. If there is no other way, please add this information in the commit message. That way we can find back why it was decided to declare the ABI on a platform as unstable.

libcxx/include/optional
641

Why not guard this attribute with a _LIBCPP_ABI_FOO_FLAG instead of breaking the ABI unconditionally?

I'm not really fond of declaring the MSVC ABI as unstable. If there is no other way, please add this information in the commit message. That way we can find back why it was decided to declare the ABI on a platform as unstable.

FWIW, treating the libc++ ABI as unstable in MSVC environments has been considered a couple times before, but without formally spelling it out like this. See e.g. D134912 where we’d be more or less agreed upon the same already (even if that change hasn’t been landed yet).

Happy to do this however you all think is appropriate. I was just basing this on the discussion in https://reviews.llvm.org/D120064, which suggested folks preferred treating the MSVC ABI as unstable. (I'll update the description to link to the discussion.)

davidben edited the summary of this revision. (Show Details)Mar 16 2023, 2:24 PM
EricWF accepted this revision as: EricWF.Mar 17 2023, 2:35 PM
EricWF added a subscriber: EricWF.
EricWF added inline comments.
libcxx/include/optional
641

Because that would prevent most users from ever getting value from it.

If we don't have any libc++ users who care about ABI compatibility with MSVC, then we should do this unconditionally.

davidben added inline comments.Mar 19 2023, 7:08 PM
libcxx/include/optional
641

Unconditional is also my preference, but I'll do whatever the project prefers. Currently assuming that's to leave it at is. (What's the process for driving that question to a conclusion?)

Since @EricWF feels this is fine for Windows I don't have objections either. However I really feel we need to document this better.

libcxx/include/optional
641

When that is the rationale for forcing an ABI break on all Windows users, then let's document that in the commit message.

I think it would be good to add this rationale to the index.rst, since this is against the normal libc++ policy. I really want to avoid people thinking an unstable ABI is acceptable on all platforms.

libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
81

This is not needed in C++17, the same for the static_asserts below.

davidben updated this revision to Diff 507170.Mar 21 2023, 4:15 PM
davidben edited the summary of this revision. (Show Details)

Address review comments

davidben added inline comments.Mar 21 2023, 4:17 PM
libcxx/include/optional
641

Updated the commit message.

Couldn't find a good place to work it into index.rst, as it doesn't talk about ABI much in the first place, but I added a paragraph to ABIVersioning.rst. This what you had in mind?

libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
81

Done. I've left the existing instances in the file alone.

Are folks satisfied with the state of this? What's needed to move forward with this change?

philnik accepted this revision as: philnik.Apr 10 2023, 12:26 PM
philnik added a subscriber: philnik.

LGTM. I'll leave final approval to @Mordante, since he had comments.

EricWF accepted this revision.Apr 10 2023, 1:35 PM

I think this is ready. It LGTM. Lets just get the CI passing.

libcxx/docs/DesignDocs/ABIVersioning.rst
26 ↗(On Diff #507170)

I agree with this. Is there anyway to call it out more prominently?

This revision is now accepted and ready to land.Apr 10 2023, 1:35 PM
philnik requested changes to this revision.Apr 10 2023, 1:38 PM

I think this is ready. It LGTM. Lets just get the CI passing.

Please wait for other people who have already commented. It's really not nice to overrule people like that, and this isn't exactly time sensitive.

This revision now requires changes to proceed.Apr 10 2023, 1:38 PM
philnik accepted this revision as: philnik.Apr 10 2023, 1:38 PM
davidben updated this revision to Diff 512263.Apr 10 2023, 2:30 PM

CI failure seems unrelated. Rebasing (changed test to use std:size_t since it seems you all have started qualifying it) and reuploading in hopes that clears.

davidben added inline comments.Apr 10 2023, 2:32 PM
libcxx/docs/DesignDocs/ABIVersioning.rst
26 ↗(On Diff #507170)

Happy to put it wherever you all like. :-) Any place in particular? I put it in index.rst, with the supported platforms, and this file, which talks about ABI considerations, since those seemed the natural places.

EricWF accepted this revision.Apr 10 2023, 3:48 PM

I think this is ready. It LGTM. Lets just get the CI passing.

Please wait for other people who have already commented. It's really not nice to overrule people like that, and this isn't exactly time sensitive.

Which issues are you talking about? They all seem to be resolved. There doesn't appear to be any blockers. If someone want's changes before this proceeds, there's a way to do that.
Otherwise, I feel comfortable that the objections have been addressed and this is ready to land. There's no need to wait.

This revision is now accepted and ready to land.Apr 10 2023, 3:48 PM
philnik requested changes to this revision.Apr 10 2023, 3:59 PM

I think this is ready. It LGTM. Lets just get the CI passing.

Please wait for other people who have already commented. It's really not nice to overrule people like that, and this isn't exactly time sensitive.

Which issues are you talking about? They all seem to be resolved. There doesn't appear to be any blockers. If someone want's changes before this proceeds, there's a way to do that.
Otherwise, I feel comfortable that the objections have been addressed and this is ready to land. There's no need to wait.

In https://reviews.llvm.org/D146190#inline-1415505 Mark voiced concerns about the documentation and he didn't have a look whether the extended documentation suffices. That's why I'd like him to have a look. While I consider them to be resolved, I think there is nothing wrong with waiting a few days until he had a look. Again, there is no need to get this in as soon as possible.

This revision now requires changes to proceed.Apr 10 2023, 3:59 PM

@philnik I believe your actions here are unbecoming. I would ask you to reconsider the way you interact in the community.

Re a few days, I added more notes to the documentation March 21st, which was about three weeks ago. :-) Also the original patch is over a year old now.

Anyway, I'm happy to tweak this however folks prefer, but I'd need to know your preferences to do that. If folks are agreed on the direction and it's just documentation, I'm also happy to upload a follow-up patch to make further documentation changes if feedback comes in after the change lands.

Timing-wise, this is a blocker for us using libc++'s std::variant and std::optional in Chromium. Right now we're using the Abseil polyfills, and I'm interested in moving to the STL implementation. We also have some code we're looking to extract into a standalone library with fewer dependencies, so STL types are ideal. But without this issue fixed, the libc++ types aren't usable for us, which leaves us in a bind.

EricWF accepted this revision.Apr 11 2023, 12:06 PM

OK, lets try this again. Hopefully with cooler heads.

I've reviewed the LLVM code review guidance, and am comfortable that moving forward with this change today falls well within them.
@Mordante Feel free to leave additional feedback, and we'll make sure it's address post-commit.

philnik accepted this revision.Apr 12 2023, 8:40 AM

Re a few days, I added more notes to the documentation March 21st, which was about three weeks ago. :-) Also the original patch is over a year old now.

It's easy to sometimes miss a patch. Feel free ping after a week if you don't get feedback (for smaller patches; larger ones unfortunately always take a long time).

Anyway, I'm happy to tweak this however folks prefer, but I'd need to know your preferences to do that. If folks are agreed on the direction and it's just documentation, I'm also happy to upload a follow-up patch to make further documentation changes if feedback comes in after the change lands.

Timing-wise, this is a blocker for us using libc++'s std::variant and std::optional in Chromium. Right now we're using the Abseil polyfills, and I'm interested in moving to the STL implementation. We also have some code we're looking to extract into a standalone library with fewer dependencies, so STL types are ideal. But without this issue fixed, the libc++ types aren't usable for us, which leaves us in a bind.

I'm OK with landing this now if you commit to addressing any feedback Mark might have, since this is actually a blocker for you.

This revision is now accepted and ready to land.Apr 12 2023, 8:40 AM

I'm OK with landing this now if you commit to addressing any feedback Mark might have, since this is actually a blocker for you.

Sure! More than happy to tweak the documentation however you all like. Also happy to tweak the code based on feedback, though my sense is folks were happy with the direction (don't promise ABI for MSVC to avoid gating this on ABI versioning), and the concerns were just about where to say it.

(But if I'm wrong and the project's consensus ends up on using ABI versioning here, happy to sort that out too.)

ldionne accepted this revision.Apr 13 2023, 9:54 AM

Based on the discussion we had in D146190 where we agreed that the ABI on MSVC was not to be considered stable, I think this patch does the right thing. There are a few things I think we can improve in the patch, but the overall goal sounds good to me.

libcxx/test/libcxx/utilities/optional/optional.object/optional_size.pass.cpp
25
libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
67

Can't we always use unsigned char? It would be nice to avoid checking an internal macro like _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION from the test suite if we can.

80
davidben updated this revision to Diff 513380.Apr 13 2023, 3:57 PM

Update bug URL

davidben added inline comments.Apr 13 2023, 3:59 PM
libcxx/test/libcxx/utilities/optional/optional.object/optional_size.pass.cpp
25

Done.

libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp
67

I don't think that works. This is trying to model the expected size of std::variant<T> but, when _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION is unset, the index is unsigned int instead of unsigned char. You all, I gather, couldn't apply the optimization unconditionally due to ABI stability.

This isn't the only place in the file that needs to handle this. See ExpectEqual a few lines up in the file.

80

Done.

A few documentation comments.

libcxx/docs/DesignDocs/ABIVersioning.rst
26 ↗(On Diff #513380)

Can you make this a section MSVC Envirionments to make it slightly more explicit this is MSVC only.

libcxx/docs/index.rst
122

How about making unstable a link to the ABI document explaining why this ABI is unstable?

davidben updated this revision to Diff 514470.Apr 17 2023, 5:16 PM

Documentation tweaks

davidben added inline comments.Apr 17 2023, 5:18 PM
libcxx/docs/DesignDocs/ABIVersioning.rst
26 ↗(On Diff #513380)

Done. Did it in sentence case, rather than title case, to match the heading in the file, though I've noticed files are a bit inconsistent here.

libcxx/docs/index.rst
122

Done. Hopefully I got the syntax right?

Mordante accepted this revision.Apr 18 2023, 11:21 AM

LGTM modulo the documentation issue. Please make sure the CI is green before landing. Note the sanitizers CI is currently broken and the AIX may also be offline. So feel free to ignore errors from these runners.

libcxx/docs/DesignDocs/ABIVersioning.rst
25 ↗(On Diff #514470)
libcxx/docs/index.rst
122
122

Done. Hopefully I got the syntax right?

CI says no. I have two suggestions that I've tested locally this fixes the link.

davidben updated this revision to Diff 514729.Apr 18 2023, 1:37 PM

Fix link

libcxx/docs/index.rst
122

That didn't work (looks like :ref: is for links within a document), but I repro'd it and fixed it. Just was missing the DesignDocs path.

LGTM modulo the documentation issue. Please make sure the CI is green before landing. Note the sanitizers CI is currently broken and the AIX may also be offline. So feel free to ignore errors from these runners.

Ack. Though I don't think I have bits to land things, so I'll need to wait for one of you all to do it anyway. :-)

LGTM modulo the documentation issue. Please make sure the CI is green before landing. Note the sanitizers CI is currently broken and the AIX may also be offline. So feel free to ignore errors from these runners.

Ack. Though I don't think I have bits to land things, so I'll need to wait for one of you all to do it anyway. :-)

Can you provide "your name <your@email.address>" then somebody can commit it on your behalf.

libcxx/docs/index.rst
122

Odd it works for me locally and I have used this in the past. However the CI is happy so no need to change.

LGTM modulo the documentation issue. Please make sure the CI is green before landing. Note the sanitizers CI is currently broken and the AIX may also be offline. So feel free to ignore errors from these runners.

Ack. Though I don't think I have bits to land things, so I'll need to wait for one of you all to do it anyway. :-)

Can you provide "your name <your@email.address>" then somebody can commit it on your behalf.

David Benjamin <davidben@google.com>

Friendly ping