del_op.cc, [...]: New files.
authorRichard Henderson <rth@cygnus.com>
Sat, 7 Oct 2000 19:21:05 +0000 (12:21 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 7 Oct 2000 19:21:05 +0000 (12:21 -0700)
        * 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

23 files changed:
libstdc++/ChangeLog
libstdc++/Makefile.in
libstdc++/configure.in
libstdc++/cxxabi.h [new file with mode: 0644]
libstdc++/del_op.cc [new file with mode: 0644]
libstdc++/del_opnt.cc [new file with mode: 0644]
libstdc++/del_opv.cc [new file with mode: 0644]
libstdc++/del_opvnt.cc [new file with mode: 0644]
libstdc++/exception [new file with mode: 0644]
libstdc++/exception.cc [new file with mode: 0644]
libstdc++/new [new file with mode: 0644]
libstdc++/new.h [new file with mode: 0644]
libstdc++/new_handler.cc [new file with mode: 0644]
libstdc++/new_op.cc [new file with mode: 0644]
libstdc++/new_opnt.cc [new file with mode: 0644]
libstdc++/new_opv.cc [new file with mode: 0644]
libstdc++/new_opvnt.cc [new file with mode: 0644]
libstdc++/pure.c [new file with mode: 0644]
libstdc++/tinfo.cc [new file with mode: 0644]
libstdc++/tinfo.hP [new file with mode: 0644]
libstdc++/tinfo2.cc [new file with mode: 0644]
libstdc++/typeinfo [new file with mode: 0644]
libstdc++/vec.cc [new file with mode: 0644]

index 5da8c11dfa999274978bbb88f89bbb86993da351..9fa25078079db59f4bfa19f1bf546c7790741375 100644 (file)
@@ -1,3 +1,14 @@
+2000-10-07  Richard Henderson  <rth@cygnus.com>
+
+       * 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  <edelsohn@gnu.org>
 
        * configure.in: Add AIX multithread support fragment.
index cbbc14901dfd430c039612778308e6f33b9c973e..3db3b73a7801d862cec53d362b0b72367bcc9230 100644 (file)
@@ -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 \
index ac55a7583ce90a8a48c26fbed2ed5f8c3edfc4dd..54483d2d451d84c6e6933958a01e3e0426b3c482 100644 (file)
@@ -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 (file)
index 0000000..908d7c4
--- /dev/null
@@ -0,0 +1,519 @@
+/* new abi support -*- C++ -*-
+   Copyright (C) 2000
+   Free Software Foundation, Inc.
+   Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>  */
+
+// 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 <cstddef> and whether -fhonor-std was supplied.
+// <cstddef> is not currently available during compiler building anyway.
+// Including <stddef.h> would be wrong, as that would rudely place size_t in
+// the global namespace.
+
+#include <typeinfo>
+
+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 (file)
index 0000000..c009a16
--- /dev/null
@@ -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 (file)
index 0000000..d5d619e
--- /dev/null
@@ -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 (file)
index 0000000..b43d45a
--- /dev/null
@@ -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 (file)
index 0000000..e91096c
--- /dev/null
@@ -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 (file)
index 0000000..4d35c56
--- /dev/null
@@ -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 (file)
index 0000000..886915c
--- /dev/null
@@ -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 <stddef.h>
+#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 (file)
index 0000000..cbb8d10
--- /dev/null
@@ -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 <stddef.h>
+#include <exception>
+
+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 (file)
index 0000000..cb1fa4c
--- /dev/null
@@ -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 <new>
+
+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 (file)
index 0000000..183d1b2
--- /dev/null
@@ -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 (file)
index 0000000..92577e2
--- /dev/null
@@ -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 (file)
index 0000000..27a9283
--- /dev/null
@@ -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 (file)
index 0000000..1e14ca8
--- /dev/null
@@ -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 (file)
index 0000000..dde0a7c
--- /dev/null
@@ -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 (file)
index 0000000..abaed59
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#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 (file)
index 0000000..ffad6e7
--- /dev/null
@@ -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 <stddef.h>
+#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 <const __user_type_info &> (*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 <const __user_type_info &> (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 <const __user_type_info &> (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 <typename T>
+inline const T *
+adjust_pointer (const void *base, ptrdiff_t offset)
+{
+  return reinterpret_cast <const T *>
+    (reinterpret_cast <const char *> (base) + offset);
+}
+
+// ADDR is a pointer to an object.  Convert it to a pointer to a base,
+// using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base.
+inline void const *
+convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset)
+{
+  if (is_virtual)
+    {
+      const void *vtable = *static_cast <const void *const *> (addr);
+      
+      offset = *adjust_pointer<ptrdiff_t> (vtable, offset);
+    }
+
+  return adjust_pointer<void> (addr, offset);
+}
+
+// some predicate functions for __class_type_info::__sub_kind
+inline bool contained_p (__class_type_info::__sub_kind access_path)
+{
+  return access_path >= __class_type_info::__contained_mask;
+}
+inline bool public_p (__class_type_info::__sub_kind access_path)
+{
+  return access_path & __class_type_info::__contained_public_mask;
+}
+inline bool virtual_p (__class_type_info::__sub_kind access_path)
+{
+  return (access_path & __class_type_info::__contained_virtual_mask);
+}
+inline bool contained_public_p (__class_type_info::__sub_kind access_path)
+{
+  return ((access_path & __class_type_info::__contained_public)
+          == __class_type_info::__contained_public);
+}
+inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path)
+{
+  return ((access_path & __class_type_info::__contained_public)
+          == __class_type_info::__contained_mask);
+}
+inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path)
+{
+  return ((access_path & (__class_type_info::__contained_mask
+                          | __class_type_info::__contained_virtual_mask))
+          == __class_type_info::__contained_mask);
+}
+
+static const __class_type_info *const nonvirtual_base_type =
+    static_cast <const __class_type_info *> (0) + 1;
+
+}; // namespace
+
+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 <void *> (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 <void> (obj_ptr, src2dst) == src_ptr
+            ? __contained_public : __not_contained;
+  if (src2dst == -2)
+    return __not_contained;
+  return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
+}
+
+__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 <void> (obj_ptr, src2dst) == src_ptr
+              ? __contained_public : __not_contained;
+      else if (src2dst == -2)
+        result.dst2src = __not_contained;
+      return false;
+    }
+  if (obj_ptr == src_ptr && *this == *src_type)
+    {
+      // The src object we started from. Indicate how we are accessible from
+      // the most derived object.
+      result.whole2src = access_path;
+      return false;
+    }
+  return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr,
+                             src_type, src_ptr, result);
+}
+
+// This is a big hairy function. Although the run-time behaviour of
+// dynamic_cast is simple to describe, it gives rise to some non-obvious
+// behaviour. We also desire to determine as early as possible any definite
+// answer we can get. Because it is unknown what the run-time ratio of
+// succeeding to failing dynamic casts is, we do not know in which direction
+// to bias any optimizations. To that end we make no particular effort towards
+// early fail answers or early success answers. Instead we try to minimize
+// work by filling in things lazily (when we know we need the information),
+// and opportunisticly take early success or failure results.
+bool __vmi_class_type_info::
+__do_dyncast (ptrdiff_t src2dst,
+              __sub_kind access_path,
+              const __class_type_info *dst_type,
+              const void *obj_ptr,
+              const __class_type_info *src_type,
+              const void *src_ptr,
+              __dyncast_result &__restrict result) const
+{
+  if (result.whole_details & __flags_unknown_mask)
+    result.whole_details = __flags;
+  
+  if (obj_ptr == src_ptr && *this == *src_type)
+    {
+      // The src object we started from. Indicate how we are accessible from
+      // the most derived object.
+      result.whole2src = access_path;
+      return false;
+    }
+  if (*this == *dst_type)
+    {
+      result.dst_ptr = obj_ptr;
+      result.whole2dst = access_path;
+      if (src2dst >= 0)
+        result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
+              ? __contained_public : __not_contained;
+      else if (src2dst == -2)
+        result.dst2src = __not_contained;
+      return false;
+    }
+
+  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 <const void *const *> (src_ptr);
+  const vtable_prefix *prefix =
+      adjust_pointer <vtable_prefix> (vtable, 
+                                     -offsetof (vtable_prefix, origin));
+  const void *whole_ptr =
+      adjust_pointer <void> (src_ptr, prefix->whole_object);
+  const __class_type_info *whole_type = prefix->whole_type;
+  __class_type_info::__dyncast_result result;
+  
+  whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
+                            dst_type, whole_ptr, src_type, src_ptr, result);
+  if (!result.dst_ptr)
+    return NULL;
+  if (contained_public_p (result.dst2src))
+    // Src is known to be a public base of dst.
+    return const_cast <void *> (result.dst_ptr);
+  if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
+    // Both src and dst are known to be public bases of whole. Found a valid
+    // cross cast.
+    return const_cast <void *> (result.dst_ptr);
+  if (contained_nonvirtual_p (result.whole2src))
+    // Src is known to be a non-public nonvirtual base of whole, and not a
+    // base of dst. Found an invalid cross cast, which cannot also be a down
+    // cast
+    return NULL;
+  if (result.dst2src == __class_type_info::__unknown)
+    result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
+                                                  src_type, src_ptr);
+  if (contained_public_p (result.dst2src))
+    // Found a valid down cast
+    return const_cast <void *> (result.dst_ptr);
+  // Must be an invalid down cast, or the cross cast wasn't bettered
+  return NULL;
+}
+
+}; // namespace __cxxabiv1
+#endif
diff --git a/libstdc++/tinfo.hP b/libstdc++/tinfo.hP
new file mode 100644 (file)
index 0000000..6be77ba
--- /dev/null
@@ -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 <const type_info *> (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 <limits.h>
+
+#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 <cxxabi.h>
+
+#endif
diff --git a/libstdc++/tinfo2.cc b/libstdc++/tinfo2.cc
new file mode 100644 (file)
index 0000000..6e1c916
--- /dev/null
@@ -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 <stddef.h>
+#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 <cxxabi.h>
+#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 <const __pbase_type_info *> (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 <const __pointer_to_member_type_info *> (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 <const __user_type_info *> (&throw_type))
+    {
+      return p->upcast (catch_type, objptr, valp);
+    }
+  else if (const __pointer_type_info *fr =
+          dynamic_cast <const __pointer_type_info *> (&throw_type))
+    {
+      const __pointer_type_info *to =
+          dynamic_cast <const __pointer_type_info *> (&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 <const __attr_type_info *> (subfr))
+       {
+         cvfrom = at->attr;
+         subfr = &at->type;
+       }
+      else
+       cvfrom = __attr_type_info::NONE;
+      
+      if (const __attr_type_info *at
+         = dynamic_cast <const __attr_type_info *> (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 <const __func_type_info *> (subfr) == 0)
+       return 1;
+      else if (const __user_type_info *p
+              = dynamic_cast <const __user_type_info *> (subfr))
+       return p->upcast (*subto, objptr, valp);
+      else if (const __pointer_type_info *pfr
+              = dynamic_cast <const __pointer_type_info *> (subfr))
+       {
+         // Multi-level pointer conversion.
+
+         const __pointer_type_info *pto
+           = dynamic_cast <const __pointer_type_info *> (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 <const __attr_type_info *> (subfr))
+               {
+                 cvfrom = at->attr;
+                 subfr = &at->type;
+               }
+             else
+               cvfrom = __attr_type_info::NONE;
+      
+             if (const __attr_type_info *at
+                 = dynamic_cast <const __attr_type_info *> (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 <const __pointer_type_info *> (subto);
+             pfr = dynamic_cast <const __pointer_type_info *> (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 <const type_info *>(p);
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+// old abi
+  const __pointer_type_info *pt =
+    dynamic_cast <const __pointer_type_info *> (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 (file)
index 0000000..91f0de2
--- /dev/null
@@ -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 <exception>
+
+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 (file)
index 0000000..966feb4
--- /dev/null
@@ -0,0 +1,279 @@
+// new abi support -*- C++ -*-
+// Copyright (C) 2000
+// Free Software Foundation, Inc.
+// Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
+// 
+// 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 <cxxabi.h>
+#include <new>
+#include <exception>
+
+// 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 <char *> (alloc (size));
+  
+  if (padding_size)
+    {
+      base += padding_size;
+      reinterpret_cast <size_t *> (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 <char *> (alloc (size));
+  
+  if (padding_size)
+    {
+      base += padding_size;
+      reinterpret_cast <size_t *> (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 <char *> (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 <char *> (dest_array);
+  char *src_ptr = static_cast <char *> (src_array);
+
+  try
+    {
+      if (constructor)
+       for (; ix != element_count; 
+            ix++, src_ptr += element_size, dest_ptr += element_size)
+         constructor (dest_ptr, src_ptr);
+    }
+  catch (...)
+    {
+      __uncatch_exception ();
+      __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 <char *> (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 <char *> (array_address);
+  
+  if (padding_size)
+    {
+      size_t element_count = reinterpret_cast <size_t *> (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 <char *> (array_address);
+  size_t size = 0;
+  
+  if (padding_size)
+    {
+      size_t element_count = reinterpret_cast <size_t *> (base)[-1];
+      base -= padding_size;
+      size = element_count * element_size + padding_size;
+      try
+        {
+          __cxa_vec_dtor (array_address, element_count, element_size,
+                          destructor);
+        }
+      catch (...)
+        {
+          __uncatch_exception ();
+          dealloc (base, size);
+          throw;
+        }
+    }
+  dealloc (base, size);
+}
+
+} // namespace __cxxabiv1
+
+#endif // defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100