Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix empty_value MSVC bug #175

Merged
merged 4 commits into from
Jul 12, 2024

Conversation

k3DW
Copy link
Contributor

@k3DW k3DW commented Jun 19, 2024

See unordered#257.

Is this a breaking change in Core? It doesn't break any tests, but is it conceptually wrong?

@mglisse
Copy link

mglisse commented Jun 22, 2024

(thank you for working on this. Just a user's comments below)

Is this a breaking change in Core?

I think so. As broken as the permission model is in C++ (private things are traps instead of being invisible), there are still some cases where SFINAE can ignore private things, that work with the current code and would be broken with public inheritance.

is it conceptually wrong?

Again, I think so. It may still be worth it if the bug it works around is worse than what this breaks (I have no idea how to measure that), but if this change is done, in my opinion it should be protected by something like BOOST_WORKAROUND(BOOST_MSVC, ...) with a link to the bug report on Microsoft's website.

On recent compilers, a simpler implementation of empty_value based on (msvc::)no_unique_address could also be considered.

@pdimov
Copy link
Member

pdimov commented Jun 22, 2024

On recent compilers, a simpler implementation of empty_value based on (msvc::)no_unique_address could also be considered.

This sounds like the best course of action here.

@k3DW
Copy link
Contributor Author

k3DW commented Jun 23, 2024

On recent compilers, a simpler implementation of empty_value based on (msvc::)no_unique_address could also be considered.

This sounds like the best course of action here.

I'm not sure how far back this problem goes on MSVC. On 16.0, the oldest available version on Compiler Explorer right now, the issue reproduces.

That said, how would this be implemented using [[msvc::no_unique_address]]? Usages of empty_value rely on EBO, which is transitive through inheritance. Anything using NUA isn't transitive. CE link

I can't find any documentation for when [[msvc::no_unique_address]] was introduced. This attribute doesn't work in MSVC 16.8, but it starts working in MSVC 16.9. We need this fixed earlier than 16.8, so I don't think we can use NUA here.

@pdimov
Copy link
Member

pdimov commented Jun 23, 2024

[[no_unique_address]] works for the same example under Clang and GCC: https://godbolt.org/z/PzqreT8Eb
But we need it for MSVC, which is exactly where it doesn't. :-)

@Lastique
Copy link
Member

Lastique commented Jun 24, 2024

Was this bug reported to MSVC devs? If not, please do.

As to this PR, I think, this is a better workaround. [[no_unique_address]] is not worth it. And not the right way to go anyway, as compilers are allowed to ignore/not support attributes, while EBO is a requirement.

@k3DW k3DW force-pushed the feature/empty-value-inherit-public branch from 54096b8 to 42b199c Compare June 24, 2024 04:32
@k3DW k3DW changed the title Inherit publicly in empty_value to work around MSVC bug Fix empty_value MSVC bug Jun 24, 2024
@k3DW k3DW force-pushed the feature/empty-value-inherit-public branch from 42b199c to 17a16d6 Compare June 24, 2024 04:34
@mglisse
Copy link

mglisse commented Jun 24, 2024

That said, how would this be implemented using [[msvc::no_unique_address]]? Usages of empty_value rely on EBO, which is transitive through inheritance. Anything using NUA isn't transitive. CE link

🤯 The whole point of NUA is to replace EBO, and MSVC managed to fail...

Actually, msvc::no_unique_address is a failure, but there may still be a bit of hope for the real no_unique_address if we complain enough (report 1, report 2) before the next ABI break in MSVC 🤞

@k3DW k3DW force-pushed the feature/empty-value-inherit-public branch from 17a16d6 to 4570d1a Compare June 24, 2024 18:15
@Lastique
Copy link
Member

Thanks. Looks ok to me.

@k3DW
Copy link
Contributor Author

k3DW commented Jun 25, 2024

Thanks. Looks ok to me.

Great thanks

Was this bug reported to MSVC devs? If not, please do.

Got it, here is the bug report. It seems like it's been around for a while, so I'm not holding out hope that it'll get fixed any time soon. But at least we were able to get a workaround

@Lastique
Copy link
Member

Lastique commented Jun 25, 2024

Was this bug reported to MSVC devs? If not, please do.

Got it, here is the bug report.

Please, add a short description and a link to the bug in a comment near #if defined(BOOST_MSVC) and the new test_derived_compile test.

It seems like it's been around for a while, so I'm not holding out hope that it'll get fixed any time soon.

If it's not been reported before, it is likely it wasn't known to the MSVC devs, which is why it wasn't fixed and why it needed to be reported. I don't expect it to be immediately fixed, but it will be, eventually.

@joaquintides
Copy link
Member

Reminder that we should merge this fix before the Boost 1.86 release window closes. Thank you!

@pdimov
Copy link
Member

pdimov commented Jul 8, 2024

@glenfe ?

@k3DW k3DW force-pushed the feature/empty-value-inherit-public branch from c5cf950 to acbeaae Compare July 11, 2024 22:02
@glenfe glenfe merged commit 83a3a51 into boostorg:develop Jul 12, 2024
66 of 67 checks passed
@k3DW k3DW deleted the feature/empty-value-inherit-public branch July 12, 2024 19:24
@ashtum
Copy link
Contributor

ashtum commented Jul 13, 2024

The following issue has arisen due to a conflict with the new private type alias base introduced recently:

#include <boost/core/empty_value.hpp>
#include <memory>

struct A : boost::empty_value<std::allocator<void>>
{
};

using base = A;

struct B : base
{
  B()
    : base{}
  {
  }
};
Error (active)	E0265	type "boost::empty_::empty_value<T, N, true>::base [with T=std::allocator<void>, N=0U]" (declared at line 141 of "C:\Users\win\Desktop\boost\boost\core\empty_value.hpp") is inaccessible	

@pdimov
Copy link
Member

pdimov commented Jul 13, 2024

This can be fixed by renaming empty_value<..>::base to something less likely to cause conflicts, such as e.g. core_ev_base.

@ashtum
Copy link
Contributor

ashtum commented Jul 16, 2024

242b14b broke Boost.Beast again. I can rename the typedefs in Beast, but I guess base_type is quite a common name used by other users as well: https://github.com/boostorg/beast/blob/develop/test/beast/core/async_base.cpp#L677

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants