sdk: delete old libsupc++ source
git-svn-id: svn://kolibrios.org@5135 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
9d5ad505ec
commit
834480f388
@ -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
|
||||
|
@ -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";
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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__
|
@ -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;
|
||||
}
|
@ -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";
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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 ();
|
||||
}
|
@ -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
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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() { }
|
||||
}
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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 ();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -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
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
Loading…
Reference in New Issue
Block a user