Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5133 → Rev 5134

/contrib/sdk/sources/libstdc++-v3/libsupc++/Makefile
0,0 → 1,103
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= -DHAVE_CONFIG_H -DIN_GCC -DUSE_EMUTLS=1 -D_GLIBCXX_HAVE_TLS
 
 
SOURCES = gthr_mutex.c \
array_type_info.cc \
atexit_thread.cc \
bad_alloc.cc \
bad_cast.cc \
bad_typeid.cc \
class_type_info.cc \
del_op.cc \
del_opnt.cc \
del_opv.cc \
del_opvnt.cc \
dyncast.cc \
eh_alloc.cc \
eh_aux_runtime.cc \
eh_call.cc \
eh_catch.cc \
eh_exception.cc \
eh_globals.cc \
eh_personality.cc \
eh_ptr.cc \
eh_term_handler.cc \
eh_terminate.cc \
eh_throw.cc \
eh_tm.cc \
eh_type.c \
eh_unex_handler.cc \
enum_type_info.cc \
function_type_info.cc \
fundamental_type_info.cc \
guard.cc \
guard_error.cc \
hash_bytes.cc \
nested_exception.cc \
new_handler.cc \
new_op.cc \
new_opnt.cc \
new_opv.cc \
new_opvnt.cc \
pbase_type_info.cc \
pmem_type_info.cc \
pointer_type_info.cc \
pure.cc \
si_class_type_info.cc \
tinfo.cc \
tinfo2.cc \
vec.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 $@ $<
 
eh_ptr.o: eh_ptr.cc
$(CPP) $(CFLAGS) -std=gnu++0x $(DEFINES) $(INCLUDES) -o $@ $<
 
eh_throw.o: eh_throw.cc
$(CPP) $(CFLAGS) -std=gnu++0x $(DEFINES) $(INCLUDES) -o $@ $<
 
guard.o: guard.cc
$(CPP) $(CFLAGS) -std=gnu++0x $(DEFINES) $(INCLUDES) -o $@ $<
 
atexit_thread.o: atexit_thread.cc
$(CPP) $(CFLAGS) -std=gnu++0x $(DEFINES) $(INCLUDES) -o $@ $<
 
nested_exception.o: nested_exception.cc
$(CPP) $(CFLAGS) -std=gnu++0x $(DEFINES) $(INCLUDES) -o $@ $<
 
clean:
-rm -f *.o
 
/contrib/sdk/sources/libstdc++-v3/libsupc++/array_type_info.cc
0,0 → 1,32
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__array_type_info::
~__array_type_info ()
{}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/atexit_arm.cc
0,0 → 1,39
// Copyright (C) 2007-2013 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 <cxxabi.h>
 
#if defined(__arm__) && defined(__ARM_EABI__)
 
namespace __aeabiv1
{
extern "C" int
__aeabi_atexit (void *object,
void (*destructor) (void *),
void *dso_handle) throw ()
{
return abi::__cxa_atexit(destructor, object, dso_handle);
}
} // namespace __aeabiv1
 
#endif // defined(__arm__) && defined(__ARM_EABI__)
/contrib/sdk/sources/libstdc++-v3/libsupc++/atexit_thread.cc
0,0 → 1,145
// Copyright (C) 2012-2013 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 <cxxabi.h>
#include <cstdlib>
#include <new>
#include "bits/gthr.h"
 
#if HAVE___CXA_THREAD_ATEXIT_IMPL
 
extern "C" int __cxa_thread_atexit_impl (void (*func) (void *),
void *arg, void *d);
extern "C" int
__cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *),
void *obj, void *dso_handle)
_GLIBCXX_NOTHROW
{
return __cxa_thread_atexit_impl (dtor, obj, dso_handle);
}
 
#else /* HAVE___CXA_THREAD_ATEXIT_IMPL */
 
namespace {
// One element in a singly-linked stack of cleanups.
struct elt
{
void (*destructor)(void *);
void *object;
elt *next;
};
 
// Keep a per-thread list of cleanups in gthread_key storage.
__gthread_key_t key;
// But also support non-threaded mode.
elt *single_thread;
 
// Run the specified stack of cleanups.
void run (void *p)
{
elt *e = static_cast<elt*>(p);
while (e)
{
elt *old_e = e;
e->destructor (e->object);
e = e->next;
delete (old_e);
}
}
 
// Run the stack of cleanups for the current thread.
void run ()
{
void *e;
if (__gthread_active_p ())
{
e = __gthread_getspecific (key);
__gthread_setspecific (key, NULL);
}
else
{
e = single_thread;
single_thread = NULL;
}
run (e);
}
 
// Initialize the key for the cleanup stack. We use a static local for
// key init/delete rather than atexit so that delete is run on dlclose.
void key_init() {
struct key_s {
key_s() { __gthread_key_create (&key, run); }
~key_s() { __gthread_key_delete (key); }
};
static key_s ks;
// Also make sure the destructors are run by std::exit.
// FIXME TLS cleanups should run before static cleanups and atexit
// cleanups.
std::atexit (run);
}
}
 
extern "C" int
__cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *), void *obj, void */*dso_handle*/)
_GLIBCXX_NOTHROW
{
// Do this initialization once.
if (__gthread_active_p ())
{
// When threads are active use __gthread_once.
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once (&once, key_init);
}
else
{
// And when threads aren't active use a static local guard.
static bool queued;
if (!queued)
{
queued = true;
std::atexit (run);
}
}
 
elt *first;
if (__gthread_active_p ())
first = static_cast<elt*>(__gthread_getspecific (key));
else
first = single_thread;
 
elt *new_elt = new (std::nothrow) elt;
if (!new_elt)
return -1;
new_elt->destructor = dtor;
new_elt->object = obj;
new_elt->next = first;
 
if (__gthread_active_p ())
__gthread_setspecific (key, new_elt);
else
single_thread = new_elt;
 
return 0;
}
 
#endif /* HAVE___CXA_THREAD_ATEXIT_IMPL */
/contrib/sdk/sources/libstdc++-v3/libsupc++/atomic_lockfree_defines.h
0,0 → 1,63
// -*- C++ -*- header.
 
// Copyright (C) 2008-2013 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/atomic_lockfree_defines.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{atomic}
*/
 
#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H
#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1
 
#pragma GCC system_header
 
/**
* @addtogroup atomics
* @{
*/
 
/**
* Lock-free property.
*
* 0 indicates that the types are never lock-free.
* 1 indicates that the types are sometimes lock-free.
* 2 indicates that the types are always lock-free.
*/
 
#if __cplusplus >= 201103L
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
#endif
 
// @} group atomics
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/bad_alloc.cc
0,0 → 1,34
// Implementation file for the -*- C++ -*- dynamic memory management header.
 
// Copyright (C) 2010-2013 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 "new"
 
std::bad_alloc::~bad_alloc() _GLIBCXX_USE_NOEXCEPT { }
 
const char*
std::bad_alloc::what() const _GLIBCXX_USE_NOEXCEPT
{
return "std::bad_alloc";
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/bad_cast.cc
0,0 → 1,36
// Copyright (C) 1994-2013 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>
 
namespace std {
 
bad_cast::~bad_cast() _GLIBCXX_USE_NOEXCEPT { }
 
const char*
bad_cast::what() const _GLIBCXX_USE_NOEXCEPT
{
return "std::bad_cast";
}
 
} // namespace std
/contrib/sdk/sources/libstdc++-v3/libsupc++/bad_typeid.cc
0,0 → 1,36
// Copyright (C) 1994-2013 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>
 
namespace std {
 
bad_typeid::~bad_typeid() _GLIBCXX_USE_NOEXCEPT { }
 
const char*
bad_typeid::what() const _GLIBCXX_USE_NOEXCEPT
{
return "std::bad_typeid";
}
 
} // namespace std
/contrib/sdk/sources/libstdc++-v3/libsupc++/class_type_info.cc
0,0 → 1,110
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__class_type_info::
~__class_type_info ()
{}
 
bool __class_type_info::
__do_catch (const type_info *thr_type,
void **thr_obj,
unsigned outer) const
{
if (*this == *thr_type)
return true;
if (outer >= 4)
// Neither `A' nor `A *'.
return false;
return thr_type->__do_upcast (this, thr_obj);
}
 
bool __class_type_info::
__do_upcast (const __class_type_info *dst_type,
void **obj_ptr) const
{
__upcast_result result (__vmi_class_type_info::__flags_unknown_mask);
__do_upcast (dst_type, *obj_ptr, result);
if (!contained_public_p (result.part2dst))
return false;
*obj_ptr = const_cast <void *> (result.dst_ptr);
return true;
}
 
__class_type_info::__sub_kind __class_type_info::
__do_find_public_src (ptrdiff_t,
const void *obj_ptr,
const __class_type_info *,
const void *src_ptr) const
{
if (src_ptr == obj_ptr)
// Must be our type, as the pointers match.
return __contained_public;
return __not_contained;
}
 
bool __class_type_info::
__do_dyncast (ptrdiff_t,
__sub_kind access_path,
const __class_type_info *dst_type,
const void *obj_ptr,
const __class_type_info *src_type,
const void *src_ptr,
__dyncast_result &__restrict result) const
{
if (obj_ptr == src_ptr && *this == *src_type)
{
// The src object we started from. Indicate how we are accessible from
// the most derived object.
result.whole2src = access_path;
return false;
}
if (*this == *dst_type)
{
result.dst_ptr = obj_ptr;
result.whole2dst = access_path;
result.dst2src = __not_contained;
return false;
}
return false;
}
 
bool __class_type_info::
__do_upcast (const __class_type_info *dst, const void *obj,
__upcast_result &__restrict result) const
{
if (*this == *dst)
{
result.dst_ptr = obj;
result.base_type = nonvirtual_base_type;
result.part2dst = __contained_public;
return true;
}
return false;
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/cp-demangle.c
0,0 → 1,5950
/* Demangler for g++ V3 ABI.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@wasabisystems.com>.
 
This file is part of the libiberty library, which is part of GCC.
 
This file 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 2 of the License, or
(at your option) any later version.
 
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combined
executable.)
 
This program 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.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
 
/* This code implements a demangler for the g++ V3 ABI. The ABI is
described on this web page:
http://www.codesourcery.com/cxx-abi/abi.html#mangling
 
This code was written while looking at the demangler written by
Alex Samuel <samuel@codesourcery.com>.
 
This code first pulls the mangled name apart into a list of
components, and then walks the list generating the demangled
name.
 
This file will normally define the following functions, q.v.:
char *cplus_demangle_v3(const char *mangled, int options)
char *java_demangle_v3(const char *mangled)
int cplus_demangle_v3_callback(const char *mangled, int options,
demangle_callbackref callback)
int java_demangle_v3_callback(const char *mangled,
demangle_callbackref callback)
enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name)
enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name)
 
Also, the interface to the component list is public, and defined in
demangle.h. The interface consists of these types, which are
defined in demangle.h:
enum demangle_component_type
struct demangle_component
demangle_callbackref
and these functions defined in this file:
cplus_demangle_fill_name
cplus_demangle_fill_extended_operator
cplus_demangle_fill_ctor
cplus_demangle_fill_dtor
cplus_demangle_print
cplus_demangle_print_callback
and other functions defined in the file cp-demint.c.
 
This file also defines some other functions and variables which are
only to be used by the file cp-demint.c.
 
Preprocessor macros you can define while compiling this file:
 
IN_LIBGCC2
If defined, this file defines the following functions, q.v.:
char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
int *status)
int __gcclibcxx_demangle_callback (const char *,
void (*)
(const char *, size_t, void *),
void *)
instead of cplus_demangle_v3[_callback]() and
java_demangle_v3[_callback]().
 
IN_GLIBCPP_V3
If defined, this file defines only __cxa_demangle() and
__gcclibcxx_demangle_callback(), and no other publically visible
functions or variables.
 
STANDALONE_DEMANGLER
If defined, this file defines a main() function which demangles
any arguments, or, if none, demangles stdin.
 
CP_DEMANGLE_DEBUG
If defined, turns on debugging mode, which prints information on
stdout about the mangled string. This is not generally useful.
*/
 
#if defined (_AIX) && !defined (__GNUC__)
#pragma alloca
#endif
 
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
 
#include <stdio.h>
 
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
 
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#else
# ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# else
extern char *alloca ();
# endif /* __GNUC__ */
# endif /* alloca */
#endif /* HAVE_ALLOCA_H */
 
#include "ansidecl.h"
#include "libiberty.h"
#include "demangle.h"
#include "cp-demangle.h"
 
/* If IN_GLIBCPP_V3 is defined, some functions are made static. We
also rename them via #define to avoid compiler errors when the
static definition conflicts with the extern declaration in a header
file. */
#ifdef IN_GLIBCPP_V3
 
#define CP_STATIC_IF_GLIBCPP_V3 static
 
#define cplus_demangle_fill_name d_fill_name
static int d_fill_name (struct demangle_component *, const char *, int);
 
#define cplus_demangle_fill_extended_operator d_fill_extended_operator
static int
d_fill_extended_operator (struct demangle_component *, int,
struct demangle_component *);
 
#define cplus_demangle_fill_ctor d_fill_ctor
static int
d_fill_ctor (struct demangle_component *, enum gnu_v3_ctor_kinds,
struct demangle_component *);
 
#define cplus_demangle_fill_dtor d_fill_dtor
static int
d_fill_dtor (struct demangle_component *, enum gnu_v3_dtor_kinds,
struct demangle_component *);
 
#define cplus_demangle_mangled_name d_mangled_name
static struct demangle_component *d_mangled_name (struct d_info *, int);
 
#define cplus_demangle_type d_type
static struct demangle_component *d_type (struct d_info *);
 
#define cplus_demangle_print d_print
static char *d_print (int, const struct demangle_component *, int, size_t *);
 
#define cplus_demangle_print_callback d_print_callback
static int d_print_callback (int, const struct demangle_component *,
demangle_callbackref, void *);
 
#define cplus_demangle_init_info d_init_info
static void d_init_info (const char *, int, size_t, struct d_info *);
 
#else /* ! defined(IN_GLIBCPP_V3) */
#define CP_STATIC_IF_GLIBCPP_V3
#endif /* ! defined(IN_GLIBCPP_V3) */
 
/* See if the compiler supports dynamic arrays. */
 
#ifdef __GNUC__
#define CP_DYNAMIC_ARRAYS
#else
#ifdef __STDC__
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ >= 199901L
#define CP_DYNAMIC_ARRAYS
#endif /* __STDC__VERSION >= 199901L */
#endif /* defined (__STDC_VERSION__) */
#endif /* defined (__STDC__) */
#endif /* ! defined (__GNUC__) */
 
/* We avoid pulling in the ctype tables, to prevent pulling in
additional unresolved symbols when this code is used in a library.
FIXME: Is this really a valid reason? This comes from the original
V3 demangler code.
 
As of this writing this file has the following undefined references
when compiled with -DIN_GLIBCPP_V3: realloc, free, memcpy, strcpy,
strcat, strlen. */
 
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
 
/* The prefix prepended by GCC to an identifier represnting the
anonymous namespace. */
#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
#define ANONYMOUS_NAMESPACE_PREFIX_LEN \
(sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1)
 
/* Information we keep for the standard substitutions. */
 
struct d_standard_sub_info
{
/* The code for this substitution. */
char code;
/* The simple string it expands to. */
const char *simple_expansion;
/* The length of the simple expansion. */
int simple_len;
/* The results of a full, verbose, expansion. This is used when
qualifying a constructor/destructor, or when in verbose mode. */
const char *full_expansion;
/* The length of the full expansion. */
int full_len;
/* What to set the last_name field of d_info to; NULL if we should
not set it. This is only relevant when qualifying a
constructor/destructor. */
const char *set_last_name;
/* The length of set_last_name. */
int set_last_name_len;
};
 
/* Accessors for subtrees of struct demangle_component. */
 
#define d_left(dc) ((dc)->u.s_binary.left)
#define d_right(dc) ((dc)->u.s_binary.right)
 
/* A list of templates. This is used while printing. */
 
struct d_print_template
{
/* Next template on the list. */
struct d_print_template *next;
/* This template. */
const struct demangle_component *template_decl;
};
 
/* A list of type modifiers. This is used while printing. */
 
struct d_print_mod
{
/* Next modifier on the list. These are in the reverse of the order
in which they appeared in the mangled string. */
struct d_print_mod *next;
/* The modifier. */
const struct demangle_component *mod;
/* Whether this modifier was printed. */
int printed;
/* The list of templates which applies to this modifier. */
struct d_print_template *templates;
};
 
/* We use these structures to hold information during printing. */
 
struct d_growable_string
{
/* Buffer holding the result. */
char *buf;
/* Current length of data in buffer. */
size_t len;
/* Allocated size of buffer. */
size_t alc;
/* Set to 1 if we had a memory allocation failure. */
int allocation_failure;
};
 
enum { D_PRINT_BUFFER_LENGTH = 256 };
struct d_print_info
{
/* Fixed-length allocated buffer for demangled data, flushed to the
callback with a NUL termination once full. */
char buf[D_PRINT_BUFFER_LENGTH];
/* Current length of data in buffer. */
size_t len;
/* The last character printed, saved individually so that it survives
any buffer flush. */
char last_char;
/* Callback function to handle demangled buffer flush. */
demangle_callbackref callback;
/* Opaque callback argument. */
void *opaque;
/* The current list of templates, if any. */
struct d_print_template *templates;
/* The current list of modifiers (e.g., pointer, reference, etc.),
if any. */
struct d_print_mod *modifiers;
/* Set to 1 if we saw a demangling error. */
int demangle_failure;
/* The current index into any template argument packs we are using
for printing. */
int pack_index;
/* Number of d_print_flush calls so far. */
unsigned long int flush_count;
};
 
#ifdef CP_DEMANGLE_DEBUG
static void d_dump (struct demangle_component *, int);
#endif
 
static struct demangle_component *
d_make_empty (struct d_info *);
 
static struct demangle_component *
d_make_comp (struct d_info *, enum demangle_component_type,
struct demangle_component *,
struct demangle_component *);
 
static struct demangle_component *
d_make_name (struct d_info *, const char *, int);
 
static struct demangle_component *
d_make_demangle_mangled_name (struct d_info *, const char *);
 
static struct demangle_component *
d_make_builtin_type (struct d_info *,
const struct demangle_builtin_type_info *);
 
static struct demangle_component *
d_make_operator (struct d_info *,
const struct demangle_operator_info *);
 
static struct demangle_component *
d_make_extended_operator (struct d_info *, int,
struct demangle_component *);
 
static struct demangle_component *
d_make_ctor (struct d_info *, enum gnu_v3_ctor_kinds,
struct demangle_component *);
 
static struct demangle_component *
d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds,
struct demangle_component *);
 
static struct demangle_component *
d_make_template_param (struct d_info *, long);
 
static struct demangle_component *
d_make_sub (struct d_info *, const char *, int);
 
static int
has_return_type (struct demangle_component *);
 
static int
is_ctor_dtor_or_conversion (struct demangle_component *);
 
static struct demangle_component *d_encoding (struct d_info *, int);
 
static struct demangle_component *d_name (struct d_info *);
 
static struct demangle_component *d_nested_name (struct d_info *);
 
static struct demangle_component *d_prefix (struct d_info *);
 
static struct demangle_component *d_unqualified_name (struct d_info *);
 
static struct demangle_component *d_source_name (struct d_info *);
 
static long d_number (struct d_info *);
 
static struct demangle_component *d_identifier (struct d_info *, int);
 
static struct demangle_component *d_operator_name (struct d_info *);
 
static struct demangle_component *d_special_name (struct d_info *);
 
static int d_call_offset (struct d_info *, int);
 
static struct demangle_component *d_ctor_dtor_name (struct d_info *);
 
static struct demangle_component **
d_cv_qualifiers (struct d_info *, struct demangle_component **, int);
 
static struct demangle_component *
d_ref_qualifier (struct d_info *, struct demangle_component *);
 
static struct demangle_component *
d_function_type (struct d_info *);
 
static struct demangle_component *
d_bare_function_type (struct d_info *, int);
 
static struct demangle_component *
d_class_enum_type (struct d_info *);
 
static struct demangle_component *d_array_type (struct d_info *);
 
static struct demangle_component *d_vector_type (struct d_info *);
 
static struct demangle_component *
d_pointer_to_member_type (struct d_info *);
 
static struct demangle_component *
d_template_param (struct d_info *);
 
static struct demangle_component *d_template_args (struct d_info *);
 
static struct demangle_component *
d_template_arg (struct d_info *);
 
static struct demangle_component *d_expression (struct d_info *);
 
static struct demangle_component *d_expr_primary (struct d_info *);
 
static struct demangle_component *d_local_name (struct d_info *);
 
static int d_discriminator (struct d_info *);
 
static struct demangle_component *d_lambda (struct d_info *);
 
static struct demangle_component *d_unnamed_type (struct d_info *);
 
static struct demangle_component *
d_clone_suffix (struct d_info *, struct demangle_component *);
 
static int
d_add_substitution (struct d_info *, struct demangle_component *);
 
static struct demangle_component *d_substitution (struct d_info *, int);
 
static void d_growable_string_init (struct d_growable_string *, size_t);
 
static inline void
d_growable_string_resize (struct d_growable_string *, size_t);
 
static inline void
d_growable_string_append_buffer (struct d_growable_string *,
const char *, size_t);
static void
d_growable_string_callback_adapter (const char *, size_t, void *);
 
static void
d_print_init (struct d_print_info *, demangle_callbackref, void *);
 
static inline void d_print_error (struct d_print_info *);
 
static inline int d_print_saw_error (struct d_print_info *);
 
static inline void d_print_flush (struct d_print_info *);
 
static inline void d_append_char (struct d_print_info *, char);
 
static inline void d_append_buffer (struct d_print_info *,
const char *, size_t);
 
static inline void d_append_string (struct d_print_info *, const char *);
 
static inline char d_last_char (struct d_print_info *);
 
static void
d_print_comp (struct d_print_info *, int, const struct demangle_component *);
 
static void
d_print_java_identifier (struct d_print_info *, const char *, int);
 
static void
d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int);
 
static void
d_print_mod (struct d_print_info *, int, const struct demangle_component *);
 
static void
d_print_function_type (struct d_print_info *, int,
const struct demangle_component *,
struct d_print_mod *);
 
static void
d_print_array_type (struct d_print_info *, int,
const struct demangle_component *,
struct d_print_mod *);
 
static void
d_print_expr_op (struct d_print_info *, int, const struct demangle_component *);
 
static void
d_print_cast (struct d_print_info *, int, const struct demangle_component *);
 
static int d_demangle_callback (const char *, int,
demangle_callbackref, void *);
static char *d_demangle (const char *, int, size_t *);
 
#ifdef CP_DEMANGLE_DEBUG
 
static void
d_dump (struct demangle_component *dc, int indent)
{
int i;
 
if (dc == NULL)
{
if (indent == 0)
printf ("failed demangling\n");
return;
}
 
for (i = 0; i < indent; ++i)
putchar (' ');
 
switch (dc->type)
{
case DEMANGLE_COMPONENT_NAME:
printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
return;
case DEMANGLE_COMPONENT_TAGGED_NAME:
printf ("tagged name\n");
d_dump (dc->u.s_binary.left, indent + 2);
d_dump (dc->u.s_binary.right, indent + 2);
return;
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
printf ("template parameter %ld\n", dc->u.s_number.number);
return;
case DEMANGLE_COMPONENT_CTOR:
printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
d_dump (dc->u.s_ctor.name, indent + 2);
return;
case DEMANGLE_COMPONENT_DTOR:
printf ("destructor %d\n", (int) dc->u.s_dtor.kind);
d_dump (dc->u.s_dtor.name, indent + 2);
return;
case DEMANGLE_COMPONENT_SUB_STD:
printf ("standard substitution %s\n", dc->u.s_string.string);
return;
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
printf ("builtin type %s\n", dc->u.s_builtin.type->name);
return;
case DEMANGLE_COMPONENT_OPERATOR:
printf ("operator %s\n", dc->u.s_operator.op->name);
return;
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
printf ("extended operator with %d args\n",
dc->u.s_extended_operator.args);
d_dump (dc->u.s_extended_operator.name, indent + 2);
return;
 
case DEMANGLE_COMPONENT_QUAL_NAME:
printf ("qualified name\n");
break;
case DEMANGLE_COMPONENT_LOCAL_NAME:
printf ("local name\n");
break;
case DEMANGLE_COMPONENT_TYPED_NAME:
printf ("typed name\n");
break;
case DEMANGLE_COMPONENT_TEMPLATE:
printf ("template\n");
break;
case DEMANGLE_COMPONENT_VTABLE:
printf ("vtable\n");
break;
case DEMANGLE_COMPONENT_VTT:
printf ("VTT\n");
break;
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
printf ("construction vtable\n");
break;
case DEMANGLE_COMPONENT_TYPEINFO:
printf ("typeinfo\n");
break;
case DEMANGLE_COMPONENT_TYPEINFO_NAME:
printf ("typeinfo name\n");
break;
case DEMANGLE_COMPONENT_TYPEINFO_FN:
printf ("typeinfo function\n");
break;
case DEMANGLE_COMPONENT_THUNK:
printf ("thunk\n");
break;
case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
printf ("virtual thunk\n");
break;
case DEMANGLE_COMPONENT_COVARIANT_THUNK:
printf ("covariant thunk\n");
break;
case DEMANGLE_COMPONENT_JAVA_CLASS:
printf ("java class\n");
break;
case DEMANGLE_COMPONENT_GUARD:
printf ("guard\n");
break;
case DEMANGLE_COMPONENT_REFTEMP:
printf ("reference temporary\n");
break;
case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
printf ("hidden alias\n");
break;
case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
printf ("transaction clone\n");
break;
case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
printf ("non-transaction clone\n");
break;
case DEMANGLE_COMPONENT_RESTRICT:
printf ("restrict\n");
break;
case DEMANGLE_COMPONENT_VOLATILE:
printf ("volatile\n");
break;
case DEMANGLE_COMPONENT_CONST:
printf ("const\n");
break;
case DEMANGLE_COMPONENT_RESTRICT_THIS:
printf ("restrict this\n");
break;
case DEMANGLE_COMPONENT_VOLATILE_THIS:
printf ("volatile this\n");
break;
case DEMANGLE_COMPONENT_CONST_THIS:
printf ("const this\n");
break;
case DEMANGLE_COMPONENT_REFERENCE_THIS:
printf ("reference this\n");
break;
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
printf ("rvalue reference this\n");
break;
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
printf ("vendor type qualifier\n");
break;
case DEMANGLE_COMPONENT_POINTER:
printf ("pointer\n");
break;
case DEMANGLE_COMPONENT_REFERENCE:
printf ("reference\n");
break;
case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
printf ("rvalue reference\n");
break;
case DEMANGLE_COMPONENT_COMPLEX:
printf ("complex\n");
break;
case DEMANGLE_COMPONENT_IMAGINARY:
printf ("imaginary\n");
break;
case DEMANGLE_COMPONENT_VENDOR_TYPE:
printf ("vendor type\n");
break;
case DEMANGLE_COMPONENT_FUNCTION_TYPE:
printf ("function type\n");
break;
case DEMANGLE_COMPONENT_ARRAY_TYPE:
printf ("array type\n");
break;
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
printf ("pointer to member type\n");
break;
case DEMANGLE_COMPONENT_FIXED_TYPE:
printf ("fixed-point type\n");
break;
case DEMANGLE_COMPONENT_ARGLIST:
printf ("argument list\n");
break;
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
printf ("template argument list\n");
break;
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
printf ("initializer list\n");
break;
case DEMANGLE_COMPONENT_CAST:
printf ("cast\n");
break;
case DEMANGLE_COMPONENT_NULLARY:
printf ("nullary operator\n");
break;
case DEMANGLE_COMPONENT_UNARY:
printf ("unary operator\n");
break;
case DEMANGLE_COMPONENT_BINARY:
printf ("binary operator\n");
break;
case DEMANGLE_COMPONENT_BINARY_ARGS:
printf ("binary operator arguments\n");
break;
case DEMANGLE_COMPONENT_TRINARY:
printf ("trinary operator\n");
break;
case DEMANGLE_COMPONENT_TRINARY_ARG1:
printf ("trinary operator arguments 1\n");
break;
case DEMANGLE_COMPONENT_TRINARY_ARG2:
printf ("trinary operator arguments 1\n");
break;
case DEMANGLE_COMPONENT_LITERAL:
printf ("literal\n");
break;
case DEMANGLE_COMPONENT_LITERAL_NEG:
printf ("negative literal\n");
break;
case DEMANGLE_COMPONENT_JAVA_RESOURCE:
printf ("java resource\n");
break;
case DEMANGLE_COMPONENT_COMPOUND_NAME:
printf ("compound name\n");
break;
case DEMANGLE_COMPONENT_CHARACTER:
printf ("character '%c'\n", dc->u.s_character.character);
return;
case DEMANGLE_COMPONENT_DECLTYPE:
printf ("decltype\n");
break;
case DEMANGLE_COMPONENT_PACK_EXPANSION:
printf ("pack expansion\n");
break;
case DEMANGLE_COMPONENT_TLS_INIT:
printf ("tls init function\n");
break;
case DEMANGLE_COMPONENT_TLS_WRAPPER:
printf ("tls wrapper function\n");
break;
case DEMANGLE_COMPONENT_DEFAULT_ARG:
printf ("default argument %d\n", dc->u.s_unary_num.num);
d_dump (dc->u.s_unary_num.sub, indent+2);
return;
case DEMANGLE_COMPONENT_LAMBDA:
printf ("lambda %d\n", dc->u.s_unary_num.num);
d_dump (dc->u.s_unary_num.sub, indent+2);
return;
}
 
d_dump (d_left (dc), indent + 2);
d_dump (d_right (dc), indent + 2);
}
 
#endif /* CP_DEMANGLE_DEBUG */
 
/* Fill in a DEMANGLE_COMPONENT_NAME. */
 
CP_STATIC_IF_GLIBCPP_V3
int
cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len)
{
if (p == NULL || s == NULL || len == 0)
return 0;
p->type = DEMANGLE_COMPONENT_NAME;
p->u.s_name.s = s;
p->u.s_name.len = len;
return 1;
}
 
/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */
 
CP_STATIC_IF_GLIBCPP_V3
int
cplus_demangle_fill_extended_operator (struct demangle_component *p, int args,
struct demangle_component *name)
{
if (p == NULL || args < 0 || name == NULL)
return 0;
p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR;
p->u.s_extended_operator.args = args;
p->u.s_extended_operator.name = name;
return 1;
}
 
/* Fill in a DEMANGLE_COMPONENT_CTOR. */
 
CP_STATIC_IF_GLIBCPP_V3
int
cplus_demangle_fill_ctor (struct demangle_component *p,
enum gnu_v3_ctor_kinds kind,
struct demangle_component *name)
{
if (p == NULL
|| name == NULL
|| (int) kind < gnu_v3_complete_object_ctor
|| (int) kind > gnu_v3_object_ctor_group)
return 0;
p->type = DEMANGLE_COMPONENT_CTOR;
p->u.s_ctor.kind = kind;
p->u.s_ctor.name = name;
return 1;
}
 
/* Fill in a DEMANGLE_COMPONENT_DTOR. */
 
CP_STATIC_IF_GLIBCPP_V3
int
cplus_demangle_fill_dtor (struct demangle_component *p,
enum gnu_v3_dtor_kinds kind,
struct demangle_component *name)
{
if (p == NULL
|| name == NULL
|| (int) kind < gnu_v3_deleting_dtor
|| (int) kind > gnu_v3_object_dtor_group)
return 0;
p->type = DEMANGLE_COMPONENT_DTOR;
p->u.s_dtor.kind = kind;
p->u.s_dtor.name = name;
return 1;
}
 
/* Add a new component. */
 
static struct demangle_component *
d_make_empty (struct d_info *di)
{
struct demangle_component *p;
 
if (di->next_comp >= di->num_comps)
return NULL;
p = &di->comps[di->next_comp];
++di->next_comp;
return p;
}
 
/* Add a new generic component. */
 
static struct demangle_component *
d_make_comp (struct d_info *di, enum demangle_component_type type,
struct demangle_component *left,
struct demangle_component *right)
{
struct demangle_component *p;
 
/* We check for errors here. A typical error would be a NULL return
from a subroutine. We catch those here, and return NULL
upward. */
switch (type)
{
/* These types require two parameters. */
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
case DEMANGLE_COMPONENT_TYPED_NAME:
case DEMANGLE_COMPONENT_TAGGED_NAME:
case DEMANGLE_COMPONENT_TEMPLATE:
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
case DEMANGLE_COMPONENT_UNARY:
case DEMANGLE_COMPONENT_BINARY:
case DEMANGLE_COMPONENT_BINARY_ARGS:
case DEMANGLE_COMPONENT_TRINARY:
case DEMANGLE_COMPONENT_TRINARY_ARG1:
case DEMANGLE_COMPONENT_LITERAL:
case DEMANGLE_COMPONENT_LITERAL_NEG:
case DEMANGLE_COMPONENT_COMPOUND_NAME:
case DEMANGLE_COMPONENT_VECTOR_TYPE:
case DEMANGLE_COMPONENT_CLONE:
if (left == NULL || right == NULL)
return NULL;
break;
 
/* These types only require one parameter. */
case DEMANGLE_COMPONENT_VTABLE:
case DEMANGLE_COMPONENT_VTT:
case DEMANGLE_COMPONENT_TYPEINFO:
case DEMANGLE_COMPONENT_TYPEINFO_NAME:
case DEMANGLE_COMPONENT_TYPEINFO_FN:
case DEMANGLE_COMPONENT_THUNK:
case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
case DEMANGLE_COMPONENT_COVARIANT_THUNK:
case DEMANGLE_COMPONENT_JAVA_CLASS:
case DEMANGLE_COMPONENT_GUARD:
case DEMANGLE_COMPONENT_TLS_INIT:
case DEMANGLE_COMPONENT_TLS_WRAPPER:
case DEMANGLE_COMPONENT_REFTEMP:
case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_REFERENCE:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
case DEMANGLE_COMPONENT_COMPLEX:
case DEMANGLE_COMPONENT_IMAGINARY:
case DEMANGLE_COMPONENT_VENDOR_TYPE:
case DEMANGLE_COMPONENT_CAST:
case DEMANGLE_COMPONENT_JAVA_RESOURCE:
case DEMANGLE_COMPONENT_DECLTYPE:
case DEMANGLE_COMPONENT_PACK_EXPANSION:
case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
case DEMANGLE_COMPONENT_NULLARY:
case DEMANGLE_COMPONENT_TRINARY_ARG2:
if (left == NULL)
return NULL;
break;
 
/* This needs a right parameter, but the left parameter can be
empty. */
case DEMANGLE_COMPONENT_ARRAY_TYPE:
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
if (right == NULL)
return NULL;
break;
 
/* These are allowed to have no parameters--in some cases they
will be filled in later. */
case DEMANGLE_COMPONENT_FUNCTION_TYPE:
case DEMANGLE_COMPONENT_RESTRICT:
case DEMANGLE_COMPONENT_VOLATILE:
case DEMANGLE_COMPONENT_CONST:
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_REFERENCE_THIS:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
case DEMANGLE_COMPONENT_ARGLIST:
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
break;
 
/* Other types should not be seen here. */
default:
return NULL;
}
 
p = d_make_empty (di);
if (p != NULL)
{
p->type = type;
p->u.s_binary.left = left;
p->u.s_binary.right = right;
}
return p;
}
 
/* Add a new demangle mangled name component. */
 
static struct demangle_component *
d_make_demangle_mangled_name (struct d_info *di, const char *s)
{
if (d_peek_char (di) != '_' || d_peek_next_char (di) != 'Z')
return d_make_name (di, s, strlen (s));
d_advance (di, 2);
return d_encoding (di, 0);
}
 
/* Add a new name component. */
 
static struct demangle_component *
d_make_name (struct d_info *di, const char *s, int len)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (! cplus_demangle_fill_name (p, s, len))
return NULL;
return p;
}
 
/* Add a new builtin type component. */
 
static struct demangle_component *
d_make_builtin_type (struct d_info *di,
const struct demangle_builtin_type_info *type)
{
struct demangle_component *p;
 
if (type == NULL)
return NULL;
p = d_make_empty (di);
if (p != NULL)
{
p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE;
p->u.s_builtin.type = type;
}
return p;
}
 
/* Add a new operator component. */
 
static struct demangle_component *
d_make_operator (struct d_info *di, const struct demangle_operator_info *op)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (p != NULL)
{
p->type = DEMANGLE_COMPONENT_OPERATOR;
p->u.s_operator.op = op;
}
return p;
}
 
/* Add a new extended operator component. */
 
static struct demangle_component *
d_make_extended_operator (struct d_info *di, int args,
struct demangle_component *name)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (! cplus_demangle_fill_extended_operator (p, args, name))
return NULL;
return p;
}
 
static struct demangle_component *
d_make_default_arg (struct d_info *di, int num,
struct demangle_component *sub)
{
struct demangle_component *p = d_make_empty (di);
if (p)
{
p->type = DEMANGLE_COMPONENT_DEFAULT_ARG;
p->u.s_unary_num.num = num;
p->u.s_unary_num.sub = sub;
}
return p;
}
 
/* Add a new constructor component. */
 
static struct demangle_component *
d_make_ctor (struct d_info *di, enum gnu_v3_ctor_kinds kind,
struct demangle_component *name)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (! cplus_demangle_fill_ctor (p, kind, name))
return NULL;
return p;
}
 
/* Add a new destructor component. */
 
static struct demangle_component *
d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind,
struct demangle_component *name)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (! cplus_demangle_fill_dtor (p, kind, name))
return NULL;
return p;
}
 
/* Add a new template parameter. */
 
static struct demangle_component *
d_make_template_param (struct d_info *di, long i)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (p != NULL)
{
p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM;
p->u.s_number.number = i;
}
return p;
}
 
/* Add a new function parameter. */
 
static struct demangle_component *
d_make_function_param (struct d_info *di, long i)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (p != NULL)
{
p->type = DEMANGLE_COMPONENT_FUNCTION_PARAM;
p->u.s_number.number = i;
}
return p;
}
 
/* Add a new standard substitution component. */
 
static struct demangle_component *
d_make_sub (struct d_info *di, const char *name, int len)
{
struct demangle_component *p;
 
p = d_make_empty (di);
if (p != NULL)
{
p->type = DEMANGLE_COMPONENT_SUB_STD;
p->u.s_string.string = name;
p->u.s_string.len = len;
}
return p;
}
 
/* <mangled-name> ::= _Z <encoding> [<clone-suffix>]*
 
TOP_LEVEL is non-zero when called at the top level. */
 
CP_STATIC_IF_GLIBCPP_V3
struct demangle_component *
cplus_demangle_mangled_name (struct d_info *di, int top_level)
{
struct demangle_component *p;
 
if (! d_check_char (di, '_')
/* Allow missing _ if not at toplevel to work around a
bug in G++ abi-version=2 mangling; see the comment in
write_template_arg. */
&& top_level)
return NULL;
if (! d_check_char (di, 'Z'))
return NULL;
p = d_encoding (di, top_level);
 
/* If at top level and parsing parameters, check for a clone
suffix. */
if (top_level && (di->options & DMGL_PARAMS) != 0)
while (d_peek_char (di) == '.'
&& (IS_LOWER (d_peek_next_char (di))
|| d_peek_next_char (di) == '_'
|| IS_DIGIT (d_peek_next_char (di))))
p = d_clone_suffix (di, p);
 
return p;
}
 
/* Return whether a function should have a return type. The argument
is the function name, which may be qualified in various ways. The
rules are that template functions have return types with some
exceptions, function types which are not part of a function name
mangling have return types with some exceptions, and non-template
function names do not have return types. The exceptions are that
constructors, destructors, and conversion operators do not have
return types. */
 
static int
has_return_type (struct demangle_component *dc)
{
if (dc == NULL)
return 0;
switch (dc->type)
{
default:
return 0;
case DEMANGLE_COMPONENT_TEMPLATE:
return ! is_ctor_dtor_or_conversion (d_left (dc));
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_REFERENCE_THIS:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
return has_return_type (d_left (dc));
}
}
 
/* Return whether a name is a constructor, a destructor, or a
conversion operator. */
 
static int
is_ctor_dtor_or_conversion (struct demangle_component *dc)
{
if (dc == NULL)
return 0;
switch (dc->type)
{
default:
return 0;
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
return is_ctor_dtor_or_conversion (d_right (dc));
case DEMANGLE_COMPONENT_CTOR:
case DEMANGLE_COMPONENT_DTOR:
case DEMANGLE_COMPONENT_CAST:
return 1;
}
}
 
/* <encoding> ::= <(function) name> <bare-function-type>
::= <(data) name>
::= <special-name>
 
TOP_LEVEL is non-zero when called at the top level, in which case
if DMGL_PARAMS is not set we do not demangle the function
parameters. We only set this at the top level, because otherwise
we would not correctly demangle names in local scopes. */
 
static struct demangle_component *
d_encoding (struct d_info *di, int top_level)
{
char peek = d_peek_char (di);
 
if (peek == 'G' || peek == 'T')
return d_special_name (di);
else
{
struct demangle_component *dc;
 
dc = d_name (di);
 
if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0)
{
/* Strip off any initial CV-qualifiers, as they really apply
to the `this' parameter, and they were not output by the
v2 demangler without DMGL_PARAMS. */
while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| dc->type == DEMANGLE_COMPONENT_CONST_THIS
|| dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|| dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
dc = d_left (dc);
 
/* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
there may be CV-qualifiers on its right argument which
really apply here; this happens when parsing a class
which is local to a function. */
if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME)
{
struct demangle_component *dcr;
 
dcr = d_right (dc);
while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| dcr->type == DEMANGLE_COMPONENT_CONST_THIS
|| dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|| dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
dcr = d_left (dcr);
dc->u.s_binary.right = dcr;
}
 
return dc;
}
 
peek = d_peek_char (di);
if (dc == NULL || peek == '\0' || peek == 'E')
return dc;
return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc,
d_bare_function_type (di, has_return_type (dc)));
}
}
 
/* <tagged-name> ::= <name> B <source-name> */
 
static struct demangle_component *
d_abi_tags (struct d_info *di, struct demangle_component *dc)
{
char peek;
while (peek = d_peek_char (di),
peek == 'B')
{
struct demangle_component *tag;
d_advance (di, 1);
tag = d_source_name (di);
dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag);
}
return dc;
}
 
/* <name> ::= <nested-name>
::= <unscoped-name>
::= <unscoped-template-name> <template-args>
::= <local-name>
 
<unscoped-name> ::= <unqualified-name>
::= St <unqualified-name>
 
<unscoped-template-name> ::= <unscoped-name>
::= <substitution>
*/
 
static struct demangle_component *
d_name (struct d_info *di)
{
char peek = d_peek_char (di);
struct demangle_component *dc;
 
switch (peek)
{
case 'N':
return d_nested_name (di);
 
case 'Z':
return d_local_name (di);
 
case 'L':
case 'U':
return d_unqualified_name (di);
 
case 'S':
{
int subst;
 
if (d_peek_next_char (di) != 't')
{
dc = d_substitution (di, 0);
subst = 1;
}
else
{
d_advance (di, 2);
dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME,
d_make_name (di, "std", 3),
d_unqualified_name (di));
di->expansion += 3;
subst = 0;
}
 
if (d_peek_char (di) != 'I')
{
/* The grammar does not permit this case to occur if we
called d_substitution() above (i.e., subst == 1). We
don't bother to check. */
}
else
{
/* This is <template-args>, which means that we just saw
<unscoped-template-name>, which is a substitution
candidate if we didn't just get it from a
substitution. */
if (! subst)
{
if (! d_add_substitution (di, dc))
return NULL;
}
dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
d_template_args (di));
}
 
return dc;
}
 
default:
dc = d_unqualified_name (di);
if (d_peek_char (di) == 'I')
{
/* This is <template-args>, which means that we just saw
<unscoped-template-name>, which is a substitution
candidate. */
if (! d_add_substitution (di, dc))
return NULL;
dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
d_template_args (di));
}
return dc;
}
}
 
/* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
*/
 
static struct demangle_component *
d_nested_name (struct d_info *di)
{
struct demangle_component *ret;
struct demangle_component **pret;
struct demangle_component *rqual;
 
if (! d_check_char (di, 'N'))
return NULL;
 
pret = d_cv_qualifiers (di, &ret, 1);
if (pret == NULL)
return NULL;
 
/* Parse the ref-qualifier now and then attach it
once we have something to attach it to. */
rqual = d_ref_qualifier (di, NULL);
 
*pret = d_prefix (di);
if (*pret == NULL)
return NULL;
 
if (rqual)
{
d_left (rqual) = ret;
ret = rqual;
}
 
if (! d_check_char (di, 'E'))
return NULL;
 
return ret;
}
 
/* <prefix> ::= <prefix> <unqualified-name>
::= <template-prefix> <template-args>
::= <template-param>
::= <decltype>
::=
::= <substitution>
 
<template-prefix> ::= <prefix> <(template) unqualified-name>
::= <template-param>
::= <substitution>
*/
 
static struct demangle_component *
d_prefix (struct d_info *di)
{
struct demangle_component *ret = NULL;
 
while (1)
{
char peek;
enum demangle_component_type comb_type;
struct demangle_component *dc;
 
peek = d_peek_char (di);
if (peek == '\0')
return NULL;
 
/* The older code accepts a <local-name> here, but I don't see
that in the grammar. The older code does not accept a
<template-param> here. */
 
comb_type = DEMANGLE_COMPONENT_QUAL_NAME;
if (peek == 'D')
{
char peek2 = d_peek_next_char (di);
if (peek2 == 'T' || peek2 == 't')
/* Decltype. */
dc = cplus_demangle_type (di);
else
/* Destructor name. */
dc = d_unqualified_name (di);
}
else if (IS_DIGIT (peek)
|| IS_LOWER (peek)
|| peek == 'C'
|| peek == 'U'
|| peek == 'L')
dc = d_unqualified_name (di);
else if (peek == 'S')
dc = d_substitution (di, 1);
else if (peek == 'I')
{
if (ret == NULL)
return NULL;
comb_type = DEMANGLE_COMPONENT_TEMPLATE;
dc = d_template_args (di);
}
else if (peek == 'T')
dc = d_template_param (di);
else if (peek == 'E')
return ret;
else if (peek == 'M')
{
/* Initializer scope for a lambda. We don't need to represent
this; the normal code will just treat the variable as a type
scope, which gives appropriate output. */
if (ret == NULL)
return NULL;
d_advance (di, 1);
continue;
}
else
return NULL;
 
if (ret == NULL)
ret = dc;
else
ret = d_make_comp (di, comb_type, ret, dc);
 
if (peek != 'S' && d_peek_char (di) != 'E')
{
if (! d_add_substitution (di, ret))
return NULL;
}
}
}
 
/* <unqualified-name> ::= <operator-name>
::= <ctor-dtor-name>
::= <source-name>
::= <local-source-name>
 
<local-source-name> ::= L <source-name> <discriminator>
*/
 
static struct demangle_component *
d_unqualified_name (struct d_info *di)
{
struct demangle_component *ret;
char peek;
 
peek = d_peek_char (di);
if (IS_DIGIT (peek))
ret = d_source_name (di);
else if (IS_LOWER (peek))
{
ret = d_operator_name (di);
if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
{
di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
if (!strcmp (ret->u.s_operator.op->code, "li"))
ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret,
d_source_name (di));
}
}
else if (peek == 'C' || peek == 'D')
ret = d_ctor_dtor_name (di);
else if (peek == 'L')
{
d_advance (di, 1);
 
ret = d_source_name (di);
if (ret == NULL)
return NULL;
if (! d_discriminator (di))
return NULL;
}
else if (peek == 'U')
{
switch (d_peek_next_char (di))
{
case 'l':
ret = d_lambda (di);
break;
case 't':
ret = d_unnamed_type (di);
break;
default:
return NULL;
}
}
else
return NULL;
 
if (d_peek_char (di) == 'B')
ret = d_abi_tags (di, ret);
return ret;
}
 
/* <source-name> ::= <(positive length) number> <identifier> */
 
static struct demangle_component *
d_source_name (struct d_info *di)
{
long len;
struct demangle_component *ret;
 
len = d_number (di);
if (len <= 0)
return NULL;
ret = d_identifier (di, len);
di->last_name = ret;
return ret;
}
 
/* number ::= [n] <(non-negative decimal integer)> */
 
static long
d_number (struct d_info *di)
{
int negative;
char peek;
long ret;
 
negative = 0;
peek = d_peek_char (di);
if (peek == 'n')
{
negative = 1;
d_advance (di, 1);
peek = d_peek_char (di);
}
 
ret = 0;
while (1)
{
if (! IS_DIGIT (peek))
{
if (negative)
ret = - ret;
return ret;
}
ret = ret * 10 + peek - '0';
d_advance (di, 1);
peek = d_peek_char (di);
}
}
 
/* Like d_number, but returns a demangle_component. */
 
static struct demangle_component *
d_number_component (struct d_info *di)
{
struct demangle_component *ret = d_make_empty (di);
if (ret)
{
ret->type = DEMANGLE_COMPONENT_NUMBER;
ret->u.s_number.number = d_number (di);
}
return ret;
}
 
/* identifier ::= <(unqualified source code identifier)> */
 
static struct demangle_component *
d_identifier (struct d_info *di, int len)
{
const char *name;
 
name = d_str (di);
 
if (di->send - name < len)
return NULL;
 
d_advance (di, len);
 
/* A Java mangled name may have a trailing '$' if it is a C++
keyword. This '$' is not included in the length count. We just
ignore the '$'. */
if ((di->options & DMGL_JAVA) != 0
&& d_peek_char (di) == '$')
d_advance (di, 1);
 
/* Look for something which looks like a gcc encoding of an
anonymous namespace, and replace it with a more user friendly
name. */
if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2
&& memcmp (name, ANONYMOUS_NAMESPACE_PREFIX,
ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0)
{
const char *s;
 
s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN;
if ((*s == '.' || *s == '_' || *s == '$')
&& s[1] == 'N')
{
di->expansion -= len - sizeof "(anonymous namespace)";
return d_make_name (di, "(anonymous namespace)",
sizeof "(anonymous namespace)" - 1);
}
}
 
return d_make_name (di, name, len);
}
 
/* operator_name ::= many different two character encodings.
::= cv <type>
::= v <digit> <source-name>
 
This list is sorted for binary search. */
 
#define NL(s) s, (sizeof s) - 1
 
CP_STATIC_IF_GLIBCPP_V3
const struct demangle_operator_info cplus_demangle_operators[] =
{
{ "aN", NL ("&="), 2 },
{ "aS", NL ("="), 2 },
{ "aa", NL ("&&"), 2 },
{ "ad", NL ("&"), 1 },
{ "an", NL ("&"), 2 },
{ "at", NL ("alignof "), 1 },
{ "az", NL ("alignof "), 1 },
{ "cc", NL ("const_cast"), 2 },
{ "cl", NL ("()"), 2 },
{ "cm", NL (","), 2 },
{ "co", NL ("~"), 1 },
{ "dV", NL ("/="), 2 },
{ "da", NL ("delete[] "), 1 },
{ "dc", NL ("dynamic_cast"), 2 },
{ "de", NL ("*"), 1 },
{ "dl", NL ("delete "), 1 },
{ "ds", NL (".*"), 2 },
{ "dt", NL ("."), 2 },
{ "dv", NL ("/"), 2 },
{ "eO", NL ("^="), 2 },
{ "eo", NL ("^"), 2 },
{ "eq", NL ("=="), 2 },
{ "ge", NL (">="), 2 },
{ "gs", NL ("::"), 1 },
{ "gt", NL (">"), 2 },
{ "ix", NL ("[]"), 2 },
{ "lS", NL ("<<="), 2 },
{ "le", NL ("<="), 2 },
{ "li", NL ("operator\"\" "), 1 },
{ "ls", NL ("<<"), 2 },
{ "lt", NL ("<"), 2 },
{ "mI", NL ("-="), 2 },
{ "mL", NL ("*="), 2 },
{ "mi", NL ("-"), 2 },
{ "ml", NL ("*"), 2 },
{ "mm", NL ("--"), 1 },
{ "na", NL ("new[]"), 3 },
{ "ne", NL ("!="), 2 },
{ "ng", NL ("-"), 1 },
{ "nt", NL ("!"), 1 },
{ "nw", NL ("new"), 3 },
{ "oR", NL ("|="), 2 },
{ "oo", NL ("||"), 2 },
{ "or", NL ("|"), 2 },
{ "pL", NL ("+="), 2 },
{ "pl", NL ("+"), 2 },
{ "pm", NL ("->*"), 2 },
{ "pp", NL ("++"), 1 },
{ "ps", NL ("+"), 1 },
{ "pt", NL ("->"), 2 },
{ "qu", NL ("?"), 3 },
{ "rM", NL ("%="), 2 },
{ "rS", NL (">>="), 2 },
{ "rc", NL ("reinterpret_cast"), 2 },
{ "rm", NL ("%"), 2 },
{ "rs", NL (">>"), 2 },
{ "sc", NL ("static_cast"), 2 },
{ "st", NL ("sizeof "), 1 },
{ "sz", NL ("sizeof "), 1 },
{ "tr", NL ("throw"), 0 },
{ "tw", NL ("throw "), 1 },
{ NULL, NULL, 0, 0 }
};
 
static struct demangle_component *
d_operator_name (struct d_info *di)
{
char c1;
char c2;
 
c1 = d_next_char (di);
c2 = d_next_char (di);
if (c1 == 'v' && IS_DIGIT (c2))
return d_make_extended_operator (di, c2 - '0', d_source_name (di));
else if (c1 == 'c' && c2 == 'v')
return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
cplus_demangle_type (di), NULL);
else
{
/* LOW is the inclusive lower bound. */
int low = 0;
/* HIGH is the exclusive upper bound. We subtract one to ignore
the sentinel at the end of the array. */
int high = ((sizeof (cplus_demangle_operators)
/ sizeof (cplus_demangle_operators[0]))
- 1);
 
while (1)
{
int i;
const struct demangle_operator_info *p;
 
i = low + (high - low) / 2;
p = cplus_demangle_operators + i;
 
if (c1 == p->code[0] && c2 == p->code[1])
return d_make_operator (di, p);
 
if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1]))
high = i;
else
low = i + 1;
if (low == high)
return NULL;
}
}
}
 
static struct demangle_component *
d_make_character (struct d_info *di, int c)
{
struct demangle_component *p;
p = d_make_empty (di);
if (p != NULL)
{
p->type = DEMANGLE_COMPONENT_CHARACTER;
p->u.s_character.character = c;
}
return p;
}
 
static struct demangle_component *
d_java_resource (struct d_info *di)
{
struct demangle_component *p = NULL;
struct demangle_component *next = NULL;
long len, i;
char c;
const char *str;
 
len = d_number (di);
if (len <= 1)
return NULL;
 
/* Eat the leading '_'. */
if (d_next_char (di) != '_')
return NULL;
len--;
 
str = d_str (di);
i = 0;
 
while (len > 0)
{
c = str[i];
if (!c)
return NULL;
 
/* Each chunk is either a '$' escape... */
if (c == '$')
{
i++;
switch (str[i++])
{
case 'S':
c = '/';
break;
case '_':
c = '.';
break;
case '$':
c = '$';
break;
default:
return NULL;
}
next = d_make_character (di, c);
d_advance (di, i);
str = d_str (di);
len -= i;
i = 0;
if (next == NULL)
return NULL;
}
/* ... or a sequence of characters. */
else
{
while (i < len && str[i] && str[i] != '$')
i++;
 
next = d_make_name (di, str, i);
d_advance (di, i);
str = d_str (di);
len -= i;
i = 0;
if (next == NULL)
return NULL;
}
 
if (p == NULL)
p = next;
else
{
p = d_make_comp (di, DEMANGLE_COMPONENT_COMPOUND_NAME, p, next);
if (p == NULL)
return NULL;
}
}
 
p = d_make_comp (di, DEMANGLE_COMPONENT_JAVA_RESOURCE, p, NULL);
 
return p;
}
 
/* <special-name> ::= TV <type>
::= TT <type>
::= TI <type>
::= TS <type>
::= GV <(object) name>
::= T <call-offset> <(base) encoding>
::= Tc <call-offset> <call-offset> <(base) encoding>
Also g++ extensions:
::= TC <type> <(offset) number> _ <(base) type>
::= TF <type>
::= TJ <type>
::= GR <name>
::= GA <encoding>
::= Gr <resource name>
::= GTt <encoding>
::= GTn <encoding>
*/
 
static struct demangle_component *
d_special_name (struct d_info *di)
{
di->expansion += 20;
if (d_check_char (di, 'T'))
{
switch (d_next_char (di))
{
case 'V':
di->expansion -= 5;
return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE,
cplus_demangle_type (di), NULL);
case 'T':
di->expansion -= 10;
return d_make_comp (di, DEMANGLE_COMPONENT_VTT,
cplus_demangle_type (di), NULL);
case 'I':
return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO,
cplus_demangle_type (di), NULL);
case 'S':
return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME,
cplus_demangle_type (di), NULL);
 
case 'h':
if (! d_call_offset (di, 'h'))
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_THUNK,
d_encoding (di, 0), NULL);
 
case 'v':
if (! d_call_offset (di, 'v'))
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK,
d_encoding (di, 0), NULL);
 
case 'c':
if (! d_call_offset (di, '\0'))
return NULL;
if (! d_call_offset (di, '\0'))
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK,
d_encoding (di, 0), NULL);
 
case 'C':
{
struct demangle_component *derived_type;
long offset;
struct demangle_component *base_type;
 
derived_type = cplus_demangle_type (di);
offset = d_number (di);
if (offset < 0)
return NULL;
if (! d_check_char (di, '_'))
return NULL;
base_type = cplus_demangle_type (di);
/* We don't display the offset. FIXME: We should display
it in verbose mode. */
di->expansion += 5;
return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE,
base_type, derived_type);
}
 
case 'F':
return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN,
cplus_demangle_type (di), NULL);
case 'J':
return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
cplus_demangle_type (di), NULL);
 
case 'H':
return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT,
d_name (di), NULL);
 
case 'W':
return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
d_name (di), NULL);
 
default:
return NULL;
}
}
else if (d_check_char (di, 'G'))
{
switch (d_next_char (di))
{
case 'V':
return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL);
 
case 'R':
{
struct demangle_component *name = d_name (di);
return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name,
d_number_component (di));
}
 
case 'A':
return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS,
d_encoding (di, 0), NULL);
 
case 'T':
switch (d_next_char (di))
{
case 'n':
return d_make_comp (di, DEMANGLE_COMPONENT_NONTRANSACTION_CLONE,
d_encoding (di, 0), NULL);
default:
/* ??? The proposal is that other letters (such as 'h') stand
for different variants of transaction cloning, such as
compiling directly for hardware transaction support. But
they still should all be transactional clones of some sort
so go ahead and call them that. */
case 't':
return d_make_comp (di, DEMANGLE_COMPONENT_TRANSACTION_CLONE,
d_encoding (di, 0), NULL);
}
 
case 'r':
return d_java_resource (di);
 
default:
return NULL;
}
}
else
return NULL;
}
 
/* <call-offset> ::= h <nv-offset> _
::= v <v-offset> _
 
<nv-offset> ::= <(offset) number>
 
<v-offset> ::= <(offset) number> _ <(virtual offset) number>
 
The C parameter, if not '\0', is a character we just read which is
the start of the <call-offset>.
 
We don't display the offset information anywhere. FIXME: We should
display it in verbose mode. */
 
static int
d_call_offset (struct d_info *di, int c)
{
if (c == '\0')
c = d_next_char (di);
 
if (c == 'h')
d_number (di);
else if (c == 'v')
{
d_number (di);
if (! d_check_char (di, '_'))
return 0;
d_number (di);
}
else
return 0;
 
if (! d_check_char (di, '_'))
return 0;
 
return 1;
}
 
/* <ctor-dtor-name> ::= C1
::= C2
::= C3
::= D0
::= D1
::= D2
*/
 
static struct demangle_component *
d_ctor_dtor_name (struct d_info *di)
{
if (di->last_name != NULL)
{
if (di->last_name->type == DEMANGLE_COMPONENT_NAME)
di->expansion += di->last_name->u.s_name.len;
else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
di->expansion += di->last_name->u.s_string.len;
}
switch (d_peek_char (di))
{
case 'C':
{
enum gnu_v3_ctor_kinds kind;
 
switch (d_peek_next_char (di))
{
case '1':
kind = gnu_v3_complete_object_ctor;
break;
case '2':
kind = gnu_v3_base_object_ctor;
break;
case '3':
kind = gnu_v3_complete_object_allocating_ctor;
break;
case '5':
kind = gnu_v3_object_ctor_group;
break;
default:
return NULL;
}
d_advance (di, 2);
return d_make_ctor (di, kind, di->last_name);
}
 
case 'D':
{
enum gnu_v3_dtor_kinds kind;
 
switch (d_peek_next_char (di))
{
case '0':
kind = gnu_v3_deleting_dtor;
break;
case '1':
kind = gnu_v3_complete_object_dtor;
break;
case '2':
kind = gnu_v3_base_object_dtor;
break;
case '5':
kind = gnu_v3_object_dtor_group;
break;
default:
return NULL;
}
d_advance (di, 2);
return d_make_dtor (di, kind, di->last_name);
}
 
default:
return NULL;
}
}
 
/* <type> ::= <builtin-type>
::= <function-type>
::= <class-enum-type>
::= <array-type>
::= <pointer-to-member-type>
::= <template-param>
::= <template-template-param> <template-args>
::= <substitution>
::= <CV-qualifiers> <type>
::= P <type>
::= R <type>
::= O <type> (C++0x)
::= C <type>
::= G <type>
::= U <source-name> <type>
 
<builtin-type> ::= various one letter codes
::= u <source-name>
*/
 
CP_STATIC_IF_GLIBCPP_V3
const struct demangle_builtin_type_info
cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
{
/* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_DEFAULT },
/* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL },
/* c */ { NL ("char"), NL ("byte"), D_PRINT_DEFAULT },
/* d */ { NL ("double"), NL ("double"), D_PRINT_FLOAT },
/* e */ { NL ("long double"), NL ("long double"), D_PRINT_FLOAT },
/* f */ { NL ("float"), NL ("float"), D_PRINT_FLOAT },
/* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_FLOAT },
/* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_DEFAULT },
/* i */ { NL ("int"), NL ("int"), D_PRINT_INT },
/* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_UNSIGNED },
/* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* l */ { NL ("long"), NL ("long"), D_PRINT_LONG },
/* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_UNSIGNED_LONG },
/* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT },
/* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"),
D_PRINT_DEFAULT },
/* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* s */ { NL ("short"), NL ("short"), D_PRINT_DEFAULT },
/* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT },
/* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* v */ { NL ("void"), NL ("void"), D_PRINT_VOID },
/* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_DEFAULT },
/* x */ { NL ("long long"), NL ("long"), D_PRINT_LONG_LONG },
/* y */ { NL ("unsigned long long"), NL ("unsigned long long"),
D_PRINT_UNSIGNED_LONG_LONG },
/* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT },
/* 26 */ { NL ("decimal32"), NL ("decimal32"), D_PRINT_DEFAULT },
/* 27 */ { NL ("decimal64"), NL ("decimal64"), D_PRINT_DEFAULT },
/* 28 */ { NL ("decimal128"), NL ("decimal128"), D_PRINT_DEFAULT },
/* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT },
/* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT },
/* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT },
/* 32 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
D_PRINT_DEFAULT },
};
 
CP_STATIC_IF_GLIBCPP_V3
struct demangle_component *
cplus_demangle_type (struct d_info *di)
{
char peek;
struct demangle_component *ret;
int can_subst;
 
/* The ABI specifies that when CV-qualifiers are used, the base type
is substitutable, and the fully qualified type is substitutable,
but the base type with a strict subset of the CV-qualifiers is
not substitutable. The natural recursive implementation of the
CV-qualifiers would cause subsets to be substitutable, so instead
we pull them all off now.
 
FIXME: The ABI says that order-insensitive vendor qualifiers
should be handled in the same way, but we have no way to tell
which vendor qualifiers are order-insensitive and which are
order-sensitive. So we just assume that they are all
order-sensitive. g++ 3.4 supports only one vendor qualifier,
__vector, and it treats it as order-sensitive when mangling
names. */
 
peek = d_peek_char (di);
if (peek == 'r' || peek == 'V' || peek == 'K')
{
struct demangle_component **pret;
 
pret = d_cv_qualifiers (di, &ret, 0);
if (pret == NULL)
return NULL;
*pret = cplus_demangle_type (di);
if (! *pret)
return NULL;
if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|| (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
{
/* Move the ref-qualifier outside the cv-qualifiers so that
they are printed in the right order. */
struct demangle_component *fn = d_left (*pret);
d_left (*pret) = ret;
ret = *pret;
*pret = fn;
}
if (! d_add_substitution (di, ret))
return NULL;
return ret;
}
 
can_subst = 1;
 
switch (peek)
{
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
case 'h': case 'i': case 'j': case 'l': case 'm': case 'n':
case 'o': case 's': case 't':
case 'v': case 'w': case 'x': case 'y': case 'z':
ret = d_make_builtin_type (di,
&cplus_demangle_builtin_types[peek - 'a']);
di->expansion += ret->u.s_builtin.type->len;
can_subst = 0;
d_advance (di, 1);
break;
 
case 'u':
d_advance (di, 1);
ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE,
d_source_name (di), NULL);
break;
 
case 'F':
ret = d_function_type (di);
break;
 
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'N':
case 'Z':
ret = d_class_enum_type (di);
break;
 
case 'A':
ret = d_array_type (di);
break;
 
case 'M':
ret = d_pointer_to_member_type (di);
break;
 
case 'T':
ret = d_template_param (di);
if (d_peek_char (di) == 'I')
{
/* This is <template-template-param> <template-args>. The
<template-template-param> part is a substitution
candidate. */
if (! d_add_substitution (di, ret))
return NULL;
ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
d_template_args (di));
}
break;
 
case 'S':
/* If this is a special substitution, then it is the start of
<class-enum-type>. */
{
char peek_next;
 
peek_next = d_peek_next_char (di);
if (IS_DIGIT (peek_next)
|| peek_next == '_'
|| IS_UPPER (peek_next))
{
ret = d_substitution (di, 0);
/* The substituted name may have been a template name and
may be followed by tepmlate args. */
if (d_peek_char (di) == 'I')
ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
d_template_args (di));
else
can_subst = 0;
}
else
{
ret = d_class_enum_type (di);
/* If the substitution was a complete type, then it is not
a new substitution candidate. However, if the
substitution was followed by template arguments, then
the whole thing is a substitution candidate. */
if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD)
can_subst = 0;
}
}
break;
 
case 'O':
d_advance (di, 1);
ret = d_make_comp (di, DEMANGLE_COMPONENT_RVALUE_REFERENCE,
cplus_demangle_type (di), NULL);
break;
 
case 'P':
d_advance (di, 1);
ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER,
cplus_demangle_type (di), NULL);
break;
 
case 'R':
d_advance (di, 1);
ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE,
cplus_demangle_type (di), NULL);
break;
 
case 'C':
d_advance (di, 1);
ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX,
cplus_demangle_type (di), NULL);
break;
 
case 'G':
d_advance (di, 1);
ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY,
cplus_demangle_type (di), NULL);
break;
 
case 'U':
d_advance (di, 1);
ret = d_source_name (di);
ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
cplus_demangle_type (di), ret);
break;
 
case 'D':
can_subst = 0;
d_advance (di, 1);
peek = d_next_char (di);
switch (peek)
{
case 'T':
case 't':
/* decltype (expression) */
ret = d_make_comp (di, DEMANGLE_COMPONENT_DECLTYPE,
d_expression (di), NULL);
if (ret && d_next_char (di) != 'E')
ret = NULL;
can_subst = 1;
break;
case 'p':
/* Pack expansion. */
ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
cplus_demangle_type (di), NULL);
can_subst = 1;
break;
 
case 'a':
/* auto */
ret = d_make_name (di, "auto", 4);
break;
case 'f':
/* 32-bit decimal floating point */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 'd':
/* 64-bit DFP */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[27]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 'e':
/* 128-bit DFP */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[28]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 'h':
/* 16-bit half-precision FP */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[29]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 's':
/* char16_t */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 'i':
/* char32_t */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]);
di->expansion += ret->u.s_builtin.type->len;
break;
 
case 'F':
/* Fixed point types. DF<int bits><length><fract bits><sat> */
ret = d_make_empty (di);
ret->type = DEMANGLE_COMPONENT_FIXED_TYPE;
if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di))))
/* For demangling we don't care about the bits. */
d_number (di);
ret->u.s_fixed.length = cplus_demangle_type (di);
if (ret->u.s_fixed.length == NULL)
return NULL;
d_number (di);
peek = d_next_char (di);
ret->u.s_fixed.sat = (peek == 's');
break;
 
case 'v':
ret = d_vector_type (di);
can_subst = 1;
break;
 
case 'n':
/* decltype(nullptr) */
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]);
di->expansion += ret->u.s_builtin.type->len;
break;
 
default:
return NULL;
}
break;
 
default:
return NULL;
}
 
if (can_subst)
{
if (! d_add_substitution (di, ret))
return NULL;
}
 
return ret;
}
 
/* <CV-qualifiers> ::= [r] [V] [K] */
 
static struct demangle_component **
d_cv_qualifiers (struct d_info *di,
struct demangle_component **pret, int member_fn)
{
struct demangle_component **pstart;
char peek;
 
pstart = pret;
peek = d_peek_char (di);
while (peek == 'r' || peek == 'V' || peek == 'K')
{
enum demangle_component_type t;
 
d_advance (di, 1);
if (peek == 'r')
{
t = (member_fn
? DEMANGLE_COMPONENT_RESTRICT_THIS
: DEMANGLE_COMPONENT_RESTRICT);
di->expansion += sizeof "restrict";
}
else if (peek == 'V')
{
t = (member_fn
? DEMANGLE_COMPONENT_VOLATILE_THIS
: DEMANGLE_COMPONENT_VOLATILE);
di->expansion += sizeof "volatile";
}
else
{
t = (member_fn
? DEMANGLE_COMPONENT_CONST_THIS
: DEMANGLE_COMPONENT_CONST);
di->expansion += sizeof "const";
}
 
*pret = d_make_comp (di, t, NULL, NULL);
if (*pret == NULL)
return NULL;
pret = &d_left (*pret);
 
peek = d_peek_char (di);
}
 
if (!member_fn && peek == 'F')
{
while (pstart != pret)
{
switch ((*pstart)->type)
{
case DEMANGLE_COMPONENT_RESTRICT:
(*pstart)->type = DEMANGLE_COMPONENT_RESTRICT_THIS;
break;
case DEMANGLE_COMPONENT_VOLATILE:
(*pstart)->type = DEMANGLE_COMPONENT_VOLATILE_THIS;
break;
case DEMANGLE_COMPONENT_CONST:
(*pstart)->type = DEMANGLE_COMPONENT_CONST_THIS;
break;
default:
break;
}
pstart = &d_left (*pstart);
}
}
 
return pret;
}
 
/* <ref-qualifier> ::= R
::= O */
 
static struct demangle_component *
d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
{
struct demangle_component *ret = sub;
char peek;
 
peek = d_peek_char (di);
if (peek == 'R' || peek == 'O')
{
enum demangle_component_type t;
if (peek == 'R')
{
t = DEMANGLE_COMPONENT_REFERENCE_THIS;
di->expansion += sizeof "&";
}
else
{
t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS;
di->expansion += sizeof "&&";
}
d_advance (di, 1);
 
ret = d_make_comp (di, t, ret, NULL);
}
 
return ret;
}
 
/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E */
 
static struct demangle_component *
d_function_type (struct d_info *di)
{
struct demangle_component *ret;
 
if (! d_check_char (di, 'F'))
return NULL;
if (d_peek_char (di) == 'Y')
{
/* Function has C linkage. We don't print this information.
FIXME: We should print it in verbose mode. */
d_advance (di, 1);
}
ret = d_bare_function_type (di, 1);
ret = d_ref_qualifier (di, ret);
 
if (! d_check_char (di, 'E'))
return NULL;
return ret;
}
 
/* <type>+ */
 
static struct demangle_component *
d_parmlist (struct d_info *di)
{
struct demangle_component *tl;
struct demangle_component **ptl;
 
tl = NULL;
ptl = &tl;
while (1)
{
struct demangle_component *type;
 
char peek = d_peek_char (di);
if (peek == '\0' || peek == 'E' || peek == '.')
break;
if ((peek == 'R' || peek == 'O')
&& d_peek_next_char (di) == 'E')
/* Function ref-qualifier, not a ref prefix for a parameter type. */
break;
type = cplus_demangle_type (di);
if (type == NULL)
return NULL;
*ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
if (*ptl == NULL)
return NULL;
ptl = &d_right (*ptl);
}
 
/* There should be at least one parameter type besides the optional
return type. A function which takes no arguments will have a
single parameter type void. */
if (tl == NULL)
return NULL;
 
/* If we have a single parameter type void, omit it. */
if (d_right (tl) == NULL
&& d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
&& d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
{
di->expansion -= d_left (tl)->u.s_builtin.type->len;
d_left (tl) = NULL;
}
 
return tl;
}
 
/* <bare-function-type> ::= [J]<type>+ */
 
static struct demangle_component *
d_bare_function_type (struct d_info *di, int has_return_type)
{
struct demangle_component *return_type;
struct demangle_component *tl;
char peek;
 
/* Detect special qualifier indicating that the first argument
is the return type. */
peek = d_peek_char (di);
if (peek == 'J')
{
d_advance (di, 1);
has_return_type = 1;
}
 
if (has_return_type)
{
return_type = cplus_demangle_type (di);
if (return_type == NULL)
return NULL;
}
else
return_type = NULL;
 
tl = d_parmlist (di);
if (tl == NULL)
return NULL;
 
return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE,
return_type, tl);
}
 
/* <class-enum-type> ::= <name> */
 
static struct demangle_component *
d_class_enum_type (struct d_info *di)
{
return d_name (di);
}
 
/* <array-type> ::= A <(positive dimension) number> _ <(element) type>
::= A [<(dimension) expression>] _ <(element) type>
*/
 
static struct demangle_component *
d_array_type (struct d_info *di)
{
char peek;
struct demangle_component *dim;
 
if (! d_check_char (di, 'A'))
return NULL;
 
peek = d_peek_char (di);
if (peek == '_')
dim = NULL;
else if (IS_DIGIT (peek))
{
const char *s;
 
s = d_str (di);
do
{
d_advance (di, 1);
peek = d_peek_char (di);
}
while (IS_DIGIT (peek));
dim = d_make_name (di, s, d_str (di) - s);
if (dim == NULL)
return NULL;
}
else
{
dim = d_expression (di);
if (dim == NULL)
return NULL;
}
 
if (! d_check_char (di, '_'))
return NULL;
 
return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
cplus_demangle_type (di));
}
 
/* <vector-type> ::= Dv <number> _ <type>
::= Dv _ <expression> _ <type> */
 
static struct demangle_component *
d_vector_type (struct d_info *di)
{
char peek;
struct demangle_component *dim;
 
peek = d_peek_char (di);
if (peek == '_')
{
d_advance (di, 1);
dim = d_expression (di);
}
else
dim = d_number_component (di);
 
if (dim == NULL)
return NULL;
 
if (! d_check_char (di, '_'))
return NULL;
 
return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim,
cplus_demangle_type (di));
}
 
/* <pointer-to-member-type> ::= M <(class) type> <(member) type> */
 
static struct demangle_component *
d_pointer_to_member_type (struct d_info *di)
{
struct demangle_component *cl;
struct demangle_component *mem;
struct demangle_component **pmem;
 
if (! d_check_char (di, 'M'))
return NULL;
 
cl = cplus_demangle_type (di);
 
/* The ABI specifies that any type can be a substitution source, and
that M is followed by two types, and that when a CV-qualified
type is seen both the base type and the CV-qualified types are
substitution sources. The ABI also specifies that for a pointer
to a CV-qualified member function, the qualifiers are attached to
the second type. Given the grammar, a plain reading of the ABI
suggests that both the CV-qualified member function and the
non-qualified member function are substitution sources. However,
g++ does not work that way. g++ treats only the CV-qualified
member function as a substitution source. FIXME. So to work
with g++, we need to pull off the CV-qualifiers here, in order to
avoid calling add_substitution() in cplus_demangle_type(). But
for a CV-qualified member which is not a function, g++ does
follow the ABI, so we need to handle that case here by calling
d_add_substitution ourselves. */
 
pmem = d_cv_qualifiers (di, &mem, 1);
if (pmem == NULL)
return NULL;
*pmem = cplus_demangle_type (di);
if (*pmem == NULL)
return NULL;
 
if (pmem != &mem
&& ((*pmem)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|| (*pmem)->type == DEMANGLE_COMPONENT_REFERENCE_THIS))
{
/* Move the ref-qualifier outside the cv-qualifiers so that
they are printed in the right order. */
struct demangle_component *fn = d_left (*pmem);
d_left (*pmem) = mem;
mem = *pmem;
*pmem = fn;
}
 
if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
{
if (! d_add_substitution (di, mem))
return NULL;
}
 
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
}
 
/* <non-negative number> _ */
 
static long
d_compact_number (struct d_info *di)
{
long num;
if (d_peek_char (di) == '_')
num = 0;
else if (d_peek_char (di) == 'n')
return -1;
else
num = d_number (di) + 1;
 
if (! d_check_char (di, '_'))
return -1;
return num;
}
 
/* <template-param> ::= T_
::= T <(parameter-2 non-negative) number> _
*/
 
static struct demangle_component *
d_template_param (struct d_info *di)
{
long param;
 
if (! d_check_char (di, 'T'))
return NULL;
 
param = d_compact_number (di);
if (param < 0)
return NULL;
 
++di->did_subs;
 
return d_make_template_param (di, param);
}
 
/* <template-args> ::= I <template-arg>+ E */
 
static struct demangle_component *
d_template_args (struct d_info *di)
{
struct demangle_component *hold_last_name;
struct demangle_component *al;
struct demangle_component **pal;
 
/* Preserve the last name we saw--don't let the template arguments
clobber it, as that would give us the wrong name for a subsequent
constructor or destructor. */
hold_last_name = di->last_name;
 
if (d_peek_char (di) != 'I'
&& d_peek_char (di) != 'J')
return NULL;
d_advance (di, 1);
 
if (d_peek_char (di) == 'E')
{
/* An argument pack can be empty. */
d_advance (di, 1);
return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, NULL, NULL);
}
 
al = NULL;
pal = &al;
while (1)
{
struct demangle_component *a;
 
a = d_template_arg (di);
if (a == NULL)
return NULL;
 
*pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL);
if (*pal == NULL)
return NULL;
pal = &d_right (*pal);
 
if (d_peek_char (di) == 'E')
{
d_advance (di, 1);
break;
}
}
 
di->last_name = hold_last_name;
 
return al;
}
 
/* <template-arg> ::= <type>
::= X <expression> E
::= <expr-primary>
*/
 
static struct demangle_component *
d_template_arg (struct d_info *di)
{
struct demangle_component *ret;
 
switch (d_peek_char (di))
{
case 'X':
d_advance (di, 1);
ret = d_expression (di);
if (! d_check_char (di, 'E'))
return NULL;
return ret;
 
case 'L':
return d_expr_primary (di);
 
case 'I':
case 'J':
/* An argument pack. */
return d_template_args (di);
 
default:
return cplus_demangle_type (di);
}
}
 
/* Parse a sequence of expressions until we hit the terminator
character. */
 
static struct demangle_component *
d_exprlist (struct d_info *di, char terminator)
{
struct demangle_component *list = NULL;
struct demangle_component **p = &list;
 
if (d_peek_char (di) == terminator)
{
d_advance (di, 1);
return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL);
}
 
while (1)
{
struct demangle_component *arg = d_expression (di);
if (arg == NULL)
return NULL;
 
*p = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, arg, NULL);
if (*p == NULL)
return NULL;
p = &d_right (*p);
 
if (d_peek_char (di) == terminator)
{
d_advance (di, 1);
break;
}
}
 
return list;
}
 
/* Returns nonzero iff OP is an operator for a C++ cast: const_cast,
dynamic_cast, static_cast or reinterpret_cast. */
 
static int
op_is_new_cast (struct demangle_component *op)
{
const char *code = op->u.s_operator.op->code;
return (code[1] == 'c'
&& (code[0] == 's' || code[0] == 'd'
|| code[0] == 'c' || code[0] == 'r'));
}
 
/* <expression> ::= <(unary) operator-name> <expression>
::= <(binary) operator-name> <expression> <expression>
::= <(trinary) operator-name> <expression> <expression> <expression>
::= cl <expression>+ E
::= st <type>
::= <template-param>
::= sr <type> <unqualified-name>
::= sr <type> <unqualified-name> <template-args>
::= <expr-primary>
*/
 
static struct demangle_component *
d_expression (struct d_info *di)
{
char peek;
 
peek = d_peek_char (di);
if (peek == 'L')
return d_expr_primary (di);
else if (peek == 'T')
return d_template_param (di);
else if (peek == 's' && d_peek_next_char (di) == 'r')
{
struct demangle_component *type;
struct demangle_component *name;
 
d_advance (di, 2);
type = cplus_demangle_type (di);
name = d_unqualified_name (di);
if (d_peek_char (di) != 'I')
return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
else
return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type,
d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
d_template_args (di)));
}
else if (peek == 's' && d_peek_next_char (di) == 'p')
{
d_advance (di, 2);
return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
d_expression (di), NULL);
}
else if (peek == 'f' && d_peek_next_char (di) == 'p')
{
/* Function parameter used in a late-specified return type. */
int index;
d_advance (di, 2);
if (d_peek_char (di) == 'T')
{
/* 'this' parameter. */
d_advance (di, 1);
index = 0;
}
else
{
index = d_compact_number (di) + 1;
if (index == 0)
return NULL;
}
return d_make_function_param (di, index);
}
else if (IS_DIGIT (peek)
|| (peek == 'o' && d_peek_next_char (di) == 'n'))
{
/* We can get an unqualified name as an expression in the case of
a dependent function call, i.e. decltype(f(t)). */
struct demangle_component *name;
 
if (peek == 'o')
/* operator-function-id, i.e. operator+(t). */
d_advance (di, 2);
 
name = d_unqualified_name (di);
if (name == NULL)
return NULL;
if (d_peek_char (di) == 'I')
return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
d_template_args (di));
else
return name;
}
else if ((peek == 'i' || peek == 't')
&& d_peek_next_char (di) == 'l')
{
/* Brace-enclosed initializer list, untyped or typed. */
struct demangle_component *type = NULL;
if (peek == 't')
type = cplus_demangle_type (di);
d_advance (di, 2);
return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
type, d_exprlist (di, 'E'));
}
else
{
struct demangle_component *op;
const char *code = NULL;
int args;
 
op = d_operator_name (di);
if (op == NULL)
return NULL;
 
if (op->type == DEMANGLE_COMPONENT_OPERATOR)
{
code = op->u.s_operator.op->code;
di->expansion += op->u.s_operator.op->len - 2;
if (strcmp (code, "st") == 0)
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
cplus_demangle_type (di));
}
 
switch (op->type)
{
default:
return NULL;
case DEMANGLE_COMPONENT_OPERATOR:
args = op->u.s_operator.op->args;
break;
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
args = op->u.s_extended_operator.args;
break;
case DEMANGLE_COMPONENT_CAST:
args = 1;
break;
}
 
switch (args)
{
case 0:
return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL);
 
case 1:
{
struct demangle_component *operand;
int suffix = 0;
 
if (code && (code[0] == 'p' || code[0] == 'm')
&& code[1] == code[0])
/* pp_ and mm_ are the prefix variants. */
suffix = !d_check_char (di, '_');
 
if (op->type == DEMANGLE_COMPONENT_CAST
&& d_check_char (di, '_'))
operand = d_exprlist (di, 'E');
else
operand = d_expression (di);
 
if (suffix)
/* Indicate the suffix variant for d_print_comp. */
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
d_make_comp (di,
DEMANGLE_COMPONENT_BINARY_ARGS,
operand, operand));
else
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
operand);
}
case 2:
{
struct demangle_component *left;
struct demangle_component *right;
 
if (op_is_new_cast (op))
left = cplus_demangle_type (di);
else
left = d_expression (di);
if (!strcmp (code, "cl"))
right = d_exprlist (di, 'E');
else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
{
right = d_unqualified_name (di);
if (d_peek_char (di) == 'I')
right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE,
right, d_template_args (di));
}
else
right = d_expression (di);
 
return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
d_make_comp (di,
DEMANGLE_COMPONENT_BINARY_ARGS,
left, right));
}
case 3:
{
struct demangle_component *first;
struct demangle_component *second;
struct demangle_component *third;
 
if (!strcmp (code, "qu"))
{
/* ?: expression. */
first = d_expression (di);
second = d_expression (di);
third = d_expression (di);
}
else if (code[0] == 'n')
{
/* new-expression. */
if (code[1] != 'w' && code[1] != 'a')
return NULL;
first = d_exprlist (di, '_');
second = cplus_demangle_type (di);
if (d_peek_char (di) == 'E')
{
d_advance (di, 1);
third = NULL;
}
else if (d_peek_char (di) == 'p'
&& d_peek_next_char (di) == 'i')
{
/* Parenthesized initializer. */
d_advance (di, 2);
third = d_exprlist (di, 'E');
}
else if (d_peek_char (di) == 'i'
&& d_peek_next_char (di) == 'l')
/* initializer-list. */
third = d_expression (di);
else
return NULL;
}
else
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
d_make_comp (di,
DEMANGLE_COMPONENT_TRINARY_ARG1,
first,
d_make_comp (di,
DEMANGLE_COMPONENT_TRINARY_ARG2,
second, third)));
}
default:
return NULL;
}
}
}
 
/* <expr-primary> ::= L <type> <(value) number> E
::= L <type> <(value) float> E
::= L <mangled-name> E
*/
 
static struct demangle_component *
d_expr_primary (struct d_info *di)
{
struct demangle_component *ret;
 
if (! d_check_char (di, 'L'))
return NULL;
if (d_peek_char (di) == '_'
/* Workaround for G++ bug; see comment in write_template_arg. */
|| d_peek_char (di) == 'Z')
ret = cplus_demangle_mangled_name (di, 0);
else
{
struct demangle_component *type;
enum demangle_component_type t;
const char *s;
 
type = cplus_demangle_type (di);
if (type == NULL)
return NULL;
 
/* If we have a type we know how to print, we aren't going to
print the type name itself. */
if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
&& type->u.s_builtin.type->print != D_PRINT_DEFAULT)
di->expansion -= type->u.s_builtin.type->len;
 
/* Rather than try to interpret the literal value, we just
collect it as a string. Note that it's possible to have a
floating point literal here. The ABI specifies that the
format of such literals is machine independent. That's fine,
but what's not fine is that versions of g++ up to 3.2 with
-fabi-version=1 used upper case letters in the hex constant,
and dumped out gcc's internal representation. That makes it
hard to tell where the constant ends, and hard to dump the
constant in any readable form anyhow. We don't attempt to
handle these cases. */
 
t = DEMANGLE_COMPONENT_LITERAL;
if (d_peek_char (di) == 'n')
{
t = DEMANGLE_COMPONENT_LITERAL_NEG;
d_advance (di, 1);
}
s = d_str (di);
while (d_peek_char (di) != 'E')
{
if (d_peek_char (di) == '\0')
return NULL;
d_advance (di, 1);
}
ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
}
if (! d_check_char (di, 'E'))
return NULL;
return ret;
}
 
/* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
::= Z <(function) encoding> E s [<discriminator>]
::= Z <(function) encoding> E d [<parameter> number>] _ <entity name>
*/
 
static struct demangle_component *
d_local_name (struct d_info *di)
{
struct demangle_component *function;
 
if (! d_check_char (di, 'Z'))
return NULL;
 
function = d_encoding (di, 0);
 
if (! d_check_char (di, 'E'))
return NULL;
 
if (d_peek_char (di) == 's')
{
d_advance (di, 1);
if (! d_discriminator (di))
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function,
d_make_name (di, "string literal",
sizeof "string literal" - 1));
}
else
{
struct demangle_component *name;
int num = -1;
 
if (d_peek_char (di) == 'd')
{
/* Default argument scope: d <number> _. */
d_advance (di, 1);
num = d_compact_number (di);
if (num < 0)
return NULL;
}
 
name = d_name (di);
if (name)
switch (name->type)
{
/* Lambdas and unnamed types have internal discriminators. */
case DEMANGLE_COMPONENT_LAMBDA:
case DEMANGLE_COMPONENT_UNNAMED_TYPE:
break;
default:
if (! d_discriminator (di))
return NULL;
}
if (num >= 0)
name = d_make_default_arg (di, num, name);
return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name);
}
}
 
/* <discriminator> ::= _ <(non-negative) number>
 
We demangle the discriminator, but we don't print it out. FIXME:
We should print it out in verbose mode. */
 
static int
d_discriminator (struct d_info *di)
{
long discrim;
 
if (d_peek_char (di) != '_')
return 1;
d_advance (di, 1);
discrim = d_number (di);
if (discrim < 0)
return 0;
return 1;
}
 
/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ */
 
static struct demangle_component *
d_lambda (struct d_info *di)
{
struct demangle_component *tl;
struct demangle_component *ret;
int num;
 
if (! d_check_char (di, 'U'))
return NULL;
if (! d_check_char (di, 'l'))
return NULL;
 
tl = d_parmlist (di);
if (tl == NULL)
return NULL;
 
if (! d_check_char (di, 'E'))
return NULL;
 
num = d_compact_number (di);
if (num < 0)
return NULL;
 
ret = d_make_empty (di);
if (ret)
{
ret->type = DEMANGLE_COMPONENT_LAMBDA;
ret->u.s_unary_num.sub = tl;
ret->u.s_unary_num.num = num;
}
 
if (! d_add_substitution (di, ret))
return NULL;
 
return ret;
}
 
/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
 
static struct demangle_component *
d_unnamed_type (struct d_info *di)
{
struct demangle_component *ret;
long num;
 
if (! d_check_char (di, 'U'))
return NULL;
if (! d_check_char (di, 't'))
return NULL;
 
num = d_compact_number (di);
if (num < 0)
return NULL;
 
ret = d_make_empty (di);
if (ret)
{
ret->type = DEMANGLE_COMPONENT_UNNAMED_TYPE;
ret->u.s_number.number = num;
}
 
if (! d_add_substitution (di, ret))
return NULL;
 
return ret;
}
 
/* <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]*
*/
 
static struct demangle_component *
d_clone_suffix (struct d_info *di, struct demangle_component *encoding)
{
const char *suffix = d_str (di);
const char *pend = suffix;
struct demangle_component *n;
 
if (*pend == '.' && (IS_LOWER (pend[1]) || pend[1] == '_'))
{
pend += 2;
while (IS_LOWER (*pend) || *pend == '_')
++pend;
}
while (*pend == '.' && IS_DIGIT (pend[1]))
{
pend += 2;
while (IS_DIGIT (*pend))
++pend;
}
d_advance (di, pend - suffix);
n = d_make_name (di, suffix, pend - suffix);
return d_make_comp (di, DEMANGLE_COMPONENT_CLONE, encoding, n);
}
 
/* Add a new substitution. */
 
static int
d_add_substitution (struct d_info *di, struct demangle_component *dc)
{
if (dc == NULL)
return 0;
if (di->next_sub >= di->num_subs)
return 0;
di->subs[di->next_sub] = dc;
++di->next_sub;
return 1;
}
 
/* <substitution> ::= S <seq-id> _
::= S_
::= St
::= Sa
::= Sb
::= Ss
::= Si
::= So
::= Sd
 
If PREFIX is non-zero, then this type is being used as a prefix in
a qualified name. In this case, for the standard substitutions, we
need to check whether we are being used as a prefix for a
constructor or destructor, and return a full template name.
Otherwise we will get something like std::iostream::~iostream()
which does not correspond particularly well to any function which
actually appears in the source.
*/
 
static const struct d_standard_sub_info standard_subs[] =
{
{ 't', NL ("std"),
NL ("std"),
NULL, 0 },
{ 'a', NL ("std::allocator"),
NL ("std::allocator"),
NL ("allocator") },
{ 'b', NL ("std::basic_string"),
NL ("std::basic_string"),
NL ("basic_string") },
{ 's', NL ("std::string"),
NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
NL ("basic_string") },
{ 'i', NL ("std::istream"),
NL ("std::basic_istream<char, std::char_traits<char> >"),
NL ("basic_istream") },
{ 'o', NL ("std::ostream"),
NL ("std::basic_ostream<char, std::char_traits<char> >"),
NL ("basic_ostream") },
{ 'd', NL ("std::iostream"),
NL ("std::basic_iostream<char, std::char_traits<char> >"),
NL ("basic_iostream") }
};
 
static struct demangle_component *
d_substitution (struct d_info *di, int prefix)
{
char c;
 
if (! d_check_char (di, 'S'))
return NULL;
 
c = d_next_char (di);
if (c == '_' || IS_DIGIT (c) || IS_UPPER (c))
{
unsigned int id;
 
id = 0;
if (c != '_')
{
do
{
unsigned int new_id;
 
if (IS_DIGIT (c))
new_id = id * 36 + c - '0';
else if (IS_UPPER (c))
new_id = id * 36 + c - 'A' + 10;
else
return NULL;
if (new_id < id)
return NULL;
id = new_id;
c = d_next_char (di);
}
while (c != '_');
 
++id;
}
 
if (id >= (unsigned int) di->next_sub)
return NULL;
 
++di->did_subs;
 
return di->subs[id];
}
else
{
int verbose;
const struct d_standard_sub_info *p;
const struct d_standard_sub_info *pend;
 
verbose = (di->options & DMGL_VERBOSE) != 0;
if (! verbose && prefix)
{
char peek;
 
peek = d_peek_char (di);
if (peek == 'C' || peek == 'D')
verbose = 1;
}
 
pend = (&standard_subs[0]
+ sizeof standard_subs / sizeof standard_subs[0]);
for (p = &standard_subs[0]; p < pend; ++p)
{
if (c == p->code)
{
const char *s;
int len;
 
if (p->set_last_name != NULL)
di->last_name = d_make_sub (di, p->set_last_name,
p->set_last_name_len);
if (verbose)
{
s = p->full_expansion;
len = p->full_len;
}
else
{
s = p->simple_expansion;
len = p->simple_len;
}
di->expansion += len;
return d_make_sub (di, s, len);
}
}
 
return NULL;
}
}
 
/* Initialize a growable string. */
 
static void
d_growable_string_init (struct d_growable_string *dgs, size_t estimate)
{
dgs->buf = NULL;
dgs->len = 0;
dgs->alc = 0;
dgs->allocation_failure = 0;
 
if (estimate > 0)
d_growable_string_resize (dgs, estimate);
}
 
/* Grow a growable string to a given size. */
 
static inline void
d_growable_string_resize (struct d_growable_string *dgs, size_t need)
{
size_t newalc;
char *newbuf;
 
if (dgs->allocation_failure)
return;
 
/* Start allocation at two bytes to avoid any possibility of confusion
with the special value of 1 used as a return in *palc to indicate
allocation failures. */
newalc = dgs->alc > 0 ? dgs->alc : 2;
while (newalc < need)
newalc <<= 1;
 
newbuf = (char *) realloc (dgs->buf, newalc);
if (newbuf == NULL)
{
free (dgs->buf);
dgs->buf = NULL;
dgs->len = 0;
dgs->alc = 0;
dgs->allocation_failure = 1;
return;
}
dgs->buf = newbuf;
dgs->alc = newalc;
}
 
/* Append a buffer to a growable string. */
 
static inline void
d_growable_string_append_buffer (struct d_growable_string *dgs,
const char *s, size_t l)
{
size_t need;
 
need = dgs->len + l + 1;
if (need > dgs->alc)
d_growable_string_resize (dgs, need);
 
if (dgs->allocation_failure)
return;
 
memcpy (dgs->buf + dgs->len, s, l);
dgs->buf[dgs->len + l] = '\0';
dgs->len += l;
}
 
/* Bridge growable strings to the callback mechanism. */
 
static void
d_growable_string_callback_adapter (const char *s, size_t l, void *opaque)
{
struct d_growable_string *dgs = (struct d_growable_string*) opaque;
 
d_growable_string_append_buffer (dgs, s, l);
}
 
/* Initialize a print information structure. */
 
static void
d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
void *opaque)
{
dpi->len = 0;
dpi->last_char = '\0';
dpi->templates = NULL;
dpi->modifiers = NULL;
dpi->pack_index = 0;
dpi->flush_count = 0;
 
dpi->callback = callback;
dpi->opaque = opaque;
 
dpi->demangle_failure = 0;
}
 
/* Indicate that an error occurred during printing, and test for error. */
 
static inline void
d_print_error (struct d_print_info *dpi)
{
dpi->demangle_failure = 1;
}
 
static inline int
d_print_saw_error (struct d_print_info *dpi)
{
return dpi->demangle_failure != 0;
}
 
/* Flush buffered characters to the callback. */
 
static inline void
d_print_flush (struct d_print_info *dpi)
{
dpi->buf[dpi->len] = '\0';
dpi->callback (dpi->buf, dpi->len, dpi->opaque);
dpi->len = 0;
dpi->flush_count++;
}
 
/* Append characters and buffers for printing. */
 
static inline void
d_append_char (struct d_print_info *dpi, char c)
{
if (dpi->len == sizeof (dpi->buf) - 1)
d_print_flush (dpi);
 
dpi->buf[dpi->len++] = c;
dpi->last_char = c;
}
 
static inline void
d_append_buffer (struct d_print_info *dpi, const char *s, size_t l)
{
size_t i;
 
for (i = 0; i < l; i++)
d_append_char (dpi, s[i]);
}
 
static inline void
d_append_string (struct d_print_info *dpi, const char *s)
{
d_append_buffer (dpi, s, strlen (s));
}
 
static inline void
d_append_num (struct d_print_info *dpi, long l)
{
char buf[25];
sprintf (buf,"%ld", l);
d_append_string (dpi, buf);
}
 
static inline char
d_last_char (struct d_print_info *dpi)
{
return dpi->last_char;
}
 
/* Turn components into a human readable string. OPTIONS is the
options bits passed to the demangler. DC is the tree to print.
CALLBACK is a function to call to flush demangled string segments
as they fill the intermediate buffer, and OPAQUE is a generalized
callback argument. On success, this returns 1. On failure,
it returns 0, indicating a bad parse. It does not use heap
memory to build an output string, so cannot encounter memory
allocation failure. */
 
CP_STATIC_IF_GLIBCPP_V3
int
cplus_demangle_print_callback (int options,
const struct demangle_component *dc,
demangle_callbackref callback, void *opaque)
{
struct d_print_info dpi;
 
d_print_init (&dpi, callback, opaque);
 
d_print_comp (&dpi, options, dc);
 
d_print_flush (&dpi);
 
return ! d_print_saw_error (&dpi);
}
 
/* Turn components into a human readable string. OPTIONS is the
options bits passed to the demangler. DC is the tree to print.
ESTIMATE is a guess at the length of the result. This returns a
string allocated by malloc, or NULL on error. On success, this
sets *PALC to the size of the allocated buffer. On failure, this
sets *PALC to 0 for a bad parse, or to 1 for a memory allocation
failure. */
 
CP_STATIC_IF_GLIBCPP_V3
char *
cplus_demangle_print (int options, const struct demangle_component *dc,
int estimate, size_t *palc)
{
struct d_growable_string dgs;
 
d_growable_string_init (&dgs, estimate);
 
if (! cplus_demangle_print_callback (options, dc,
d_growable_string_callback_adapter,
&dgs))
{
free (dgs.buf);
*palc = 0;
return NULL;
}
 
*palc = dgs.allocation_failure ? 1 : dgs.alc;
return dgs.buf;
}
 
/* Returns the I'th element of the template arglist ARGS, or NULL on
failure. */
 
static struct demangle_component *
d_index_template_argument (struct demangle_component *args, int i)
{
struct demangle_component *a;
 
for (a = args;
a != NULL;
a = d_right (a))
{
if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
return NULL;
if (i <= 0)
break;
--i;
}
if (i != 0 || a == NULL)
return NULL;
 
return d_left (a);
}
 
/* Returns the template argument from the current context indicated by DC,
which is a DEMANGLE_COMPONENT_TEMPLATE_PARAM, or NULL. */
 
static struct demangle_component *
d_lookup_template_argument (struct d_print_info *dpi,
const struct demangle_component *dc)
{
if (dpi->templates == NULL)
{
d_print_error (dpi);
return NULL;
}
return d_index_template_argument
(d_right (dpi->templates->template_decl),
dc->u.s_number.number);
}
 
/* Returns a template argument pack used in DC (any will do), or NULL. */
 
static struct demangle_component *
d_find_pack (struct d_print_info *dpi,
const struct demangle_component *dc)
{
struct demangle_component *a;
if (dc == NULL)
return NULL;
 
switch (dc->type)
{
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
a = d_lookup_template_argument (dpi, dc);
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
return a;
return NULL;
 
case DEMANGLE_COMPONENT_PACK_EXPANSION:
return NULL;
case DEMANGLE_COMPONENT_LAMBDA:
case DEMANGLE_COMPONENT_NAME:
case DEMANGLE_COMPONENT_TAGGED_NAME:
case DEMANGLE_COMPONENT_OPERATOR:
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
case DEMANGLE_COMPONENT_SUB_STD:
case DEMANGLE_COMPONENT_CHARACTER:
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
case DEMANGLE_COMPONENT_UNNAMED_TYPE:
return NULL;
 
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
return d_find_pack (dpi, dc->u.s_extended_operator.name);
case DEMANGLE_COMPONENT_CTOR:
return d_find_pack (dpi, dc->u.s_ctor.name);
case DEMANGLE_COMPONENT_DTOR:
return d_find_pack (dpi, dc->u.s_dtor.name);
 
default:
a = d_find_pack (dpi, d_left (dc));
if (a)
return a;
return d_find_pack (dpi, d_right (dc));
}
}
 
/* Returns the length of the template argument pack DC. */
 
static int
d_pack_length (const struct demangle_component *dc)
{
int count = 0;
while (dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST
&& d_left (dc) != NULL)
{
++count;
dc = d_right (dc);
}
return count;
}
 
/* DC is a component of a mangled expression. Print it, wrapped in parens
if needed. */
 
static void
d_print_subexpr (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
int simple = 0;
if (dc->type == DEMANGLE_COMPONENT_NAME
|| dc->type == DEMANGLE_COMPONENT_QUAL_NAME
|| dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST
|| dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
simple = 1;
if (!simple)
d_append_char (dpi, '(');
d_print_comp (dpi, options, dc);
if (!simple)
d_append_char (dpi, ')');
}
 
/* Subroutine to handle components. */
 
static void
d_print_comp (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
/* Magic variable to let reference smashing skip over the next modifier
without needing to modify *dc. */
const struct demangle_component *mod_inner = NULL;
 
if (dc == NULL)
{
d_print_error (dpi);
return;
}
if (d_print_saw_error (dpi))
return;
 
switch (dc->type)
{
case DEMANGLE_COMPONENT_NAME:
if ((options & DMGL_JAVA) == 0)
d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
else
d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
return;
 
case DEMANGLE_COMPONENT_TAGGED_NAME:
d_print_comp (dpi, options, d_left (dc));
d_append_string (dpi, "[abi:");
d_print_comp (dpi, options, d_right (dc));
d_append_char (dpi, ']');
return;
 
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
d_print_comp (dpi, options, d_left (dc));
if ((options & DMGL_JAVA) == 0)
d_append_string (dpi, "::");
else
d_append_char (dpi, '.');
{
struct demangle_component *local_name = d_right (dc);
if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
{
d_append_string (dpi, "{default arg#");
d_append_num (dpi, local_name->u.s_unary_num.num + 1);
d_append_string (dpi, "}::");
local_name = local_name->u.s_unary_num.sub;
}
d_print_comp (dpi, options, local_name);
}
return;
 
case DEMANGLE_COMPONENT_TYPED_NAME:
{
struct d_print_mod *hold_modifiers;
struct demangle_component *typed_name;
struct d_print_mod adpm[4];
unsigned int i;
struct d_print_template dpt;
 
/* Pass the name down to the type so that it can be printed in
the right place for the type. We also have to pass down
any CV-qualifiers, which apply to the this parameter. */
hold_modifiers = dpi->modifiers;
dpi->modifiers = 0;
i = 0;
typed_name = d_left (dc);
while (typed_name != NULL)
{
if (i >= sizeof adpm / sizeof adpm[0])
{
d_print_error (dpi);
return;
}
 
adpm[i].next = dpi->modifiers;
dpi->modifiers = &adpm[i];
adpm[i].mod = typed_name;
adpm[i].printed = 0;
adpm[i].templates = dpi->templates;
++i;
 
if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
&& typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
&& typed_name->type != DEMANGLE_COMPONENT_CONST_THIS
&& typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
&& typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS)
break;
 
typed_name = d_left (typed_name);
}
 
if (typed_name == NULL)
{
d_print_error (dpi);
return;
}
 
/* If typed_name is a template, then it applies to the
function type as well. */
if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
{
dpt.next = dpi->templates;
dpi->templates = &dpt;
dpt.template_decl = typed_name;
}
 
/* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then
there may be CV-qualifiers on its right argument which
really apply here; this happens when parsing a class which
is local to a function. */
if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME)
{
struct demangle_component *local_name;
 
local_name = d_right (typed_name);
if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
local_name = local_name->u.s_unary_num.sub;
while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| local_name->type == DEMANGLE_COMPONENT_CONST_THIS
|| local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|| (local_name->type
== DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))
{
if (i >= sizeof adpm / sizeof adpm[0])
{
d_print_error (dpi);
return;
}
 
adpm[i] = adpm[i - 1];
adpm[i].next = &adpm[i - 1];
dpi->modifiers = &adpm[i];
 
adpm[i - 1].mod = local_name;
adpm[i - 1].printed = 0;
adpm[i - 1].templates = dpi->templates;
++i;
 
local_name = d_left (local_name);
}
}
 
d_print_comp (dpi, options, d_right (dc));
 
if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
dpi->templates = dpt.next;
 
/* If the modifiers didn't get printed by the type, print them
now. */
while (i > 0)
{
--i;
if (! adpm[i].printed)
{
d_append_char (dpi, ' ');
d_print_mod (dpi, options, adpm[i].mod);
}
}
 
dpi->modifiers = hold_modifiers;
 
return;
}
 
case DEMANGLE_COMPONENT_TEMPLATE:
{
struct d_print_mod *hold_dpm;
struct demangle_component *dcl;
 
/* Don't push modifiers into a template definition. Doing so
could give the wrong definition for a template argument.
Instead, treat the template essentially as a name. */
 
hold_dpm = dpi->modifiers;
dpi->modifiers = NULL;
 
dcl = d_left (dc);
 
if ((options & DMGL_JAVA) != 0
&& dcl->type == DEMANGLE_COMPONENT_NAME
&& dcl->u.s_name.len == 6
&& strncmp (dcl->u.s_name.s, "JArray", 6) == 0)
{
/* Special-case Java arrays, so that JArray<TYPE> appears
instead as TYPE[]. */
 
d_print_comp (dpi, options, d_right (dc));
d_append_string (dpi, "[]");
}
else
{
d_print_comp (dpi, options, dcl);
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
d_append_char (dpi, '<');
d_print_comp (dpi, options, d_right (dc));
/* Avoid generating two consecutive '>' characters, to avoid
the C++ syntactic ambiguity. */
if (d_last_char (dpi) == '>')
d_append_char (dpi, ' ');
d_append_char (dpi, '>');
}
 
dpi->modifiers = hold_dpm;
 
return;
}
 
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
{
struct d_print_template *hold_dpt;
struct demangle_component *a = d_lookup_template_argument (dpi, dc);
 
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
a = d_index_template_argument (a, dpi->pack_index);
 
if (a == NULL)
{
d_print_error (dpi);
return;
}
 
/* While processing this parameter, we need to pop the list of
templates. This is because the template parameter may
itself be a reference to a parameter of an outer
template. */
 
hold_dpt = dpi->templates;
dpi->templates = hold_dpt->next;
 
d_print_comp (dpi, options, a);
 
dpi->templates = hold_dpt;
 
return;
}
 
case DEMANGLE_COMPONENT_CTOR:
d_print_comp (dpi, options, dc->u.s_ctor.name);
return;
 
case DEMANGLE_COMPONENT_DTOR:
d_append_char (dpi, '~');
d_print_comp (dpi, options, dc->u.s_dtor.name);
return;
 
case DEMANGLE_COMPONENT_VTABLE:
d_append_string (dpi, "vtable for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_VTT:
d_append_string (dpi, "VTT for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
d_append_string (dpi, "construction vtable for ");
d_print_comp (dpi, options, d_left (dc));
d_append_string (dpi, "-in-");
d_print_comp (dpi, options, d_right (dc));
return;
 
case DEMANGLE_COMPONENT_TYPEINFO:
d_append_string (dpi, "typeinfo for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_TYPEINFO_NAME:
d_append_string (dpi, "typeinfo name for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_TYPEINFO_FN:
d_append_string (dpi, "typeinfo fn for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_THUNK:
d_append_string (dpi, "non-virtual thunk to ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
d_append_string (dpi, "virtual thunk to ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_COVARIANT_THUNK:
d_append_string (dpi, "covariant return thunk to ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_JAVA_CLASS:
d_append_string (dpi, "java Class for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_GUARD:
d_append_string (dpi, "guard variable for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_TLS_INIT:
d_append_string (dpi, "TLS init function for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_TLS_WRAPPER:
d_append_string (dpi, "TLS wrapper function for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_REFTEMP:
d_append_string (dpi, "reference temporary #");
d_print_comp (dpi, options, d_right (dc));
d_append_string (dpi, " for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
d_append_string (dpi, "hidden alias for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
d_append_string (dpi, "transaction clone for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
d_append_string (dpi, "non-transaction clone for ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_SUB_STD:
d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
return;
 
case DEMANGLE_COMPONENT_RESTRICT:
case DEMANGLE_COMPONENT_VOLATILE:
case DEMANGLE_COMPONENT_CONST:
{
struct d_print_mod *pdpm;
 
/* When printing arrays, it's possible to have cases where the
same CV-qualifier gets pushed on the stack multiple times.
We only need to print it once. */
 
for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next)
{
if (! pdpm->printed)
{
if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT
&& pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE
&& pdpm->mod->type != DEMANGLE_COMPONENT_CONST)
break;
if (pdpm->mod->type == dc->type)
{
d_print_comp (dpi, options, d_left (dc));
return;
}
}
}
}
goto modifier;
 
case DEMANGLE_COMPONENT_REFERENCE:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
{
/* Handle reference smashing: & + && = &. */
const struct demangle_component *sub = d_left (dc);
if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
{
struct demangle_component *a = d_lookup_template_argument (dpi, sub);
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
a = d_index_template_argument (a, dpi->pack_index);
 
if (a == NULL)
{
d_print_error (dpi);
return;
}
 
sub = a;
}
 
if (sub->type == DEMANGLE_COMPONENT_REFERENCE
|| sub->type == dc->type)
dc = sub;
else if (sub->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE)
mod_inner = d_left (sub);
}
/* Fall through. */
 
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_REFERENCE_THIS:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_COMPLEX:
case DEMANGLE_COMPONENT_IMAGINARY:
modifier:
{
/* We keep a list of modifiers on the stack. */
struct d_print_mod dpm;
 
dpm.next = dpi->modifiers;
dpi->modifiers = &dpm;
dpm.mod = dc;
dpm.printed = 0;
dpm.templates = dpi->templates;
 
if (!mod_inner)
mod_inner = d_left (dc);
 
d_print_comp (dpi, options, mod_inner);
 
/* If the modifier didn't get printed by the type, print it
now. */
if (! dpm.printed)
d_print_mod (dpi, options, dc);
 
dpi->modifiers = dpm.next;
 
return;
}
 
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
if ((options & DMGL_JAVA) == 0)
d_append_buffer (dpi, dc->u.s_builtin.type->name,
dc->u.s_builtin.type->len);
else
d_append_buffer (dpi, dc->u.s_builtin.type->java_name,
dc->u.s_builtin.type->java_len);
return;
 
case DEMANGLE_COMPONENT_VENDOR_TYPE:
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_FUNCTION_TYPE:
{
if ((options & DMGL_RET_POSTFIX) != 0)
d_print_function_type (dpi,
options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
dc, dpi->modifiers);
 
/* Print return type if present */
if (d_left (dc) != NULL && (options & DMGL_RET_POSTFIX) != 0)
d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
d_left (dc));
else if (d_left (dc) != NULL && (options & DMGL_RET_DROP) == 0)
{
struct d_print_mod dpm;
 
/* We must pass this type down as a modifier in order to
print it in the right location. */
dpm.next = dpi->modifiers;
dpi->modifiers = &dpm;
dpm.mod = dc;
dpm.printed = 0;
dpm.templates = dpi->templates;
 
d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
d_left (dc));
 
dpi->modifiers = dpm.next;
 
if (dpm.printed)
return;
 
/* In standard prefix notation, there is a space between the
return type and the function signature. */
if ((options & DMGL_RET_POSTFIX) == 0)
d_append_char (dpi, ' ');
}
 
if ((options & DMGL_RET_POSTFIX) == 0)
d_print_function_type (dpi,
options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
dc, dpi->modifiers);
 
return;
}
 
case DEMANGLE_COMPONENT_ARRAY_TYPE:
{
struct d_print_mod *hold_modifiers;
struct d_print_mod adpm[4];
unsigned int i;
struct d_print_mod *pdpm;
 
/* We must pass this type down as a modifier in order to print
multi-dimensional arrays correctly. If the array itself is
CV-qualified, we act as though the element type were
CV-qualified. We do this by copying the modifiers down
rather than fiddling pointers, so that we don't wind up
with a d_print_mod higher on the stack pointing into our
stack frame after we return. */
 
hold_modifiers = dpi->modifiers;
 
adpm[0].next = hold_modifiers;
dpi->modifiers = &adpm[0];
adpm[0].mod = dc;
adpm[0].printed = 0;
adpm[0].templates = dpi->templates;
 
i = 1;
pdpm = hold_modifiers;
while (pdpm != NULL
&& (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT
|| pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE
|| pdpm->mod->type == DEMANGLE_COMPONENT_CONST))
{
if (! pdpm->printed)
{
if (i >= sizeof adpm / sizeof adpm[0])
{
d_print_error (dpi);
return;
}
 
adpm[i] = *pdpm;
adpm[i].next = dpi->modifiers;
dpi->modifiers = &adpm[i];
pdpm->printed = 1;
++i;
}
 
pdpm = pdpm->next;
}
 
d_print_comp (dpi, options, d_right (dc));
 
dpi->modifiers = hold_modifiers;
 
if (adpm[0].printed)
return;
 
while (i > 1)
{
--i;
d_print_mod (dpi, options, adpm[i].mod);
}
 
d_print_array_type (dpi, options, dc, dpi->modifiers);
 
return;
}
 
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
case DEMANGLE_COMPONENT_VECTOR_TYPE:
{
struct d_print_mod dpm;
 
dpm.next = dpi->modifiers;
dpi->modifiers = &dpm;
dpm.mod = dc;
dpm.printed = 0;
dpm.templates = dpi->templates;
 
d_print_comp (dpi, options, d_right (dc));
 
/* If the modifier didn't get printed by the type, print it
now. */
if (! dpm.printed)
d_print_mod (dpi, options, dc);
 
dpi->modifiers = dpm.next;
 
return;
}
 
case DEMANGLE_COMPONENT_FIXED_TYPE:
if (dc->u.s_fixed.sat)
d_append_string (dpi, "_Sat ");
/* Don't print "int _Accum". */
if (dc->u.s_fixed.length->u.s_builtin.type
!= &cplus_demangle_builtin_types['i'-'a'])
{
d_print_comp (dpi, options, dc->u.s_fixed.length);
d_append_char (dpi, ' ');
}
if (dc->u.s_fixed.accum)
d_append_string (dpi, "_Accum");
else
d_append_string (dpi, "_Fract");
return;
 
case DEMANGLE_COMPONENT_ARGLIST:
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
if (d_left (dc) != NULL)
d_print_comp (dpi, options, d_left (dc));
if (d_right (dc) != NULL)
{
size_t len;
unsigned long int flush_count;
/* Make sure ", " isn't flushed by d_append_string, otherwise
dpi->len -= 2 wouldn't work. */
if (dpi->len >= sizeof (dpi->buf) - 2)
d_print_flush (dpi);
d_append_string (dpi, ", ");
len = dpi->len;
flush_count = dpi->flush_count;
d_print_comp (dpi, options, d_right (dc));
/* If that didn't print anything (which can happen with empty
template argument packs), remove the comma and space. */
if (dpi->flush_count == flush_count && dpi->len == len)
dpi->len -= 2;
}
return;
 
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
{
struct demangle_component *type = d_left (dc);
struct demangle_component *list = d_right (dc);
 
if (type)
d_print_comp (dpi, options, type);
d_append_char (dpi, '{');
d_print_comp (dpi, options, list);
d_append_char (dpi, '}');
}
return;
 
case DEMANGLE_COMPONENT_OPERATOR:
{
const struct demangle_operator_info *op = dc->u.s_operator.op;
int len = op->len;
 
d_append_string (dpi, "operator");
/* Add a space before new/delete. */
if (IS_LOWER (op->name[0]))
d_append_char (dpi, ' ');
/* Omit a trailing space. */
if (op->name[len-1] == ' ')
--len;
d_append_buffer (dpi, op->name, len);
return;
}
 
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
d_append_string (dpi, "operator ");
d_print_comp (dpi, options, dc->u.s_extended_operator.name);
return;
 
case DEMANGLE_COMPONENT_CAST:
d_append_string (dpi, "operator ");
d_print_cast (dpi, options, dc);
return;
 
case DEMANGLE_COMPONENT_NULLARY:
d_print_expr_op (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_UNARY:
{
struct demangle_component *op = d_left (dc);
struct demangle_component *operand = d_right (dc);
const char *code = NULL;
 
if (op->type == DEMANGLE_COMPONENT_OPERATOR)
{
code = op->u.s_operator.op->code;
if (!strcmp (code, "ad"))
{
/* Don't print the argument list for the address of a
function. */
if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME
&& d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME
&& d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
operand = d_left (operand);
}
if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS)
{
/* This indicates a suffix operator. */
operand = d_left (operand);
d_print_subexpr (dpi, options, operand);
d_print_expr_op (dpi, options, op);
return;
}
}
 
if (op->type != DEMANGLE_COMPONENT_CAST)
d_print_expr_op (dpi, options, op);
else
{
d_append_char (dpi, '(');
d_print_cast (dpi, options, op);
d_append_char (dpi, ')');
}
if (code && !strcmp (code, "gs"))
/* Avoid parens after '::'. */
d_print_comp (dpi, options, operand);
else if (code && !strcmp (code, "st"))
/* Always print parens for sizeof (type). */
{
d_append_char (dpi, '(');
d_print_comp (dpi, options, operand);
d_append_char (dpi, ')');
}
else
d_print_subexpr (dpi, options, operand);
}
return;
 
case DEMANGLE_COMPONENT_BINARY:
if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS)
{
d_print_error (dpi);
return;
}
 
if (op_is_new_cast (d_left (dc)))
{
d_print_expr_op (dpi, options, d_left (dc));
d_append_char (dpi, '<');
d_print_comp (dpi, options, d_left (d_right (dc)));
d_append_string (dpi, ">(");
d_print_comp (dpi, options, d_right (d_right (dc)));
d_append_char (dpi, ')');
return;
}
 
/* We wrap an expression which uses the greater-than operator in
an extra layer of parens so that it does not get confused
with the '>' which ends the template parameters. */
if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
&& d_left (dc)->u.s_operator.op->len == 1
&& d_left (dc)->u.s_operator.op->name[0] == '>')
d_append_char (dpi, '(');
 
if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") == 0
&& d_left (d_right (dc))->type == DEMANGLE_COMPONENT_TYPED_NAME)
{
/* Function call used in an expression should not have printed types
of the function arguments. Values of the function arguments still
get printed below. */
 
const struct demangle_component *func = d_left (d_right (dc));
 
if (d_right (func)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
d_print_error (dpi);
d_print_subexpr (dpi, options, d_left (func));
}
else
d_print_subexpr (dpi, options, d_left (d_right (dc)));
if (strcmp (d_left (dc)->u.s_operator.op->code, "ix") == 0)
{
d_append_char (dpi, '[');
d_print_comp (dpi, options, d_right (d_right (dc)));
d_append_char (dpi, ']');
}
else
{
if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0)
d_print_expr_op (dpi, options, d_left (dc));
d_print_subexpr (dpi, options, d_right (d_right (dc)));
}
 
if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
&& d_left (dc)->u.s_operator.op->len == 1
&& d_left (dc)->u.s_operator.op->name[0] == '>')
d_append_char (dpi, ')');
 
return;
 
case DEMANGLE_COMPONENT_BINARY_ARGS:
/* We should only see this as part of DEMANGLE_COMPONENT_BINARY. */
d_print_error (dpi);
return;
 
case DEMANGLE_COMPONENT_TRINARY:
if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1
|| d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2)
{
d_print_error (dpi);
return;
}
{
struct demangle_component *op = d_left (dc);
struct demangle_component *first = d_left (d_right (dc));
struct demangle_component *second = d_left (d_right (d_right (dc)));
struct demangle_component *third = d_right (d_right (d_right (dc)));
 
if (!strcmp (op->u.s_operator.op->code, "qu"))
{
d_print_subexpr (dpi, options, first);
d_print_expr_op (dpi, options, op);
d_print_subexpr (dpi, options, second);
d_append_string (dpi, " : ");
d_print_subexpr (dpi, options, third);
}
else
{
d_append_string (dpi, "new ");
if (d_left (first) != NULL)
{
d_print_subexpr (dpi, options, first);
d_append_char (dpi, ' ');
}
d_print_comp (dpi, options, second);
if (third)
d_print_subexpr (dpi, options, third);
}
}
return;
 
case DEMANGLE_COMPONENT_TRINARY_ARG1:
case DEMANGLE_COMPONENT_TRINARY_ARG2:
/* We should only see these are part of DEMANGLE_COMPONENT_TRINARY. */
d_print_error (dpi);
return;
 
case DEMANGLE_COMPONENT_LITERAL:
case DEMANGLE_COMPONENT_LITERAL_NEG:
{
enum d_builtin_type_print tp;
 
/* For some builtin types, produce simpler output. */
tp = D_PRINT_DEFAULT;
if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE)
{
tp = d_left (dc)->u.s_builtin.type->print;
switch (tp)
{
case D_PRINT_INT:
case D_PRINT_UNSIGNED:
case D_PRINT_LONG:
case D_PRINT_UNSIGNED_LONG:
case D_PRINT_LONG_LONG:
case D_PRINT_UNSIGNED_LONG_LONG:
if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME)
{
if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
d_append_char (dpi, '-');
d_print_comp (dpi, options, d_right (dc));
switch (tp)
{
default:
break;
case D_PRINT_UNSIGNED:
d_append_char (dpi, 'u');
break;
case D_PRINT_LONG:
d_append_char (dpi, 'l');
break;
case D_PRINT_UNSIGNED_LONG:
d_append_string (dpi, "ul");
break;
case D_PRINT_LONG_LONG:
d_append_string (dpi, "ll");
break;
case D_PRINT_UNSIGNED_LONG_LONG:
d_append_string (dpi, "ull");
break;
}
return;
}
break;
 
case D_PRINT_BOOL:
if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME
&& d_right (dc)->u.s_name.len == 1
&& dc->type == DEMANGLE_COMPONENT_LITERAL)
{
switch (d_right (dc)->u.s_name.s[0])
{
case '0':
d_append_string (dpi, "false");
return;
case '1':
d_append_string (dpi, "true");
return;
default:
break;
}
}
break;
 
default:
break;
}
}
 
d_append_char (dpi, '(');
d_print_comp (dpi, options, d_left (dc));
d_append_char (dpi, ')');
if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
d_append_char (dpi, '-');
if (tp == D_PRINT_FLOAT)
d_append_char (dpi, '[');
d_print_comp (dpi, options, d_right (dc));
if (tp == D_PRINT_FLOAT)
d_append_char (dpi, ']');
}
return;
 
case DEMANGLE_COMPONENT_NUMBER:
d_append_num (dpi, dc->u.s_number.number);
return;
 
case DEMANGLE_COMPONENT_JAVA_RESOURCE:
d_append_string (dpi, "java resource ");
d_print_comp (dpi, options, d_left (dc));
return;
 
case DEMANGLE_COMPONENT_COMPOUND_NAME:
d_print_comp (dpi, options, d_left (dc));
d_print_comp (dpi, options, d_right (dc));
return;
 
case DEMANGLE_COMPONENT_CHARACTER:
d_append_char (dpi, dc->u.s_character.character);
return;
 
case DEMANGLE_COMPONENT_DECLTYPE:
d_append_string (dpi, "decltype (");
d_print_comp (dpi, options, d_left (dc));
d_append_char (dpi, ')');
return;
 
case DEMANGLE_COMPONENT_PACK_EXPANSION:
{
int len;
int i;
struct demangle_component *a = d_find_pack (dpi, d_left (dc));
if (a == NULL)
{
/* d_find_pack won't find anything if the only packs involved
in this expansion are function parameter packs; in that
case, just print the pattern and "...". */
d_print_subexpr (dpi, options, d_left (dc));
d_append_string (dpi, "...");
return;
}
 
len = d_pack_length (a);
dc = d_left (dc);
for (i = 0; i < len; ++i)
{
dpi->pack_index = i;
d_print_comp (dpi, options, dc);
if (i < len-1)
d_append_string (dpi, ", ");
}
}
return;
 
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
{
long num = dc->u.s_number.number;
if (num == 0)
d_append_string (dpi, "this");
else
{
d_append_string (dpi, "{parm#");
d_append_num (dpi, num);
d_append_char (dpi, '}');
}
}
return;
 
case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
d_append_string (dpi, "global constructors keyed to ");
d_print_comp (dpi, options, dc->u.s_binary.left);
return;
 
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
d_append_string (dpi, "global destructors keyed to ");
d_print_comp (dpi, options, dc->u.s_binary.left);
return;
 
case DEMANGLE_COMPONENT_LAMBDA:
d_append_string (dpi, "{lambda(");
d_print_comp (dpi, options, dc->u.s_unary_num.sub);
d_append_string (dpi, ")#");
d_append_num (dpi, dc->u.s_unary_num.num + 1);
d_append_char (dpi, '}');
return;
 
case DEMANGLE_COMPONENT_UNNAMED_TYPE:
d_append_string (dpi, "{unnamed type#");
d_append_num (dpi, dc->u.s_number.number + 1);
d_append_char (dpi, '}');
return;
 
case DEMANGLE_COMPONENT_CLONE:
d_print_comp (dpi, options, d_left (dc));
d_append_string (dpi, " [clone ");
d_print_comp (dpi, options, d_right (dc));
d_append_char (dpi, ']');
return;
 
default:
d_print_error (dpi);
return;
}
}
 
/* Print a Java dentifier. For Java we try to handle encoded extended
Unicode characters. The C++ ABI doesn't mention Unicode encoding,
so we don't it for C++. Characters are encoded as
__U<hex-char>+_. */
 
static void
d_print_java_identifier (struct d_print_info *dpi, const char *name, int len)
{
const char *p;
const char *end;
 
end = name + len;
for (p = name; p < end; ++p)
{
if (end - p > 3
&& p[0] == '_'
&& p[1] == '_'
&& p[2] == 'U')
{
unsigned long c;
const char *q;
 
c = 0;
for (q = p + 3; q < end; ++q)
{
int dig;
 
if (IS_DIGIT (*q))
dig = *q - '0';
else if (*q >= 'A' && *q <= 'F')
dig = *q - 'A' + 10;
else if (*q >= 'a' && *q <= 'f')
dig = *q - 'a' + 10;
else
break;
 
c = c * 16 + dig;
}
/* If the Unicode character is larger than 256, we don't try
to deal with it here. FIXME. */
if (q < end && *q == '_' && c < 256)
{
d_append_char (dpi, c);
p = q;
continue;
}
}
 
d_append_char (dpi, *p);
}
}
 
/* Print a list of modifiers. SUFFIX is 1 if we are printing
qualifiers on this after printing a function. */
 
static void
d_print_mod_list (struct d_print_info *dpi, int options,
struct d_print_mod *mods, int suffix)
{
struct d_print_template *hold_dpt;
 
if (mods == NULL || d_print_saw_error (dpi))
return;
 
if (mods->printed
|| (! suffix
&& (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS
|| mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|| (mods->mod->type
== DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))))
{
d_print_mod_list (dpi, options, mods->next, suffix);
return;
}
 
mods->printed = 1;
 
hold_dpt = dpi->templates;
dpi->templates = mods->templates;
 
if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
{
d_print_function_type (dpi, options, mods->mod, mods->next);
dpi->templates = hold_dpt;
return;
}
else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
{
d_print_array_type (dpi, options, mods->mod, mods->next);
dpi->templates = hold_dpt;
return;
}
else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME)
{
struct d_print_mod *hold_modifiers;
struct demangle_component *dc;
 
/* When this is on the modifier stack, we have pulled any
qualifiers off the right argument already. Otherwise, we
print it as usual, but don't let the left argument see any
modifiers. */
 
hold_modifiers = dpi->modifiers;
dpi->modifiers = NULL;
d_print_comp (dpi, options, d_left (mods->mod));
dpi->modifiers = hold_modifiers;
 
if ((options & DMGL_JAVA) == 0)
d_append_string (dpi, "::");
else
d_append_char (dpi, '.');
 
dc = d_right (mods->mod);
 
if (dc->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
{
d_append_string (dpi, "{default arg#");
d_append_num (dpi, dc->u.s_unary_num.num + 1);
d_append_string (dpi, "}::");
dc = dc->u.s_unary_num.sub;
}
 
while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| dc->type == DEMANGLE_COMPONENT_CONST_THIS
|| dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|| dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
dc = d_left (dc);
 
d_print_comp (dpi, options, dc);
 
dpi->templates = hold_dpt;
return;
}
 
d_print_mod (dpi, options, mods->mod);
 
dpi->templates = hold_dpt;
 
d_print_mod_list (dpi, options, mods->next, suffix);
}
 
/* Print a modifier. */
 
static void
d_print_mod (struct d_print_info *dpi, int options,
const struct demangle_component *mod)
{
switch (mod->type)
{
case DEMANGLE_COMPONENT_RESTRICT:
case DEMANGLE_COMPONENT_RESTRICT_THIS:
d_append_string (dpi, " restrict");
return;
case DEMANGLE_COMPONENT_VOLATILE:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
d_append_string (dpi, " volatile");
return;
case DEMANGLE_COMPONENT_CONST:
case DEMANGLE_COMPONENT_CONST_THIS:
d_append_string (dpi, " const");
return;
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
d_append_char (dpi, ' ');
d_print_comp (dpi, options, d_right (mod));
return;
case DEMANGLE_COMPONENT_POINTER:
/* There is no pointer symbol in Java. */
if ((options & DMGL_JAVA) == 0)
d_append_char (dpi, '*');
return;
case DEMANGLE_COMPONENT_REFERENCE_THIS:
/* For the ref-qualifier, put a space before the &. */
d_append_char (dpi, ' ');
case DEMANGLE_COMPONENT_REFERENCE:
d_append_char (dpi, '&');
return;
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
d_append_char (dpi, ' ');
case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
d_append_string (dpi, "&&");
return;
case DEMANGLE_COMPONENT_COMPLEX:
d_append_string (dpi, "complex ");
return;
case DEMANGLE_COMPONENT_IMAGINARY:
d_append_string (dpi, "imaginary ");
return;
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
if (d_last_char (dpi) != '(')
d_append_char (dpi, ' ');
d_print_comp (dpi, options, d_left (mod));
d_append_string (dpi, "::*");
return;
case DEMANGLE_COMPONENT_TYPED_NAME:
d_print_comp (dpi, options, d_left (mod));
return;
case DEMANGLE_COMPONENT_VECTOR_TYPE:
d_append_string (dpi, " __vector(");
d_print_comp (dpi, options, d_left (mod));
d_append_char (dpi, ')');
return;
 
default:
/* Otherwise, we have something that won't go back on the
modifier stack, so we can just print it. */
d_print_comp (dpi, options, mod);
return;
}
}
 
/* Print a function type, except for the return type. */
 
static void
d_print_function_type (struct d_print_info *dpi, int options,
const struct demangle_component *dc,
struct d_print_mod *mods)
{
int need_paren;
int need_space;
struct d_print_mod *p;
struct d_print_mod *hold_modifiers;
 
need_paren = 0;
need_space = 0;
for (p = mods; p != NULL; p = p->next)
{
if (p->printed)
break;
 
switch (p->mod->type)
{
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_REFERENCE:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
need_paren = 1;
break;
case DEMANGLE_COMPONENT_RESTRICT:
case DEMANGLE_COMPONENT_VOLATILE:
case DEMANGLE_COMPONENT_CONST:
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
case DEMANGLE_COMPONENT_COMPLEX:
case DEMANGLE_COMPONENT_IMAGINARY:
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
need_space = 1;
need_paren = 1;
break;
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_REFERENCE_THIS:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
break;
default:
break;
}
if (need_paren)
break;
}
 
if (need_paren)
{
if (! need_space)
{
if (d_last_char (dpi) != '('
&& d_last_char (dpi) != '*')
need_space = 1;
}
if (need_space && d_last_char (dpi) != ' ')
d_append_char (dpi, ' ');
d_append_char (dpi, '(');
}
 
hold_modifiers = dpi->modifiers;
dpi->modifiers = NULL;
 
d_print_mod_list (dpi, options, mods, 0);
 
if (need_paren)
d_append_char (dpi, ')');
 
d_append_char (dpi, '(');
 
if (d_right (dc) != NULL)
d_print_comp (dpi, options, d_right (dc));
 
d_append_char (dpi, ')');
 
d_print_mod_list (dpi, options, mods, 1);
 
dpi->modifiers = hold_modifiers;
}
 
/* Print an array type, except for the element type. */
 
static void
d_print_array_type (struct d_print_info *dpi, int options,
const struct demangle_component *dc,
struct d_print_mod *mods)
{
int need_space;
 
need_space = 1;
if (mods != NULL)
{
int need_paren;
struct d_print_mod *p;
 
need_paren = 0;
for (p = mods; p != NULL; p = p->next)
{
if (! p->printed)
{
if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
{
need_space = 0;
break;
}
else
{
need_paren = 1;
need_space = 1;
break;
}
}
}
 
if (need_paren)
d_append_string (dpi, " (");
 
d_print_mod_list (dpi, options, mods, 0);
 
if (need_paren)
d_append_char (dpi, ')');
}
 
if (need_space)
d_append_char (dpi, ' ');
 
d_append_char (dpi, '[');
 
if (d_left (dc) != NULL)
d_print_comp (dpi, options, d_left (dc));
 
d_append_char (dpi, ']');
}
 
/* Print an operator in an expression. */
 
static void
d_print_expr_op (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
if (dc->type == DEMANGLE_COMPONENT_OPERATOR)
d_append_buffer (dpi, dc->u.s_operator.op->name,
dc->u.s_operator.op->len);
else
d_print_comp (dpi, options, dc);
}
 
/* Print a cast. */
 
static void
d_print_cast (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
d_print_comp (dpi, options, d_left (dc));
else
{
struct d_print_mod *hold_dpm;
struct d_print_template dpt;
 
/* It appears that for a templated cast operator, we need to put
the template parameters in scope for the operator name, but
not for the parameters. The effect is that we need to handle
the template printing here. */
 
hold_dpm = dpi->modifiers;
dpi->modifiers = NULL;
 
dpt.next = dpi->templates;
dpi->templates = &dpt;
dpt.template_decl = d_left (dc);
 
d_print_comp (dpi, options, d_left (d_left (dc)));
 
dpi->templates = dpt.next;
 
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
d_append_char (dpi, '<');
d_print_comp (dpi, options, d_right (d_left (dc)));
/* Avoid generating two consecutive '>' characters, to avoid
the C++ syntactic ambiguity. */
if (d_last_char (dpi) == '>')
d_append_char (dpi, ' ');
d_append_char (dpi, '>');
 
dpi->modifiers = hold_dpm;
}
}
 
/* Initialize the information structure we use to pass around
information. */
 
CP_STATIC_IF_GLIBCPP_V3
void
cplus_demangle_init_info (const char *mangled, int options, size_t len,
struct d_info *di)
{
di->s = mangled;
di->send = mangled + len;
di->options = options;
 
di->n = mangled;
 
/* We can not need more components than twice the number of chars in
the mangled string. Most components correspond directly to
chars, but the ARGLIST types are exceptions. */
di->num_comps = 2 * len;
di->next_comp = 0;
 
/* Similarly, we can not need more substitutions than there are
chars in the mangled string. */
di->num_subs = len;
di->next_sub = 0;
di->did_subs = 0;
 
di->last_name = NULL;
 
di->expansion = 0;
}
 
/* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI
mangled name, return strings in repeated callback giving the demangled
name. OPTIONS is the usual libiberty demangler options. On success,
this returns 1. On failure, returns 0. */
 
static int
d_demangle_callback (const char *mangled, int options,
demangle_callbackref callback, void *opaque)
{
enum
{
DCT_TYPE,
DCT_MANGLED,
DCT_GLOBAL_CTORS,
DCT_GLOBAL_DTORS
}
type;
struct d_info di;
struct demangle_component *dc;
int status;
 
if (mangled[0] == '_' && mangled[1] == 'Z')
type = DCT_MANGLED;
else if (strncmp (mangled, "_GLOBAL_", 8) == 0
&& (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$')
&& (mangled[9] == 'D' || mangled[9] == 'I')
&& mangled[10] == '_')
type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS;
else
{
if ((options & DMGL_TYPES) == 0)
return 0;
type = DCT_TYPE;
}
 
cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
 
{
#ifdef CP_DYNAMIC_ARRAYS
__extension__ struct demangle_component comps[di.num_comps];
__extension__ struct demangle_component *subs[di.num_subs];
 
di.comps = comps;
di.subs = subs;
#else
di.comps = alloca (di.num_comps * sizeof (*di.comps));
di.subs = alloca (di.num_subs * sizeof (*di.subs));
#endif
 
switch (type)
{
case DCT_TYPE:
dc = cplus_demangle_type (&di);
break;
case DCT_MANGLED:
dc = cplus_demangle_mangled_name (&di, 1);
break;
case DCT_GLOBAL_CTORS:
case DCT_GLOBAL_DTORS:
d_advance (&di, 11);
dc = d_make_comp (&di,
(type == DCT_GLOBAL_CTORS
? DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS
: DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS),
d_make_demangle_mangled_name (&di, d_str (&di)),
NULL);
d_advance (&di, strlen (d_str (&di)));
break;
}
 
/* If DMGL_PARAMS is set, then if we didn't consume the entire
mangled string, then we didn't successfully demangle it. If
DMGL_PARAMS is not set, we didn't look at the trailing
parameters. */
if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
dc = NULL;
 
#ifdef CP_DEMANGLE_DEBUG
d_dump (dc, 0);
#endif
 
status = (dc != NULL)
? cplus_demangle_print_callback (options, dc, callback, opaque)
: 0;
}
 
return status;
}
 
/* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled
name, return a buffer allocated with malloc holding the demangled
name. OPTIONS is the usual libiberty demangler options. On
success, this sets *PALC to the allocated size of the returned
buffer. On failure, this sets *PALC to 0 for a bad name, or 1 for
a memory allocation failure, and returns NULL. */
 
static char *
d_demangle (const char *mangled, int options, size_t *palc)
{
struct d_growable_string dgs;
int status;
 
d_growable_string_init (&dgs, 0);
 
status = d_demangle_callback (mangled, options,
d_growable_string_callback_adapter, &dgs);
if (status == 0)
{
free (dgs.buf);
*palc = 0;
return NULL;
}
 
*palc = dgs.allocation_failure ? 1 : dgs.alc;
return dgs.buf;
}
 
#if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
 
extern char *__cxa_demangle (const char *, char *, size_t *, int *);
 
/* ia64 ABI-mandated entry point in the C++ runtime library for
performing demangling. MANGLED_NAME is a NUL-terminated character
string containing the name to be demangled.
 
OUTPUT_BUFFER is a region of memory, allocated with malloc, of
*LENGTH bytes, into which the demangled name is stored. If
OUTPUT_BUFFER is not long enough, it is expanded using realloc.
OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
is placed in a region of memory allocated with malloc.
 
If LENGTH is non-NULL, the length of the buffer containing the
demangled name, is placed in *LENGTH.
 
The return value is a pointer to the start of the NUL-terminated
demangled name, or NULL if the demangling fails. The caller is
responsible for deallocating this memory using free.
 
*STATUS is set to one of the following values:
0: The demangling operation succeeded.
-1: A memory allocation failure occurred.
-2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
-3: One of the arguments is invalid.
 
The demangling is performed using the C++ ABI mangling rules, with
GNU extensions. */
 
char *
__cxa_demangle (const char *mangled_name, char *output_buffer,
size_t *length, int *status)
{
char *demangled;
size_t alc;
 
if (mangled_name == NULL)
{
if (status != NULL)
*status = -3;
return NULL;
}
 
if (output_buffer != NULL && length == NULL)
{
if (status != NULL)
*status = -3;
return NULL;
}
 
demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc);
 
if (demangled == NULL)
{
if (status != NULL)
{
if (alc == 1)
*status = -1;
else
*status = -2;
}
return NULL;
}
 
if (output_buffer == NULL)
{
if (length != NULL)
*length = alc;
}
else
{
if (strlen (demangled) < *length)
{
strcpy (output_buffer, demangled);
free (demangled);
demangled = output_buffer;
}
else
{
free (output_buffer);
*length = alc;
}
}
 
if (status != NULL)
*status = 0;
 
return demangled;
}
 
extern int __gcclibcxx_demangle_callback (const char *,
void (*)
(const char *, size_t, void *),
void *);
 
/* Alternative, allocationless entry point in the C++ runtime library
for performing demangling. MANGLED_NAME is a NUL-terminated character
string containing the name to be demangled.
 
CALLBACK is a callback function, called with demangled string
segments as demangling progresses; it is called at least once,
but may be called more than once. OPAQUE is a generalized pointer
used as a callback argument.
 
The return code is one of the following values, equivalent to
the STATUS values of __cxa_demangle() (excluding -1, since this
function performs no memory allocations):
0: The demangling operation succeeded.
-2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
-3: One of the arguments is invalid.
 
The demangling is performed using the C++ ABI mangling rules, with
GNU extensions. */
 
int
__gcclibcxx_demangle_callback (const char *mangled_name,
void (*callback) (const char *, size_t, void *),
void *opaque)
{
int status;
 
if (mangled_name == NULL || callback == NULL)
return -3;
 
status = d_demangle_callback (mangled_name, DMGL_PARAMS | DMGL_TYPES,
callback, opaque);
if (status == 0)
return -2;
 
return 0;
}
 
#else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */
 
/* Entry point for libiberty demangler. If MANGLED is a g++ v3 ABI
mangled name, return a buffer allocated with malloc holding the
demangled name. Otherwise, return NULL. */
 
char *
cplus_demangle_v3 (const char *mangled, int options)
{
size_t alc;
 
return d_demangle (mangled, options, &alc);
}
 
int
cplus_demangle_v3_callback (const char *mangled, int options,
demangle_callbackref callback, void *opaque)
{
return d_demangle_callback (mangled, options, callback, opaque);
}
 
/* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling
conventions, but the output formatting is a little different.
This instructs the C++ demangler not to emit pointer characters ("*"), to
use Java's namespace separator symbol ("." instead of "::"), and to output
JArray<TYPE> as TYPE[]. */
 
char *
java_demangle_v3 (const char *mangled)
{
size_t alc;
 
return d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, &alc);
}
 
int
java_demangle_v3_callback (const char *mangled,
demangle_callbackref callback, void *opaque)
{
return d_demangle_callback (mangled,
DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX,
callback, opaque);
}
 
#endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */
 
#ifndef IN_GLIBCPP_V3
 
/* Demangle a string in order to find out whether it is a constructor
or destructor. Return non-zero on success. Set *CTOR_KIND and
*DTOR_KIND appropriately. */
 
static int
is_ctor_or_dtor (const char *mangled,
enum gnu_v3_ctor_kinds *ctor_kind,
enum gnu_v3_dtor_kinds *dtor_kind)
{
struct d_info di;
struct demangle_component *dc;
int ret;
 
*ctor_kind = (enum gnu_v3_ctor_kinds) 0;
*dtor_kind = (enum gnu_v3_dtor_kinds) 0;
 
cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di);
 
{
#ifdef CP_DYNAMIC_ARRAYS
__extension__ struct demangle_component comps[di.num_comps];
__extension__ struct demangle_component *subs[di.num_subs];
 
di.comps = comps;
di.subs = subs;
#else
di.comps = alloca (di.num_comps * sizeof (*di.comps));
di.subs = alloca (di.num_subs * sizeof (*di.subs));
#endif
 
dc = cplus_demangle_mangled_name (&di, 1);
 
/* Note that because we did not pass DMGL_PARAMS, we don't expect
to demangle the entire string. */
 
ret = 0;
while (dc != NULL)
{
switch (dc->type)
{
/* These cannot appear on a constructor or destructor. */
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_REFERENCE_THIS:
case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
default:
dc = NULL;
break;
case DEMANGLE_COMPONENT_TYPED_NAME:
case DEMANGLE_COMPONENT_TEMPLATE:
dc = d_left (dc);
break;
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
dc = d_right (dc);
break;
case DEMANGLE_COMPONENT_CTOR:
*ctor_kind = dc->u.s_ctor.kind;
ret = 1;
dc = NULL;
break;
case DEMANGLE_COMPONENT_DTOR:
*dtor_kind = dc->u.s_dtor.kind;
ret = 1;
dc = NULL;
break;
}
}
}
 
return ret;
}
 
/* Return whether NAME is the mangled form of a g++ V3 ABI constructor
name. A non-zero return indicates the type of constructor. */
 
enum gnu_v3_ctor_kinds
is_gnu_v3_mangled_ctor (const char *name)
{
enum gnu_v3_ctor_kinds ctor_kind;
enum gnu_v3_dtor_kinds dtor_kind;
 
if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
return (enum gnu_v3_ctor_kinds) 0;
return ctor_kind;
}
 
 
/* Return whether NAME is the mangled form of a g++ V3 ABI destructor
name. A non-zero return indicates the type of destructor. */
 
enum gnu_v3_dtor_kinds
is_gnu_v3_mangled_dtor (const char *name)
{
enum gnu_v3_ctor_kinds ctor_kind;
enum gnu_v3_dtor_kinds dtor_kind;
 
if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
return (enum gnu_v3_dtor_kinds) 0;
return dtor_kind;
}
 
#endif /* IN_GLIBCPP_V3 */
 
#ifdef STANDALONE_DEMANGLER
 
#include "getopt.h"
#include "dyn-string.h"
 
static void print_usage (FILE* fp, int exit_value);
 
#define IS_ALPHA(CHAR) \
(((CHAR) >= 'a' && (CHAR) <= 'z') \
|| ((CHAR) >= 'A' && (CHAR) <= 'Z'))
 
/* Non-zero if CHAR is a character than can occur in a mangled name. */
#define is_mangled_char(CHAR) \
(IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
|| (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
 
/* The name of this program, as invoked. */
const char* program_name;
 
/* Prints usage summary to FP and then exits with EXIT_VALUE. */
 
static void
print_usage (FILE* fp, int exit_value)
{
fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
fprintf (fp, "Options:\n");
fprintf (fp, " -h,--help Display this message.\n");
fprintf (fp, " -p,--no-params Don't display function parameters\n");
fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
 
exit (exit_value);
}
 
/* Option specification for getopt_long. */
static const struct option long_options[] =
{
{ "help", no_argument, NULL, 'h' },
{ "no-params", no_argument, NULL, 'p' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, no_argument, NULL, 0 },
};
 
/* Main entry for a demangling filter executable. It will demangle
its command line arguments, if any. If none are provided, it will
filter stdin to stdout, replacing any recognized mangled C++ names
with their demangled equivalents. */
 
int
main (int argc, char *argv[])
{
int i;
int opt_char;
int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
 
/* Use the program name of this program, as invoked. */
program_name = argv[0];
 
/* Parse options. */
do
{
opt_char = getopt_long (argc, argv, "hpv", long_options, NULL);
switch (opt_char)
{
case '?': /* Unrecognized option. */
print_usage (stderr, 1);
break;
 
case 'h':
print_usage (stdout, 0);
break;
 
case 'p':
options &= ~ DMGL_PARAMS;
break;
 
case 'v':
options |= DMGL_VERBOSE;
break;
}
}
while (opt_char != -1);
 
if (optind == argc)
/* No command line arguments were provided. Filter stdin. */
{
dyn_string_t mangled = dyn_string_new (3);
char *s;
 
/* Read all of input. */
while (!feof (stdin))
{
char c;
 
/* Pile characters into mangled until we hit one that can't
occur in a mangled name. */
c = getchar ();
while (!feof (stdin) && is_mangled_char (c))
{
dyn_string_append_char (mangled, c);
if (feof (stdin))
break;
c = getchar ();
}
 
if (dyn_string_length (mangled) > 0)
{
#ifdef IN_GLIBCPP_V3
s = __cxa_demangle (dyn_string_buf (mangled), NULL, NULL, NULL);
#else
s = cplus_demangle_v3 (dyn_string_buf (mangled), options);
#endif
 
if (s != NULL)
{
fputs (s, stdout);
free (s);
}
else
{
/* It might not have been a mangled name. Print the
original text. */
fputs (dyn_string_buf (mangled), stdout);
}
 
dyn_string_clear (mangled);
}
 
/* If we haven't hit EOF yet, we've read one character that
can't occur in a mangled name, so print it out. */
if (!feof (stdin))
putchar (c);
}
 
dyn_string_delete (mangled);
}
else
/* Demangle command line arguments. */
{
/* Loop over command line arguments. */
for (i = optind; i < argc; ++i)
{
char *s;
#ifdef IN_GLIBCPP_V3
int status;
#endif
 
/* Attempt to demangle. */
#ifdef IN_GLIBCPP_V3
s = __cxa_demangle (argv[i], NULL, NULL, &status);
#else
s = cplus_demangle_v3 (argv[i], options);
#endif
 
/* If it worked, print the demangled name. */
if (s != NULL)
{
printf ("%s\n", s);
free (s);
}
else
{
#ifdef IN_GLIBCPP_V3
fprintf (stderr, "Failed: %s (status %d)\n", argv[i], status);
#else
fprintf (stderr, "Failed: %s\n", argv[i]);
#endif
}
}
}
 
return 0;
}
 
#endif /* STANDALONE_DEMANGLER */
/contrib/sdk/sources/libstdc++-v3/libsupc++/cxxabi.h
0,0 → 1,700
// ABI Support -*- C++ -*-
 
// Copyright (C) 2000-2013 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 Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
 
/* This file declares the new abi entry points into the runtime. It is not
normally necessary for user programs to include this header, or use the
entry points directly. However, this header is available should that be
needed.
 
Some of the entry points are intended for both C and C++, thus this header
is includable from both C and C++. Though the C++ specific parts are not
available in C, naturally enough. */
 
/** @file cxxabi.h
* The header provides an interface to the C++ ABI.
*/
 
#ifndef _CXXABI_H
#define _CXXABI_H 1
 
#pragma GCC system_header
 
#pragma GCC visibility push(default)
 
#include <stddef.h>
#include <bits/c++config.h>
#include <bits/cxxabi_tweaks.h>
#include <bits/cxxabi_forced.h>
 
#ifndef _GLIBCXX_CDTOR_CALLABI
#define _GLIBCXX_CDTOR_CALLABI
#endif
 
#ifdef __cplusplus
namespace __cxxabiv1
{
extern "C"
{
#endif
 
typedef __cxa_cdtor_return_type (*__cxa_cdtor_type)(void *);
 
// Allocate array.
void*
__cxa_vec_new(size_t __element_count, size_t __element_size,
size_t __padding_size, __cxa_cdtor_type __constructor,
__cxa_cdtor_type __destructor);
 
void*
__cxa_vec_new2(size_t __element_count, size_t __element_size,
size_t __padding_size, __cxa_cdtor_type __constructor,
__cxa_cdtor_type __destructor, void *(*__alloc) (size_t),
void (*__dealloc) (void*));
 
void*
__cxa_vec_new3(size_t __element_count, size_t __element_size,
size_t __padding_size, __cxa_cdtor_type __constructor,
__cxa_cdtor_type __destructor, void *(*__alloc) (size_t),
void (*__dealloc) (void*, size_t));
 
// Construct array.
__cxa_vec_ctor_return_type
__cxa_vec_ctor(void* __array_address, size_t __element_count,
size_t __element_size, __cxa_cdtor_type __constructor,
__cxa_cdtor_type __destructor);
 
__cxa_vec_ctor_return_type
__cxa_vec_cctor(void* __dest_array, void* __src_array,
size_t __element_count, size_t __element_size,
__cxa_cdtor_return_type (*__constructor) (void*, void*),
__cxa_cdtor_type __destructor);
 
// Destruct array.
void
__cxa_vec_dtor(void* __array_address, size_t __element_count,
size_t __element_size, __cxa_cdtor_type __destructor);
 
void
__cxa_vec_cleanup(void* __array_address, size_t __element_count, size_t __s,
__cxa_cdtor_type __destructor) _GLIBCXX_NOTHROW;
 
// Destruct and release array.
void
__cxa_vec_delete(void* __array_address, size_t __element_size,
size_t __padding_size, __cxa_cdtor_type __destructor);
 
void
__cxa_vec_delete2(void* __array_address, size_t __element_size,
size_t __padding_size, __cxa_cdtor_type __destructor,
void (*__dealloc) (void*));
 
void
__cxa_vec_delete3(void* __array_address, size_t __element_size,
size_t __padding_size, __cxa_cdtor_type __destructor,
void (*__dealloc) (void*, size_t));
 
int
__cxa_guard_acquire(__guard*);
 
void
__cxa_guard_release(__guard*) _GLIBCXX_NOTHROW;
 
void
__cxa_guard_abort(__guard*) _GLIBCXX_NOTHROW;
 
// DSO destruction.
int
__cxa_atexit(void (*)(void*), void*, void*) _GLIBCXX_NOTHROW;
 
int
__cxa_finalize(void*);
 
// TLS destruction.
int
__cxa_thread_atexit(void (*)(void*), void*, void *) _GLIBCXX_NOTHROW;
 
// Pure virtual functions.
void
__cxa_pure_virtual(void) __attribute__ ((__noreturn__));
 
void
__cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
 
// Exception handling auxillary.
void
__cxa_bad_cast() __attribute__((__noreturn__));
 
void
__cxa_bad_typeid() __attribute__((__noreturn__));
 
 
/**
* @brief Demangling routine.
* ABI-mandated entry point in the C++ runtime library for demangling.
*
* @param __mangled_name A NUL-terminated character string
* containing the name to be demangled.
*
* @param __output_buffer A region of memory, allocated with
* malloc, of @a *__length bytes, into which the demangled name is
* stored. If @a __output_buffer is not long enough, it is
* expanded using realloc. @a __output_buffer may instead be NULL;
* in that case, the demangled name is placed in a region of memory
* allocated with malloc.
*
* @param __length If @a __length is non-NULL, the length of the
* buffer containing the demangled name is placed in @a *__length.
*
* @param __status @a *__status is set to one of the following values:
* 0: The demangling operation succeeded.
* -1: A memory allocation failure occurred.
* -2: @a mangled_name is not a valid name under the C++ ABI mangling rules.
* -3: One of the arguments is invalid.
*
* @return A pointer to the start of the NUL-terminated demangled
* name, or NULL if the demangling fails. The caller is
* responsible for deallocating this memory using @c free.
*
* The demangling is performed using the C++ ABI mangling rules,
* with GNU extensions. For example, this function is used in
* __gnu_cxx::__verbose_terminate_handler.
*
* See http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch39.html
* for other examples of use.
*
* @note The same demangling functionality is available via
* libiberty (@c <libiberty/demangle.h> and @c libiberty.a) in GCC
* 3.1 and later, but that requires explicit installation (@c
* --enable-install-libiberty) and uses a different API, although
* the ABI is unchanged.
*/
char*
__cxa_demangle(const char* __mangled_name, char* __output_buffer,
size_t* __length, int* __status);
 
#ifdef __cplusplus
}
} // namespace __cxxabiv1
#endif
 
#ifdef __cplusplus
 
#include <typeinfo>
 
namespace __cxxabiv1
{
// Type information for int, float etc.
class __fundamental_type_info : public std::type_info
{
public:
explicit
__fundamental_type_info(const char* __n) : std::type_info(__n) { }
 
virtual
~__fundamental_type_info();
};
 
// Type information for array objects.
class __array_type_info : public std::type_info
{
public:
explicit
__array_type_info(const char* __n) : std::type_info(__n) { }
 
virtual
~__array_type_info();
};
 
// Type information for functions (both member and non-member).
class __function_type_info : public std::type_info
{
public:
explicit
__function_type_info(const char* __n) : std::type_info(__n) { }
 
virtual
~__function_type_info();
 
protected:
// Implementation defined member function.
virtual bool
__is_function_p() const;
};
 
// Type information for enumerations.
class __enum_type_info : public std::type_info
{
public:
explicit
__enum_type_info(const char* __n) : std::type_info(__n) { }
 
virtual
~__enum_type_info();
};
 
// Common type information for simple pointers and pointers to member.
class __pbase_type_info : public std::type_info
{
public:
unsigned int __flags; // Qualification of the target object.
const std::type_info* __pointee; // Type of pointed to object.
 
explicit
__pbase_type_info(const char* __n, int __quals,
const std::type_info* __type)
: std::type_info(__n), __flags(__quals), __pointee(__type)
{ }
 
virtual
~__pbase_type_info();
 
// Implementation defined type.
enum __masks
{
__const_mask = 0x1,
__volatile_mask = 0x2,
__restrict_mask = 0x4,
__incomplete_mask = 0x8,
__incomplete_class_mask = 0x10
};
 
protected:
__pbase_type_info(const __pbase_type_info&);
 
__pbase_type_info&
operator=(const __pbase_type_info&);
 
// Implementation defined member functions.
virtual bool
__do_catch(const std::type_info* __thr_type, void** __thr_obj,
unsigned int __outer) const;
 
inline virtual bool
__pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj,
unsigned __outer) const;
};
 
// Type information for simple pointers.
class __pointer_type_info : public __pbase_type_info
{
public:
explicit
__pointer_type_info(const char* __n, int __quals,
const std::type_info* __type)
: __pbase_type_info (__n, __quals, __type) { }
 
 
virtual
~__pointer_type_info();
 
protected:
// Implementation defined member functions.
virtual bool
__is_pointer_p() const;
 
virtual bool
__pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj,
unsigned __outer) const;
};
 
class __class_type_info;
 
// Type information for a pointer to member variable.
class __pointer_to_member_type_info : public __pbase_type_info
{
public:
__class_type_info* __context; // Class of the member.
 
explicit
__pointer_to_member_type_info(const char* __n, int __quals,
const std::type_info* __type,
__class_type_info* __klass)
: __pbase_type_info(__n, __quals, __type), __context(__klass) { }
 
virtual
~__pointer_to_member_type_info();
 
protected:
__pointer_to_member_type_info(const __pointer_to_member_type_info&);
 
__pointer_to_member_type_info&
operator=(const __pointer_to_member_type_info&);
 
// Implementation defined member function.
virtual bool
__pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj,
unsigned __outer) const;
};
 
// Helper class for __vmi_class_type.
class __base_class_type_info
{
public:
const __class_type_info* __base_type; // Base class type.
#ifdef _GLIBCXX_LLP64
long long __offset_flags; // Offset and info.
#else
long __offset_flags; // Offset and info.
#endif
 
enum __offset_flags_masks
{
__virtual_mask = 0x1,
__public_mask = 0x2,
__hwm_bit = 2,
__offset_shift = 8 // Bits to shift offset.
};
 
// Implementation defined member functions.
bool
__is_virtual_p() const
{ return __offset_flags & __virtual_mask; }
 
bool
__is_public_p() const
{ return __offset_flags & __public_mask; }
 
ptrdiff_t
__offset() const
{
// This shift, being of a signed type, is implementation
// defined. GCC implements such shifts as arithmetic, which is
// what we want.
return static_cast<ptrdiff_t>(__offset_flags) >> __offset_shift;
}
};
 
// Type information for a class.
class __class_type_info : public std::type_info
{
public:
explicit
__class_type_info (const char *__n) : type_info(__n) { }
 
virtual
~__class_type_info ();
 
// Implementation defined types.
// The type sub_kind tells us about how a base object is contained
// within a derived object. We often do this lazily, hence the
// UNKNOWN value. At other times we may use NOT_CONTAINED to mean
// not publicly contained.
enum __sub_kind
{
// We have no idea.
__unknown = 0,
 
// Not contained within us (in some circumstances this might
// mean not contained publicly)
__not_contained,
 
// Contained ambiguously.
__contained_ambig,
 
// Via a virtual path.
__contained_virtual_mask = __base_class_type_info::__virtual_mask,
 
// Via a public path.
__contained_public_mask = __base_class_type_info::__public_mask,
 
// Contained within us.
__contained_mask = 1 << __base_class_type_info::__hwm_bit,
 
__contained_private = __contained_mask,
__contained_public = __contained_mask | __contained_public_mask
};
 
struct __upcast_result;
struct __dyncast_result;
 
protected:
// Implementation defined member functions.
virtual bool
__do_upcast(const __class_type_info* __dst_type, void**__obj_ptr) const;
 
virtual bool
__do_catch(const type_info* __thr_type, void** __thr_obj,
unsigned __outer) const;
 
public:
// Helper for upcast. See if DST is us, or one of our bases.
// Return false if not found, true if found.
virtual bool
__do_upcast(const __class_type_info* __dst, const void* __obj,
__upcast_result& __restrict __result) const;
 
// Indicate whether SRC_PTR of type SRC_TYPE is contained publicly
// within OBJ_PTR. OBJ_PTR points to a base object of our type,
// which is the destination type. SRC2DST indicates how SRC
// objects might be contained within this type. If SRC_PTR is one
// of our SRC_TYPE bases, indicate the virtuality. Returns
// not_contained for non containment or private containment.
inline __sub_kind
__find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
const __class_type_info* __src_type,
const void* __src_ptr) const;
 
// Helper for dynamic cast. ACCESS_PATH gives the access from the
// most derived object to this base. DST_TYPE indicates the
// desired type we want. OBJ_PTR points to a base of our type
// within the complete object. SRC_TYPE indicates the static type
// started from and SRC_PTR points to that base within the most
// derived object. Fill in RESULT with what we find. Return true
// if we have located an ambiguous match.
virtual bool
__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& __result) const;
 
// Helper for find_public_subobj. SRC2DST indicates how SRC_TYPE
// bases are inherited by the type started from -- which is not
// necessarily the current type. The current type will be a base
// of the destination type. OBJ_PTR points to the current base.
virtual __sub_kind
__do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
const __class_type_info* __src_type,
const void* __src_ptr) const;
};
 
// Type information for a class with a single non-virtual base.
class __si_class_type_info : public __class_type_info
{
public:
const __class_type_info* __base_type;
 
explicit
__si_class_type_info(const char *__n, const __class_type_info *__base)
: __class_type_info(__n), __base_type(__base) { }
 
virtual
~__si_class_type_info();
 
protected:
__si_class_type_info(const __si_class_type_info&);
 
__si_class_type_info&
operator=(const __si_class_type_info&);
 
// Implementation defined member functions.
virtual bool
__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& __result) const;
 
virtual __sub_kind
__do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
const __class_type_info* __src_type,
const void* __sub_ptr) const;
 
virtual bool
__do_upcast(const __class_type_info*__dst, const void*__obj,
__upcast_result& __restrict __result) const;
};
 
// Type information for a class with multiple and/or virtual bases.
class __vmi_class_type_info : public __class_type_info
{
public:
unsigned int __flags; // Details about the class hierarchy.
unsigned int __base_count; // Number of direct bases.
 
// The array of bases uses the trailing array struct hack so this
// class is not constructable with a normal constructor. It is
// internally generated by the compiler.
__base_class_type_info __base_info[1]; // Array of bases.
 
explicit
__vmi_class_type_info(const char* __n, int ___flags)
: __class_type_info(__n), __flags(___flags), __base_count(0) { }
 
virtual
~__vmi_class_type_info();
 
// Implementation defined types.
enum __flags_masks
{
__non_diamond_repeat_mask = 0x1, // Distinct instance of repeated base.
__diamond_shaped_mask = 0x2, // Diamond shaped multiple inheritance.
__flags_unknown_mask = 0x10
};
 
protected:
// Implementation defined member functions.
virtual bool
__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& __result) const;
 
virtual __sub_kind
__do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
const __class_type_info* __src_type,
const void* __src_ptr) const;
 
virtual bool
__do_upcast(const __class_type_info* __dst, const void* __obj,
__upcast_result& __restrict __result) const;
};
 
// Exception handling forward declarations.
struct __cxa_exception;
struct __cxa_refcounted_exception;
struct __cxa_dependent_exception;
struct __cxa_eh_globals;
 
extern "C"
{
// Dynamic cast runtime.
 
// src2dst has the following possible values
// >-1: src_type is a unique public non-virtual base of dst_type
// dst_ptr + src2dst == src_ptr
// -1: unspecified relationship
// -2: src_type is not a public base of dst_type
// -3: src_type is a multiple public non-virtual base of dst_type
void*
__dynamic_cast(const void* __src_ptr, // Starting object.
const __class_type_info* __src_type, // Static type of object.
const __class_type_info* __dst_type, // Desired target type.
ptrdiff_t __src2dst); // How src and dst are related.
 
 
// Exception handling runtime.
 
// The __cxa_eh_globals for the current thread can be obtained by using
// either of the following functions. The "fast" version assumes at least
// one prior call of __cxa_get_globals has been made from the current
// thread, so no initialization is necessary.
__cxa_eh_globals*
__cxa_get_globals() _GLIBCXX_NOTHROW __attribute__ ((__const__));
 
__cxa_eh_globals*
__cxa_get_globals_fast() _GLIBCXX_NOTHROW __attribute__ ((__const__));
 
// Allocate memory for the primary exception plus the thrown object.
void*
__cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
 
// Free the space allocated for the primary exception.
void
__cxa_free_exception(void*) _GLIBCXX_NOTHROW;
 
// Throw the exception.
void
__cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *))
__attribute__((__noreturn__));
 
// Used to implement exception handlers.
void*
__cxa_get_exception_ptr(void*) _GLIBCXX_NOTHROW __attribute__ ((__pure__));
 
void*
__cxa_begin_catch(void*) _GLIBCXX_NOTHROW;
 
void
__cxa_end_catch();
 
void
__cxa_rethrow() __attribute__((__noreturn__));
 
// Returns the type_info for the currently handled exception [15.3/8], or
// null if there is none.
std::type_info*
__cxa_current_exception_type() _GLIBCXX_NOTHROW __attribute__ ((__pure__));
 
// GNU Extensions.
 
// Allocate memory for a dependent exception.
__cxa_dependent_exception*
__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW;
 
// Free the space allocated for the dependent exception.
void
__cxa_free_dependent_exception(__cxa_dependent_exception*) _GLIBCXX_NOTHROW;
 
} // extern "C"
 
// A magic placeholder class that can be caught by reference
// to recognize foreign exceptions.
class __foreign_exception
{
virtual ~__foreign_exception() throw();
virtual void __pure_dummy() = 0; // prevent catch by value
};
 
} // namespace __cxxabiv1
 
/** @namespace abi
* @brief The cross-vendor C++ Application Binary Interface. A
* namespace alias to __cxxabiv1, but user programs should use the
* alias 'abi'.
*
* A brief overview of an ABI is given in the libstdc++ FAQ, question
* 5.8 (you may have a copy of the FAQ locally, or you can view the online
* version at http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#5_8 ).
*
* GCC subscribes to a cross-vendor ABI for C++, sometimes
* called the IA64 ABI because it happens to be the native ABI for that
* platform. It is summarized at http://www.codesourcery.com/cxx-abi/
* along with the current specification.
*
* For users of GCC greater than or equal to 3.x, entry points are
* available in <cxxabi.h>, which notes, <em>'It is not normally
* necessary for user programs to include this header, or use the
* entry points directly. However, this header is available should
* that be needed.'</em>
*/
namespace abi = __cxxabiv1;
 
namespace __gnu_cxx
{
/**
* @brief Exception thrown by __cxa_guard_acquire.
* @ingroup exceptions
*
* 6.7[stmt.dcl]/4: If control re-enters the declaration (recursively)
* while the object is being initialized, the behavior is undefined.
*
* Since we already have a library function to handle locking, we might
* as well check for this situation and throw an exception.
* We use the second byte of the guard variable to remember that we're
* in the middle of an initialization.
*/
class recursive_init_error: public std::exception
{
public:
recursive_init_error() throw() { }
virtual ~recursive_init_error() throw ();
};
}
#endif // __cplusplus
 
#pragma GCC visibility pop
 
#endif // __CXXABI_H
/contrib/sdk/sources/libstdc++-v3/libsupc++/cxxabi_forced.h
0,0 → 1,60
// cxxabi.h subset for cancellation -*- C++ -*-
// Copyright (C) 2007-2013 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 bits/cxxabi_forced.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{cxxabi.h}
*/
 
#ifndef _CXXABI_FORCED_H
#define _CXXABI_FORCED_H 1
 
#pragma GCC system_header
 
#pragma GCC visibility push(default)
 
#ifdef __cplusplus
namespace __cxxabiv1
{
/**
* @brief Thrown as part of forced unwinding.
* @ingroup exceptions
*
* A magic placeholder class that can be caught by reference to
* recognize forced unwinding.
*/
class __forced_unwind
{
virtual ~__forced_unwind() throw();
 
// Prevent catch by value.
virtual void __pure_dummy() = 0;
};
}
#endif // __cplusplus
 
#pragma GCC visibility pop
 
#endif // __CXXABI_FORCED_H
/contrib/sdk/sources/libstdc++-v3/libsupc++/del_op.cc
0,0 → 1,48
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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>
 
#if !_GLIBCXX_HOSTED
// A freestanding C runtime may not provide "free" -- but there is no
// other reasonable way to implement "operator delete".
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
extern "C" void free(void*);
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#else
# include <cstdlib>
#endif
 
#include "new"
 
_GLIBCXX_WEAK_DEFINITION void
operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT
{
if (ptr)
std::free(ptr);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/del_opnt.cc
0,0 → 1,35
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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 "new"
 
extern "C" void free (void *);
 
_GLIBCXX_WEAK_DEFINITION void
operator delete (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
free (ptr);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/del_opv.cc
0,0 → 1,33
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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 "new"
 
_GLIBCXX_WEAK_DEFINITION void
operator delete[] (void *ptr) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/del_opvnt.cc
0,0 → 1,33
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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 "new"
 
_GLIBCXX_WEAK_DEFINITION void
operator delete[] (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/dyncast.cc
0,0 → 1,85
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
 
// this is the external interface to the dynamic cast machinery
/* sub: source address to be adjusted; nonnull, and since the
* source object is polymorphic, *(void**)sub is a virtual pointer.
* src: static type of the source object.
* dst: destination type (the "T" in "dynamic_cast<T>(v)").
* src2dst_offset: a static hint about the location of the
* source subobject with respect to the complete object;
* special negative values are:
* -1: no hint
* -2: src is not a public base of dst
* -3: src is a multiple public base type but never a
* virtual base type
* otherwise, the src type is a unique public nonvirtual
* base type of dst at offset src2dst_offset from the
* origin of dst. */
extern "C" void *
__dynamic_cast (const void *src_ptr, // object started from
const __class_type_info *src_type, // type of the starting object
const __class_type_info *dst_type, // desired target type
ptrdiff_t src2dst) // how src and dst are related
{
const void *vtable = *static_cast <const void *const *> (src_ptr);
const vtable_prefix *prefix =
adjust_pointer <vtable_prefix> (vtable,
-offsetof (vtable_prefix, origin));
const void *whole_ptr =
adjust_pointer <void> (src_ptr, prefix->whole_object);
const __class_type_info *whole_type = prefix->whole_type;
__class_type_info::__dyncast_result result;
whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
dst_type, whole_ptr, src_type, src_ptr, result);
if (!result.dst_ptr)
return NULL;
if (contained_public_p (result.dst2src))
// Src is known to be a public base of dst.
return const_cast <void *> (result.dst_ptr);
if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
// Both src and dst are known to be public bases of whole. Found a valid
// cross cast.
return const_cast <void *> (result.dst_ptr);
if (contained_nonvirtual_p (result.whole2src))
// Src is known to be a non-public nonvirtual base of whole, and not a
// base of dst. Found an invalid cross cast, which cannot also be a down
// cast
return NULL;
if (result.dst2src == __class_type_info::__unknown)
result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
src_type, src_ptr);
if (contained_public_p (result.dst2src))
// Found a valid down cast
return const_cast <void *> (result.dst_ptr);
// Must be an invalid down cast, or the cross cast wasn't bettered
return NULL;
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_alloc.cc
0,0 → 1,223
// -*- C++ -*- Allocate exception objects.
// Copyright (C) 2001-2013 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 !defined (_GLIBCXX_LLP64) && 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
#if defined (_GLIBCXX_LLP64)
typedef unsigned long long bitmask_type;
#else
typedef unsigned long bitmask_type;
#endif
#endif
 
 
typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
static bitmask_type emergency_used;
 
static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT];
static bitmask_type dependents_used;
 
namespace
{
// A single mutex controlling emergency allocations.
__gnu_cxx::__mutex emergency_mutex;
}
 
extern "C" void *
__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW
{
void *ret;
 
thrown_size += sizeof (__cxa_refcounted_exception);
ret = malloc (thrown_size);
 
if (! ret)
{
__gnu_cxx::__scoped_lock sentry(emergency_mutex);
 
bitmask_type used = emergency_used;
unsigned int which = 0;
 
if (thrown_size > EMERGENCY_OBJ_SIZE)
goto failed;
while (used & 1)
{
used >>= 1;
if (++which >= EMERGENCY_OBJ_COUNT)
goto failed;
}
 
emergency_used |= (bitmask_type)1 << which;
ret = &emergency_buffer[which][0];
 
failed:;
 
if (!ret)
std::terminate ();
}
 
// We have an uncaught exception as soon as we allocate memory. This
// yields uncaught_exception() true during the copy-constructor that
// initializes the exception object. See Issue 475.
__cxa_eh_globals *globals = __cxa_get_globals ();
globals->uncaughtExceptions += 1;
 
memset (ret, 0, sizeof (__cxa_refcounted_exception));
 
return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
}
 
 
extern "C" void
__cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW
{
char *base = (char *) emergency_buffer;
char *ptr = (char *) vptr;
if (ptr >= base
&& ptr < base + sizeof (emergency_buffer))
{
const unsigned int which
= (unsigned) (ptr - base) / EMERGENCY_OBJ_SIZE;
 
__gnu_cxx::__scoped_lock sentry(emergency_mutex);
emergency_used &= ~((bitmask_type)1 << which);
}
else
free (ptr - sizeof (__cxa_refcounted_exception));
}
 
 
extern "C" __cxa_dependent_exception*
__cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW
{
__cxa_dependent_exception *ret;
 
ret = static_cast<__cxa_dependent_exception*>
(malloc (sizeof (__cxa_dependent_exception)));
 
if (!ret)
{
__gnu_cxx::__scoped_lock sentry(emergency_mutex);
 
bitmask_type used = dependents_used;
unsigned int which = 0;
 
while (used & 1)
{
used >>= 1;
if (++which >= EMERGENCY_OBJ_COUNT)
goto failed;
}
 
dependents_used |= (bitmask_type)1 << which;
ret = &dependents_buffer[which];
 
failed:;
 
if (!ret)
std::terminate ();
}
 
// We have an uncaught exception as soon as we allocate memory. This
// yields uncaught_exception() true during the copy-constructor that
// initializes the exception object. See Issue 475.
__cxa_eh_globals *globals = __cxa_get_globals ();
globals->uncaughtExceptions += 1;
 
memset (ret, 0, sizeof (__cxa_dependent_exception));
 
return ret;
}
 
 
extern "C" void
__cxxabiv1::__cxa_free_dependent_exception
(__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW
{
char *base = (char *) dependents_buffer;
char *ptr = (char *) vptr;
if (ptr >= base
&& ptr < base + sizeof (dependents_buffer))
{
const unsigned int which
= (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception);
 
__gnu_cxx::__scoped_lock sentry(emergency_mutex);
dependents_used &= ~((bitmask_type)1 << which);
}
else
free (vptr);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_arm.cc
0,0 → 1,227
// -*- C++ -*- ARM specific Exception handling support routines.
// Copyright (C) 2004-2013 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 <cxxabi.h>
#include "unwind-cxx.h"
 
#ifdef __ARM_EABI_UNWINDER__
 
using namespace __cxxabiv1;
 
 
// Given the thrown type THROW_TYPE, exception object UE_HEADER and a
// type CATCH_TYPE to compare against, return whether or not there is
// a match and if so, update *THROWN_PTR_P to point to either the
// type-matched object, or in the case of a pointer type, the object
// pointed to by the pointer.
 
extern "C" __cxa_type_match_result
__cxa_type_match(_Unwind_Exception* ue_header,
const std::type_info* catch_type,
bool is_reference __attribute__((__unused__)),
void** thrown_ptr_p)
{
bool forced_unwind
= __is_gxx_forced_unwind_class(ue_header->exception_class);
bool foreign_exception
= !forced_unwind && !__is_gxx_exception_class(ue_header->exception_class);
bool dependent_exception
= __is_dependent_exception(ue_header->exception_class);
__cxa_exception* xh = __get_exception_header_from_ue(ue_header);
__cxa_dependent_exception *dx = __get_dependent_exception_from_ue(ue_header);
const std::type_info* throw_type;
void *thrown_ptr = 0;
 
if (forced_unwind)
throw_type = &typeid(abi::__forced_unwind);
else if (foreign_exception)
throw_type = &typeid(abi::__foreign_exception);
else
{
if (dependent_exception)
xh = __get_exception_header_from_obj (dx->primaryException);
throw_type = xh->exceptionType;
// We used to require the caller set the target of thrown_ptr_p,
// but that's incorrect -- the EHABI makes no such requirement
// -- and not all callers will set it. Fortunately callers that
// do initialize will always pass us the value we calculate
// here, so there's no backwards compatibility problem.
thrown_ptr = __get_object_from_ue (ue_header);
}
__cxa_type_match_result result = ctm_succeeded;
 
// 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;
// We need to indicate the indirection to our caller.
result = ctm_succeeded_with_ptr_to_base;
}
 
if (catch_type->__do_catch(throw_type, &thrown_ptr, 1))
{
*thrown_ptr_p = thrown_ptr;
return result;
}
 
return ctm_failed;
}
 
// ABI defined routine called at the start of a cleanup handler.
extern "C" bool
__cxa_begin_cleanup(_Unwind_Exception* ue_header)
{
__cxa_eh_globals *globals = __cxa_get_globals();
__cxa_exception *header = __get_exception_header_from_ue(ue_header);
bool native = __is_gxx_exception_class(header->unwindHeader.exception_class);
 
 
if (native)
{
header->propagationCount++;
// Add it to the chain if this is the first time we've seen this
// exception.
if (header->propagationCount == 1)
{
header->nextPropagatingException = globals->propagatingExceptions;
globals->propagatingExceptions = header;
}
}
else
{
// Remember the exception object, so end_cleanup can return it.
// These cannot be stacked, so we must abort if we already have
// a propagating exception.
if (globals->propagatingExceptions)
std::terminate ();
globals->propagatingExceptions = header;
}
 
return true;
}
 
// Do the work for __cxa_end_cleanup. Returns the currently propagating
// exception object.
extern "C" _Unwind_Exception *
__gnu_end_cleanup(void)
{
__cxa_exception *header;
__cxa_eh_globals *globals = __cxa_get_globals();
 
header = globals->propagatingExceptions;
 
// Check something hasn't gone horribly wrong.
if (!header)
std::terminate();
 
if (__is_gxx_exception_class(header->unwindHeader.exception_class))
{
header->propagationCount--;
if (header->propagationCount == 0)
{
// Remove exception from chain.
globals->propagatingExceptions = header->nextPropagatingException;
header->nextPropagatingException = NULL;
}
}
else
globals->propagatingExceptions = NULL;
 
return &header->unwindHeader;
}
 
#ifdef __TMS320C6X__
// Assembly wrapper to call __gnu_end_cleanup without clobbering
// function arguments to _Unwind_Resume.
asm (".global __cxa_end_cleanup\n"
" .type __cxa_end_cleanup, \"function\"\n"
"__cxa_end_cleanup:\n"
" stw .d2t2 B9, *B15--[10]\n"
" stw .d2t2 B8, *+B15[9]\n"
" stw .d2t2 B7, *+B15[8]\n"
" stw .d2t2 B6, *+B15[7]\n"
" stw .d2t2 B5, *+B15[6]\n"
" stw .d2t2 B4, *+B15[5]\n"
" stw .d2t1 A9, *+B15[4]\n"
" stw .d2t1 A8, *+B15[3]\n"
" stw .d2t1 A7, *+B15[2]\n"
" stw .d2t1 A6, *+B15[1]\n"
#ifdef _TMS320C6400_PLUS
" callp .s2 (__gnu_end_cleanup), B3\n"
#elif defined(_TMS320C6400)
" call .s2 (__gnu_end_cleanup)\n"
" addkpc .s2 1f, B3, 0\n"
" nop 4\n"
"1:\n"
#else
" call .s2 (__gnu_end_cleanup)\n"
" mvkl .s2 1f, B3\n"
" mvkh .s2 1f, B3\n"
" nop 3\n"
"1:\n"
#endif
" ldw .d2t1 *+B15[1], A6\n"
" ldw .d2t1 *+B15[2], A7\n"
" ldw .d2t1 *+B15[3], A8\n"
" ldw .d2t1 *+B15[4], A9\n"
" ldw .d2t2 *+B15[5], B4\n"
" ldw .d2t2 *+B15[6], B5\n"
" ldw .d2t2 *+B15[7], B6\n"
" ldw .d2t2 *+B15[8], B7\n"
" ldw .d2t2 *+B15[9], B8\n"
" ldw .d2t2 *++B15[10], B9\n"
" b .s2 _Unwind_Resume\n"
" nop 5\n");
#else
// Assembly wrapper to call __gnu_end_cleanup without clobbering r1-r3.
// Also push r4 to preserve stack alignment.
#ifdef __thumb__
asm (" .pushsection .text.__cxa_end_cleanup\n"
" .global __cxa_end_cleanup\n"
" .type __cxa_end_cleanup, \"function\"\n"
" .thumb_func\n"
"__cxa_end_cleanup:\n"
" push\t{r1, r2, r3, r4}\n"
" bl\t__gnu_end_cleanup\n"
" pop\t{r1, r2, r3, r4}\n"
" bl\t_Unwind_Resume @ Never returns\n"
" .popsection\n");
#else
asm (" .pushsection .text.__cxa_end_cleanup\n"
" .global __cxa_end_cleanup\n"
" .type __cxa_end_cleanup, \"function\"\n"
"__cxa_end_cleanup:\n"
" stmfd\tsp!, {r1, r2, r3, r4}\n"
" bl\t__gnu_end_cleanup\n"
" ldmfd\tsp!, {r1, r2, r3, r4}\n"
" bl\t_Unwind_Resume @ Never returns\n"
" .popsection\n");
#endif
#endif
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_aux_runtime.cc
0,0 → 1,38
// -*- C++ -*- Common throw conditions.
// Copyright (C) 1994-2013 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 "exception"
#include <cstdlib>
#include "unwind-cxx.h"
#include <bits/exception_defines.h>
 
extern "C" void
__cxxabiv1::__cxa_bad_cast ()
{ _GLIBCXX_THROW_OR_ABORT(std::bad_cast()); }
 
extern "C" void
__cxxabiv1::__cxa_bad_typeid ()
{ _GLIBCXX_THROW_OR_ABORT(std::bad_typeid()); }
 
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_call.cc
0,0 → 1,157
// -*- C++ -*- Helpers for calling unextected and terminate
// Copyright (C) 2001-2013 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
 
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
 
#include <bits/c++config.h>
#include <cstdlib>
#include <bits/exception_defines.h>
#include "unwind-cxx.h"
 
using namespace __cxxabiv1;
 
#include "unwind-pe.h"
 
 
// Helper routine for when the exception handling code needs to call
// terminate.
 
extern "C" void
__cxa_call_terminate(_Unwind_Exception* ue_header) throw ()
{
 
if (ue_header)
{
// terminate is classed as a catch handler.
__cxa_begin_catch(ue_header);
 
// Call the terminate handler that was in effect when we threw this
// exception. */
if (__is_gxx_exception_class(ue_header->exception_class))
{
__cxa_exception* xh;
 
xh = __get_exception_header_from_ue(ue_header);
__terminate(xh->terminateHandler);
}
}
/* Call the global routine if we don't have anything better. */
std::terminate();
}
 
 
#ifdef __ARM_EABI_UNWINDER__
// The ARM EABI __cxa_call_unexpected has the same semantics as the generic
// routine, but the exception specification has a different format.
extern "C" void
__cxa_call_unexpected(void* exc_obj_in)
{
_Unwind_Exception* exc_obj
= reinterpret_cast<_Unwind_Exception*>(exc_obj_in);
 
int rtti_count = 0;
_Unwind_Word rtti_stride = 0;
_Unwind_Word* rtti_list = NULL;
_Unwind_Ptr rtti_base = 0;
bool foreign_exception;
std::unexpected_handler unexpectedHandler = NULL;
std::terminate_handler terminateHandler = NULL;
__cxa_exception* xh;
if (__is_gxx_exception_class(exc_obj->exception_class))
{
// Save data from the EO, which may be clobbered by _cxa_begin_catch.
xh = __get_exception_header_from_ue(exc_obj);
unexpectedHandler = xh->unexpectedHandler;
terminateHandler = xh->terminateHandler;
rtti_count = exc_obj->barrier_cache.bitpattern[1];
rtti_base = (_Unwind_Ptr) exc_obj->barrier_cache.bitpattern[2];
rtti_stride = exc_obj->barrier_cache.bitpattern[3];
rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4];
foreign_exception = false;
}
else
foreign_exception = true;
 
/* This must be called after extracting data from the EO, but before
calling unexpected(). */
__cxa_begin_catch(exc_obj);
 
// This function is a handler for our exception argument. If we exit
// by throwing a different exception, we'll need the original cleaned up.
struct end_catch_protect
{
end_catch_protect() { }
~end_catch_protect() { __cxa_end_catch(); }
} end_catch_protect_obj;
 
 
__try
{
if (foreign_exception)
std::unexpected();
else
__unexpected(unexpectedHandler);
}
__catch(...)
{
/* See if the new exception matches the rtti list. */
if (foreign_exception)
std::terminate();
 
// Get the exception thrown from unexpected.
 
__cxa_eh_globals* globals = __cxa_get_globals_fast();
__cxa_exception* new_xh = globals->caughtExceptions;
void* new_ptr = __get_object_from_ambiguous_exception (new_xh);
const std::type_info* catch_type;
int n;
bool bad_exception_allowed = false;
const std::type_info& bad_exc = typeid(std::bad_exception);
 
// Check the new exception against the rtti list
for (n = 0; n < rtti_count; n++)
{
_Unwind_Word offset;
 
offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)];
offset = _Unwind_decode_typeinfo_ptr(rtti_base, offset);
catch_type = (const std::type_info*) (offset);
 
if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false,
&new_ptr) != ctm_failed)
__throw_exception_again;
 
if (catch_type->__do_catch(&bad_exc, 0, 1))
bad_exception_allowed = true;
}
 
// If the exception spec allows std::bad_exception, throw that.
#ifdef __EXCEPTIONS
if (bad_exception_allowed)
throw std::bad_exception();
#endif
 
// Otherwise, die.
__terminate(terminateHandler);
}
}
#endif // __ARM_EABI_UNWINDER__
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_catch.cc
0,0 → 1,141
// -*- C++ -*- Exception handling routines for catching.
// Copyright (C) 2001-2013 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);
 
PROBE2 (catch, objectp, header->exceptionType);
 
#ifdef __ARM_EABI_UNWINDER__
_Unwind_Complete(exceptionObject);
#endif
return objectp;
}
 
 
extern "C" void
__cxxabiv1::__cxa_end_catch ()
{
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
__cxa_exception *header = globals->caughtExceptions;
 
// A rethrow of a foreign exception will be removed from the
// the exception stack immediately by __cxa_rethrow.
if (!header)
return;
 
// A foreign exception couldn't have been stacked (see above),
// so by definition processing must be complete.
if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
{
globals->caughtExceptions = 0;
_Unwind_DeleteException (&header->unwindHeader);
return;
}
 
int count = header->handlerCount;
if (count < 0)
{
// This exception was rethrown. Decrement the (inverted) catch
// count and remove it from the chain when it reaches zero.
if (++count == 0)
globals->caughtExceptions = header->nextException;
}
else if (--count == 0)
{
// Handling for this exception is complete. Destroy the object.
globals->caughtExceptions = header->nextException;
_Unwind_DeleteException (&header->unwindHeader);
return;
}
else if (count < 0)
// A bug in the exception handling library or compiler.
std::terminate ();
 
header->handlerCount = count;
}
 
 
bool
std::uncaught_exception() throw()
{
__cxa_eh_globals *globals = __cxa_get_globals ();
return globals->uncaughtExceptions != 0;
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_exception.cc
0,0 → 1,50
// -*- C++ -*- std::exception implementation.
// Copyright (C) 1994-2013 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 "exception"
#include <cxxabi.h>
 
std::exception::~exception() _GLIBCXX_USE_NOEXCEPT { }
 
std::bad_exception::~bad_exception() _GLIBCXX_USE_NOEXCEPT { }
 
abi::__forced_unwind::~__forced_unwind() throw() { }
 
abi::__foreign_exception::~__foreign_exception() throw() { }
 
const char*
std::exception::what() const _GLIBCXX_USE_NOEXCEPT
{
// NB: Another elegant option would be returning typeid(*this).name()
// and not overriding what() in bad_exception, bad_alloc, etc. In
// that case, however, mangled names would be returned, PR 14493.
return "std::exception";
}
 
const char*
std::bad_exception::what() const _GLIBCXX_USE_NOEXCEPT
{
return "std::bad_exception";
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_globals.cc
0,0 → 1,159
// -*- C++ -*- Manage the thread-local exception globals.
// Copyright (C) 2001-2013 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
 
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
 
#include <bits/c++config.h>
#include <exception>
#include <cstdlib>
#include "cxxabi.h"
#include "unwind-cxx.h"
#include "bits/gthr.h"
 
#if _GLIBCXX_HOSTED
using std::free;
using std::malloc;
#else
// In a freestanding environment, these functions may not be
// available -- but for now, we assume that they are.
extern "C" void *malloc (std::size_t);
extern "C" void free(void *);
#endif
 
using namespace __cxxabiv1;
 
#if _GLIBCXX_HAVE_TLS
 
namespace
{
abi::__cxa_eh_globals*
get_global() _GLIBCXX_NOTHROW
{
static __thread abi::__cxa_eh_globals global;
return &global;
}
} // anonymous namespace
 
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
{ return get_global(); }
 
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
{ return get_global(); }
 
 
#else
 
// Single-threaded fallback buffer.
static __cxa_eh_globals eh_globals;
 
#if __GTHREADS
 
static void
eh_globals_dtor(void* ptr)
{
if (ptr)
{
__cxa_eh_globals* g = reinterpret_cast<__cxa_eh_globals*>(ptr);
__cxa_exception* exn = g->caughtExceptions;
__cxa_exception* next;
while (exn)
{
next = exn->nextException;
_Unwind_DeleteException(&exn->unwindHeader);
exn = next;
}
free(ptr);
}
}
 
struct __eh_globals_init
{
__gthread_key_t _M_key;
bool _M_init;
 
__eh_globals_init() : _M_init(false)
{
if (__gthread_active_p())
_M_init = __gthread_key_create(&_M_key, eh_globals_dtor) == 0;
}
 
~__eh_globals_init()
{
if (_M_init)
__gthread_key_delete(_M_key);
_M_init = false;
}
};
 
static __eh_globals_init init;
 
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
{
__cxa_eh_globals* g;
if (init._M_init)
g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key));
else
g = &eh_globals;
return g;
}
 
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
{
__cxa_eh_globals* g;
if (init._M_init)
{
g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key));
if (!g)
{
void* v = malloc(sizeof(__cxa_eh_globals));
if (v == 0 || __gthread_setspecific(init._M_key, v) != 0)
std::terminate();
g = static_cast<__cxa_eh_globals*>(v);
g->caughtExceptions = 0;
g->uncaughtExceptions = 0;
#ifdef __ARM_EABI_UNWINDER__
g->propagatingExceptions = 0;
#endif
}
}
else
g = &eh_globals;
return g;
}
 
#else
 
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
{ return &eh_globals; }
 
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
{ return &eh_globals; }
 
#endif
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_personality.cc
0,0 → 1,797
// -*- C++ -*- The GNU C++ exception personality routine.
// Copyright (C) 2001-2013 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
#elif defined(__SEH__) && !defined (_GLIBCXX_SJLJ_EXCEPTIONS)
#define PERSONALITY_FUNCTION __gxx_personality_imp
#else
#define PERSONALITY_FUNCTION __gxx_personality_v0
#endif
 
#if defined (__SEH__) && !defined (_GLIBCXX_SJLJ_EXCEPTIONS)
static
#else
extern "C"
#endif
_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
 
#if defined (__SEH__) && !defined (_GLIBCXX_SJLJ_EXCEPTIONS)
extern "C"
EXCEPTION_DISPOSITION
__gxx_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
{
return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
ms_disp, __gxx_personality_imp);
}
#endif /* SEH */
 
} // namespace __cxxabiv1
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_ptr.cc
0,0 → 1,233
// -*- C++ -*- Implement the members of exception_ptr.
// Copyright (C) 2008-2013 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 <bits/atomic_lockfree_defines.h>
 
#if ATOMIC_INT_LOCK_FREE > 1
 
#define _GLIBCXX_EH_PTR_COMPAT
 
#include <exception>
#include <bits/exception_ptr.h>
#include "unwind-cxx.h"
 
using namespace __cxxabiv1;
 
std::__exception_ptr::exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
: _M_exception_object(0) { }
 
 
std::__exception_ptr::exception_ptr::exception_ptr(void* obj)
_GLIBCXX_USE_NOEXCEPT
: _M_exception_object(obj) { _M_addref(); }
 
 
std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool)
_GLIBCXX_USE_NOEXCEPT
: _M_exception_object(0) { }
 
 
std::__exception_ptr::
exception_ptr::exception_ptr(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT
: _M_exception_object(other._M_exception_object)
{ _M_addref(); }
 
 
std::__exception_ptr::exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
{ _M_release(); }
 
 
std::__exception_ptr::exception_ptr&
std::__exception_ptr::
exception_ptr::operator=(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT
{
exception_ptr(other).swap(*this);
return *this;
}
 
 
void
std::__exception_ptr::exception_ptr::_M_addref() _GLIBCXX_USE_NOEXCEPT
{
if (_M_exception_object)
{
__cxa_refcounted_exception *eh =
__get_refcounted_exception_header_from_obj (_M_exception_object);
__atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL);
}
}
 
 
void
std::__exception_ptr::exception_ptr::_M_release() _GLIBCXX_USE_NOEXCEPT
{
if (_M_exception_object)
{
__cxa_refcounted_exception *eh =
__get_refcounted_exception_header_from_obj (_M_exception_object);
if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
{
if (eh->exc.exceptionDestructor)
eh->exc.exceptionDestructor (_M_exception_object);
 
__cxa_free_exception (_M_exception_object);
_M_exception_object = 0;
}
}
}
 
 
void*
std::__exception_ptr::exception_ptr::_M_get() const _GLIBCXX_USE_NOEXCEPT
{ return _M_exception_object; }
 
 
void
std::__exception_ptr::exception_ptr::swap(exception_ptr &other)
_GLIBCXX_USE_NOEXCEPT
{
void *tmp = _M_exception_object;
_M_exception_object = other._M_exception_object;
other._M_exception_object = tmp;
}
 
 
// Retained for compatibility with CXXABI_1.3.
void
std::__exception_ptr::exception_ptr::_M_safe_bool_dummy()
_GLIBCXX_USE_NOEXCEPT { }
 
 
// Retained for compatibility with CXXABI_1.3.
bool
std::__exception_ptr::exception_ptr::operator!() const _GLIBCXX_USE_NOEXCEPT
{ return _M_exception_object == 0; }
 
 
// Retained for compatibility with CXXABI_1.3.
std::__exception_ptr::exception_ptr::operator __safe_bool() const
_GLIBCXX_USE_NOEXCEPT
{
return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
}
 
 
const std::type_info*
std::__exception_ptr::exception_ptr::__cxa_exception_type() const
_GLIBCXX_USE_NOEXCEPT
{
__cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object);
return eh->exceptionType;
}
 
 
bool std::__exception_ptr::operator==(const exception_ptr& lhs,
const exception_ptr& rhs)
_GLIBCXX_USE_NOEXCEPT
{ return lhs._M_exception_object == rhs._M_exception_object; }
 
 
bool std::__exception_ptr::operator!=(const exception_ptr& lhs,
const exception_ptr& rhs)
_GLIBCXX_USE_NOEXCEPT
{ return !(lhs == rhs);}
 
 
std::exception_ptr
std::current_exception() _GLIBCXX_USE_NOEXCEPT
{
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
 
if (!header)
return std::exception_ptr();
 
// Since foreign exceptions can't be counted, we can't return them.
if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
return std::exception_ptr();
 
return std::exception_ptr(
__get_object_from_ambiguous_exception (header));
}
 
 
static void
__gxx_dependent_exception_cleanup(_Unwind_Reason_Code code,
_Unwind_Exception *exc)
{
// This cleanup is set only for dependents.
__cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
__cxa_refcounted_exception *header =
__get_refcounted_exception_header_from_obj (dep->primaryException);
 
// 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);
 
__cxa_free_dependent_exception (dep);
 
if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
{
if (header->exc.exceptionDestructor)
header->exc.exceptionDestructor (header + 1);
 
__cxa_free_exception (header + 1);
}
}
 
 
void
std::rethrow_exception(std::exception_ptr ep)
{
void *obj = ep._M_get();
__cxa_refcounted_exception *eh
= __get_refcounted_exception_header_from_obj (obj);
 
__cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
dep->primaryException = obj;
__atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL);
 
dep->unexpectedHandler = __unexpected_handler;
dep->terminateHandler = __terminate_handler;
__GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class);
dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup;
 
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
_Unwind_SjLj_RaiseException (&dep->unwindHeader);
#else
_Unwind_RaiseException (&dep->unwindHeader);
#endif
 
// Some sort of unwinding error. Note that terminate is a handler.
__cxa_begin_catch (&dep->unwindHeader);
std::terminate();
}
 
#undef _GLIBCXX_EH_PTR_COMPAT
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_term_handler.cc
0,0 → 1,44
// -*- C++ -*- std::terminate handler
// Copyright (C) 2002-2013 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"
 
/* 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 configuring GCC with
--disable-libstdcxx-verbose and rebuilding the library.
In a freestanding environment, we default to this latter approach. */
 
#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE
/* The current installed user handler. */
std::terminate_handler __cxxabiv1::__terminate_handler =
__gnu_cxx::__verbose_terminate_handler;
#else
# include <cstdlib>
/* The current installed user handler. */
std::terminate_handler __cxxabiv1::__terminate_handler = std::abort;
#endif
 
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_terminate.cc
0,0 → 1,78
// -*- C++ -*- std::terminate, std::unexpected and friends.
// Copyright (C) 1994-2013 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 "exception"
#include <cstdlib>
#include "unwind-cxx.h"
#include <bits/exception_defines.h>
 
using namespace __cxxabiv1;
 
void
__cxxabiv1::__terminate (std::terminate_handler handler) throw ()
{
__try
{
handler ();
std::abort ();
}
__catch(...)
{ std::abort (); }
}
 
void
std::terminate () throw()
{
__terminate (__terminate_handler);
}
 
void
__cxxabiv1::__unexpected (std::unexpected_handler handler)
{
handler();
std::terminate ();
}
 
void
std::unexpected ()
{
__unexpected (__unexpected_handler);
}
 
std::terminate_handler
std::set_terminate (std::terminate_handler func) throw()
{
std::terminate_handler old = __terminate_handler;
__terminate_handler = func;
return old;
}
 
std::unexpected_handler
std::set_unexpected (std::unexpected_handler func) throw()
{
std::unexpected_handler old = __unexpected_handler;
__unexpected_handler = func;
return old;
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_throw.cc
0,0 → 1,123
// -*- C++ -*- Exception handling routines for throwing.
// Copyright (C) 2001-2013 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 *))
{
PROBE2 (throw, obj, tinfo);
 
// 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;
// Only notify probe for C++ exceptions.
PROBE2 (rethrow, __get_object_from_ambiguous_exception(header),
header->exceptionType);
}
 
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
_Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
#else
#if defined(_LIBUNWIND_STD_ABI)
_Unwind_RaiseException (&header->unwindHeader);
#else
_Unwind_Resume_or_Rethrow (&header->unwindHeader);
#endif
#endif
// Some sort of unwinding error. Note that terminate is a handler.
__cxa_begin_catch (&header->unwindHeader);
}
std::terminate ();
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_tm.cc
0,0 → 1,126
// -*- C++ -*- Exception handling routines for Transactional Memory.
// Copyright (C) 2009-2013 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;
 
// Free one C++ exception.
 
static void
free_any_cxa_exception (_Unwind_Exception *eo)
{
__cxa_refcounted_exception *h
= __get_refcounted_exception_header_from_ue (eo);
 
if (__is_dependent_exception (eo->exception_class))
{
__cxa_dependent_exception *dep
= __get_dependent_exception_from_ue (eo);
 
h = __get_refcounted_exception_header_from_obj (dep->primaryException);
 
__cxa_free_dependent_exception (dep);
}
 
#if __GCC_ATOMIC_INT_LOCK_FREE > 1
if (__atomic_sub_fetch (&h->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
#endif
__cxa_free_exception (h + 1);
}
 
// Cleanup exception handling state while rolling back state for
// a software transactional memory transaction.
//
// UNTHROWN_OBJ is non-null if we've called __cxa_allocate_exception
// but not yet called __cxa_throw for it.
//
// CLEANUP_EXC is non-null if we're currently processing a cleanup
// along an exception path, but we've not caught the exception yet.
//
// CAUGHT_COUNT is the nesting depth of __cxa_begin_catch within
// the transaction; undo as if calling __cxa_end_catch that many times.
 
extern "C" void
__cxxabiv1::__cxa_tm_cleanup (void *unthrown_obj,
void *cleanup_exc,
unsigned int caught_count) throw()
{
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
 
// Handle a C++ exception not yet thrown.
if (unthrown_obj)
{
globals->uncaughtExceptions -= 1;
__cxa_free_exception (unthrown_obj);
}
 
// Handle an exception not yet caught ie. processing a cleanup
// in between the throw and the catch.
if (cleanup_exc)
{
_Unwind_Exception *eo
= reinterpret_cast <_Unwind_Exception *>(cleanup_exc);
if (__is_gxx_exception_class (eo->exception_class))
free_any_cxa_exception (eo);
else
_Unwind_DeleteException (eo);
}
 
// Do __cxa_end_catch caught_count times, but don't bother running
// the destructors for the objects involved. All of that is being
// undone by the transaction restart.
if (caught_count > 0)
{
__cxa_exception *h = globals->caughtExceptions;
 
// Rethrown foreign exceptions are removed from the stack immediately.
// We would have freed this exception via THIS_EXC above.
if (h == NULL)
return;
 
do
{
__cxa_exception *next;
_Unwind_Exception *eo = &h->unwindHeader;
 
if (__is_gxx_exception_class (eo->exception_class))
{
next = h->nextException;
free_any_cxa_exception (eo);
}
else
{
_Unwind_DeleteException (eo);
next = 0;
}
 
h = next;
}
while (--caught_count);
 
globals->caughtExceptions = h;
}
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_type.cc
0,0 → 1,54
// -*- C++ -*- Exception handling routines for catching.
// Copyright (C) 2001-2013 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
 
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
 
 
#include <typeinfo>
#include <cxxabi.h>
#include "unwind-cxx.h"
 
namespace __cxxabiv1
{
 
// Returns the type_info for the currently handled exception [15.3/8], or
// null if there is none.
extern "C"
std::type_info *__cxa_current_exception_type () _GLIBCXX_NOTHROW
{
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
if (header)
{
if (__is_dependent_exception (header->unwindHeader.exception_class))
{
__cxa_dependent_exception *de =
__get_dependent_exception_from_ue (&header->unwindHeader);
header = __get_exception_header_from_obj (de->primaryException);
}
return header->exceptionType;
}
else
return 0;
}
 
} // namespace __cxxabiv1
/contrib/sdk/sources/libstdc++-v3/libsupc++/eh_unex_handler.cc
0,0 → 1,29
// -*- C++ -*- std::unexpected handler
// Copyright (C) 2002-2013 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 "unwind-cxx.h"
 
/* The current installed user handler. */
std::unexpected_handler __cxxabiv1::__unexpected_handler = std::terminate;
 
/contrib/sdk/sources/libstdc++-v3/libsupc++/enum_type_info.cc
0,0 → 1,32
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__enum_type_info::
~__enum_type_info ()
{}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/exception
0,0 → 1,156
// Exception Handling support header for -*- C++ -*-
 
// Copyright (C) 1995-2013 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 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 (__cplusplus >= 201103L) && (ATOMIC_INT_LOCK_FREE > 1)
#include <bits/exception_ptr.h>
#include <bits/nested_exception.h>
#endif
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/exception_defines.h
0,0 → 1,45
// -fno-exceptions Support -*- C++ -*-
 
// Copyright (C) 2001-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
 
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
 
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
 
/** @file bits/exception_defines.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{exception}
*/
 
#ifndef _EXCEPTION_DEFINES_H
#define _EXCEPTION_DEFINES_H 1
 
#ifndef __EXCEPTIONS
// Iff -fno-exceptions, transform error handling code to work without it.
# define __try if (true)
# define __catch(X) if (false)
# define __throw_exception_again
#else
// Else proceed normally.
# define __try try
# define __catch(X) catch(X)
# define __throw_exception_again throw
#endif
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/exception_ptr.h
0,0 → 1,198
// Exception Handling support header (exception_ptr class) for -*- C++ -*-
 
// Copyright (C) 2008-2013 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 bits/exception_ptr.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{exception}
*/
 
#ifndef _EXCEPTION_PTR_H
#define _EXCEPTION_PTR_H
 
#pragma GCC visibility push(default)
 
#include <bits/c++config.h>
#include <bits/exception_defines.h>
 
#if ATOMIC_INT_LOCK_FREE < 2
# error This platform does not support exception propagation.
#endif
 
extern "C++" {
 
namespace std
{
class type_info;
 
/**
* @addtogroup exceptions
* @{
*/
namespace __exception_ptr
{
class exception_ptr;
}
 
using __exception_ptr::exception_ptr;
 
/** Obtain an exception_ptr to the currently handled exception. If there
* is none, or the currently handled exception is foreign, return the null
* value.
*/
exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
 
/// Throw the object pointed to by the exception_ptr.
void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
 
namespace __exception_ptr
{
/**
* @brief An opaque pointer to an arbitrary exception.
* @ingroup exceptions
*/
class exception_ptr
{
void* _M_exception_object;
 
explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT;
 
void _M_addref() _GLIBCXX_USE_NOEXCEPT;
void _M_release() _GLIBCXX_USE_NOEXCEPT;
 
void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__));
 
friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
friend void std::rethrow_exception(exception_ptr);
 
public:
exception_ptr() _GLIBCXX_USE_NOEXCEPT;
 
exception_ptr(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
 
#if __cplusplus >= 201103L
exception_ptr(nullptr_t) noexcept
: _M_exception_object(0)
{ }
 
exception_ptr(exception_ptr&& __o) noexcept
: _M_exception_object(__o._M_exception_object)
{ __o._M_exception_object = 0; }
#endif
 
#if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT)
typedef void (exception_ptr::*__safe_bool)();
 
// For construction from nullptr or 0.
exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT;
#endif
 
exception_ptr&
operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
 
#if __cplusplus >= 201103L
exception_ptr&
operator=(exception_ptr&& __o) noexcept
{
exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
return *this;
}
#endif
 
~exception_ptr() _GLIBCXX_USE_NOEXCEPT;
 
void
swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
 
#ifdef _GLIBCXX_EH_PTR_COMPAT
// Retained for compatibility with CXXABI_1.3.
void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT
__attribute__ ((__const__));
bool operator!() const _GLIBCXX_USE_NOEXCEPT
__attribute__ ((__pure__));
operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT;
#endif
 
#if __cplusplus >= 201103L
explicit operator bool() const
{ return _M_exception_object; }
#endif
 
friend bool
operator==(const exception_ptr&, const exception_ptr&)
_GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__));
 
const class std::type_info*
__cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
__attribute__ ((__pure__));
};
 
bool
operator==(const exception_ptr&, const exception_ptr&)
_GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__));
 
bool
operator!=(const exception_ptr&, const exception_ptr&)
_GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__));
 
inline void
swap(exception_ptr& __lhs, exception_ptr& __rhs)
{ __lhs.swap(__rhs); }
 
} // namespace __exception_ptr
 
 
/// Obtain an exception_ptr pointing to a copy of the supplied object.
template<typename _Ex>
exception_ptr
copy_exception(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
{
__try
{
#ifdef __EXCEPTIONS
throw __ex;
#endif
}
__catch(...)
{
return current_exception();
}
}
 
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 1130. copy_exception name misleading
/// Obtain an exception_ptr pointing to a copy of the supplied object.
template<typename _Ex>
exception_ptr
make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
{ return std::copy_exception<_Ex>(__ex); }
 
// @} group exceptions
} // namespace std
 
} // extern "C++"
 
#pragma GCC visibility pop
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/function_type_info.cc
0,0 → 1,38
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__function_type_info::
~__function_type_info ()
{}
 
bool __function_type_info::
__is_function_p () const
{
return true;
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/fundamental_type_info.cc
0,0 → 1,35
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
// This has special meaning to the compiler, and will cause it
// to emit the type_info structures for the fundamental types which are
// mandated to exist in the runtime.
__fundamental_type_info::
~__fundamental_type_info ()
{}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/gthr-default.h
0,0 → 1,772
/* Threads compatibility routines for libgcc2 and libobjc. */
/* Compile this one with gcc. */
 
/* Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2008, 2009
Free Software Foundation, Inc.
Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
 
This file is part of GCC.
 
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
 
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
 
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
 
#ifndef GCC_GTHR_WIN32_H
#define GCC_GTHR_WIN32_H
 
/* Make sure CONST_CAST2 (origin in system.h) is declared. */
#ifndef CONST_CAST2
#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
#endif
 
/* Windows32 threads specific definitions. The windows32 threading model
does not map well into pthread-inspired gcc's threading model, and so
there are caveats one needs to be aware of.
 
1. The destructor supplied to __gthread_key_create is ignored for
generic x86-win32 ports. This will certainly cause memory leaks
due to unreclaimed eh contexts (sizeof (eh_context) is at least
24 bytes for x86 currently).
 
This memory leak may be significant for long-running applications
that make heavy use of C++ EH.
 
However, Mingw runtime (version 0.3 or newer) provides a mechanism
to emulate pthreads key dtors; the runtime provides a special DLL,
linked in if -mthreads option is specified, that runs the dtors in
the reverse order of registration when each thread exits. If
-mthreads option is not given, a stub is linked in instead of the
DLL, which results in memory leak. Other x86-win32 ports can use
the same technique of course to avoid the leak.
 
2. The error codes returned are non-POSIX like, and cast into ints.
This may cause incorrect error return due to truncation values on
hw where sizeof (DWORD) > sizeof (int).
 
3. We are currently using a special mutex instead of the Critical
Sections, since Win9x does not support TryEnterCriticalSection
(while NT does).
 
The basic framework should work well enough. In the long term, GCC
needs to use Structured Exception Handling on Windows32. */
 
#define __GTHREADS 1
 
#include <errno.h>
#ifdef __MINGW32__
#include <_mingw.h>
#endif
 
#ifndef __UNUSED_PARAM
#define __UNUSED_PARAM(x) x
#endif
 
#ifdef _LIBOBJC
 
/* This is necessary to prevent windef.h (included from windows.h) from
defining its own BOOL as a typedef. */
#ifndef __OBJC__
#define __OBJC__
#endif
#include <windows.h>
/* Now undef the windows BOOL. */
#undef BOOL
 
/* Key structure for maintaining thread specific storage */
static DWORD __gthread_objc_data_tls = (DWORD) -1;
 
/* Backend initialization functions */
 
/* Initialize the threads subsystem. */
int
__gthread_objc_init_thread_system (void)
{
/* Initialize the thread storage key. */
if ((__gthread_objc_data_tls = TlsAlloc ()) != (DWORD) -1)
return 0;
else
return -1;
}
 
/* Close the threads subsystem. */
int
__gthread_objc_close_thread_system (void)
{
if (__gthread_objc_data_tls != (DWORD) -1)
TlsFree (__gthread_objc_data_tls);
return 0;
}
 
/* Backend thread functions */
 
/* Create a new thread of execution. */
objc_thread_t
__gthread_objc_thread_detach (void (*func)(void *arg), void *arg)
{
DWORD thread_id = 0;
HANDLE win32_handle;
 
if (!(win32_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) func,
arg, 0, &thread_id)))
thread_id = 0;
 
return (objc_thread_t) (INT_PTR) thread_id;
}
 
/* Set the current thread's priority. */
int
__gthread_objc_thread_set_priority (int priority)
{
int sys_priority = 0;
 
switch (priority)
{
case OBJC_THREAD_INTERACTIVE_PRIORITY:
sys_priority = THREAD_PRIORITY_NORMAL;
break;
default:
case OBJC_THREAD_BACKGROUND_PRIORITY:
sys_priority = THREAD_PRIORITY_BELOW_NORMAL;
break;
case OBJC_THREAD_LOW_PRIORITY:
sys_priority = THREAD_PRIORITY_LOWEST;
break;
}
 
/* Change priority */
if (SetThreadPriority (GetCurrentThread (), sys_priority))
return 0;
else
return -1;
}
 
/* Return the current thread's priority. */
int
__gthread_objc_thread_get_priority (void)
{
int sys_priority;
 
sys_priority = GetThreadPriority (GetCurrentThread ());
 
switch (sys_priority)
{
case THREAD_PRIORITY_HIGHEST:
case THREAD_PRIORITY_TIME_CRITICAL:
case THREAD_PRIORITY_ABOVE_NORMAL:
case THREAD_PRIORITY_NORMAL:
return OBJC_THREAD_INTERACTIVE_PRIORITY;
 
default:
case THREAD_PRIORITY_BELOW_NORMAL:
return OBJC_THREAD_BACKGROUND_PRIORITY;
 
case THREAD_PRIORITY_IDLE:
case THREAD_PRIORITY_LOWEST:
return OBJC_THREAD_LOW_PRIORITY;
}
 
/* Couldn't get priority. */
return -1;
}
 
/* Yield our process time to another thread. */
void
__gthread_objc_thread_yield (void)
{
Sleep (0);
}
 
/* Terminate the current thread. */
int
__gthread_objc_thread_exit (void)
{
/* exit the thread */
ExitThread (__objc_thread_exit_status);
 
/* Failed if we reached here */
return -1;
}
 
/* Returns an integer value which uniquely describes a thread. */
objc_thread_t
__gthread_objc_thread_id (void)
{
return (objc_thread_t) (INT_PTR) GetCurrentThreadId ();
}
 
/* Sets the thread's local storage pointer. */
int
__gthread_objc_thread_set_data (void *value)
{
if (TlsSetValue (__gthread_objc_data_tls, value))
return 0;
else
return -1;
}
 
/* Returns the thread's local storage pointer. */
void *
__gthread_objc_thread_get_data (void)
{
DWORD lasterror;
void *ptr;
 
lasterror = GetLastError ();
 
ptr = TlsGetValue (__gthread_objc_data_tls); /* Return thread data. */
 
SetLastError (lasterror);
 
return ptr;
}
 
/* Backend mutex functions */
 
/* Allocate a mutex. */
int
__gthread_objc_mutex_allocate (objc_mutex_t mutex)
{
if ((mutex->backend = (void *) CreateMutex (NULL, 0, NULL)) == NULL)
return -1;
else
return 0;
}
 
/* Deallocate a mutex. */
int
__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
{
CloseHandle ((HANDLE) (mutex->backend));
return 0;
}
 
/* Grab a lock on a mutex. */
int
__gthread_objc_mutex_lock (objc_mutex_t mutex)
{
int status;
 
status = WaitForSingleObject ((HANDLE) (mutex->backend), INFINITE);
if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
return -1;
else
return 0;
}
 
/* Try to grab a lock on a mutex. */
int
__gthread_objc_mutex_trylock (objc_mutex_t mutex)
{
int status;
 
status = WaitForSingleObject ((HANDLE) (mutex->backend), 0);
if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
return -1;
else
return 0;
}
 
/* Unlock the mutex */
int
__gthread_objc_mutex_unlock (objc_mutex_t mutex)
{
if (ReleaseMutex ((HANDLE) (mutex->backend)) == 0)
return -1;
else
return 0;
}
 
/* Backend condition mutex functions */
 
/* Allocate a condition. */
int
__gthread_objc_condition_allocate (objc_condition_t __UNUSED_PARAM(condition))
{
/* Unimplemented. */
return -1;
}
 
/* Deallocate a condition. */
int
__gthread_objc_condition_deallocate (objc_condition_t __UNUSED_PARAM(condition))
{
/* Unimplemented. */
return -1;
}
 
/* Wait on the condition */
int
__gthread_objc_condition_wait (objc_condition_t __UNUSED_PARAM(condition),
objc_mutex_t __UNUSED_PARAM(mutex))
{
/* Unimplemented. */
return -1;
}
 
/* Wake up all threads waiting on this condition. */
int
__gthread_objc_condition_broadcast (objc_condition_t __UNUSED_PARAM(condition))
{
/* Unimplemented. */
return -1;
}
 
/* Wake up one thread waiting on this condition. */
int
__gthread_objc_condition_signal (objc_condition_t __UNUSED_PARAM(condition))
{
/* Unimplemented. */
return -1;
}
 
#else /* _LIBOBJC */
 
#ifdef __cplusplus
extern "C" {
#endif
 
typedef unsigned long __gthread_key_t;
 
typedef struct {
int done;
long started;
} __gthread_once_t;
 
typedef struct {
long counter;
void *sema;
} __gthread_mutex_t;
 
typedef struct {
long counter;
long depth;
unsigned long owner;
void *sema;
} __gthread_recursive_mutex_t;
 
#define __GTHREAD_ONCE_INIT {0, -1}
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
#define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0}
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
__gthread_recursive_mutex_init_function
#define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0}
 
#if defined (_WIN32) && !defined(__CYGWIN__)
#define MINGW32_SUPPORTS_MT_EH 1
/* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero
if -mthreads option was specified, or 0 otherwise. This is to get around
the lack of weak symbols in PE-COFF. */
extern int _CRT_MT;
extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
#endif /* _WIN32 && !__CYGWIN__ */
 
/* The Windows95 kernel does not export InterlockedCompareExchange.
This provides a substitute. When building apps that reference
gthread_mutex_try_lock, the __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
macro must be defined if Windows95 is a target. Currently
gthread_mutex_try_lock is not referenced by libgcc or libstdc++. */
#ifdef __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
static inline long
__gthr_i486_lock_cmp_xchg(long *__dest, long __xchg, long __comperand)
{
long result;
__asm__ __volatile__ ("\n\
lock\n\
cmpxchg{l} {%4, %1|%1, %4}\n"
: "=a" (result), "=m" (*__dest)
: "0" (__comperand), "m" (*__dest), "r" (__xchg)
: "cc");
return result;
}
#define __GTHR_W32_InterlockedCompareExchange __gthr_i486_lock_cmp_xchg
#else /* __GTHREAD_I486_INLINE_LOCK_PRIMITIVES */
#define __GTHR_W32_InterlockedCompareExchange InterlockedCompareExchange
#endif /* __GTHREAD_I486_INLINE_LOCK_PRIMITIVES */
 
static inline int
__gthread_active_p (void)
{
#ifdef MINGW32_SUPPORTS_MT_EH
return _CRT_MT;
#else
return 1;
#endif
}
 
#if __GTHREAD_HIDE_WIN32API
 
/* The implementations are in config/i386/gthr-win32.c in libgcc.a.
Only stubs are exposed to avoid polluting the C++ namespace with
windows api definitions. */
 
extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
extern int __gthr_win32_key_delete (__gthread_key_t);
extern void * __gthr_win32_getspecific (__gthread_key_t);
extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
extern void
__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *);
extern int __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *);
extern int
__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *);
extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *);
 
static inline int
__gthread_once (__gthread_once_t *__once, void (*__func) (void))
{
if (__gthread_active_p ())
return __gthr_win32_once (__once, __func);
else
return -1;
}
 
static inline int
__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
{
return __gthr_win32_key_create (__key, __dtor);
}
 
static inline int
__gthread_key_delete (__gthread_key_t __key)
{
return __gthr_win32_key_delete (__key);
}
 
static inline void *
__gthread_getspecific (__gthread_key_t __key)
{
return __gthr_win32_getspecific (__key);
}
 
static inline int
__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
{
return __gthr_win32_setspecific (__key, __ptr);
}
 
static inline void
__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
{
__gthr_win32_mutex_init_function (__mutex);
}
 
static inline void
__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
{
__gthr_win32_mutex_destroy (__mutex);
}
 
static inline int
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthr_win32_mutex_lock (__mutex);
else
return 0;
}
 
static inline int
__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthr_win32_mutex_trylock (__mutex);
else
return 0;
}
 
static inline int
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthr_win32_mutex_unlock (__mutex);
else
return 0;
}
 
static inline void
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
{
__gthr_win32_recursive_mutex_init_function (__mutex);
}
 
static inline int
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthr_win32_recursive_mutex_lock (__mutex);
else
return 0;
}
 
static inline int
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthr_win32_recursive_mutex_trylock (__mutex);
else
return 0;
}
 
static inline int
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
return __gthr_win32_recursive_mutex_unlock (__mutex);
else
return 0;
}
 
#else /* ! __GTHREAD_HIDE_WIN32API */
 
#include <windows.h>
#include <errno.h>
 
static inline int
__gthread_once (__gthread_once_t *__once, void (*__func) (void))
{
if (! __gthread_active_p ())
return -1;
else if (__once == NULL || __func == NULL)
return EINVAL;
 
if (! __once->done)
{
if (InterlockedIncrement (&(__once->started)) == 0)
{
(*__func) ();
__once->done = TRUE;
}
else
{
/* Another thread is currently executing the code, so wait for it
to finish; yield the CPU in the meantime. If performance
does become an issue, the solution is to use an Event that
we wait on here (and set above), but that implies a place to
create the event before this routine is called. */
while (! __once->done)
Sleep (0);
}
}
 
return 0;
}
 
/* Windows32 thread local keys don't support destructors; this leads to
leaks, especially in threaded applications making extensive use of
C++ EH. Mingw uses a thread-support DLL to work-around this problem. */
static inline int
__gthread_key_create (__gthread_key_t *__key,
void (*__dtor) (void *) __attribute__((unused)))
{
int __status = 0;
DWORD __tls_index = TlsAlloc ();
if (__tls_index != 0xFFFFFFFF)
{
*__key = __tls_index;
#ifdef MINGW32_SUPPORTS_MT_EH
/* Mingw runtime will run the dtors in reverse order for each thread
when the thread exits. */
__status = __mingwthr_key_dtor (*__key, __dtor);
#endif
}
else
__status = (int) GetLastError ();
return __status;
}
 
static inline int
__gthread_key_delete (__gthread_key_t __key)
{
return (TlsFree (__key) != 0) ? 0 : (int) GetLastError ();
}
 
static inline void *
__gthread_getspecific (__gthread_key_t __key)
{
DWORD __lasterror;
void *__ptr;
 
__lasterror = GetLastError ();
 
__ptr = TlsGetValue (__key);
 
SetLastError (__lasterror);
 
return __ptr;
}
 
static inline int
__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
{
if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)) != 0)
return 0;
else
return GetLastError ();
}
 
static inline void
__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
{
__mutex->counter = -1;
__mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
}
 
static inline void
__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
{
CloseHandle ((HANDLE) __mutex->sema);
}
 
static inline int
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
{
int __status = 0;
 
if (__gthread_active_p ())
{
if (InterlockedIncrement (&__mutex->counter) == 0 ||
WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
__status = 0;
else
{
/* WaitForSingleObject returns WAIT_FAILED, and we can only do
some best-effort cleanup here. */
InterlockedDecrement (&__mutex->counter);
__status = 1;
}
}
return __status;
}
 
static inline int
__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
{
int __status = 0;
 
if (__gthread_active_p ())
{
if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
__status = 0;
else
__status = 1;
}
return __status;
}
 
static inline int
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
{
if (InterlockedDecrement (&__mutex->counter) >= 0)
return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
}
return 0;
}
 
static inline void
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
{
__mutex->counter = -1;
__mutex->depth = 0;
__mutex->owner = 0;
__mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
}
 
static inline int
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
{
DWORD __me = GetCurrentThreadId();
if (InterlockedIncrement (&__mutex->counter) == 0)
{
__mutex->depth = 1;
__mutex->owner = __me;
}
else if (__mutex->owner == __me)
{
InterlockedDecrement (&__mutex->counter);
++(__mutex->depth);
}
else if (WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
{
__mutex->depth = 1;
__mutex->owner = __me;
}
else
{
/* WaitForSingleObject returns WAIT_FAILED, and we can only do
some best-effort cleanup here. */
InterlockedDecrement (&__mutex->counter);
return 1;
}
}
return 0;
}
 
static inline int
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
{
DWORD __me = GetCurrentThreadId();
if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
{
__mutex->depth = 1;
__mutex->owner = __me;
}
else if (__mutex->owner == __me)
++(__mutex->depth);
else
return 1;
}
return 0;
}
 
static inline int
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
{
--(__mutex->depth);
if (__mutex->depth == 0)
{
__mutex->owner = 0;
 
if (InterlockedDecrement (&__mutex->counter) >= 0)
return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
}
}
return 0;
}
 
#endif /* __GTHREAD_HIDE_WIN32API */
 
#ifdef __cplusplus
}
#endif
 
#endif /* _LIBOBJC */
 
#endif /* ! GCC_GTHR_WIN32_H */
/contrib/sdk/sources/libstdc++-v3/libsupc++/gthr_mutex.c
0,0 → 1,150
#include <stdlib.h>
#include <sys/errno.h>
#include <kos32sys.h>
 
void __mutex_lock(volatile int *val);
 
static inline int tls_get(int key)
{
int val;
__asm__ __volatile__(
"movl %%fs:(%1), %0"
:"=r"(val)
:"r"(key));
 
return val;
};
 
typedef struct {
int done;
long started;
} __gthread_once_t;
 
typedef struct {
int counter;
void *sema;
} __gthread_mutex_t;
 
typedef struct {
int counter;
int depth;
unsigned long owner;
int sema;
} __gthread_recursive_mutex_t;
 
 
int
__gthr_win32_once (__gthread_once_t *once, void (*func) (void))
{
if (once == NULL || func == NULL)
return EINVAL;
 
if (! once->done)
{
if (__sync_add_and_fetch (&(once->started), 1) == 0)
{
(*func) ();
once->done = 1;
}
else
{
/* Another thread is currently executing the code, so wait for it
to finish; yield the CPU in the meantime. If performance
does become an issue, the solution is to use an Event that
we wait on here (and set above), but that implies a place to
create the event before this routine is called. */
while (! once->done)
delay(1);
}
}
return 0;
}
 
void __gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
{
mutex->counter = 0;
mutex->sema = 0;
}
 
int __gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
{
__mutex_lock(&mutex->counter);
return 0;
}
 
int
__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
{
mutex->counter = 0;
return 0;
}
 
void
__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
{
mutex->counter = -1;
mutex->depth = 0;
mutex->owner = 0;
mutex->sema = 0;
}
 
void
__gthr_win32_mutex_destroy (__gthread_mutex_t *mutex)
{ }
 
int
__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
{
int me = tls_get(0);
if ( __sync_add_and_fetch(&mutex->counter, 1) == 0)
{
mutex->depth = 1;
mutex->owner = me;
mutex->sema = 1;
}
else if (mutex->owner == me)
{
__sync_sub_and_fetch(&mutex->counter, 1);
++(mutex->depth);
}
else
{
__mutex_lock(&mutex->sema);
mutex->depth = 1;
mutex->owner = me;
}
return 0;
}
 
int
__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
{
int me = tls_get(0);
if (__sync_val_compare_and_swap (&mutex->counter, -1, 0) < 0)
{
mutex->depth = 1;
mutex->owner = me;
mutex->sema = 1;
}
else if (mutex->owner == me)
++(mutex->depth);
else
return 1;
 
return 0;
}
 
int
__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
{
--(mutex->depth);
if (mutex->depth == 0)
{
mutex->owner = 0;
 
if (__sync_sub_and_fetch (&mutex->counter, 1) >= 0)
mutex->sema = 0;
}
 
return 0;
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/guard.cc
0,0 → 1,415
// Copyright (C) 2002-2013 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
 
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
 
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
 
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
 
// Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com>
// Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com>
 
#include <bits/c++config.h>
#include <cxxabi.h>
#include <exception>
#include <new>
#include <ext/atomicity.h>
#include <ext/concurrence.h>
#if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \
&& (ATOMIC_INT_LOCK_FREE > 1) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
# include <climits>
# include <syscall.h>
# include <unistd.h>
# define _GLIBCXX_USE_FUTEX
# define _GLIBCXX_FUTEX_WAIT 0
# define _GLIBCXX_FUTEX_WAKE 1
#endif
 
// The IA64/generic ABI uses the first byte of the guard variable.
// The ARM EABI uses the least significant bit.
 
// Thread-safe static local initialization support.
#ifdef __GTHREADS
# ifndef _GLIBCXX_USE_FUTEX
namespace
{
// A single mutex controlling all static initializations.
static __gnu_cxx::__recursive_mutex* static_mutex;
 
typedef char fake_recursive_mutex[sizeof(__gnu_cxx::__recursive_mutex)]
__attribute__ ((aligned(__alignof__(__gnu_cxx::__recursive_mutex))));
fake_recursive_mutex fake_mutex;
 
static void init()
{ static_mutex = new (&fake_mutex) __gnu_cxx::__recursive_mutex(); }
 
__gnu_cxx::__recursive_mutex&
get_static_mutex()
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once(&once, init);
return *static_mutex;
}
 
// Simple wrapper for exception safety.
struct mutex_wrapper
{
bool unlock;
mutex_wrapper() : unlock(true)
{ get_static_mutex().lock(); }
 
~mutex_wrapper()
{
if (unlock)
static_mutex->unlock();
}
};
}
# endif
 
# if defined(__GTHREAD_HAS_COND) && !defined(_GLIBCXX_USE_FUTEX)
namespace
{
// A single condition variable controlling all static initializations.
static __gnu_cxx::__cond* static_cond;
 
// using a fake type to avoid initializing a static class.
typedef char fake_cond_t[sizeof(__gnu_cxx::__cond)]
__attribute__ ((aligned(__alignof__(__gnu_cxx::__cond))));
fake_cond_t fake_cond;
 
static void init_static_cond()
{ static_cond = new (&fake_cond) __gnu_cxx::__cond(); }
 
__gnu_cxx::__cond&
get_static_cond()
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once(&once, init_static_cond);
return *static_cond;
}
}
# endif
 
# ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
inline bool
__test_and_acquire (__cxxabiv1::__guard *g)
{
bool b = _GLIBCXX_GUARD_TEST (g);
_GLIBCXX_READ_MEM_BARRIER;
return b;
}
# define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
# endif
 
# ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
inline void
__set_and_release (__cxxabiv1::__guard *g)
{
_GLIBCXX_WRITE_MEM_BARRIER;
_GLIBCXX_GUARD_SET (g);
}
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
# endif
 
#else /* !__GTHREADS */
 
# undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
# undef _GLIBCXX_GUARD_SET_AND_RELEASE
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
 
#endif /* __GTHREADS */
 
//
// Here are C++ run-time routines for guarded initialization of static
// variables. There are 4 scenarios under which these routines are called:
//
// 1. Threads not supported (__GTHREADS not defined)
// 2. Threads are supported but not enabled at run-time.
// 3. Threads enabled at run-time but __gthreads_* are not fully POSIX.
// 4. Threads enabled at run-time and __gthreads_* support all POSIX threads
// primitives we need here.
//
// The old code supported scenarios 1-3 but was broken since it used a global
// mutex for all threads and had the mutex locked during the whole duration of
// initialization of a guarded static variable. The following created a
// dead-lock with the old code.
//
// Thread 1 acquires the global mutex.
// Thread 1 starts initializing static variable.
// Thread 1 creates thread 2 during initialization.
// Thread 2 attempts to acquire mutex to initialize another variable.
// Thread 2 blocks since thread 1 is locking the mutex.
// Thread 1 waits for result from thread 2 and also blocks. A deadlock.
//
// The new code here can handle this situation and thus is more robust. However,
// we need to use the POSIX thread condition variable, which is not supported
// in all platforms, notably older versions of Microsoft Windows. The gthr*.h
// headers define a symbol __GTHREAD_HAS_COND for platforms that support POSIX
// like condition variables. For platforms that do not support condition
// variables, we need to fall back to the old code.
 
// If _GLIBCXX_USE_FUTEX, no global mutex or condition variable is used,
// only atomic operations are used together with futex syscall.
// Valid values of the first integer in guard are:
// 0 No thread encountered the guarded init
// yet or it has been aborted.
// _GLIBCXX_GUARD_BIT The guarded static var has been successfully
// initialized.
// _GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized
// and no other thread is waiting for its
// initialization.
// (_GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized
// | _GLIBCXX_GUARD_WAITING_BIT) and some other threads are waiting until
// it is initialized.
 
namespace __cxxabiv1
{
#ifdef _GLIBCXX_USE_FUTEX
namespace
{
static inline int __guard_test_bit (const int __byte, const int __val)
{
union { int __i; char __c[sizeof (int)]; } __u = { 0 };
__u.__c[__byte] = __val;
return __u.__i;
}
}
#endif
 
static inline int
init_in_progress_flag(__guard* g)
{ return ((char *)g)[1]; }
 
static inline void
set_init_in_progress_flag(__guard* g, int v)
{ ((char *)g)[1] = v; }
 
static inline void
throw_recursive_init_exception()
{
#ifdef __EXCEPTIONS
throw __gnu_cxx::recursive_init_error();
#else
// Use __builtin_trap so we don't require abort().
__builtin_trap();
#endif
}
 
// acquire() is a helper function used to acquire guard if thread support is
// not compiled in or is compiled in but not enabled at run-time.
static int
acquire(__guard *g)
{
// Quit if the object is already initialized.
if (_GLIBCXX_GUARD_TEST(g))
return 0;
 
if (init_in_progress_flag(g))
throw_recursive_init_exception();
 
set_init_in_progress_flag(g, 1);
return 1;
}
 
extern "C"
int __cxa_guard_acquire (__guard *g)
{
#ifdef __GTHREADS
// If the target can reorder loads, we need to insert a read memory
// barrier so that accesses to the guarded variable happen after the
// guard test.
if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
return 0;
 
# ifdef _GLIBCXX_USE_FUTEX
// If __atomic_* and futex syscall are supported, don't use any global
// mutex.
if (__gthread_active_p ())
{
int *gi = (int *) (void *) g;
const int guard_bit = _GLIBCXX_GUARD_BIT;
const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
 
while (1)
{
int expected(0);
if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false,
__ATOMIC_ACQ_REL,
__ATOMIC_ACQUIRE))
{
// This thread should do the initialization.
return 1;
}
if (expected == guard_bit)
{
// Already initialized.
return 0;
}
 
if (expected == pending_bit)
{
// Use acquire here.
int newv = expected | waiting_bit;
if (!__atomic_compare_exchange_n(gi, &expected, newv, false,
__ATOMIC_ACQ_REL,
__ATOMIC_ACQUIRE))
{
if (expected == guard_bit)
{
// Make a thread that failed to set the
// waiting bit exit the function earlier,
// if it detects that another thread has
// successfully finished initialising.
return 0;
}
if (expected == 0)
continue;
}
expected = newv;
}
 
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, expected, 0);
}
}
# else
if (__gthread_active_p ())
{
mutex_wrapper mw;
 
while (1) // When this loop is executing, mutex is locked.
{
# ifdef __GTHREAD_HAS_COND
// The static is already initialized.
if (_GLIBCXX_GUARD_TEST(g))
return 0; // The mutex will be unlocked via wrapper
 
if (init_in_progress_flag(g))
{
// The guarded static is currently being initialized by
// another thread, so we release mutex and wait for the
// condition variable. We will lock the mutex again after
// this.
get_static_cond().wait_recursive(&get_static_mutex());
}
else
{
set_init_in_progress_flag(g, 1);
return 1; // The mutex will be unlocked via wrapper.
}
# else
// This provides compatibility with older systems not supporting
// POSIX like condition variables.
if (acquire(g))
{
mw.unlock = false;
return 1; // The mutex still locked.
}
return 0; // The mutex will be unlocked via wrapper.
# endif
}
}
# endif
#endif
 
return acquire (g);
}
 
extern "C"
void __cxa_guard_abort (__guard *g) throw ()
{
#ifdef _GLIBCXX_USE_FUTEX
// If __atomic_* and futex syscall are supported, don't use any global
// mutex.
if (__gthread_active_p ())
{
int *gi = (int *) (void *) g;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
int old = __atomic_exchange_n (gi, 0, __ATOMIC_ACQ_REL);
 
if ((old & waiting_bit) != 0)
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
return;
}
#elif defined(__GTHREAD_HAS_COND)
if (__gthread_active_p())
{
mutex_wrapper mw;
 
set_init_in_progress_flag(g, 0);
 
// If we abort, we still need to wake up all other threads waiting for
// the condition variable.
get_static_cond().broadcast();
return;
}
#endif
 
set_init_in_progress_flag(g, 0);
#if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND)
// This provides compatibility with older systems not supporting POSIX like
// condition variables.
if (__gthread_active_p ())
static_mutex->unlock();
#endif
}
 
extern "C"
void __cxa_guard_release (__guard *g) throw ()
{
#ifdef _GLIBCXX_USE_FUTEX
// If __atomic_* and futex syscall are supported, don't use any global
// mutex.
if (__gthread_active_p ())
{
int *gi = (int *) (void *) g;
const int guard_bit = _GLIBCXX_GUARD_BIT;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
int old = __atomic_exchange_n (gi, guard_bit, __ATOMIC_ACQ_REL);
 
if ((old & waiting_bit) != 0)
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
return;
}
#elif defined(__GTHREAD_HAS_COND)
if (__gthread_active_p())
{
mutex_wrapper mw;
 
set_init_in_progress_flag(g, 0);
_GLIBCXX_GUARD_SET_AND_RELEASE(g);
 
get_static_cond().broadcast();
return;
}
#endif
 
set_init_in_progress_flag(g, 0);
_GLIBCXX_GUARD_SET_AND_RELEASE (g);
 
#if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND)
// This provides compatibility with older systems not supporting POSIX like
// condition variables.
if (__gthread_active_p())
static_mutex->unlock();
#endif
}
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/guard_error.cc
0,0 → 1,31
// Copyright (C) 2011-2013 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
 
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
 
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
 
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
 
#include <bits/c++config.h>
#include <cxxabi.h>
 
namespace __gnu_cxx
{
recursive_init_error::~recursive_init_error() throw() { }
}
 
/contrib/sdk/sources/libstdc++-v3/libsupc++/hash_bytes.cc
0,0 → 1,190
// Definition of _Hash_bytes. -*- C++ -*-
 
// Copyright (C) 2010-2013 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/>.
 
// This file defines Hash_bytes, a primitive used for defining hash
// functions. Based on public domain MurmurHashUnaligned2, by Austin
// Appleby. http://murmurhash.googlepages.com/
 
// This file also defines _Fnv_hash_bytes, another primitive with
// exactly the same interface but using a different hash algorithm,
// Fowler / Noll / Vo (FNV) Hash (type FNV-1a). The Murmur hash
// function apears to be better in both speed and hash quality, and
// FNV is provided primarily for backward compatibility.
 
#include <bits/hash_bytes.h>
 
namespace
{
inline std::size_t
unaligned_load(const char* p)
{
std::size_t result;
__builtin_memcpy(&result, p, sizeof(result));
return result;
}
 
#if __SIZEOF_SIZE_T__ == 8
// Loads n bytes, where 1 <= n < 8.
inline std::size_t
load_bytes(const char* p, int n)
{
std::size_t result = 0;
--n;
do
result = (result << 8) + static_cast<unsigned char>(p[n]);
while (--n >= 0);
return result;
}
 
inline std::size_t
shift_mix(std::size_t v)
{ return v ^ (v >> 47);}
#endif
}
 
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
#if __SIZEOF_SIZE_T__ == 4
 
// Implementation of Murmur hash for 32-bit size_t.
size_t
_Hash_bytes(const void* ptr, size_t len, size_t seed)
{
const size_t m = 0x5bd1e995;
size_t hash = seed ^ len;
const char* buf = static_cast<const char*>(ptr);
 
// Mix 4 bytes at a time into the hash.
while(len >= 4)
{
size_t k = unaligned_load(buf);
k *= m;
k ^= k >> 24;
k *= m;
hash *= m;
hash ^= k;
buf += 4;
len -= 4;
}
 
// Handle the last few bytes of the input array.
switch(len)
{
case 3:
hash ^= static_cast<unsigned char>(buf[2]) << 16;
case 2:
hash ^= static_cast<unsigned char>(buf[1]) << 8;
case 1:
hash ^= static_cast<unsigned char>(buf[0]);
hash *= m;
};
 
// Do a few final mixes of the hash.
hash ^= hash >> 13;
hash *= m;
hash ^= hash >> 15;
return hash;
}
 
// Implementation of FNV hash for 32-bit size_t.
size_t
_Fnv_hash_bytes(const void* ptr, size_t len, size_t hash)
{
const char* cptr = static_cast<const char*>(ptr);
for (; len; --len)
{
hash ^= static_cast<size_t>(*cptr++);
hash *= static_cast<size_t>(16777619UL);
}
return hash;
}
 
#elif __SIZEOF_SIZE_T__ == 8
 
// Implementation of Murmur hash for 64-bit size_t.
size_t
_Hash_bytes(const void* ptr, size_t len, size_t seed)
{
static const size_t mul = (((size_t) 0xc6a4a793UL) << 32UL)
+ (size_t) 0x5bd1e995UL;
const char* const buf = static_cast<const char*>(ptr);
 
// Remove the bytes not divisible by the sizeof(size_t). This
// allows the main loop to process the data as 64-bit integers.
const int len_aligned = len & ~0x7;
const char* const end = buf + len_aligned;
size_t hash = seed ^ (len * mul);
for (const char* p = buf; p != end; p += 8)
{
const size_t data = shift_mix(unaligned_load(p) * mul) * mul;
hash ^= data;
hash *= mul;
}
if ((len & 0x7) != 0)
{
const size_t data = load_bytes(end, len & 0x7);
hash ^= data;
hash *= mul;
}
hash = shift_mix(hash) * mul;
hash = shift_mix(hash);
return hash;
}
 
// Implementation of FNV hash for 64-bit size_t.
size_t
_Fnv_hash_bytes(const void* ptr, size_t len, size_t hash)
{
const char* cptr = static_cast<const char*>(ptr);
for (; len; --len)
{
hash ^= static_cast<size_t>(*cptr++);
hash *= static_cast<size_t>(1099511628211ULL);
}
return hash;
}
 
#else
 
// Dummy hash implementation for unusual sizeof(size_t).
size_t
_Hash_bytes(const void* ptr, size_t len, size_t seed)
{
size_t hash = seed;
const char* cptr = reinterpret_cast<const char*>(ptr);
for (; len; --len)
hash = (hash * 131) + *cptr++;
return hash;
}
 
size_t
_Fnv_hash_bytes(const void* ptr, size_t len, size_t seed)
{ return _Hash_bytes(ptr, len, seed); }
 
#endif /* __SIZEOF_SIZE_T__ */
 
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
/contrib/sdk/sources/libstdc++-v3/libsupc++/hash_bytes.h
0,0 → 1,59
// Declarations for hash functions. -*- C++ -*-
 
// Copyright (C) 2010-2013 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/hash_bytes.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{functional}
*/
 
#ifndef _HASH_BYTES_H
#define _HASH_BYTES_H 1
 
#pragma GCC system_header
 
#include <bits/c++config.h>
 
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
// Hash function implementation for the nontrivial specialization.
// All of them are based on a primitive that hashes a pointer to a
// byte array. The actual hash algorithm is not guaranteed to stay
// the same from release to release -- it may be updated or tuned to
// improve hash quality or speed.
size_t
_Hash_bytes(const void* __ptr, size_t __len, size_t __seed);
 
// A similar hash primitive, using the FNV hash algorithm. This
// algorithm is guaranteed to stay the same from release to release.
// (although it might not produce the same values on different
// machines.)
size_t
_Fnv_hash_bytes(const void* __ptr, size_t __len, size_t __seed);
 
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/initializer_list
0,0 → 1,107
// std::initializer_list support -*- C++ -*-
 
// Copyright (C) 2008-2013 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
 
#if __cplusplus < 201103L
# 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 // C++11
 
#endif // _INITIALIZER_LIST
/contrib/sdk/sources/libstdc++-v3/libsupc++/nested_exception.cc
0,0 → 1,31
// Copyright (C) 2011-2013 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 <exception>
 
namespace std
{
#if ATOMIC_INT_LOCK_FREE > 1
nested_exception::~nested_exception() noexcept = default;
#endif
} // namespace std
/contrib/sdk/sources/libstdc++-v3/libsupc++/nested_exception.h
0,0 → 1,166
// Nested Exception support header (nested_exception class) for -*- C++ -*-
 
// Copyright (C) 2009-2013 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/nested_exception.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{exception}
*/
 
#ifndef _GLIBCXX_NESTED_EXCEPTION_H
#define _GLIBCXX_NESTED_EXCEPTION_H 1
 
#pragma GCC visibility push(default)
 
#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else
 
#include <bits/c++config.h>
 
#if ATOMIC_INT_LOCK_FREE < 2
# error This platform does not support exception propagation.
#endif
 
extern "C++" {
 
namespace std
{
/**
* @addtogroup exceptions
* @{
*/
 
/// Exception class with exception_ptr data member.
class nested_exception
{
exception_ptr _M_ptr;
 
public:
nested_exception() noexcept : _M_ptr(current_exception()) { }
 
nested_exception(const nested_exception&) = default;
 
nested_exception& operator=(const nested_exception&) = default;
 
virtual ~nested_exception() noexcept;
 
void
rethrow_nested() const __attribute__ ((__noreturn__))
{ rethrow_exception(_M_ptr); }
 
exception_ptr
nested_ptr() const
{ return _M_ptr; }
};
 
template<typename _Except>
struct _Nested_exception : public _Except, public nested_exception
{
explicit _Nested_exception(_Except&& __ex)
: _Except(static_cast<_Except&&>(__ex))
{ }
};
 
template<typename _Ex>
struct __get_nested_helper
{
static const nested_exception*
_S_get(const _Ex& __ex)
{ return dynamic_cast<const nested_exception*>(&__ex); }
};
 
template<typename _Ex>
struct __get_nested_helper<_Ex*>
{
static const nested_exception*
_S_get(const _Ex* __ex)
{ return dynamic_cast<const nested_exception*>(__ex); }
};
 
template<typename _Ex>
inline const nested_exception*
__get_nested_exception(const _Ex& __ex)
{ return __get_nested_helper<_Ex>::_S_get(__ex); }
 
template<typename _Ex>
void
__throw_with_nested(_Ex&&, const nested_exception* = 0)
__attribute__ ((__noreturn__));
 
template<typename _Ex>
void
__throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__));
 
// This function should never be called, but is needed to avoid a warning
// about ambiguous base classes when instantiating throw_with_nested<_Ex>()
// with a type that has an accessible nested_exception base.
template<typename _Ex>
inline void
__throw_with_nested(_Ex&& __ex, const nested_exception*)
{ throw __ex; }
 
template<typename _Ex>
inline void
__throw_with_nested(_Ex&& __ex, ...)
{ throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex)); }
template<typename _Ex>
void
throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__));
 
/// If @p __ex is derived from nested_exception, @p __ex.
/// Else, an implementation-defined object derived from both.
template<typename _Ex>
inline void
throw_with_nested(_Ex __ex)
{
if (__get_nested_exception(__ex))
throw __ex;
__throw_with_nested(static_cast<_Ex&&>(__ex), &__ex);
}
 
/// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested().
template<typename _Ex>
inline void
rethrow_if_nested(const _Ex& __ex)
{
if (const nested_exception* __nested = __get_nested_exception(__ex))
__nested->rethrow_nested();
}
 
/// Overload, See N2619
inline void
rethrow_if_nested(const nested_exception& __ex)
{ __ex.rethrow_nested(); }
 
// @} group exceptions
} // namespace std
 
} // extern "C++"
 
#endif // C++11
 
#pragma GCC visibility pop
 
#endif // _GLIBCXX_NESTED_EXCEPTION_H
/contrib/sdk/sources/libstdc++-v3/libsupc++/new
0,0 → 1,122
// The -*- C++ -*- dynamic memory management header.
 
// Copyright (C) 1994-2013 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 new
* This is a Standard C++ Library header.
*
* The header @c new defines several functions to manage dynamic memory and
* handling memory allocation errors; see
* http://gcc.gnu.org/onlinedocs/libstdc++/18_support/howto.html#4 for more.
*/
 
#ifndef _NEW
#define _NEW
 
#pragma GCC system_header
 
#include <bits/c++config.h>
#include <exception>
 
#pragma GCC visibility push(default)
 
extern "C++" {
 
namespace std
{
/**
* @brief Exception possibly thrown by @c new.
* @ingroup exceptions
*
* @c bad_alloc (or classes derived from it) is used to report allocation
* errors from the throwing forms of @c new. */
class bad_alloc : public exception
{
public:
bad_alloc() throw() { }
 
// This declaration is not useless:
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
virtual ~bad_alloc() throw();
 
// See comment in eh_exception.cc.
virtual const char* what() const throw();
};
 
struct nothrow_t { };
 
extern const nothrow_t nothrow;
 
/** If you write your own error handler to be called by @c new, it must
* be of this type. */
typedef void (*new_handler)();
 
/// Takes a replacement handler as the argument, returns the
/// previous handler.
new_handler set_new_handler(new_handler) throw();
} // namespace std
 
//@{
/** These are replaceable signatures:
* - normal single new and delete (no arguments, throw @c bad_alloc on error)
* - normal array new and delete (same)
* - @c nothrow single new and delete (take a @c nothrow argument, return
* @c NULL on error)
* - @c nothrow array new and delete (same)
*
* Placement new and delete signatures (take a memory address argument,
* does nothing) may not be replaced by a user's program.
*/
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
 
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
 
// Default placement versions of operator delete.
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
//@}
} // extern "C++"
 
#pragma GCC visibility pop
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/new_handler.cc
0,0 → 1,39
// Implementation file for the -*- C++ -*- dynamic memory management header.
 
// Copyright (C) 1996-2013 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 "new"
 
const std::nothrow_t std::nothrow = { };
 
using std::new_handler;
new_handler __new_handler;
 
new_handler
std::set_new_handler (new_handler handler) throw()
{
new_handler prev_handler = __new_handler;
__new_handler = handler;
return prev_handler;
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/new_op.cc
0,0 → 1,62
// Support routines for the -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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 "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)
_GLIBCXX_THROW_OR_ABORT(bad_alloc());
handler ();
p = (void *) malloc (sz);
}
 
return p;
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/new_opnt.cc
0,0 → 1,62
// Support routines for the -*- C++ -*- dynamic memory management.
// Copyright (C) 1997-2013 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 <bits/exception_defines.h>
#include "new"
 
using std::new_handler;
using std::bad_alloc;
 
extern "C" void *malloc (std::size_t);
extern new_handler __new_handler;
 
_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
void *p;
 
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
p = (void *) malloc (sz);
while (p == 0)
{
new_handler handler = __new_handler;
if (! handler)
return 0;
__try
{
handler ();
}
__catch(const bad_alloc&)
{
return 0;
}
 
p = (void *) malloc (sz);
}
 
return p;
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/new_opv.cc
0,0 → 1,33
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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 "new"
 
_GLIBCXX_WEAK_DEFINITION void*
operator new[] (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
return ::operator new(sz);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/new_opvnt.cc
0,0 → 1,34
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
 
// Copyright (C) 1997-2013 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 "new"
_GLIBCXX_WEAK_DEFINITION void*
operator new[] (std::size_t sz, const std::nothrow_t& nothrow)
_GLIBCXX_USE_NOEXCEPT
{
return ::operator new(sz, nothrow);
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/pbase_type_info.cc
0,0 → 1,64
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__pbase_type_info::
~__pbase_type_info ()
{}
 
bool __pbase_type_info::
__do_catch (const type_info *thr_type,
void **thr_obj,
unsigned outer) const
{
if (*this == *thr_type)
return true; // same type
 
#ifdef __GXX_RTTI
if (typeid (*this) != typeid (*thr_type))
return false; // not both same kind of pointers
#endif
if (!(outer & 1))
// We're not the same and our outer pointers are not all const qualified
// Therefore there must at least be a qualification conversion involved
// But for that to be valid, our outer pointers must be const qualified.
return false;
const __pbase_type_info *thrown_type =
static_cast <const __pbase_type_info *> (thr_type);
if (thrown_type->__flags & ~__flags)
// We're less qualified.
return false;
if (!(__flags & __const_mask))
outer &= ~1;
return __pointer_catch (thrown_type, thr_obj, outer);
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/pmem_type_info.cc
0,0 → 1,48
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__pointer_to_member_type_info::
~__pointer_to_member_type_info ()
{}
 
bool __pointer_to_member_type_info::
__pointer_catch (const __pbase_type_info *thr_type,
void **thr_obj,
unsigned outer) const
{
// This static cast is always valid, as our caller will have determined that
// thr_type is really a __pointer_to_member_type_info.
const __pointer_to_member_type_info *thrown_type =
static_cast <const __pointer_to_member_type_info *> (thr_type);
if (*__context != *thrown_type->__context)
return false; // not pointers to member of same class
return __pbase_type_info::__pointer_catch (thrown_type, thr_obj, outer);
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/pointer_type_info.cc
0,0 → 1,54
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__pointer_type_info::
~__pointer_type_info ()
{}
 
bool __pointer_type_info::
__is_pointer_p () const
{
return true;
}
 
bool __pointer_type_info::
__pointer_catch (const __pbase_type_info *thrown_type,
void **thr_obj,
unsigned outer) const
{
#ifdef __GXX_RTTI
if (outer < 2 && *__pointee == typeid (void))
{
// conversion to void
return !thrown_type->__pointee->__is_function_p ();
}
#endif
return __pbase_type_info::__pointer_catch (thrown_type, thr_obj, outer);
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/pure.cc
0,0 → 1,58
// -*- C++ -*-
// Copyright (C) 2000-2013 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>
#include "unwind-cxx.h"
 
#if _GLIBCXX_HOSTED && _GLIBCXX_VERBOSE
#ifdef _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
# define writestr(str) write(2, str, sizeof(str) - 1)
# ifdef __GNU_LIBRARY__
/* Avoid forcing the library's meaning of `write' on the user program
by using the "internal" name (for use within the library). */
/*# define write(fd, buf, n) __write((fd), (buf), (n))*/
# endif
#else
# include <cstdio>
# define writestr(str) std::fputs(str, stderr)
#endif
#else
# define writestr(str) /* Empty */
#endif
 
extern "C" void
__cxxabiv1::__cxa_pure_virtual (void)
{
writestr ("pure virtual method called\n");
std::terminate ();
}
 
extern "C" void
__cxxabiv1::__cxa_deleted_virtual (void)
{
writestr ("deleted virtual method called\n");
std::terminate ();
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/si_class_type_info.cc
0,0 → 1,84
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__si_class_type_info::
~__si_class_type_info ()
{}
 
__class_type_info::__sub_kind __si_class_type_info::
__do_find_public_src (ptrdiff_t src2dst,
const void *obj_ptr,
const __class_type_info *src_type,
const void *src_ptr) const
{
if (src_ptr == obj_ptr && *this == *src_type)
return __contained_public;
return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
}
 
bool __si_class_type_info::
__do_dyncast (ptrdiff_t src2dst,
__sub_kind access_path,
const __class_type_info *dst_type,
const void *obj_ptr,
const __class_type_info *src_type,
const void *src_ptr,
__dyncast_result &__restrict result) const
{
if (*this == *dst_type)
{
result.dst_ptr = obj_ptr;
result.whole2dst = access_path;
if (src2dst >= 0)
result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
? __contained_public : __not_contained;
else if (src2dst == -2)
result.dst2src = __not_contained;
return false;
}
if (obj_ptr == src_ptr && *this == *src_type)
{
// The src object we started from. Indicate how we are accessible from
// the most derived object.
result.whole2src = access_path;
return false;
}
return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr,
src_type, src_ptr, result);
}
 
bool __si_class_type_info::
__do_upcast (const __class_type_info *dst, const void *obj_ptr,
__upcast_result &__restrict result) const
{
if (__class_type_info::__do_upcast (dst, obj_ptr, result))
return true;
return __base_type->__do_upcast (dst, obj_ptr, result);
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/tinfo.cc
0,0 → 1,82
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
// Copyright (C) 1994-2013 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 <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 _GLIBCXX_NOEXCEPT
{
#if __GXX_MERGED_TYPEINFO_NAMES
return name () == arg.name ();
#else
/* The name() method will strip any leading '*' prefix. Therefore
take care to look at __name rather than name() when looking for
the "pointer" prefix. */
return (&arg == this)
|| (__name[0] != '*' && (__builtin_strcmp (name (), arg.name ()) == 0));
#endif
}
 
#endif
 
namespace std {
 
// return true if this is a type_info for a pointer type
bool type_info::
__is_pointer_p () const
{
return false;
}
 
// return true if this is a type_info for a function type
bool type_info::
__is_function_p () const
{
return false;
}
 
// try and catch a thrown object.
bool type_info::
__do_catch (const type_info *thr_type, void **, unsigned) const
{
return *this == *thr_type;
}
 
// upcast from this type to the target. __class_type_info will override
bool type_info::
__do_upcast (const abi::__class_type_info *, void **) const
{
return false;
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/tinfo.h
0,0 → 1,182
// RTTI support internals for -*- C++ -*-
// Copyright (C) 1994-2013 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 <cstddef>
 
// Class declarations shared between the typeinfo implementation files.
 
#include <cxxabi.h>
 
namespace __cxxabiv1 {
 
inline bool __pbase_type_info::
__pointer_catch (const __pbase_type_info *thrown_type,
void **thr_obj,
unsigned outer) const
{
return __pointee->__do_catch (thrown_type->__pointee, thr_obj, outer + 2);
}
 
namespace {
 
using namespace std;
using namespace abi;
 
// Initial part of a vtable, this structure is used with offsetof, so we don't
// have to keep alignments consistent manually.
struct vtable_prefix
{
// Offset to most derived object.
ptrdiff_t whole_object;
 
// Additional padding if necessary.
#ifdef _GLIBCXX_VTABLE_PADDING
ptrdiff_t padding1;
#endif
 
// Pointer to most derived type_info.
const __class_type_info *whole_type;
 
// Additional padding if necessary.
#ifdef _GLIBCXX_VTABLE_PADDING
ptrdiff_t padding2;
#endif
 
// What a class's vptr points to.
const void *origin;
};
 
template <typename T>
inline const T *
adjust_pointer (const void *base, ptrdiff_t offset)
{
return reinterpret_cast <const T *>
(reinterpret_cast <const char *> (base) + offset);
}
 
// ADDR is a pointer to an object. Convert it to a pointer to a base,
// using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base.
inline void const *
convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset)
{
if (is_virtual)
{
const void *vtable = *static_cast <const void *const *> (addr);
offset = *adjust_pointer<ptrdiff_t> (vtable, offset);
}
 
return adjust_pointer<void> (addr, offset);
}
 
// some predicate functions for __class_type_info::__sub_kind
inline bool contained_p (__class_type_info::__sub_kind access_path)
{
return access_path >= __class_type_info::__contained_mask;
}
inline bool public_p (__class_type_info::__sub_kind access_path)
{
return access_path & __class_type_info::__contained_public_mask;
}
inline bool virtual_p (__class_type_info::__sub_kind access_path)
{
return (access_path & __class_type_info::__contained_virtual_mask);
}
inline bool contained_public_p (__class_type_info::__sub_kind access_path)
{
return ((access_path & __class_type_info::__contained_public)
== __class_type_info::__contained_public);
}
inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path)
{
return ((access_path & __class_type_info::__contained_public)
== __class_type_info::__contained_mask);
}
inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path)
{
return ((access_path & (__class_type_info::__contained_mask
| __class_type_info::__contained_virtual_mask))
== __class_type_info::__contained_mask);
}
 
static const __class_type_info *const nonvirtual_base_type =
static_cast <const __class_type_info *> (0) + 1;
 
} // namespace
 
// __upcast_result is used to hold information during traversal of a class
// hierarchy when catch matching.
struct __class_type_info::__upcast_result
{
const void *dst_ptr; // pointer to caught object
__sub_kind part2dst; // path from current base to target
int src_details; // hints about the source type hierarchy
const __class_type_info *base_type; // where we found the target,
// if in vbase the __class_type_info of vbase
// if a non-virtual base then 1
// else NULL
__upcast_result (int d)
:dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL)
{}
};
 
// __dyncast_result is used to hold information during traversal of a class
// hierarchy when dynamic casting.
struct __class_type_info::__dyncast_result
{
const void *dst_ptr; // pointer to target object or NULL
__sub_kind whole2dst; // path from most derived object to target
__sub_kind whole2src; // path from most derived object to sub object
__sub_kind dst2src; // path from target to sub object
int whole_details; // details of the whole class hierarchy
__dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask)
:dst_ptr (NULL), whole2dst (__unknown),
whole2src (__unknown), dst2src (__unknown),
whole_details (details_)
{}
 
protected:
__dyncast_result(const __dyncast_result&);
__dyncast_result&
operator=(const __dyncast_result&);
};
 
inline __class_type_info::__sub_kind __class_type_info::
__find_public_src (ptrdiff_t src2dst,
const void *obj_ptr,
const __class_type_info *src_type,
const void *src_ptr) const
{
if (src2dst >= 0)
return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
? __contained_public : __not_contained;
if (src2dst == -2)
return __not_contained;
return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/tinfo2.cc
0,0 → 1,44
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
 
// Copyright (C) 1994-2013 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 <cstddef>
#include "tinfo.h"
 
using std::type_info;
 
#if !__GXX_TYPEINFO_EQUALITY_INLINE
 
bool
type_info::before (const type_info &arg) const _GLIBCXX_NOEXCEPT
{
#if __GXX_MERGED_TYPEINFO_NAMES
return name () < arg.name ();
#else
return (name ()[0] == '*') ? name () < arg.name ()
: __builtin_strcmp (name (), arg.name ()) < 0;
#endif
}
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/typeinfo
0,0 → 1,222
// RTTI support for -*- C++ -*-
// Copyright (C) 1994-2013 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 typeinfo
* This is a Standard C++ Library header.
*/
 
#ifndef _TYPEINFO
#define _TYPEINFO
 
#pragma GCC system_header
 
#include <exception>
#if __cplusplus >= 201103L
#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 _GLIBCXX_NOEXCEPT
{ 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 _GLIBCXX_NOEXCEPT;
bool operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT;
#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 _GLIBCXX_NOEXCEPT
{ return (__name[0] == '*' && __arg.__name[0] == '*')
? __name < __arg.__name
: __builtin_strcmp (__name, __arg.__name) < 0; }
 
bool operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT
{
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 _GLIBCXX_NOEXCEPT
{ return __name < __arg.__name; }
 
bool operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT
{ return __name == __arg.__name; }
#endif
#endif
bool operator!=(const type_info& __arg) const _GLIBCXX_NOEXCEPT
{ return !operator==(__arg); }
 
#if __cplusplus >= 201103L
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 // C++11
 
// Return true if this is a pointer type of some kind
virtual bool __is_pointer_p() const;
 
// Return true if this is a function type
virtual bool __is_function_p() const;
 
// Try and catch a thrown type. Store an adjusted pointer to the
// caught type in THR_OBJ. If THR_TYPE is not a pointer type, then
// THR_OBJ points to the thrown object. If THR_TYPE is a pointer
// type, then THR_OBJ is the pointer itself. OUTER indicates the
// number of outer pointers, and whether they were const
// qualified.
virtual bool __do_catch(const type_info *__thr_type, void **__thr_obj,
unsigned __outer) const;
 
// Internally used during catch matching
virtual bool __do_upcast(const __cxxabiv1::__class_type_info *__target,
void **__obj_ptr) const;
 
protected:
const char *__name;
explicit type_info(const char *__n): __name(__n) { }
private:
/// Assigning type_info is not supported.
type_info& operator=(const type_info&);
type_info(const type_info&);
};
 
/**
* @brief Thrown during incorrect typecasting.
* @ingroup exceptions
*
* If you attempt an invalid @c dynamic_cast expression, an instance of
* this class (or something derived from this class) is thrown. */
class bad_cast : public exception
{
public:
bad_cast() _GLIBCXX_USE_NOEXCEPT { }
 
// This declaration is not useless:
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
virtual ~bad_cast() _GLIBCXX_USE_NOEXCEPT;
 
// See comment in eh_exception.cc.
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT;
};
/**
* @brief Thrown when a NULL pointer in a @c typeid expression is used.
* @ingroup exceptions
*/
class bad_typeid : public exception
{
public:
bad_typeid () _GLIBCXX_USE_NOEXCEPT { }
 
// This declaration is not useless:
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
virtual ~bad_typeid() _GLIBCXX_USE_NOEXCEPT;
 
// See comment in eh_exception.cc.
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT;
};
} // namespace std
 
} // extern "C++"
 
#pragma GCC visibility pop
 
#endif
/contrib/sdk/sources/libstdc++-v3/libsupc++/unwind-cxx.h
0,0 → 1,394
// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
// Copyright (C) 2001-2013 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>
 
#ifdef _GLIBCXX_HAVE_SYS_SDT_H
#include <sys/sdt.h>
/* We only want to use stap probes starting with v3. Earlier versions
added too much startup cost. */
#if defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
#define PROBE2(name, arg1, arg2) STAP_PROBE2 (libstdcxx, name, arg1, arg2)
#endif
#endif
 
#ifndef PROBE2
#define PROBE2(name, arg1, arg2)
#endif
 
#pragma GCC visibility push(default)
 
namespace __cxxabiv1
{
 
// A primary C++ exception object consists of a header, which is a wrapper
// around an unwind object header with additional C++ specific information,
// followed by the exception object itself.
 
struct __cxa_exception
{
// Manage the exception object itself.
std::type_info *exceptionType;
void (_GLIBCXX_CDTOR_CALLABI *exceptionDestructor)(void *);
 
// The C++ standard has entertaining rules wrt calling set_terminate
// and set_unexpected in the middle of the exception cleanup process.
std::unexpected_handler unexpectedHandler;
std::terminate_handler terminateHandler;
 
// The caught exception stack threads through here.
__cxa_exception *nextException;
 
// How many nested handlers have caught this exception. A negated
// value is a signal that this object has been rethrown.
int handlerCount;
 
#ifdef __ARM_EABI_UNWINDER__
// Stack of exceptions in cleanups.
__cxa_exception* nextPropagatingException;
 
// The nuber of active cleanup handlers for this exception.
int propagationCount;
#else
// Cache parsed handler data from the personality routine Phase 1
// for Phase 2 and __cxa_call_unexpected.
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
_Unwind_Ptr catchTemp;
void *adjustedPtr;
#endif
 
// The generic exception header. Must be last.
_Unwind_Exception unwindHeader;
};
 
struct __cxa_refcounted_exception
{
// Manage this header.
_Atomic_word referenceCount;
// __cxa_exception must be last, and no padding can be after it.
__cxa_exception exc;
};
 
// A dependent C++ exception object consists of a wrapper around an unwind
// object header with additional C++ specific information, containing a pointer
// to a primary exception object.
 
struct __cxa_dependent_exception
{
// The primary exception this thing depends on.
void *primaryException;
 
// The C++ standard has entertaining rules wrt calling set_terminate
// and set_unexpected in the middle of the exception cleanup process.
std::unexpected_handler unexpectedHandler;
std::terminate_handler terminateHandler;
 
// The caught exception stack threads through here.
__cxa_exception *nextException;
 
// How many nested handlers have caught this exception. A negated
// value is a signal that this object has been rethrown.
int handlerCount;
 
#ifdef __ARM_EABI_UNWINDER__
// Stack of exceptions in cleanups.
__cxa_exception* nextPropagatingException;
 
// The nuber of active cleanup handlers for this exception.
int propagationCount;
#else
// Cache parsed handler data from the personality routine Phase 1
// for Phase 2 and __cxa_call_unexpected.
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
_Unwind_Ptr catchTemp;
void *adjustedPtr;
#endif
 
// The generic exception header. Must be last.
_Unwind_Exception unwindHeader;
};
 
// Each thread in a C++ program has access to a __cxa_eh_globals object.
struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
#ifdef __ARM_EABI_UNWINDER__
__cxa_exception* propagatingExceptions;
#endif
};
 
// @@@ These are not directly specified by the IA-64 C++ ABI.
 
// Handles re-checking the exception specification if unexpectedHandler
// throws, and if bad_exception needs to be thrown. Called from the
// compiler.
extern "C" void __cxa_call_unexpected (void *) __attribute__((__noreturn__));
extern "C" void __cxa_call_terminate (_Unwind_Exception*) throw ()
__attribute__((__noreturn__));
 
#ifdef __ARM_EABI_UNWINDER__
// Arm EABI specified routines.
typedef enum {
ctm_failed = 0,
ctm_succeeded = 1,
ctm_succeeded_with_ptr_to_base = 2
} __cxa_type_match_result;
extern "C" __cxa_type_match_result __cxa_type_match(_Unwind_Exception*,
const std::type_info*,
bool, void**);
extern "C" bool __cxa_begin_cleanup (_Unwind_Exception*);
extern "C" void __cxa_end_cleanup (void);
#endif
 
// Handles cleanup from transactional memory restart.
extern "C" void __cxa_tm_cleanup (void *, void *, unsigned int) throw();
 
// Invokes given handler, dying appropriately if the user handler was
// so inconsiderate as to return.
extern void __terminate(std::terminate_handler) throw ()
__attribute__((__noreturn__));
extern void __unexpected(std::unexpected_handler)
__attribute__((__noreturn__));
 
// The current installed user handlers.
extern std::terminate_handler __terminate_handler;
extern std::unexpected_handler __unexpected_handler;
 
// These are explicitly GNU C++ specific.
 
// Acquire the C++ exception header from the C++ object.
static inline __cxa_exception *
__get_exception_header_from_obj (void *ptr)
{
return reinterpret_cast<__cxa_exception *>(ptr) - 1;
}
 
// Acquire the C++ exception header from the generic exception header.
static inline __cxa_exception *
__get_exception_header_from_ue (_Unwind_Exception *exc)
{
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
}
 
// Acquire the C++ refcounted exception header from the C++ object.
static inline __cxa_refcounted_exception *
__get_refcounted_exception_header_from_obj (void *ptr)
{
return reinterpret_cast<__cxa_refcounted_exception *>(ptr) - 1;
}
 
// Acquire the C++ refcounted exception header from the generic exception
// header.
static inline __cxa_refcounted_exception *
__get_refcounted_exception_header_from_ue (_Unwind_Exception *exc)
{
return reinterpret_cast<__cxa_refcounted_exception *>(exc + 1) - 1;
}
 
static inline __cxa_dependent_exception *
__get_dependent_exception_from_ue (_Unwind_Exception *exc)
{
return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1;
}
 
#ifdef __ARM_EABI_UNWINDER__
static inline bool
__is_gxx_exception_class(_Unwind_Exception_Class c)
{
// TODO: Take advantage of the fact that c will always be word aligned.
return c[0] == 'G'
&& c[1] == 'N'
&& c[2] == 'U'
&& c[3] == 'C'
&& c[4] == 'C'
&& c[5] == '+'
&& c[6] == '+'
&& (c[7] == '\0' || c[7] == '\x01');
}
 
// Only checks for primary or dependent, but not that it is a C++ exception at
// all.
static inline bool
__is_dependent_exception(_Unwind_Exception_Class c)
{
return c[7] == '\x01';
}
 
static inline void
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(_Unwind_Exception_Class c)
{
c[0] = 'G';
c[1] = 'N';
c[2] = 'U';
c[3] = 'C';
c[4] = 'C';
c[5] = '+';
c[6] = '+';
c[7] = '\0';
}
 
static inline void
__GXX_INIT_DEPENDENT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
{
c[0] = 'G';
c[1] = 'N';
c[2] = 'U';
c[3] = 'C';
c[4] = 'C';
c[5] = '+';
c[6] = '+';
c[7] = '\x01';
}
 
static inline bool
__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
{
return c[0] == 'G'
&& c[1] == 'N'
&& c[2] == 'U'
&& c[3] == 'C'
&& c[4] == 'F'
&& c[5] == 'O'
&& c[6] == 'R'
&& c[7] == '\0';
}
 
static inline void
__GXX_INIT_FORCED_UNWIND_CLASS(_Unwind_Exception_Class c)
{
c[0] = 'G';
c[1] = 'N';
c[2] = 'U';
c[3] = 'C';
c[4] = 'F';
c[5] = 'O';
c[6] = 'R';
c[7] = '\0';
}
 
static inline void*
__gxx_caught_object(_Unwind_Exception* eo)
{
return (void*)eo->barrier_cache.bitpattern[0];
}
#else // !__ARM_EABI_UNWINDER__
// This is the primary exception class we report -- "GNUCC++\0".
const _Unwind_Exception_Class __gxx_primary_exception_class
= ((((((((_Unwind_Exception_Class) 'G'
<< 8 | (_Unwind_Exception_Class) 'N')
<< 8 | (_Unwind_Exception_Class) 'U')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '\0');
 
// This is the dependent (from std::rethrow_exception) exception class we report
// "GNUCC++\x01"
const _Unwind_Exception_Class __gxx_dependent_exception_class
= ((((((((_Unwind_Exception_Class) 'G'
<< 8 | (_Unwind_Exception_Class) 'N')
<< 8 | (_Unwind_Exception_Class) 'U')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) 'C')
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '\x01');
 
static inline bool
__is_gxx_exception_class(_Unwind_Exception_Class c)
{
return c == __gxx_primary_exception_class
|| c == __gxx_dependent_exception_class;
}
 
// Only checks for primary or dependent, but not that it is a C++ exception at
// all.
static inline bool
__is_dependent_exception(_Unwind_Exception_Class c)
{
return (c & 1);
}
 
#define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class
#define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \
c = __gxx_dependent_exception_class
 
// GNU C++ personality routine, Version 0.
extern "C" _Unwind_Reason_Code __gxx_personality_v0
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
 
// GNU C++ sjlj personality routine, Version 0.
extern "C" _Unwind_Reason_Code __gxx_personality_sj0
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
 
static inline void*
__gxx_caught_object(_Unwind_Exception* eo)
{
// Bad as it looks, this actually works for dependent exceptions too.
__cxa_exception* header = __get_exception_header_from_ue (eo);
return header->adjustedPtr;
}
#endif // !__ARM_EABI_UNWINDER__
 
static inline void*
__get_object_from_ue(_Unwind_Exception* eo) throw()
{
return __is_dependent_exception (eo->exception_class) ?
__get_dependent_exception_from_ue (eo)->primaryException :
eo + 1;
}
 
static inline void *
__get_object_from_ambiguous_exception(__cxa_exception *p_or_d) throw()
{
return __get_object_from_ue (&p_or_d->unwindHeader);
}
 
 
} /* namespace __cxxabiv1 */
 
#pragma GCC visibility pop
 
#endif // _UNWIND_CXX_H
/contrib/sdk/sources/libstdc++-v3/libsupc++/unwind-pe.h
0,0 → 1,289
/* Exception handling and frame unwind runtime interface routines.
Copyright (C) 2001, 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
 
This file is part of GCC.
 
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
 
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
 
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
 
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
 
/* @@@ Really this should be out of line, but this also causes link
compatibility problems with the base ABI. This is slightly better
than duplicating code, however. */
 
#ifndef GCC_UNWIND_PE_H
#define GCC_UNWIND_PE_H
 
/* If using C++, references to abort have to be qualified with std::. */
#if __cplusplus
#define __gxx_abort std::abort
#else
#define __gxx_abort abort
#endif
 
/* Pointer encodings, from dwarf2.h. */
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
 
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
 
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
#define DW_EH_PE_aligned 0x50
 
#define DW_EH_PE_indirect 0x80
 
#ifndef NO_SIZE_OF_ENCODED_VALUE
 
/* Given an encoding, return the number of bytes the format occupies.
This is only defined for fixed-size encodings, and so does not
include leb128. */
 
static unsigned int
size_of_encoded_value (unsigned char encoding) __attribute__ ((unused));
 
static unsigned int
size_of_encoded_value (unsigned char encoding)
{
if (encoding == DW_EH_PE_omit)
return 0;
 
switch (encoding & 0x07)
{
case DW_EH_PE_absptr:
return sizeof (void *);
case DW_EH_PE_udata2:
return 2;
case DW_EH_PE_udata4:
return 4;
case DW_EH_PE_udata8:
return 8;
}
__gxx_abort ();
}
 
#endif
 
#ifndef NO_BASE_OF_ENCODED_VALUE
 
/* Given an encoding and an _Unwind_Context, return the base to which
the encoding is relative. This base may then be passed to
read_encoded_value_with_base for use when the _Unwind_Context is
not available. */
 
static _Unwind_Ptr
base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
{
if (encoding == DW_EH_PE_omit)
return 0;
 
switch (encoding & 0x70)
{
case DW_EH_PE_absptr:
case DW_EH_PE_pcrel:
case DW_EH_PE_aligned:
return 0;
 
case DW_EH_PE_textrel:
return _Unwind_GetTextRelBase (context);
case DW_EH_PE_datarel:
return _Unwind_GetDataRelBase (context);
case DW_EH_PE_funcrel:
return _Unwind_GetRegionStart (context);
}
__gxx_abort ();
}
 
#endif
 
/* Read an unsigned leb128 value from P, store the value in VAL, return
P incremented past the value. We assume that a word is large enough to
hold any value so encoded; if it is smaller than a pointer on some target,
pointers should not be leb128 encoded on that target. */
 
static const unsigned char *
read_uleb128 (const unsigned char *p, _uleb128_t *val)
{
unsigned int shift = 0;
unsigned char byte;
_uleb128_t result;
 
result = 0;
do
{
byte = *p++;
result |= ((_uleb128_t)byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
 
*val = result;
return p;
}
 
/* Similar, but read a signed leb128 value. */
 
static const unsigned char *
read_sleb128 (const unsigned char *p, _sleb128_t *val)
{
unsigned int shift = 0;
unsigned char byte;
_uleb128_t result;
 
result = 0;
do
{
byte = *p++;
result |= ((_uleb128_t)byte & 0x7f) << shift;
shift += 7;
}
while (byte & 0x80);
 
/* Sign-extend a negative value. */
if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
result |= -(((_uleb128_t)1L) << shift);
 
*val = (_sleb128_t) result;
return p;
}
 
/* Load an encoded value from memory at P. The value is returned in VAL;
The function returns P incremented past the value. BASE is as given
by base_of_encoded_value for this encoding in the appropriate context. */
 
static const unsigned char *
read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
const unsigned char *p, _Unwind_Ptr *val)
{
union unaligned
{
void *ptr;
unsigned u2 __attribute__ ((mode (HI)));
unsigned u4 __attribute__ ((mode (SI)));
unsigned u8 __attribute__ ((mode (DI)));
signed s2 __attribute__ ((mode (HI)));
signed s4 __attribute__ ((mode (SI)));
signed s8 __attribute__ ((mode (DI)));
} __attribute__((__packed__));
 
const union unaligned *u = (const union unaligned *) p;
_Unwind_Internal_Ptr result;
 
if (encoding == DW_EH_PE_aligned)
{
_Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
a = (a + sizeof (void *) - 1) & - sizeof(void *);
result = *(_Unwind_Internal_Ptr *) a;
p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
}
else
{
switch (encoding & 0x0f)
{
case DW_EH_PE_absptr:
result = (_Unwind_Internal_Ptr) u->ptr;
p += sizeof (void *);
break;
 
case DW_EH_PE_uleb128:
{
_uleb128_t tmp;
p = read_uleb128 (p, &tmp);
result = (_Unwind_Internal_Ptr) tmp;
}
break;
 
case DW_EH_PE_sleb128:
{
_sleb128_t tmp;
p = read_sleb128 (p, &tmp);
result = (_Unwind_Internal_Ptr) tmp;
}
break;
 
case DW_EH_PE_udata2:
result = u->u2;
p += 2;
break;
case DW_EH_PE_udata4:
result = u->u4;
p += 4;
break;
case DW_EH_PE_udata8:
result = u->u8;
p += 8;
break;
 
case DW_EH_PE_sdata2:
result = u->s2;
p += 2;
break;
case DW_EH_PE_sdata4:
result = u->s4;
p += 4;
break;
case DW_EH_PE_sdata8:
result = u->s8;
p += 8;
break;
 
default:
__gxx_abort ();
}
 
if (result != 0)
{
result += ((encoding & 0x70) == DW_EH_PE_pcrel
? (_Unwind_Internal_Ptr) u : base);
if (encoding & DW_EH_PE_indirect)
result = *(_Unwind_Internal_Ptr *) result;
}
}
 
*val = result;
return p;
}
 
#ifndef NO_BASE_OF_ENCODED_VALUE
 
/* Like read_encoded_value_with_base, but get the base from the context
rather than providing it directly. */
 
static inline const unsigned char *
read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
const unsigned char *p, _Unwind_Ptr *val)
{
return read_encoded_value_with_base (encoding,
base_of_encoded_value (encoding, context),
p, val);
}
 
#endif
 
#endif /* unwind-pe.h */
/contrib/sdk/sources/libstdc++-v3/libsupc++/vec.cc
0,0 → 1,530
// New abi Support -*- C++ -*-
 
// Copyright (C) 2000-2013 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 Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
 
#include <cxxabi.h>
#include <new>
#include <exception>
#include <bits/exception_defines.h>
#include "unwind-cxx.h"
 
namespace __cxxabiv1
{
namespace
{
struct uncatch_exception
{
uncatch_exception();
~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
__cxa_exception* p;
 
private:
uncatch_exception&
operator=(const uncatch_exception&);
 
uncatch_exception(const uncatch_exception&);
};
 
uncatch_exception::uncatch_exception() : p(0)
{
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
 
p = globals->caughtExceptions;
p->handlerCount -= 1;
globals->caughtExceptions = p->nextException;
globals->uncaughtExceptions += 1;
}
 
// Compute the total size with overflow checking.
std::size_t compute_size(std::size_t element_count,
std::size_t element_size,
std::size_t padding_size)
{
if (element_size && element_count > std::size_t(-1) / element_size)
_GLIBCXX_THROW_OR_ABORT(std::bad_alloc());
std::size_t size = element_count * element_size;
if (size + padding_size < size)
_GLIBCXX_THROW_OR_ABORT(std::bad_alloc());
return size + padding_size;
}
}
 
// Allocate and construct array.
extern "C" void *
__cxa_vec_new(std::size_t element_count,
std::size_t element_size,
std::size_t padding_size,
__cxa_cdtor_type constructor,
__cxa_cdtor_type destructor)
{
return __cxa_vec_new2(element_count, element_size, padding_size,
constructor, destructor,
&operator new[], &operator delete []);
}
 
extern "C" void *
__cxa_vec_new2(std::size_t element_count,
std::size_t element_size,
std::size_t padding_size,
__cxa_cdtor_type constructor,
__cxa_cdtor_type destructor,
void *(*alloc) (std::size_t),
void (*dealloc) (void *))
{
std::size_t size
= compute_size(element_count, element_size, padding_size);
char *base = static_cast <char *> (alloc (size));
if (!base)
return base;
 
if (padding_size)
{
base += padding_size;
reinterpret_cast <std::size_t *> (base)[-1] = element_count;
#ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
reinterpret_cast <std::size_t *> (base)[-2] = element_size;
#endif
}
__try
{
__cxa_vec_ctor(base, element_count, element_size,
constructor, destructor);
}
__catch(...)
{
{
uncatch_exception ue;
// Core issue 901 will probably be resolved such that a
// deleted operator delete means not freeing memory here.
if (dealloc)
dealloc(base - padding_size);
}
__throw_exception_again;
}
return base;
}
extern "C" void *
__cxa_vec_new3(std::size_t element_count,
std::size_t element_size,
std::size_t padding_size,
__cxa_cdtor_type constructor,
__cxa_cdtor_type destructor,
void *(*alloc) (std::size_t),
void (*dealloc) (void *, std::size_t))
{
std::size_t size
= compute_size(element_count, element_size, padding_size);
char *base = static_cast<char *>(alloc (size));
if (!base)
return base;
if (padding_size)
{
base += padding_size;
reinterpret_cast<std::size_t *>(base)[-1] = element_count;
#ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
reinterpret_cast <std::size_t *> (base)[-2] = element_size;
#endif
}
__try
{
__cxa_vec_ctor(base, element_count, element_size,
constructor, destructor);
}
__catch(...)
{
{
uncatch_exception ue;
if (dealloc)
dealloc(base - padding_size, size);
}
__throw_exception_again;
}
return base;
}
// Construct array.
extern "C" __cxa_vec_ctor_return_type
__cxa_vec_ctor(void *array_address,
std::size_t element_count,
std::size_t element_size,
__cxa_cdtor_type constructor,
__cxa_cdtor_type destructor)
{
std::size_t ix = 0;
char *ptr = static_cast<char *>(array_address);
__try
{
if (constructor)
for (; ix != element_count; ix++, ptr += element_size)
constructor(ptr);
}
__catch(...)
{
{
uncatch_exception ue;
__cxa_vec_cleanup(array_address, ix, element_size, destructor);
}
__throw_exception_again;
}
_GLIBCXX_CXA_VEC_CTOR_RETURN (array_address);
}
// Construct an array by copying.
extern "C" __cxa_vec_ctor_return_type
__cxa_vec_cctor(void *dest_array,
void *src_array,
std::size_t element_count,
std::size_t element_size,
__cxa_cdtor_return_type (*constructor) (void *, void *),
__cxa_cdtor_type destructor)
{
std::size_t ix = 0;
char *dest_ptr = static_cast<char *>(dest_array);
char *src_ptr = static_cast<char *>(src_array);
__try
{
if (constructor)
for (; ix != element_count;
ix++, src_ptr += element_size, dest_ptr += element_size)
constructor(dest_ptr, src_ptr);
}
__catch(...)
{
{
uncatch_exception ue;
__cxa_vec_cleanup(dest_array, ix, element_size, destructor);
}
__throw_exception_again;
}
_GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array);
}
// Destruct array.
extern "C" void
__cxa_vec_dtor(void *array_address,
std::size_t element_count,
std::size_t element_size,
__cxa_cdtor_type destructor)
{
if (destructor)
{
char *ptr = static_cast<char *>(array_address);
std::size_t ix = element_count;
 
ptr += element_count * element_size;
 
__try
{
while (ix--)
{
ptr -= element_size;
destructor(ptr);
}
}
__catch(...)
{
{
uncatch_exception ue;
__cxa_vec_cleanup(array_address, ix, element_size, destructor);
}
__throw_exception_again;
}
}
}
 
// Destruct array as a result of throwing an exception.
// [except.ctor]/3 If a destructor called during stack unwinding
// exits with an exception, terminate is called.
extern "C" void
__cxa_vec_cleanup(void *array_address,
std::size_t element_count,
std::size_t element_size,
__cxa_cdtor_type destructor) throw()
{
if (destructor)
{
char *ptr = static_cast <char *> (array_address);
std::size_t ix = element_count;
 
ptr += element_count * element_size;
 
__try
{
while (ix--)
{
ptr -= element_size;
destructor(ptr);
}
}
__catch(...)
{
std::terminate();
}
}
}
 
// Destruct and release array.
extern "C" void
__cxa_vec_delete(void *array_address,
std::size_t element_size,
std::size_t padding_size,
__cxa_cdtor_type destructor)
{
__cxa_vec_delete2(array_address, element_size, padding_size,
destructor,
&operator delete []);
}
 
extern "C" void
__cxa_vec_delete2(void *array_address,
std::size_t element_size,
std::size_t padding_size,
__cxa_cdtor_type destructor,
void (*dealloc) (void *))
{
if (!array_address)
return;
 
char* base = static_cast<char *>(array_address);
if (padding_size)
{
std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
base -= padding_size;
__try
{
__cxa_vec_dtor(array_address, element_count, element_size,
destructor);
}
__catch(...)
{
{
uncatch_exception ue;
dealloc(base);
}
__throw_exception_again;
}
}
dealloc(base);
}
 
extern "C" void
__cxa_vec_delete3(void *array_address,
std::size_t element_size,
std::size_t padding_size,
__cxa_cdtor_type destructor,
void (*dealloc) (void *, std::size_t))
{
if (!array_address)
return;
 
char* base = static_cast <char *> (array_address);
std::size_t size = 0;
 
if (padding_size)
{
std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
base -= padding_size;
size = element_count * element_size + padding_size;
__try
{
__cxa_vec_dtor(array_address, element_count, element_size,
destructor);
}
__catch(...)
{
{
uncatch_exception ue;
dealloc(base, size);
}
__throw_exception_again;
}
}
dealloc(base, size);
}
} // namespace __cxxabiv1
 
#if defined(__arm__) && defined(__ARM_EABI__)
 
// The ARM C++ ABI requires that the library provide these additional
// helper functions. There are placed in this file, despite being
// architecture-specifier, so that the compiler can inline the __cxa
// functions into these functions as appropriate.
 
namespace __aeabiv1
{
extern "C" void *
__aeabi_vec_ctor_nocookie_nodtor (void *array_address,
abi::__cxa_cdtor_type constructor,
std::size_t element_size,
std::size_t element_count)
{
return abi::__cxa_vec_ctor (array_address, element_count, element_size,
constructor, /*destructor=*/NULL);
}
 
extern "C" void *
__aeabi_vec_ctor_cookie_nodtor (void *array_address,
abi::__cxa_cdtor_type constructor,
std::size_t element_size,
std::size_t element_count)
{
if (array_address == NULL)
return NULL;
 
array_address = reinterpret_cast<std::size_t *>(array_address) + 2;
reinterpret_cast<std::size_t *>(array_address)[-2] = element_size;
reinterpret_cast<std::size_t *>(array_address)[-1] = element_count;
return abi::__cxa_vec_ctor (array_address,
element_count, element_size,
constructor, /*destructor=*/NULL);
}
extern "C" void *
__aeabi_vec_cctor_nocookie_nodtor (void *dest_array,
void *src_array,
std::size_t element_size,
std::size_t element_count,
void *(*constructor) (void *, void *))
{
return abi::__cxa_vec_cctor (dest_array, src_array,
element_count, element_size,
constructor, NULL);
}
 
extern "C" void *
__aeabi_vec_new_cookie_noctor (std::size_t element_size,
std::size_t element_count)
{
return abi::__cxa_vec_new(element_count, element_size,
2 * sizeof (std::size_t),
/*constructor=*/NULL, /*destructor=*/NULL);
}
 
extern "C" void *
__aeabi_vec_new_nocookie (std::size_t element_size,
std::size_t element_count,
abi::__cxa_cdtor_type constructor)
{
return abi::__cxa_vec_new (element_count, element_size, 0, constructor,
NULL);
}
 
extern "C" void *
__aeabi_vec_new_cookie_nodtor (std::size_t element_size,
std::size_t element_count,
abi::__cxa_cdtor_type constructor)
{
return abi::__cxa_vec_new(element_count, element_size,
2 * sizeof (std::size_t),
constructor, NULL);
}
 
extern "C" void *
__aeabi_vec_new_cookie(std::size_t element_size,
std::size_t element_count,
abi::__cxa_cdtor_type constructor,
abi::__cxa_cdtor_type destructor)
{
return abi::__cxa_vec_new (element_count, element_size,
2 * sizeof (std::size_t),
constructor, destructor);
}
 
extern "C" void *
__aeabi_vec_dtor (void *array_address,
abi::__cxa_cdtor_type destructor,
std::size_t element_size,
std::size_t element_count)
{
abi::__cxa_vec_dtor (array_address, element_count, element_size,
destructor);
return reinterpret_cast<std::size_t*> (array_address) - 2;
}
 
extern "C" void *
__aeabi_vec_dtor_cookie (void *array_address,
abi::__cxa_cdtor_type destructor)
{
if (!array_address)
return NULL;
 
abi::__cxa_vec_dtor (array_address,
reinterpret_cast<std::size_t *>(array_address)[-1],
reinterpret_cast<std::size_t *>(array_address)[-2],
destructor);
return reinterpret_cast<std::size_t*> (array_address) - 2;
}
extern "C" void
__aeabi_vec_delete (void *array_address,
abi::__cxa_cdtor_type destructor)
{
if (!array_address)
return;
 
abi::__cxa_vec_delete (array_address,
reinterpret_cast<std::size_t *>(array_address)[-2],
2 * sizeof (std::size_t),
destructor);
}
 
extern "C" void
__aeabi_vec_delete3 (void *array_address,
abi::__cxa_cdtor_type destructor,
void (*dealloc) (void *, std::size_t))
{
if (!array_address)
return;
 
abi::__cxa_vec_delete3 (array_address,
reinterpret_cast<std::size_t *>(array_address)[-2],
2 * sizeof (std::size_t),
destructor, dealloc);
}
 
extern "C" void
__aeabi_vec_delete3_nodtor (void *array_address,
void (*dealloc) (void *, std::size_t))
{
if (!array_address)
return;
 
abi::__cxa_vec_delete3 (array_address,
reinterpret_cast<std::size_t *>(array_address)[-2],
2 * sizeof (std::size_t),
/*destructor=*/NULL, dealloc);
}
} // namespace __aeabiv1
 
#endif // defined(__arm__) && defined(__ARM_EABI__)
/contrib/sdk/sources/libstdc++-v3/libsupc++/vmi_class_type_info.cc
0,0 → 1,390
// Copyright (C) 1994-2013 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 "tinfo.h"
 
namespace __cxxabiv1 {
 
__vmi_class_type_info::
~__vmi_class_type_info ()
{}
 
__class_type_info::__sub_kind __vmi_class_type_info::
__do_find_public_src (ptrdiff_t src2dst,
const void *obj_ptr,
const __class_type_info *src_type,
const void *src_ptr) const
{
if (obj_ptr == src_ptr && *this == *src_type)
return __contained_public;
for (std::size_t i = __base_count; i--;)
{
if (!__base_info[i].__is_public_p ())
continue; // Not public, can't be here.
const void *base = obj_ptr;
ptrdiff_t offset = __base_info[i].__offset ();
bool is_virtual = __base_info[i].__is_virtual_p ();
if (is_virtual)
{
if (src2dst == -3)
continue; // Not a virtual base, so can't be here.
}
base = convert_to_base (base, is_virtual, offset);
__sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src
(src2dst, base, src_type, src_ptr);
if (contained_p (base_kind))
{
if (is_virtual)
base_kind = __sub_kind (base_kind | __contained_virtual_mask);
return base_kind;
}
}
return __not_contained;
}
 
// This is a big hairy function. Although the run-time behaviour of
// dynamic_cast is simple to describe, it gives rise to some non-obvious
// behaviour. We also desire to determine as early as possible any definite
// answer we can get. Because it is unknown what the run-time ratio of
// succeeding to failing dynamic casts is, we do not know in which direction
// to bias any optimizations. To that end we make no particular effort towards
// early fail answers or early success answers. Instead we try to minimize
// work by filling in things lazily (when we know we need the information),
// and opportunisticly take early success or failure results.
bool __vmi_class_type_info::
__do_dyncast (ptrdiff_t src2dst,
__sub_kind access_path,
const __class_type_info *dst_type,
const void *obj_ptr,
const __class_type_info *src_type,
const void *src_ptr,
__dyncast_result &__restrict result) const
{
if (result.whole_details & __flags_unknown_mask)
result.whole_details = __flags;
if (obj_ptr == src_ptr && *this == *src_type)
{
// The src object we started from. Indicate how we are accessible from
// the most derived object.
result.whole2src = access_path;
return false;
}
if (*this == *dst_type)
{
result.dst_ptr = obj_ptr;
result.whole2dst = access_path;
if (src2dst >= 0)
result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
? __contained_public : __not_contained;
else if (src2dst == -2)
result.dst2src = __not_contained;
return false;
}
 
// If src_type is a unique non-virtual base of dst_type, we have a good
// guess at the address we want, so in the first pass try skipping any
// bases which don't contain that address.
const void *dst_cand = NULL;
if (src2dst >= 0)
dst_cand = adjust_pointer<void>(src_ptr, -src2dst);
bool first_pass = true;
bool skipped = false;
 
bool result_ambig = false;
again:
for (std::size_t i = __base_count; i--;)
{
__dyncast_result result2 (result.whole_details);
void const *base = obj_ptr;
__sub_kind base_access = access_path;
ptrdiff_t offset = __base_info[i].__offset ();
bool is_virtual = __base_info[i].__is_virtual_p ();
if (is_virtual)
base_access = __sub_kind (base_access | __contained_virtual_mask);
base = convert_to_base (base, is_virtual, offset);
 
if (dst_cand)
{
bool skip_on_first_pass = base > dst_cand;
if (skip_on_first_pass == first_pass)
{
// We aren't interested in this base on this pass: either
// we're on the first pass and this base doesn't contain the
// likely address, or we're on the second pass and we checked
// this base on the first pass.
skipped = true;
continue;
}
}
 
if (!__base_info[i].__is_public_p ())
{
if (src2dst == -2 &&
!(result.whole_details
& (__non_diamond_repeat_mask | __diamond_shaped_mask)))
// The hierarchy has no duplicate bases (which might ambiguate
// things) and where we started is not a public base of what we
// want (so it cannot be a downcast). There is nothing of interest
// hiding in a non-public base.
continue;
base_access = __sub_kind (base_access & ~__contained_public_mask);
}
bool result2_ambig
= __base_info[i].__base_type->__do_dyncast (src2dst, base_access,
dst_type, base,
src_type, src_ptr, result2);
result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
if (result2.dst2src == __contained_public
|| result2.dst2src == __contained_ambig)
{
result.dst_ptr = result2.dst_ptr;
result.whole2dst = result2.whole2dst;
result.dst2src = result2.dst2src;
// Found a downcast which can't be bettered or an ambiguous downcast
// which can't be disambiguated
return result2_ambig;
}
if (!result_ambig && !result.dst_ptr)
{
// Not found anything yet.
result.dst_ptr = result2.dst_ptr;
result.whole2dst = result2.whole2dst;
result_ambig = result2_ambig;
if (result.dst_ptr && result.whole2src != __unknown
&& !(__flags & __non_diamond_repeat_mask))
// Found dst and src and we don't have repeated bases.
return result_ambig;
}
else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
{
// Found at same address, must be via virtual. Pick the most
// accessible path.
result.whole2dst =
__sub_kind (result.whole2dst | result2.whole2dst);
}
else if ((result.dst_ptr != 0 && result2.dst_ptr != 0)
|| (result.dst_ptr != 0 && result2_ambig)
|| (result2.dst_ptr != 0 && result_ambig))
{
// Found two different DST_TYPE bases, or a valid one and a set of
// ambiguous ones, must disambiguate. See whether SRC_PTR is
// contained publicly within one of the non-ambiguous choices. If it
// is in only one, then that's the choice. If it is in both, then
// we're ambiguous and fail. If it is in neither, we're ambiguous,
// but don't yet fail as we might later find a third base which does
// contain SRC_PTR.
__sub_kind new_sub_kind = result2.dst2src;
__sub_kind old_sub_kind = result.dst2src;
if (contained_p (result.whole2src)
&& (!virtual_p (result.whole2src)
|| !(result.whole_details & __diamond_shaped_mask)))
{
// We already found SRC_PTR as a base of most derived, and
// either it was non-virtual, or the whole hierarchy is
// not-diamond shaped. Therefore if it is in either choice, it
// can only be in one of them, and we will already know.
if (old_sub_kind == __unknown)
old_sub_kind = __not_contained;
if (new_sub_kind == __unknown)
new_sub_kind = __not_contained;
}
else
{
if (old_sub_kind >= __not_contained)
;// already calculated
else if (contained_p (new_sub_kind)
&& (!virtual_p (new_sub_kind)
|| !(__flags & __diamond_shaped_mask)))
// Already found inside the other choice, and it was
// non-virtual or we are not diamond shaped.
old_sub_kind = __not_contained;
else
old_sub_kind = dst_type->__find_public_src
(src2dst, result.dst_ptr, src_type, src_ptr);
if (new_sub_kind >= __not_contained)
;// already calculated
else if (contained_p (old_sub_kind)
&& (!virtual_p (old_sub_kind)
|| !(__flags & __diamond_shaped_mask)))
// Already found inside the other choice, and it was
// non-virtual or we are not diamond shaped.
new_sub_kind = __not_contained;
else
new_sub_kind = dst_type->__find_public_src
(src2dst, result2.dst_ptr, src_type, src_ptr);
}
// Neither sub_kind can be contained_ambig -- we bail out early
// when we find those.
if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
{
// Only on one choice, not ambiguous.
if (contained_p (new_sub_kind))
{
// Only in new.
result.dst_ptr = result2.dst_ptr;
result.whole2dst = result2.whole2dst;
result_ambig = false;
old_sub_kind = new_sub_kind;
}
result.dst2src = old_sub_kind;
if (public_p (result.dst2src))
return false; // Can't be an ambiguating downcast for later discovery.
if (!virtual_p (result.dst2src))
return false; // Found non-virtually can't be bettered
}
else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
{
// In both.
result.dst_ptr = NULL;
result.dst2src = __contained_ambig;
return true; // Fail.
}
else
{
// In neither publicly, ambiguous for the moment, but keep
// looking. It is possible that it was private in one or
// both and therefore we should fail, but that's just tough.
result.dst_ptr = NULL;
result.dst2src = __not_contained;
result_ambig = true;
}
}
if (result.whole2src == __contained_private)
// We found SRC_PTR as a private non-virtual base, therefore all
// cross casts will fail. We have already found a down cast, if
// there is one.
return result_ambig;
}
 
if (skipped && first_pass)
{
// We didn't find dst where we expected it, so let's go back and try
// the bases we skipped (if any).
first_pass = false;
goto again;
}
 
return result_ambig;
}
 
bool __vmi_class_type_info::
__do_upcast (const __class_type_info *dst, const void *obj_ptr,
__upcast_result &__restrict result) const
{
if (__class_type_info::__do_upcast (dst, obj_ptr, result))
return true;
int src_details = result.src_details;
if (src_details & __flags_unknown_mask)
src_details = __flags;
for (std::size_t i = __base_count; i--;)
{
__upcast_result result2 (src_details);
const void *base = obj_ptr;
ptrdiff_t offset = __base_info[i].__offset ();
bool is_virtual = __base_info[i].__is_virtual_p ();
bool is_public = __base_info[i].__is_public_p ();
if (!is_public && !(src_details & __non_diamond_repeat_mask))
// original cannot have an ambiguous base, so skip private bases
continue;
 
if (base)
base = convert_to_base (base, is_virtual, offset);
if (__base_info[i].__base_type->__do_upcast (dst, base, result2))
{
if (result2.base_type == nonvirtual_base_type && is_virtual)
result2.base_type = __base_info[i].__base_type;
if (contained_p (result2.part2dst) && !is_public)
result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
if (!result.base_type)
{
result = result2;
if (!contained_p (result.part2dst))
return true; // found ambiguously
if (result.part2dst & __contained_public_mask)
{
if (!(__flags & __non_diamond_repeat_mask))
return true; // cannot have an ambiguous other base
}
else
{
if (!virtual_p (result.part2dst))
return true; // cannot have another path
if (!(__flags & __diamond_shaped_mask))
return true; // cannot have a more accessible path
}
}
else if (result.dst_ptr != result2.dst_ptr)
{
// Found an ambiguity.
result.dst_ptr = NULL;
result.part2dst = __contained_ambig;
return true;
}
else if (result.dst_ptr)
{
// Ok, found real object via a virtual path.
result.part2dst
= __sub_kind (result.part2dst | result2.part2dst);
}
else
{
// Dealing with a null pointer, need to check vbase
// containing each of the two choices.
if (result2.base_type == nonvirtual_base_type
|| result.base_type == nonvirtual_base_type
|| !(*result2.base_type == *result.base_type))
{
// Already ambiguous, not virtual or via different virtuals.
// Cannot match.
result.part2dst = __contained_ambig;
return true;
}
result.part2dst
= __sub_kind (result.part2dst | result2.part2dst);
}
}
}
return result.part2dst != __unknown;
}
 
}
/contrib/sdk/sources/libstdc++-v3/libsupc++/vterminate.cc
0,0 → 1,101
// Verbose terminate_handler -*- C++ -*-
 
// Copyright (C) 2001-2013 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/>.
 
#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