From 9ab916b8ed43541ad87ded43671f473671370b0b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 7 Oct 2000 12:21:05 -0700 Subject: [PATCH] del_op.cc, [...]: New files. * del_op.cc, del_opnt.cc, del_opv.cc, del_opvnt.cc: New files. * exception.cc, new_handler.cc, new_op.cc, new_opnt.cc: New files. * new_opv.cc, new_opvnt.cc, tinfo.cc, tinfo2.cc, vec.cc: New files. * cxxabi.h, exception, new, new.h, typeinfo, pure.c: New files. * tinfo.hP: New file. * Makefile.in (OBJS, HEADERS): Add new files. * configure.in (XCXXINCLUDES): Add ../include and ../gcc. From-SVN: r36780 --- libstdc++/ChangeLog | 11 + libstdc++/Makefile.in | 29 +- libstdc++/configure.in | 2 +- libstdc++/cxxabi.h | 519 ++++++++++++++++ libstdc++/del_op.cc | 39 ++ libstdc++/del_opnt.cc | 39 ++ libstdc++/del_opv.cc | 36 ++ libstdc++/del_opvnt.cc | 36 ++ libstdc++/exception | 65 ++ libstdc++/exception.cc | 403 +++++++++++++ libstdc++/new | 68 +++ libstdc++/new.h | 38 ++ libstdc++/new_handler.cc | 44 ++ libstdc++/new_op.cc | 56 ++ libstdc++/new_opnt.cc | 64 ++ libstdc++/new_opv.cc | 36 ++ libstdc++/new_opvnt.cc | 36 ++ libstdc++/pure.c | 16 + libstdc++/tinfo.cc | 1210 ++++++++++++++++++++++++++++++++++++++ libstdc++/tinfo.hP | 223 +++++++ libstdc++/tinfo2.cc | 452 ++++++++++++++ libstdc++/typeinfo | 134 +++++ libstdc++/vec.cc | 279 +++++++++ 23 files changed, 3830 insertions(+), 5 deletions(-) create mode 100644 libstdc++/cxxabi.h create mode 100644 libstdc++/del_op.cc create mode 100644 libstdc++/del_opnt.cc create mode 100644 libstdc++/del_opv.cc create mode 100644 libstdc++/del_opvnt.cc create mode 100644 libstdc++/exception create mode 100644 libstdc++/exception.cc create mode 100644 libstdc++/new create mode 100644 libstdc++/new.h create mode 100644 libstdc++/new_handler.cc create mode 100644 libstdc++/new_op.cc create mode 100644 libstdc++/new_opnt.cc create mode 100644 libstdc++/new_opv.cc create mode 100644 libstdc++/new_opvnt.cc create mode 100644 libstdc++/pure.c create mode 100644 libstdc++/tinfo.cc create mode 100644 libstdc++/tinfo.hP create mode 100644 libstdc++/tinfo2.cc create mode 100644 libstdc++/typeinfo create mode 100644 libstdc++/vec.cc diff --git a/libstdc++/ChangeLog b/libstdc++/ChangeLog index 5da8c11dfa9..9fa25078079 100644 --- a/libstdc++/ChangeLog +++ b/libstdc++/ChangeLog @@ -1,3 +1,14 @@ +2000-10-07 Richard Henderson + + * del_op.cc, del_opnt.cc, del_opv.cc, del_opvnt.cc: New files. + * exception.cc, new_handler.cc, new_op.cc, new_opnt.cc: New files. + * new_opv.cc, new_opvnt.cc, tinfo.cc, tinfo2.cc, vec.cc: New files. + * cxxabi.h, exception, new, new.h, typeinfo, pure.c: New files. + * tinfo.hP: New file. + + * Makefile.in (OBJS, HEADERS): Add new files. + * configure.in (XCXXINCLUDES): Add ../include and ../gcc. + 2000-09-19 David Edelsohn * configure.in: Add AIX multithread support fragment. diff --git a/libstdc++/Makefile.in b/libstdc++/Makefile.in index cbbc14901df..3db3b73a780 100644 --- a/libstdc++/Makefile.in +++ b/libstdc++/Makefile.in @@ -19,7 +19,11 @@ INTERFACE = 3 gxx_include_dir=${includedir}/g++ -OBJS = cstringi.o stdexcepti.o cstdlibi.o cmathi.o stlinst.o valarray.o +OBJS = cstringi.o stdexcepti.o cstdlibi.o cmathi.o stlinst.o valarray.o \ + del_op.o del_opnt.o del_opv.o del_opvnt.o exception.o new_handler.o \ + new_op.o new_opnt.o new_opv.o new_opvnt.o tinfo.o tinfo2.o vec.o \ + pure.o + SUBLIBS = $(STAMP)-string $(STAMP)-complx # C++ headers with no extension @@ -29,7 +33,7 @@ HEADERS= cassert cctype cerrno cfloat ciso646 climits clocale cmath complex \ algorithm deque functional hash_map hash_set iterator list map \ memory numeric pthread_alloc queue rope set slist stack utility \ vector fstream iomanip iostream strstream iosfwd bitset valarray \ - sstream + sstream exception new typeinfo ARLIB = libstdc++.a.$(VERSION) ARLINK = libstdc++.a @@ -131,12 +135,29 @@ STRFUNCS = REP MAIN TRAITS ADDSS ADDPS ADDCS ADDSP ADDSC \ STRIO = EXTRACT INSERT GETLINE # These are here for SunOS VPATH. -cstringi.o: cstringi.cc -cstdlibi.o: cstdlibi.cc +cinst.o: cinst.cc cmathi.o: cmathi.cc +cstdlibi.o: cstdlibi.cc +cstringi.o: cstringi.cc +del_op.o: del_op.cc new +del_opnt.o: del_opnt.cc new +del_opv.o: del_opv.cc new +del_opvnt.o: del_opvnt.cc new +exception.o: exception.cc typeinfo $(srcdir)/../gcc/gansidecl.h \ + $(srcdir)/../include/ansidecl.h $(srcdir)/../gcc/eh-common.h +new_handler.o: new_handler.cc new +new_op.o: new_op.cc new +new_opnt.o: new_opnt.cc new +new_opv.o: new_opv.cc new +new_opvnt.o: new_opvnt.cc new +sinst.o: sinst.cc stdexcepti.o: stdexcepti.cc stlinst.o: stlinst.cc +tinfo.o: tinfo.cc tinfo.hP typeinfo new +tinfo2.o: tinfo2.cc tinfo.hP typeinfo new valarray.o: valarray.cc +vec.o: vec.cc +pure.o: pure.c # Later do wide strings, too. stmp-string: ${srcdir}/sinst.cc ${srcdir}/std/bastring.h \ diff --git a/libstdc++/configure.in b/libstdc++/configure.in index ac55a7583ce..54483d2d451 100644 --- a/libstdc++/configure.in +++ b/libstdc++/configure.in @@ -134,7 +134,7 @@ ${moveifchange} temp.mt target-mkfrag LIBDIR=yes TO_TOPDIR=../ ALL='libs' -XCXXINCLUDES="-I${srcdir} -I${srcdir}/stl -I${TO_TOPDIR}libio -I${srcdir}/${TO_TOPDIR}libio" +XCXXINCLUDES="-I${srcdir} -I${srcdir}/stl -I${TO_TOPDIR}libio -I${srcdir}/${TO_TOPDIR}libio -I${srcdir}/${TO_TOPDIR}include -I${srcdir}/${TO_TOPDIR}gcc" MOSTLYCLEAN='*.o pic stamp-picdir core so_locations $(MOSTLYCLEAN_JUNK)' CLEAN='$(CLEAN_JUNK)' EXTRA_DISTCLEAN='target-mkfrag' diff --git a/libstdc++/cxxabi.h b/libstdc++/cxxabi.h new file mode 100644 index 00000000000..908d7c467fe --- /dev/null +++ b/libstdc++/cxxabi.h @@ -0,0 +1,519 @@ +/* new abi support -*- C++ -*- + Copyright (C) 2000 + Free Software Foundation, Inc. + Written by Nathan Sidwell, Codesourcery LLC, */ + +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* 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. */ + +#ifndef __CXXABI_H +#define __CXXABI_H 1 + +#if defined(__cplusplus) && (!defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100) +/* These structures only make sense when targeting the new abi, catch a + bonehead error early rather than let the user get very confused. */ +#error "Not targetting the new abi, supply -fnew-abi" +#endif + +#ifdef __cplusplus + +// We use the compiler builtins __SIZE_TYPE__ and __PTRDIFF_TYPE__ instead of +// std::size_t and std::ptrdiff_t respectively. This makes us independant of +// the conformance level of and whether -fhonor-std was supplied. +// is not currently available during compiler building anyway. +// Including would be wrong, as that would rudely place size_t in +// the global namespace. + +#include + +namespace __cxxabiv1 +{ + +/* type information for int, float etc */ +class __fundamental_type_info + : public std::type_info +{ +public: + virtual ~__fundamental_type_info (); +public: + explicit __fundamental_type_info (const char *__n) + : std::type_info (__n) + { } +}; + +/* type information for array objects */ +class __array_type_info + : public std::type_info +{ +/* abi defined member functions */ +protected: + virtual ~__array_type_info (); +public: + explicit __array_type_info (const char *__n) + : std::type_info (__n) + { } +}; + +/* type information for functions (both member and non-member) */ +class __function_type_info + : public std::type_info +{ +/* abi defined member functions */ +public: + virtual ~__function_type_info (); +public: + explicit __function_type_info (const char *__n) + : std::type_info (__n) + { } + +/* implementation defined member functions */ +protected: + virtual bool __is_function_p () const; +}; + +/* type information for enumerations */ +class __enum_type_info + : public std::type_info +{ +/* abi defined member functions */ +public: + virtual ~__enum_type_info (); +public: + explicit __enum_type_info (const char *__n) + : std::type_info (__n) + { } +}; + +/* common type information for simple pointers and pointers to member */ +class __pbase_type_info + : public std::type_info +{ +/* abi defined member variables */ +public: + unsigned int __qualifier_flags; /* qualification of the target object */ + const std::type_info *__pointee; /* type of pointed to object */ + +/* abi defined member functions */ +public: + virtual ~__pbase_type_info (); +public: + explicit __pbase_type_info (const char *__n, + int __quals, + const std::type_info *__type) + : std::type_info (__n), __qualifier_flags (__quals), __pointee (__type) + { } + +/* implementation defined types */ +public: + enum __qualifier_masks { + __const_mask = 0x1, + __volatile_mask = 0x2, + __restrict_mask = 0x4, + __incomplete_mask = 0x8, + __incomplete_class_mask = 0x10 + }; + +/* implementation defined member functions */ +protected: + virtual bool __do_catch (const std::type_info *__thr_type, + void **__thr_obj, + unsigned __outer) const; +protected: + inline virtual bool __pointer_catch (const __pbase_type_info *__thr_type, + void **__thr_obj, + unsigned __outer) const; +}; + +/* type information for simple pointers */ +class __pointer_type_info + : public __pbase_type_info +{ +/* abi defined member functions */ +public: + virtual ~__pointer_type_info (); +public: + explicit __pointer_type_info (const char *__n, + int __quals, + const std::type_info *__type) + : __pbase_type_info (__n, __quals, __type) + { } + +/* implementation defined member functions */ +protected: + virtual bool __is_pointer_p () const; + +protected: + virtual bool __pointer_catch (const __pbase_type_info *__thr_type, + void **__thr_obj, + unsigned __outer) const; +}; + +/* type information for a pointer to member variable */ +class __pointer_to_member_type_info + : public __pbase_type_info +{ +/* abi defined member variables */ +public: + __class_type_info *__context_class; /* class of the member */ + +/* abi defined member functions */ +public: + virtual ~__pointer_to_member_type_info (); +public: + 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_class (__klass) + { } + +/* implementation defined member functions */ +protected: + virtual bool __pointer_catch (const __pbase_type_info *__thr_type, + void **__thr_obj, + unsigned __outer) const; +}; + +class __class_type_info; + +/* helper class for __vmi_class_type */ +class __base_class_info +{ +/* abi defined member variables */ +public: + const __class_type_info *__base; /* base class type */ + long __offset_flags; /* offset and info */ + +/* implementation defined types */ +public: + enum __offset_flags_masks { + __virtual_mask = 0x1, + __public_mask = 0x2, + hwm_bit = 2, + offset_shift = 8 /* bits to shift offset by */ + }; + +/* implementation defined member functions */ +public: + bool __is_virtual_p () const + { return __offset_flags & __virtual_mask; } + bool __is_public_p () const + { return __offset_flags & __public_mask; } + __PTRDIFF_TYPE__ __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_TYPE__> (__offset_flags) >> offset_shift; + } +}; + +/* type information for a class */ +class __class_type_info + : public std::type_info +{ +/* abi defined member functions */ +public: + virtual ~__class_type_info (); +public: + explicit __class_type_info (const char *__n) + : type_info (__n) + { } + +/* implementation defined types */ +public: + /* 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 + { + __unknown = 0, /* we have no idea */ + __not_contained, /* not contained within us (in some */ + /* circumstances this might mean not contained */ + /* publicly) */ + __contained_ambig, /* contained ambiguously */ + + __contained_virtual_mask = __base_class_info::__virtual_mask, /* via a virtual path */ + __contained_public_mask = __base_class_info::__public_mask, /* via a public path */ + __contained_mask = 1 << __base_class_info::hwm_bit, /* contained within us */ + + __contained_private = __contained_mask, + __contained_public = __contained_mask | __contained_public_mask + }; + +public: + struct __upcast_result; + struct __dyncast_result; + +/* implementation defined member functions */ +protected: + virtual bool __do_upcast (const __class_type_info *__dst_type, void **__obj_ptr) const; + +protected: + 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; + +public: + /* 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_TYPE__ __src2dst, + const void *__obj_ptr, + const __class_type_info *__src_type, + const void *__src_ptr) const; + +public: + /* dynamic cast helper. 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_TYPE__ __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; +public: + /* 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_TYPE__ __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 +{ +/* abi defined member variables */ +public: + const __class_type_info *__base_type; + +/* abi defined member functions */ +public: + virtual ~__si_class_type_info (); +public: + explicit __si_class_type_info (const char *__n, + const __class_type_info *__base) + : __class_type_info (__n), __base_type (__base) + { } + +/* implementation defined member functions */ +protected: + virtual bool __do_dyncast (__PTRDIFF_TYPE__ __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_TYPE__ __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 { +/* abi defined member variables */ +public: + unsigned int __flags; /* details about the class heirarchy */ + unsigned int __base_count; /* number of direct bases */ + __base_class_info const __base_info[1]; /* array of 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. */ + +/* abi defined member functions */ +public: + virtual ~__vmi_class_type_info (); +public: + explicit __vmi_class_type_info (const char *__n, + int ___flags) + : __class_type_info (__n), __flags (___flags), __base_count (0) + { } + +/* implementation defined types */ +public: + enum __flags_masks { + __non_diamond_repeat_mask = 0x1, /* distinct instance of repeated base */ + __diamond_shaped_mask = 0x2, /* diamond shaped multiple inheritance */ + non_public_base_mask = 0x4, /* has non-public direct or indirect base */ + public_base_mask = 0x8, /* has public base (direct) */ + + __flags_unknown_mask = 0x10 + }; + +/* implementation defined member functions */ +protected: + virtual bool __do_dyncast (__PTRDIFF_TYPE__ __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_TYPE__ __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; +}; + +/* dynamic cast runtime */ +extern "C" +void *__dynamic_cast (const void *__src_ptr, /* object started from */ + const __class_type_info *__src_type, /* static type of object */ + const __class_type_info *__dst_type, /* desired target type */ + __PTRDIFF_TYPE__ __src2dst); /* how src and dst are related */ + + /* src2dst has the following possible values + >= 0: 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 */ + +/* array ctor/dtor routines */ + +/* allocate and construct array */ +extern "C" +void *__cxa_vec_new (__SIZE_TYPE__ __element_count, + __SIZE_TYPE__ __element_size, + __SIZE_TYPE__ __padding_size, + void (*__constructor) (void *), + void (*__destructor) (void *)); + +extern "C" +void *__cxa_vec_new2 (__SIZE_TYPE__ __element_count, + __SIZE_TYPE__ __element_size, + __SIZE_TYPE__ __padding_size, + void (*__constructor) (void *), + void (*__destructor) (void *), + void *(*__alloc) (__SIZE_TYPE__), + void (*__dealloc) (void *)); + +extern "C" +void *__cxa_vec_new3 (__SIZE_TYPE__ __element_count, + __SIZE_TYPE__ __element_size, + __SIZE_TYPE__ __padding_size, + void (*__constructor) (void *), + void (*__destructor) (void *), + void *(*__alloc) (__SIZE_TYPE__), + void (*__dealloc) (void *, __SIZE_TYPE__)); + +/* construct array */ +extern "C" +void __cxa_vec_ctor (void *__array_address, + __SIZE_TYPE__ __element_count, + __SIZE_TYPE__ __element_size, + void (*__constructor) (void *), + void (*__destructor) (void *)); + +extern "C" +void __cxa_vec_cctor (void *dest_array, + void *src_array, + __SIZE_TYPE__ element_count, + __SIZE_TYPE__ element_size, + void (*constructor) (void *, void *), + void (*destructor) (void *)); + +/* destruct array */ +extern "C" +void __cxa_vec_dtor (void *__array_address, + __SIZE_TYPE__ __element_count, + __SIZE_TYPE__ __element_size, + void (*__destructor) (void *)); + +/* destruct and release array */ +extern "C" +void __cxa_vec_delete (void *__array_address, + __SIZE_TYPE__ __element_size, + __SIZE_TYPE__ __padding_size, + void (*__destructor) (void *)); + +extern "C" +void __cxa_vec_delete2 (void *__array_address, + __SIZE_TYPE__ __element_size, + __SIZE_TYPE__ __padding_size, + void (*__destructor) (void *), + void (*__dealloc) (void *)); + +extern "C" +void __cxa_vec_delete3 (void *__array_address, + __SIZE_TYPE__ __element_size, + __SIZE_TYPE__ __padding_size, + void (*__destructor) (void *), + void (*__dealloc) (void *, __SIZE_TYPE__)); + +/* demangling routines */ + +extern "C" +char *__cxa_demangle (const char *__mangled_name, + char *__output_buffer, + __SIZE_TYPE__ *__length, + int *__status); + +} /* namespace __cxxabiv1 */ + +/* User programs should use the alias `abi'. */ +namespace abi = __cxxabiv1; + +#else +#endif /* __cplusplus */ + + +#endif /* __CXXABI_H */ diff --git a/libstdc++/del_op.cc b/libstdc++/del_op.cc new file mode 100644 index 00000000000..c009a1637c6 --- /dev/null +++ b/libstdc++/del_op.cc @@ -0,0 +1,39 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" + +extern "C" void free (void *); + +void +operator delete (void *ptr) throw () +{ + if (ptr) + free (ptr); +} diff --git a/libstdc++/del_opnt.cc b/libstdc++/del_opnt.cc new file mode 100644 index 00000000000..d5d619e803d --- /dev/null +++ b/libstdc++/del_opnt.cc @@ -0,0 +1,39 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" + +extern "C" void free (void *); + +void +operator delete (void *ptr, const std::nothrow_t&) throw () +{ + if (ptr) + free (ptr); +} diff --git a/libstdc++/del_opv.cc b/libstdc++/del_opv.cc new file mode 100644 index 00000000000..b43d45a35a1 --- /dev/null +++ b/libstdc++/del_opv.cc @@ -0,0 +1,36 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" + +void +operator delete[] (void *ptr) throw () +{ + ::operator delete (ptr); +} diff --git a/libstdc++/del_opvnt.cc b/libstdc++/del_opvnt.cc new file mode 100644 index 00000000000..e91096c4af6 --- /dev/null +++ b/libstdc++/del_opvnt.cc @@ -0,0 +1,36 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" + +void +operator delete[] (void *ptr, const std::nothrow_t&) throw () +{ + ::operator delete (ptr); +} diff --git a/libstdc++/exception b/libstdc++/exception new file mode 100644 index 00000000000..4d35c56c405 --- /dev/null +++ b/libstdc++/exception @@ -0,0 +1,65 @@ +// Exception Handling support header for -*- C++ -*- +// Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation + +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#ifndef __EXCEPTION__ +#define __EXCEPTION__ + +#pragma interface "exception" + +extern "C++" { + +namespace std { + +class exception { +public: + exception () { } + virtual ~exception () { } + virtual const char* what () const; +}; + +class bad_exception : public exception { +public: + bad_exception () { } + virtual ~bad_exception () { } +}; + +typedef void (*terminate_handler) (); +typedef void (*unexpected_handler) (); + +terminate_handler set_terminate (terminate_handler); +void terminate () __attribute__ ((__noreturn__)); +unexpected_handler set_unexpected (unexpected_handler); +void unexpected () __attribute__ ((__noreturn__)); +bool uncaught_exception (); + +} // namespace std + +} // extern "C++" + +#endif diff --git a/libstdc++/exception.cc b/libstdc++/exception.cc new file mode 100644 index 00000000000..886915c823b --- /dev/null +++ b/libstdc++/exception.cc @@ -0,0 +1,403 @@ +// Functions for Exception Support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation + +// This file is part of GNU CC. + +// GNU CC 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. + +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#pragma implementation "exception" + +#include "typeinfo" +#include "exception" +#include +#include "gansidecl.h" /* Needed to support macros used in eh-common.h. */ +#include "eh-common.h" + +/* Define terminate, unexpected, set_terminate, set_unexpected as + well as the default terminate func and default unexpected func. */ + +extern std::terminate_handler __terminate_func __attribute__((__noreturn__)); +using std::terminate; + +void +std::terminate () +{ + __terminate_func (); +} + +void +__default_unexpected () +{ + terminate (); +} + +static std::unexpected_handler __unexpected_func __attribute__((__noreturn__)) + = __default_unexpected; + +std::terminate_handler +std::set_terminate (std::terminate_handler func) +{ + std::terminate_handler old = __terminate_func; + + __terminate_func = func; + return old; +} + +std::unexpected_handler +std::set_unexpected (std::unexpected_handler func) +{ + std::unexpected_handler old = __unexpected_func; + + __unexpected_func = func; + return old; +} + +void +std::unexpected () +{ + __unexpected_func (); +} + +/* The type of a function called to clean up an exception object. + (These will be destructors.) Under the old ABI, these take a + second argument (the `in-charge' argument), that indicates whether + or not do delete the object, and whether or not to destroy virtual + bases. Under the new ABI, there is no second argument. */ +#if !defined (__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +typedef void (*cleanup_fn)(void *, int); +/* The `2' is the value for the in-charge parameter that indicates + that virtual bases should be destroyed. */ +#define CALL_CLEANUP(FN, THIS) FN (THIS, 2) +#else +typedef void (*cleanup_fn)(void *); +#define CALL_CLEANUP(FN, THIS) FN (THIS) +#endif + +/* C++-specific state about the current exception. + This must match init_exception_processing(). + + Note that handlers and caught are not redundant; when rethrown, an + exception can have multiple active handlers and still be considered + uncaught. */ + +struct cp_eh_info +{ + __eh_info eh_info; + void *value; + void *type; + cleanup_fn cleanup; + bool caught; + cp_eh_info *next; + long handlers; + void *original_value; +}; + +/* Language-specific EH info pointer, defined in libgcc2. */ + +extern "C" cp_eh_info **__get_eh_info (); // actually void ** + +/* Exception allocate and free, defined in libgcc2. */ +extern "C" void *__eh_alloc(size_t); +extern "C" void __eh_free(void *); + +/* Is P the type_info node for a pointer of some kind? */ + +extern bool __is_pointer (void *); + + +/* OLD Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). This fudges the actualy returned value to + point to the beginning of what USE to be the cp_eh_info structure. + THis is so that old code that dereferences this pointer will find + things where it expects it to be.*/ +extern "C" void * +__cp_exception_info (void) +{ + return &((*__get_eh_info ())->value); +} + +#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ()) + +/* Old Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). */ + +extern "C" cp_eh_info * +__cp_eh_info (void) +{ + cp_eh_info *p = CP_EH_INFO; + return p; +} + +/* Compiler hook to return a pointer to the info for the current exception, + Set the caught bit, and increment the number of handlers that are + looking at this exception. This makes handlers smaller. */ + +extern "C" cp_eh_info * +__start_cp_handler (void) +{ + cp_eh_info *p = CP_EH_INFO; + p->caught = 1; + p->handlers++; + return p; +} + +extern "C" int __throw_type_match_rtti_2 (const void *, const void *, + void *, void **); + +extern "C" void * +__cplus_type_matcher (__eh_info *info_, void *match_info, + exception_descriptor *exception_table) +{ + cp_eh_info *info = (cp_eh_info *)info_; + + /* No exception table implies the old style mechanism, so don't check. */ + if (exception_table != NULL + && exception_table->lang.language != EH_LANG_C_plus_plus) + return NULL; + + if (match_info == CATCH_ALL_TYPE) + return (void *)1; + + /* we don't worry about version info yet, there is only one version! */ + + void *match_type = match_info; + +#if !defined (__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 + match_type = ((void *(*)())match_type) (); +#endif + + if (__throw_type_match_rtti_2 (match_type, info->type, + info->original_value, &info->value)) + // Arbitrary non-null pointer. + return (void *)1; + else + return NULL; +} + +/* Compiler hook to push a new exception onto the stack. + Used by expand_throw(). */ + +extern "C" void +__cp_push_exception (void *value, void *type, cleanup_fn cleanup) +{ + cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info)); + + p->value = value; + p->type = type; + p->cleanup = cleanup; + p->handlers = 0; + p->caught = false; + p->original_value = value; + + p->eh_info.match_function = __cplus_type_matcher; + p->eh_info.language = EH_LANG_C_plus_plus; + p->eh_info.version = 1; + + cp_eh_info **q = __get_eh_info (); + + p->next = *q; + *q = p; +} + +/* Compiler hook to pop an exception that has been finalized. Used by + push_eh_cleanup(). P is the info for the exception caught by the + current catch block. */ + +extern "C" void +__cp_pop_exception (cp_eh_info *p) +{ + cp_eh_info **stack = __get_eh_info (); + cp_eh_info **q = stack; + + --p->handlers; + + /* Do nothing if our exception is being rethrown (i.e. if the active + exception is our exception and it is uncaught). */ + if (p == *q && !p->caught) + return; + + /* Don't really pop if there are still active handlers for our exception; + rather, push it down past any uncaught exceptions. */ + if (p->handlers != 0) + { + if (p == *q && p->next && !p->next->caught) + { + q = &(p->next); + while (1) + { + if (*q == 0 || (*q)->caught) + break; + + q = &((*q)->next); + } + *stack = p->next; + p->next = *q; + *q = p; + } + return; + } + + for (; *q; q = &((*q)->next)) + if (*q == p) + break; + + if (! *q) + terminate (); + + *q = p->next; + + if (p->cleanup) + // value may have been adjusted. + CALL_CLEANUP (p->cleanup, p->original_value); + + if (! __is_pointer (p->type)) + __eh_free (p->original_value); // value may have been adjusted. + + __eh_free (p); +} + +/* We're doing a rethrow. Find the currently handled exception, mark it + uncaught, and move it to the top of the EH stack. */ + +extern "C" void +__uncatch_exception (void) +{ + cp_eh_info **stack = __get_eh_info (); + cp_eh_info **q = stack; + cp_eh_info *p; + + while (1) + { + p = *q; + + if (p == 0) + terminate (); + if (p->caught) + break; + + q = &(p->next); + } + + if (q != stack) + { + *q = p->next; + p->next = *stack; + *stack = p; + } + + p->caught = false; +} + +/* As per [except.unexpected]: + If an exception is thrown, we check it against the spec. If it doesn't + match, we call unexpected (). If unexpected () throws, we check that + exception against the spec. If it doesn't match, if the spec allows + bad_exception we throw that; otherwise we call terminate (). + + The compiler treats an exception spec as a try block with a generic + handler that just calls this function with a list of the allowed + exception types, so we have an active exception that can be rethrown. + + This function does not return. */ + +extern "C" void +__check_eh_spec (int n, const void **spec) +{ + cp_eh_info *p = CP_EH_INFO; + void *d; + + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d)) + throw; + } + + try + { + std::unexpected (); + } + catch (...) + { + // __exception_info is an artificial var pushed into each catch block. + if (p != __exception_info) + { + p = __exception_info; + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d)) + throw; + } + } + + const std::type_info &bad_exc = typeid (std::bad_exception); + for (int i = 0; i < n; ++i) + { + if (__throw_type_match_rtti_2 (spec[i], &bad_exc, p->value, &d)) + throw std::bad_exception (); + } + + terminate (); + } +} + +/* Special case of the above for throw() specs. */ + +extern "C" void +__check_null_eh_spec (void) +{ + __check_eh_spec (0, 0); +} + +// Helpers for rtti. Although these don't return, we give them return types so +// that the type system is not broken. + +extern "C" void * +__throw_bad_cast () +{ + throw std::bad_cast (); + return 0; +} + +extern "C" std::type_info const & +__throw_bad_typeid () +{ + throw std::bad_typeid (); + return typeid (void); +} + +/* Has the current exception been caught? */ + +bool +std::uncaught_exception () +{ + cp_eh_info *p = CP_EH_INFO; + return p && ! p->caught; +} + +const char * std::exception:: +what () const +{ + return typeid (*this).name (); +} diff --git a/libstdc++/new b/libstdc++/new new file mode 100644 index 00000000000..cbb8d107acf --- /dev/null +++ b/libstdc++/new @@ -0,0 +1,68 @@ +// The -*- C++ -*- dynamic memory management header. +// Copyright (C) 1994, 1996, 1997, 1998, 2000 Free Software Foundation + +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#ifndef __NEW__ +#define __NEW__ + +#pragma interface "new" +#include +#include + +extern "C++" { + +namespace std { + + class bad_alloc : public exception { + public: + virtual const char* what() const throw() { return "bad_alloc"; } + }; + + struct nothrow_t {}; + extern const nothrow_t nothrow; + typedef void (*new_handler)(); + new_handler set_new_handler (new_handler); + +} // namespace std + +// replaceable signatures +void *operator new (size_t) throw (std::bad_alloc); +void *operator new[] (size_t) throw (std::bad_alloc); +void operator delete (void *) throw(); +void operator delete[] (void *) throw(); +void *operator new (size_t, const std::nothrow_t&) throw(); +void *operator new[] (size_t, const std::nothrow_t&) throw(); +void operator delete (void *, const std::nothrow_t&) throw(); +void operator delete[] (void *, const std::nothrow_t&) throw(); + +// default placement versions of operator new +inline void *operator new(size_t, void *place) throw() { return place; } +inline void *operator new[](size_t, void *place) throw() { return place; } +} // extern "C++" + +#endif diff --git a/libstdc++/new.h b/libstdc++/new.h new file mode 100644 index 00000000000..cb1fa4cb5ca --- /dev/null +++ b/libstdc++/new.h @@ -0,0 +1,38 @@ +// -*- C++ -*- forwarding header. +// Copyright (C) 2000 Free Software Foundation + +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#ifndef __NEW_H__ +#define __NEW_H__ + +#include + +using std::new_handler; +using std::set_new_handler; + +#endif // __NEW_H__ diff --git a/libstdc++/new_handler.cc b/libstdc++/new_handler.cc new file mode 100644 index 00000000000..183d1b29882 --- /dev/null +++ b/libstdc++/new_handler.cc @@ -0,0 +1,44 @@ +// Implementation file for the -*- C++ -*- dynamic memory management header. +// Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#pragma implementation "new" +#include "new" + +const std::nothrow_t std::nothrow = { }; + +using std::new_handler; +new_handler __new_handler; + +new_handler +std::set_new_handler (new_handler handler) +{ + new_handler prev_handler = __new_handler; + __new_handler = handler; + return prev_handler; +} diff --git a/libstdc++/new_op.cc b/libstdc++/new_op.cc new file mode 100644 index 00000000000..92577e2f6c8 --- /dev/null +++ b/libstdc++/new_op.cc @@ -0,0 +1,56 @@ +// Support routines for the -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" +using std::new_handler; +using std::bad_alloc; + +extern "C" void *malloc (size_t); +extern new_handler __new_handler; + +void * +operator new (size_t sz) throw (std::bad_alloc) +{ + void *p; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + new_handler handler = __new_handler; + if (! handler) + throw bad_alloc (); + handler (); + p = (void *) malloc (sz); + } + + return p; +} diff --git a/libstdc++/new_opnt.cc b/libstdc++/new_opnt.cc new file mode 100644 index 00000000000..27a9283f165 --- /dev/null +++ b/libstdc++/new_opnt.cc @@ -0,0 +1,64 @@ +// Support routines for the -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" +using std::new_handler; +using std::bad_alloc; + +extern "C" void *malloc (size_t); +extern new_handler __new_handler; + +void * +operator new (size_t sz, const std::nothrow_t&) throw() +{ + void *p; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + new_handler handler = __new_handler; + if (! handler) + return 0; + try + { + handler (); + } + catch (bad_alloc &) + { + return 0; + } + + p = (void *) malloc (sz); + } + + return p; +} diff --git a/libstdc++/new_opv.cc b/libstdc++/new_opv.cc new file mode 100644 index 00000000000..1e14ca81cf6 --- /dev/null +++ b/libstdc++/new_opv.cc @@ -0,0 +1,36 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" + +void * +operator new[] (size_t sz) throw (std::bad_alloc) +{ + return ::operator new(sz); +} diff --git a/libstdc++/new_opvnt.cc b/libstdc++/new_opvnt.cc new file mode 100644 index 00000000000..dde0a7c3cf9 --- /dev/null +++ b/libstdc++/new_opvnt.cc @@ -0,0 +1,36 @@ +// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation +// +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include "new" + +void * +operator new[] (size_t sz, const std::nothrow_t& nothrow) throw() +{ + return ::operator new(sz, nothrow); +} diff --git a/libstdc++/pure.c b/libstdc++/pure.c new file mode 100644 index 00000000000..abaed59177f --- /dev/null +++ b/libstdc++/pure.c @@ -0,0 +1,16 @@ +#include + +#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 + +#define MESSAGE "pure virtual method called\n" + +void +__pure_virtual (void) +{ + write (2, MESSAGE, sizeof (MESSAGE) - 1); + __terminate (); +} diff --git a/libstdc++/tinfo.cc b/libstdc++/tinfo.cc new file mode 100644 index 00000000000..ffad6e72994 --- /dev/null +++ b/libstdc++/tinfo.cc @@ -0,0 +1,1210 @@ +// Methods for type_info for -*- C++ -*- Run Time Type Identification. +// Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation + +// This file is part of GNU CC. + +// GNU CC 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. + +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#pragma implementation "typeinfo" + +#include +#include "tinfo.hP" +#include "new" // for placement new + +// This file contains the minimal working set necessary to link with code +// that uses virtual functions and -frtti but does not actually use RTTI +// functionality. + +std::type_info:: +~type_info () +{ } + +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +// original (old) abi + +namespace +{ +// ADDR is a pointer to an object. Convert it to a pointer to a base, +// using OFFSET. +inline void* +convert_to_base (void *addr, bool is_virtual, myint32 offset) +{ + if (!addr) + return NULL; + + if (!is_virtual) + return (char *) addr + offset; + + // Under the old ABI, the offset gives us the address of a pointer + // to the virtual base. + return *((void **) ((char *) addr + offset)); +} + +} + +// We can't rely on common symbols being shared between shared objects. +bool std::type_info:: +operator== (const std::type_info& arg) const +{ + return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) == 0); +} + +extern "C" void +__rtti_class (void *addr, const char *name, + const __class_type_info::base_info *bl, size_t bn) +{ new (addr) __class_type_info (name, bl, bn); } + +extern "C" void +__rtti_si (void *addr, const char *n, const std::type_info *ti) +{ + new (addr) __si_type_info + (n, static_cast (*ti)); +} + +extern "C" void +__rtti_user (void *addr, const char *name) +{ new (addr) __user_type_info (name); } + +// Upcast for catch checking. OBJPTR points to the thrown object and might be +// NULL. Return 0 on failure, non-zero on success. Set *ADJPTR to adjusted +// object pointer. +int __user_type_info:: +upcast (const type_info &target, void *objptr, + void **adjptr) const +{ + upcast_result result; + + if (do_upcast (contained_public, target, objptr, result)) + return 0; + *adjptr = result.target_obj; + return contained_public_p (result.whole2target); +} + +// Down or cross cast for dynamic_cast. OBJPTR points to the most derrived +// object, SUBPTR points to the static base object. Both must not be NULL. +// TARGET specifies the desired target type, SUBTYPE specifies the static +// type. Both must be defined. Returns adjusted object pointer on success, +// NULL on failure. [expr.dynamic.cast]/8 says 'unambiguous public base'. This +// itself is an ambiguous statement. We choose it to mean the base must be +// separately unambiguous and public, rather than unambiguous considering only +// public bases. +void *__user_type_info:: +dyncast (int boff, + const type_info &target, void *objptr, + const type_info &subtype, void *subptr) const +{ + dyncast_result result; + + do_dyncast (boff, contained_public, + target, objptr, subtype, subptr, result); + if (!result.target_obj) + return NULL; + if (contained_public_p (result.target2sub)) + return result.target_obj; + if (contained_public_p (sub_kind (result.whole2sub & result.whole2target))) + // Found a valid cross cast + return result.target_obj; + if (contained_nonvirtual_p (result.whole2sub)) + // Found an invalid cross cast, which cannot also be a down cast + return NULL; + if (result.target2sub == unknown) + result.target2sub = static_cast (target) + .find_public_subobj (boff, subtype, + result.target_obj, subptr); + if (contained_public_p (result.target2sub)) + // Found a valid down cast + return result.target_obj; + // Must be an invalid down cast, or the cross cast wasn't bettered + return NULL; +} + +// Catch cast helper. ACCESS_PATH is the access from the complete thrown +// object to this base. TARGET is the desired type we want to catch. OBJPTR +// points to this base within the throw object, it might be NULL. Fill in +// RESULT with what we find. Return true, should we determine catch must fail. +bool __user_type_info:: +do_upcast (sub_kind access_path, + const type_info &target, void *objptr, + upcast_result &__restrict result) const +{ + if (*this == target) + { + result.target_obj = objptr; + result.base_type = nonvirtual_base_type; + result.whole2target = access_path; + return contained_nonpublic_p (access_path); + } + return false; +} + +// dynamic cast helper. ACCESS_PATH gives the access from the most derived +// object to this base. TARGET indicates the desired type we want. OBJPTR +// points to this base within the object. SUBTYPE indicates the static type +// started from and SUBPTR 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. +bool __user_type_info:: +do_dyncast (int, sub_kind access_path, + const type_info &target, void *objptr, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const +{ + if (objptr == subptr && *this == subtype) + { + // The subobject we started from. Indicate how we are accessible from + // the most derived object. + result.whole2sub = access_path; + return false; + } + if (*this == target) + { + result.target_obj = objptr; + result.whole2target = access_path; + result.target2sub = not_contained; + return false; + } + return false; +} + +// find_public_subobj helper. Return contained_public if we are the desired +// subtype. OBJPTR points to this base type, SUBPTR points to the desired base +// object. +__user_type_info::sub_kind __user_type_info:: +do_find_public_subobj (int, const type_info &, void *objptr, void *subptr) const +{ + if (subptr == objptr) + // Must be our type, as the pointers match. + return contained_public; + return not_contained; +} + +// catch helper for single public inheritance types. See +// __user_type_info::do_upcast for semantics. +bool __si_type_info:: +do_upcast (sub_kind access_path, + const type_info &target, void *objptr, + upcast_result &__restrict result) const +{ + if (*this == target) + { + result.target_obj = objptr; + result.base_type = nonvirtual_base_type; + result.whole2target = access_path; + return contained_nonpublic_p (access_path); + } + return base.do_upcast (access_path, target, objptr, result); +} + +// dynamic cast helper for single public inheritance types. See +// __user_type_info::do_dyncast for semantics. BOFF indicates how SUBTYPE +// types are inherited by TARGET types. +bool __si_type_info:: +do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *objptr, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const +{ + if (objptr == subptr && *this == subtype) + { + // The subobject we started from. Indicate how we are accessible from + // the most derived object. + result.whole2sub = access_path; + return false; + } + if (*this == target) + { + result.target_obj = objptr; + result.whole2target = access_path; + if (boff >= 0) + result.target2sub = ((char *)subptr - (char *)objptr) == boff + ? contained_public : not_contained; + else if (boff == -2) + result.target2sub = not_contained; + return false; + } + return base.do_dyncast (boff, access_path, + target, objptr, subtype, subptr, result); +} + +// find_public_subobj helper. See __user_type_info::do_find_public_subobj or +// semantics. BOFF indicates how SUBTYPE types are inherited by the original +// target object. +__user_type_info::sub_kind __si_type_info:: +do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *subptr) const +{ + if (subptr == objptr && subtype == *this) + return contained_public; + return base.do_find_public_subobj (boff, subtype, objptr, subptr); +} + +// catch helper for multiple or non-public inheritance types. See +// __user_type_info::do_upcast for semantics. +bool __class_type_info:: +do_upcast (sub_kind access_path, + const type_info &target, void *objptr, + upcast_result &__restrict result) const +{ + if (*this == target) + { + result.target_obj = objptr; + result.base_type = nonvirtual_base_type; + result.whole2target = access_path; + return contained_nonpublic_p (access_path); + } + + for (size_t i = n_bases; i--;) + { + upcast_result result2; + void *p = objptr; + sub_kind sub_access = access_path; + p = convert_to_base (p, + base_list[i].is_virtual, + base_list[i].offset); + if (base_list[i].is_virtual) + sub_access = sub_kind (sub_access | contained_virtual_mask); + if (base_list[i].access != PUBLIC) + sub_access = sub_kind (sub_access & ~contained_public_mask); + if (base_list[i].base->do_upcast (sub_access, target, p, result2) + && !contained_virtual_p (result2.whole2target)) + return true; // must fail + if (result2.base_type) + { + if (result2.base_type == nonvirtual_base_type + && base_list[i].is_virtual) + result2.base_type = base_list[i].base; + if (!result.base_type) + result = result2; + else if (result.target_obj != result2.target_obj) + { + // Found an ambiguity. + result.target_obj = NULL; + result.whole2target = contained_ambig; + return true; + } + else if (result.target_obj) + { + // Ok, found real object via a virtual path. + result.whole2target + = sub_kind (result.whole2target | result2.whole2target); + } + 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.whole2target = contained_ambig; + return true; + } + result.whole2target + = sub_kind (result.whole2target | result2.whole2target); + } + } + } + return false; +} + +// dynamic cast helper for non-public or multiple inheritance types. See +// __user_type_info::do_dyncast for overall semantics. +// 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 __class_type_info:: +do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *objptr, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const +{ + if (objptr == subptr && *this == subtype) + { + // The subobject we started from. Indicate how we are accessible from + // the most derived object. + result.whole2sub = access_path; + return false; + } + if (*this == target) + { + result.target_obj = objptr; + result.whole2target = access_path; + if (boff >= 0) + result.target2sub = ((char *)subptr - (char *)objptr) == boff + ? contained_public : not_contained; + else if (boff == -2) + result.target2sub = not_contained; + return false; + } + bool result_ambig = false; + for (size_t i = n_bases; i--;) + { + dyncast_result result2; + void *p; + sub_kind sub_access = access_path; + p = convert_to_base (objptr, + base_list[i].is_virtual, + base_list[i].offset); + if (base_list[i].is_virtual) + sub_access = sub_kind (sub_access | contained_virtual_mask); + if (base_list[i].access != PUBLIC) + sub_access = sub_kind (sub_access & ~contained_public_mask); + + bool result2_ambig + = base_list[i].base->do_dyncast (boff, sub_access, + target, p, subtype, subptr, result2); + result.whole2sub = sub_kind (result.whole2sub | result2.whole2sub); + if (result2.target2sub == contained_public + || result2.target2sub == contained_ambig) + { + result.target_obj = result2.target_obj; + result.whole2target = result2.whole2target; + result.target2sub = result2.target2sub; + // Found a downcast which can't be bettered or an ambiguous downcast + // which can't be disambiguated + return result2_ambig; + } + + if (!result_ambig && !result.target_obj) + { + // Not found anything yet. + result.target_obj = result2.target_obj; + result.whole2target = result2.whole2target; + result_ambig = result2_ambig; + } + else if (result.target_obj && result.target_obj == result2.target_obj) + { + // Found at same address, must be via virtual. Pick the most + // accessible path. + result.whole2target = + sub_kind (result.whole2target | result2.whole2target); + } + else if ((result.target_obj && result2.target_obj) + || (result_ambig && result2.target_obj) + || (result2_ambig && result.target_obj)) + { + // Found two different TARGET bases, or a valid one and a set of + // ambiguous ones, must disambiguate. See whether SUBOBJ 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 SUBPTR. + + sub_kind new_sub_kind = result2.target2sub; + sub_kind old_sub_kind = result.target2sub; + + if (contained_nonvirtual_p (result.whole2sub)) + { + // We already found SUBOBJ as a non-virtual base of most + // derived. 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 + { + const __user_type_info &t = + static_cast (target); + + if (old_sub_kind >= not_contained) + ;// already calculated + else if (contained_nonvirtual_p (new_sub_kind)) + // Already found non-virtually inside the other choice, + // cannot be in this. + old_sub_kind = not_contained; + else + old_sub_kind = t.find_public_subobj (boff, subtype, + result.target_obj, subptr); + + if (new_sub_kind >= not_contained) + ;// already calculated + else if (contained_nonvirtual_p (old_sub_kind)) + // Already found non-virtually inside the other choice, + // cannot be in this. + new_sub_kind = not_contained; + else + new_sub_kind = t.find_public_subobj (boff, subtype, + result2.target_obj, subptr); + } + + // 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.target_obj = result2.target_obj; + result.whole2target = result2.whole2target; + result_ambig = false; + old_sub_kind = new_sub_kind; + } + result.target2sub = old_sub_kind; + if (result.target2sub == contained_public) + return false; // Can't be an ambiguating downcast for later discovery. + } + else if (contained_p (sub_kind (new_sub_kind & old_sub_kind))) + { + // In both. + result.target_obj = NULL; + result.target2sub = 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.target_obj = NULL; + result.target2sub = not_contained; + result_ambig = true; + } + } + + if (result.whole2sub == contained_private) + // We found SUBOBJ 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; + } + + return result_ambig; +} + +// find_public_subobj helper for non-public or multiple inheritance types. See +// __user_type_info::do_find_public_subobj for semantics. We make use of BOFF +// to prune the base class walk. +__user_type_info::sub_kind __class_type_info:: +do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *subptr) const +{ + if (objptr == subptr && subtype == *this) + return contained_public; + + for (size_t i = n_bases; i--;) + { + if (base_list[i].access != PUBLIC) + continue; // Not public, can't be here. + void *p; + + if (base_list[i].is_virtual && boff == -3) + // Not a virtual base, so can't be here. + continue; + + p = convert_to_base (objptr, + base_list[i].is_virtual, + base_list[i].offset); + + sub_kind base_kind = base_list[i].base->do_find_public_subobj + (boff, subtype, p, subptr); + if (contained_p (base_kind)) + { + if (base_list[i].is_virtual) + base_kind = sub_kind (base_kind | contained_virtual_mask); + return base_kind; + } + } + + return not_contained; +} +#else +// new abi + +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; +} + +}; + +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 { + ptrdiff_t whole_object; // offset to most derived object + const __class_type_info *whole_type; // pointer to most derived type_info + const void *origin; // what a class's vptr points to +}; + +template +inline const T * +adjust_pointer (const void *base, ptrdiff_t offset) +{ + return reinterpret_cast + (reinterpret_cast (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 (addr); + + offset = *adjust_pointer (vtable, offset); + } + + return adjust_pointer (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 (0) + 1; + +}; // namespace + +namespace __cxxabiv1 +{ + +__class_type_info:: +~__class_type_info () +{} + +__si_class_type_info:: +~__si_class_type_info () +{} + +__vmi_class_type_info:: +~__vmi_class_type_info () +{} + +// __upcast_result is used to hold information during traversal of a class +// heirarchy 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 heirarchy + 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 + public: + __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 +// heirarchy 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 heirarchy + + public: + __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask) + :dst_ptr (NULL), whole2dst (__unknown), + whole2src (__unknown), dst2src (__unknown), + whole_details (details_) + {} +}; + +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 (result.dst_ptr); + return true; +} + +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 (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); +} + +__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; +} + +__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); +} + +__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 (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->__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; +} + +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 __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 (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); +} + +// 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 (obj_ptr, src2dst) == src_ptr + ? __contained_public : __not_contained; + else if (src2dst == -2) + result.dst2src = __not_contained; + return false; + } + + bool result_ambig = false; + for (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 (!__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->__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 | result_ambig) + && (result2.dst_ptr != 0 | result2_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 heirarchy 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; + } + + return result_ambig; +} + +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; +} + +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); +} + +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 (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->__do_upcast (dst, base, result2)) + { + if (result2.base_type == nonvirtual_base_type && is_virtual) + result2.base_type = __base_info[i].__base; + 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; +} + +// this is the external interface to the dynamic cast machinery +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 (src_ptr); + const vtable_prefix *prefix = + adjust_pointer (vtable, + -offsetof (vtable_prefix, origin)); + const void *whole_ptr = + adjust_pointer (src_ptr, prefix->whole_object); + const __class_type_info *whole_type = prefix->whole_type; + __class_type_info::__dyncast_result result; + + whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public, + dst_type, whole_ptr, src_type, src_ptr, result); + if (!result.dst_ptr) + return NULL; + if (contained_public_p (result.dst2src)) + // Src is known to be a public base of dst. + return const_cast (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 (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 (result.dst_ptr); + // Must be an invalid down cast, or the cross cast wasn't bettered + return NULL; +} + +}; // namespace __cxxabiv1 +#endif diff --git a/libstdc++/tinfo.hP b/libstdc++/tinfo.hP new file mode 100644 index 00000000000..6be77bae268 --- /dev/null +++ b/libstdc++/tinfo.hP @@ -0,0 +1,223 @@ +// RTTI support internals for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation + +#include "typeinfo" + +// Class declarations shared between the typeinfo implementation files. + +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +// original (old) abi + +// type_info for a class with no base classes (or an enum). + +struct __user_type_info : public std::type_info { + __user_type_info (const char *n) : type_info (n) {} + + // If our type can be upcast to a public and unambiguous base, then return + // non-zero and set RES to point to the base object. OBJ points to the throw + // object and can be NULL, if there is no object to adjust. + int upcast (const type_info &target, void *obj, void **res) const; + + // If our type can be dynamicly cast to the target type, then return + // pointer to the target object. OBJ is the pointer to the most derived + // type and cannot be NULL. SUBTYPE and SUBOBJ indicate the static type + // base object from whence we came, it cannot be NULL. SUBTYPE cannot be + // the same as TARGET. TARGET cannot be a base of SUBTYPE. + // BOFF indicates how SUBTYPE is related to TARGET. + // BOFF >= 0, there is only one public non-virtual SUBTYPE base at offset + // BOFF, and there are no public virtual SUBTYPE bases. + // Therefore check if SUBOBJ is at offset BOFF when we find a target + // BOFF == -1, SUBTYPE occurs as multiple public virtual or non-virtual bases. + // Lazily search all the bases of TARGET. + // BOFF == -2, SUBTYPE is not a public base. + // BOFF == -3, SUBTYPE occurs as multiple public non-virtual bases. + // Lazily search the non-virtual bases of TARGET. + // For backwards compatibility set BOFF to -1, that is the safe "unknown" + // value. We do not care about SUBTYPES as private bases of TARGET, as they + // can never succeed as downcasts, only as crosscasts -- and then only if + // they are virtual. This is more complicated that it might seem. + void *dyncast (int boff, + const type_info &target, void *obj, + const type_info &subtype, void *subobj) const; + + // non_virtual_base_type is used to indicate that a base class is via a + // non-virtual access path. + static const type_info *const nonvirtual_base_type + = static_cast (0) + 1; + + // 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 + { + unknown = 0, // we have no idea + not_contained, // not contained within us (in some + // circumstances this might mean not contained + // publicly) + contained_ambig, // contained ambiguously + contained_mask = 4, // contained within us + contained_virtual_mask = 1, // via a virtual path + contained_public_mask = 2, // via a public path + contained_private = contained_mask, + contained_public = contained_mask | contained_public_mask + }; + // some predicate functions for sub_kind + static inline bool contained_p (sub_kind access_path) + { + return access_path >= contained_mask; + } + static inline bool contained_public_p (sub_kind access_path) + { + return access_path >= contained_public; + } + static inline bool contained_nonpublic_p (sub_kind access_path) + { + return (access_path & contained_public) == contained_mask; + } + static inline bool contained_nonvirtual_p (sub_kind access_path) + { + return (access_path & (contained_mask | contained_virtual_mask)) + == contained_mask; + } + static inline bool contained_virtual_p (sub_kind access_path) + { + return (access_path & (contained_mask | contained_virtual_mask)) + == (contained_mask | contained_virtual_mask); + } + + struct upcast_result + { + void *target_obj; // pointer to target object or NULL (init NULL) + sub_kind whole2target; // path from most derived object to target + const type_info *base_type; // where we found the target, (init NULL) + // if in vbase the __user_type_info of vbase) + // if a non-virtual base then 1 + // else NULL + public: + upcast_result () + :target_obj (NULL), whole2target (unknown), base_type (NULL) + {} + }; + struct dyncast_result + { + void *target_obj; // pointer to target object or NULL (init NULL) + sub_kind whole2target; // path from most derived object to target + sub_kind whole2sub; // path from most derived object to sub object + sub_kind target2sub; // path from target to sub object + + public: + dyncast_result () + :target_obj (NULL), whole2target (unknown), + whole2sub (unknown), target2sub (unknown) + {} + }; + + public: + // Helper for upcast. See if TARGET is us, or one of our bases. ACCESS_PATH + // gives the access from the start object. Return TRUE if we know the catch + // fails. + virtual bool do_upcast (sub_kind access_path, + const type_info &target, void *obj, + upcast_result &__restrict result) const; + // Helper for dyncast. BOFF indicates how the SUBTYPE is related to TARGET. + // ACCESS_PATH indicates the access from the most derived object. It is + // used to prune the DAG walk. All information about what we find is put + // into RESULT. Return true, if the match we have found is ambiguous. + virtual bool do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *obj, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const; + public: + // Indicate whether SUBPTR of type SUBTYPE is contained publicly within + // OBJPTR. OBJPTR points to this base object. BOFF indicates how SUBTYPE + // objects might be contained within this type. If SUBPTR is one of our + // SUBTYPE bases, indicate virtuality. Returns not_contained for non + // containment or private containment. + sub_kind find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const + { + if (boff >= 0) + return ((char *)subptr - (char *)objptr) == boff + ? contained_public : not_contained; + if (boff == -2) + return not_contained; + return do_find_public_subobj (boff, subtype, objptr, subptr); + } + + public: + // Helper for find_subobj. BOFF indicates how SUBTYPE bases are inherited by + // the type started from -- which is not necessarily the current type. + // OBJPTR points to the current base. + virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const; +}; + +// type_info for a class with one public, nonvirtual base class. + +class __si_type_info : public __user_type_info { + const __user_type_info &base; + +public: + __si_type_info (const char *n, const __user_type_info &b) + : __user_type_info (n), base (b) { } + + private: + virtual bool do_upcast (sub_kind access_path, + const type_info &target, void *obj, + upcast_result &__restrict result) const; + virtual bool do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *obj, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const; + virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const; +}; + +// type_info for a general class. + +#include + +#if INT_MAX == 2147483647 +typedef int myint32; +#elif SHRT_MAX == 2147483647 +typedef short myint32; +#elif SCHAR_MAX == 2147483647 +typedef signed char myint32; +#elif LONG_MAX == 2147483647 +typedef long myint32; +#else +# error "No 32-bit data type?" +#endif + +struct __class_type_info : public __user_type_info { + enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 }; + + struct base_info { + const __user_type_info *base; + myint32 offset: 29; + bool is_virtual: 1; + enum access access: 2; + }; + + const base_info *base_list; + size_t n_bases; + + __class_type_info (const char *name, const base_info *bl, size_t bn) + : __user_type_info (name), base_list (bl), n_bases (bn) {} + + public: + virtual bool do_upcast (sub_kind access_path, + const type_info &target, void *obj, + upcast_result &__restrict result) const; + virtual bool do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *obj, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const; + virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const; +}; +#else +// new abi +#include + +#endif diff --git a/libstdc++/tinfo2.cc b/libstdc++/tinfo2.cc new file mode 100644 index 00000000000..6e1c916f177 --- /dev/null +++ b/libstdc++/tinfo2.cc @@ -0,0 +1,452 @@ +// Methods for type_info for -*- C++ -*- Run Time Type Identification. +// Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 Free Software Foundation + +// This file is part of GNU CC. + +// GNU CC 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. + +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include +#include "tinfo.hP" +#include "new" // for placement new + +// We can't rely on having stdlib.h if we're freestanding. +extern "C" void abort (); + +using std::type_info; + +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +bool +type_info::before (const type_info &arg) const +{ + return __builtin_strcmp (name (), arg.name ()) < 0; +} + +// type info for pointer type. + +struct __pointer_type_info : public type_info { + const type_info& type; + + __pointer_type_info (const char *n, const type_info& ti) + : type_info (n), type (ti) {} +}; + +// type info for attributes + +struct __attr_type_info : public type_info { + enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 }; + + const type_info& type; + cv attr; + + __attr_type_info (const char *n, cv a, const type_info& t) + : type_info (n), type (t), attr (a) {} +}; + +// type_info for builtin type + +struct __builtin_type_info : public type_info { + __builtin_type_info (const char *n): type_info (n) {} +}; + +// type info for function. + +struct __func_type_info : public type_info { + __func_type_info (const char *n) : type_info (n) {} +}; + +// type info for pointer to member function. + +struct __ptmf_type_info : public type_info { + __ptmf_type_info (const char *n) : type_info (n) {} +}; + +// type info for pointer to data member. + +struct __ptmd_type_info : public type_info { + __ptmd_type_info (const char *n): type_info (n) {} +}; + +// type info for array. + +struct __array_type_info : public type_info { + __array_type_info (const char *n): type_info (n) {} +}; + +#else + +#include +#endif + +#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 +namespace __cxxabiv1 { + +using namespace std; + +// 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 () +{} + +__array_type_info:: +~__array_type_info () +{} + +__function_type_info:: +~__function_type_info () +{} + +__enum_type_info:: +~__enum_type_info () +{} + +__pbase_type_info:: +~__pbase_type_info () +{} + +__pointer_type_info:: +~__pointer_type_info () +{} + +__pointer_to_member_type_info:: +~__pointer_to_member_type_info () +{} + +bool __pointer_type_info:: +__is_pointer_p () const +{ + return true; +} + +bool __function_type_info:: +__is_function_p () const +{ + return true; +} + +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 (typeid (*this) != typeid (*thr_type)) + return false; // not both same kind of pointers + + 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 (thr_type); + + if (thrown_type->__qualifier_flags & ~__qualifier_flags) + // We're less qualified. + return false; + + if (!(__qualifier_flags & __const_mask)) + outer &= ~1; + + return __pointer_catch (thrown_type, thr_obj, outer); +} + +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); +} + +bool __pointer_type_info:: +__pointer_catch (const __pbase_type_info *thrown_type, + void **thr_obj, + unsigned outer) const +{ + if (outer < 2 && *__pointee == typeid (void)) + { + // conversion to void + return !thrown_type->__pointee->__is_function_p (); + } + + return __pbase_type_info::__pointer_catch (thrown_type, thr_obj, outer); +} + +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 (thr_type); + + if (*__context_class != *thrown_type->__context_class) + return false; // not pointers to member of same class + + return __pbase_type_info::__pointer_catch (thrown_type, thr_obj, outer); +} + +} // namespace std +#endif + +// Entry points for the compiler. + +/* Low level match routine used by compiler to match types of catch + variables and thrown objects. */ + +extern "C" int +__throw_type_match_rtti_2 (const void *catch_type_r, const void *throw_type_r, + void *objptr, void **valp) +{ + const type_info &catch_type = *(const type_info *)catch_type_r; + const type_info &throw_type = *(const type_info *)throw_type_r; + + *valp = objptr; + +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +// old abi + if (catch_type == throw_type) + return 1; + + if (const __user_type_info *p + = dynamic_cast (&throw_type)) + { + return p->upcast (catch_type, objptr, valp); + } + else if (const __pointer_type_info *fr = + dynamic_cast (&throw_type)) + { + const __pointer_type_info *to = + dynamic_cast (&catch_type); + + if (! to) + return 0; + + const type_info *subfr = &fr->type, *subto = &to->type; + __attr_type_info::cv cvfrom, cvto; + + if (const __attr_type_info *at + = dynamic_cast (subfr)) + { + cvfrom = at->attr; + subfr = &at->type; + } + else + cvfrom = __attr_type_info::NONE; + + if (const __attr_type_info *at + = dynamic_cast (subto)) + { + cvto = at->attr; + subto = &at->type; + } + else + cvto = __attr_type_info::NONE; + + if (((cvfrom & __attr_type_info::CONST) + > (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + > (cvto & __attr_type_info::VOLATILE))) + return 0; + + if (*subto == *subfr) + return 1; + else if (*subto == typeid (void) + && dynamic_cast (subfr) == 0) + return 1; + else if (const __user_type_info *p + = dynamic_cast (subfr)) + return p->upcast (*subto, objptr, valp); + else if (const __pointer_type_info *pfr + = dynamic_cast (subfr)) + { + // Multi-level pointer conversion. + + const __pointer_type_info *pto + = dynamic_cast (subto); + + if (! pto) + return 0; + + bool constp = (cvto & __attr_type_info::CONST); + for (subto = &pto->type, subfr = &pfr->type; ; + subto = &pto->type, subfr = &pfr->type) + { + if (const __attr_type_info *at + = dynamic_cast (subfr)) + { + cvfrom = at->attr; + subfr = &at->type; + } + else + cvfrom = __attr_type_info::NONE; + + if (const __attr_type_info *at + = dynamic_cast (subto)) + { + cvto = at->attr; + subto = &at->type; + } + else + cvto = __attr_type_info::NONE; + + if (((cvfrom & __attr_type_info::CONST) + > (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + > (cvto & __attr_type_info::VOLATILE))) + return 0; + + if (! constp + && (((cvfrom & __attr_type_info::CONST) + < (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + < (cvto & __attr_type_info::VOLATILE)))) + return 0; + + if (*subto == *subfr) + return 1; + + pto = dynamic_cast (subto); + pfr = dynamic_cast (subfr); + if (! pto || ! pfr) + return 0; + + if (! (cvto & __attr_type_info::CONST)) + constp = false; + } + } + } +#else +// new abi + + return catch_type.__do_catch (&throw_type, valp, 1); +#endif + return 0; +} + +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +/* Backward compatibility wrapper. */ + +extern "C" void* +__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, + void *objptr) +{ + void *ret; + if (__throw_type_match_rtti_2 (catch_type_r, throw_type_r, objptr, &ret)) + return ret; + return NULL; +} +#endif + +/* Called from __cp_pop_exception. Is P the type_info node for a pointer + of some kind? */ + +bool +__is_pointer (void *p) +{ + const type_info *t = reinterpret_cast (p); +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +// old abi + const __pointer_type_info *pt = + dynamic_cast (t); + return pt != 0; +#else +// new abi + return t->__is_pointer_p (); +#endif +} + +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 +// old abi + +extern "C" void +__rtti_ptr (void *addr, const char *n, const type_info *ti) +{ new (addr) __pointer_type_info (n, *ti); } + +extern "C" void +__rtti_attr (void *addr, const char *n, int attrval, const type_info *ti) +{ + new (addr) __attr_type_info + (n, static_cast <__attr_type_info::cv> (attrval), *ti); +} + +extern "C" void +__rtti_func (void *addr, const char *name) +{ new (addr) __func_type_info (name); } + +extern "C" void +__rtti_ptmf (void *addr, const char *name) +{ new (addr) __ptmf_type_info (name); } + +extern "C" void +__rtti_ptmd (void *addr, const char *name) +{ new (addr) __ptmd_type_info (name); } + +extern "C" void +__rtti_array (void *addr, const char *name) +{ new (addr) __array_type_info (name); } + +extern "C" void * +__dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void), + int require_public, void *address, const type_info & (*sub)(void), void *subptr) +{ + if (!require_public) abort(); + return static_cast <__user_type_info const &> (from ()).dyncast + (/*boff=*/-1, to (), address, sub (), subptr); +} + +extern "C" void * +__dynamic_cast_2 (const type_info& (*from)(void), const type_info& (*to)(void), + int boff, + void *address, const type_info & (*sub)(void), void *subptr) +{ + return static_cast <__user_type_info const &> (from ()).dyncast + (boff, to (), address, sub (), subptr); +} + +// type_info nodes and functions for the builtin types. The mangling here +// must match the mangling in gcc/cp/rtti.c. + +#define BUILTIN(mangled) \ +unsigned char __ti##mangled [sizeof (__builtin_type_info)] \ + __attribute__ ((aligned (__alignof__ (void *)))); \ +extern "C" const type_info &__tf##mangled (void) { \ + if ((*(void **) __ti##mangled) == 0) \ + new (__ti##mangled) __builtin_type_info (#mangled); \ + return *(type_info *)__ti##mangled; \ +} + +BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b); +BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f); +BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc); +BUILTIN (Sc); + +#endif diff --git a/libstdc++/typeinfo b/libstdc++/typeinfo new file mode 100644 index 00000000000..91f0de2c720 --- /dev/null +++ b/libstdc++/typeinfo @@ -0,0 +1,134 @@ +// RTTI support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000 Free Software Foundation + +// This file is part of GNU CC. +// +// GNU CC 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. +// +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// __GXX_ABI_VERSION distinguishes the ABI that is being used. Values <100 +// indicate the `old' abi, which grew as C++ was defined. Values >=100 +// indicate the `new' abi, which is a cross vendor C++ abi, documented at +// `http://reality.sgi.com/dehnert_engr/cxx/'. + +#ifndef __TYPEINFO__ +#define __TYPEINFO__ + +#pragma interface "typeinfo" + +#include + +extern "C++" { + +#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 +namespace __cxxabiv1 +{ + class __class_type_info; +} // namespace __cxxabiv1 +#endif + +namespace std { + +class type_info { +public: + // Destructor. 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 (); + +private: + // Assigning type_info is not supported. made private. + type_info& operator= (const type_info&); + type_info (const type_info&); + +protected: + const char *__name; + +protected: + explicit type_info (const char *__n): __name (__n) { } + +public: + // the public interface +#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 + // In old abi, 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; + const char* name () const + { return __name; } + bool operator== (const type_info& __arg) const; + bool operator!= (const type_info& __arg) const + { return !operator== (__arg); } + +#else + // In new abi we can rely on type_info's NTBS being unique, + // and therefore address comparisons are sufficient. + bool before (const type_info& __arg) const + { return __name < __arg.__name; } + const char* name () const + { return __name; } + bool operator== (const type_info& __arg) const + { return __name == __arg.__name; } + bool operator!= (const type_info& __arg) const + { return !operator== (__arg); } +#endif + + // the internal interface +#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 +public: + // 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; +#endif +}; + +class bad_cast : public exception { +public: + bad_cast() { } + virtual ~bad_cast() { } +}; + +class bad_typeid : public exception { + public: + bad_typeid () { } + virtual ~bad_typeid () { } +}; + +} // namespace std + +} // extern "C++" +#endif diff --git a/libstdc++/vec.cc b/libstdc++/vec.cc new file mode 100644 index 00000000000..966feb486de --- /dev/null +++ b/libstdc++/vec.cc @@ -0,0 +1,279 @@ +// new abi support -*- C++ -*- +// Copyright (C) 2000 +// Free Software Foundation, Inc. +// Written by Nathan Sidwell, Codesourcery LLC, +// +// GNU CC 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. + +// GNU CC 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 GNU CC; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 +#include +#include +#include + +// Exception handling hook, to mark current exception as not caught -- +// generally because we're about to rethrow it after some cleanup. +extern "C" void __uncatch_exception (void); + +namespace __cxxabiv1 +{ + +/* allocate and construct array */ +extern "C" void * +__cxa_vec_new (size_t element_count, + size_t element_size, + size_t padding_size, + void (*constructor) (void *), + void (*destructor) (void *)) +{ + return __cxa_vec_new2 (element_count, element_size, padding_size, + constructor, destructor, + &operator new[], &operator delete []); +} + +extern "C" void * +__cxa_vec_new2 (size_t element_count, + size_t element_size, + size_t padding_size, + void (*constructor) (void *), + void (*destructor) (void *), + void *(*alloc) (size_t), + void (*dealloc) (void *)) +{ + size_t size = element_count * element_size + padding_size; + char *base = static_cast (alloc (size)); + + if (padding_size) + { + base += padding_size; + reinterpret_cast (base)[-1] = element_count; + } + try + { + __cxa_vec_ctor (base, element_count, element_size, + constructor, destructor); + } + catch (...) + { + __uncatch_exception (); + dealloc (base - padding_size); + throw; + } + return base; +} + +extern "C" void * +__cxa_vec_new3 (size_t element_count, + size_t element_size, + size_t padding_size, + void (*constructor) (void *), + void (*destructor) (void *), + void *(*alloc) (size_t), + void (*dealloc) (void *, size_t)) +{ + size_t size = element_count * element_size + padding_size; + char *base = static_cast (alloc (size)); + + if (padding_size) + { + base += padding_size; + reinterpret_cast (base)[-1] = element_count; + } + try + { + __cxa_vec_ctor (base, element_count, element_size, + constructor, destructor); + } + catch (...) + { + __uncatch_exception (); + dealloc (base - padding_size, size); + throw; + } + return base; +} + +/* construct array */ +extern "C" void +__cxa_vec_ctor (void *array_address, + size_t element_count, + size_t element_size, + void (*constructor) (void *), + void (*destructor) (void *)) +{ + size_t ix = 0; + char *ptr = static_cast (array_address); + + try + { + if (constructor) + for (; ix != element_count; ix++, ptr += element_size) + constructor (ptr); + } + catch (...) + { + __uncatch_exception (); + __cxa_vec_dtor (array_address, ix, element_size, destructor); + throw; + } +} + +/* construct an array by copying */ + +extern "C" void +__cxa_vec_cctor (void *dest_array, + void *src_array, + size_t element_count, + size_t element_size, + void (*constructor) (void *, void *), + void (*destructor) (void *)) +{ + size_t ix = 0; + char *dest_ptr = static_cast (dest_array); + char *src_ptr = static_cast (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 (); + __cxa_vec_dtor (dest_array, ix, element_size, destructor); + throw; + } +} + +/* destruct array */ +extern "C" void +__cxa_vec_dtor (void *array_address, + size_t element_count, + size_t element_size, + void (*destructor) (void *)) +{ + if (destructor) + { + char *ptr = static_cast (array_address); + size_t ix = element_count; + bool unwinding = std::uncaught_exception (); + + ptr += element_count * element_size; + + try + { + while (ix--) + { + ptr -= element_size; + destructor (ptr); + } + } + catch (...) + { + if (unwinding) + // [except.ctor]/3 If a destructor called during stack unwinding + // exits with an exception, terminate is called. + std::terminate (); + __uncatch_exception (); + __cxa_vec_dtor (array_address, ix, element_size, destructor); + throw; + } + } +} + +/* destruct and release array */ +extern "C" void +__cxa_vec_delete (void *array_address, + size_t element_size, + size_t padding_size, + void (*destructor) (void *)) +{ + __cxa_vec_delete2 (array_address, element_size, padding_size, + destructor, + &operator delete []); +} + +extern "C" void +__cxa_vec_delete2 (void *array_address, + size_t element_size, + size_t padding_size, + void (*destructor) (void *), + void (*dealloc) (void *)) +{ + char *base = static_cast (array_address); + + if (padding_size) + { + size_t element_count = reinterpret_cast (base)[-1]; + base -= padding_size; + try + { + __cxa_vec_dtor (array_address, element_count, element_size, + destructor); + } + catch (...) + { + __uncatch_exception (); + dealloc (base); + throw; + } + } + dealloc (base); +} + +extern "C" void +__cxa_vec_delete3 (void *array_address, + size_t element_size, + size_t padding_size, + void (*destructor) (void *), + void (*dealloc) (void *, size_t)) +{ + char *base = static_cast (array_address); + size_t size = 0; + + if (padding_size) + { + size_t element_count = reinterpret_cast (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 (); + dealloc (base, size); + throw; + } + } + dealloc (base, size); +} + +} // namespace __cxxabiv1 + +#endif // defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 -- 2.30.2