1
1

sdk: delete old libsupc++ source

git-svn-id: svn://kolibrios.org@5135 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2014-09-21 10:55:49 +00:00
parent 9d5ad505ec
commit 834480f388
39 changed files with 0 additions and 6058 deletions

View File

@ -1,70 +0,0 @@
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

View File

@ -1,34 +0,0 @@
// 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";
}

View File

@ -1,111 +0,0 @@
// 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;
}
}

View File

@ -1,49 +0,0 @@
// 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);
}

View File

@ -1,34 +0,0 @@
// 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);
}

View File

@ -1,220 +0,0 @@
// -*- 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);
}

View File

@ -1,51 +0,0 @@
// -*- 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
}

View File

@ -1,159 +0,0 @@
// -*- 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__

View File

@ -1,138 +0,0 @@
// -*- 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;
}

View File

@ -1,52 +0,0 @@
// -*- 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";
}

View File

@ -1,160 +0,0 @@
// -*- 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

View File

@ -1,781 +0,0 @@
// -*- 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

View File

@ -1,46 +0,0 @@
// -*- 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

View File

@ -1,80 +0,0 @@
// -*- 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;
}

View File

@ -1,117 +0,0 @@
// -*- 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 ();
}

View File

@ -1,54 +0,0 @@
// -*- 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

View File

@ -1,29 +0,0 @@
// -*- 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;

View File

@ -1,158 +0,0 @@
// 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

View File

@ -1,47 +0,0 @@
// -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

View File

@ -1,772 +0,0 @@
/* 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 */

View File

@ -1,150 +0,0 @@
#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;
}

View File

@ -1,416 +0,0 @@
// 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
}
}

View File

@ -1,31 +0,0 @@
// 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() { }
}

View File

@ -1,107 +0,0 @@
// 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

View File

@ -1,124 +0,0 @@
// 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

View File

@ -1,41 +0,0 @@
// 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;
}

View File

@ -1,67 +0,0 @@
// 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;
}

View File

@ -1,63 +0,0 @@
// 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;
}

View File

@ -1,34 +0,0 @@
// 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);
}

View File

@ -1,66 +0,0 @@
// 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);
}
}

View File

@ -1,58 +0,0 @@
// -*- 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 ();
}

View File

@ -1,85 +0,0 @@
// 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);
}
}

View File

@ -1,84 +0,0 @@
// 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;
}
}

View File

@ -1,183 +0,0 @@
// 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);
}
}

View File

@ -1,224 +0,0 @@
// 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

View File

@ -1,382 +0,0 @@
// -*- 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

View File

@ -1,289 +0,0 @@
/* 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 */

View File

@ -1,391 +0,0 @@
// 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;
}
}

View File

@ -1,101 +0,0 @@
// 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