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 error_category regression with Boost.System #3176

Merged
merged 2 commits into from
Oct 26, 2022

Conversation

StephanTLavavej
Copy link
Member

@StephanTLavavej StephanTLavavej commented Oct 25, 2022

Followup to #3139.

Bad kitties jump up on the table where they're not allowed. 😼 Boost.System was a very bad kitty:

https://github.com/boostorg/system/blob/9a6d79b84147854aa919644b56b8553f5a2bedb8/include/boost/system/detail/std_category.hpp#L46-L52

#if defined(_MSC_VER) && defined(_CPPLIB_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000

            // Poking into the protected _Addr member of std::error_category
            // is not a particularly good programming practice, but what can
            // you do

            _Addr = id;

When #3139 fixed error_category's default constructor to be constexpr, it had to change _Addr into a union, breaking this highly non-Standard code in Boost.System. This resulted in widespread breakage in our test team's "Real World Code" suites.

Because Boost is a widely used third-party library, even if we reported this upstream and they were somehow able to avoid doing this, or simply changed their non-Standard code to detect our new error_category and use different non-Standard code, projects throughout the C++ ecosystem would be broken until they updated Boost.

Adjusting the STL's code to continue permitting this non-Standard usage is the least undesirable option here (compared to reverting #3139, refusing to yield, adding an escape hatch, etc.). Notes for these changes:

  • This is adding a public operator= to _Addr_storage, but it and _Addr are still protected, so this is not observable to Standard code.
  • The operator is constexpr to be "transparent", even though Boost doesn't need this.
  • The operator takes uintptr_t also to be transparent, because that's what we store.
  • The operator is noexcept to avoid emitting EH enforcement.

While RWC test coverage would be sufficient, I'm adding a bit of test code in order to more quickly detect any maintenance changes that would break this workaround. The test takes unsigned int because that's what Boost is using.

(To be clear, I love Boost and I've used it for 20 years, but accessing internal data members is problematic for precisely this reason! 😹)

@StephanTLavavej StephanTLavavej added bug Something isn't working high priority Important! labels Oct 25, 2022
@StephanTLavavej StephanTLavavej requested a review from a team as a code owner October 25, 2022 16:39
stl/inc/system_error Outdated Show resolved Hide resolved
Copy link
Contributor

@strega-nil-ms strega-nil-ms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reluctantly approved 😿

@StephanTLavavej StephanTLavavej self-assigned this Oct 25, 2022
@StephanTLavavej
Copy link
Member Author

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit 82837b7 into microsoft:main Oct 26, 2022
@StephanTLavavej StephanTLavavej deleted the fix-boost-system branch October 26, 2022 13:12
@vinniefalco
Copy link

@StephanTLavavej Thank you very much for this fix

@pdimov
Copy link

pdimov commented Nov 8, 2022

Should have alerted me about it. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working high priority Important!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants