STL
STL copied to clipboard
<exception>: std::exception::what has wrong signature
Describe the bug
std::exception::what
is not noexcept
.
See also #882 - should probably be fixed together. #808 is also in similar area
Command-line test case
d:\Temp2>type repro.cpp
#include <cstdio>
#include <exception>
int main()
{
auto b = noexcept(std::exception{}.what());
std::printf("%d\n", (int)b);
}
d:\Temp2>cl /EHsc /permissive- /std:c++latest /Zc:__cplusplus /Zc:externConstexpr repro.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29009.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
/std:c++latest is provided as a preview of language features from the latest C++
working draft, and we're eager to hear about bugs and suggestions for improvements.
However, note that these features are provided as-is without support, and subject
to changes or removal as the working draft evolves. See
https://go.microsoft.com/fwlink/?linkid=2045807 for details.
repro.cpp
Microsoft (R) Incremental Linker Version 14.27.29009.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:repro.exe
repro.obj
d:\Temp2>.\repro.exe
0
Expected behavior Should print 1 as ctor is noexcept.
STL version
Microsoft Visual Studio Professional 2019 Preview
Version 16.7.0 Preview 3.1
Additional context This item is also tracked on Developer Community as DevCom-785027 and by Microsoft-internal VSO-1006425 / AB#1006425.
vNext note: Resolving this issue will require breaking binary compatibility. We won't be able to accept pull requests for this issue until the vNext branch is available. See #169 for more information.
Thanks, I've linked the Microsoft-internal bug to this issue. This is a rare example of a vNext
bug where the bincompat break isn't nearly as bad as the source-compat break (as it breaks every pre-noexcept
override of what()
).
After thinking about this again, I suspect that this is not actually ABI-breaking, but the source-breaking change is indeed severe and I still don't know how to logistically go about doing this: https://godbolt.org/z/PjEnhxdjW
We could explore guarding the change for C++23, so only /std:c++latest
compilations would encounter breaks, but we'd still have to go report/fix/workaround a whole bunch of problems in the Real World Code test suite, MSVC and VS, Office, Windows, etc. Even with an escape hatch I'm not very eager to explore this. vNext doesn't technically make this any easier to do, except that it'll likely be filled with other source-compat breaks.
Is it time for us to have our first /permissive-
-only library "conformance improvement"? People use /permissive-
because they want to write standard-conforming code, they are likely willing to add a few noexcept
s. Note that a noexcept
function can override a non-noexcept
signature (https://godbolt.org/z/ocd4zWdYb), so libraries with noexcept
will continue to work in permissive mode. I feel like gating this behind /permissive-
(probably still with an escape hatch) is consistent with how the compiler has been handling breaking conformance improvements for the last 8 years. (I do think we want a reliable mechanism to determine whether the compiler is in permissive or strict mode for this, the hack we use for tests is fine for tests but feels brittle to rely on for production.)
There doesn't seem to be a technical reason to put this off. We know we want to be conformant eventually, it feels like we're waiting for a "good time" to do this that's never going to appear.
It would still be a lot of work to clean up RWC but /permissive-
does feel right for this.
(I see how we could use our hack to apply noexcept to the signature, but it would be gross and having a macro to finally sense the mode would be better.)
I suggest a visit to this STL project's stated mission, goals, and non-goals to help in this discussion...
- Mission and reason-to-exist is "ships as part of the MSVC toolset". It is clearly stated, first sentence.
- Goal 1 is conformance.
what()
is not. - Goal 4 is compatibility. There is consensus ABI is not involved. A subset of legacy code source compatibility is involved. Goal 4 writes "We consider source compatibility to be important, but not all-important; breaking source compatibility can be an acceptable cost if done for the right reasons in the right way (e.g. in a controlled manner with escape hatches)."
- Non-goal 2: Adding non-Standard extensions.
what()
is non-standard and porting the non-standard what() to each update 17/20/23... is adding it over and over.
Nowhere is it stated this project's goal is to consider private internal needs of other Microsoft divisions (MSVC and VS, Office, Windows, etc). Someone somewhere in Microsoft might question the P&L of correcting what()
because it will burn some resources to fix or toggle-switch their non-compliant code. But that's simply not of concern to me and (if polled) a measurable group of other ISVs.
🤔Am I reading correctly that the source-breaking behavior is primarily when code derives from what/exceptions? 🤔And that code that doesn't derive (like below) would not be affected and instead be better...it would compile cleanly like gcc and clang do already.
void myfunc() noexcept {
try {
// do work
throw std::exception("my text");
}
catch (const std::exception& err) {
printf("%s", err.what());
}
}
If both 🤔 are true, then I suggest breaking a subset of old code's what()
. And if you want to reduce complaints from old code, then put old non-compliant behavior in a switch. Make the non-compliant code be required to apply the switch. By default...should be compliant. This approach is alignment with all four mission+goal bullets I list at the top.
Since it is no longer vNext
, what
would be the strategy to fix it?
My proposal(as this is only source breaking thing) is to make a preprocessor define(documented), which people would be able to use to restore the non-conforming behavior so the migration would be less noisy.
My proposal(as this is only source breaking thing) is to make a preprocessor define(documented), which people would be able to use to restore the non-conforming behavior so the migration would be less noisy.
That's the "escape hatch" that Stephan mentioned in https://github.com/microsoft/STL/issues/948#issuecomment-1785057335
@cpplearner Sorry, not sure how I missed that.