/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/Makefile |
---|
0,0 → 1,105 |
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 |
CPPFLAGS = -fno-rtti |
ARFLAGS= crs |
INCLUDES= -I. -I../include/mingw32 -I../include -I../../newlib/libc/include -I/home/autobuild/tools/win32/include |
LIBS:= -ldll -lc.dll |
DEFINES= -DHAVE_CONFIG_H -DIN_GCC -DIN_GLIBCPP_V3 -DUSE_EMUTLS=1 -D_GLIBCXX_HAVE_TLS |
SOURCES = \ |
cp-demangle.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) $(CPPFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
eh_ptr.o: eh_ptr.cc |
$(CPP) $(CFLAGS) -std=gnu++0x $(CPPFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
eh_throw.o: eh_throw.cc |
$(CPP) $(CFLAGS) -std=gnu++0x $(CPPFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
guard.o: guard.cc |
$(CPP) $(CFLAGS) -std=gnu++0x $(CPPFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
atexit_thread.o: atexit_thread.cc |
$(CPP) $(CFLAGS) -std=gnu++0x $(CPPFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
nested_exception.o: nested_exception.cc |
$(CPP) $(CFLAGS) -std=gnu++0x $(CPPFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
clean: |
-rm -f *.o |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/array_type_info.cc |
---|
0,0 → 1,32 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/atexit_arm.cc |
---|
0,0 → 1,39 |
// Copyright (C) 2007-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/atexit_thread.cc |
---|
0,0 → 1,165 |
// Copyright (C) 2012-2015 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" |
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32 |
#define WIN32_LEAN_AND_MEAN |
#include <windows.h> |
#endif |
#if _GLIBCXX_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 /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ |
namespace { |
// One element in a singly-linked stack of cleanups. |
struct elt |
{ |
void (*destructor)(void *); |
void *object; |
elt *next; |
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32 |
HMODULE dll; |
#endif |
}; |
// 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); |
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32 |
/* Decrement DLL count */ |
if (e->dll) |
FreeLibrary (e->dll); |
#endif |
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; |
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32 |
/* Store the DLL address for a later call to FreeLibrary in new_elt and |
increment DLL load count. This blocks the unloading of the DLL |
before the thread-local dtors have been called. This does NOT help |
if FreeLibrary/dlclose is called in excess. */ |
GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, |
(LPCWSTR) dtor, &new_elt->dll); |
#endif |
if (__gthread_active_p ()) |
__gthread_setspecific (key, new_elt); |
else |
single_thread = new_elt; |
return 0; |
} |
#endif /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/atomic_lockfree_defines.h |
---|
0,0 → 1,63 |
// -*- C++ -*- header. |
// Copyright (C) 2008-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/bad_alloc.cc |
---|
0,0 → 1,34 |
// Implementation file for the -*- C++ -*- dynamic memory management header. |
// Copyright (C) 2010-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/bad_array_length.cc |
---|
0,0 → 1,57 |
// Copyright (C) 2013-2015 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> |
namespace std |
{ |
// From N3639. This was voted in and then back out of C++14, and is now |
// just here for backward link compatibility with code built with 4.9. |
class bad_array_length : public bad_alloc |
{ |
public: |
bad_array_length() throw() { }; |
// This declaration is not useless: |
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
virtual ~bad_array_length() throw(); |
// See comment in eh_exception.cc. |
virtual const char* what() const throw(); |
}; |
bad_array_length::~bad_array_length() _GLIBCXX_USE_NOEXCEPT { } |
const char* |
bad_array_length::what() const _GLIBCXX_USE_NOEXCEPT |
{ return "std::bad_array_length"; } |
} // namespace std |
namespace __cxxabiv1 { |
extern "C" void |
__cxa_throw_bad_array_length () |
{ _GLIBCXX_THROW_OR_ABORT(std::bad_array_length()); } |
} // namespace __cxxabiv1 |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/bad_array_new.cc |
---|
0,0 → 1,35 |
// Copyright (C) 2013-2015 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> |
namespace std |
{ |
bad_array_new_length::~bad_array_new_length() _GLIBCXX_USE_NOEXCEPT { } |
const char* |
bad_array_new_length::what() const _GLIBCXX_USE_NOEXCEPT |
{ return "std::bad_array_new_length"; } |
} // namespace std |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/bad_cast.cc |
---|
0,0 → 1,36 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/bad_typeid.cc |
---|
0,0 → 1,36 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/class_type_info.cc |
---|
0,0 → 1,110 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/config.h |
---|
0,0 → 1,500 |
/* config.h. Generated from config.in by configure. */ |
/* config.in. Generated from configure.ac by autoheader. */ |
/* Define if building universal (internal helper macro) */ |
/* #undef AC_APPLE_UNIVERSAL_BUILD */ |
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. |
This function is required for alloca.c support on those systems. */ |
/* #undef CRAY_STACKSEG_END */ |
/* Define to 1 if you have the <alloca.h> header file. */ |
#define HAVE_ALLOCA_H 1 |
/* Define to 1 if you have the `asprintf' function. */ |
#define HAVE_ASPRINTF 1 |
/* Define to 1 if you have the `atexit' function. */ |
#define HAVE_ATEXIT 1 |
/* Define to 1 if you have the `basename' function. */ |
#define HAVE_BASENAME 1 |
/* Define to 1 if you have the `bcmp' function. */ |
/* #undef HAVE_BCMP */ |
/* Define to 1 if you have the `bcopy' function. */ |
/* #undef HAVE_BCOPY */ |
/* Define to 1 if you have the `bsearch' function. */ |
#define HAVE_BSEARCH 1 |
/* Define to 1 if you have the `bzero' function. */ |
/* #undef HAVE_BZERO */ |
/* Define to 1 if you have the `calloc' function. */ |
#define HAVE_CALLOC 1 |
/* Define to 1 if you have the `canonicalize_file_name' function. */ |
/* #undef HAVE_CANONICALIZE_FILE_NAME */ |
/* Define to 1 if you have the `clock' function. */ |
#define HAVE_CLOCK 1 |
/* Define to 1 if you have the declaration of `asprintf', and to 0 if you |
don't. */ |
#define HAVE_DECL_ASPRINTF 0 |
/* Define to 1 if you have the declaration of `basename(char *)', and to 0 if |
you don't. */ |
#define HAVE_DECL_BASENAME 0 |
/* Define to 1 if you have the declaration of `calloc', and to 0 if you don't. |
*/ |
#define HAVE_DECL_CALLOC 1 |
/* Define to 1 if you have the declaration of `ffs', and to 0 if you don't. */ |
#define HAVE_DECL_FFS 0 |
/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't. |
*/ |
#define HAVE_DECL_GETENV 1 |
/* Define to 1 if you have the declaration of `getopt', and to 0 if you don't. |
*/ |
#define HAVE_DECL_GETOPT 1 |
/* Define to 1 if you have the declaration of `malloc', and to 0 if you don't. |
*/ |
#define HAVE_DECL_MALLOC 1 |
/* Define to 1 if you have the declaration of `realloc', and to 0 if you |
don't. */ |
#define HAVE_DECL_REALLOC 1 |
/* Define to 1 if you have the declaration of `sbrk', and to 0 if you don't. |
*/ |
#define HAVE_DECL_SBRK 0 |
/* Define to 1 if you have the declaration of `snprintf', and to 0 if you |
don't. */ |
#define HAVE_DECL_SNPRINTF 1 |
/* Define to 1 if you have the declaration of `strverscmp', and to 0 if you |
don't. */ |
#define HAVE_DECL_STRVERSCMP 0 |
/* Define to 1 if you have the declaration of `vasprintf', and to 0 if you |
don't. */ |
#define HAVE_DECL_VASPRINTF 0 |
/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you |
don't. */ |
#define HAVE_DECL_VSNPRINTF 1 |
/* Define to 1 if you have the `dup3' function. */ |
/* #undef HAVE_DUP3 */ |
/* Define to 1 if you have the <fcntl.h> header file. */ |
#define HAVE_FCNTL_H 1 |
/* Define to 1 if you have the `ffs' function. */ |
/* #undef HAVE_FFS */ |
/* Define to 1 if you have the `fork' function. */ |
/* #undef HAVE_FORK */ |
/* Define to 1 if you have the `getcwd' function. */ |
#define HAVE_GETCWD 1 |
/* Define to 1 if you have the `getpagesize' function. */ |
#define HAVE_GETPAGESIZE 1 |
/* Define to 1 if you have the `getrlimit' function. */ |
/* #undef HAVE_GETRLIMIT */ |
/* Define to 1 if you have the `getrusage' function. */ |
/* #undef HAVE_GETRUSAGE */ |
/* Define to 1 if you have the `getsysinfo' function. */ |
/* #undef HAVE_GETSYSINFO */ |
/* Define to 1 if you have the `gettimeofday' function. */ |
#define HAVE_GETTIMEOFDAY 1 |
/* Define to 1 if you have the `index' function. */ |
/* #undef HAVE_INDEX */ |
/* Define to 1 if you have the `insque' function. */ |
/* #undef HAVE_INSQUE */ |
/* Define to 1 if the system has the type `intptr_t'. */ |
#define HAVE_INTPTR_T 1 |
/* Define to 1 if you have the <inttypes.h> header file. */ |
#define HAVE_INTTYPES_H 1 |
/* Define to 1 if you have the <limits.h> header file. */ |
#define HAVE_LIMITS_H 1 |
/* Define to 1 if you have the <machine/hal_sysinfo.h> header file. */ |
/* #undef HAVE_MACHINE_HAL_SYSINFO_H */ |
/* Define to 1 if you have the <malloc.h> header file. */ |
#define HAVE_MALLOC_H 1 |
/* Define to 1 if you have the `memchr' function. */ |
#define HAVE_MEMCHR 1 |
/* Define to 1 if you have the `memcmp' function. */ |
#define HAVE_MEMCMP 1 |
/* Define to 1 if you have the `memcpy' function. */ |
#define HAVE_MEMCPY 1 |
/* Define to 1 if you have the `memmem' function. */ |
/* #undef HAVE_MEMMEM */ |
/* Define to 1 if you have the `memmove' function. */ |
#define HAVE_MEMMOVE 1 |
/* Define to 1 if you have the <memory.h> header file. */ |
#define HAVE_MEMORY_H 1 |
/* Define to 1 if you have the `memset' function. */ |
#define HAVE_MEMSET 1 |
/* Define to 1 if you have the `mkstemps' function. */ |
/* #undef HAVE_MKSTEMPS */ |
/* Define to 1 if you have a working `mmap' system call. */ |
/* #undef HAVE_MMAP */ |
/* Define to 1 if you have the `on_exit' function. */ |
/* #undef HAVE_ON_EXIT */ |
/* Define to 1 if you have the <process.h> header file. */ |
#define HAVE_PROCESS_H 1 |
/* Define to 1 if you have the `psignal' function. */ |
/* #undef HAVE_PSIGNAL */ |
/* Define to 1 if you have the `pstat_getdynamic' function. */ |
/* #undef HAVE_PSTAT_GETDYNAMIC */ |
/* Define to 1 if you have the `pstat_getstatic' function. */ |
/* #undef HAVE_PSTAT_GETSTATIC */ |
/* Define to 1 if you have the `putenv' function. */ |
#define HAVE_PUTENV 1 |
/* Define to 1 if you have the `random' function. */ |
/* #undef HAVE_RANDOM */ |
/* Define to 1 if you have the `realpath' function. */ |
/* #undef HAVE_REALPATH */ |
/* Define to 1 if you have the `rename' function. */ |
#define HAVE_RENAME 1 |
/* Define to 1 if you have the `rindex' function. */ |
/* #undef HAVE_RINDEX */ |
/* Define to 1 if you have the `sbrk' function. */ |
/* #undef HAVE_SBRK */ |
/* Define to 1 if you have the `setenv' function. */ |
/* #undef HAVE_SETENV */ |
/* Define to 1 if you have the `setproctitle' function. */ |
/* #undef HAVE_SETPROCTITLE */ |
/* Define to 1 if you have the `setrlimit' function. */ |
/* #undef HAVE_SETRLIMIT */ |
/* Define to 1 if you have the `sigsetmask' function. */ |
/* #undef HAVE_SIGSETMASK */ |
/* Define to 1 if you have the `snprintf' function. */ |
#define HAVE_SNPRINTF 1 |
/* Define to 1 if you have the `spawnve' function. */ |
#define HAVE_SPAWNVE 1 |
/* Define to 1 if you have the `spawnvpe' function. */ |
#define HAVE_SPAWNVPE 1 |
/* Define to 1 if you have the <stdint.h> header file. */ |
#define HAVE_STDINT_H 1 |
/* Define to 1 if you have the <stdio_ext.h> header file. */ |
/* #undef HAVE_STDIO_EXT_H */ |
/* Define to 1 if you have the <stdlib.h> header file. */ |
#define HAVE_STDLIB_H 1 |
/* Define to 1 if you have the `stpcpy' function. */ |
/* #undef HAVE_STPCPY */ |
/* Define to 1 if you have the `stpncpy' function. */ |
/* #undef HAVE_STPNCPY */ |
/* Define to 1 if you have the `strcasecmp' function. */ |
/* #undef HAVE_STRCASECMP */ |
/* Define to 1 if you have the `strchr' function. */ |
#define HAVE_STRCHR 1 |
/* Define to 1 if you have the `strdup' function. */ |
#define HAVE_STRDUP 1 |
/* Define to 1 if you have the `strerror' function. */ |
#define HAVE_STRERROR 1 |
/* Define to 1 if you have the <strings.h> header file. */ |
#define HAVE_STRINGS_H 1 |
/* Define to 1 if you have the <string.h> header file. */ |
#define HAVE_STRING_H 1 |
/* Define to 1 if you have the `strncasecmp' function. */ |
/* #undef HAVE_STRNCASECMP */ |
/* Define to 1 if you have the `strndup' function. */ |
/* #undef HAVE_STRNDUP */ |
/* Define to 1 if you have the `strnlen' function. */ |
/* #undef HAVE_STRNLEN */ |
/* Define to 1 if you have the `strrchr' function. */ |
#define HAVE_STRRCHR 1 |
/* Define to 1 if you have the `strsignal' function. */ |
/* #undef HAVE_STRSIGNAL */ |
/* Define to 1 if you have the `strstr' function. */ |
#define HAVE_STRSTR 1 |
/* Define to 1 if you have the `strtod' function. */ |
#define HAVE_STRTOD 1 |
/* Define to 1 if you have the `strtol' function. */ |
#define HAVE_STRTOL 1 |
/* Define to 1 if you have the `strtoul' function. */ |
#define HAVE_STRTOUL 1 |
/* Define to 1 if you have the `strverscmp' function. */ |
/* #undef HAVE_STRVERSCMP */ |
/* Define to 1 if you have the `sysconf' function. */ |
/* #undef HAVE_SYSCONF */ |
/* Define to 1 if you have the `sysctl' function. */ |
/* #undef HAVE_SYSCTL */ |
/* Define to 1 if you have the `sysmp' function. */ |
/* #undef HAVE_SYSMP */ |
/* Define if you have the sys_errlist variable. */ |
#define HAVE_SYS_ERRLIST 1 |
/* Define to 1 if you have the <sys/file.h> header file. */ |
#define HAVE_SYS_FILE_H 1 |
/* Define to 1 if you have the <sys/mman.h> header file. */ |
/* #undef HAVE_SYS_MMAN_H */ |
/* Define if you have the sys_nerr variable. */ |
#define HAVE_SYS_NERR 1 |
/* Define to 1 if you have the <sys/param.h> header file. */ |
#define HAVE_SYS_PARAM_H 1 |
/* Define to 1 if you have the <sys/prctl.h> header file. */ |
/* #undef HAVE_SYS_PRCTL_H */ |
/* Define to 1 if you have the <sys/pstat.h> header file. */ |
/* #undef HAVE_SYS_PSTAT_H */ |
/* Define to 1 if you have the <sys/resource.h> header file. */ |
/* #undef HAVE_SYS_RESOURCE_H */ |
/* Define if you have the sys_siglist variable. */ |
/* #undef HAVE_SYS_SIGLIST */ |
/* Define to 1 if you have the <sys/stat.h> header file. */ |
#define HAVE_SYS_STAT_H 1 |
/* Define to 1 if you have the <sys/sysctl.h> header file. */ |
/* #undef HAVE_SYS_SYSCTL_H */ |
/* Define to 1 if you have the <sys/sysinfo.h> header file. */ |
/* #undef HAVE_SYS_SYSINFO_H */ |
/* Define to 1 if you have the <sys/sysmp.h> header file. */ |
/* #undef HAVE_SYS_SYSMP_H */ |
/* Define to 1 if you have the <sys/systemcfg.h> header file. */ |
/* #undef HAVE_SYS_SYSTEMCFG_H */ |
/* Define to 1 if you have the <sys/table.h> header file. */ |
/* #undef HAVE_SYS_TABLE_H */ |
/* Define to 1 if you have the <sys/time.h> header file. */ |
#define HAVE_SYS_TIME_H 1 |
/* Define to 1 if you have the <sys/types.h> header file. */ |
#define HAVE_SYS_TYPES_H 1 |
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ |
/* #undef HAVE_SYS_WAIT_H */ |
/* Define to 1 if you have the `table' function. */ |
/* #undef HAVE_TABLE */ |
/* Define to 1 if you have the `times' function. */ |
/* #undef HAVE_TIMES */ |
/* Define to 1 if you have the <time.h> header file. */ |
#define HAVE_TIME_H 1 |
/* Define to 1 if you have the `tmpnam' function. */ |
#define HAVE_TMPNAM 1 |
/* Define if you have the \`uintptr_t' type. */ |
#define HAVE_UINTPTR_T 1 |
/* Define to 1 if you have the <unistd.h> header file. */ |
#define HAVE_UNISTD_H 1 |
/* Define to 1 if you have the `vasprintf' function. */ |
/* #undef HAVE_VASPRINTF */ |
/* Define to 1 if you have the `vfork' function. */ |
/* #undef HAVE_VFORK */ |
/* Define to 1 if you have the <vfork.h> header file. */ |
/* #undef HAVE_VFORK_H */ |
/* Define to 1 if you have the `vfprintf' function. */ |
#define HAVE_VFPRINTF 1 |
/* Define to 1 if you have the `vprintf' function. */ |
#define HAVE_VPRINTF 1 |
/* Define to 1 if you have the `vsprintf' function. */ |
#define HAVE_VSPRINTF 1 |
/* Define to 1 if you have the `wait3' function. */ |
/* #undef HAVE_WAIT3 */ |
/* Define to 1 if you have the `wait4' function. */ |
/* #undef HAVE_WAIT4 */ |
/* Define to 1 if you have the `waitpid' function. */ |
/* #undef HAVE_WAITPID */ |
/* Define to 1 if `fork' works. */ |
/* #undef HAVE_WORKING_FORK */ |
/* Define to 1 if `vfork' works. */ |
/* #undef HAVE_WORKING_VFORK */ |
/* Define to 1 if you have the `_doprnt' function. */ |
/* #undef HAVE__DOPRNT */ |
/* Define if you have the _system_configuration variable. */ |
/* #undef HAVE__SYSTEM_CONFIGURATION */ |
/* Define to 1 if you have the `__fsetlocking' function. */ |
/* #undef HAVE___FSETLOCKING */ |
/* Define if canonicalize_file_name is not declared in system header files. */ |
#define NEED_DECLARATION_CANONICALIZE_FILE_NAME 1 |
/* Define if errno must be declared even when <errno.h> is included. */ |
/* #undef NEED_DECLARATION_ERRNO */ |
/* Define to 1 if your C compiler doesn't accept -c and -o together. */ |
/* #undef NO_MINUS_C_MINUS_O */ |
/* Define to the address where bug reports for this package should be sent. */ |
#define PACKAGE_BUGREPORT "" |
/* Define to the full name of this package. */ |
#define PACKAGE_NAME "" |
/* Define to the full name and version of this package. */ |
#define PACKAGE_STRING "" |
/* Define to the one symbol short name of this package. */ |
#define PACKAGE_TARNAME "" |
/* Define to the home page for this package. */ |
#define PACKAGE_URL "" |
/* Define to the version of this package. */ |
#define PACKAGE_VERSION "" |
/* The size of `int', as computed by sizeof. */ |
#define SIZEOF_INT 4 |
/* Define if you know the direction of stack growth for your system; otherwise |
it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows |
toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses |
STACK_DIRECTION = 0 => direction of growth unknown */ |
#define STACK_DIRECTION -1 |
/* Define to 1 if you have the ANSI C header files. */ |
#define STDC_HEADERS 1 |
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ |
#define TIME_WITH_SYS_TIME 1 |
/* Define to an unsigned 64-bit type available in the compiler. */ |
#define UNSIGNED_64BIT_TYPE uint64_t |
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most |
significant byte first (like Motorola and SPARC, unlike Intel). */ |
#if defined AC_APPLE_UNIVERSAL_BUILD |
# if defined __BIG_ENDIAN__ |
# define WORDS_BIGENDIAN 1 |
# endif |
#else |
# ifndef WORDS_BIGENDIAN |
/* # undef WORDS_BIGENDIAN */ |
# endif |
#endif |
/* Number of bits in a file offset, on hosts where this is settable. */ |
/* #undef _FILE_OFFSET_BITS */ |
/* Define for large files, on AIX-style hosts. */ |
/* #undef _LARGE_FILES */ |
/* Define to empty if `const' does not conform to ANSI C. */ |
/* #undef const */ |
/* Define to `__inline__' or `__inline' if that's what the C compiler |
calls it, or to nothing if 'inline' is not supported under any name. */ |
#ifndef __cplusplus |
/* #undef inline */ |
#endif |
/* Define to the type of a signed integer type wide enough to hold a pointer, |
if such a type exists, and if the system does not define it. */ |
/* #undef intptr_t */ |
/* Define to `int' if <sys/types.h> does not define. */ |
/* #undef pid_t */ |
/* Define to `int' if <sys/types.h> does not define. */ |
/* #undef ssize_t */ |
/* Define to the type of an unsigned integer type wide enough to hold a |
pointer, if such a type exists, and if the system does not define it. */ |
/* #undef uintptr_t */ |
/* Define as `fork' if `vfork' does not work. */ |
#define vfork fork |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/cp-demangle.c |
---|
0,0 → 1,6450 |
/* Demangler for g++ V3 ABI. |
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 |
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 */ |
#ifdef HAVE_LIMITS_H |
#include <limits.h> |
#endif |
#ifndef INT_MAX |
# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ |
#endif |
#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; |
}; |
/* Stack of components, innermost first, used to avoid loops. */ |
struct d_component_stack |
{ |
/* This component. */ |
const struct demangle_component *dc; |
/* This component's parent. */ |
const struct d_component_stack *parent; |
}; |
/* A demangle component and some scope captured when it was first |
traversed. */ |
struct d_saved_scope |
{ |
/* The component whose scope this is. */ |
const struct demangle_component *container; |
/* The list of templates, if any, that was current when this |
scope was captured. */ |
struct d_print_template *templates; |
}; |
/* Checkpoint structure to allow backtracking. This holds copies |
of the fields of struct d_info that need to be restored |
if a trial parse needs to be backtracked over. */ |
struct d_info_checkpoint |
{ |
const char *n; |
int next_comp; |
int next_sub; |
int did_subs; |
int expansion; |
}; |
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; |
/* Stack of components, innermost first, used to avoid loops. */ |
const struct d_component_stack *component_stack; |
/* Array of saved scopes for evaluating substitutions. */ |
struct d_saved_scope *saved_scopes; |
/* Index of the next unused saved scope in the above array. */ |
int next_saved_scope; |
/* Number of saved scopes in the above array. */ |
int num_saved_scopes; |
/* Array of templates for saving into scopes. */ |
struct d_print_template *copy_templates; |
/* Index of the next unused copy template in the above array. */ |
int next_copy_template; |
/* Number of copy templates in the above array. */ |
int num_copy_templates; |
/* The nearest enclosing template, if any. */ |
const struct demangle_component *current_template; |
}; |
#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 *, int); |
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 int 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_checkpoint (struct d_info *, struct d_info_checkpoint *); |
static void d_backtrack (struct d_info *, struct d_info_checkpoint *); |
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 *, |
const struct demangle_component *); |
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 void d_print_conversion (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_FUNCTION_PARAM: |
printf ("function 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, accum? %d, sat? %d\n", |
dc->u.s_fixed.accum, dc->u.s_fixed.sat); |
d_dump (dc->u.s_fixed.length, indent + 2); |
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_CONVERSION: |
printf ("conversion operator\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_NUMBER: |
printf ("number %ld\n", dc->u.s_number.number); |
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_CONVERSION: |
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, int 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, int 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_CONVERSION: |
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 '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; |
} |
case 'L': |
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) |
{ |
int 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 int |
d_number (struct d_info *di) |
{ |
int negative; |
char peek; |
int 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') |
{ |
struct demangle_component *type; |
int was_conversion = di->is_conversion; |
struct demangle_component *res; |
di->is_conversion = ! di->is_expression; |
type = cplus_demangle_type (di); |
if (di->is_conversion) |
res = d_make_comp (di, DEMANGLE_COMPONENT_CONVERSION, type, NULL); |
else |
res = d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); |
di->is_conversion = was_conversion; |
return res; |
} |
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; |
int 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; |
int 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 '4': |
kind = gnu_v3_unified_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; |
/* digit '3' is not used */ |
case '4': |
kind = gnu_v3_unified_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; |
if (d_peek_char (di) == 'F') |
{ |
/* cv-qualifiers before a function type apply to 'this', |
so avoid adding the unqualified function type to |
the substitution list. */ |
*pret = d_function_type (di); |
} |
else |
*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 may be <template-template-param> <template-args>. |
If this is the type for a conversion operator, we can |
have a <template-template-param> here only by following |
a derivation like this: |
<nested-name> |
-> <template-prefix> <template-args> |
-> <prefix> <template-unqualified-name> <template-args> |
-> <unqualified-name> <template-unqualified-name> <template-args> |
-> <source-name> <template-unqualified-name> <template-args> |
-> <source-name> <operator-name> <template-args> |
-> <source-name> cv <type> <template-args> |
-> <source-name> cv <template-template-param> <template-args> <template-args> |
where the <template-args> is followed by another. |
Otherwise, we must have a derivation like this: |
<nested-name> |
-> <template-prefix> <template-args> |
-> <prefix> <template-unqualified-name> <template-args> |
-> <unqualified-name> <template-unqualified-name> <template-args> |
-> <source-name> <template-unqualified-name> <template-args> |
-> <source-name> <operator-name> <template-args> |
-> <source-name> cv <type> <template-args> |
-> <source-name> cv <template-param> <template-args> |
where we need to leave the <template-args> to be processed |
by d_prefix (following the <template-prefix>). |
The <template-template-param> part is a substitution |
candidate. */ |
if (! di->is_conversion) |
{ |
if (! d_add_substitution (di, ret)) |
return NULL; |
ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, |
d_template_args (di)); |
} |
else |
{ |
struct demangle_component *args; |
struct d_info_checkpoint checkpoint; |
d_checkpoint (di, &checkpoint); |
args = d_template_args (di); |
if (d_peek_char (di) == 'I') |
{ |
if (! d_add_substitution (di, ret)) |
return NULL; |
ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, |
args); |
} |
else |
d_backtrack (di, &checkpoint); |
} |
} |
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; |
if (! d_check_char (di, 'M')) |
return NULL; |
cl = cplus_demangle_type (di); |
if (cl == NULL) |
return NULL; |
/* The ABI says, "The type of a non-static member function is considered |
to be different, for the purposes of substitution, from the type of a |
namespace-scope or static member function whose type appears |
similar. The types of two non-static member functions are considered |
to be different, for the purposes of substitution, if the functions |
are members of different classes. In other words, for the purposes of |
substitution, the class of which the function is a member is |
considered part of the type of function." |
For a pointer to member function, this call to cplus_demangle_type |
will end up adding a (possibly qualified) non-member function type to |
the substitution table, which is not correct; however, the member |
function type will never be used in a substitution, so putting the |
wrong type in the substitution table is harmless. */ |
mem = cplus_demangle_type (di); |
if (mem == NULL) |
return NULL; |
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); |
} |
/* <non-negative number> _ */ |
static int |
d_compact_number (struct d_info *di) |
{ |
int num; |
if (d_peek_char (di) == '_') |
num = 0; |
else if (d_peek_char (di) == 'n') |
return -1; |
else |
num = d_number (di) + 1; |
if (num < 0 || ! 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) |
{ |
int 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 inline struct demangle_component * |
d_expression_1 (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_1 (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); |
if (index == INT_MAX || index == -1) |
return NULL; |
index++; |
} |
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); |
if (!d_peek_next_char (di)) |
return NULL; |
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_1 (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 (code == NULL) |
return NULL; |
if (op_is_new_cast (op)) |
left = cplus_demangle_type (di); |
else |
left = d_expression_1 (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_1 (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 (code == NULL) |
return NULL; |
else if (!strcmp (code, "qu")) |
{ |
/* ?: expression. */ |
first = d_expression_1 (di); |
second = d_expression_1 (di); |
third = d_expression_1 (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_1 (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; |
} |
} |
} |
static struct demangle_component * |
d_expression (struct d_info *di) |
{ |
struct demangle_component *ret; |
int was_expression = di->is_expression; |
di->is_expression = 1; |
ret = d_expression_1 (di); |
di->is_expression = was_expression; |
return ret; |
} |
/* <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) |
{ |
int 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; |
int 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; |
struct demangle_component *c; |
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; |
c = d_make_sub (di, s, len); |
if (d_peek_char (di) == 'B') |
{ |
/* If there are ABI tags on the abbreviation, it becomes |
a substitution candidate. */ |
c = d_abi_tags (di, c); |
d_add_substitution (di, c); |
} |
return c; |
} |
} |
return NULL; |
} |
} |
static void |
d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint) |
{ |
checkpoint->n = di->n; |
checkpoint->next_comp = di->next_comp; |
checkpoint->next_sub = di->next_sub; |
checkpoint->did_subs = di->did_subs; |
checkpoint->expansion = di->expansion; |
} |
static void |
d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint) |
{ |
di->n = checkpoint->n; |
di->next_comp = checkpoint->next_comp; |
di->next_sub = checkpoint->next_sub; |
di->did_subs = checkpoint->did_subs; |
di->expansion = checkpoint->expansion; |
} |
/* 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); |
} |
/* Walk the tree, counting the number of templates encountered, and |
the number of times a scope might be saved. These counts will be |
used to allocate data structures for d_print_comp, so the logic |
here must mirror the logic d_print_comp will use. It is not |
important that the resulting numbers are exact, so long as they |
are larger than the actual numbers encountered. */ |
static void |
d_count_templates_scopes (int *num_templates, int *num_scopes, |
const struct demangle_component *dc) |
{ |
if (dc == NULL) |
return; |
switch (dc->type) |
{ |
case DEMANGLE_COMPONENT_NAME: |
case DEMANGLE_COMPONENT_TEMPLATE_PARAM: |
case DEMANGLE_COMPONENT_FUNCTION_PARAM: |
case DEMANGLE_COMPONENT_SUB_STD: |
case DEMANGLE_COMPONENT_BUILTIN_TYPE: |
case DEMANGLE_COMPONENT_OPERATOR: |
case DEMANGLE_COMPONENT_CHARACTER: |
case DEMANGLE_COMPONENT_NUMBER: |
case DEMANGLE_COMPONENT_UNNAMED_TYPE: |
break; |
case DEMANGLE_COMPONENT_TEMPLATE: |
(*num_templates)++; |
goto recurse_left_right; |
case DEMANGLE_COMPONENT_REFERENCE: |
case DEMANGLE_COMPONENT_RVALUE_REFERENCE: |
if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) |
(*num_scopes)++; |
goto recurse_left_right; |
case DEMANGLE_COMPONENT_QUAL_NAME: |
case DEMANGLE_COMPONENT_LOCAL_NAME: |
case DEMANGLE_COMPONENT_TYPED_NAME: |
case DEMANGLE_COMPONENT_VTABLE: |
case DEMANGLE_COMPONENT_VTT: |
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: |
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_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_VENDOR_TYPE_QUAL: |
case DEMANGLE_COMPONENT_POINTER: |
case DEMANGLE_COMPONENT_COMPLEX: |
case DEMANGLE_COMPONENT_IMAGINARY: |
case DEMANGLE_COMPONENT_VENDOR_TYPE: |
case DEMANGLE_COMPONENT_FUNCTION_TYPE: |
case DEMANGLE_COMPONENT_ARRAY_TYPE: |
case DEMANGLE_COMPONENT_PTRMEM_TYPE: |
case DEMANGLE_COMPONENT_VECTOR_TYPE: |
case DEMANGLE_COMPONENT_ARGLIST: |
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: |
case DEMANGLE_COMPONENT_INITIALIZER_LIST: |
case DEMANGLE_COMPONENT_CAST: |
case DEMANGLE_COMPONENT_CONVERSION: |
case DEMANGLE_COMPONENT_NULLARY: |
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_TRINARY_ARG2: |
case DEMANGLE_COMPONENT_LITERAL: |
case DEMANGLE_COMPONENT_LITERAL_NEG: |
case DEMANGLE_COMPONENT_JAVA_RESOURCE: |
case DEMANGLE_COMPONENT_COMPOUND_NAME: |
case DEMANGLE_COMPONENT_DECLTYPE: |
case DEMANGLE_COMPONENT_TRANSACTION_CLONE: |
case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: |
case DEMANGLE_COMPONENT_PACK_EXPANSION: |
case DEMANGLE_COMPONENT_TAGGED_NAME: |
case DEMANGLE_COMPONENT_CLONE: |
recurse_left_right: |
d_count_templates_scopes (num_templates, num_scopes, |
d_left (dc)); |
d_count_templates_scopes (num_templates, num_scopes, |
d_right (dc)); |
break; |
case DEMANGLE_COMPONENT_CTOR: |
d_count_templates_scopes (num_templates, num_scopes, |
dc->u.s_ctor.name); |
break; |
case DEMANGLE_COMPONENT_DTOR: |
d_count_templates_scopes (num_templates, num_scopes, |
dc->u.s_dtor.name); |
break; |
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: |
d_count_templates_scopes (num_templates, num_scopes, |
dc->u.s_extended_operator.name); |
break; |
case DEMANGLE_COMPONENT_FIXED_TYPE: |
d_count_templates_scopes (num_templates, num_scopes, |
dc->u.s_fixed.length); |
break; |
case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: |
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: |
d_count_templates_scopes (num_templates, num_scopes, |
d_left (dc)); |
break; |
case DEMANGLE_COMPONENT_LAMBDA: |
case DEMANGLE_COMPONENT_DEFAULT_ARG: |
d_count_templates_scopes (num_templates, num_scopes, |
dc->u.s_unary_num.sub); |
break; |
} |
} |
/* Initialize a print information structure. */ |
static void |
d_print_init (struct d_print_info *dpi, demangle_callbackref callback, |
void *opaque, const struct demangle_component *dc) |
{ |
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; |
dpi->component_stack = NULL; |
dpi->saved_scopes = NULL; |
dpi->next_saved_scope = 0; |
dpi->num_saved_scopes = 0; |
dpi->copy_templates = NULL; |
dpi->next_copy_template = 0; |
dpi->num_copy_templates = 0; |
d_count_templates_scopes (&dpi->num_copy_templates, |
&dpi->num_saved_scopes, dc); |
dpi->num_copy_templates *= dpi->num_saved_scopes; |
dpi->current_template = NULL; |
} |
/* 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, int l) |
{ |
char buf[25]; |
sprintf (buf,"%d", 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, dc); |
{ |
#ifdef CP_DYNAMIC_ARRAYS |
__extension__ struct d_saved_scope scopes[dpi.num_saved_scopes]; |
__extension__ struct d_print_template temps[dpi.num_copy_templates]; |
dpi.saved_scopes = scopes; |
dpi.copy_templates = temps; |
#else |
dpi.saved_scopes = alloca (dpi.num_saved_scopes |
* sizeof (*dpi.saved_scopes)); |
dpi.copy_templates = alloca (dpi.num_copy_templates |
* sizeof (*dpi.copy_templates)); |
#endif |
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: |
case DEMANGLE_COMPONENT_FIXED_TYPE: |
case DEMANGLE_COMPONENT_DEFAULT_ARG: |
case DEMANGLE_COMPONENT_NUMBER: |
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, ')'); |
} |
/* Save the current scope. */ |
static void |
d_save_scope (struct d_print_info *dpi, |
const struct demangle_component *container) |
{ |
struct d_saved_scope *scope; |
struct d_print_template *src, **link; |
if (dpi->next_saved_scope >= dpi->num_saved_scopes) |
{ |
d_print_error (dpi); |
return; |
} |
scope = &dpi->saved_scopes[dpi->next_saved_scope]; |
dpi->next_saved_scope++; |
scope->container = container; |
link = &scope->templates; |
for (src = dpi->templates; src != NULL; src = src->next) |
{ |
struct d_print_template *dst; |
if (dpi->next_copy_template >= dpi->num_copy_templates) |
{ |
d_print_error (dpi); |
return; |
} |
dst = &dpi->copy_templates[dpi->next_copy_template]; |
dpi->next_copy_template++; |
dst->template_decl = src->template_decl; |
*link = dst; |
link = &dst->next; |
} |
*link = NULL; |
} |
/* Attempt to locate a previously saved scope. Returns NULL if no |
corresponding saved scope was found. */ |
static struct d_saved_scope * |
d_get_saved_scope (struct d_print_info *dpi, |
const struct demangle_component *container) |
{ |
int i; |
for (i = 0; i < dpi->next_saved_scope; i++) |
if (dpi->saved_scopes[i].container == container) |
return &dpi->saved_scopes[i]; |
return NULL; |
} |
/* Subroutine to handle components. */ |
static void |
d_print_comp_inner (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; |
/* Variable used to store the current templates while a previously |
captured scope is used. */ |
struct d_print_template *saved_templates; |
/* Nonzero if templates have been stored in the above variable. */ |
int need_template_restore = 0; |
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; |
if (local_name == NULL) |
{ |
d_print_error (dpi); |
return; |
} |
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; |
const struct demangle_component *hold_current; |
/* This template may need to be referenced by a cast operator |
contained in its subtree. */ |
hold_current = dpi->current_template; |
dpi->current_template = dc; |
/* 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; |
dpi->current_template = hold_current; |
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 d_saved_scope *scope = d_get_saved_scope (dpi, sub); |
struct demangle_component *a; |
if (scope == NULL) |
{ |
/* This is the first time SUB has been traversed. |
We need to capture the current templates so |
they can be restored if SUB is reentered as a |
substitution. */ |
d_save_scope (dpi, sub); |
if (d_print_saw_error (dpi)) |
return; |
} |
else |
{ |
const struct d_component_stack *dcse; |
int found_self_or_parent = 0; |
/* This traversal is reentering SUB as a substition. |
If we are not beneath SUB or DC in the tree then we |
need to restore SUB's template stack temporarily. */ |
for (dcse = dpi->component_stack; dcse != NULL; |
dcse = dcse->parent) |
{ |
if (dcse->dc == sub |
|| (dcse->dc == dc |
&& dcse != dpi->component_stack)) |
{ |
found_self_or_parent = 1; |
break; |
} |
} |
if (!found_self_or_parent) |
{ |
saved_templates = dpi->templates; |
dpi->templates = scope->templates; |
need_template_restore = 1; |
} |
} |
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) |
{ |
if (need_template_restore) |
dpi->templates = saved_templates; |
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; |
if (need_template_restore) |
dpi->templates = saved_templates; |
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_CONVERSION: |
d_append_string (dpi, "operator "); |
d_print_conversion (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; |
} |
} |
static void |
d_print_comp (struct d_print_info *dpi, int options, |
const struct demangle_component *dc) |
{ |
struct d_component_stack self; |
self.dc = dc; |
self.parent = dpi->component_stack; |
dpi->component_stack = &self; |
d_print_comp_inner (dpi, options, dc); |
dpi->component_stack = self.parent; |
} |
/* 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) |
{ |
d_print_comp (dpi, options, d_left (dc)); |
} |
/* Print a conversion operator. */ |
static void |
d_print_conversion (struct d_print_info *dpi, int options, |
const struct demangle_component *dc) |
{ |
struct d_print_template dpt; |
/* For a conversion operator, we need the template parameters from |
the enclosing template in scope for processing the type. */ |
if (dpi->current_template != NULL) |
{ |
dpt.next = dpi->templates; |
dpi->templates = &dpt; |
dpt.template_decl = dpi->current_template; |
} |
if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) |
{ |
d_print_comp (dpi, options, d_left (dc)); |
if (dpi->current_template != NULL) |
dpi->templates = dpt.next; |
} |
else |
{ |
d_print_comp (dpi, options, d_left (d_left (dc))); |
/* For a templated cast operator, we need to remove the template |
parameters from scope after printing the operator name, |
so we need to handle the template printing here. */ |
if (dpi->current_template != NULL) |
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, '>'); |
} |
} |
/* 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; |
di->is_expression = 0; |
di->is_conversion = 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; |
default: |
abort (); /* We have listed all the cases. */ |
} |
/* 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/cp-demangle.h |
---|
0,0 → 1,169 |
/* Internal demangler interface for g++ V3 ABI. |
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 |
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 file provides some definitions shared by cp-demangle.c and |
cp-demint.c. It should not be included by any other files. */ |
/* Information we keep for operators. */ |
struct demangle_operator_info |
{ |
/* Mangled name. */ |
const char *code; |
/* Real name. */ |
const char *name; |
/* Length of real name. */ |
int len; |
/* Number of arguments. */ |
int args; |
}; |
/* How to print the value of a builtin type. */ |
enum d_builtin_type_print |
{ |
/* Print as (type)val. */ |
D_PRINT_DEFAULT, |
/* Print as integer. */ |
D_PRINT_INT, |
/* Print as unsigned integer, with trailing "u". */ |
D_PRINT_UNSIGNED, |
/* Print as long, with trailing "l". */ |
D_PRINT_LONG, |
/* Print as unsigned long, with trailing "ul". */ |
D_PRINT_UNSIGNED_LONG, |
/* Print as long long, with trailing "ll". */ |
D_PRINT_LONG_LONG, |
/* Print as unsigned long long, with trailing "ull". */ |
D_PRINT_UNSIGNED_LONG_LONG, |
/* Print as bool. */ |
D_PRINT_BOOL, |
/* Print as float--put value in square brackets. */ |
D_PRINT_FLOAT, |
/* Print in usual way, but here to detect void. */ |
D_PRINT_VOID |
}; |
/* Information we keep for a builtin type. */ |
struct demangle_builtin_type_info |
{ |
/* Type name. */ |
const char *name; |
/* Length of type name. */ |
int len; |
/* Type name when using Java. */ |
const char *java_name; |
/* Length of java name. */ |
int java_len; |
/* How to print a value of this type. */ |
enum d_builtin_type_print print; |
}; |
/* The information structure we pass around. */ |
struct d_info |
{ |
/* The string we are demangling. */ |
const char *s; |
/* The end of the string we are demangling. */ |
const char *send; |
/* The options passed to the demangler. */ |
int options; |
/* The next character in the string to consider. */ |
const char *n; |
/* The array of components. */ |
struct demangle_component *comps; |
/* The index of the next available component. */ |
int next_comp; |
/* The number of available component structures. */ |
int num_comps; |
/* The array of substitutions. */ |
struct demangle_component **subs; |
/* The index of the next substitution. */ |
int next_sub; |
/* The number of available entries in the subs array. */ |
int num_subs; |
/* The number of substitutions which we actually made from the subs |
array, plus the number of template parameter references we |
saw. */ |
int did_subs; |
/* The last name we saw, for constructors and destructors. */ |
struct demangle_component *last_name; |
/* A running total of the length of large expansions from the |
mangled name to the demangled name, such as standard |
substitutions and builtin types. */ |
int expansion; |
}; |
/* To avoid running past the ending '\0', don't: |
- call d_peek_next_char if d_peek_char returned '\0' |
- call d_advance with an 'i' that is too large |
- call d_check_char(di, '\0') |
Everything else is safe. */ |
#define d_peek_char(di) (*((di)->n)) |
#define d_peek_next_char(di) ((di)->n[1]) |
#define d_advance(di, i) ((di)->n += (i)) |
#define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0) |
#define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++)) |
#define d_str(di) ((di)->n) |
/* Functions and arrays in cp-demangle.c which are referenced by |
functions in cp-demint.c. */ |
#ifdef IN_GLIBCPP_V3 |
#define CP_STATIC_IF_GLIBCPP_V3 static |
#else |
#define CP_STATIC_IF_GLIBCPP_V3 extern |
#endif |
#ifndef IN_GLIBCPP_V3 |
extern const struct demangle_operator_info cplus_demangle_operators[]; |
#endif |
#define D_BUILTIN_TYPE_COUNT (33) |
CP_STATIC_IF_GLIBCPP_V3 |
const struct demangle_builtin_type_info |
cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT]; |
CP_STATIC_IF_GLIBCPP_V3 |
struct demangle_component * |
cplus_demangle_mangled_name (struct d_info *, int); |
CP_STATIC_IF_GLIBCPP_V3 |
struct demangle_component * |
cplus_demangle_type (struct d_info *); |
extern void |
cplus_demangle_init_info (const char *, int, size_t, struct d_info *); |
/* cp-demangle.c needs to define this a little differently */ |
#undef CP_STATIC_IF_GLIBCPP_V3 |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/cxxabi.h |
---|
0,0 → 1,710 |
// ABI Support -*- C++ -*- |
// Copyright (C) 2000-2015 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 auxiliary. |
void |
__cxa_bad_cast() __attribute__((__noreturn__)); |
void |
__cxa_bad_typeid() __attribute__((__noreturn__)); |
void |
__cxa_throw_bad_array_new_length() __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; |
}; |
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); |
} |
// 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/cxxabi_forced.h |
---|
0,0 → 1,60 |
// cxxabi.h subset for cancellation -*- C++ -*- |
// Copyright (C) 2007-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/del_op.cc |
---|
0,0 → 1,47 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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 |
{ |
std::free(ptr); |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/del_opnt.cc |
---|
0,0 → 1,47 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT |
{ |
std::free(ptr); |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/del_ops.cc |
---|
0,0 → 1,33 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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, std::size_t) _GLIBCXX_USE_NOEXCEPT |
{ |
::operator delete (ptr); |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/del_opv.cc |
---|
0,0 → 1,33 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/del_opvnt.cc |
---|
0,0 → 1,33 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/del_opvs.cc |
---|
0,0 → 1,33 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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, std::size_t) _GLIBCXX_USE_NOEXCEPT |
{ |
::operator delete[] (ptr); |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/demangle.h |
---|
0,0 → 1,671 |
/* Defs for interface to demanglers. |
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, |
2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
This program is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public License |
as published by the Free Software Foundation; either version 2, or |
(at your option) any later version. |
In addition to the permissions in the GNU Library 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 Library 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 |
Library General Public License for more details. |
You should have received a copy of the GNU Library 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. */ |
#if !defined (DEMANGLE_H) |
#define DEMANGLE_H |
#include "libiberty.h" |
#ifdef __cplusplus |
extern "C" { |
#endif /* __cplusplus */ |
/* Options passed to cplus_demangle (in 2nd parameter). */ |
#define DMGL_NO_OPTS 0 /* For readability... */ |
#define DMGL_PARAMS (1 << 0) /* Include function args */ |
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */ |
#define DMGL_VERBOSE (1 << 3) /* Include implementation details. */ |
#define DMGL_TYPES (1 << 4) /* Also try to demangle type encodings. */ |
#define DMGL_RET_POSTFIX (1 << 5) /* Print function return types (when |
present) after function signature. |
It applies only to the toplevel |
function type. */ |
#define DMGL_RET_DROP (1 << 6) /* Suppress printing function return |
types, even if present. It applies |
only to the toplevel function type. |
*/ |
#define DMGL_AUTO (1 << 8) |
#define DMGL_GNU (1 << 9) |
#define DMGL_LUCID (1 << 10) |
#define DMGL_ARM (1 << 11) |
#define DMGL_HP (1 << 12) /* For the HP aCC compiler; |
same as ARM except for |
template arguments, etc. */ |
#define DMGL_EDG (1 << 13) |
#define DMGL_GNU_V3 (1 << 14) |
#define DMGL_GNAT (1 << 15) |
/* If none of these are set, use 'current_demangling_style' as the default. */ |
#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT) |
/* Enumeration of possible demangling styles. |
Lucid and ARM styles are still kept logically distinct, even though |
they now both behave identically. The resulting style is actual the |
union of both. I.E. either style recognizes both "__pt__" and "__rf__" |
for operator "->", even though the first is lucid style and the second |
is ARM style. (FIXME?) */ |
extern enum demangling_styles |
{ |
no_demangling = -1, |
unknown_demangling = 0, |
auto_demangling = DMGL_AUTO, |
gnu_demangling = DMGL_GNU, |
lucid_demangling = DMGL_LUCID, |
arm_demangling = DMGL_ARM, |
hp_demangling = DMGL_HP, |
edg_demangling = DMGL_EDG, |
gnu_v3_demangling = DMGL_GNU_V3, |
java_demangling = DMGL_JAVA, |
gnat_demangling = DMGL_GNAT |
} current_demangling_style; |
/* Define string names for the various demangling styles. */ |
#define NO_DEMANGLING_STYLE_STRING "none" |
#define AUTO_DEMANGLING_STYLE_STRING "auto" |
#define GNU_DEMANGLING_STYLE_STRING "gnu" |
#define LUCID_DEMANGLING_STYLE_STRING "lucid" |
#define ARM_DEMANGLING_STYLE_STRING "arm" |
#define HP_DEMANGLING_STYLE_STRING "hp" |
#define EDG_DEMANGLING_STYLE_STRING "edg" |
#define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3" |
#define JAVA_DEMANGLING_STYLE_STRING "java" |
#define GNAT_DEMANGLING_STYLE_STRING "gnat" |
/* Some macros to test what demangling style is active. */ |
#define CURRENT_DEMANGLING_STYLE current_demangling_style |
#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO) |
#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU) |
#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID) |
#define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM) |
#define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP) |
#define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG) |
#define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) |
#define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) |
#define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) |
/* Provide information about the available demangle styles. This code is |
pulled from gdb into libiberty because it is useful to binutils also. */ |
extern const struct demangler_engine |
{ |
const char *const demangling_style_name; |
const enum demangling_styles demangling_style; |
const char *const demangling_style_doc; |
} libiberty_demanglers[]; |
extern char * |
cplus_demangle (const char *mangled, int options); |
extern int |
cplus_demangle_opname (const char *opname, char *result, int options); |
extern const char * |
cplus_mangle_opname (const char *opname, int options); |
/* Note: This sets global state. FIXME if you care about multi-threading. */ |
extern void |
set_cplus_marker_for_demangling (int ch); |
extern enum demangling_styles |
cplus_demangle_set_style (enum demangling_styles style); |
extern enum demangling_styles |
cplus_demangle_name_to_style (const char *name); |
/* Callback typedef for allocation-less demangler interfaces. */ |
typedef void (*demangle_callbackref) (const char *, size_t, void *); |
/* V3 ABI demangling entry points, defined in cp-demangle.c. Callback |
variants return non-zero on success, zero on error. char* variants |
return a string allocated by malloc on success, NULL on error. */ |
extern int |
cplus_demangle_v3_callback (const char *mangled, int options, |
demangle_callbackref callback, void *opaque); |
extern char* |
cplus_demangle_v3 (const char *mangled, int options); |
extern int |
java_demangle_v3_callback (const char *mangled, |
demangle_callbackref callback, void *opaque); |
extern char* |
java_demangle_v3 (const char *mangled); |
char * |
ada_demangle (const char *mangled, int options); |
enum gnu_v3_ctor_kinds { |
gnu_v3_complete_object_ctor = 1, |
gnu_v3_base_object_ctor, |
gnu_v3_complete_object_allocating_ctor, |
gnu_v3_object_ctor_group |
}; |
/* Return non-zero iff NAME is the mangled form of a constructor name |
in the G++ V3 ABI demangling style. Specifically, return an `enum |
gnu_v3_ctor_kinds' value indicating what kind of constructor |
it is. */ |
extern enum gnu_v3_ctor_kinds |
is_gnu_v3_mangled_ctor (const char *name); |
enum gnu_v3_dtor_kinds { |
gnu_v3_deleting_dtor = 1, |
gnu_v3_complete_object_dtor, |
gnu_v3_base_object_dtor, |
gnu_v3_object_dtor_group |
}; |
/* Return non-zero iff NAME is the mangled form of a destructor name |
in the G++ V3 ABI demangling style. Specifically, return an `enum |
gnu_v3_dtor_kinds' value, indicating what kind of destructor |
it is. */ |
extern enum gnu_v3_dtor_kinds |
is_gnu_v3_mangled_dtor (const char *name); |
/* The V3 demangler works in two passes. The first pass builds a tree |
representation of the mangled name, and the second pass turns the |
tree representation into a demangled string. Here we define an |
interface to permit a caller to build their own tree |
representation, which they can pass to the demangler to get a |
demangled string. This can be used to canonicalize user input into |
something which the demangler might output. It could also be used |
by other demanglers in the future. */ |
/* These are the component types which may be found in the tree. Many |
component types have one or two subtrees, referred to as left and |
right (a component type with only one subtree puts it in the left |
subtree). */ |
enum demangle_component_type |
{ |
/* A name, with a length and a pointer to a string. */ |
DEMANGLE_COMPONENT_NAME, |
/* A qualified name. The left subtree is a class or namespace or |
some such thing, and the right subtree is a name qualified by |
that class. */ |
DEMANGLE_COMPONENT_QUAL_NAME, |
/* A local name. The left subtree describes a function, and the |
right subtree is a name which is local to that function. */ |
DEMANGLE_COMPONENT_LOCAL_NAME, |
/* A typed name. The left subtree is a name, and the right subtree |
describes that name as a function. */ |
DEMANGLE_COMPONENT_TYPED_NAME, |
/* A template. The left subtree is a template name, and the right |
subtree is a template argument list. */ |
DEMANGLE_COMPONENT_TEMPLATE, |
/* A template parameter. This holds a number, which is the template |
parameter index. */ |
DEMANGLE_COMPONENT_TEMPLATE_PARAM, |
/* A function parameter. This holds a number, which is the index. */ |
DEMANGLE_COMPONENT_FUNCTION_PARAM, |
/* A constructor. This holds a name and the kind of |
constructor. */ |
DEMANGLE_COMPONENT_CTOR, |
/* A destructor. This holds a name and the kind of destructor. */ |
DEMANGLE_COMPONENT_DTOR, |
/* A vtable. This has one subtree, the type for which this is a |
vtable. */ |
DEMANGLE_COMPONENT_VTABLE, |
/* A VTT structure. This has one subtree, the type for which this |
is a VTT. */ |
DEMANGLE_COMPONENT_VTT, |
/* A construction vtable. The left subtree is the type for which |
this is a vtable, and the right subtree is the derived type for |
which this vtable is built. */ |
DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, |
/* A typeinfo structure. This has one subtree, the type for which |
this is the tpeinfo structure. */ |
DEMANGLE_COMPONENT_TYPEINFO, |
/* A typeinfo name. This has one subtree, the type for which this |
is the typeinfo name. */ |
DEMANGLE_COMPONENT_TYPEINFO_NAME, |
/* A typeinfo function. This has one subtree, the type for which |
this is the tpyeinfo function. */ |
DEMANGLE_COMPONENT_TYPEINFO_FN, |
/* A thunk. This has one subtree, the name for which this is a |
thunk. */ |
DEMANGLE_COMPONENT_THUNK, |
/* A virtual thunk. This has one subtree, the name for which this |
is a virtual thunk. */ |
DEMANGLE_COMPONENT_VIRTUAL_THUNK, |
/* A covariant thunk. This has one subtree, the name for which this |
is a covariant thunk. */ |
DEMANGLE_COMPONENT_COVARIANT_THUNK, |
/* A Java class. This has one subtree, the type. */ |
DEMANGLE_COMPONENT_JAVA_CLASS, |
/* A guard variable. This has one subtree, the name for which this |
is a guard variable. */ |
DEMANGLE_COMPONENT_GUARD, |
/* The init and wrapper functions for C++11 thread_local variables. */ |
DEMANGLE_COMPONENT_TLS_INIT, |
DEMANGLE_COMPONENT_TLS_WRAPPER, |
/* A reference temporary. This has one subtree, the name for which |
this is a temporary. */ |
DEMANGLE_COMPONENT_REFTEMP, |
/* A hidden alias. This has one subtree, the encoding for which it |
is providing alternative linkage. */ |
DEMANGLE_COMPONENT_HIDDEN_ALIAS, |
/* A standard substitution. This holds the name of the |
substitution. */ |
DEMANGLE_COMPONENT_SUB_STD, |
/* The restrict qualifier. The one subtree is the type which is |
being qualified. */ |
DEMANGLE_COMPONENT_RESTRICT, |
/* The volatile qualifier. The one subtree is the type which is |
being qualified. */ |
DEMANGLE_COMPONENT_VOLATILE, |
/* The const qualifier. The one subtree is the type which is being |
qualified. */ |
DEMANGLE_COMPONENT_CONST, |
/* The restrict qualifier modifying a member function. The one |
subtree is the type which is being qualified. */ |
DEMANGLE_COMPONENT_RESTRICT_THIS, |
/* The volatile qualifier modifying a member function. The one |
subtree is the type which is being qualified. */ |
DEMANGLE_COMPONENT_VOLATILE_THIS, |
/* The const qualifier modifying a member function. The one subtree |
is the type which is being qualified. */ |
DEMANGLE_COMPONENT_CONST_THIS, |
/* C++11 A reference modifying a member function. The one subtree is the |
type which is being referenced. */ |
DEMANGLE_COMPONENT_REFERENCE_THIS, |
/* C++11: An rvalue reference modifying a member function. The one |
subtree is the type which is being referenced. */ |
DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS, |
/* A vendor qualifier. The left subtree is the type which is being |
qualified, and the right subtree is the name of the |
qualifier. */ |
DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, |
/* A pointer. The one subtree is the type which is being pointed |
to. */ |
DEMANGLE_COMPONENT_POINTER, |
/* A reference. The one subtree is the type which is being |
referenced. */ |
DEMANGLE_COMPONENT_REFERENCE, |
/* C++0x: An rvalue reference. The one subtree is the type which is |
being referenced. */ |
DEMANGLE_COMPONENT_RVALUE_REFERENCE, |
/* A complex type. The one subtree is the base type. */ |
DEMANGLE_COMPONENT_COMPLEX, |
/* An imaginary type. The one subtree is the base type. */ |
DEMANGLE_COMPONENT_IMAGINARY, |
/* A builtin type. This holds the builtin type information. */ |
DEMANGLE_COMPONENT_BUILTIN_TYPE, |
/* A vendor's builtin type. This holds the name of the type. */ |
DEMANGLE_COMPONENT_VENDOR_TYPE, |
/* A function type. The left subtree is the return type. The right |
subtree is a list of ARGLIST nodes. Either or both may be |
NULL. */ |
DEMANGLE_COMPONENT_FUNCTION_TYPE, |
/* An array type. The left subtree is the dimension, which may be |
NULL, or a string (represented as DEMANGLE_COMPONENT_NAME), or an |
expression. The right subtree is the element type. */ |
DEMANGLE_COMPONENT_ARRAY_TYPE, |
/* A pointer to member type. The left subtree is the class type, |
and the right subtree is the member type. CV-qualifiers appear |
on the latter. */ |
DEMANGLE_COMPONENT_PTRMEM_TYPE, |
/* A fixed-point type. */ |
DEMANGLE_COMPONENT_FIXED_TYPE, |
/* A vector type. The left subtree is the number of elements, |
the right subtree is the element type. */ |
DEMANGLE_COMPONENT_VECTOR_TYPE, |
/* An argument list. The left subtree is the current argument, and |
the right subtree is either NULL or another ARGLIST node. */ |
DEMANGLE_COMPONENT_ARGLIST, |
/* A template argument list. The left subtree is the current |
template argument, and the right subtree is either NULL or |
another TEMPLATE_ARGLIST node. */ |
DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, |
/* An initializer list. The left subtree is either an explicit type or |
NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST. */ |
DEMANGLE_COMPONENT_INITIALIZER_LIST, |
/* An operator. This holds information about a standard |
operator. */ |
DEMANGLE_COMPONENT_OPERATOR, |
/* An extended operator. This holds the number of arguments, and |
the name of the extended operator. */ |
DEMANGLE_COMPONENT_EXTENDED_OPERATOR, |
/* A typecast, represented as a unary operator. The one subtree is |
the type to which the argument should be cast. */ |
DEMANGLE_COMPONENT_CAST, |
/* A nullary expression. The left subtree is the operator. */ |
DEMANGLE_COMPONENT_NULLARY, |
/* A unary expression. The left subtree is the operator, and the |
right subtree is the single argument. */ |
DEMANGLE_COMPONENT_UNARY, |
/* A binary expression. The left subtree is the operator, and the |
right subtree is a BINARY_ARGS. */ |
DEMANGLE_COMPONENT_BINARY, |
/* Arguments to a binary expression. The left subtree is the first |
argument, and the right subtree is the second argument. */ |
DEMANGLE_COMPONENT_BINARY_ARGS, |
/* A trinary expression. The left subtree is the operator, and the |
right subtree is a TRINARY_ARG1. */ |
DEMANGLE_COMPONENT_TRINARY, |
/* Arguments to a trinary expression. The left subtree is the first |
argument, and the right subtree is a TRINARY_ARG2. */ |
DEMANGLE_COMPONENT_TRINARY_ARG1, |
/* More arguments to a trinary expression. The left subtree is the |
second argument, and the right subtree is the third argument. */ |
DEMANGLE_COMPONENT_TRINARY_ARG2, |
/* A literal. The left subtree is the type, and the right subtree |
is the value, represented as a DEMANGLE_COMPONENT_NAME. */ |
DEMANGLE_COMPONENT_LITERAL, |
/* A negative literal. Like LITERAL, but the value is negated. |
This is a minor hack: the NAME used for LITERAL points directly |
to the mangled string, but since negative numbers are mangled |
using 'n' instead of '-', we want a way to indicate a negative |
number which involves neither modifying the mangled string nor |
allocating a new copy of the literal in memory. */ |
DEMANGLE_COMPONENT_LITERAL_NEG, |
/* A libgcj compiled resource. The left subtree is the name of the |
resource. */ |
DEMANGLE_COMPONENT_JAVA_RESOURCE, |
/* A name formed by the concatenation of two parts. The left |
subtree is the first part and the right subtree the second. */ |
DEMANGLE_COMPONENT_COMPOUND_NAME, |
/* A name formed by a single character. */ |
DEMANGLE_COMPONENT_CHARACTER, |
/* A number. */ |
DEMANGLE_COMPONENT_NUMBER, |
/* A decltype type. */ |
DEMANGLE_COMPONENT_DECLTYPE, |
/* Global constructors keyed to name. */ |
DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS, |
/* Global destructors keyed to name. */ |
DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS, |
/* A lambda closure type. */ |
DEMANGLE_COMPONENT_LAMBDA, |
/* A default argument scope. */ |
DEMANGLE_COMPONENT_DEFAULT_ARG, |
/* An unnamed type. */ |
DEMANGLE_COMPONENT_UNNAMED_TYPE, |
/* A transactional clone. This has one subtree, the encoding for |
which it is providing alternative linkage. */ |
DEMANGLE_COMPONENT_TRANSACTION_CLONE, |
/* A non-transactional clone entry point. In the i386/x86_64 abi, |
the unmangled symbol of a tm_callable becomes a thunk and the |
non-transactional function version is mangled thus. */ |
DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, |
/* A pack expansion. */ |
DEMANGLE_COMPONENT_PACK_EXPANSION, |
/* A name with an ABI tag. */ |
DEMANGLE_COMPONENT_TAGGED_NAME, |
/* A cloned function. */ |
DEMANGLE_COMPONENT_CLONE |
}; |
/* Types which are only used internally. */ |
struct demangle_operator_info; |
struct demangle_builtin_type_info; |
/* A node in the tree representation is an instance of a struct |
demangle_component. Note that the field names of the struct are |
not well protected against macros defined by the file including |
this one. We can fix this if it ever becomes a problem. */ |
struct demangle_component |
{ |
/* The type of this component. */ |
enum demangle_component_type type; |
union |
{ |
/* For DEMANGLE_COMPONENT_NAME. */ |
struct |
{ |
/* A pointer to the name (which need not NULL terminated) and |
its length. */ |
const char *s; |
int len; |
} s_name; |
/* For DEMANGLE_COMPONENT_OPERATOR. */ |
struct |
{ |
/* Operator. */ |
const struct demangle_operator_info *op; |
} s_operator; |
/* For DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ |
struct |
{ |
/* Number of arguments. */ |
int args; |
/* Name. */ |
struct demangle_component *name; |
} s_extended_operator; |
/* For DEMANGLE_COMPONENT_FIXED_TYPE. */ |
struct |
{ |
/* The length, indicated by a C integer type name. */ |
struct demangle_component *length; |
/* _Accum or _Fract? */ |
short accum; |
/* Saturating or not? */ |
short sat; |
} s_fixed; |
/* For DEMANGLE_COMPONENT_CTOR. */ |
struct |
{ |
/* Kind of constructor. */ |
enum gnu_v3_ctor_kinds kind; |
/* Name. */ |
struct demangle_component *name; |
} s_ctor; |
/* For DEMANGLE_COMPONENT_DTOR. */ |
struct |
{ |
/* Kind of destructor. */ |
enum gnu_v3_dtor_kinds kind; |
/* Name. */ |
struct demangle_component *name; |
} s_dtor; |
/* For DEMANGLE_COMPONENT_BUILTIN_TYPE. */ |
struct |
{ |
/* Builtin type. */ |
const struct demangle_builtin_type_info *type; |
} s_builtin; |
/* For DEMANGLE_COMPONENT_SUB_STD. */ |
struct |
{ |
/* Standard substitution string. */ |
const char* string; |
/* Length of string. */ |
int len; |
} s_string; |
/* For DEMANGLE_COMPONENT_*_PARAM. */ |
struct |
{ |
/* Parameter index. */ |
long number; |
} s_number; |
/* For DEMANGLE_COMPONENT_CHARACTER. */ |
struct |
{ |
int character; |
} s_character; |
/* For other types. */ |
struct |
{ |
/* Left (or only) subtree. */ |
struct demangle_component *left; |
/* Right subtree. */ |
struct demangle_component *right; |
} s_binary; |
struct |
{ |
/* subtree, same place as d_left. */ |
struct demangle_component *sub; |
/* integer. */ |
int num; |
} s_unary_num; |
} u; |
}; |
/* People building mangled trees are expected to allocate instances of |
struct demangle_component themselves. They can then call one of |
the following functions to fill them in. */ |
/* Fill in most component types with a left subtree and a right |
subtree. Returns non-zero on success, zero on failure, such as an |
unrecognized or inappropriate component type. */ |
extern int |
cplus_demangle_fill_component (struct demangle_component *fill, |
enum demangle_component_type, |
struct demangle_component *left, |
struct demangle_component *right); |
/* Fill in a DEMANGLE_COMPONENT_NAME. Returns non-zero on success, |
zero for bad arguments. */ |
extern int |
cplus_demangle_fill_name (struct demangle_component *fill, |
const char *, int); |
/* Fill in a DEMANGLE_COMPONENT_BUILTIN_TYPE, using the name of the |
builtin type (e.g., "int", etc.). Returns non-zero on success, |
zero if the type is not recognized. */ |
extern int |
cplus_demangle_fill_builtin_type (struct demangle_component *fill, |
const char *type_name); |
/* Fill in a DEMANGLE_COMPONENT_OPERATOR, using the name of the |
operator and the number of arguments which it takes (the latter is |
used to disambiguate operators which can be both binary and unary, |
such as '-'). Returns non-zero on success, zero if the operator is |
not recognized. */ |
extern int |
cplus_demangle_fill_operator (struct demangle_component *fill, |
const char *opname, int args); |
/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR, providing the |
number of arguments and the name. Returns non-zero on success, |
zero for bad arguments. */ |
extern int |
cplus_demangle_fill_extended_operator (struct demangle_component *fill, |
int numargs, |
struct demangle_component *nm); |
/* Fill in a DEMANGLE_COMPONENT_CTOR. Returns non-zero on success, |
zero for bad arguments. */ |
extern int |
cplus_demangle_fill_ctor (struct demangle_component *fill, |
enum gnu_v3_ctor_kinds kind, |
struct demangle_component *name); |
/* Fill in a DEMANGLE_COMPONENT_DTOR. Returns non-zero on success, |
zero for bad arguments. */ |
extern int |
cplus_demangle_fill_dtor (struct demangle_component *fill, |
enum gnu_v3_dtor_kinds kind, |
struct demangle_component *name); |
/* This function translates a mangled name into a struct |
demangle_component tree. The first argument is the mangled name. |
The second argument is DMGL_* options. This returns a pointer to a |
tree on success, or NULL on failure. On success, the third |
argument is set to a block of memory allocated by malloc. This |
block should be passed to free when the tree is no longer |
needed. */ |
extern struct demangle_component * |
cplus_demangle_v3_components (const char *mangled, int options, void **mem); |
/* This function takes a struct demangle_component tree and returns |
the corresponding demangled string. The first argument is DMGL_* |
options. The second is the tree to demangle. The third is a guess |
at the length of the demangled string, used to initially allocate |
the return buffer. The fourth is a pointer to a size_t. On |
success, this function returns a buffer allocated by malloc(), and |
sets the size_t pointed to by the fourth argument to the size of |
the allocated buffer (not the length of the returned string). On |
failure, this function returns NULL, and sets the size_t pointed to |
by the fourth argument to 0 for an invalid tree, or to 1 for a |
memory allocation error. */ |
extern char * |
cplus_demangle_print (int options, |
const struct demangle_component *tree, |
int estimated_length, |
size_t *p_allocated_size); |
/* This function takes a struct demangle_component tree and passes back |
a demangled string in one or more calls to a callback function. |
The first argument is DMGL_* options. The second is the tree to |
demangle. The third is a pointer to a callback function; on each call |
this receives an element of the demangled string, its length, and an |
opaque value. The fourth is the opaque value passed to the callback. |
The callback is called once or more to return the full demangled |
string. The demangled element string is always nul-terminated, though |
its length is also provided for convenience. In contrast to |
cplus_demangle_print(), this function does not allocate heap memory |
to grow output strings (except perhaps where alloca() is implemented |
by malloc()), and so is normally safe for use where the heap has been |
corrupted. On success, this function returns 1; on failure, 0. */ |
extern int |
cplus_demangle_print_callback (int options, |
const struct demangle_component *tree, |
demangle_callbackref callback, void *opaque); |
#ifdef __cplusplus |
} |
#endif /* __cplusplus */ |
#endif /* DEMANGLE_H */ |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/dyncast.cc |
---|
0,0 → 1,97 |
// Copyright (C) 1994-2015 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; |
// If the whole object vptr doesn't refer to the whole object type, we're |
// in the middle of constructing a primary base, and src is a separate |
// base. This has undefined behavior and we can't find anything outside |
// of the base we're actually constructing, so fail now rather than |
// segfault later trying to use a vbase offset that doesn't exist. |
const void *whole_vtable = *static_cast <const void *const *> (whole_ptr); |
const vtable_prefix *whole_prefix = |
adjust_pointer <vtable_prefix> (whole_vtable, |
-offsetof (vtable_prefix, origin)); |
if (whole_prefix->whole_type != whole_type) |
return NULL; |
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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_alloc.cc |
---|
0,0 → 1,307 |
// -*- C++ -*- Allocate exception objects. |
// Copyright (C) 2001-2015 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> |
#include <new> |
#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 |
namespace |
{ |
// A fixed-size heap, variable size object allocator |
class pool |
{ |
public: |
pool(); |
void *allocate (std::size_t); |
void free (void *); |
bool in_pool (void *); |
private: |
struct free_entry { |
std::size_t size; |
free_entry *next; |
}; |
struct allocated_entry { |
std::size_t size; |
char data[] __attribute__((aligned)); |
}; |
// A single mutex controlling emergency allocations. |
__gnu_cxx::__mutex emergency_mutex; |
// The free-list |
free_entry *first_free_entry; |
// The arena itself - we need to keep track of these only |
// to implement in_pool. |
char *arena; |
std::size_t arena_size; |
}; |
pool::pool() |
{ |
// Allocate the arena - we could add a GLIBCXX_EH_ARENA_SIZE environment |
// to make this tunable. |
arena_size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT |
+ EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception)); |
arena = (char *)malloc (arena_size); |
if (!arena) |
{ |
// If the allocation failed go without an emergency pool. |
arena_size = 0; |
first_free_entry = NULL; |
return; |
} |
// Populate the free-list with a single entry covering the whole arena |
first_free_entry = reinterpret_cast <free_entry *> (arena); |
new (first_free_entry) free_entry; |
first_free_entry->size = arena_size; |
first_free_entry->next = NULL; |
} |
void *pool::allocate (std::size_t size) |
{ |
__gnu_cxx::__scoped_lock sentry(emergency_mutex); |
// We need an additional size_t member plus the padding to |
// ensure proper alignment of data. |
size += offsetof (allocated_entry, data); |
// And we need to at least hand out objects of the size of |
// a freelist entry. |
if (size < sizeof (free_entry)) |
size = sizeof (free_entry); |
// And we need to align objects we hand out to the maximum |
// alignment required on the target (this really aligns the |
// tail which will become a new freelist entry). |
size = ((size + __alignof__ (allocated_entry::data) - 1) |
& ~(__alignof__ (allocated_entry::data) - 1)); |
// Search for an entry of proper size on the freelist. |
free_entry **e; |
for (e = &first_free_entry; |
*e && (*e)->size < size; |
e = &(*e)->next) |
; |
if (!*e) |
return NULL; |
allocated_entry *x; |
if ((*e)->size - size >= sizeof (free_entry)) |
{ |
// Slit block if it is too large. |
free_entry *f = reinterpret_cast <free_entry *> |
(reinterpret_cast <char *> (*e) + size); |
std::size_t sz = (*e)->size; |
free_entry *next = (*e)->next; |
new (f) free_entry; |
f->next = next; |
f->size = sz - size; |
x = reinterpret_cast <allocated_entry *> (*e); |
new (x) allocated_entry; |
x->size = size; |
*e = f; |
} |
else |
{ |
// Exact size match or too small overhead for a free entry. |
std::size_t sz = (*e)->size; |
free_entry *next = (*e)->next; |
x = reinterpret_cast <allocated_entry *> (*e); |
new (x) allocated_entry; |
x->size = sz; |
*e = next; |
} |
return &x->data; |
} |
void pool::free (void *data) |
{ |
__gnu_cxx::__scoped_lock sentry(emergency_mutex); |
allocated_entry *e = reinterpret_cast <allocated_entry *> |
(reinterpret_cast <char *> (data) - offsetof (allocated_entry, data)); |
std::size_t sz = e->size; |
if (!first_free_entry) |
{ |
// If the free list is empty just put the entry there. |
free_entry *f = reinterpret_cast <free_entry *> (e); |
new (f) free_entry; |
f->size = sz; |
f->next = NULL; |
first_free_entry = f; |
} |
else if (reinterpret_cast <char *> (e) + sz |
== reinterpret_cast <char *> (first_free_entry)) |
{ |
// Check if we can merge with the first free entry being right |
// after us. |
free_entry *f = reinterpret_cast <free_entry *> (e); |
new (f) free_entry; |
f->size = sz + first_free_entry->size; |
f->next = first_free_entry->next; |
first_free_entry = f; |
} |
else |
{ |
// Else search for a free item we can merge with at its end. |
free_entry **fe; |
for (fe = &first_free_entry; |
(*fe)->next |
&& (reinterpret_cast <char *> ((*fe)->next) |
> reinterpret_cast <char *> (e) + sz); |
fe = &(*fe)->next) |
; |
if (reinterpret_cast <char *> (*fe) + (*fe)->size |
== reinterpret_cast <char *> (e)) |
/* Merge with the freelist entry. */ |
(*fe)->size += sz; |
else |
{ |
// Else put it after it which keeps the freelist sorted. |
free_entry *f = reinterpret_cast <free_entry *> (e); |
new (f) free_entry; |
f->size = sz; |
f->next = (*fe)->next; |
(*fe)->next = f; |
} |
} |
} |
bool pool::in_pool (void *ptr) |
{ |
char *p = reinterpret_cast <char *> (ptr); |
return (p > arena |
&& p < arena + arena_size); |
} |
pool emergency_pool; |
} |
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) |
ret = emergency_pool.allocate (thrown_size); |
if (!ret) |
std::terminate (); |
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 *ptr = (char *) vptr - sizeof (__cxa_refcounted_exception); |
if (emergency_pool.in_pool (ptr)) |
emergency_pool.free (ptr); |
else |
free (ptr); |
} |
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) |
ret = static_cast <__cxa_dependent_exception*> |
(emergency_pool.allocate (sizeof (__cxa_dependent_exception))); |
if (!ret) |
std::terminate (); |
memset (ret, 0, sizeof (__cxa_dependent_exception)); |
return ret; |
} |
extern "C" void |
__cxxabiv1::__cxa_free_dependent_exception |
(__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW |
{ |
if (emergency_pool.in_pool (vptr)) |
emergency_pool.free (vptr); |
else |
free (vptr); |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_arm.cc |
---|
0,0 → 1,227 |
// -*- C++ -*- ARM specific Exception handling support routines. |
// Copyright (C) 2004-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_aux_runtime.cc |
---|
0,0 → 1,42 |
// -*- C++ -*- Common throw conditions. |
// Copyright (C) 1994-2015 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 "new" |
#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()); } |
extern "C" void |
__cxxabiv1::__cxa_throw_bad_array_new_length () |
{ _GLIBCXX_THROW_OR_ABORT(std::bad_array_new_length()); } |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_call.cc |
---|
0,0 → 1,161 |
// -*- C++ -*- Helpers for calling unextected and terminate |
// Copyright (C) 2001-2015 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 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 NULL. |
void* obj = NULL; |
if (catch_type->__do_catch(&bad_exc, &obj, 1)) |
bad_exception_allowed = true; |
} |
// If the exception spec allows std::bad_exception, throw that. |
#if __cpp_exceptions |
if (bad_exception_allowed) |
throw std::bad_exception(); |
#endif |
// Otherwise, die. |
__terminate(terminateHandler); |
} |
} |
#endif // __ARM_EABI_UNWINDER__ |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_catch.cc |
---|
0,0 → 1,141 |
// -*- C++ -*- Exception handling routines for catching. |
// Copyright (C) 2001-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_exception.cc |
---|
0,0 → 1,50 |
// -*- C++ -*- std::exception implementation. |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_globals.cc |
---|
0,0 → 1,159 |
// -*- C++ -*- Manage the thread-local exception globals. |
// Copyright (C) 2001-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_personality.cc |
---|
0,0 → 1,803 |
// -*- C++ -*- The GNU C++ exception personality routine. |
// Copyright (C) 2001-2015 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: |
// If the unwind state pattern is |
// _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND |
// then we don't need to search for any handler as it is not a real |
// exception. Just unwind the stack. |
if (state & _US_FORCE_UNWIND) |
CONTINUE_UNWINDING; |
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 |
#if __cpp_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 __cpp_exceptions && __cpp_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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_ptr.cc |
---|
0,0 → 1,264 |
// -*- C++ -*- Implement the members of exception_ptr. |
// Copyright (C) 2008-2015 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; |
// Verify assumptions about member layout in exception types |
namespace |
{ |
template<typename Ex> |
constexpr std::size_t unwindhdr() |
{ return offsetof(Ex, unwindHeader); } |
template<typename Ex> |
constexpr std::size_t termHandler() |
{ return unwindhdr<Ex>() - offsetof(Ex, terminateHandler); } |
static_assert( termHandler<__cxa_exception>() |
== termHandler<__cxa_dependent_exception>(), |
"__cxa_dependent_exception::termHandler layout must be" |
" consistent with __cxa_exception::termHandler" ); |
#ifndef __ARM_EABI_UNWINDER__ |
template<typename Ex> |
constexpr std::ptrdiff_t adjptr() |
{ return unwindhdr<Ex>() - offsetof(Ex, adjustedPtr); } |
static_assert( adjptr<__cxa_exception>() |
== adjptr<__cxa_dependent_exception>(), |
"__cxa_dependent_exception::adjustedPtr layout must be" |
" consistent with __cxa_exception::adjustedPtr" ); |
#endif |
} |
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 = get_unexpected (); |
dep->terminateHandler = get_terminate (); |
__GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class); |
dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup; |
__cxa_eh_globals *globals = __cxa_get_globals (); |
globals->uncaughtExceptions += 1; |
#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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_term_handler.cc |
---|
0,0 → 1,44 |
// -*- C++ -*- std::terminate handler |
// Copyright (C) 2002-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_terminate.cc |
---|
0,0 → 1,125 |
// -*- C++ -*- std::terminate, std::unexpected and friends. |
// Copyright (C) 1994-2015 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> |
#include <bits/atomic_lockfree_defines.h> |
#if ATOMIC_POINTER_LOCK_FREE < 2 |
#include <ext/concurrence.h> |
namespace |
{ |
__gnu_cxx::__mutex mx; |
} |
#endif |
using namespace __cxxabiv1; |
void |
__cxxabiv1::__terminate (std::terminate_handler handler) throw () |
{ |
__try |
{ |
handler (); |
std::abort (); |
} |
__catch(...) |
{ std::abort (); } |
} |
void |
std::terminate () throw() |
{ |
__terminate (get_terminate ()); |
} |
void |
__cxxabiv1::__unexpected (std::unexpected_handler handler) |
{ |
handler(); |
std::terminate (); |
} |
void |
std::unexpected () |
{ |
__unexpected (get_unexpected ()); |
} |
std::terminate_handler |
std::set_terminate (std::terminate_handler func) throw() |
{ |
std::terminate_handler old; |
#if ATOMIC_POINTER_LOCK_FREE > 1 |
__atomic_exchange (&__terminate_handler, &func, &old, __ATOMIC_ACQ_REL); |
#else |
__gnu_cxx::__scoped_lock l(mx); |
old = __terminate_handler; |
__terminate_handler = func; |
#endif |
return old; |
} |
std::terminate_handler |
std::get_terminate () noexcept |
{ |
std::terminate_handler func; |
#if ATOMIC_POINTER_LOCK_FREE > 1 |
__atomic_load (&__terminate_handler, &func, __ATOMIC_ACQUIRE); |
#else |
__gnu_cxx::__scoped_lock l(mx); |
func = __terminate_handler; |
#endif |
return func; |
} |
std::unexpected_handler |
std::set_unexpected (std::unexpected_handler func) throw() |
{ |
std::unexpected_handler old; |
#if ATOMIC_POINTER_LOCK_FREE > 1 |
__atomic_exchange (&__unexpected_handler, &func, &old, __ATOMIC_ACQ_REL); |
#else |
__gnu_cxx::__scoped_lock l(mx); |
old = __unexpected_handler; |
__unexpected_handler = func; |
#endif |
return old; |
} |
std::unexpected_handler |
std::get_unexpected () noexcept |
{ |
std::unexpected_handler func; |
#if ATOMIC_POINTER_LOCK_FREE > 1 |
__atomic_load (&__unexpected_handler, &func, __ATOMIC_ACQUIRE); |
#else |
__gnu_cxx::__scoped_lock l(mx); |
func = __unexpected_handler; |
#endif |
return func; |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_throw.cc |
---|
0,0 → 1,126 |
// -*- C++ -*- Exception handling routines for throwing. |
// Copyright (C) 2001-2015 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); |
__cxa_eh_globals *globals = __cxa_get_globals (); |
globals->uncaughtExceptions += 1; |
// 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 = std::get_unexpected (); |
header->exc.terminateHandler = std::get_terminate (); |
__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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_tm.cc |
---|
0,0 → 1,126 |
// -*- C++ -*- Exception handling routines for Transactional Memory. |
// Copyright (C) 2009-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_type.cc |
---|
0,0 → 1,54 |
// -*- C++ -*- Exception handling routines for catching. |
// Copyright (C) 2001-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/eh_unex_handler.cc |
---|
0,0 → 1,29 |
// -*- C++ -*- std::unexpected handler |
// Copyright (C) 2002-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/enum_type_info.cc |
---|
0,0 → 1,32 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/exception |
---|
0,0 → 1,166 |
// Exception Handling support header for -*- C++ -*- |
// Copyright (C) 1995-2015 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; |
#if __cplusplus >= 201103L |
/// Return the current terminate handler. |
terminate_handler get_terminate() noexcept; |
#endif |
/** 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; |
#if __cplusplus >= 201103L |
/// Return the current unexpected handler. |
unexpected_handler get_unexpected() noexcept; |
#endif |
/** 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/exception_defines.h |
---|
0,0 → 1,45 |
// -fno-exceptions Support -*- C++ -*- |
// Copyright (C) 2001-2015 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 |
#if ! __cpp_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/toolchain/gcc/5x/libstdc++-v3/libsupc++/exception_ptr.h |
---|
0,0 → 1,205 |
// Exception Handling support header (exception_ptr class) for -*- C++ -*- |
// Copyright (C) 2008-2015 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 |
make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT |
{ |
#if __cpp_exceptions |
try |
{ |
throw __ex; |
} |
catch(...) |
{ |
return current_exception(); |
} |
#else |
return exception_ptr(); |
#endif |
} |
// _GLIBCXX_RESOLVE_LIB_DEFECTS |
// 1130. copy_exception name misleading |
/// Obtain an exception_ptr pointing to a copy of the supplied object. |
/// This function is deprecated, use std::make_exception_ptr instead. |
template<typename _Ex> |
exception_ptr |
copy_exception(_Ex __ex) _GLIBCXX_USE_NOEXCEPT _GLIBCXX_DEPRECATED; |
template<typename _Ex> |
exception_ptr |
copy_exception(_Ex __ex) _GLIBCXX_USE_NOEXCEPT |
{ return std::make_exception_ptr<_Ex>(__ex); } |
// @} group exceptions |
} // namespace std |
} // extern "C++" |
#pragma GCC visibility pop |
#endif |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/function_type_info.cc |
---|
0,0 → 1,38 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/fundamental_type_info.cc |
---|
0,0 → 1,35 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/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/toolchain/gcc/5x/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/toolchain/gcc/5x/libstdc++-v3/libsupc++/guard.cc |
---|
0,0 → 1,415 |
// Copyright (C) 2002-2015 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() |
{ |
#if __cpp_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/toolchain/gcc/5x/libstdc++-v3/libsupc++/guard_error.cc |
---|
0,0 → 1,31 |
// Copyright (C) 2011-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/hash_bytes.cc |
---|
0,0 → 1,190 |
// Definition of _Hash_bytes. -*- C++ -*- |
// Copyright (C) 2010-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/hash_bytes.h |
---|
0,0 → 1,59 |
// Declarations for hash functions. -*- C++ -*- |
// Copyright (C) 2010-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/initializer_list |
---|
0,0 → 1,107 |
// std::initializer_list support -*- C++ -*- |
// Copyright (C) 2008-2015 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 initializer_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 initializer_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/toolchain/gcc/5x/libstdc++-v3/libsupc++/libiberty.h |
---|
0,0 → 1,686 |
/* Function declarations for libiberty. |
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, |
2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. |
Note - certain prototypes declared in this header file are for |
functions whoes implementation copyright does not belong to the |
FSF. Those prototypes are present in this file for reference |
purposes only and their presence in this file should not construed |
as an indication of ownership by the FSF of the implementation of |
those functions in any way or form whatsoever. |
This program 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, or (at your option) |
any later version. |
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. |
Written by Cygnus Support, 1994. |
The libiberty library provides a number of functions which are |
missing on some operating systems. We do not declare those here, |
to avoid conflicts with the system header files on operating |
systems that do support those functions. In this file we only |
declare those functions which are specific to libiberty. */ |
#ifndef LIBIBERTY_H |
#define LIBIBERTY_H |
#ifdef __cplusplus |
extern "C" { |
#endif |
#include "ansidecl.h" |
/* Get a definition for size_t. */ |
#include <stddef.h> |
/* Get a definition for va_list. */ |
#include <stdarg.h> |
#include <stdio.h> |
/* If the OS supports it, ensure that the supplied stream is setup to |
avoid any multi-threaded locking. Otherwise leave the FILE pointer |
unchanged. If the stream is NULL do nothing. */ |
extern void unlock_stream (FILE *); |
/* If the OS supports it, ensure that the standard I/O streams, stdin, |
stdout and stderr are setup to avoid any multi-threaded locking. |
Otherwise do nothing. */ |
extern void unlock_std_streams (void); |
/* Open and return a FILE pointer. If the OS supports it, ensure that |
the stream is setup to avoid any multi-threaded locking. Otherwise |
return the FILE pointer unchanged. */ |
extern FILE *fopen_unlocked (const char *, const char *); |
extern FILE *fdopen_unlocked (int, const char *); |
extern FILE *freopen_unlocked (const char *, const char *, FILE *); |
/* Build an argument vector from a string. Allocates memory using |
malloc. Use freeargv to free the vector. */ |
extern char **buildargv (const char *) ATTRIBUTE_MALLOC; |
/* Free a vector returned by buildargv. */ |
extern void freeargv (char **); |
/* Duplicate an argument vector. Allocates memory using malloc. Use |
freeargv to free the vector. */ |
extern char **dupargv (char **) ATTRIBUTE_MALLOC; |
/* Expand "@file" arguments in argv. */ |
extern void expandargv (int *, char ***); |
/* Write argv to an @-file, inserting necessary quoting. */ |
extern int writeargv (char **, FILE *); |
/* Return the number of elements in argv. */ |
extern int countargv (char**); |
/* Return the last component of a path name. Note that we can't use a |
prototype here because the parameter is declared inconsistently |
across different systems, sometimes as "char *" and sometimes as |
"const char *" */ |
/* HAVE_DECL_* is a three-state macro: undefined, 0 or 1. If it is |
undefined, we haven't run the autoconf check so provide the |
declaration without arguments. If it is 0, we checked and failed |
to find the declaration so provide a fully prototyped one. If it |
is 1, we found it so don't provide any declaration at all. */ |
#if !HAVE_DECL_BASENAME |
#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) || defined (HAVE_DECL_BASENAME) |
extern char *basename (const char *); |
#else |
/* Do not allow basename to be used if there is no prototype seen. We |
either need to use the above prototype or have one from |
autoconf which would result in HAVE_DECL_BASENAME being set. */ |
#define basename basename_cannot_be_used_without_a_prototype |
#endif |
#endif |
/* A well-defined basename () that is always compiled in. */ |
extern const char *lbasename (const char *); |
/* Same, but assumes DOS semantics (drive name, backslash is also a |
dir separator) regardless of host. */ |
extern const char *dos_lbasename (const char *); |
/* Same, but assumes Unix semantics (absolute paths always start with |
a slash, only forward slash is accepted as dir separator) |
regardless of host. */ |
extern const char *unix_lbasename (const char *); |
/* A well-defined realpath () that is always compiled in. */ |
extern char *lrealpath (const char *); |
/* Concatenate an arbitrary number of strings. You must pass NULL as |
the last argument of this function, to terminate the list of |
strings. Allocates memory using xmalloc. */ |
extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL; |
/* Concatenate an arbitrary number of strings. You must pass NULL as |
the last argument of this function, to terminate the list of |
strings. Allocates memory using xmalloc. The first argument is |
not one of the strings to be concatenated, but if not NULL is a |
pointer to be freed after the new string is created, similar to the |
way xrealloc works. */ |
extern char *reconcat (char *, const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL; |
/* Determine the length of concatenating an arbitrary number of |
strings. You must pass NULL as the last argument of this function, |
to terminate the list of strings. */ |
extern unsigned long concat_length (const char *, ...) ATTRIBUTE_SENTINEL; |
/* Concatenate an arbitrary number of strings into a SUPPLIED area of |
memory. You must pass NULL as the last argument of this function, |
to terminate the list of strings. The supplied memory is assumed |
to be large enough. */ |
extern char *concat_copy (char *, const char *, ...) ATTRIBUTE_SENTINEL; |
/* Concatenate an arbitrary number of strings into a GLOBAL area of |
memory. You must pass NULL as the last argument of this function, |
to terminate the list of strings. The supplied memory is assumed |
to be large enough. */ |
extern char *concat_copy2 (const char *, ...) ATTRIBUTE_SENTINEL; |
/* This is the global area used by concat_copy2. */ |
extern char *libiberty_concat_ptr; |
/* Concatenate an arbitrary number of strings. You must pass NULL as |
the last argument of this function, to terminate the list of |
strings. Allocates memory using alloca. The arguments are |
evaluated twice! */ |
#define ACONCAT(ACONCAT_PARAMS) \ |
(libiberty_concat_ptr = (char *) alloca (concat_length ACONCAT_PARAMS + 1), \ |
concat_copy2 ACONCAT_PARAMS) |
/* Check whether two file descriptors refer to the same file. */ |
extern int fdmatch (int fd1, int fd2); |
/* Return the position of the first bit set in the argument. */ |
/* Prototypes vary from system to system, so we only provide a |
prototype on systems where we know that we need it. */ |
#if defined (HAVE_DECL_FFS) && !HAVE_DECL_FFS |
extern int ffs(int); |
#endif |
/* Get the working directory. The result is cached, so don't call |
chdir() between calls to getpwd(). */ |
extern char * getpwd (void); |
/* Get the current time. */ |
/* Prototypes vary from system to system, so we only provide a |
prototype on systems where we know that we need it. */ |
#ifdef __MINGW32__ |
/* Forward declaration to avoid #include <sys/time.h>. */ |
struct timeval; |
extern int gettimeofday (struct timeval *, void *); |
#endif |
/* Get the amount of time the process has run, in microseconds. */ |
extern long get_run_time (void); |
/* Generate a relocated path to some installation directory. Allocates |
return value using malloc. */ |
extern char *make_relative_prefix (const char *, const char *, |
const char *) ATTRIBUTE_MALLOC; |
/* Generate a relocated path to some installation directory without |
attempting to follow any soft links. Allocates |
return value using malloc. */ |
extern char *make_relative_prefix_ignore_links (const char *, const char *, |
const char *) ATTRIBUTE_MALLOC; |
/* Choose a temporary directory to use for scratch files. */ |
extern char *choose_temp_base (void) ATTRIBUTE_MALLOC; |
/* Return a temporary file name or NULL if unable to create one. */ |
extern char *make_temp_file (const char *) ATTRIBUTE_MALLOC; |
/* Remove a link to a file unless it is special. */ |
extern int unlink_if_ordinary (const char *); |
/* Allocate memory filled with spaces. Allocates using malloc. */ |
extern const char *spaces (int count); |
/* Return the maximum error number for which strerror will return a |
string. */ |
extern int errno_max (void); |
/* Return the name of an errno value (e.g., strerrno (EINVAL) returns |
"EINVAL"). */ |
extern const char *strerrno (int); |
/* Given the name of an errno value, return the value. */ |
extern int strtoerrno (const char *); |
/* ANSI's strerror(), but more robust. */ |
extern char *xstrerror (int); |
/* Return the maximum signal number for which strsignal will return a |
string. */ |
extern int signo_max (void); |
/* Return a signal message string for a signal number |
(e.g., strsignal (SIGHUP) returns something like "Hangup"). */ |
/* This is commented out as it can conflict with one in system headers. |
We still document its existence though. */ |
/*extern const char *strsignal (int);*/ |
/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns |
"SIGHUP"). */ |
extern const char *strsigno (int); |
/* Given the name of a signal, return its number. */ |
extern int strtosigno (const char *); |
/* Register a function to be run by xexit. Returns 0 on success. */ |
extern int xatexit (void (*fn) (void)); |
/* Exit, calling all the functions registered with xatexit. */ |
extern void xexit (int status) ATTRIBUTE_NORETURN; |
/* Set the program name used by xmalloc. */ |
extern void xmalloc_set_program_name (const char *); |
/* Report an allocation failure. */ |
extern void xmalloc_failed (size_t) ATTRIBUTE_NORETURN; |
/* Allocate memory without fail. If malloc fails, this will print a |
message to stderr (using the name set by xmalloc_set_program_name, |
if any) and then call xexit. */ |
extern void *xmalloc (size_t) ATTRIBUTE_MALLOC; |
/* Reallocate memory without fail. This works like xmalloc. Note, |
realloc type functions are not suitable for attribute malloc since |
they may return the same address across multiple calls. */ |
extern void *xrealloc (void *, size_t); |
/* Allocate memory without fail and set it to zero. This works like |
xmalloc. */ |
extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC; |
/* Copy a string into a memory buffer without fail. */ |
extern char *xstrdup (const char *) ATTRIBUTE_MALLOC; |
/* Copy at most N characters from string into a buffer without fail. */ |
extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC; |
/* Copy an existing memory buffer to a new memory buffer without fail. */ |
extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC; |
/* Physical memory routines. Return values are in BYTES. */ |
extern double physmem_total (void); |
extern double physmem_available (void); |
/* Compute the 32-bit CRC of a block of memory. */ |
extern unsigned int xcrc32 (const unsigned char *, int, unsigned int); |
/* These macros provide a K&R/C89/C++-friendly way of allocating structures |
with nice encapsulation. The XDELETE*() macros are technically |
superfluous, but provided here for symmetry. Using them consistently |
makes it easier to update client code to use different allocators such |
as new/delete and new[]/delete[]. */ |
/* Scalar allocators. */ |
#define XALLOCA(T) ((T *) alloca (sizeof (T))) |
#define XNEW(T) ((T *) xmalloc (sizeof (T))) |
#define XCNEW(T) ((T *) xcalloc (1, sizeof (T))) |
#define XDUP(T, P) ((T *) xmemdup ((P), sizeof (T), sizeof (T))) |
#define XDELETE(P) free ((void*) (P)) |
/* Array allocators. */ |
#define XALLOCAVEC(T, N) ((T *) alloca (sizeof (T) * (N))) |
#define XNEWVEC(T, N) ((T *) xmalloc (sizeof (T) * (N))) |
#define XCNEWVEC(T, N) ((T *) xcalloc ((N), sizeof (T))) |
#define XDUPVEC(T, P, N) ((T *) xmemdup ((P), sizeof (T) * (N), sizeof (T) * (N))) |
#define XRESIZEVEC(T, P, N) ((T *) xrealloc ((void *) (P), sizeof (T) * (N))) |
#define XDELETEVEC(P) free ((void*) (P)) |
/* Allocators for variable-sized structures and raw buffers. */ |
#define XALLOCAVAR(T, S) ((T *) alloca ((S))) |
#define XNEWVAR(T, S) ((T *) xmalloc ((S))) |
#define XCNEWVAR(T, S) ((T *) xcalloc (1, (S))) |
#define XDUPVAR(T, P, S1, S2) ((T *) xmemdup ((P), (S1), (S2))) |
#define XRESIZEVAR(T, P, S) ((T *) xrealloc ((P), (S))) |
/* Type-safe obstack allocator. */ |
#define XOBNEW(O, T) ((T *) obstack_alloc ((O), sizeof (T))) |
#define XOBNEWVEC(O, T, N) ((T *) obstack_alloc ((O), sizeof (T) * (N))) |
#define XOBNEWVAR(O, T, S) ((T *) obstack_alloc ((O), (S))) |
#define XOBFINISH(O, T) ((T) obstack_finish ((O))) |
/* hex character manipulation routines */ |
#define _hex_array_size 256 |
#define _hex_bad 99 |
extern const unsigned char _hex_value[_hex_array_size]; |
extern void hex_init (void); |
#define hex_p(c) (hex_value (c) != _hex_bad) |
/* If you change this, note well: Some code relies on side effects in |
the argument being performed exactly once. */ |
#define hex_value(c) ((unsigned int) _hex_value[(unsigned char) (c)]) |
/* Flags for pex_init. These are bits to be or'ed together. */ |
/* Record subprocess times, if possible. */ |
#define PEX_RECORD_TIMES 0x1 |
/* Use pipes for communication between processes, if possible. */ |
#define PEX_USE_PIPES 0x2 |
/* Save files used for communication between processes. */ |
#define PEX_SAVE_TEMPS 0x4 |
/* Prepare to execute one or more programs, with standard output of |
each program fed to standard input of the next. |
FLAGS As above. |
PNAME The name of the program to report in error messages. |
TEMPBASE A base name to use for temporary files; may be NULL to |
use a random name. |
Returns NULL on error. */ |
extern struct pex_obj *pex_init (int flags, const char *pname, |
const char *tempbase); |
/* Flags for pex_run. These are bits to be or'ed together. */ |
/* Last program in pipeline. Standard output of program goes to |
OUTNAME, or, if OUTNAME is NULL, to standard output of caller. Do |
not set this if you want to call pex_read_output. After this is |
set, pex_run may no longer be called with the same struct |
pex_obj. */ |
#define PEX_LAST 0x1 |
/* Search for program in executable search path. */ |
#define PEX_SEARCH 0x2 |
/* OUTNAME is a suffix. */ |
#define PEX_SUFFIX 0x4 |
/* Send program's standard error to standard output. */ |
#define PEX_STDERR_TO_STDOUT 0x8 |
/* Input file should be opened in binary mode. This flag is ignored |
on Unix. */ |
#define PEX_BINARY_INPUT 0x10 |
/* Output file should be opened in binary mode. This flag is ignored |
on Unix. For proper behaviour PEX_BINARY_INPUT and |
PEX_BINARY_OUTPUT have to match appropriately--i.e., a call using |
PEX_BINARY_OUTPUT should be followed by a call using |
PEX_BINARY_INPUT. */ |
#define PEX_BINARY_OUTPUT 0x20 |
/* Capture stderr to a pipe. The output can be read by |
calling pex_read_err and reading from the returned |
FILE object. This flag may be specified only for |
the last program in a pipeline. |
This flag is supported only on Unix and Windows. */ |
#define PEX_STDERR_TO_PIPE 0x40 |
/* Capture stderr in binary mode. This flag is ignored |
on Unix. */ |
#define PEX_BINARY_ERROR 0x80 |
/* Execute one program. Returns NULL on success. On error returns an |
error string (typically just the name of a system call); the error |
string is statically allocated. |
OBJ Returned by pex_init. |
FLAGS As above. |
EXECUTABLE The program to execute. |
ARGV NULL terminated array of arguments to pass to the program. |
OUTNAME Sets the output file name as follows: |
PEX_SUFFIX set (OUTNAME may not be NULL): |
TEMPBASE parameter to pex_init not NULL: |
Output file name is the concatenation of TEMPBASE |
and OUTNAME. |
TEMPBASE is NULL: |
Output file name is a random file name ending in |
OUTNAME. |
PEX_SUFFIX not set: |
OUTNAME not NULL: |
Output file name is OUTNAME. |
OUTNAME NULL, TEMPBASE not NULL: |
Output file name is randomly chosen using |
TEMPBASE. |
OUTNAME NULL, TEMPBASE NULL: |
Output file name is randomly chosen. |
If PEX_LAST is not set, the output file name is the |
name to use for a temporary file holding stdout, if |
any (there will not be a file if PEX_USE_PIPES is set |
and the system supports pipes). If a file is used, it |
will be removed when no longer needed unless |
PEX_SAVE_TEMPS is set. |
If PEX_LAST is set, and OUTNAME is not NULL, standard |
output is written to the output file name. The file |
will not be removed. If PEX_LAST and PEX_SUFFIX are |
both set, TEMPBASE may not be NULL. |
ERRNAME If not NULL, this is the name of a file to which |
standard error is written. If NULL, standard error of |
the program is standard error of the caller. |
ERR On an error return, *ERR is set to an errno value, or |
to 0 if there is no relevant errno. |
*/ |
extern const char *pex_run (struct pex_obj *obj, int flags, |
const char *executable, char * const *argv, |
const char *outname, const char *errname, |
int *err); |
/* As for pex_run (), but takes an extra parameter to enable the |
environment for the child process to be specified. |
ENV The environment for the child process, specified as |
an array of character pointers. Each element of the |
array should point to a string of the form VAR=VALUE, |
with the exception of the last element which must be |
a null pointer. |
*/ |
extern const char *pex_run_in_environment (struct pex_obj *obj, int flags, |
const char *executable, |
char * const *argv, |
char * const *env, |
const char *outname, |
const char *errname, int *err); |
/* Return a stream for a temporary file to pass to the first program |
in the pipeline as input. The file name is chosen as for pex_run. |
pex_run closes the file automatically; don't close it yourself. */ |
extern FILE *pex_input_file (struct pex_obj *obj, int flags, |
const char *in_name); |
/* Return a stream for a pipe connected to the standard input of the |
first program in the pipeline. You must have passed |
`PEX_USE_PIPES' to `pex_init'. Close the returned stream |
yourself. */ |
extern FILE *pex_input_pipe (struct pex_obj *obj, int binary); |
/* Read the standard output of the last program to be executed. |
pex_run can not be called after this. BINARY should be non-zero if |
the file should be opened in binary mode; this is ignored on Unix. |
Returns NULL on error. Don't call fclose on the returned FILE; it |
will be closed by pex_free. */ |
extern FILE *pex_read_output (struct pex_obj *, int binary); |
/* Read the standard error of the last program to be executed. |
pex_run can not be called after this. BINARY should be non-zero if |
the file should be opened in binary mode; this is ignored on Unix. |
Returns NULL on error. Don't call fclose on the returned FILE; it |
will be closed by pex_free. */ |
extern FILE *pex_read_err (struct pex_obj *, int binary); |
/* Return exit status of all programs in VECTOR. COUNT indicates the |
size of VECTOR. The status codes in the vector are in the order of |
the calls to pex_run. Returns 0 on error, 1 on success. */ |
extern int pex_get_status (struct pex_obj *, int count, int *vector); |
/* Return times of all programs in VECTOR. COUNT indicates the size |
of VECTOR. struct pex_time is really just struct timeval, but that |
is not portable to all systems. Returns 0 on error, 1 on |
success. */ |
struct pex_time |
{ |
unsigned long user_seconds; |
unsigned long user_microseconds; |
unsigned long system_seconds; |
unsigned long system_microseconds; |
}; |
extern int pex_get_times (struct pex_obj *, int count, |
struct pex_time *vector); |
/* Clean up a pex_obj. If you have not called pex_get_times or |
pex_get_status, this will try to kill the subprocesses. */ |
extern void pex_free (struct pex_obj *); |
/* Just execute one program. Return value is as for pex_run. |
FLAGS Combination of PEX_SEARCH and PEX_STDERR_TO_STDOUT. |
EXECUTABLE As for pex_run. |
ARGV As for pex_run. |
PNAME As for pex_init. |
OUTNAME As for pex_run when PEX_LAST is set. |
ERRNAME As for pex_run. |
STATUS Set to exit status on success. |
ERR As for pex_run. |
*/ |
extern const char *pex_one (int flags, const char *executable, |
char * const *argv, const char *pname, |
const char *outname, const char *errname, |
int *status, int *err); |
/* pexecute and pwait are the old pexecute interface, still here for |
backward compatibility. Don't use these for new code. Instead, |
use pex_init/pex_run/pex_get_status/pex_free, or pex_one. */ |
/* Definitions used by the pexecute routine. */ |
#define PEXECUTE_FIRST 1 |
#define PEXECUTE_LAST 2 |
#define PEXECUTE_ONE (PEXECUTE_FIRST + PEXECUTE_LAST) |
#define PEXECUTE_SEARCH 4 |
#define PEXECUTE_VERBOSE 8 |
/* Execute a program. */ |
extern int pexecute (const char *, char * const *, const char *, |
const char *, char **, char **, int); |
/* Wait for pexecute to finish. */ |
extern int pwait (int, int *, int); |
#if !HAVE_DECL_ASPRINTF |
/* Like sprintf but provides a pointer to malloc'd storage, which must |
be freed by the caller. */ |
extern int asprintf (char **, const char *, ...) ATTRIBUTE_PRINTF_2; |
#endif |
#if !HAVE_DECL_VASPRINTF |
/* Like vsprintf but provides a pointer to malloc'd storage, which |
must be freed by the caller. */ |
extern int vasprintf (char **, const char *, va_list) ATTRIBUTE_PRINTF(2,0); |
#endif |
#if defined(HAVE_DECL_SNPRINTF) && !HAVE_DECL_SNPRINTF |
/* Like sprintf but prints at most N characters. */ |
extern int snprintf (char *, size_t, const char *, ...) ATTRIBUTE_PRINTF_3; |
#endif |
#if defined(HAVE_DECL_VSNPRINTF) && !HAVE_DECL_VSNPRINTF |
/* Like vsprintf but prints at most N characters. */ |
extern int vsnprintf (char *, size_t, const char *, va_list) ATTRIBUTE_PRINTF(3,0); |
#endif |
#if defined(HAVE_DECL_STRVERSCMP) && !HAVE_DECL_STRVERSCMP |
/* Compare version strings. */ |
extern int strverscmp (const char *, const char *); |
#endif |
/* Set the title of a process */ |
extern void setproctitle (const char *name, ...); |
/* Increase stack limit if possible. */ |
extern void stack_limit_increase (unsigned long); |
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) |
/* Drastically simplified alloca configurator. If we're using GCC, |
we use __builtin_alloca; otherwise we use the C alloca. The C |
alloca is always available. You can override GCC by defining |
USE_C_ALLOCA yourself. The canonical autoconf macro C_ALLOCA is |
also set/unset as it is often used to indicate whether code needs |
to call alloca(0). */ |
extern void *C_alloca (size_t) ATTRIBUTE_MALLOC; |
#undef alloca |
#if GCC_VERSION >= 2000 && !defined USE_C_ALLOCA |
# define alloca(x) __builtin_alloca(x) |
# undef C_ALLOCA |
# define ASTRDUP(X) \ |
(__extension__ ({ const char *const libiberty_optr = (X); \ |
const unsigned long libiberty_len = strlen (libiberty_optr) + 1; \ |
char *const libiberty_nptr = (char *const) alloca (libiberty_len); \ |
(char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len); })) |
#else |
# define alloca(x) C_alloca(x) |
# undef USE_C_ALLOCA |
# define USE_C_ALLOCA 1 |
# undef C_ALLOCA |
# define C_ALLOCA 1 |
extern const char *libiberty_optr; |
extern char *libiberty_nptr; |
extern unsigned long libiberty_len; |
# define ASTRDUP(X) \ |
(libiberty_optr = (X), \ |
libiberty_len = strlen (libiberty_optr) + 1, \ |
libiberty_nptr = (char *) alloca (libiberty_len), \ |
(char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len)) |
#endif |
#ifdef __cplusplus |
} |
#endif |
#endif /* ! defined (LIBIBERTY_H) */ |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/nested_exception.cc |
---|
0,0 → 1,31 |
// Copyright (C) 2011-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/nested_exception.h |
---|
0,0 → 1,173 |
// Nested Exception support header (nested_exception class) for -*- C++ -*- |
// Copyright (C) 2009-2015 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&) noexcept = default; |
nested_exception& operator=(const nested_exception&) noexcept = default; |
virtual ~nested_exception() noexcept; |
[[noreturn]] |
void |
rethrow_nested() const |
{ |
if (_M_ptr) |
rethrow_exception(_M_ptr); |
std::terminate(); |
} |
exception_ptr |
nested_ptr() const noexcept |
{ return _M_ptr; } |
}; |
template<typename _Except> |
struct _Nested_exception : public _Except, public nested_exception |
{ |
explicit _Nested_exception(const _Except& __ex) |
: _Except(__ex) |
{ } |
explicit _Nested_exception(_Except&& __ex) |
: _Except(static_cast<_Except&&>(__ex)) |
{ } |
}; |
template<typename _Tp, |
bool __with_nested = !__is_base_of(nested_exception, _Tp)> |
struct _Throw_with_nested_impl |
{ |
template<typename _Up> |
static void _S_throw(_Up&& __t) |
{ throw _Nested_exception<_Tp>{static_cast<_Up&&>(__t)}; } |
}; |
template<typename _Tp> |
struct _Throw_with_nested_impl<_Tp, false> |
{ |
template<typename _Up> |
static void _S_throw(_Up&& __t) |
{ throw static_cast<_Up&&>(__t); } |
}; |
template<typename _Tp, bool = __is_class(_Tp) && !__is_final(_Tp)> |
struct _Throw_with_nested_helper : _Throw_with_nested_impl<_Tp> |
{ }; |
template<typename _Tp> |
struct _Throw_with_nested_helper<_Tp, false> |
: _Throw_with_nested_impl<_Tp, false> |
{ }; |
template<typename _Tp> |
struct _Throw_with_nested_helper<_Tp&, false> |
: _Throw_with_nested_helper<_Tp> |
{ }; |
template<typename _Tp> |
struct _Throw_with_nested_helper<_Tp&&, false> |
: _Throw_with_nested_helper<_Tp> |
{ }; |
/// If @p __t is derived from nested_exception, throws @p __t. |
/// Else, throws an implementation-defined object derived from both. |
template<typename _Tp> |
[[noreturn]] |
inline void |
throw_with_nested(_Tp&& __t) |
{ |
_Throw_with_nested_helper<_Tp>::_S_throw(static_cast<_Tp&&>(__t)); |
} |
template<typename _Tp, bool = __is_polymorphic(_Tp)> |
struct _Rethrow_if_nested_impl |
{ |
static void _S_rethrow(const _Tp& __t) |
{ |
if (auto __tp = dynamic_cast<const nested_exception*>(&__t)) |
__tp->rethrow_nested(); |
} |
}; |
template<typename _Tp> |
struct _Rethrow_if_nested_impl<_Tp, false> |
{ |
static void _S_rethrow(const _Tp&) { } |
}; |
/// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). |
template<typename _Ex> |
inline void |
rethrow_if_nested(const _Ex& __ex) |
{ |
_Rethrow_if_nested_impl<_Ex>::_S_rethrow(__ex); |
} |
// @} group exceptions |
} // namespace std |
} // extern "C++" |
#endif // C++11 |
#pragma GCC visibility pop |
#endif // _GLIBCXX_NESTED_EXCEPTION_H |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/new |
---|
0,0 → 1,142 |
// The -*- C++ -*- dynamic memory management header. |
// Copyright (C) 1994-2015 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(); |
}; |
#if __cplusplus >= 201103L |
class bad_array_new_length : public bad_alloc |
{ |
public: |
bad_array_new_length() throw() { }; |
// This declaration is not useless: |
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
virtual ~bad_array_new_length() throw(); |
// See comment in eh_exception.cc. |
virtual const char* what() const throw(); |
}; |
#endif |
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(); |
#if __cplusplus >= 201103L |
/// Return the current new handler. |
new_handler get_new_handler() noexcept; |
#endif |
} // 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/new_handler.cc |
---|
0,0 → 1,71 |
// Implementation file for the -*- C++ -*- dynamic memory management header. |
// Copyright (C) 1996-2015 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" |
#include <bits/atomic_lockfree_defines.h> |
#if ATOMIC_POINTER_LOCK_FREE < 2 |
#include <ext/concurrence.h> |
namespace |
{ |
__gnu_cxx::__mutex mx; |
} |
#endif |
const std::nothrow_t std::nothrow = { }; |
using std::new_handler; |
namespace |
{ |
new_handler __new_handler; |
} |
new_handler |
std::set_new_handler (new_handler handler) throw() |
{ |
new_handler prev_handler; |
#if ATOMIC_POINTER_LOCK_FREE > 1 |
__atomic_exchange (&__new_handler, &handler, &prev_handler, |
__ATOMIC_ACQ_REL); |
#else |
__gnu_cxx::__scoped_lock l(mx); |
prev_handler = __new_handler; |
__new_handler = handler; |
#endif |
return prev_handler; |
} |
new_handler |
std::get_new_handler () noexcept |
{ |
new_handler handler; |
#if ATOMIC_POINTER_LOCK_FREE > 1 |
__atomic_load (&__new_handler, &handler, __ATOMIC_ACQUIRE); |
#else |
__gnu_cxx::__scoped_lock l(mx); |
handler = __new_handler; |
#endif |
return handler; |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/new_op.cc |
---|
0,0 → 1,59 |
// Support routines for the -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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 |
_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; |
while (__builtin_expect ((p = malloc (sz)) == 0, false)) |
{ |
new_handler handler = std::get_new_handler (); |
if (! handler) |
_GLIBCXX_THROW_OR_ABORT(bad_alloc()); |
handler (); |
} |
return p; |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/new_opnt.cc |
---|
0,0 → 1,59 |
// Support routines for the -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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); |
_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; |
while (__builtin_expect ((p = malloc (sz)) == 0, false)) |
{ |
new_handler handler = std::get_new_handler (); |
if (! handler) |
return 0; |
__try |
{ |
handler (); |
} |
__catch(const bad_alloc&) |
{ |
return 0; |
} |
} |
return p; |
} |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/new_opv.cc |
---|
0,0 → 1,33 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/new_opvnt.cc |
---|
0,0 → 1,34 |
// Boilerplate support routines for -*- C++ -*- dynamic memory management. |
// Copyright (C) 1997-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/pbase_type_info.cc |
---|
0,0 → 1,64 |
// Copyright (C) 1994-2015 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 |
#if __cpp_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/toolchain/gcc/5x/libstdc++-v3/libsupc++/pmem_type_info.cc |
---|
0,0 → 1,48 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/pointer_type_info.cc |
---|
0,0 → 1,54 |
// Copyright (C) 1994-2015 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 |
{ |
#if __cpp_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/toolchain/gcc/5x/libstdc++-v3/libsupc++/pure.cc |
---|
0,0 → 1,58 |
// -*- C++ -*- |
// Copyright (C) 2000-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/si_class_type_info.cc |
---|
0,0 → 1,84 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/tinfo.cc |
---|
0,0 → 1,82 |
// Methods for type_info for -*- C++ -*- Run Time Type Identification. |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/tinfo.h |
---|
0,0 → 1,174 |
// RTTI support internals for -*- C++ -*- |
// Copyright (C) 1994-2015 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 { |
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/toolchain/gcc/5x/libstdc++-v3/libsupc++/tinfo2.cc |
---|
0,0 → 1,44 |
// Methods for type_info for -*- C++ -*- Run Time Type Identification. |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/typeinfo |
---|
0,0 → 1,222 |
// RTTI support for -*- C++ -*- |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/unwind-cxx.h |
---|
0,0 → 1,399 |
// -*- C++ -*- Exception handling and frame unwind runtime interface routines. |
// Copyright (C) 2001-2015 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 number 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; |
// Unused member to get similar layout to __cxa_exception, otherwise the |
// alignment requirements of _Unwind_Exception would require padding bytes |
// before the unwindHeader member. |
void (_GLIBCXX_CDTOR_CALLABI *__padding)(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 number 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/toolchain/gcc/5x/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/toolchain/gcc/5x/libstdc++-v3/libsupc++/vec.cc |
---|
0,0 → 1,530 |
// New abi Support -*- C++ -*- |
// Copyright (C) 2000-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/vmi_class_type_info.cc |
---|
0,0 → 1,390 |
// Copyright (C) 1994-2015 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/toolchain/gcc/5x/libstdc++-v3/libsupc++/vterminate.cc |
---|
0,0 → 1,101 |
// Verbose terminate_handler -*- C++ -*- |
// Copyright (C) 2001-2015 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; } |
#if __cpp_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 |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/vterminate.idb |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/contrib/toolchain/gcc/5x/libstdc++-v3/libsupc++/vtv_stubs.cc |
---|
0,0 → 1,134 |
// Copyright (C) 2012-2015 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 is part of the vtable verification runtime library. For more |
information about this feature, see the comments in libvtv/vtv_rts.cc. */ |
/* The functions in this file are used to create the libvtv_stubs |
library, as part of the vtable verification feature. When building |
a binary without vtable verification, and linking it with a |
(possibly pre-built third-party) library that was built with |
verification, it is possible that vtable verification will fail due |
to incomplete data (rather than due to corrupt vtable pointers). In |
this case we need to give programmers a way of turning off the |
vtable verification in their libraries. They can do so by linking |
with the libvtv_stubs library, which (as you can see) will replace |
the real verification functions with a set of functions that do |
nothing (so no more verification failures/aborts). */ |
#include <cstddef> |
/* weak symbols on Windows work differently than on Linux. To be able |
to switch vtv on and off on Windows two dlls are built. One with |
the sources from libvtv, the other from these stubs. Depending on |
which dll is placed in the folder of the executable the functions |
from libvtv or the stubs functions are used. */ |
#if defined (__CYGWIN__) || defined (__MINGW32__) |
extern "C" |
void |
__VLTChangePermission(int); |
void |
__VLTRegisterSet(void**, const void*, std::size_t, std::size_t, |
void**); |
void |
__VLTRegisterPair(void**, const void*, std::size_t, |
const void*); |
const void* |
__VLTVerifyVtablePointer(void**, const void*); |
void |
__VLTRegisterSetDebug(void**, const void*, std::size_t, std::size_t, |
void**); |
void |
__VLTRegisterPairDebug(void**, const void*, std::size_t, const void*, |
const char*, const char*); |
const void* |
__VLTVerifyVtablePointerDebug(void**, const void*, const char*, |
const char*); |
#else |
// Declare as weak for libsupc++, strong definitions are in libvtv. |
#if __GXX_WEAK__ |
extern "C" |
void |
__VLTChangePermission(int) __attribute__((weak)); |
void |
__VLTRegisterSet(void**, const void*, std::size_t, std::size_t, |
void**) __attribute__((weak)); |
void |
__VLTRegisterPair(void**, const void*, std::size_t, |
const void*) __attribute__((weak)); |
const void* |
__VLTVerifyVtablePointer(void**, const void*) __attribute__((weak)); |
void |
__VLTRegisterSetDebug(void**, const void*, std::size_t, std::size_t, |
void**) __attribute__((weak)); |
void |
__VLTRegisterPairDebug(void**, const void*, std::size_t, const void*, |
const char*, const char*) __attribute__((weak)); |
const void* |
__VLTVerifyVtablePointerDebug(void**, const void*, const char*, |
const char*) __attribute__((weak)); |
#endif |
#endif |
// Stub definitions. |
extern "C" |
void |
__VLTChangePermission(int) |
{ } |
void |
__VLTRegisterSet(void**, const void*, std::size_t, std::size_t, void**) |
{ } |
void |
__VLTRegisterPair(void**, const void*, std::size_t, const void*) |
{ } |
const void* |
__VLTVerifyVtablePointer(void**, const void* vtable_ptr) |
{ return vtable_ptr; } |
void |
__VLTRegisterSetDebug(void**, const void*, std::size_t, std::size_t, void**) |
{ } |
void |
__VLTRegisterPairDebug(void**, const void*, std::size_t, const void*, |
const char*, const char*) |
{ } |
const void* |
__VLTVerifyVtablePointerDebug(void**, const void* vtable_ptr, const char*, |
const char*) |
{ return vtable_ptr; } |