-
Notifications
You must be signed in to change notification settings - Fork 13.5k
clang-cl incorrect SEH exception handling #62606
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
Comments
This should work correctly using latest development branch with /EHa. (This isn't supported without /EHa. And I don't think LLVM 16 has the relevant fixes.) |
Thanks for the info. I'm hoping it will not actually require |
You can handle SEH exceptions without As far as I know, this is the same model MSVC uses (https://learn.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=msvc-170). Maybe extremely simple cases like your testcase somehow work without /EHa, but in general you won't get the expected result. If there's an important use-case that involves not using /EHa, please open a feature request explaining what cases you need to handle, and why it's important it works without /EHa. |
Thanks for the additional information.
That's a dangerous assumption.
i. e. Further, you can find a list of typical structured exception codes in
Given the above, I'd assume that the compiler is not allowed to move any instructions into or out of a The code in question was taken from the OpenJDK; it was introduced in 2005 and has been working reliably ever since. The code does not use How do I open a feature request? Couldn't find that information in the "contributing" guide. |
Feature requests are the same as bug reports... with the discussion here, I can just reopen this, I guess. From the documentation:
Maybe we can carve out a narrow exception for load/store ops that are contained directly in an __try...? |
I checked the compilation results for #include <stdio.h>
#include <windows.h>
int SafeFetch32(const int* adr, int errValue) {
int v = 0;
__try {
v = *adr;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
v = errValue;
}
return v;
}
int main() {
return SafeFetch32(0, -1);
} produces the same code (SEH table) with The following code: #include <stdio.h>
#include <windows.h>
int SafeFetch32(const int* adr, int errValue) {
int v = 0;
try {
v = *adr;
}
catch(...) {
v = errValue;
}
return v;
}
int main() {
return SafeFetch32(0, -1);
} produces stack unwinding code (much longer code than the first example) with either This confirms that EDIT: |
@llvm/issue-subscribers-clang-codegen Author: Daniel Jelinski (djelinski)
The following code is supposed to read from potentially inaccessible memory, and return the provided default value if the memory is not accessible. It works fine when compiled with with `cl` (outputs `except` and `done`), but crashes when compiled with clang-cl:
```c
#include <stdio.h>
#include <windows.h>
//#define WORKAROUND int SafeFetch32(const int* adr, int errValue) {
Not sure if that's relevant, but the results were collected on Windows 11 21H2. |
I was scratching my head facing the same issue. |
Some of this discussion is confused, and hard to explain. Now I realize, if you interpret /EHa as something to do with destructors, then this is a contradiction. And /EHa has more meaning than someone said. Let's say we have: A a1; There is the question as to if "something here" can raise an exception. But with regular /EH, the compiler can try to prove that "something here" cannot raise exceptions. But it is a question as to if the program is guaranteed to progress from constructing a1 through to constructing a2, or if it can fail part way through. If it cannot fail part away through, there are optimizations to be had. And /EHa drastically increases what can fail part way through. |
That is: Agreed, that was my point too. |
The SEH support in LLVM is not rail to rail with MSVC.. I did a little archeology. The initial support of __try in LLVM was written by @rnk. The commit said:
Especially,
I didn't dig much on following changes, my impression is the non-call exceptions were never supported before @tentzen 's solution. It took a long time before all patches merged. So only LLVM19 and forward support it. The In a word, the mismatch between LLVM and MSVC is a long existing problem. The suggestion is to specify |
Yep, this is the history I remember. I feel like I have some responsibility for not engaging with the reviews for these patches, which I guess have dragged on as recently as 2024. I think it makes sense for |
The following code is supposed to read from potentially inaccessible memory, and return the provided default value if the memory is not accessible. It works fine when compiled with with
cl
(outputsexcept
anddone
), but crashes when compiled with clang-cl:When compiled with
-DWORKAROUND
, the code generated byclang-cl
works as expected.Clang downloaded with MS Visual Studio 2022 Community:
Not sure if that's relevant, but the results were collected on Windows 11 21H2.
The text was updated successfully, but these errors were encountered: