/contrib/sdk/sources/libsupc++/Makefile |
---|
0,0 → 1,70 |
LIBRARY= libsupc++ |
CC = kos32-gcc |
AR = kos32-ar |
LD = kos32-ld |
CPP= kos32-g++ |
STRIP = kos32-strip |
CFLAGS = -U_Win32 -U_WIN32 -U__MINGW32__ -c -O2 -fno-ident -fomit-frame-pointer |
ARFLAGS= crs |
INCLUDES= -I. -I../newlib/libc/include |
LIBS:= -ldll -lc.dll |
DEFINES= -DIN_GCC -DUSE_EMUTLS=1 -D_GLIBCXX_HAVE_TLS |
SOURCES = gthr_mutex.c \ |
bad_alloc.cc \ |
class_type_info.cc \ |
del_op.cc \ |
del_opv.cc \ |
eh_alloc.cc \ |
eh_aux_runtime.cc \ |
eh_call.cc \ |
eh_catch.cc \ |
eh_exception.cc \ |
eh_globals.cc \ |
eh_personality.cc \ |
eh_term_handler.cc \ |
eh_terminate.cc \ |
eh_throw.cc \ |
eh_type.c \ |
eh_unex_handler.cc \ |
guard.cc \ |
guard_error.cc \ |
new_handler.cc \ |
new_op.cc \ |
new_opnt.cc \ |
new_opv.cc \ |
pbase_type_info.cc \ |
pure.cc \ |
si_class_type_info.cc \ |
tinfo.cc \ |
vmi_class_type_info.cc \ |
vterminate.cc |
OBJECTS = $(patsubst %.cc, %.o, $(patsubst %.c, %.o, $(SOURCES))) |
# targets |
all:$(LIBRARY).a |
$(LIBRARY).a: $(OBJECTS) Makefile |
$(AR) $(ARFLAGS) $(LIBRARY).a $(OBJECTS) |
mv -f $(LIBRARY).a ../../lib |
%.o : %.c Makefile |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
%.o : %.cc Makefile |
$(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
clean: |
-rm -f *.o |
/contrib/sdk/sources/libsupc++/gthr-default.h |
---|
0,0 → 1,772 |
/* Threads compatibility routines for libgcc2 and libobjc. */ |
/* Compile this one with gcc. */ |
/* Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2008, 2009 |
Free Software Foundation, Inc. |
Contributed by Mumit Khan <khan@xraylith.wisc.edu>. |
This file is part of GCC. |
GCC is free software; you can redistribute it and/or modify it under |
the terms of the GNU General Public License as published by the Free |
Software Foundation; either version 3, or (at your option) any later |
version. |
GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
WARRANTY; without even the implied warranty of MERCHANTABILITY or |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
for more details. |
Under Section 7 of GPL version 3, you are granted additional |
permissions described in the GCC Runtime Library Exception, version |
3.1, as published by the Free Software Foundation. |
You should have received a copy of the GNU General Public License and |
a copy of the GCC Runtime Library Exception along with this program; |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
#ifndef GCC_GTHR_WIN32_H |
#define GCC_GTHR_WIN32_H |
/* Make sure CONST_CAST2 (origin in system.h) is declared. */ |
#ifndef CONST_CAST2 |
#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq) |
#endif |
/* Windows32 threads specific definitions. The windows32 threading model |
does not map well into pthread-inspired gcc's threading model, and so |
there are caveats one needs to be aware of. |
1. The destructor supplied to __gthread_key_create is ignored for |
generic x86-win32 ports. This will certainly cause memory leaks |
due to unreclaimed eh contexts (sizeof (eh_context) is at least |
24 bytes for x86 currently). |
This memory leak may be significant for long-running applications |
that make heavy use of C++ EH. |
However, Mingw runtime (version 0.3 or newer) provides a mechanism |
to emulate pthreads key dtors; the runtime provides a special DLL, |
linked in if -mthreads option is specified, that runs the dtors in |
the reverse order of registration when each thread exits. If |
-mthreads option is not given, a stub is linked in instead of the |
DLL, which results in memory leak. Other x86-win32 ports can use |
the same technique of course to avoid the leak. |
2. The error codes returned are non-POSIX like, and cast into ints. |
This may cause incorrect error return due to truncation values on |
hw where sizeof (DWORD) > sizeof (int). |
3. We are currently using a special mutex instead of the Critical |
Sections, since Win9x does not support TryEnterCriticalSection |
(while NT does). |
The basic framework should work well enough. In the long term, GCC |
needs to use Structured Exception Handling on Windows32. */ |
#define __GTHREADS 1 |
#include <errno.h> |
#ifdef __MINGW32__ |
#include <_mingw.h> |
#endif |
#ifndef __UNUSED_PARAM |
#define __UNUSED_PARAM(x) x |
#endif |
#ifdef _LIBOBJC |
/* This is necessary to prevent windef.h (included from windows.h) from |
defining its own BOOL as a typedef. */ |
#ifndef __OBJC__ |
#define __OBJC__ |
#endif |
#include <windows.h> |
/* Now undef the windows BOOL. */ |
#undef BOOL |
/* Key structure for maintaining thread specific storage */ |
static DWORD __gthread_objc_data_tls = (DWORD) -1; |
/* Backend initialization functions */ |
/* Initialize the threads subsystem. */ |
int |
__gthread_objc_init_thread_system (void) |
{ |
/* Initialize the thread storage key. */ |
if ((__gthread_objc_data_tls = TlsAlloc ()) != (DWORD) -1) |
return 0; |
else |
return -1; |
} |
/* Close the threads subsystem. */ |
int |
__gthread_objc_close_thread_system (void) |
{ |
if (__gthread_objc_data_tls != (DWORD) -1) |
TlsFree (__gthread_objc_data_tls); |
return 0; |
} |
/* Backend thread functions */ |
/* Create a new thread of execution. */ |
objc_thread_t |
__gthread_objc_thread_detach (void (*func)(void *arg), void *arg) |
{ |
DWORD thread_id = 0; |
HANDLE win32_handle; |
if (!(win32_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) func, |
arg, 0, &thread_id))) |
thread_id = 0; |
return (objc_thread_t) (INT_PTR) thread_id; |
} |
/* Set the current thread's priority. */ |
int |
__gthread_objc_thread_set_priority (int priority) |
{ |
int sys_priority = 0; |
switch (priority) |
{ |
case OBJC_THREAD_INTERACTIVE_PRIORITY: |
sys_priority = THREAD_PRIORITY_NORMAL; |
break; |
default: |
case OBJC_THREAD_BACKGROUND_PRIORITY: |
sys_priority = THREAD_PRIORITY_BELOW_NORMAL; |
break; |
case OBJC_THREAD_LOW_PRIORITY: |
sys_priority = THREAD_PRIORITY_LOWEST; |
break; |
} |
/* Change priority */ |
if (SetThreadPriority (GetCurrentThread (), sys_priority)) |
return 0; |
else |
return -1; |
} |
/* Return the current thread's priority. */ |
int |
__gthread_objc_thread_get_priority (void) |
{ |
int sys_priority; |
sys_priority = GetThreadPriority (GetCurrentThread ()); |
switch (sys_priority) |
{ |
case THREAD_PRIORITY_HIGHEST: |
case THREAD_PRIORITY_TIME_CRITICAL: |
case THREAD_PRIORITY_ABOVE_NORMAL: |
case THREAD_PRIORITY_NORMAL: |
return OBJC_THREAD_INTERACTIVE_PRIORITY; |
default: |
case THREAD_PRIORITY_BELOW_NORMAL: |
return OBJC_THREAD_BACKGROUND_PRIORITY; |
case THREAD_PRIORITY_IDLE: |
case THREAD_PRIORITY_LOWEST: |
return OBJC_THREAD_LOW_PRIORITY; |
} |
/* Couldn't get priority. */ |
return -1; |
} |
/* Yield our process time to another thread. */ |
void |
__gthread_objc_thread_yield (void) |
{ |
Sleep (0); |
} |
/* Terminate the current thread. */ |
int |
__gthread_objc_thread_exit (void) |
{ |
/* exit the thread */ |
ExitThread (__objc_thread_exit_status); |
/* Failed if we reached here */ |
return -1; |
} |
/* Returns an integer value which uniquely describes a thread. */ |
objc_thread_t |
__gthread_objc_thread_id (void) |
{ |
return (objc_thread_t) (INT_PTR) GetCurrentThreadId (); |
} |
/* Sets the thread's local storage pointer. */ |
int |
__gthread_objc_thread_set_data (void *value) |
{ |
if (TlsSetValue (__gthread_objc_data_tls, value)) |
return 0; |
else |
return -1; |
} |
/* Returns the thread's local storage pointer. */ |
void * |
__gthread_objc_thread_get_data (void) |
{ |
DWORD lasterror; |
void *ptr; |
lasterror = GetLastError (); |
ptr = TlsGetValue (__gthread_objc_data_tls); /* Return thread data. */ |
SetLastError (lasterror); |
return ptr; |
} |
/* Backend mutex functions */ |
/* Allocate a mutex. */ |
int |
__gthread_objc_mutex_allocate (objc_mutex_t mutex) |
{ |
if ((mutex->backend = (void *) CreateMutex (NULL, 0, NULL)) == NULL) |
return -1; |
else |
return 0; |
} |
/* Deallocate a mutex. */ |
int |
__gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
{ |
CloseHandle ((HANDLE) (mutex->backend)); |
return 0; |
} |
/* Grab a lock on a mutex. */ |
int |
__gthread_objc_mutex_lock (objc_mutex_t mutex) |
{ |
int status; |
status = WaitForSingleObject ((HANDLE) (mutex->backend), INFINITE); |
if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED) |
return -1; |
else |
return 0; |
} |
/* Try to grab a lock on a mutex. */ |
int |
__gthread_objc_mutex_trylock (objc_mutex_t mutex) |
{ |
int status; |
status = WaitForSingleObject ((HANDLE) (mutex->backend), 0); |
if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED) |
return -1; |
else |
return 0; |
} |
/* Unlock the mutex */ |
int |
__gthread_objc_mutex_unlock (objc_mutex_t mutex) |
{ |
if (ReleaseMutex ((HANDLE) (mutex->backend)) == 0) |
return -1; |
else |
return 0; |
} |
/* Backend condition mutex functions */ |
/* Allocate a condition. */ |
int |
__gthread_objc_condition_allocate (objc_condition_t __UNUSED_PARAM(condition)) |
{ |
/* Unimplemented. */ |
return -1; |
} |
/* Deallocate a condition. */ |
int |
__gthread_objc_condition_deallocate (objc_condition_t __UNUSED_PARAM(condition)) |
{ |
/* Unimplemented. */ |
return -1; |
} |
/* Wait on the condition */ |
int |
__gthread_objc_condition_wait (objc_condition_t __UNUSED_PARAM(condition), |
objc_mutex_t __UNUSED_PARAM(mutex)) |
{ |
/* Unimplemented. */ |
return -1; |
} |
/* Wake up all threads waiting on this condition. */ |
int |
__gthread_objc_condition_broadcast (objc_condition_t __UNUSED_PARAM(condition)) |
{ |
/* Unimplemented. */ |
return -1; |
} |
/* Wake up one thread waiting on this condition. */ |
int |
__gthread_objc_condition_signal (objc_condition_t __UNUSED_PARAM(condition)) |
{ |
/* Unimplemented. */ |
return -1; |
} |
#else /* _LIBOBJC */ |
#ifdef __cplusplus |
extern "C" { |
#endif |
typedef unsigned long __gthread_key_t; |
typedef struct { |
int done; |
long started; |
} __gthread_once_t; |
typedef struct { |
long counter; |
void *sema; |
} __gthread_mutex_t; |
typedef struct { |
long counter; |
long depth; |
unsigned long owner; |
void *sema; |
} __gthread_recursive_mutex_t; |
#define __GTHREAD_ONCE_INIT {0, -1} |
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function |
#define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0} |
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \ |
__gthread_recursive_mutex_init_function |
#define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0} |
#if defined (_WIN32) && !defined(__CYGWIN__) |
#define MINGW32_SUPPORTS_MT_EH 1 |
/* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero |
if -mthreads option was specified, or 0 otherwise. This is to get around |
the lack of weak symbols in PE-COFF. */ |
extern int _CRT_MT; |
extern int __mingwthr_key_dtor (unsigned long, void (*) (void *)); |
#endif /* _WIN32 && !__CYGWIN__ */ |
/* The Windows95 kernel does not export InterlockedCompareExchange. |
This provides a substitute. When building apps that reference |
gthread_mutex_try_lock, the __GTHREAD_I486_INLINE_LOCK_PRIMITIVES |
macro must be defined if Windows95 is a target. Currently |
gthread_mutex_try_lock is not referenced by libgcc or libstdc++. */ |
#ifdef __GTHREAD_I486_INLINE_LOCK_PRIMITIVES |
static inline long |
__gthr_i486_lock_cmp_xchg(long *__dest, long __xchg, long __comperand) |
{ |
long result; |
__asm__ __volatile__ ("\n\ |
lock\n\ |
cmpxchg{l} {%4, %1|%1, %4}\n" |
: "=a" (result), "=m" (*__dest) |
: "0" (__comperand), "m" (*__dest), "r" (__xchg) |
: "cc"); |
return result; |
} |
#define __GTHR_W32_InterlockedCompareExchange __gthr_i486_lock_cmp_xchg |
#else /* __GTHREAD_I486_INLINE_LOCK_PRIMITIVES */ |
#define __GTHR_W32_InterlockedCompareExchange InterlockedCompareExchange |
#endif /* __GTHREAD_I486_INLINE_LOCK_PRIMITIVES */ |
static inline int |
__gthread_active_p (void) |
{ |
#ifdef MINGW32_SUPPORTS_MT_EH |
return _CRT_MT; |
#else |
return 1; |
#endif |
} |
#if __GTHREAD_HIDE_WIN32API |
/* The implementations are in config/i386/gthr-win32.c in libgcc.a. |
Only stubs are exposed to avoid polluting the C++ namespace with |
windows api definitions. */ |
extern int __gthr_win32_once (__gthread_once_t *, void (*) (void)); |
extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*)); |
extern int __gthr_win32_key_delete (__gthread_key_t); |
extern void * __gthr_win32_getspecific (__gthread_key_t); |
extern int __gthr_win32_setspecific (__gthread_key_t, const void *); |
extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *); |
extern int __gthr_win32_mutex_lock (__gthread_mutex_t *); |
extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *); |
extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *); |
extern void |
__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *); |
extern int __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *); |
extern int |
__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *); |
extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *); |
extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *); |
static inline int |
__gthread_once (__gthread_once_t *__once, void (*__func) (void)) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_once (__once, __func); |
else |
return -1; |
} |
static inline int |
__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) |
{ |
return __gthr_win32_key_create (__key, __dtor); |
} |
static inline int |
__gthread_key_delete (__gthread_key_t __key) |
{ |
return __gthr_win32_key_delete (__key); |
} |
static inline void * |
__gthread_getspecific (__gthread_key_t __key) |
{ |
return __gthr_win32_getspecific (__key); |
} |
static inline int |
__gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
{ |
return __gthr_win32_setspecific (__key, __ptr); |
} |
static inline void |
__gthread_mutex_init_function (__gthread_mutex_t *__mutex) |
{ |
__gthr_win32_mutex_init_function (__mutex); |
} |
static inline void |
__gthread_mutex_destroy (__gthread_mutex_t *__mutex) |
{ |
__gthr_win32_mutex_destroy (__mutex); |
} |
static inline int |
__gthread_mutex_lock (__gthread_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_mutex_lock (__mutex); |
else |
return 0; |
} |
static inline int |
__gthread_mutex_trylock (__gthread_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_mutex_trylock (__mutex); |
else |
return 0; |
} |
static inline int |
__gthread_mutex_unlock (__gthread_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_mutex_unlock (__mutex); |
else |
return 0; |
} |
static inline void |
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) |
{ |
__gthr_win32_recursive_mutex_init_function (__mutex); |
} |
static inline int |
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_recursive_mutex_lock (__mutex); |
else |
return 0; |
} |
static inline int |
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_recursive_mutex_trylock (__mutex); |
else |
return 0; |
} |
static inline int |
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
return __gthr_win32_recursive_mutex_unlock (__mutex); |
else |
return 0; |
} |
#else /* ! __GTHREAD_HIDE_WIN32API */ |
#include <windows.h> |
#include <errno.h> |
static inline int |
__gthread_once (__gthread_once_t *__once, void (*__func) (void)) |
{ |
if (! __gthread_active_p ()) |
return -1; |
else if (__once == NULL || __func == NULL) |
return EINVAL; |
if (! __once->done) |
{ |
if (InterlockedIncrement (&(__once->started)) == 0) |
{ |
(*__func) (); |
__once->done = TRUE; |
} |
else |
{ |
/* Another thread is currently executing the code, so wait for it |
to finish; yield the CPU in the meantime. If performance |
does become an issue, the solution is to use an Event that |
we wait on here (and set above), but that implies a place to |
create the event before this routine is called. */ |
while (! __once->done) |
Sleep (0); |
} |
} |
return 0; |
} |
/* Windows32 thread local keys don't support destructors; this leads to |
leaks, especially in threaded applications making extensive use of |
C++ EH. Mingw uses a thread-support DLL to work-around this problem. */ |
static inline int |
__gthread_key_create (__gthread_key_t *__key, |
void (*__dtor) (void *) __attribute__((unused))) |
{ |
int __status = 0; |
DWORD __tls_index = TlsAlloc (); |
if (__tls_index != 0xFFFFFFFF) |
{ |
*__key = __tls_index; |
#ifdef MINGW32_SUPPORTS_MT_EH |
/* Mingw runtime will run the dtors in reverse order for each thread |
when the thread exits. */ |
__status = __mingwthr_key_dtor (*__key, __dtor); |
#endif |
} |
else |
__status = (int) GetLastError (); |
return __status; |
} |
static inline int |
__gthread_key_delete (__gthread_key_t __key) |
{ |
return (TlsFree (__key) != 0) ? 0 : (int) GetLastError (); |
} |
static inline void * |
__gthread_getspecific (__gthread_key_t __key) |
{ |
DWORD __lasterror; |
void *__ptr; |
__lasterror = GetLastError (); |
__ptr = TlsGetValue (__key); |
SetLastError (__lasterror); |
return __ptr; |
} |
static inline int |
__gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
{ |
if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)) != 0) |
return 0; |
else |
return GetLastError (); |
} |
static inline void |
__gthread_mutex_init_function (__gthread_mutex_t *__mutex) |
{ |
__mutex->counter = -1; |
__mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL); |
} |
static inline void |
__gthread_mutex_destroy (__gthread_mutex_t *__mutex) |
{ |
CloseHandle ((HANDLE) __mutex->sema); |
} |
static inline int |
__gthread_mutex_lock (__gthread_mutex_t *__mutex) |
{ |
int __status = 0; |
if (__gthread_active_p ()) |
{ |
if (InterlockedIncrement (&__mutex->counter) == 0 || |
WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0) |
__status = 0; |
else |
{ |
/* WaitForSingleObject returns WAIT_FAILED, and we can only do |
some best-effort cleanup here. */ |
InterlockedDecrement (&__mutex->counter); |
__status = 1; |
} |
} |
return __status; |
} |
static inline int |
__gthread_mutex_trylock (__gthread_mutex_t *__mutex) |
{ |
int __status = 0; |
if (__gthread_active_p ()) |
{ |
if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0) |
__status = 0; |
else |
__status = 1; |
} |
return __status; |
} |
static inline int |
__gthread_mutex_unlock (__gthread_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
{ |
if (InterlockedDecrement (&__mutex->counter) >= 0) |
return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1; |
} |
return 0; |
} |
static inline void |
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) |
{ |
__mutex->counter = -1; |
__mutex->depth = 0; |
__mutex->owner = 0; |
__mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL); |
} |
static inline int |
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
{ |
DWORD __me = GetCurrentThreadId(); |
if (InterlockedIncrement (&__mutex->counter) == 0) |
{ |
__mutex->depth = 1; |
__mutex->owner = __me; |
} |
else if (__mutex->owner == __me) |
{ |
InterlockedDecrement (&__mutex->counter); |
++(__mutex->depth); |
} |
else if (WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0) |
{ |
__mutex->depth = 1; |
__mutex->owner = __me; |
} |
else |
{ |
/* WaitForSingleObject returns WAIT_FAILED, and we can only do |
some best-effort cleanup here. */ |
InterlockedDecrement (&__mutex->counter); |
return 1; |
} |
} |
return 0; |
} |
static inline int |
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
{ |
DWORD __me = GetCurrentThreadId(); |
if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0) |
{ |
__mutex->depth = 1; |
__mutex->owner = __me; |
} |
else if (__mutex->owner == __me) |
++(__mutex->depth); |
else |
return 1; |
} |
return 0; |
} |
static inline int |
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) |
{ |
if (__gthread_active_p ()) |
{ |
--(__mutex->depth); |
if (__mutex->depth == 0) |
{ |
__mutex->owner = 0; |
if (InterlockedDecrement (&__mutex->counter) >= 0) |
return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1; |
} |
} |
return 0; |
} |
#endif /* __GTHREAD_HIDE_WIN32API */ |
#ifdef __cplusplus |
} |
#endif |
#endif /* _LIBOBJC */ |
#endif /* ! GCC_GTHR_WIN32_H */ |
/contrib/sdk/sources/libsupc++/gthr_mutex.c |
---|
0,0 → 1,150 |
#include <stdlib.h> |
#include <sys/errno.h> |
#include <kos32sys.h> |
void __mutex_lock(volatile int *val); |
static inline int tls_get(int key) |
{ |
int val; |
__asm__ __volatile__( |
"movl %%fs:(%1), %0" |
:"=r"(val) |
:"r"(key)); |
return val; |
}; |
typedef struct { |
int done; |
long started; |
} __gthread_once_t; |
typedef struct { |
int counter; |
void *sema; |
} __gthread_mutex_t; |
typedef struct { |
int counter; |
int depth; |
unsigned long owner; |
int sema; |
} __gthread_recursive_mutex_t; |
int |
__gthr_win32_once (__gthread_once_t *once, void (*func) (void)) |
{ |
if (once == NULL || func == NULL) |
return EINVAL; |
if (! once->done) |
{ |
if (__sync_add_and_fetch (&(once->started), 1) == 0) |
{ |
(*func) (); |
once->done = 1; |
} |
else |
{ |
/* Another thread is currently executing the code, so wait for it |
to finish; yield the CPU in the meantime. If performance |
does become an issue, the solution is to use an Event that |
we wait on here (and set above), but that implies a place to |
create the event before this routine is called. */ |
while (! once->done) |
delay(1); |
} |
} |
return 0; |
} |
void __gthr_win32_mutex_init_function (__gthread_mutex_t *mutex) |
{ |
mutex->counter = 0; |
mutex->sema = 0; |
} |
int __gthr_win32_mutex_lock (__gthread_mutex_t *mutex) |
{ |
__mutex_lock(&mutex->counter); |
return 0; |
} |
int |
__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex) |
{ |
mutex->counter = 0; |
return 0; |
} |
void |
__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) |
{ |
mutex->counter = -1; |
mutex->depth = 0; |
mutex->owner = 0; |
mutex->sema = 0; |
} |
void |
__gthr_win32_mutex_destroy (__gthread_mutex_t *mutex) |
{ } |
int |
__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) |
{ |
int me = tls_get(0); |
if ( __sync_add_and_fetch(&mutex->counter, 1) == 0) |
{ |
mutex->depth = 1; |
mutex->owner = me; |
mutex->sema = 1; |
} |
else if (mutex->owner == me) |
{ |
__sync_sub_and_fetch(&mutex->counter, 1); |
++(mutex->depth); |
} |
else |
{ |
__mutex_lock(&mutex->sema); |
mutex->depth = 1; |
mutex->owner = me; |
} |
return 0; |
} |
int |
__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) |
{ |
int me = tls_get(0); |
if (__sync_val_compare_and_swap (&mutex->counter, -1, 0) < 0) |
{ |
mutex->depth = 1; |
mutex->owner = me; |
mutex->sema = 1; |
} |
else if (mutex->owner == me) |
++(mutex->depth); |
else |
return 1; |
return 0; |
} |
int |
__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) |
{ |
--(mutex->depth); |
if (mutex->depth == 0) |
{ |
mutex->owner = 0; |
if (__sync_sub_and_fetch (&mutex->counter, 1) >= 0) |
mutex->sema = 0; |
} |
return 0; |
} |
/contrib/sdk/sources/libsupc++/bad_alloc.cc |
---|
0,0 → 1,34 |
// Implementation file for the -*- C++ -*- dynamic memory management header. |
// Copyright (C) 2010, 2011 Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "new" |
std::bad_alloc::~bad_alloc() _GLIBCXX_USE_NOEXCEPT { } |
const char* |
std::bad_alloc::what() const _GLIBCXX_USE_NOEXCEPT |
{ |
return "std::bad_alloc"; |
} |
/contrib/sdk/sources/libsupc++/class_type_info.cc |
---|
0,0 → 1,111 |
// Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, |
// 2009 Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "tinfo.h" |
namespace __cxxabiv1 { |
__class_type_info:: |
~__class_type_info () |
{} |
bool __class_type_info:: |
__do_catch (const type_info *thr_type, |
void **thr_obj, |
unsigned outer) const |
{ |
if (*this == *thr_type) |
return true; |
if (outer >= 4) |
// Neither `A' nor `A *'. |
return false; |
return thr_type->__do_upcast (this, thr_obj); |
} |
bool __class_type_info:: |
__do_upcast (const __class_type_info *dst_type, |
void **obj_ptr) const |
{ |
__upcast_result result (__vmi_class_type_info::__flags_unknown_mask); |
__do_upcast (dst_type, *obj_ptr, result); |
if (!contained_public_p (result.part2dst)) |
return false; |
*obj_ptr = const_cast <void *> (result.dst_ptr); |
return true; |
} |
__class_type_info::__sub_kind __class_type_info:: |
__do_find_public_src (ptrdiff_t, |
const void *obj_ptr, |
const __class_type_info *, |
const void *src_ptr) const |
{ |
if (src_ptr == obj_ptr) |
// Must be our type, as the pointers match. |
return __contained_public; |
return __not_contained; |
} |
bool __class_type_info:: |
__do_dyncast (ptrdiff_t, |
__sub_kind access_path, |
const __class_type_info *dst_type, |
const void *obj_ptr, |
const __class_type_info *src_type, |
const void *src_ptr, |
__dyncast_result &__restrict result) const |
{ |
if (obj_ptr == src_ptr && *this == *src_type) |
{ |
// The src object we started from. Indicate how we are accessible from |
// the most derived object. |
result.whole2src = access_path; |
return false; |
} |
if (*this == *dst_type) |
{ |
result.dst_ptr = obj_ptr; |
result.whole2dst = access_path; |
result.dst2src = __not_contained; |
return false; |
} |
return false; |
} |
bool __class_type_info:: |
__do_upcast (const __class_type_info *dst, const void *obj, |
__upcast_result &__restrict result) const |
{ |
if (*this == *dst) |
{ |
result.dst_ptr = obj; |
result.base_type = nonvirtual_base_type; |
result.part2dst = __contained_public; |
return true; |
} |
return false; |
} |
} |
/contrib/sdk/sources/libsupc++/del_op.cc |
---|
0,0 → 1,49 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2007, 2009, 2010, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#if !_GLIBCXX_HOSTED |
// A freestanding C runtime may not provide "free" -- but there is no |
// other reasonable way to implement "operator delete". |
namespace std |
{ |
_GLIBCXX_BEGIN_NAMESPACE_VERSION |
extern "C" void free(void*); |
_GLIBCXX_END_NAMESPACE_VERSION |
} // namespace |
#else |
# include <cstdlib> |
#endif |
#include "new" |
_GLIBCXX_WEAK_DEFINITION void |
operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT |
{ |
if (ptr) |
std::free(ptr); |
} |
/contrib/sdk/sources/libsupc++/del_opv.cc |
---|
0,0 → 1,34 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include "new" |
_GLIBCXX_WEAK_DEFINITION void |
operator delete[] (void *ptr) _GLIBCXX_USE_NOEXCEPT |
{ |
::operator delete (ptr); |
} |
/contrib/sdk/sources/libsupc++/eh_alloc.cc |
---|
0,0 → 1,220 |
// -*- C++ -*- Allocate exception objects. |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2011 |
// Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
// This is derived from the C++ ABI for IA-64. Where we diverge |
// for cross-architecture compatibility are noted with "@@@". |
#include <bits/c++config.h> |
#include <cstdlib> |
#if _GLIBCXX_HOSTED |
#include <cstring> |
#endif |
#include <climits> |
#include <exception> |
#include "unwind-cxx.h" |
#include <ext/concurrence.h> |
#if _GLIBCXX_HOSTED |
using std::free; |
using std::malloc; |
using std::memset; |
#else |
// In a freestanding environment, these functions may not be available |
// -- but for now, we assume that they are. |
extern "C" void *malloc (std::size_t); |
extern "C" void free(void *); |
extern "C" void *memset (void *, int, std::size_t); |
#endif |
using namespace __cxxabiv1; |
// ??? How to control these parameters. |
// Guess from the size of basic types how large a buffer is reasonable. |
// Note that the basic c++ exception header has 13 pointers and 2 ints, |
// so on a system with PSImode pointers we're talking about 56 bytes |
// just for overhead. |
#if INT_MAX == 32767 |
# define EMERGENCY_OBJ_SIZE 128 |
# define EMERGENCY_OBJ_COUNT 16 |
#elif LONG_MAX == 2147483647 |
# define EMERGENCY_OBJ_SIZE 512 |
# define EMERGENCY_OBJ_COUNT 32 |
#else |
# define EMERGENCY_OBJ_SIZE 1024 |
# define EMERGENCY_OBJ_COUNT 64 |
#endif |
#ifndef __GTHREADS |
# undef EMERGENCY_OBJ_COUNT |
# define EMERGENCY_OBJ_COUNT 4 |
#endif |
#if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32 |
typedef unsigned int bitmask_type; |
#else |
typedef unsigned long bitmask_type; |
#endif |
typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned)); |
static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT]; |
static bitmask_type emergency_used; |
static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT]; |
static bitmask_type dependents_used; |
namespace |
{ |
// A single mutex controlling emergency allocations. |
__gnu_cxx::__mutex emergency_mutex; |
} |
extern "C" void * |
__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW |
{ |
void *ret; |
thrown_size += sizeof (__cxa_refcounted_exception); |
ret = malloc (thrown_size); |
if (! ret) |
{ |
__gnu_cxx::__scoped_lock sentry(emergency_mutex); |
bitmask_type used = emergency_used; |
unsigned int which = 0; |
if (thrown_size > EMERGENCY_OBJ_SIZE) |
goto failed; |
while (used & 1) |
{ |
used >>= 1; |
if (++which >= EMERGENCY_OBJ_COUNT) |
goto failed; |
} |
emergency_used |= (bitmask_type)1 << which; |
ret = &emergency_buffer[which][0]; |
failed:; |
if (!ret) |
std::terminate (); |
} |
// We have an uncaught exception as soon as we allocate memory. This |
// yields uncaught_exception() true during the copy-constructor that |
// initializes the exception object. See Issue 475. |
__cxa_eh_globals *globals = __cxa_get_globals (); |
globals->uncaughtExceptions += 1; |
memset (ret, 0, sizeof (__cxa_refcounted_exception)); |
return (void *)((char *)ret + sizeof (__cxa_refcounted_exception)); |
} |
extern "C" void |
__cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW |
{ |
char *base = (char *) emergency_buffer; |
char *ptr = (char *) vptr; |
if (ptr >= base |
&& ptr < base + sizeof (emergency_buffer)) |
{ |
const unsigned int which |
= (unsigned) (ptr - base) / EMERGENCY_OBJ_SIZE; |
__gnu_cxx::__scoped_lock sentry(emergency_mutex); |
emergency_used &= ~((bitmask_type)1 << which); |
} |
else |
free (ptr - sizeof (__cxa_refcounted_exception)); |
} |
extern "C" __cxa_dependent_exception* |
__cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW |
{ |
__cxa_dependent_exception *ret; |
ret = static_cast<__cxa_dependent_exception*> |
(malloc (sizeof (__cxa_dependent_exception))); |
if (!ret) |
{ |
__gnu_cxx::__scoped_lock sentry(emergency_mutex); |
bitmask_type used = dependents_used; |
unsigned int which = 0; |
while (used & 1) |
{ |
used >>= 1; |
if (++which >= EMERGENCY_OBJ_COUNT) |
goto failed; |
} |
dependents_used |= (bitmask_type)1 << which; |
ret = &dependents_buffer[which]; |
failed:; |
if (!ret) |
std::terminate (); |
} |
// We have an uncaught exception as soon as we allocate memory. This |
// yields uncaught_exception() true during the copy-constructor that |
// initializes the exception object. See Issue 475. |
__cxa_eh_globals *globals = __cxa_get_globals (); |
globals->uncaughtExceptions += 1; |
memset (ret, 0, sizeof (__cxa_dependent_exception)); |
return ret; |
} |
extern "C" void |
__cxxabiv1::__cxa_free_dependent_exception |
(__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW |
{ |
char *base = (char *) dependents_buffer; |
char *ptr = (char *) vptr; |
if (ptr >= base |
&& ptr < base + sizeof (dependents_buffer)) |
{ |
const unsigned int which |
= (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception); |
__gnu_cxx::__scoped_lock sentry(emergency_mutex); |
dependents_used &= ~((bitmask_type)1 << which); |
} |
else |
free (vptr); |
} |
/contrib/sdk/sources/libsupc++/eh_aux_runtime.cc |
---|
0,0 → 1,51 |
// -*- C++ -*- Common throw conditions. |
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2009, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "typeinfo" |
#include "exception" |
#include <cstdlib> |
#include "unwind-cxx.h" |
#include <bits/exception_defines.h> |
extern "C" void |
__cxxabiv1::__cxa_bad_cast () |
{ |
#ifdef __EXCEPTIONS |
throw std::bad_cast(); |
#else |
std::abort(); |
#endif |
} |
extern "C" void |
__cxxabiv1::__cxa_bad_typeid () |
{ |
#ifdef __EXCEPTIONS |
throw std::bad_typeid(); |
#else |
std::abort(); |
#endif |
} |
/contrib/sdk/sources/libsupc++/eh_call.cc |
---|
0,0 → 1,159 |
// -*- C++ -*- Helpers for calling unextected and terminate |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
// 2011 |
// Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <cstdlib> |
#include <bits/exception_defines.h> |
#include "unwind-cxx.h" |
using namespace __cxxabiv1; |
#include "unwind-pe.h" |
// Helper routine for when the exception handling code needs to call |
// terminate. |
extern "C" void |
__cxa_call_terminate(_Unwind_Exception* ue_header) throw () |
{ |
if (ue_header) |
{ |
// terminate is classed as a catch handler. |
__cxa_begin_catch(ue_header); |
// Call the terminate handler that was in effect when we threw this |
// exception. */ |
if (__is_gxx_exception_class(ue_header->exception_class)) |
{ |
__cxa_exception* xh; |
xh = __get_exception_header_from_ue(ue_header); |
__terminate(xh->terminateHandler); |
} |
} |
/* Call the global routine if we don't have anything better. */ |
std::terminate(); |
} |
#ifdef __ARM_EABI_UNWINDER__ |
// The ARM EABI __cxa_call_unexpected has the same semantics as the generic |
// routine, but the exception specification has a different format. |
extern "C" void |
__cxa_call_unexpected(void* exc_obj_in) |
{ |
_Unwind_Exception* exc_obj |
= reinterpret_cast<_Unwind_Exception*>(exc_obj_in); |
int rtti_count = 0; |
_Unwind_Word rtti_stride = 0; |
_Unwind_Word* rtti_list = NULL; |
_Unwind_Ptr rtti_base = 0; |
bool foreign_exception; |
std::unexpected_handler unexpectedHandler = NULL; |
std::terminate_handler terminateHandler = NULL; |
__cxa_exception* xh; |
if (__is_gxx_exception_class(exc_obj->exception_class)) |
{ |
// Save data from the EO, which may be clobbered by _cxa_begin_catch. |
xh = __get_exception_header_from_ue(exc_obj); |
unexpectedHandler = xh->unexpectedHandler; |
terminateHandler = xh->terminateHandler; |
rtti_count = exc_obj->barrier_cache.bitpattern[1]; |
rtti_base = (_Unwind_Ptr) exc_obj->barrier_cache.bitpattern[2]; |
rtti_stride = exc_obj->barrier_cache.bitpattern[3]; |
rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4]; |
foreign_exception = false; |
} |
else |
foreign_exception = true; |
/* This must be called after extracting data from the EO, but before |
calling unexpected(). */ |
__cxa_begin_catch(exc_obj); |
// This function is a handler for our exception argument. If we exit |
// by throwing a different exception, we'll need the original cleaned up. |
struct end_catch_protect |
{ |
end_catch_protect() { } |
~end_catch_protect() { __cxa_end_catch(); } |
} end_catch_protect_obj; |
__try |
{ |
if (foreign_exception) |
std::unexpected(); |
else |
__unexpected(unexpectedHandler); |
} |
__catch(...) |
{ |
/* See if the new exception matches the rtti list. */ |
if (foreign_exception) |
std::terminate(); |
// Get the exception thrown from unexpected. |
__cxa_eh_globals* globals = __cxa_get_globals_fast(); |
__cxa_exception* new_xh = globals->caughtExceptions; |
void* new_ptr = __get_object_from_ambiguous_exception (new_xh); |
const std::type_info* catch_type; |
int n; |
bool bad_exception_allowed = false; |
const std::type_info& bad_exc = typeid(std::bad_exception); |
// Check the new exception against the rtti list |
for (n = 0; n < rtti_count; n++) |
{ |
_Unwind_Word offset; |
offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)]; |
offset = _Unwind_decode_typeinfo_ptr(rtti_base, offset); |
catch_type = (const std::type_info*) (offset); |
if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false, |
&new_ptr) != ctm_failed) |
__throw_exception_again; |
if (catch_type->__do_catch(&bad_exc, 0, 1)) |
bad_exception_allowed = true; |
} |
// If the exception spec allows std::bad_exception, throw that. |
#ifdef __EXCEPTIONS |
if (bad_exception_allowed) |
throw std::bad_exception(); |
#endif |
// Otherwise, die. |
__terminate(terminateHandler); |
} |
} |
#endif // __ARM_EABI_UNWINDER__ |
/contrib/sdk/sources/libsupc++/eh_catch.cc |
---|
0,0 → 1,138 |
// -*- C++ -*- Exception handling routines for catching. |
// Copyright (C) 2001, 2003, 2004, 2009, 2011 Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <cstdlib> |
#include "unwind-cxx.h" |
using namespace __cxxabiv1; |
extern "C" void * |
__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) _GLIBCXX_NOTHROW |
{ |
_Unwind_Exception *exceptionObject |
= reinterpret_cast <_Unwind_Exception *>(exc_obj_in); |
return __gxx_caught_object(exceptionObject); |
} |
extern "C" void * |
__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) _GLIBCXX_NOTHROW |
{ |
_Unwind_Exception *exceptionObject |
= reinterpret_cast <_Unwind_Exception *>(exc_obj_in); |
__cxa_eh_globals *globals = __cxa_get_globals (); |
__cxa_exception *prev = globals->caughtExceptions; |
__cxa_exception *header = __get_exception_header_from_ue (exceptionObject); |
void* objectp; |
// Foreign exceptions can't be stacked here. If the exception stack is |
// empty, then fine. Otherwise we really have no choice but to terminate. |
// Note that this use of "header" is a lie. It's fine so long as we only |
// examine header->unwindHeader though. |
if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) |
{ |
if (prev != 0) |
std::terminate (); |
// Remember for end_catch and rethrow. |
globals->caughtExceptions = header; |
// ??? No sensible value to return; we don't know what the |
// object is, much less where it is in relation to the header. |
return 0; |
} |
int count = header->handlerCount; |
// Count is less than zero if this exception was rethrown from an |
// immediately enclosing region. |
if (count < 0) |
count = -count + 1; |
else |
count += 1; |
header->handlerCount = count; |
globals->uncaughtExceptions -= 1; |
if (header != prev) |
{ |
header->nextException = prev; |
globals->caughtExceptions = header; |
} |
objectp = __gxx_caught_object(exceptionObject); |
#ifdef __ARM_EABI_UNWINDER__ |
_Unwind_Complete(exceptionObject); |
#endif |
return objectp; |
} |
extern "C" void |
__cxxabiv1::__cxa_end_catch () |
{ |
__cxa_eh_globals *globals = __cxa_get_globals_fast (); |
__cxa_exception *header = globals->caughtExceptions; |
// A rethrow of a foreign exception will be removed from the |
// the exception stack immediately by __cxa_rethrow. |
if (!header) |
return; |
// A foreign exception couldn't have been stacked (see above), |
// so by definition processing must be complete. |
if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) |
{ |
globals->caughtExceptions = 0; |
_Unwind_DeleteException (&header->unwindHeader); |
return; |
} |
int count = header->handlerCount; |
if (count < 0) |
{ |
// This exception was rethrown. Decrement the (inverted) catch |
// count and remove it from the chain when it reaches zero. |
if (++count == 0) |
globals->caughtExceptions = header->nextException; |
} |
else if (--count == 0) |
{ |
// Handling for this exception is complete. Destroy the object. |
globals->caughtExceptions = header->nextException; |
_Unwind_DeleteException (&header->unwindHeader); |
return; |
} |
else if (count < 0) |
// A bug in the exception handling library or compiler. |
std::terminate (); |
header->handlerCount = count; |
} |
bool |
std::uncaught_exception() throw() |
{ |
__cxa_eh_globals *globals = __cxa_get_globals (); |
return globals->uncaughtExceptions != 0; |
} |
/contrib/sdk/sources/libsupc++/eh_exception.cc |
---|
0,0 → 1,52 |
// -*- C++ -*- std::exception implementation. |
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
// 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "typeinfo" |
#include "exception" |
#include <cxxabi.h> |
std::exception::~exception() _GLIBCXX_USE_NOEXCEPT { } |
std::bad_exception::~bad_exception() _GLIBCXX_USE_NOEXCEPT { } |
abi::__forced_unwind::~__forced_unwind() throw() { } |
abi::__foreign_exception::~__foreign_exception() throw() { } |
const char* |
std::exception::what() const _GLIBCXX_USE_NOEXCEPT |
{ |
// NB: Another elegant option would be returning typeid(*this).name() |
// and not overriding what() in bad_exception, bad_alloc, etc. In |
// that case, however, mangled names would be returned, PR 14493. |
return "std::exception"; |
} |
const char* |
std::bad_exception::what() const _GLIBCXX_USE_NOEXCEPT |
{ |
return "std::bad_exception"; |
} |
/contrib/sdk/sources/libsupc++/eh_globals.cc |
---|
0,0 → 1,160 |
// -*- C++ -*- Manage the thread-local exception globals. |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2011 |
// Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <exception> |
#include <cstdlib> |
#include "cxxabi.h" |
#include "unwind-cxx.h" |
#include "bits/gthr.h" |
#if _GLIBCXX_HOSTED |
using std::free; |
using std::malloc; |
#else |
// In a freestanding environment, these functions may not be |
// available -- but for now, we assume that they are. |
extern "C" void *malloc (std::size_t); |
extern "C" void free(void *); |
#endif |
using namespace __cxxabiv1; |
#if _GLIBCXX_HAVE_TLS |
namespace |
{ |
abi::__cxa_eh_globals* |
get_global() _GLIBCXX_NOTHROW |
{ |
static __thread abi::__cxa_eh_globals global; |
return &global; |
} |
} // anonymous namespace |
extern "C" __cxa_eh_globals* |
__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW |
{ return get_global(); } |
extern "C" __cxa_eh_globals* |
__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW |
{ return get_global(); } |
#else |
// Single-threaded fallback buffer. |
static __cxa_eh_globals eh_globals; |
#if __GTHREADS |
static void |
eh_globals_dtor(void* ptr) |
{ |
if (ptr) |
{ |
__cxa_eh_globals* g = reinterpret_cast<__cxa_eh_globals*>(ptr); |
__cxa_exception* exn = g->caughtExceptions; |
__cxa_exception* next; |
while (exn) |
{ |
next = exn->nextException; |
_Unwind_DeleteException(&exn->unwindHeader); |
exn = next; |
} |
free(ptr); |
} |
} |
struct __eh_globals_init |
{ |
__gthread_key_t _M_key; |
bool _M_init; |
__eh_globals_init() : _M_init(false) |
{ |
if (__gthread_active_p()) |
_M_init = __gthread_key_create(&_M_key, eh_globals_dtor) == 0; |
} |
~__eh_globals_init() |
{ |
if (_M_init) |
__gthread_key_delete(_M_key); |
_M_init = false; |
} |
}; |
static __eh_globals_init init; |
extern "C" __cxa_eh_globals* |
__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW |
{ |
__cxa_eh_globals* g; |
if (init._M_init) |
g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key)); |
else |
g = &eh_globals; |
return g; |
} |
extern "C" __cxa_eh_globals* |
__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW |
{ |
__cxa_eh_globals* g; |
if (init._M_init) |
{ |
g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key)); |
if (!g) |
{ |
void* v = malloc(sizeof(__cxa_eh_globals)); |
if (v == 0 || __gthread_setspecific(init._M_key, v) != 0) |
std::terminate(); |
g = static_cast<__cxa_eh_globals*>(v); |
g->caughtExceptions = 0; |
g->uncaughtExceptions = 0; |
#ifdef __ARM_EABI_UNWINDER__ |
g->propagatingExceptions = 0; |
#endif |
} |
} |
else |
g = &eh_globals; |
return g; |
} |
#else |
extern "C" __cxa_eh_globals* |
__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW |
{ return &eh_globals; } |
extern "C" __cxa_eh_globals* |
__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW |
{ return &eh_globals; } |
#endif |
#endif |
/contrib/sdk/sources/libsupc++/eh_personality.cc |
---|
0,0 → 1,781 |
// -*- C++ -*- The GNU C++ exception personality routine. |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
// 2011 |
// Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <cstdlib> |
#include <bits/exception_defines.h> |
#include <cxxabi.h> |
#include "unwind-cxx.h" |
using namespace __cxxabiv1; |
#include "unwind-pe.h" |
struct lsda_header_info |
{ |
_Unwind_Ptr Start; |
_Unwind_Ptr LPStart; |
_Unwind_Ptr ttype_base; |
const unsigned char *TType; |
const unsigned char *action_table; |
unsigned char ttype_encoding; |
unsigned char call_site_encoding; |
}; |
static const unsigned char * |
parse_lsda_header (_Unwind_Context *context, const unsigned char *p, |
lsda_header_info *info) |
{ |
_uleb128_t tmp; |
unsigned char lpstart_encoding; |
info->Start = (context ? _Unwind_GetRegionStart (context) : 0); |
// Find @LPStart, the base to which landing pad offsets are relative. |
lpstart_encoding = *p++; |
if (lpstart_encoding != DW_EH_PE_omit) |
p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart); |
else |
info->LPStart = info->Start; |
// Find @TType, the base of the handler and exception spec type data. |
info->ttype_encoding = *p++; |
if (info->ttype_encoding != DW_EH_PE_omit) |
{ |
#if _GLIBCXX_OVERRIDE_TTYPE_ENCODING |
/* Older ARM EABI toolchains set this value incorrectly, so use a |
hardcoded OS-specific format. */ |
info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING; |
#endif |
p = read_uleb128 (p, &tmp); |
info->TType = p + tmp; |
} |
else |
info->TType = 0; |
// The encoding and length of the call-site table; the action table |
// immediately follows. |
info->call_site_encoding = *p++; |
p = read_uleb128 (p, &tmp); |
info->action_table = p + tmp; |
return p; |
} |
// Return an element from a type table. |
static const std::type_info* |
get_ttype_entry(lsda_header_info* info, _uleb128_t i) |
{ |
_Unwind_Ptr ptr; |
i *= size_of_encoded_value (info->ttype_encoding); |
read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, |
info->TType - i, &ptr); |
return reinterpret_cast<const std::type_info *>(ptr); |
} |
#ifdef __ARM_EABI_UNWINDER__ |
// The ABI provides a routine for matching exception object types. |
typedef _Unwind_Control_Block _throw_typet; |
#define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \ |
(__cxa_type_match (throw_type, catch_type, false, thrown_ptr_p) \ |
!= ctm_failed) |
// Return true if THROW_TYPE matches one if the filter types. |
static bool |
check_exception_spec(lsda_header_info* info, _throw_typet* throw_type, |
void* thrown_ptr, _sleb128_t filter_value) |
{ |
const _uleb128_t* e = ((const _uleb128_t*) info->TType) |
- filter_value - 1; |
while (1) |
{ |
const std::type_info* catch_type; |
_uleb128_t tmp; |
tmp = *e; |
// Zero signals the end of the list. If we've not found |
// a match by now, then we've failed the specification. |
if (tmp == 0) |
return false; |
tmp = _Unwind_decode_typeinfo_ptr(info->ttype_base, (_Unwind_Word) e); |
// Match a ttype entry. |
catch_type = reinterpret_cast<const std::type_info*>(tmp); |
// ??? There is currently no way to ask the RTTI code about the |
// relationship between two types without reference to a specific |
// object. There should be; then we wouldn't need to mess with |
// thrown_ptr here. |
if (get_adjusted_ptr(catch_type, throw_type, &thrown_ptr)) |
return true; |
// Advance to the next entry. |
e++; |
} |
} |
// Save stage1 handler information in the exception object |
static inline void |
save_caught_exception(struct _Unwind_Exception* ue_header, |
struct _Unwind_Context* context, |
void* thrown_ptr, |
int handler_switch_value, |
const unsigned char* language_specific_data, |
_Unwind_Ptr landing_pad, |
const unsigned char* action_record |
__attribute__((__unused__))) |
{ |
ue_header->barrier_cache.sp = _Unwind_GetGR(context, UNWIND_STACK_REG); |
ue_header->barrier_cache.bitpattern[0] = (_uw) thrown_ptr; |
ue_header->barrier_cache.bitpattern[1] |
= (_uw) handler_switch_value; |
ue_header->barrier_cache.bitpattern[2] |
= (_uw) language_specific_data; |
ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad; |
} |
// Restore the catch handler data saved during phase1. |
static inline void |
restore_caught_exception(struct _Unwind_Exception* ue_header, |
int& handler_switch_value, |
const unsigned char*& language_specific_data, |
_Unwind_Ptr& landing_pad) |
{ |
handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1]; |
language_specific_data = |
(const unsigned char*) ue_header->barrier_cache.bitpattern[2]; |
landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3]; |
} |
#define CONTINUE_UNWINDING \ |
do \ |
{ \ |
if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \ |
return _URC_FAILURE; \ |
return _URC_CONTINUE_UNWIND; \ |
} \ |
while (0) |
// Return true if the filter spec is empty, ie throw(). |
static bool |
empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value) |
{ |
const _Unwind_Word* e = ((const _Unwind_Word*) info->TType) |
- filter_value - 1; |
return *e == 0; |
} |
#else |
typedef const std::type_info _throw_typet; |
// Given the thrown type THROW_TYPE, pointer to a variable containing a |
// pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to |
// compare against, return whether or not there is a match and if so, |
// update *THROWN_PTR_P. |
static bool |
get_adjusted_ptr (const std::type_info *catch_type, |
const std::type_info *throw_type, |
void **thrown_ptr_p) |
{ |
void *thrown_ptr = *thrown_ptr_p; |
// Pointer types need to adjust the actual pointer, not |
// the pointer to pointer that is the exception object. |
// This also has the effect of passing pointer types |
// "by value" through the __cxa_begin_catch return value. |
if (throw_type->__is_pointer_p ()) |
thrown_ptr = *(void **) thrown_ptr; |
if (catch_type->__do_catch (throw_type, &thrown_ptr, 1)) |
{ |
*thrown_ptr_p = thrown_ptr; |
return true; |
} |
return false; |
} |
// Return true if THROW_TYPE matches one if the filter types. |
static bool |
check_exception_spec(lsda_header_info* info, _throw_typet* throw_type, |
void* thrown_ptr, _sleb128_t filter_value) |
{ |
const unsigned char *e = info->TType - filter_value - 1; |
while (1) |
{ |
const std::type_info *catch_type; |
_uleb128_t tmp; |
e = read_uleb128 (e, &tmp); |
// Zero signals the end of the list. If we've not found |
// a match by now, then we've failed the specification. |
if (tmp == 0) |
return false; |
// Match a ttype entry. |
catch_type = get_ttype_entry (info, tmp); |
// ??? There is currently no way to ask the RTTI code about the |
// relationship between two types without reference to a specific |
// object. There should be; then we wouldn't need to mess with |
// thrown_ptr here. |
if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr)) |
return true; |
} |
} |
// Save stage1 handler information in the exception object |
static inline void |
save_caught_exception(struct _Unwind_Exception* ue_header, |
struct _Unwind_Context* context |
__attribute__((__unused__)), |
void* thrown_ptr, |
int handler_switch_value, |
const unsigned char* language_specific_data, |
_Unwind_Ptr landing_pad __attribute__((__unused__)), |
const unsigned char* action_record) |
{ |
__cxa_exception* xh = __get_exception_header_from_ue(ue_header); |
xh->handlerSwitchValue = handler_switch_value; |
xh->actionRecord = action_record; |
xh->languageSpecificData = language_specific_data; |
xh->adjustedPtr = thrown_ptr; |
// ??? Completely unknown what this field is supposed to be for. |
// ??? Need to cache TType encoding base for call_unexpected. |
xh->catchTemp = landing_pad; |
} |
// Restore the catch handler information saved during phase1. |
static inline void |
restore_caught_exception(struct _Unwind_Exception* ue_header, |
int& handler_switch_value, |
const unsigned char*& language_specific_data, |
_Unwind_Ptr& landing_pad) |
{ |
__cxa_exception* xh = __get_exception_header_from_ue(ue_header); |
handler_switch_value = xh->handlerSwitchValue; |
language_specific_data = xh->languageSpecificData; |
landing_pad = (_Unwind_Ptr) xh->catchTemp; |
} |
#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND |
// Return true if the filter spec is empty, ie throw(). |
static bool |
empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value) |
{ |
const unsigned char *e = info->TType - filter_value - 1; |
_uleb128_t tmp; |
e = read_uleb128 (e, &tmp); |
return tmp == 0; |
} |
#endif // !__ARM_EABI_UNWINDER__ |
namespace __cxxabiv1 |
{ |
// Using a different personality function name causes link failures |
// when trying to mix code using different exception handling models. |
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS |
#define PERSONALITY_FUNCTION __gxx_personality_sj0 |
#define __builtin_eh_return_data_regno(x) x |
#else |
#define PERSONALITY_FUNCTION __gxx_personality_v0 |
#endif |
extern "C" _Unwind_Reason_Code |
#ifdef __ARM_EABI_UNWINDER__ |
PERSONALITY_FUNCTION (_Unwind_State state, |
struct _Unwind_Exception* ue_header, |
struct _Unwind_Context* context) |
#else |
PERSONALITY_FUNCTION (int version, |
_Unwind_Action actions, |
_Unwind_Exception_Class exception_class, |
struct _Unwind_Exception *ue_header, |
struct _Unwind_Context *context) |
#endif |
{ |
enum found_handler_type |
{ |
found_nothing, |
found_terminate, |
found_cleanup, |
found_handler |
} found_type; |
lsda_header_info info; |
const unsigned char *language_specific_data; |
const unsigned char *action_record; |
const unsigned char *p; |
_Unwind_Ptr landing_pad, ip; |
int handler_switch_value; |
void* thrown_ptr = 0; |
bool foreign_exception; |
int ip_before_insn = 0; |
#ifdef __ARM_EABI_UNWINDER__ |
_Unwind_Action actions; |
switch (state & _US_ACTION_MASK) |
{ |
case _US_VIRTUAL_UNWIND_FRAME: |
actions = _UA_SEARCH_PHASE; |
break; |
case _US_UNWIND_FRAME_STARTING: |
actions = _UA_CLEANUP_PHASE; |
if (!(state & _US_FORCE_UNWIND) |
&& ue_header->barrier_cache.sp == _Unwind_GetGR(context, |
UNWIND_STACK_REG)) |
actions |= _UA_HANDLER_FRAME; |
break; |
case _US_UNWIND_FRAME_RESUME: |
CONTINUE_UNWINDING; |
break; |
default: |
std::abort(); |
} |
actions |= state & _US_FORCE_UNWIND; |
// We don't know which runtime we're working with, so can't check this. |
// However the ABI routines hide this from us, and we don't actually need |
// to know. |
foreign_exception = false; |
// The dwarf unwinder assumes the context structure holds things like the |
// function and LSDA pointers. The ARM implementation caches these in |
// the exception header (UCB). To avoid rewriting everything we make a |
// virtual scratch register point at the UCB. |
ip = (_Unwind_Ptr) ue_header; |
_Unwind_SetGR(context, UNWIND_POINTER_REG, ip); |
#else |
__cxa_exception* xh = __get_exception_header_from_ue(ue_header); |
// Interface version check. |
if (version != 1) |
return _URC_FATAL_PHASE1_ERROR; |
foreign_exception = !__is_gxx_exception_class(exception_class); |
#endif |
// Shortcut for phase 2 found handler for domestic exception. |
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) |
&& !foreign_exception) |
{ |
restore_caught_exception(ue_header, handler_switch_value, |
language_specific_data, landing_pad); |
found_type = (landing_pad == 0 ? found_terminate : found_handler); |
goto install_context; |
} |
language_specific_data = (const unsigned char *) |
_Unwind_GetLanguageSpecificData (context); |
// If no LSDA, then there are no handlers or cleanups. |
if (! language_specific_data) |
CONTINUE_UNWINDING; |
// Parse the LSDA header. |
p = parse_lsda_header (context, language_specific_data, &info); |
info.ttype_base = base_of_encoded_value (info.ttype_encoding, context); |
#ifdef _GLIBCXX_HAVE_GETIPINFO |
ip = _Unwind_GetIPInfo (context, &ip_before_insn); |
#else |
ip = _Unwind_GetIP (context); |
#endif |
if (! ip_before_insn) |
--ip; |
landing_pad = 0; |
action_record = 0; |
handler_switch_value = 0; |
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS |
// The given "IP" is an index into the call-site table, with two |
// exceptions -- -1 means no-action, and 0 means terminate. But |
// since we're using uleb128 values, we've not got random access |
// to the array. |
if ((int) ip < 0) |
return _URC_CONTINUE_UNWIND; |
else if (ip == 0) |
{ |
// Fall through to set found_terminate. |
} |
else |
{ |
_uleb128_t cs_lp, cs_action; |
do |
{ |
p = read_uleb128 (p, &cs_lp); |
p = read_uleb128 (p, &cs_action); |
} |
while (--ip); |
// Can never have null landing pad for sjlj -- that would have |
// been indicated by a -1 call site index. |
landing_pad = cs_lp + 1; |
if (cs_action) |
action_record = info.action_table + cs_action - 1; |
goto found_something; |
} |
#else |
// Search the call-site table for the action associated with this IP. |
while (p < info.action_table) |
{ |
_Unwind_Ptr cs_start, cs_len, cs_lp; |
_uleb128_t cs_action; |
// Note that all call-site encodings are "absolute" displacements. |
p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); |
p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); |
p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); |
p = read_uleb128 (p, &cs_action); |
// The table is sorted, so if we've passed the ip, stop. |
if (ip < info.Start + cs_start) |
p = info.action_table; |
else if (ip < info.Start + cs_start + cs_len) |
{ |
if (cs_lp) |
landing_pad = info.LPStart + cs_lp; |
if (cs_action) |
action_record = info.action_table + cs_action - 1; |
goto found_something; |
} |
} |
#endif // _GLIBCXX_SJLJ_EXCEPTIONS |
// If ip is not present in the table, call terminate. This is for |
// a destructor inside a cleanup, or a library routine the compiler |
// was not expecting to throw. |
found_type = found_terminate; |
goto do_something; |
found_something: |
if (landing_pad == 0) |
{ |
// If ip is present, and has a null landing pad, there are |
// no cleanups or handlers to be run. |
found_type = found_nothing; |
} |
else if (action_record == 0) |
{ |
// If ip is present, has a non-null landing pad, and a null |
// action table offset, then there are only cleanups present. |
// Cleanups use a zero switch value, as set above. |
found_type = found_cleanup; |
} |
else |
{ |
// Otherwise we have a catch handler or exception specification. |
_sleb128_t ar_filter, ar_disp; |
const std::type_info* catch_type; |
_throw_typet* throw_type; |
bool saw_cleanup = false; |
bool saw_handler = false; |
#ifdef __ARM_EABI_UNWINDER__ |
// ??? How does this work - more importantly, how does it interact with |
// dependent exceptions? |
throw_type = ue_header; |
if (actions & _UA_FORCE_UNWIND) |
{ |
__GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class); |
} |
else if (!foreign_exception) |
thrown_ptr = __get_object_from_ue (ue_header); |
#else |
#ifdef __GXX_RTTI |
// During forced unwinding, match a magic exception type. |
if (actions & _UA_FORCE_UNWIND) |
{ |
throw_type = &typeid(abi::__forced_unwind); |
} |
// With a foreign exception class, there's no exception type. |
// ??? What to do about GNU Java and GNU Ada exceptions? |
else if (foreign_exception) |
{ |
throw_type = &typeid(abi::__foreign_exception); |
} |
else |
#endif |
{ |
thrown_ptr = __get_object_from_ue (ue_header); |
throw_type = __get_exception_header_from_obj |
(thrown_ptr)->exceptionType; |
} |
#endif |
while (1) |
{ |
p = action_record; |
p = read_sleb128 (p, &ar_filter); |
read_sleb128 (p, &ar_disp); |
if (ar_filter == 0) |
{ |
// Zero filter values are cleanups. |
saw_cleanup = true; |
} |
else if (ar_filter > 0) |
{ |
// Positive filter values are handlers. |
catch_type = get_ttype_entry (&info, ar_filter); |
// Null catch type is a catch-all handler; we can catch foreign |
// exceptions with this. Otherwise we must match types. |
if (! catch_type |
|| (throw_type |
&& get_adjusted_ptr (catch_type, throw_type, |
&thrown_ptr))) |
{ |
saw_handler = true; |
break; |
} |
} |
else |
{ |
// Negative filter values are exception specifications. |
// ??? How do foreign exceptions fit in? As far as I can |
// see we can't match because there's no __cxa_exception |
// object to stuff bits in for __cxa_call_unexpected to use. |
// Allow them iff the exception spec is non-empty. I.e. |
// a throw() specification results in __unexpected. |
if ((throw_type |
&& !(actions & _UA_FORCE_UNWIND) |
&& !foreign_exception) |
? ! check_exception_spec (&info, throw_type, thrown_ptr, |
ar_filter) |
: empty_exception_spec (&info, ar_filter)) |
{ |
saw_handler = true; |
break; |
} |
} |
if (ar_disp == 0) |
break; |
action_record = p + ar_disp; |
} |
if (saw_handler) |
{ |
handler_switch_value = ar_filter; |
found_type = found_handler; |
} |
else |
found_type = (saw_cleanup ? found_cleanup : found_nothing); |
} |
do_something: |
if (found_type == found_nothing) |
CONTINUE_UNWINDING; |
if (actions & _UA_SEARCH_PHASE) |
{ |
if (found_type == found_cleanup) |
CONTINUE_UNWINDING; |
// For domestic exceptions, we cache data from phase 1 for phase 2. |
if (!foreign_exception) |
{ |
save_caught_exception(ue_header, context, thrown_ptr, |
handler_switch_value, language_specific_data, |
landing_pad, action_record); |
} |
return _URC_HANDLER_FOUND; |
} |
install_context: |
// We can't use any of the cxa routines with foreign exceptions, |
// because they all expect ue_header to be a struct __cxa_exception. |
// So in that case, call terminate or unexpected directly. |
if ((actions & _UA_FORCE_UNWIND) |
|| foreign_exception) |
{ |
if (found_type == found_terminate) |
std::terminate (); |
else if (handler_switch_value < 0) |
{ |
__try |
{ std::unexpected (); } |
__catch(...) |
{ std::terminate (); } |
} |
} |
else |
{ |
if (found_type == found_terminate) |
__cxa_call_terminate(ue_header); |
// Cache the TType base value for __cxa_call_unexpected, as we won't |
// have an _Unwind_Context then. |
if (handler_switch_value < 0) |
{ |
parse_lsda_header (context, language_specific_data, &info); |
info.ttype_base = base_of_encoded_value (info.ttype_encoding, |
context); |
#ifdef __ARM_EABI_UNWINDER__ |
const _Unwind_Word* e; |
_Unwind_Word n; |
e = ((const _Unwind_Word*) info.TType) - handler_switch_value - 1; |
// Count the number of rtti objects. |
n = 0; |
while (e[n] != 0) |
n++; |
// Count. |
ue_header->barrier_cache.bitpattern[1] = n; |
// Base |
ue_header->barrier_cache.bitpattern[2] = info.ttype_base; |
// Stride. |
ue_header->barrier_cache.bitpattern[3] = 4; |
// List head. |
ue_header->barrier_cache.bitpattern[4] = (_Unwind_Word) e; |
#else |
xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context); |
#endif |
} |
} |
/* For targets with pointers smaller than the word size, we must extend the |
pointer, and this extension is target dependent. */ |
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0), |
__builtin_extend_pointer (ue_header)); |
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1), |
handler_switch_value); |
_Unwind_SetIP (context, landing_pad); |
#ifdef __ARM_EABI_UNWINDER__ |
if (found_type == found_cleanup) |
__cxa_begin_cleanup(ue_header); |
#endif |
return _URC_INSTALL_CONTEXT; |
} |
/* The ARM EABI implementation of __cxa_call_unexpected is in a |
different file so that the personality routine (PR) can be used |
standalone. The generic routine shared datastructures with the PR |
so it is most convenient to implement it here. */ |
#ifndef __ARM_EABI_UNWINDER__ |
extern "C" void |
__cxa_call_unexpected (void *exc_obj_in) |
{ |
_Unwind_Exception *exc_obj |
= reinterpret_cast <_Unwind_Exception *>(exc_obj_in); |
__cxa_begin_catch (exc_obj); |
// This function is a handler for our exception argument. If we exit |
// by throwing a different exception, we'll need the original cleaned up. |
struct end_catch_protect |
{ |
end_catch_protect() { } |
~end_catch_protect() { __cxa_end_catch(); } |
} end_catch_protect_obj; |
lsda_header_info info; |
__cxa_exception *xh = __get_exception_header_from_ue (exc_obj); |
const unsigned char *xh_lsda; |
_Unwind_Sword xh_switch_value; |
std::terminate_handler xh_terminate_handler; |
// If the unexpectedHandler rethrows the exception (e.g. to categorize it), |
// it will clobber data about the current handler. So copy the data out now. |
xh_lsda = xh->languageSpecificData; |
xh_switch_value = xh->handlerSwitchValue; |
xh_terminate_handler = xh->terminateHandler; |
info.ttype_base = (_Unwind_Ptr) xh->catchTemp; |
__try |
{ __unexpected (xh->unexpectedHandler); } |
__catch(...) |
{ |
// Get the exception thrown from unexpected. |
__cxa_eh_globals *globals = __cxa_get_globals_fast (); |
__cxa_exception *new_xh = globals->caughtExceptions; |
void *new_ptr = __get_object_from_ambiguous_exception (new_xh); |
// We don't quite have enough stuff cached; re-parse the LSDA. |
parse_lsda_header (0, xh_lsda, &info); |
// If this new exception meets the exception spec, allow it. |
if (check_exception_spec (&info, __get_exception_header_from_obj |
(new_ptr)->exceptionType, |
new_ptr, xh_switch_value)) |
__throw_exception_again; |
// If the exception spec allows std::bad_exception, throw that. |
// We don't have a thrown object to compare against, but since |
// bad_exception doesn't have virtual bases, that's OK; just pass 0. |
#if defined(__EXCEPTIONS) && defined(__GXX_RTTI) |
const std::type_info &bad_exc = typeid (std::bad_exception); |
if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value)) |
throw std::bad_exception(); |
#endif |
// Otherwise, die. |
__terminate (xh_terminate_handler); |
} |
} |
#endif |
} // namespace __cxxabiv1 |
/contrib/sdk/sources/libsupc++/eh_term_handler.cc |
---|
0,0 → 1,46 |
// -*- C++ -*- std::terminate handler |
// Copyright (C) 2002, 2003, 2009 Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include "unwind-cxx.h" |
/* We default to the talkative, informative handler in a normal hosted |
library. This pulls in the demangler, the dyn-string utilities, and |
elements of the I/O library. For a low-memory environment, you can return |
to the earlier "silent death" handler by including <cstdlib>, initializing |
to "std::abort", and rebuilding the library. In a freestanding mode, we |
default to this latter approach. */ |
#if ! _GLIBCXX_HOSTED |
# include <cstdlib> |
#endif |
/* The current installed user handler. */ |
std::terminate_handler __cxxabiv1::__terminate_handler = |
#if _GLIBCXX_HOSTED |
__gnu_cxx::__verbose_terminate_handler; |
#else |
std::abort; |
#endif |
/contrib/sdk/sources/libsupc++/eh_terminate.cc |
---|
0,0 → 1,80 |
// -*- C++ -*- std::terminate, std::unexpected and friends. |
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2009, |
// 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "typeinfo" |
#include "exception" |
#include <cstdlib> |
#include "unwind-cxx.h" |
#include <bits/exception_defines.h> |
using namespace __cxxabiv1; |
void |
__cxxabiv1::__terminate (std::terminate_handler handler) throw () |
{ |
__try |
{ |
handler (); |
std::abort (); |
} |
__catch(...) |
{ std::abort (); } |
} |
void |
std::terminate () throw() |
{ |
__terminate (__terminate_handler); |
} |
void |
__cxxabiv1::__unexpected (std::unexpected_handler handler) |
{ |
handler(); |
std::terminate (); |
} |
void |
std::unexpected () |
{ |
__unexpected (__unexpected_handler); |
} |
std::terminate_handler |
std::set_terminate (std::terminate_handler func) throw() |
{ |
std::terminate_handler old = __terminate_handler; |
__terminate_handler = func; |
return old; |
} |
std::unexpected_handler |
std::set_unexpected (std::unexpected_handler func) throw() |
{ |
std::unexpected_handler old = __unexpected_handler; |
__unexpected_handler = func; |
return old; |
} |
/contrib/sdk/sources/libsupc++/eh_throw.cc |
---|
0,0 → 1,117 |
// -*- C++ -*- Exception handling routines for throwing. |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
// 2011, 2012 Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include "unwind-cxx.h" |
using namespace __cxxabiv1; |
static void |
__gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc) |
{ |
// This cleanup is set only for primaries. |
__cxa_refcounted_exception *header |
= __get_refcounted_exception_header_from_ue (exc); |
// We only want to be called through _Unwind_DeleteException. |
// _Unwind_DeleteException in the HP-UX IA64 libunwind library |
// returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT |
// like the GCC _Unwind_DeleteException function does. |
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON) |
__terminate (header->exc.terminateHandler); |
#if ATOMIC_INT_LOCK_FREE > 1 |
if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0) |
{ |
#endif |
if (header->exc.exceptionDestructor) |
header->exc.exceptionDestructor (header + 1); |
__cxa_free_exception (header + 1); |
#if ATOMIC_INT_LOCK_FREE > 1 |
} |
#endif |
} |
extern "C" void |
__cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo, |
void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) |
{ |
// Definitely a primary. |
__cxa_refcounted_exception *header |
= __get_refcounted_exception_header_from_obj (obj); |
header->referenceCount = 1; |
header->exc.exceptionType = tinfo; |
header->exc.exceptionDestructor = dest; |
header->exc.unexpectedHandler = __unexpected_handler; |
header->exc.terminateHandler = __terminate_handler; |
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class); |
header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup; |
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS |
_Unwind_SjLj_RaiseException (&header->exc.unwindHeader); |
#else |
_Unwind_RaiseException (&header->exc.unwindHeader); |
#endif |
// Some sort of unwinding error. Note that terminate is a handler. |
__cxa_begin_catch (&header->exc.unwindHeader); |
std::terminate (); |
} |
extern "C" void |
__cxxabiv1::__cxa_rethrow () |
{ |
__cxa_eh_globals *globals = __cxa_get_globals (); |
__cxa_exception *header = globals->caughtExceptions; |
globals->uncaughtExceptions += 1; |
// Watch for luser rethrowing with no active exception. |
if (header) |
{ |
// Tell __cxa_end_catch this is a rethrow. |
if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) |
globals->caughtExceptions = 0; |
else |
header->handlerCount = -header->handlerCount; |
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS |
_Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader); |
#else |
#if defined(_LIBUNWIND_STD_ABI) |
_Unwind_RaiseException (&header->unwindHeader); |
#else |
_Unwind_Resume_or_Rethrow (&header->unwindHeader); |
#endif |
#endif |
// Some sort of unwinding error. Note that terminate is a handler. |
__cxa_begin_catch (&header->unwindHeader); |
} |
std::terminate (); |
} |
/contrib/sdk/sources/libsupc++/eh_type.cc |
---|
0,0 → 1,54 |
// -*- C++ -*- Exception handling routines for catching. |
// Copyright (C) 2001, 2008, 2009, 2011 Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <typeinfo> |
#include <cxxabi.h> |
#include "unwind-cxx.h" |
namespace __cxxabiv1 |
{ |
// Returns the type_info for the currently handled exception [15.3/8], or |
// null if there is none. |
extern "C" |
std::type_info *__cxa_current_exception_type () _GLIBCXX_NOTHROW |
{ |
__cxa_eh_globals *globals = __cxa_get_globals (); |
__cxa_exception *header = globals->caughtExceptions; |
if (header) |
{ |
if (__is_dependent_exception (header->unwindHeader.exception_class)) |
{ |
__cxa_dependent_exception *de = |
__get_dependent_exception_from_ue (&header->unwindHeader); |
header = __get_exception_header_from_obj (de->primaryException); |
} |
return header->exceptionType; |
} |
else |
return 0; |
} |
} // namespace __cxxabiv1 |
/contrib/sdk/sources/libsupc++/eh_unex_handler.cc |
---|
0,0 → 1,29 |
// -*- C++ -*- std::unexpected handler |
// Copyright (C) 2002, 2009 Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "unwind-cxx.h" |
/* The current installed user handler. */ |
std::unexpected_handler __cxxabiv1::__unexpected_handler = std::terminate; |
/contrib/sdk/sources/libsupc++/exception |
---|
0,0 → 1,158 |
// Exception Handling support header for -*- C++ -*- |
// Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
// 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
/** @file exception |
* This is a Standard C++ Library header. |
*/ |
#ifndef __EXCEPTION__ |
#define __EXCEPTION__ |
#pragma GCC system_header |
#pragma GCC visibility push(default) |
#include <bits/c++config.h> |
#include <bits/atomic_lockfree_defines.h> |
extern "C++" { |
namespace std |
{ |
/** |
* @defgroup exceptions Exceptions |
* @ingroup diagnostics |
* |
* Classes and functions for reporting errors via exception classes. |
* @{ |
*/ |
/** |
* @brief Base class for all library exceptions. |
* |
* This is the base class for all exceptions thrown by the standard |
* library, and by certain language expressions. You are free to derive |
* your own %exception classes, or use a different hierarchy, or to |
* throw non-class data (e.g., fundamental types). |
*/ |
class exception |
{ |
public: |
exception() _GLIBCXX_USE_NOEXCEPT { } |
virtual ~exception() _GLIBCXX_USE_NOEXCEPT; |
/** Returns a C-style character string describing the general cause |
* of the current error. */ |
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; |
}; |
/** If an %exception is thrown which is not listed in a function's |
* %exception specification, one of these may be thrown. */ |
class bad_exception : public exception |
{ |
public: |
bad_exception() _GLIBCXX_USE_NOEXCEPT { } |
// This declaration is not useless: |
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
virtual ~bad_exception() _GLIBCXX_USE_NOEXCEPT; |
// See comment in eh_exception.cc. |
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; |
}; |
/// If you write a replacement %terminate handler, it must be of this type. |
typedef void (*terminate_handler) (); |
/// If you write a replacement %unexpected handler, it must be of this type. |
typedef void (*unexpected_handler) (); |
/// Takes a new handler function as an argument, returns the old function. |
terminate_handler set_terminate(terminate_handler) _GLIBCXX_USE_NOEXCEPT; |
/** The runtime will call this function if %exception handling must be |
* abandoned for any reason. It can also be called by the user. */ |
void terminate() _GLIBCXX_USE_NOEXCEPT __attribute__ ((__noreturn__)); |
/// Takes a new handler function as an argument, returns the old function. |
unexpected_handler set_unexpected(unexpected_handler) _GLIBCXX_USE_NOEXCEPT; |
/** The runtime will call this function if an %exception is thrown which |
* violates the function's %exception specification. */ |
void unexpected() __attribute__ ((__noreturn__)); |
/** [18.6.4]/1: 'Returns true after completing evaluation of a |
* throw-expression until either completing initialization of the |
* exception-declaration in the matching handler or entering @c unexpected() |
* due to the throw; or after entering @c terminate() for any reason |
* other than an explicit call to @c terminate(). [Note: This includes |
* stack unwinding [15.2]. end note]' |
* |
* 2: 'When @c uncaught_exception() is true, throwing an |
* %exception can result in a call of @c terminate() |
* (15.5.1).' |
*/ |
bool uncaught_exception() _GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__)); |
// @} group exceptions |
} // namespace std |
namespace __gnu_cxx |
{ |
_GLIBCXX_BEGIN_NAMESPACE_VERSION |
/** |
* @brief A replacement for the standard terminate_handler which |
* prints more information about the terminating exception (if any) |
* on stderr. |
* |
* @ingroup exceptions |
* |
* Call |
* @code |
* std::set_terminate(__gnu_cxx::__verbose_terminate_handler) |
* @endcode |
* to use. For more info, see |
* http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt02ch06s02.html |
* |
* In 3.4 and later, this is on by default. |
*/ |
void __verbose_terminate_handler(); |
_GLIBCXX_END_NAMESPACE_VERSION |
} // namespace |
} // extern "C++" |
#pragma GCC visibility pop |
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && (ATOMIC_INT_LOCK_FREE > 1) |
#include <bits/exception_ptr.h> |
#include <bits/nested_exception.h> |
#endif |
#endif |
/contrib/sdk/sources/libsupc++/exception_defines.h |
---|
0,0 → 1,47 |
// -fno-exceptions Support -*- C++ -*- |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2006, 2007, 2008, 2009, |
// 2011 |
// Free Software Foundation, Inc. |
// |
// This file is part of the GNU ISO C++ Library. This library is free |
// software; you can redistribute it and/or modify it under the |
// terms of the GNU General Public License as published by the |
// Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// This library is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
/** @file bits/exception_defines.h |
* This is an internal header file, included by other library headers. |
* Do not attempt to use it directly. @headername{exception} |
*/ |
#ifndef _EXCEPTION_DEFINES_H |
#define _EXCEPTION_DEFINES_H 1 |
#ifndef __EXCEPTIONS |
// Iff -fno-exceptions, transform error handling code to work without it. |
# define __try if (true) |
# define __catch(X) if (false) |
# define __throw_exception_again |
#else |
// Else proceed normally. |
# define __try try |
# define __catch(X) catch(X) |
# define __throw_exception_again throw |
#endif |
#endif |
/contrib/sdk/sources/libsupc++/guard.cc |
---|
0,0 → 1,416 |
// Copyright (C) 2002, 2004, 2006, 2008, 2009, 2010, 2011, 2012 |
// Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
// Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com> |
// Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com> |
#include <bits/c++config.h> |
#include <cxxabi.h> |
#include <exception> |
#include <new> |
#include <ext/atomicity.h> |
#include <ext/concurrence.h> |
#if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \ |
&& (ATOMIC_INT_LOCK_FREE > 1) && defined(_GLIBCXX_HAVE_LINUX_FUTEX) |
# include <climits> |
# include <syscall.h> |
# include <unistd.h> |
# define _GLIBCXX_USE_FUTEX |
# define _GLIBCXX_FUTEX_WAIT 0 |
# define _GLIBCXX_FUTEX_WAKE 1 |
#endif |
// The IA64/generic ABI uses the first byte of the guard variable. |
// The ARM EABI uses the least significant bit. |
// Thread-safe static local initialization support. |
#ifdef __GTHREADS |
# ifndef _GLIBCXX_USE_FUTEX |
namespace |
{ |
// A single mutex controlling all static initializations. |
static __gnu_cxx::__recursive_mutex* static_mutex; |
typedef char fake_recursive_mutex[sizeof(__gnu_cxx::__recursive_mutex)] |
__attribute__ ((aligned(__alignof__(__gnu_cxx::__recursive_mutex)))); |
fake_recursive_mutex fake_mutex; |
static void init() |
{ static_mutex = new (&fake_mutex) __gnu_cxx::__recursive_mutex(); } |
__gnu_cxx::__recursive_mutex& |
get_static_mutex() |
{ |
static __gthread_once_t once = __GTHREAD_ONCE_INIT; |
__gthread_once(&once, init); |
return *static_mutex; |
} |
// Simple wrapper for exception safety. |
struct mutex_wrapper |
{ |
bool unlock; |
mutex_wrapper() : unlock(true) |
{ get_static_mutex().lock(); } |
~mutex_wrapper() |
{ |
if (unlock) |
static_mutex->unlock(); |
} |
}; |
} |
# endif |
# if defined(__GTHREAD_HAS_COND) && !defined(_GLIBCXX_USE_FUTEX) |
namespace |
{ |
// A single condition variable controlling all static initializations. |
static __gnu_cxx::__cond* static_cond; |
// using a fake type to avoid initializing a static class. |
typedef char fake_cond_t[sizeof(__gnu_cxx::__cond)] |
__attribute__ ((aligned(__alignof__(__gnu_cxx::__cond)))); |
fake_cond_t fake_cond; |
static void init_static_cond() |
{ static_cond = new (&fake_cond) __gnu_cxx::__cond(); } |
__gnu_cxx::__cond& |
get_static_cond() |
{ |
static __gthread_once_t once = __GTHREAD_ONCE_INIT; |
__gthread_once(&once, init_static_cond); |
return *static_cond; |
} |
} |
# endif |
# ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE |
inline bool |
__test_and_acquire (__cxxabiv1::__guard *g) |
{ |
bool b = _GLIBCXX_GUARD_TEST (g); |
_GLIBCXX_READ_MEM_BARRIER; |
return b; |
} |
# define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G) |
# endif |
# ifndef _GLIBCXX_GUARD_SET_AND_RELEASE |
inline void |
__set_and_release (__cxxabiv1::__guard *g) |
{ |
_GLIBCXX_WRITE_MEM_BARRIER; |
_GLIBCXX_GUARD_SET (g); |
} |
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G) |
# endif |
#else /* !__GTHREADS */ |
# undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE |
# undef _GLIBCXX_GUARD_SET_AND_RELEASE |
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G) |
#endif /* __GTHREADS */ |
// |
// Here are C++ run-time routines for guarded initialization of static |
// variables. There are 4 scenarios under which these routines are called: |
// |
// 1. Threads not supported (__GTHREADS not defined) |
// 2. Threads are supported but not enabled at run-time. |
// 3. Threads enabled at run-time but __gthreads_* are not fully POSIX. |
// 4. Threads enabled at run-time and __gthreads_* support all POSIX threads |
// primitives we need here. |
// |
// The old code supported scenarios 1-3 but was broken since it used a global |
// mutex for all threads and had the mutex locked during the whole duration of |
// initialization of a guarded static variable. The following created a |
// dead-lock with the old code. |
// |
// Thread 1 acquires the global mutex. |
// Thread 1 starts initializing static variable. |
// Thread 1 creates thread 2 during initialization. |
// Thread 2 attempts to acquire mutex to initialize another variable. |
// Thread 2 blocks since thread 1 is locking the mutex. |
// Thread 1 waits for result from thread 2 and also blocks. A deadlock. |
// |
// The new code here can handle this situation and thus is more robust. However, |
// we need to use the POSIX thread condition variable, which is not supported |
// in all platforms, notably older versions of Microsoft Windows. The gthr*.h |
// headers define a symbol __GTHREAD_HAS_COND for platforms that support POSIX |
// like condition variables. For platforms that do not support condition |
// variables, we need to fall back to the old code. |
// If _GLIBCXX_USE_FUTEX, no global mutex or condition variable is used, |
// only atomic operations are used together with futex syscall. |
// Valid values of the first integer in guard are: |
// 0 No thread encountered the guarded init |
// yet or it has been aborted. |
// _GLIBCXX_GUARD_BIT The guarded static var has been successfully |
// initialized. |
// _GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized |
// and no other thread is waiting for its |
// initialization. |
// (_GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized |
// | _GLIBCXX_GUARD_WAITING_BIT) and some other threads are waiting until |
// it is initialized. |
namespace __cxxabiv1 |
{ |
#ifdef _GLIBCXX_USE_FUTEX |
namespace |
{ |
static inline int __guard_test_bit (const int __byte, const int __val) |
{ |
union { int __i; char __c[sizeof (int)]; } __u = { 0 }; |
__u.__c[__byte] = __val; |
return __u.__i; |
} |
} |
#endif |
static inline int |
init_in_progress_flag(__guard* g) |
{ return ((char *)g)[1]; } |
static inline void |
set_init_in_progress_flag(__guard* g, int v) |
{ ((char *)g)[1] = v; } |
static inline void |
throw_recursive_init_exception() |
{ |
#ifdef __EXCEPTIONS |
throw __gnu_cxx::recursive_init_error(); |
#else |
// Use __builtin_trap so we don't require abort(). |
__builtin_trap(); |
#endif |
} |
// acquire() is a helper function used to acquire guard if thread support is |
// not compiled in or is compiled in but not enabled at run-time. |
static int |
acquire(__guard *g) |
{ |
// Quit if the object is already initialized. |
if (_GLIBCXX_GUARD_TEST(g)) |
return 0; |
if (init_in_progress_flag(g)) |
throw_recursive_init_exception(); |
set_init_in_progress_flag(g, 1); |
return 1; |
} |
extern "C" |
int __cxa_guard_acquire (__guard *g) |
{ |
#ifdef __GTHREADS |
// If the target can reorder loads, we need to insert a read memory |
// barrier so that accesses to the guarded variable happen after the |
// guard test. |
if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g)) |
return 0; |
# ifdef _GLIBCXX_USE_FUTEX |
// If __atomic_* and futex syscall are supported, don't use any global |
// mutex. |
if (__gthread_active_p ()) |
{ |
int *gi = (int *) (void *) g; |
const int guard_bit = _GLIBCXX_GUARD_BIT; |
const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT; |
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT; |
while (1) |
{ |
int expected(0); |
if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false, |
__ATOMIC_ACQ_REL, |
__ATOMIC_ACQUIRE)) |
{ |
// This thread should do the initialization. |
return 1; |
} |
if (expected == guard_bit) |
{ |
// Already initialized. |
return 0; |
} |
if (expected == pending_bit) |
{ |
// Use acquire here. |
int newv = expected | waiting_bit; |
if (!__atomic_compare_exchange_n(gi, &expected, newv, false, |
__ATOMIC_ACQ_REL, |
__ATOMIC_ACQUIRE)) |
{ |
if (expected == guard_bit) |
{ |
// Make a thread that failed to set the |
// waiting bit exit the function earlier, |
// if it detects that another thread has |
// successfully finished initialising. |
return 0; |
} |
if (expected == 0) |
continue; |
} |
expected = newv; |
} |
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, expected, 0); |
} |
} |
# else |
if (__gthread_active_p ()) |
{ |
mutex_wrapper mw; |
while (1) // When this loop is executing, mutex is locked. |
{ |
# ifdef __GTHREAD_HAS_COND |
// The static is already initialized. |
if (_GLIBCXX_GUARD_TEST(g)) |
return 0; // The mutex will be unlocked via wrapper |
if (init_in_progress_flag(g)) |
{ |
// The guarded static is currently being initialized by |
// another thread, so we release mutex and wait for the |
// condition variable. We will lock the mutex again after |
// this. |
get_static_cond().wait_recursive(&get_static_mutex()); |
} |
else |
{ |
set_init_in_progress_flag(g, 1); |
return 1; // The mutex will be unlocked via wrapper. |
} |
# else |
// This provides compatibility with older systems not supporting |
// POSIX like condition variables. |
if (acquire(g)) |
{ |
mw.unlock = false; |
return 1; // The mutex still locked. |
} |
return 0; // The mutex will be unlocked via wrapper. |
# endif |
} |
} |
# endif |
#endif |
return acquire (g); |
} |
extern "C" |
void __cxa_guard_abort (__guard *g) throw () |
{ |
#ifdef _GLIBCXX_USE_FUTEX |
// If __atomic_* and futex syscall are supported, don't use any global |
// mutex. |
if (__gthread_active_p ()) |
{ |
int *gi = (int *) (void *) g; |
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT; |
int old = __atomic_exchange_n (gi, 0, __ATOMIC_ACQ_REL); |
if ((old & waiting_bit) != 0) |
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX); |
return; |
} |
#elif defined(__GTHREAD_HAS_COND) |
if (__gthread_active_p()) |
{ |
mutex_wrapper mw; |
set_init_in_progress_flag(g, 0); |
// If we abort, we still need to wake up all other threads waiting for |
// the condition variable. |
get_static_cond().broadcast(); |
return; |
} |
#endif |
set_init_in_progress_flag(g, 0); |
#if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND) |
// This provides compatibility with older systems not supporting POSIX like |
// condition variables. |
if (__gthread_active_p ()) |
static_mutex->unlock(); |
#endif |
} |
extern "C" |
void __cxa_guard_release (__guard *g) throw () |
{ |
#ifdef _GLIBCXX_USE_FUTEX |
// If __atomic_* and futex syscall are supported, don't use any global |
// mutex. |
if (__gthread_active_p ()) |
{ |
int *gi = (int *) (void *) g; |
const int guard_bit = _GLIBCXX_GUARD_BIT; |
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT; |
int old = __atomic_exchange_n (gi, guard_bit, __ATOMIC_ACQ_REL); |
if ((old & waiting_bit) != 0) |
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX); |
return; |
} |
#elif defined(__GTHREAD_HAS_COND) |
if (__gthread_active_p()) |
{ |
mutex_wrapper mw; |
set_init_in_progress_flag(g, 0); |
_GLIBCXX_GUARD_SET_AND_RELEASE(g); |
get_static_cond().broadcast(); |
return; |
} |
#endif |
set_init_in_progress_flag(g, 0); |
_GLIBCXX_GUARD_SET_AND_RELEASE (g); |
#if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND) |
// This provides compatibility with older systems not supporting POSIX like |
// condition variables. |
if (__gthread_active_p()) |
static_mutex->unlock(); |
#endif |
} |
} |
/contrib/sdk/sources/libsupc++/guard_error.cc |
---|
0,0 → 1,31 |
// Copyright (C) 2011 Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <cxxabi.h> |
namespace __gnu_cxx |
{ |
recursive_init_error::~recursive_init_error() throw() { } |
} |
/contrib/sdk/sources/libsupc++/initializer_list |
---|
0,0 → 1,107 |
// std::initializer_list support -*- C++ -*- |
// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
/** @file initializer_list |
* This is a Standard C++ Library header. |
*/ |
#ifndef _INITIALIZER_LIST |
#define _INITIALIZER_LIST |
#pragma GCC system_header |
#ifndef __GXX_EXPERIMENTAL_CXX0X__ |
# include <bits/c++0x_warning.h> |
#else // C++0x |
#pragma GCC visibility push(default) |
#include <bits/c++config.h> |
namespace std |
{ |
/// initializer_list |
template<class _E> |
class initializer_list |
{ |
public: |
typedef _E value_type; |
typedef const _E& reference; |
typedef const _E& const_reference; |
typedef size_t size_type; |
typedef const _E* iterator; |
typedef const _E* const_iterator; |
private: |
iterator _M_array; |
size_type _M_len; |
// The compiler can call a private constructor. |
constexpr initializer_list(const_iterator __a, size_type __l) |
: _M_array(__a), _M_len(__l) { } |
public: |
constexpr initializer_list() noexcept |
: _M_array(0), _M_len(0) { } |
// Number of elements. |
constexpr size_type |
size() const noexcept { return _M_len; } |
// First element. |
constexpr const_iterator |
begin() const noexcept { return _M_array; } |
// One past the last element. |
constexpr const_iterator |
end() const noexcept { return begin() + size(); } |
}; |
/** |
* @brief Return an iterator pointing to the first element of |
* the initilizer_list. |
* @param __ils Initializer list. |
*/ |
template<class _Tp> |
constexpr const _Tp* |
begin(initializer_list<_Tp> __ils) noexcept |
{ return __ils.begin(); } |
/** |
* @brief Return an iterator pointing to one past the last element |
* of the initilizer_list. |
* @param __ils Initializer list. |
*/ |
template<class _Tp> |
constexpr const _Tp* |
end(initializer_list<_Tp> __ils) noexcept |
{ return __ils.end(); } |
} |
#pragma GCC visibility pop |
#endif // __GXX_EXPERIMENTAL_CXX0X__ |
#endif // _INITIALIZER_LIST |
/contrib/sdk/sources/libsupc++/new |
---|
0,0 → 1,124 |
// The -*- C++ -*- dynamic memory management header. |
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
// 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 |
// Free Software Foundation |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
/** @file new |
* This is a Standard C++ Library header. |
* |
* The header @c new defines several functions to manage dynamic memory and |
* handling memory allocation errors; see |
* http://gcc.gnu.org/onlinedocs/libstdc++/18_support/howto.html#4 for more. |
*/ |
#ifndef _NEW |
#define _NEW |
#pragma GCC system_header |
#include <bits/c++config.h> |
#include <exception> |
#pragma GCC visibility push(default) |
extern "C++" { |
namespace std |
{ |
/** |
* @brief Exception possibly thrown by @c new. |
* @ingroup exceptions |
* |
* @c bad_alloc (or classes derived from it) is used to report allocation |
* errors from the throwing forms of @c new. */ |
class bad_alloc : public exception |
{ |
public: |
bad_alloc() throw() { } |
// This declaration is not useless: |
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
virtual ~bad_alloc() throw(); |
// See comment in eh_exception.cc. |
virtual const char* what() const throw(); |
}; |
struct nothrow_t { }; |
extern const nothrow_t nothrow; |
/** If you write your own error handler to be called by @c new, it must |
* be of this type. */ |
typedef void (*new_handler)(); |
/// Takes a replacement handler as the argument, returns the |
/// previous handler. |
new_handler set_new_handler(new_handler) throw(); |
} // namespace std |
//@{ |
/** These are replaceable signatures: |
* - normal single new and delete (no arguments, throw @c bad_alloc on error) |
* - normal array new and delete (same) |
* - @c nothrow single new and delete (take a @c nothrow argument, return |
* @c NULL on error) |
* - @c nothrow array new and delete (same) |
* |
* Placement new and delete signatures (take a memory address argument, |
* does nothing) may not be replaced by a user's program. |
*/ |
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) |
__attribute__((__externally_visible__)); |
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) |
__attribute__((__externally_visible__)); |
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT |
__attribute__((__externally_visible__)); |
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT |
__attribute__((__externally_visible__)); |
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT |
__attribute__((__externally_visible__)); |
void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT |
__attribute__((__externally_visible__)); |
void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT |
__attribute__((__externally_visible__)); |
void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT |
__attribute__((__externally_visible__)); |
// Default placement versions of operator new. |
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT |
{ return __p; } |
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT |
{ return __p; } |
// Default placement versions of operator delete. |
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { } |
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } |
//@} |
} // extern "C++" |
#pragma GCC visibility pop |
#endif |
/contrib/sdk/sources/libsupc++/new_handler.cc |
---|
0,0 → 1,41 |
// Implementation file for the -*- C++ -*- dynamic memory management header. |
// Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
// 2005, 2006, 2007, 2008, 2009, 2010 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "new" |
const std::nothrow_t std::nothrow = { }; |
using std::new_handler; |
new_handler __new_handler; |
new_handler |
std::set_new_handler (new_handler handler) throw() |
{ |
new_handler prev_handler = __new_handler; |
__new_handler = handler; |
return prev_handler; |
} |
/contrib/sdk/sources/libsupc++/new_op.cc |
---|
0,0 → 1,67 |
// Support routines for the -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2009, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <cstdlib> |
#include <bits/exception_defines.h> |
#include "new" |
using std::new_handler; |
using std::bad_alloc; |
#if _GLIBCXX_HOSTED |
using std::malloc; |
#else |
// A freestanding C runtime may not provide "malloc" -- but there is no |
// other reasonable way to implement "operator new". |
extern "C" void *malloc (std::size_t); |
#endif |
extern new_handler __new_handler; |
_GLIBCXX_WEAK_DEFINITION void * |
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc) |
{ |
void *p; |
/* malloc (0) is unpredictable; avoid it. */ |
if (sz == 0) |
sz = 1; |
p = (void *) malloc (sz); |
while (p == 0) |
{ |
new_handler handler = __new_handler; |
if (! handler) |
#ifdef __EXCEPTIONS |
throw bad_alloc(); |
#else |
std::abort(); |
#endif |
handler (); |
p = (void *) malloc (sz); |
} |
return p; |
} |
/contrib/sdk/sources/libsupc++/new_opnt.cc |
---|
0,0 → 1,63 |
// Support routines for the -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2004, 2009, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <bits/exception_defines.h> |
#include "new" |
using std::new_handler; |
using std::bad_alloc; |
extern "C" void *malloc (std::size_t); |
extern new_handler __new_handler; |
_GLIBCXX_WEAK_DEFINITION void * |
operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT |
{ |
void *p; |
/* malloc (0) is unpredictable; avoid it. */ |
if (sz == 0) |
sz = 1; |
p = (void *) malloc (sz); |
while (p == 0) |
{ |
new_handler handler = __new_handler; |
if (! handler) |
return 0; |
__try |
{ |
handler (); |
} |
__catch(const bad_alloc&) |
{ |
return 0; |
} |
p = (void *) malloc (sz); |
} |
return p; |
} |
/contrib/sdk/sources/libsupc++/new_opv.cc |
---|
0,0 → 1,34 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include "new" |
_GLIBCXX_WEAK_DEFINITION void* |
operator new[] (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc) |
{ |
return ::operator new(sz); |
} |
/contrib/sdk/sources/libsupc++/pbase_type_info.cc |
---|
0,0 → 1,66 |
// Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, |
// 2009, 2010 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "tinfo.h" |
namespace __cxxabiv1 { |
__pbase_type_info:: |
~__pbase_type_info () |
{} |
bool __pbase_type_info:: |
__do_catch (const type_info *thr_type, |
void **thr_obj, |
unsigned outer) const |
{ |
if (*this == *thr_type) |
return true; // same type |
#ifdef __GXX_RTTI |
if (typeid (*this) != typeid (*thr_type)) |
return false; // not both same kind of pointers |
#endif |
if (!(outer & 1)) |
// We're not the same and our outer pointers are not all const qualified |
// Therefore there must at least be a qualification conversion involved |
// But for that to be valid, our outer pointers must be const qualified. |
return false; |
const __pbase_type_info *thrown_type = |
static_cast <const __pbase_type_info *> (thr_type); |
if (thrown_type->__flags & ~__flags) |
// We're less qualified. |
return false; |
if (!(__flags & __const_mask)) |
outer &= ~1; |
return __pointer_catch (thrown_type, thr_obj, outer); |
} |
} |
/contrib/sdk/sources/libsupc++/pure.cc |
---|
0,0 → 1,58 |
// -*- C++ -*- |
// Copyright (C) 2000, 2001, 2009, 2011 Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <cxxabi.h> |
#include "unwind-cxx.h" |
#if _GLIBCXX_HOSTED |
#ifdef _GLIBCXX_HAVE_UNISTD_H |
# include <unistd.h> |
# define writestr(str) write(2, str, sizeof(str) - 1) |
# ifdef __GNU_LIBRARY__ |
/* Avoid forcing the library's meaning of `write' on the user program |
by using the "internal" name (for use within the library). */ |
/*# define write(fd, buf, n) __write((fd), (buf), (n))*/ |
# endif |
#else |
# include <cstdio> |
# define writestr(str) std::fputs(str, stderr) |
#endif |
#else |
# define writestr(str) /* Empty */ |
#endif |
extern "C" void |
__cxxabiv1::__cxa_pure_virtual (void) |
{ |
writestr ("pure virtual method called\n"); |
std::terminate (); |
} |
extern "C" void |
__cxxabiv1::__cxa_deleted_virtual (void) |
{ |
writestr ("deleted virtual method called\n"); |
std::terminate (); |
} |
/contrib/sdk/sources/libsupc++/si_class_type_info.cc |
---|
0,0 → 1,85 |
// Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, 2009 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "tinfo.h" |
namespace __cxxabiv1 { |
__si_class_type_info:: |
~__si_class_type_info () |
{} |
__class_type_info::__sub_kind __si_class_type_info:: |
__do_find_public_src (ptrdiff_t src2dst, |
const void *obj_ptr, |
const __class_type_info *src_type, |
const void *src_ptr) const |
{ |
if (src_ptr == obj_ptr && *this == *src_type) |
return __contained_public; |
return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); |
} |
bool __si_class_type_info:: |
__do_dyncast (ptrdiff_t src2dst, |
__sub_kind access_path, |
const __class_type_info *dst_type, |
const void *obj_ptr, |
const __class_type_info *src_type, |
const void *src_ptr, |
__dyncast_result &__restrict result) const |
{ |
if (*this == *dst_type) |
{ |
result.dst_ptr = obj_ptr; |
result.whole2dst = access_path; |
if (src2dst >= 0) |
result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr |
? __contained_public : __not_contained; |
else if (src2dst == -2) |
result.dst2src = __not_contained; |
return false; |
} |
if (obj_ptr == src_ptr && *this == *src_type) |
{ |
// The src object we started from. Indicate how we are accessible from |
// the most derived object. |
result.whole2src = access_path; |
return false; |
} |
return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr, |
src_type, src_ptr, result); |
} |
bool __si_class_type_info:: |
__do_upcast (const __class_type_info *dst, const void *obj_ptr, |
__upcast_result &__restrict result) const |
{ |
if (__class_type_info::__do_upcast (dst, obj_ptr, result)) |
return true; |
return __base_type->__do_upcast (dst, obj_ptr, result); |
} |
} |
/contrib/sdk/sources/libsupc++/tinfo.cc |
---|
0,0 → 1,84 |
// Methods for type_info for -*- C++ -*- Run Time Type Identification. |
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
// 2003, 2004, 2005, 2006, 2007, 2009 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#include <cstddef> |
#include "tinfo.h" |
std::type_info:: |
~type_info () |
{ } |
#if !__GXX_TYPEINFO_EQUALITY_INLINE |
// We can't rely on common symbols being shared between shared objects. |
bool std::type_info:: |
operator== (const std::type_info& arg) const |
{ |
#if __GXX_MERGED_TYPEINFO_NAMES |
return name () == arg.name (); |
#else |
/* The name() method will strip any leading '*' prefix. Therefore |
take care to look at __name rather than name() when looking for |
the "pointer" prefix. */ |
return (&arg == this) |
|| (__name[0] != '*' && (__builtin_strcmp (name (), arg.name ()) == 0)); |
#endif |
} |
#endif |
namespace std { |
// return true if this is a type_info for a pointer type |
bool type_info:: |
__is_pointer_p () const |
{ |
return false; |
} |
// return true if this is a type_info for a function type |
bool type_info:: |
__is_function_p () const |
{ |
return false; |
} |
// try and catch a thrown object. |
bool type_info:: |
__do_catch (const type_info *thr_type, void **, unsigned) const |
{ |
return *this == *thr_type; |
} |
// upcast from this type to the target. __class_type_info will override |
bool type_info:: |
__do_upcast (const abi::__class_type_info *, void **) const |
{ |
return false; |
} |
} |
/contrib/sdk/sources/libsupc++/tinfo.h |
---|
0,0 → 1,183 |
// RTTI support internals for -*- C++ -*- |
// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2004, 2009 |
// Free Software Foundation |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "typeinfo" |
#include <cstddef> |
// Class declarations shared between the typeinfo implementation files. |
#include <cxxabi.h> |
namespace __cxxabiv1 { |
inline bool __pbase_type_info:: |
__pointer_catch (const __pbase_type_info *thrown_type, |
void **thr_obj, |
unsigned outer) const |
{ |
return __pointee->__do_catch (thrown_type->__pointee, thr_obj, outer + 2); |
} |
namespace { |
using namespace std; |
using namespace abi; |
// Initial part of a vtable, this structure is used with offsetof, so we don't |
// have to keep alignments consistent manually. |
struct vtable_prefix |
{ |
// Offset to most derived object. |
ptrdiff_t whole_object; |
// Additional padding if necessary. |
#ifdef _GLIBCXX_VTABLE_PADDING |
ptrdiff_t padding1; |
#endif |
// Pointer to most derived type_info. |
const __class_type_info *whole_type; |
// Additional padding if necessary. |
#ifdef _GLIBCXX_VTABLE_PADDING |
ptrdiff_t padding2; |
#endif |
// What a class's vptr points to. |
const void *origin; |
}; |
template <typename T> |
inline const T * |
adjust_pointer (const void *base, ptrdiff_t offset) |
{ |
return reinterpret_cast <const T *> |
(reinterpret_cast <const char *> (base) + offset); |
} |
// ADDR is a pointer to an object. Convert it to a pointer to a base, |
// using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base. |
inline void const * |
convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset) |
{ |
if (is_virtual) |
{ |
const void *vtable = *static_cast <const void *const *> (addr); |
offset = *adjust_pointer<ptrdiff_t> (vtable, offset); |
} |
return adjust_pointer<void> (addr, offset); |
} |
// some predicate functions for __class_type_info::__sub_kind |
inline bool contained_p (__class_type_info::__sub_kind access_path) |
{ |
return access_path >= __class_type_info::__contained_mask; |
} |
inline bool public_p (__class_type_info::__sub_kind access_path) |
{ |
return access_path & __class_type_info::__contained_public_mask; |
} |
inline bool virtual_p (__class_type_info::__sub_kind access_path) |
{ |
return (access_path & __class_type_info::__contained_virtual_mask); |
} |
inline bool contained_public_p (__class_type_info::__sub_kind access_path) |
{ |
return ((access_path & __class_type_info::__contained_public) |
== __class_type_info::__contained_public); |
} |
inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path) |
{ |
return ((access_path & __class_type_info::__contained_public) |
== __class_type_info::__contained_mask); |
} |
inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path) |
{ |
return ((access_path & (__class_type_info::__contained_mask |
| __class_type_info::__contained_virtual_mask)) |
== __class_type_info::__contained_mask); |
} |
static const __class_type_info *const nonvirtual_base_type = |
static_cast <const __class_type_info *> (0) + 1; |
} // namespace |
// __upcast_result is used to hold information during traversal of a class |
// hierarchy when catch matching. |
struct __class_type_info::__upcast_result |
{ |
const void *dst_ptr; // pointer to caught object |
__sub_kind part2dst; // path from current base to target |
int src_details; // hints about the source type hierarchy |
const __class_type_info *base_type; // where we found the target, |
// if in vbase the __class_type_info of vbase |
// if a non-virtual base then 1 |
// else NULL |
__upcast_result (int d) |
:dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL) |
{} |
}; |
// __dyncast_result is used to hold information during traversal of a class |
// hierarchy when dynamic casting. |
struct __class_type_info::__dyncast_result |
{ |
const void *dst_ptr; // pointer to target object or NULL |
__sub_kind whole2dst; // path from most derived object to target |
__sub_kind whole2src; // path from most derived object to sub object |
__sub_kind dst2src; // path from target to sub object |
int whole_details; // details of the whole class hierarchy |
__dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask) |
:dst_ptr (NULL), whole2dst (__unknown), |
whole2src (__unknown), dst2src (__unknown), |
whole_details (details_) |
{} |
protected: |
__dyncast_result(const __dyncast_result&); |
__dyncast_result& |
operator=(const __dyncast_result&); |
}; |
inline __class_type_info::__sub_kind __class_type_info:: |
__find_public_src (ptrdiff_t src2dst, |
const void *obj_ptr, |
const __class_type_info *src_type, |
const void *src_ptr) const |
{ |
if (src2dst >= 0) |
return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr |
? __contained_public : __not_contained; |
if (src2dst == -2) |
return __not_contained; |
return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); |
} |
} |
/contrib/sdk/sources/libsupc++/typeinfo |
---|
0,0 → 1,224 |
// RTTI support for -*- C++ -*- |
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
// 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, 2012 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
/** @file typeinfo |
* This is a Standard C++ Library header. |
*/ |
#ifndef _TYPEINFO |
#define _TYPEINFO |
#pragma GCC system_header |
#include <exception> |
#ifdef __GXX_EXPERIMENTAL_CXX0X__ |
#include <bits/hash_bytes.h> |
#endif |
#pragma GCC visibility push(default) |
extern "C++" { |
namespace __cxxabiv1 |
{ |
class __class_type_info; |
} // namespace __cxxabiv1 |
// Determine whether typeinfo names for the same type are merged (in which |
// case comparison can just compare pointers) or not (in which case strings |
// must be compared), and whether comparison is to be implemented inline or |
// not. We used to do inline pointer comparison by default if weak symbols |
// are available, but even with weak symbols sometimes names are not merged |
// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by |
// default. For ABI compatibility, we do the strcmp inline if weak symbols |
// are available, and out-of-line if not. Out-of-line pointer comparison |
// is used where the object files are to be portable to multiple systems, |
// some of which may not be able to use pointer comparison, but the |
// particular system for which libstdc++ is being built can use pointer |
// comparison; in particular for most ARM EABI systems, where the ABI |
// specifies out-of-line comparison. The compiler's target configuration |
// can override the defaults by defining __GXX_TYPEINFO_EQUALITY_INLINE to |
// 1 or 0 to indicate whether or not comparison is inline, and |
// __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to indicate whether or not pointer |
// comparison can be used. |
#ifndef __GXX_MERGED_TYPEINFO_NAMES |
// By default, typeinfo names are not merged. |
#define __GXX_MERGED_TYPEINFO_NAMES 0 |
#endif |
// By default follow the old inline rules to avoid ABI changes. |
#ifndef __GXX_TYPEINFO_EQUALITY_INLINE |
#if !__GXX_WEAK__ |
#define __GXX_TYPEINFO_EQUALITY_INLINE 0 |
#else |
#define __GXX_TYPEINFO_EQUALITY_INLINE 1 |
#endif |
#endif |
namespace std |
{ |
/** |
* @brief Part of RTTI. |
* |
* The @c type_info class describes type information generated by |
* an implementation. |
*/ |
class type_info |
{ |
public: |
/** Destructor first. Being the first non-inline virtual function, this |
* controls in which translation unit the vtable is emitted. The |
* compiler makes use of that information to know where to emit |
* the runtime-mandated type_info structures in the new-abi. */ |
virtual ~type_info(); |
/** Returns an @e implementation-defined byte string; this is not |
* portable between compilers! */ |
const char* name() const |
{ return __name[0] == '*' ? __name + 1 : __name; } |
#if !__GXX_TYPEINFO_EQUALITY_INLINE |
// In old abi, or when weak symbols are not supported, there can |
// be multiple instances of a type_info object for one |
// type. Uniqueness must use the _name value, not object address. |
bool before(const type_info& __arg) const; |
bool operator==(const type_info& __arg) const; |
#else |
#if !__GXX_MERGED_TYPEINFO_NAMES |
/** Returns true if @c *this precedes @c __arg in the implementation's |
* collation order. */ |
// Even with the new abi, on systems that support dlopen |
// we can run into cases where type_info names aren't merged, |
// so we still need to do string comparison. |
bool before(const type_info& __arg) const |
{ return (__name[0] == '*' && __arg.__name[0] == '*') |
? __name < __arg.__name |
: __builtin_strcmp (__name, __arg.__name) < 0; } |
bool operator==(const type_info& __arg) const |
{ |
return ((__name == __arg.__name) |
|| (__name[0] != '*' && |
__builtin_strcmp (__name, __arg.__name) == 0)); |
} |
#else |
// On some targets we can rely on type_info's NTBS being unique, |
// and therefore address comparisons are sufficient. |
bool before(const type_info& __arg) const |
{ return __name < __arg.__name; } |
bool operator==(const type_info& __arg) const |
{ return __name == __arg.__name; } |
#endif |
#endif |
bool operator!=(const type_info& __arg) const |
{ return !operator==(__arg); } |
#ifdef __GXX_EXPERIMENTAL_CXX0X__ |
size_t hash_code() const noexcept |
{ |
# if !__GXX_MERGED_TYPEINFO_NAMES |
return _Hash_bytes(name(), __builtin_strlen(name()), |
static_cast<size_t>(0xc70f6907UL)); |
# else |
return reinterpret_cast<size_t>(__name); |
# endif |
} |
#endif // __GXX_EXPERIMENTAL_CXX0X__ |
// Return true if this is a pointer type of some kind |
virtual bool __is_pointer_p() const; |
// Return true if this is a function type |
virtual bool __is_function_p() const; |
// Try and catch a thrown type. Store an adjusted pointer to the |
// caught type in THR_OBJ. If THR_TYPE is not a pointer type, then |
// THR_OBJ points to the thrown object. If THR_TYPE is a pointer |
// type, then THR_OBJ is the pointer itself. OUTER indicates the |
// number of outer pointers, and whether they were const |
// qualified. |
virtual bool __do_catch(const type_info *__thr_type, void **__thr_obj, |
unsigned __outer) const; |
// Internally used during catch matching |
virtual bool __do_upcast(const __cxxabiv1::__class_type_info *__target, |
void **__obj_ptr) const; |
protected: |
const char *__name; |
explicit type_info(const char *__n): __name(__n) { } |
private: |
/// Assigning type_info is not supported. |
type_info& operator=(const type_info&); |
type_info(const type_info&); |
}; |
/** |
* @brief Thrown during incorrect typecasting. |
* @ingroup exceptions |
* |
* If you attempt an invalid @c dynamic_cast expression, an instance of |
* this class (or something derived from this class) is thrown. */ |
class bad_cast : public exception |
{ |
public: |
bad_cast() _GLIBCXX_USE_NOEXCEPT { } |
// This declaration is not useless: |
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
virtual ~bad_cast() _GLIBCXX_USE_NOEXCEPT; |
// See comment in eh_exception.cc. |
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; |
}; |
/** |
* @brief Thrown when a NULL pointer in a @c typeid expression is used. |
* @ingroup exceptions |
*/ |
class bad_typeid : public exception |
{ |
public: |
bad_typeid () _GLIBCXX_USE_NOEXCEPT { } |
// This declaration is not useless: |
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
virtual ~bad_typeid() _GLIBCXX_USE_NOEXCEPT; |
// See comment in eh_exception.cc. |
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; |
}; |
} // namespace std |
} // extern "C++" |
#pragma GCC visibility pop |
#endif |
/contrib/sdk/sources/libsupc++/unwind-cxx.h |
---|
0,0 → 1,382 |
// -*- C++ -*- Exception handling and frame unwind runtime interface routines. |
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
// 2011 Free Software Foundation, Inc. |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
// This is derived from the C++ ABI for IA-64. Where we diverge |
// for cross-architecture compatibility are noted with "@@@". |
#ifndef _UNWIND_CXX_H |
#define _UNWIND_CXX_H 1 |
// Level 2: C++ ABI |
#include <typeinfo> |
#include <exception> |
#include <cstddef> |
#include "unwind.h" |
#include <bits/atomic_word.h> |
#include <cxxabi.h> |
#pragma GCC visibility push(default) |
namespace __cxxabiv1 |
{ |
// A primary C++ exception object consists of a header, which is a wrapper |
// around an unwind object header with additional C++ specific information, |
// followed by the exception object itself. |
struct __cxa_exception |
{ |
// Manage the exception object itself. |
std::type_info *exceptionType; |
void (_GLIBCXX_CDTOR_CALLABI *exceptionDestructor)(void *); |
// The C++ standard has entertaining rules wrt calling set_terminate |
// and set_unexpected in the middle of the exception cleanup process. |
std::unexpected_handler unexpectedHandler; |
std::terminate_handler terminateHandler; |
// The caught exception stack threads through here. |
__cxa_exception *nextException; |
// How many nested handlers have caught this exception. A negated |
// value is a signal that this object has been rethrown. |
int handlerCount; |
#ifdef __ARM_EABI_UNWINDER__ |
// Stack of exceptions in cleanups. |
__cxa_exception* nextPropagatingException; |
// The nuber of active cleanup handlers for this exception. |
int propagationCount; |
#else |
// Cache parsed handler data from the personality routine Phase 1 |
// for Phase 2 and __cxa_call_unexpected. |
int handlerSwitchValue; |
const unsigned char *actionRecord; |
const unsigned char *languageSpecificData; |
_Unwind_Ptr catchTemp; |
void *adjustedPtr; |
#endif |
// The generic exception header. Must be last. |
_Unwind_Exception unwindHeader; |
}; |
struct __cxa_refcounted_exception |
{ |
// Manage this header. |
_Atomic_word referenceCount; |
// __cxa_exception must be last, and no padding can be after it. |
__cxa_exception exc; |
}; |
// A dependent C++ exception object consists of a wrapper around an unwind |
// object header with additional C++ specific information, containing a pointer |
// to a primary exception object. |
struct __cxa_dependent_exception |
{ |
// The primary exception this thing depends on. |
void *primaryException; |
// The C++ standard has entertaining rules wrt calling set_terminate |
// and set_unexpected in the middle of the exception cleanup process. |
std::unexpected_handler unexpectedHandler; |
std::terminate_handler terminateHandler; |
// The caught exception stack threads through here. |
__cxa_exception *nextException; |
// How many nested handlers have caught this exception. A negated |
// value is a signal that this object has been rethrown. |
int handlerCount; |
#ifdef __ARM_EABI_UNWINDER__ |
// Stack of exceptions in cleanups. |
__cxa_exception* nextPropagatingException; |
// The nuber of active cleanup handlers for this exception. |
int propagationCount; |
#else |
// Cache parsed handler data from the personality routine Phase 1 |
// for Phase 2 and __cxa_call_unexpected. |
int handlerSwitchValue; |
const unsigned char *actionRecord; |
const unsigned char *languageSpecificData; |
_Unwind_Ptr catchTemp; |
void *adjustedPtr; |
#endif |
// The generic exception header. Must be last. |
_Unwind_Exception unwindHeader; |
}; |
// Each thread in a C++ program has access to a __cxa_eh_globals object. |
struct __cxa_eh_globals |
{ |
__cxa_exception *caughtExceptions; |
unsigned int uncaughtExceptions; |
#ifdef __ARM_EABI_UNWINDER__ |
__cxa_exception* propagatingExceptions; |
#endif |
}; |
// @@@ These are not directly specified by the IA-64 C++ ABI. |
// Handles re-checking the exception specification if unexpectedHandler |
// throws, and if bad_exception needs to be thrown. Called from the |
// compiler. |
extern "C" void __cxa_call_unexpected (void *) __attribute__((__noreturn__)); |
extern "C" void __cxa_call_terminate (_Unwind_Exception*) throw () |
__attribute__((__noreturn__)); |
#ifdef __ARM_EABI_UNWINDER__ |
// Arm EABI specified routines. |
typedef enum { |
ctm_failed = 0, |
ctm_succeeded = 1, |
ctm_succeeded_with_ptr_to_base = 2 |
} __cxa_type_match_result; |
extern "C" __cxa_type_match_result __cxa_type_match(_Unwind_Exception*, |
const std::type_info*, |
bool, void**); |
extern "C" bool __cxa_begin_cleanup (_Unwind_Exception*); |
extern "C" void __cxa_end_cleanup (void); |
#endif |
// Handles cleanup from transactional memory restart. |
extern "C" void __cxa_tm_cleanup (void *, void *, unsigned int) throw(); |
// Invokes given handler, dying appropriately if the user handler was |
// so inconsiderate as to return. |
extern void __terminate(std::terminate_handler) throw () |
__attribute__((__noreturn__)); |
extern void __unexpected(std::unexpected_handler) |
__attribute__((__noreturn__)); |
// The current installed user handlers. |
extern std::terminate_handler __terminate_handler; |
extern std::unexpected_handler __unexpected_handler; |
// These are explicitly GNU C++ specific. |
// Acquire the C++ exception header from the C++ object. |
static inline __cxa_exception * |
__get_exception_header_from_obj (void *ptr) |
{ |
return reinterpret_cast<__cxa_exception *>(ptr) - 1; |
} |
// Acquire the C++ exception header from the generic exception header. |
static inline __cxa_exception * |
__get_exception_header_from_ue (_Unwind_Exception *exc) |
{ |
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1; |
} |
// Acquire the C++ refcounted exception header from the C++ object. |
static inline __cxa_refcounted_exception * |
__get_refcounted_exception_header_from_obj (void *ptr) |
{ |
return reinterpret_cast<__cxa_refcounted_exception *>(ptr) - 1; |
} |
// Acquire the C++ refcounted exception header from the generic exception |
// header. |
static inline __cxa_refcounted_exception * |
__get_refcounted_exception_header_from_ue (_Unwind_Exception *exc) |
{ |
return reinterpret_cast<__cxa_refcounted_exception *>(exc + 1) - 1; |
} |
static inline __cxa_dependent_exception * |
__get_dependent_exception_from_ue (_Unwind_Exception *exc) |
{ |
return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1; |
} |
#ifdef __ARM_EABI_UNWINDER__ |
static inline bool |
__is_gxx_exception_class(_Unwind_Exception_Class c) |
{ |
// TODO: Take advantage of the fact that c will always be word aligned. |
return c[0] == 'G' |
&& c[1] == 'N' |
&& c[2] == 'U' |
&& c[3] == 'C' |
&& c[4] == 'C' |
&& c[5] == '+' |
&& c[6] == '+' |
&& (c[7] == '\0' || c[7] == '\x01'); |
} |
// Only checks for primary or dependent, but not that it is a C++ exception at |
// all. |
static inline bool |
__is_dependent_exception(_Unwind_Exception_Class c) |
{ |
return c[7] == '\x01'; |
} |
static inline void |
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(_Unwind_Exception_Class c) |
{ |
c[0] = 'G'; |
c[1] = 'N'; |
c[2] = 'U'; |
c[3] = 'C'; |
c[4] = 'C'; |
c[5] = '+'; |
c[6] = '+'; |
c[7] = '\0'; |
} |
static inline void |
__GXX_INIT_DEPENDENT_EXCEPTION_CLASS(_Unwind_Exception_Class c) |
{ |
c[0] = 'G'; |
c[1] = 'N'; |
c[2] = 'U'; |
c[3] = 'C'; |
c[4] = 'C'; |
c[5] = '+'; |
c[6] = '+'; |
c[7] = '\x01'; |
} |
static inline bool |
__is_gxx_forced_unwind_class(_Unwind_Exception_Class c) |
{ |
return c[0] == 'G' |
&& c[1] == 'N' |
&& c[2] == 'U' |
&& c[3] == 'C' |
&& c[4] == 'F' |
&& c[5] == 'O' |
&& c[6] == 'R' |
&& c[7] == '\0'; |
} |
static inline void |
__GXX_INIT_FORCED_UNWIND_CLASS(_Unwind_Exception_Class c) |
{ |
c[0] = 'G'; |
c[1] = 'N'; |
c[2] = 'U'; |
c[3] = 'C'; |
c[4] = 'F'; |
c[5] = 'O'; |
c[6] = 'R'; |
c[7] = '\0'; |
} |
static inline void* |
__gxx_caught_object(_Unwind_Exception* eo) |
{ |
return (void*)eo->barrier_cache.bitpattern[0]; |
} |
#else // !__ARM_EABI_UNWINDER__ |
// This is the primary exception class we report -- "GNUCC++\0". |
const _Unwind_Exception_Class __gxx_primary_exception_class |
= ((((((((_Unwind_Exception_Class) 'G' |
<< 8 | (_Unwind_Exception_Class) 'N') |
<< 8 | (_Unwind_Exception_Class) 'U') |
<< 8 | (_Unwind_Exception_Class) 'C') |
<< 8 | (_Unwind_Exception_Class) 'C') |
<< 8 | (_Unwind_Exception_Class) '+') |
<< 8 | (_Unwind_Exception_Class) '+') |
<< 8 | (_Unwind_Exception_Class) '\0'); |
// This is the dependent (from std::rethrow_exception) exception class we report |
// "GNUCC++\x01" |
const _Unwind_Exception_Class __gxx_dependent_exception_class |
= ((((((((_Unwind_Exception_Class) 'G' |
<< 8 | (_Unwind_Exception_Class) 'N') |
<< 8 | (_Unwind_Exception_Class) 'U') |
<< 8 | (_Unwind_Exception_Class) 'C') |
<< 8 | (_Unwind_Exception_Class) 'C') |
<< 8 | (_Unwind_Exception_Class) '+') |
<< 8 | (_Unwind_Exception_Class) '+') |
<< 8 | (_Unwind_Exception_Class) '\x01'); |
static inline bool |
__is_gxx_exception_class(_Unwind_Exception_Class c) |
{ |
return c == __gxx_primary_exception_class |
|| c == __gxx_dependent_exception_class; |
} |
// Only checks for primary or dependent, but not that it is a C++ exception at |
// all. |
static inline bool |
__is_dependent_exception(_Unwind_Exception_Class c) |
{ |
return (c & 1); |
} |
#define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class |
#define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \ |
c = __gxx_dependent_exception_class |
// GNU C++ personality routine, Version 0. |
extern "C" _Unwind_Reason_Code __gxx_personality_v0 |
(int, _Unwind_Action, _Unwind_Exception_Class, |
struct _Unwind_Exception *, struct _Unwind_Context *); |
// GNU C++ sjlj personality routine, Version 0. |
extern "C" _Unwind_Reason_Code __gxx_personality_sj0 |
(int, _Unwind_Action, _Unwind_Exception_Class, |
struct _Unwind_Exception *, struct _Unwind_Context *); |
static inline void* |
__gxx_caught_object(_Unwind_Exception* eo) |
{ |
// Bad as it looks, this actually works for dependent exceptions too. |
__cxa_exception* header = __get_exception_header_from_ue (eo); |
return header->adjustedPtr; |
} |
#endif // !__ARM_EABI_UNWINDER__ |
static inline void* |
__get_object_from_ue(_Unwind_Exception* eo) throw() |
{ |
return __is_dependent_exception (eo->exception_class) ? |
__get_dependent_exception_from_ue (eo)->primaryException : |
eo + 1; |
} |
static inline void * |
__get_object_from_ambiguous_exception(__cxa_exception *p_or_d) throw() |
{ |
return __get_object_from_ue (&p_or_d->unwindHeader); |
} |
} /* namespace __cxxabiv1 */ |
#pragma GCC visibility pop |
#endif // _UNWIND_CXX_H |
/contrib/sdk/sources/libsupc++/unwind-pe.h |
---|
0,0 → 1,289 |
/* Exception handling and frame unwind runtime interface routines. |
Copyright (C) 2001, 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc. |
This file is part of GCC. |
GCC is free software; you can redistribute it and/or modify it |
under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 3, or (at your option) |
any later version. |
GCC is distributed in the hope that it will be useful, but WITHOUT |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
License for more details. |
Under Section 7 of GPL version 3, you are granted additional |
permissions described in the GCC Runtime Library Exception, version |
3.1, as published by the Free Software Foundation. |
You should have received a copy of the GNU General Public License and |
a copy of the GCC Runtime Library Exception along with this program; |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
/* @@@ Really this should be out of line, but this also causes link |
compatibility problems with the base ABI. This is slightly better |
than duplicating code, however. */ |
#ifndef GCC_UNWIND_PE_H |
#define GCC_UNWIND_PE_H |
/* If using C++, references to abort have to be qualified with std::. */ |
#if __cplusplus |
#define __gxx_abort std::abort |
#else |
#define __gxx_abort abort |
#endif |
/* Pointer encodings, from dwarf2.h. */ |
#define DW_EH_PE_absptr 0x00 |
#define DW_EH_PE_omit 0xff |
#define DW_EH_PE_uleb128 0x01 |
#define DW_EH_PE_udata2 0x02 |
#define DW_EH_PE_udata4 0x03 |
#define DW_EH_PE_udata8 0x04 |
#define DW_EH_PE_sleb128 0x09 |
#define DW_EH_PE_sdata2 0x0A |
#define DW_EH_PE_sdata4 0x0B |
#define DW_EH_PE_sdata8 0x0C |
#define DW_EH_PE_signed 0x08 |
#define DW_EH_PE_pcrel 0x10 |
#define DW_EH_PE_textrel 0x20 |
#define DW_EH_PE_datarel 0x30 |
#define DW_EH_PE_funcrel 0x40 |
#define DW_EH_PE_aligned 0x50 |
#define DW_EH_PE_indirect 0x80 |
#ifndef NO_SIZE_OF_ENCODED_VALUE |
/* Given an encoding, return the number of bytes the format occupies. |
This is only defined for fixed-size encodings, and so does not |
include leb128. */ |
static unsigned int |
size_of_encoded_value (unsigned char encoding) __attribute__ ((unused)); |
static unsigned int |
size_of_encoded_value (unsigned char encoding) |
{ |
if (encoding == DW_EH_PE_omit) |
return 0; |
switch (encoding & 0x07) |
{ |
case DW_EH_PE_absptr: |
return sizeof (void *); |
case DW_EH_PE_udata2: |
return 2; |
case DW_EH_PE_udata4: |
return 4; |
case DW_EH_PE_udata8: |
return 8; |
} |
__gxx_abort (); |
} |
#endif |
#ifndef NO_BASE_OF_ENCODED_VALUE |
/* Given an encoding and an _Unwind_Context, return the base to which |
the encoding is relative. This base may then be passed to |
read_encoded_value_with_base for use when the _Unwind_Context is |
not available. */ |
static _Unwind_Ptr |
base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context) |
{ |
if (encoding == DW_EH_PE_omit) |
return 0; |
switch (encoding & 0x70) |
{ |
case DW_EH_PE_absptr: |
case DW_EH_PE_pcrel: |
case DW_EH_PE_aligned: |
return 0; |
case DW_EH_PE_textrel: |
return _Unwind_GetTextRelBase (context); |
case DW_EH_PE_datarel: |
return _Unwind_GetDataRelBase (context); |
case DW_EH_PE_funcrel: |
return _Unwind_GetRegionStart (context); |
} |
__gxx_abort (); |
} |
#endif |
/* Read an unsigned leb128 value from P, store the value in VAL, return |
P incremented past the value. We assume that a word is large enough to |
hold any value so encoded; if it is smaller than a pointer on some target, |
pointers should not be leb128 encoded on that target. */ |
static const unsigned char * |
read_uleb128 (const unsigned char *p, _uleb128_t *val) |
{ |
unsigned int shift = 0; |
unsigned char byte; |
_uleb128_t result; |
result = 0; |
do |
{ |
byte = *p++; |
result |= ((_uleb128_t)byte & 0x7f) << shift; |
shift += 7; |
} |
while (byte & 0x80); |
*val = result; |
return p; |
} |
/* Similar, but read a signed leb128 value. */ |
static const unsigned char * |
read_sleb128 (const unsigned char *p, _sleb128_t *val) |
{ |
unsigned int shift = 0; |
unsigned char byte; |
_uleb128_t result; |
result = 0; |
do |
{ |
byte = *p++; |
result |= ((_uleb128_t)byte & 0x7f) << shift; |
shift += 7; |
} |
while (byte & 0x80); |
/* Sign-extend a negative value. */ |
if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) |
result |= -(((_uleb128_t)1L) << shift); |
*val = (_sleb128_t) result; |
return p; |
} |
/* Load an encoded value from memory at P. The value is returned in VAL; |
The function returns P incremented past the value. BASE is as given |
by base_of_encoded_value for this encoding in the appropriate context. */ |
static const unsigned char * |
read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, |
const unsigned char *p, _Unwind_Ptr *val) |
{ |
union unaligned |
{ |
void *ptr; |
unsigned u2 __attribute__ ((mode (HI))); |
unsigned u4 __attribute__ ((mode (SI))); |
unsigned u8 __attribute__ ((mode (DI))); |
signed s2 __attribute__ ((mode (HI))); |
signed s4 __attribute__ ((mode (SI))); |
signed s8 __attribute__ ((mode (DI))); |
} __attribute__((__packed__)); |
const union unaligned *u = (const union unaligned *) p; |
_Unwind_Internal_Ptr result; |
if (encoding == DW_EH_PE_aligned) |
{ |
_Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p; |
a = (a + sizeof (void *) - 1) & - sizeof(void *); |
result = *(_Unwind_Internal_Ptr *) a; |
p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *)); |
} |
else |
{ |
switch (encoding & 0x0f) |
{ |
case DW_EH_PE_absptr: |
result = (_Unwind_Internal_Ptr) u->ptr; |
p += sizeof (void *); |
break; |
case DW_EH_PE_uleb128: |
{ |
_uleb128_t tmp; |
p = read_uleb128 (p, &tmp); |
result = (_Unwind_Internal_Ptr) tmp; |
} |
break; |
case DW_EH_PE_sleb128: |
{ |
_sleb128_t tmp; |
p = read_sleb128 (p, &tmp); |
result = (_Unwind_Internal_Ptr) tmp; |
} |
break; |
case DW_EH_PE_udata2: |
result = u->u2; |
p += 2; |
break; |
case DW_EH_PE_udata4: |
result = u->u4; |
p += 4; |
break; |
case DW_EH_PE_udata8: |
result = u->u8; |
p += 8; |
break; |
case DW_EH_PE_sdata2: |
result = u->s2; |
p += 2; |
break; |
case DW_EH_PE_sdata4: |
result = u->s4; |
p += 4; |
break; |
case DW_EH_PE_sdata8: |
result = u->s8; |
p += 8; |
break; |
default: |
__gxx_abort (); |
} |
if (result != 0) |
{ |
result += ((encoding & 0x70) == DW_EH_PE_pcrel |
? (_Unwind_Internal_Ptr) u : base); |
if (encoding & DW_EH_PE_indirect) |
result = *(_Unwind_Internal_Ptr *) result; |
} |
} |
*val = result; |
return p; |
} |
#ifndef NO_BASE_OF_ENCODED_VALUE |
/* Like read_encoded_value_with_base, but get the base from the context |
rather than providing it directly. */ |
static inline const unsigned char * |
read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, |
const unsigned char *p, _Unwind_Ptr *val) |
{ |
return read_encoded_value_with_base (encoding, |
base_of_encoded_value (encoding, context), |
p, val); |
} |
#endif |
#endif /* unwind-pe.h */ |
/contrib/sdk/sources/libsupc++/vmi_class_type_info.cc |
---|
0,0 → 1,391 |
// Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, 2009 |
// Free Software Foundation |
// |
// This file is part of GCC. |
// |
// GCC is free software; you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// GCC is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include "tinfo.h" |
namespace __cxxabiv1 { |
__vmi_class_type_info:: |
~__vmi_class_type_info () |
{} |
__class_type_info::__sub_kind __vmi_class_type_info:: |
__do_find_public_src (ptrdiff_t src2dst, |
const void *obj_ptr, |
const __class_type_info *src_type, |
const void *src_ptr) const |
{ |
if (obj_ptr == src_ptr && *this == *src_type) |
return __contained_public; |
for (std::size_t i = __base_count; i--;) |
{ |
if (!__base_info[i].__is_public_p ()) |
continue; // Not public, can't be here. |
const void *base = obj_ptr; |
ptrdiff_t offset = __base_info[i].__offset (); |
bool is_virtual = __base_info[i].__is_virtual_p (); |
if (is_virtual) |
{ |
if (src2dst == -3) |
continue; // Not a virtual base, so can't be here. |
} |
base = convert_to_base (base, is_virtual, offset); |
__sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src |
(src2dst, base, src_type, src_ptr); |
if (contained_p (base_kind)) |
{ |
if (is_virtual) |
base_kind = __sub_kind (base_kind | __contained_virtual_mask); |
return base_kind; |
} |
} |
return __not_contained; |
} |
// This is a big hairy function. Although the run-time behaviour of |
// dynamic_cast is simple to describe, it gives rise to some non-obvious |
// behaviour. We also desire to determine as early as possible any definite |
// answer we can get. Because it is unknown what the run-time ratio of |
// succeeding to failing dynamic casts is, we do not know in which direction |
// to bias any optimizations. To that end we make no particular effort towards |
// early fail answers or early success answers. Instead we try to minimize |
// work by filling in things lazily (when we know we need the information), |
// and opportunisticly take early success or failure results. |
bool __vmi_class_type_info:: |
__do_dyncast (ptrdiff_t src2dst, |
__sub_kind access_path, |
const __class_type_info *dst_type, |
const void *obj_ptr, |
const __class_type_info *src_type, |
const void *src_ptr, |
__dyncast_result &__restrict result) const |
{ |
if (result.whole_details & __flags_unknown_mask) |
result.whole_details = __flags; |
if (obj_ptr == src_ptr && *this == *src_type) |
{ |
// The src object we started from. Indicate how we are accessible from |
// the most derived object. |
result.whole2src = access_path; |
return false; |
} |
if (*this == *dst_type) |
{ |
result.dst_ptr = obj_ptr; |
result.whole2dst = access_path; |
if (src2dst >= 0) |
result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr |
? __contained_public : __not_contained; |
else if (src2dst == -2) |
result.dst2src = __not_contained; |
return false; |
} |
// If src_type is a unique non-virtual base of dst_type, we have a good |
// guess at the address we want, so in the first pass try skipping any |
// bases which don't contain that address. |
const void *dst_cand = NULL; |
if (src2dst >= 0) |
dst_cand = adjust_pointer<void>(src_ptr, -src2dst); |
bool first_pass = true; |
bool skipped = false; |
bool result_ambig = false; |
again: |
for (std::size_t i = __base_count; i--;) |
{ |
__dyncast_result result2 (result.whole_details); |
void const *base = obj_ptr; |
__sub_kind base_access = access_path; |
ptrdiff_t offset = __base_info[i].__offset (); |
bool is_virtual = __base_info[i].__is_virtual_p (); |
if (is_virtual) |
base_access = __sub_kind (base_access | __contained_virtual_mask); |
base = convert_to_base (base, is_virtual, offset); |
if (dst_cand) |
{ |
bool skip_on_first_pass = base > dst_cand; |
if (skip_on_first_pass == first_pass) |
{ |
// We aren't interested in this base on this pass: either |
// we're on the first pass and this base doesn't contain the |
// likely address, or we're on the second pass and we checked |
// this base on the first pass. |
skipped = true; |
continue; |
} |
} |
if (!__base_info[i].__is_public_p ()) |
{ |
if (src2dst == -2 && |
!(result.whole_details |
& (__non_diamond_repeat_mask | __diamond_shaped_mask))) |
// The hierarchy has no duplicate bases (which might ambiguate |
// things) and where we started is not a public base of what we |
// want (so it cannot be a downcast). There is nothing of interest |
// hiding in a non-public base. |
continue; |
base_access = __sub_kind (base_access & ~__contained_public_mask); |
} |
bool result2_ambig |
= __base_info[i].__base_type->__do_dyncast (src2dst, base_access, |
dst_type, base, |
src_type, src_ptr, result2); |
result.whole2src = __sub_kind (result.whole2src | result2.whole2src); |
if (result2.dst2src == __contained_public |
|| result2.dst2src == __contained_ambig) |
{ |
result.dst_ptr = result2.dst_ptr; |
result.whole2dst = result2.whole2dst; |
result.dst2src = result2.dst2src; |
// Found a downcast which can't be bettered or an ambiguous downcast |
// which can't be disambiguated |
return result2_ambig; |
} |
if (!result_ambig && !result.dst_ptr) |
{ |
// Not found anything yet. |
result.dst_ptr = result2.dst_ptr; |
result.whole2dst = result2.whole2dst; |
result_ambig = result2_ambig; |
if (result.dst_ptr && result.whole2src != __unknown |
&& !(__flags & __non_diamond_repeat_mask)) |
// Found dst and src and we don't have repeated bases. |
return result_ambig; |
} |
else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr) |
{ |
// Found at same address, must be via virtual. Pick the most |
// accessible path. |
result.whole2dst = |
__sub_kind (result.whole2dst | result2.whole2dst); |
} |
else if ((result.dst_ptr != 0 && result2.dst_ptr != 0) |
|| (result.dst_ptr != 0 && result2_ambig) |
|| (result2.dst_ptr != 0 && result_ambig)) |
{ |
// Found two different DST_TYPE bases, or a valid one and a set of |
// ambiguous ones, must disambiguate. See whether SRC_PTR is |
// contained publicly within one of the non-ambiguous choices. If it |
// is in only one, then that's the choice. If it is in both, then |
// we're ambiguous and fail. If it is in neither, we're ambiguous, |
// but don't yet fail as we might later find a third base which does |
// contain SRC_PTR. |
__sub_kind new_sub_kind = result2.dst2src; |
__sub_kind old_sub_kind = result.dst2src; |
if (contained_p (result.whole2src) |
&& (!virtual_p (result.whole2src) |
|| !(result.whole_details & __diamond_shaped_mask))) |
{ |
// We already found SRC_PTR as a base of most derived, and |
// either it was non-virtual, or the whole hierarchy is |
// not-diamond shaped. Therefore if it is in either choice, it |
// can only be in one of them, and we will already know. |
if (old_sub_kind == __unknown) |
old_sub_kind = __not_contained; |
if (new_sub_kind == __unknown) |
new_sub_kind = __not_contained; |
} |
else |
{ |
if (old_sub_kind >= __not_contained) |
;// already calculated |
else if (contained_p (new_sub_kind) |
&& (!virtual_p (new_sub_kind) |
|| !(__flags & __diamond_shaped_mask))) |
// Already found inside the other choice, and it was |
// non-virtual or we are not diamond shaped. |
old_sub_kind = __not_contained; |
else |
old_sub_kind = dst_type->__find_public_src |
(src2dst, result.dst_ptr, src_type, src_ptr); |
if (new_sub_kind >= __not_contained) |
;// already calculated |
else if (contained_p (old_sub_kind) |
&& (!virtual_p (old_sub_kind) |
|| !(__flags & __diamond_shaped_mask))) |
// Already found inside the other choice, and it was |
// non-virtual or we are not diamond shaped. |
new_sub_kind = __not_contained; |
else |
new_sub_kind = dst_type->__find_public_src |
(src2dst, result2.dst_ptr, src_type, src_ptr); |
} |
// Neither sub_kind can be contained_ambig -- we bail out early |
// when we find those. |
if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind))) |
{ |
// Only on one choice, not ambiguous. |
if (contained_p (new_sub_kind)) |
{ |
// Only in new. |
result.dst_ptr = result2.dst_ptr; |
result.whole2dst = result2.whole2dst; |
result_ambig = false; |
old_sub_kind = new_sub_kind; |
} |
result.dst2src = old_sub_kind; |
if (public_p (result.dst2src)) |
return false; // Can't be an ambiguating downcast for later discovery. |
if (!virtual_p (result.dst2src)) |
return false; // Found non-virtually can't be bettered |
} |
else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind))) |
{ |
// In both. |
result.dst_ptr = NULL; |
result.dst2src = __contained_ambig; |
return true; // Fail. |
} |
else |
{ |
// In neither publicly, ambiguous for the moment, but keep |
// looking. It is possible that it was private in one or |
// both and therefore we should fail, but that's just tough. |
result.dst_ptr = NULL; |
result.dst2src = __not_contained; |
result_ambig = true; |
} |
} |
if (result.whole2src == __contained_private) |
// We found SRC_PTR as a private non-virtual base, therefore all |
// cross casts will fail. We have already found a down cast, if |
// there is one. |
return result_ambig; |
} |
if (skipped && first_pass) |
{ |
// We didn't find dst where we expected it, so let's go back and try |
// the bases we skipped (if any). |
first_pass = false; |
goto again; |
} |
return result_ambig; |
} |
bool __vmi_class_type_info:: |
__do_upcast (const __class_type_info *dst, const void *obj_ptr, |
__upcast_result &__restrict result) const |
{ |
if (__class_type_info::__do_upcast (dst, obj_ptr, result)) |
return true; |
int src_details = result.src_details; |
if (src_details & __flags_unknown_mask) |
src_details = __flags; |
for (std::size_t i = __base_count; i--;) |
{ |
__upcast_result result2 (src_details); |
const void *base = obj_ptr; |
ptrdiff_t offset = __base_info[i].__offset (); |
bool is_virtual = __base_info[i].__is_virtual_p (); |
bool is_public = __base_info[i].__is_public_p (); |
if (!is_public && !(src_details & __non_diamond_repeat_mask)) |
// original cannot have an ambiguous base, so skip private bases |
continue; |
if (base) |
base = convert_to_base (base, is_virtual, offset); |
if (__base_info[i].__base_type->__do_upcast (dst, base, result2)) |
{ |
if (result2.base_type == nonvirtual_base_type && is_virtual) |
result2.base_type = __base_info[i].__base_type; |
if (contained_p (result2.part2dst) && !is_public) |
result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask); |
if (!result.base_type) |
{ |
result = result2; |
if (!contained_p (result.part2dst)) |
return true; // found ambiguously |
if (result.part2dst & __contained_public_mask) |
{ |
if (!(__flags & __non_diamond_repeat_mask)) |
return true; // cannot have an ambiguous other base |
} |
else |
{ |
if (!virtual_p (result.part2dst)) |
return true; // cannot have another path |
if (!(__flags & __diamond_shaped_mask)) |
return true; // cannot have a more accessible path |
} |
} |
else if (result.dst_ptr != result2.dst_ptr) |
{ |
// Found an ambiguity. |
result.dst_ptr = NULL; |
result.part2dst = __contained_ambig; |
return true; |
} |
else if (result.dst_ptr) |
{ |
// Ok, found real object via a virtual path. |
result.part2dst |
= __sub_kind (result.part2dst | result2.part2dst); |
} |
else |
{ |
// Dealing with a null pointer, need to check vbase |
// containing each of the two choices. |
if (result2.base_type == nonvirtual_base_type |
|| result.base_type == nonvirtual_base_type |
|| !(*result2.base_type == *result.base_type)) |
{ |
// Already ambiguous, not virtual or via different virtuals. |
// Cannot match. |
result.part2dst = __contained_ambig; |
return true; |
} |
result.part2dst |
= __sub_kind (result.part2dst | result2.part2dst); |
} |
} |
} |
return result.part2dst != __unknown; |
} |
} |
/contrib/sdk/sources/libsupc++/vterminate.cc |
---|
0,0 → 1,101 |
// Verbose terminate_handler -*- C++ -*- |
// Copyright (C) 2001, 2002, 2004, 2005, 2009, 2011 Free Software Foundation |
// |
// This file is part of the GNU ISO C++ Library. This library is free |
// software; you can redistribute it and/or modify it under the |
// terms of the GNU General Public License as published by the |
// Free Software Foundation; either version 3, or (at your option) |
// any later version. |
// This library is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
#include <bits/c++config.h> |
#if _GLIBCXX_HOSTED |
#include <cstdlib> |
#include <exception> |
#include <bits/exception_defines.h> |
#include <cxxabi.h> |
# include <cstdio> |
using namespace std; |
using namespace abi; |
namespace __gnu_cxx |
{ |
_GLIBCXX_BEGIN_NAMESPACE_VERSION |
// A replacement for the standard terminate_handler which prints |
// more information about the terminating exception (if any) on |
// stderr. |
void __verbose_terminate_handler() |
{ |
static bool terminating; |
if (terminating) |
{ |
//fputs("terminate called recursively\n", stderr); |
abort (); |
} |
terminating = true; |
// Make sure there was an exception; terminate is also called for an |
// attempt to rethrow when there is no suitable exception. |
type_info *t = __cxa_current_exception_type(); |
if (t) |
{ |
// Note that "name" is the mangled name. |
char const *name = t->name(); |
{ |
int status = -1; |
char *dem = 0; |
// dem = __cxa_demangle(name, 0, 0, &status); |
// fputs("terminate called after throwing an instance of '", stderr); |
// if (status == 0) |
// fputs(dem, stderr); |
// else |
// fputs(name, stderr); |
// fputs("'\n", stderr); |
// if (status == 0) |
// free(dem); |
} |
// If the exception is derived from std::exception, we can |
// give more information. |
__try { __throw_exception_again; } |
#ifdef __EXCEPTIONS |
__catch(const exception& exc) |
{ |
char const *w = exc.what(); |
// fputs(" what(): ", stderr); |
// fputs(w, stderr); |
// fputs("\n", stderr); |
} |
#endif |
__catch(...) { } |
} |
else; |
// fputs("terminate called without an active exception\n", stderr); |
abort(); |
} |
_GLIBCXX_END_NAMESPACE_VERSION |
} // namespace |
#endif |