[llvm-dev] Exceptions on Windows & MSVC

921 views
Skip to first unread message

Alexandre Ganea via llvm-dev

unread,
Nov 8, 2019, 3:55:21 PM11/8/19
to llvm-dev, Reid Kleckner, david.m...@gmail.com

Hello everyone,

 

I was wondering what is the status regarding exceptions for the windows-msvc target? The corresponding part of the documentation (llvm/decs/ExceptionHandling.rst) hasn’t been updated since 2015, was there any progress since?

 

This is most likely known, but there’s significant divergence between the behavior of MSVC cl.exe and clang-cl.exe:

Consider:

 

void crash() {

  struct A {

    ~A() {}

  } Obj;

  *(volatile int *)0x11 = 0;

}

 

#ifdef SEH

  #define TRY __try

  #define CATCH_ALL __except (1)

#else

  #define TRY try

  #define CATCH_ALL catch (...)

#endif

 

int main() {

  TRY { crash(); }

  CATCH_ALL {}

  return 0;

}

 

using try/catch (SEH not defined):

 

         |               (default)               |          /EHa            |          /EHs            |

--------------------------------------------------------------------------------------------------------

MSVC cl  | warning [1], no unwind, crash catched |    unwind, crash catched |          crash unhandled |

clang-cl | compilation error [2]                 |          crash unhandled |          crash unhandled |

 

 

using __try/__except (SEH defined):

 

         |               (default)               |          /EHa            |           /EHs           |

--------------------------------------------------------------------------------------------------------

MSVC cl  |              no unwind, crash catched |    unwind, crash catched |          crash unhandled |

clang-cl |              no unwind, crash catched | no unwind, crash catched | no unwind, crash catched |

 

 

According to Microsoft’s documentation [3],

                (default) means:              async exceptions + C++ exceptions, but no unwinding

                /EHa means:                      async exceptions + C++ exceptions, with unwinding in both cases

                /EHs means:                      C++ exceptions only, with unwinding

 

I’m using MSVC VS2017 15.9.16 and clang-cl from github at HEAD. In both cases I’m targeting x64.

Using _set_se_translator [4] and /EHa does not help with clang-cl.

 

Are there any plans to improve  the async exceptions unwinding in the short term?

 

Thanks!

Alex.

 

 

[1] warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc

[2] error: cannot use 'try' with exceptions disabled

[3] https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=vs-2019

[4] https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-se-translator?view=vs-2019

Aaron Smith via llvm-dev

unread,
Nov 11, 2019, 5:03:05 PM11/11/19
to llvm...@lists.llvm.org
At Microsoft we open sourced some of our compiler tests for exception handling on github.

We are looking into what it would take to get these to work with clang-cl. I’m planning to share a design document on the mailing list soon.

Aaron


Reid Kleckner via llvm-dev

unread,
Nov 11, 2019, 5:25:38 PM11/11/19
to Aaron Smith, llvm-dev
Good to hear. I re-ran the C++ EH tests locally a few months ago with clang-cl. Most of the tests passed, but some failed. For the ones that failed, it wasn't immediately clear if it was an EH bug or not. It seemed like clang was doing more copy elision than MSVC, and that accounted for most of the variation. It would be good to get to the bottom of it and be certain, though. In the end it runs fast enough that we could run it continuously.

_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

Reid Kleckner via llvm-dev

unread,
Nov 11, 2019, 6:19:20 PM11/11/19
to Alexandre Ganea, Aaron Smith, llvm-dev
I wasn't able to find where we say this in the docs, but the important thing to understand is that LLVM is currently incapable of representing non-call instructions that might throw an exception. So, in your example with the destructor, LLVM thinks there are no potentially throwing operations in this function, so there is no need to emit an exceptional destructor cleanup. I didn't read through the tables to see what actually happens in practice, but it should mostly be explained by the above.

If we do anything at all with /EHa in clang-cl, we just flip the bit that says "run destructor cleanups even when a non-C++ exception occurs". I can't remember if anyone actually hooked that up, though.

Aaron expressed interest in implementing support for non-call exceptions in LLVM. I'm happy to help review the design and code, but neither I nor anyone on my team is currently planning to work on this.

Michael Kruse via llvm-dev

unread,
Nov 11, 2019, 6:57:55 PM11/11/19
to Reid Kleckner, llvm-dev
Am Mo., 11. Nov. 2019 um 17:19 Uhr schrieb Reid Kleckner via llvm-dev
<llvm...@lists.llvm.org>:

> I wasn't able to find where we say this in the docs, but the important thing to understand is that LLVM is currently incapable of representing non-call instructions that might throw an exception.

Here: https://clang.llvm.org/docs/MSVCCompatibility.html ?

Asynchronous Exceptions (SEH): Partial. Structured exceptions (__try /
__except / __finally) mostly work on x86 and x64. LLVM does not model
asynchronous exceptions, so it is currently impossible to catch an
asynchronous exception generated in the same frame as the catching
__try.

Michael

Gaier, Bjoern via llvm-dev

unread,
Nov 13, 2019, 7:29:02 AM11/13/19
to llvm-dev

I tried compiling the source files under “SEH” with the latest official version of Clang-Cl and Visual Studio 2015. Compiling:

seh0015.c

seh0017.c

seh0035.c

seh0034.c

seh0036.c

seh0041.c

seh0043.c

seh0042.c

seh0049.c

seh0048.c

seh0050.c

xcpt4u.c

Will crash the compiler with “clang frontend command failed due to signal (use -v to see invocation)” and a stack dump.
Am I the only one having that issue?

Als GmbH eingetragen im Handelsregister Bad Homburg v.d.H. HRB 9816, USt.ID-Nr. DE 114 165 789 Geschäftsführer: Dr. Hiroshi Nakamura, Dr. Robert Plank, Markus Bode, Heiko Lampert, Takashi Nagano, Takeshi Fukushima. Junichi Tajika

Gaier, Bjoern via llvm-dev

unread,
Nov 19, 2019, 1:59:19 AM11/19/19
to llvm...@lists.llvm.org

Thank you for this Aaron!

 

In our company we rely heavily on the compatibility between Clang-Cl and the Visual Studio compiler, lately we encountered big problems with the handling of SEH exceptions in our code, so running those tests helped us. (Sadly we can’t move to the Visual Studio compiler)

 

However, maybe it helps someone if I share the results from running those tests… I imported all of the tests into separated projects, compiling them with the same settings, with MSVC (v141) and Clang (9), then I compared the output. The compiler settings for all those projects were:

/permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Gm- /Ox /Ob2 /sdl /Zc:inline /fp:precise /D "_MBCS" /errorReport:prompt /GF- /WX- /Zc:forScope /Gd /Oy /Oi /MD /FC /EHsc /nologo /Ot /diagnostics:classic

 

The MSVC compiler only failed the following test:

EH:
ihateeh.cxx

 

Clang however failed multiple tests:
EH:

ihateeh.cxx

 

SEH:

seh0007.c (-> Test failed; The access violation was optimized away, leading to a random result; – forcing the access violation caused no catching of the exception)
seh0019.c (-> No exception caught; Which makes sense because there are no catch handler, but MSVC does catch them)
seh0055.c (-> Test failed; The result is not correct)

sehframes.cpp (-> A certain exception was not caught)

 

The following tests didn’t even compiled, instead they crashed the compiler:

seh0034.c

seh0035.c

seh0036.c

seh0041.c

seh0042.c

seh0043.c

seh0048.c

seh0049.c

seh0050.c
xcpt4u.c

 

I hope that helped in some way – any comments or suggestions? I’m up for it!

 

From: llvm-dev <llvm-dev...@lists.llvm.org> On Behalf Of Aaron Smith via llvm-dev
Sent: 11 November 2019 23:03
To: llvm...@lists.llvm.org
Subject: [llvm-dev] Exceptions on Windows & MSVC

 

At Microsoft we open sourced some of our compiler tests for exception handling on github.

Als GmbH eingetragen im Handelsregister Bad Homburg v.d.H. HRB 9816, USt.ID-Nr. DE 114 165 789 Geschäftsführer: Dr. Hiroshi Nakamura, Dr. Robert Plank, Markus Bode, Heiko Lampert, Takashi Nagano, Takeshi Fukushima. Junichi Tajika

Aaron Smith via llvm-dev

unread,
Mar 27, 2020, 4:32:45 PM3/27/20
to Gaier, Bjoern, llvm...@lists.llvm.org
Here is a wiki page and git repo with an implementation of SEH that passes all the tests for x86.
We're looking for feedback before putting a patch on Phabricator.

Gaier, Bjoern via llvm-dev

unread,
Apr 1, 2020, 3:34:10 AM4/1/20
to Aaron Smith, llvm...@lists.llvm.org

Oh woah! That is really really cool! I hope I can try this out soon >o<

 

What is the Phabricator?

Gaier, Bjoern via llvm-dev

unread,
Apr 3, 2020, 5:27:15 AM4/3/20
to Aaron Smith, llvm...@lists.llvm.org

Hey Aaron,

 

I downloaded the source files from the git repo and build the LLVM and Clang with it. It is awesome to see that the SEH tests from Microsoft are working now. However Clang still crashes when trying to compile the “xcpt4u.c” source file from the SEH tests. I did a small source code modification by changing the return statement of the main to “return 0;”

 

Is this test supposed to work? Have I misconfigured something?

 

Kind greetings

Björn

 

From: Aaron Smith <aaron.l...@gmail.com>

Sent: 27 March 2020 21:31
To: Gaier, Bjoern <Bjoern...@horiba.com>
Cc: llvm...@lists.llvm.org

Aaron Smith via llvm-dev

unread,
Apr 3, 2020, 3:35:35 PM4/3/20
to Gaier, Bjoern, llvm...@lists.llvm.org
There are five bugs (three left) that are being fixed. Test58 & Test61 were fixed in Ten's last commit.
Both pass the entire SEH test suite except the following failures:
   -- Xcpt4u: test58 & test61:  due to Nested_Finally, a missing feature of
              present compiler. On MSVC this feature is only valid on X64 target.
   -- Xcpt4u: test84 & test87: leaving an except handler must invoke _local_unwind().
   -- Seh0020 (-O2 only):  a present setjmp/longjmp bug.
Reply all
Reply to author
Forward
0 new messages