Implement __finally support for C++

svn path=/trunk/; revision=62626
This commit is contained in:
Timo Kreuzer 2014-04-05 15:41:03 +00:00
parent 9f2427ba20
commit b938bfc001
2 changed files with 26 additions and 9 deletions

View file

@ -10,7 +10,7 @@
#pragma once
#define _PSEH3_H_
#include "excpt.h"
#include <excpt.h>
#ifdef __cplusplus
extern "C" {
@ -111,7 +111,7 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter
#endif
/* This attribute allows automatic cleanup of the registered frames */
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_Unregister)))
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_AutoCleanup)))
/* CLANG specific definitions! */
#ifdef __clang__
@ -217,7 +217,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
/* Use the global unregister function */
void
__attribute__((regparm(1)))
_SEH3$_Unregister(
_SEH3$_AutoCleanup(
volatile SEH3$_REGISTRATION_FRAME *Frame);
/* These are only dummies here */
@ -251,7 +251,7 @@ _SEH3$_Unregister(
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS()
/* Since we cannot use nested functions, we declare these globally as macros */
#define _abnormal_termination() (_SEH3$_TrylevelFrame.ScopeTable != 0)
#define _abnormal_termination() (_SEH3$_TrylevelFrame.ExceptionPointers != 0)
#define _exception_code() (_SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode)
#define _exception_info() (_SEH3$_TrylevelFrame.ExceptionPointers)
@ -294,7 +294,7 @@ _SEH3$_Unregister(
_SEH3$_NESTED_FUNC_OPEN(_Name) \
/* Declare the intrinsics for the finally function */ \
inline __attribute__((always_inline, gnu_inline)) \
int _abnormal_termination() { return (_SEH3$_TrylevelFrame.ScopeTable != 0); } \
int _abnormal_termination() { return (_SEH3$_TrylevelFrame.ExceptionPointers != 0); } \
\
/* This construct makes sure that the finally function returns */ \
/* a proper value at the end */ \
@ -351,7 +351,7 @@ _SEH3$_Unregister(
}; \
\
/* Forward declaration of the auto cleanup function */ \
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_Unregister); \
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
\
/* Allocate a registration frame */ \
volatile SEH3$_REGISTRATION_FRAME _SEH3$_AUTO_CLEANUP _SEH3$_TrylevelFrame; \
@ -412,8 +412,8 @@ _SEH3$_Unregister(
/* End the try block */ \
while (0); \
_SEH3$_l_AfterTry: (void)0; \
/* Set ScopeTable to 0, this is used by _abnormal_termination() */ \
_SEH3$_TrylevelFrame.ScopeTable = 0; \
/* Set ExceptionPointers to 0, this is used by _abnormal_termination() */ \
_SEH3$_TrylevelFrame.ExceptionPointers = 0; \
\
goto _SEH3$_l_EndTry; \
\
@ -454,7 +454,7 @@ _SEH3$_Unregister(
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
\
/* Implementation of the auto cleanup function */ \
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_Unregister); \
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
\
/* Close the outer scope */ \
} while (0);

View file

@ -130,6 +130,23 @@ _SEH3$_InvokeFilter(
return FilterResult;
}
void
__attribute__((regparm(1)))
_SEH3$_AutoCleanup(
SEH3$_REGISTRATION_FRAME *Frame)
{
/* Check for __finally frames */
if (Frame->ScopeTable->Target == NULL)
{
_SEH3$_InvokeFilter(Frame, Frame->ScopeTable->Filter);
}
if (Frame->Handler)
_SEH3$_UnregisterFrame(Frame);
else
_SEH3$_UnregisterTryLevel(Frame);
}
static inline
LONG
_SEH3$_GetFilterResult(