When the msvc setjmpex.h file is included in source file then msvc changes
the behavior of C setjmp() and longjmp() calls to be SEH safe. Without
including the setjmpex.h file, these C calls are not SEH safe by default.

In following table is behavior of the msvc compiler, which symbols are
called in the emitted binary object code (not linked):

               without setjmpex.h         with setjmpex.h

    i386      _setjmp3  + longjmp      _setjmp3  + _longjmpex
    amd64     _setjmp   + longjmp      _setjmpex + longjmp
    arm32     _setjmp   + longjmp      _setjmpex + longjmp
    arm64     _setjmpex + longjmp      _setjmpex + longjmp

This table was produced from results on https://godbolt.org/z/Gabv1qT9c

When the compiled code is linked into final binary with UCRT library, the
_setjmp symbol is resolved to UCRT _intrinsic_setjmp symbol and the
_setjmpex symbol is resolved to UCRT _intrinsic_setjmpex. i386 _setjmp3
stays as without the _intrinsic prefix and the i386 _setjmp is not emitted
at all.

Fix the mingw-w64 setjmpex.h and setjmp.h include files to define setjmp()
and longjmp() macros which expands to functions emitted by msvc compiler to
match the msvc behavior.

Note that msvc setjmpex.h and setjmp.h header files are different than
mingw-w64 and is because it looks like that msvc compiler parses the source
code with setjmp and longjmp keywords differently and is doing some
transformations not specified in header files. Something which gcc is not
doing.

mingw-w64 setjmpex.h and setjmp.h files are defined based on the
observation of output from msvc compiler, not from the msvc header files.
---
 mingw-w64-headers/crt/setjmp.h   | 104 ++++++++++++++++++-------------
 mingw-w64-headers/crt/setjmpex.h |  16 +----
 2 files changed, 63 insertions(+), 57 deletions(-)

diff --git a/mingw-w64-headers/crt/setjmp.h b/mingw-w64-headers/crt/setjmp.h
index 54e3ad03b67f..0d85d0e9f9f8 100644
--- a/mingw-w64-headers/crt/setjmp.h
+++ b/mingw-w64-headers/crt/setjmp.h
@@ -26,7 +26,7 @@
 extern "C" {
 #endif
 
-#if (defined(_X86_) && !defined(__x86_64))
+#if defined(__i386__)
 
 #define _JBLEN 16
 #define _JBTYPE int
@@ -40,6 +40,7 @@ extern "C" {
     unsigned long Eip;
     unsigned long Registration;
     unsigned long TryLevel;
+    /* Following fields are only for new _setjmp3(), the are not for old 
_setjmp(). */
     unsigned long Cookie;
     unsigned long UnwindFunc;
     unsigned long UnwindData[6];
@@ -107,7 +108,7 @@ extern "C" {
 
   } _JUMP_BUFFER;
 
-#elif defined(__x86_64)
+#elif defined(__x86_64__)
 
   typedef _CRT_ALIGN(16) struct _SETJMP_FLOAT128 {
     __MINGW_EXTENSION unsigned __int64 Part[2];
@@ -202,64 +203,83 @@ extern "C" {
 #define _JMP_BUF_DEFINED
 #endif
 
-_CRTIMP __MINGW_ATTRIB_NORETURN __attribute__ ((__nothrow__)) void __cdecl 
longjmp(jmp_buf _Buf,int _Value);
+_CRTIMP __MINGW_ATTRIB_NORETURN __attribute__ ((__nothrow__)) void __cdecl 
longjmp(jmp_buf _Buf, int _Value); /* for setjmp.h and non-i386 setjmpex.h */
+#ifdef __i386__
+_CRTIMP __MINGW_ATTRIB_NORETURN __attribute__ ((__nothrow__)) void __cdecl 
_longjmpex(jmp_buf _Buf, int _Value); /* for i386 setjmpex.h */
+#endif
+
+#ifdef __i386__
+_CRTIMP int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
_setjmp(jmp_buf _Buf); /* old i386 crtdll setjmp.h */
+_CRTIMP int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
_setjmp3(jmp_buf _Buf, int _Count, ...); /* new i386 msvcrt20+ setjmp.h and 
setjmpex.h */
+#else
+#ifndef __aarch64__
+_CRTIMP int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
_setjmp(jmp_buf _Buf, void *_Frame); /* for non-i386 and non-aarch64 setjmp.h */
+#endif
+_CRTIMP int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
_setjmpex(jmp_buf _Buf, void *_Frame); /* for non-i386 setjmpex.h and aarch64 
setjmp.h */
+#endif
+
+#if defined(__arm__) || defined(__aarch64__)
+int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
__mingw_setjmp(jmp_buf _Buf);
+__MINGW_ATTRIB_NORETURN __attribute__ ((__nothrow__)) void 
__mingw_longjmp(jmp_buf _Buf, int _Value);
+#endif
 
 void * __cdecl __attribute__ ((__nothrow__)) mingw_getsp (void);
 
+#ifdef __cplusplus
+}
+#endif
+
+#pragma pack(pop)
+#endif /* _INC_SETJMP */
+
+/*
+ * Now outside of the _INC_SETJMP block, defines setjmp() and longjmp().
+ * It allows '#include <setjmpex.h>' to override the existing setjmp() and 
longjmp() definitions.
+ */
+
 #pragma push_macro("__has_builtin")
 #ifndef __has_builtin
   #define __has_builtin(x) 0
 #endif
 
-#ifdef __aarch64__
-   /* ARM64 lacks _setjmp, only has _setjmpex. */
-#  define _setjmp _setjmpex
+#ifdef setjmp
+#  undef setjmp
 #endif
-#ifndef _INC_SETJMPEX
-#  if defined(_X86_) || defined(__i386__)
-#    define setjmp(BUF) _setjmp3((BUF), 0)
-#  elif !defined(__SEH__) || defined(__USE_MINGW_SETJMP_NON_SEH)
-#    if defined(__arm__) || defined(__aarch64__)
-#      define setjmp(BUF) __mingw_setjmp((BUF))
-#      define longjmp __mingw_longjmp
-      int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
__mingw_setjmp(jmp_buf _Buf);
-      __MINGW_ATTRIB_NORETURN __attribute__ ((__nothrow__)) void 
__mingw_longjmp(jmp_buf _Buf,int _Value);
-#    else
-#      define setjmp(BUF) _setjmp((BUF), NULL)
-#    endif
-#  elif __has_builtin(__builtin_sponentry)
+#if defined(__i386__)
+#  define setjmp(BUF) _setjmp3((BUF), 0)
+#elif !defined(_INC_SETJMPEX) && (!defined(__SEH__) || 
defined(__USE_MINGW_SETJMP_NON_SEH))
+#  if defined(__arm__) || defined(__aarch64__)
+#    define setjmp(BUF) __mingw_setjmp((BUF))
+#  else
+#    define setjmp(BUF) _setjmp((BUF), NULL)
+#  endif
+#elif !defined(_INC_SETJMPEX) && !defined(__aarch64__)
+#  if __has_builtin(__builtin_sponentry)
 #    define setjmp(BUF) _setjmp((BUF), __builtin_sponentry())
 #  elif (__MINGW_GCC_VERSION < 40702) && !defined(__clang__)
 #    define setjmp(BUF) _setjmp((BUF), mingw_getsp())
 #  else
-#    define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0))
-#  endif
-  int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) _setjmp(jmp_buf 
_Buf, void *_Ctx);
-#  if defined(_X86_) || defined(__i386__)
-  int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) _setjmp3(jmp_buf 
_Buf, int _Count, ...);
+#    define setjmp(BUF) _setjmp((BUF), __builtin_frame_address(0))
 #  endif
 #else
-#  undef setjmp
-#  ifdef __SEH__
-#    if (__MINGW_GCC_VERSION < 40702) && !defined(__clang__)
-#      define setjmp(BUF) _setjmpex((BUF), mingw_getsp())
-#      define setjmpex(BUF) _setjmpex((BUF), mingw_getsp())
-#    else
-#      define setjmp(BUF) _setjmpex((BUF), __builtin_frame_address (0))
-#      define setjmpex(BUF) _setjmpex((BUF), __builtin_frame_address (0))
-#    endif
+#  if __has_builtin(__builtin_sponentry)
+#    define setjmp(BUF) _setjmpex((BUF), __builtin_sponentry())
+#  elif (__MINGW_GCC_VERSION < 40702) && !defined(__clang__)
+#    define setjmp(BUF) _setjmpex((BUF), mingw_getsp())
 #  else
-#    define setjmp(BUF) _setjmpex((BUF), NULL)
-#    define setjmpex(BUF) _setjmpex((BUF), NULL)
+#    define setjmp(BUF) _setjmpex((BUF), __builtin_frame_address(0))
 #  endif
-  int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) 
_setjmpex(jmp_buf _Buf,void *_Ctx);
 #endif
 
-#pragma pop_macro("__has_builtin")
-
-#ifdef __cplusplus
-}
+#ifdef longjmp
+#  undef longjmp
 #endif
-
-#pragma pack(pop)
+#if defined(_INC_SETJMPEX) && defined(__i386__)
+#  define longjmp _longjmpex
+#elif !defined(_INC_SETJMPEX) && (!defined(__SEH__) || 
defined(__USE_MINGW_SETJMP_NON_SEH)) && (defined(__arm__) || 
defined(__aarch64__))
+#  define longjmp __mingw_longjmp
+#else
+#  define longjmp longjmp
 #endif
+
+#pragma pop_macro("__has_builtin")
diff --git a/mingw-w64-headers/crt/setjmpex.h b/mingw-w64-headers/crt/setjmpex.h
index c5540b970f05..a1017c3e9e4c 100644
--- a/mingw-w64-headers/crt/setjmpex.h
+++ b/mingw-w64-headers/crt/setjmpex.h
@@ -4,21 +4,7 @@
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
 #ifndef _INC_SETJMPEX
+/* setjmp.h defines setjmp() and longjmp() based on _INC_SETJMPEX */
 #define _INC_SETJMPEX
-
-#ifndef _WIN32
-#error Only Win32 target is supported!
-#endif
-
-#if (defined(_X86_) && !defined(__x86_64))
-#define setjmp _setjmp
-#define longjmp _longjmpex
-#else
-#ifdef setjmp
-#undef setjmp
-#endif
-#define setjmp _setjmpex
-#endif
-
 #include <setjmp.h>
 #endif
-- 
2.20.1



_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to