From: Jason Merrill Date: Fri, 21 Nov 1997 21:04:23 +0000 (-0500) Subject: revert large changes X-Git-Tag: releases/egcs-1.0.0~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11c4a5a2e820bdd85379b6a6333920daf223f15a;p=thirdparty%2Fgcc.git revert large changes From-SVN: r16655 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b94e102ec9f0..f2df07d0752e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -21,10 +21,6 @@ Thu Nov 20 16:11:50 1997 Klaus Kaempf Thu Nov 20 14:42:15 1997 Jason Merrill - * Makefile.in (LIB2FUNCS): Remove C++ memory management support. - * libgcc2.c: Remove __builtin_new, __builtin_vec_new, set_new_handler, - __builtin_delete, and __builtin_vec_delete. - * except.c (output_exception_table): Don't bother with __EXCEPTION_END__. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 3779ae2e6362..b02f0c6ec076 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -631,8 +631,8 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \ _fixunsdfsi _fixunssfsi _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi \ _fixxfdi _fixunsxfdi _floatdixf _fixunsxfsi \ _fixtfdi _fixunstfdi _floatditf \ - __gcc_bcmp _varargs __dummy _eprintf \ - _bb _shtab _clear_cache _trampoline __main _exit \ + __gcc_bcmp _varargs __dummy _eprintf _op_new _op_vnew _new_handler \ + _op_delete _op_vdel _bb _shtab _clear_cache _trampoline __main _exit \ _ctors _eh _pure # The files that "belong" in CONFIG_H are deliberately omitted diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 48099a7a8227..8a5a8b37d225 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,31 +1,11 @@ Fri Nov 21 12:22:07 1997 Jason Merrill - * except.c (expand_start_eh_spec): Use the try/catch code. - (expand_end_eh_spec): Likewise. Call __check_eh_spec instead of - doing everything inline. - (init_exception_processing): throw_type_match now takes - const void pointers. - * exception.cc (__check_eh_spec): New fn. - * inc/exception: Neither terminate nor unexpected return. - * decl.c: Make const_ptr_type_node public. - * tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly. - * except.c (expand_start_catch_block): We only need the rethrow region for non-sjlj exceptions. (expand_end_catch_block): Likewise. Use outer_context_label_stack. Thu Nov 20 14:40:17 1997 Jason Merrill - * Make-lang.in (CXX_LIB2FUNCS): Add new op new and op delete objs. - (various.o): Likewise. - * inc/new: Add placement deletes. Add throw specs for default new. - * new.cc (set_new_handler): Move here from libgcc2. - * new1.cc (new (nothrow)): Catch a bad_alloc thrown from the handler. - (new): Move from libgcc2. Throw bad_alloc. - * new2.cc: Move the rest of the op news and op deletes from libgcc2. - * decl.c (init_decl_processing): Update exception specs on new and - delete. - * method.c (build_decl_overload_real): Don't mess with global placement delete. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index fa0f1dd62893..903faffc2ace 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -58,8 +58,7 @@ CXX_EXTRA_HEADERS = $(srcdir)/cp/inc/typeinfo $(srcdir)/cp/inc/exception \ $(srcdir)/cp/inc/new $(srcdir)/cp/inc/new.h # Extra code to include in libgcc2. -CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o opnew.o opnewnt.o opvnew.o opvnewnt.o \ - opdel.o opdelnt.o opvdel.o opvdelnt.o exception.o +CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o new1.o new2.o exception.o CXX_LIB2SRCS = $(srcdir)/cp/new.cc $(srcdir)/cp/new1.cc $(srcdir)/cp/new2.cc \ $(srcdir)/cp/exception.cc $(srcdir)/cp/tinfo.cc \ $(srcdir)/cp/tinfo2.cc $(srcdir)/cp/tinfo.h @@ -148,30 +147,12 @@ exception.o: cc1plus $(srcdir)/cp/exception.cc new.o: cc1plus $(srcdir)/cp/new.cc $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ -c $(srcdir)/cp/new.cc -opnew.o: cc1plus $(srcdir)/cp/new1.cc +new1.o: cc1plus $(srcdir)/cp/new1.cc $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new1.cc -DL_op_new -o opnew.o -opnewnt.o: cc1plus $(srcdir)/cp/new1.cc + -c $(srcdir)/cp/new1.cc +new2.o: cc1plus $(srcdir)/cp/new2.cc $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new1.cc -DL_op_newnt -o opnewnt.o -opvnew.o: cc1plus $(srcdir)/cp/new2.cc - $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new2.cc -DL_op_vnew -o opvnew.o -opvnewnt.o: cc1plus $(srcdir)/cp/new2.cc - $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new2.cc -DL_op_vnewnt -o opvnewnt.o -opdel.o: cc1plus $(srcdir)/cp/new2.cc - $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new2.cc -DL_op_delete -o opdel.o -opdelnt.o: cc1plus $(srcdir)/cp/new2.cc - $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new2.cc -DL_op_delnt -o opdelnt.o -opvdel.o: cc1plus $(srcdir)/cp/new2.cc - $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new2.cc -DL_op_vdel -o opvdel.o -opvdelnt.o: cc1plus $(srcdir)/cp/new2.cc - $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ - -c $(srcdir)/cp/new2.cc -DL_op_vdelnt -o opvdelnt.o + -c $(srcdir)/cp/new2.cc # We want to update cplib2.txt if any of the source files change... cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c9e5c475ee56..b60f842fa43b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -239,7 +239,7 @@ tree void_zero_node; /* Nodes for types `void *' and `const void *'. */ tree ptr_type_node; -tree const_ptr_type_node; +static tree const_ptr_type_node; /* Nodes for types `char *' and `const char *'. */ @@ -5577,18 +5577,14 @@ init_decl_processing () /* Now, C++. */ current_lang_name = lang_name_cplusplus; - { - tree bad_alloc_type_node = xref_tag - (class_type_node, get_identifier ("bad_alloc"), NULL_TREE, 1); - tree newtype = build_exception_variant - (ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node)); - tree deltype = build_exception_variant - (void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE)); - auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN); - auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN); - auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN); - auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN); - } + auto_function (ansi_opname[(int) NEW_EXPR], ptr_ftype_sizetype, + NOT_BUILT_IN); + auto_function (ansi_opname[(int) VEC_NEW_EXPR], ptr_ftype_sizetype, + NOT_BUILT_IN); + auto_function (ansi_opname[(int) DELETE_EXPR], void_ftype_ptr, + NOT_BUILT_IN); + auto_function (ansi_opname[(int) VEC_DELETE_EXPR], void_ftype_ptr, + NOT_BUILT_IN); abort_fndecl = define_function ("__pure_virtual", void_ftype, diff --git a/gcc/cp/except.c b/gcc/cp/except.c index bd26053dfcef..5c2344d43d79 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -197,7 +197,6 @@ static tree saved_pc; extern int throw_used; extern rtx catch_clauses; -extern tree const_ptr_type_node; /* ========================================================================= */ @@ -264,8 +263,8 @@ init_exception_processing () ? "__throw_type_match_rtti" : "__throw_type_match", build_function_type (ptr_type_node, - tree_cons (NULL_TREE, const_ptr_type_node, - tree_cons (NULL_TREE, const_ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node)))), NOT_BUILT_IN, NULL_PTR); @@ -1021,84 +1020,101 @@ expand_builtin_throw () #endif /* DWARF2_UNWIND_INFO */ } -/* An exception spec is implemented more or less like: - - try { - function body; - } catch (...) { - void *p[] = { typeid(raises) }; - __check_eh_spec (p, count); - } - - __check_eh_spec in exception.cc handles all the details. */ void expand_start_eh_spec () { - expand_start_try_stmts (); + expand_eh_region_start (); } static void expand_end_eh_spec (raises) tree raises; { - tree tmp, fn, decl, types = NULL_TREE; - int count = 0; - - expand_start_all_catch (); - expand_start_catch_block (NULL_TREE, NULL_TREE); + tree expr, second_try; + rtx check = gen_label_rtx (); + rtx cont; + rtx ret = gen_reg_rtx (Pmode); + rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node)); + rtx end = gen_label_rtx (); + + expr = make_node (RTL_EXPR); + TREE_TYPE (expr) = void_type_node; + RTL_EXPR_RTL (expr) = const0_rtx; + TREE_SIDE_EFFECTS (expr) = 1; + do_pending_stack_adjust (); + start_sequence_for_rtl_expr (expr); + cont = gen_label_rtx (); + emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont)); + emit_jump (check); + emit_label (cont); + jumpif (make_tree (integer_type_node, flag), end); + do_function_call (Terminate, NULL_TREE, NULL_TREE); + assemble_external (TREE_OPERAND (Terminate, 0)); + emit_barrier (); + do_pending_stack_adjust (); + RTL_EXPR_SEQUENCE (expr) = get_insns (); + end_sequence (); + + second_try = expr; - /* Build up an array of type_infos. */ - for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises)) - { - types = expr_tree_cons - (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types); - ++count; - } + expr = make_node (RTL_EXPR); + TREE_TYPE (expr) = void_type_node; + RTL_EXPR_RTL (expr) = const0_rtx; + TREE_SIDE_EFFECTS (expr) = 1; + do_pending_stack_adjust (); + start_sequence_for_rtl_expr (expr); - types = build_nt (CONSTRUCTOR, NULL_TREE, types); - TREE_HAS_CONSTRUCTOR (types) = 1; + cont = gen_label_rtx (); + emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont)); + emit_jump (check); + emit_label (cont); + jumpif (make_tree (integer_type_node, flag), end); + expand_eh_region_start (); + do_function_call (Unexpected, NULL_TREE, NULL_TREE); + assemble_external (TREE_OPERAND (Unexpected, 0)); + emit_barrier (); - /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */ - tmp = build_array_type (const_ptr_type_node, NULL_TREE); - decl = build_decl (VAR_DECL, NULL_TREE, tmp); - DECL_ARTIFICIAL (decl) = 1; - DECL_INITIAL (decl) = types; - cp_finish_decl (decl, types, NULL_TREE, 0, 0); + expand_eh_region_end (second_try); + + emit_label (check); + emit_move_insn (flag, const1_rtx); + cont = gen_label_rtx (); - decl = decay_conversion (decl); + push_eh_info (); - fn = get_identifier ("__check_eh_spec"); - if (IDENTIFIER_GLOBAL_VALUE (fn)) - fn = IDENTIFIER_GLOBAL_VALUE (fn); - else + while (raises) { - push_obstacks_nochange (); - end_temporary_allocation (); + tree exp; + tree match_type = TREE_VALUE (raises); + + if (match_type) + { + /* check TREE_VALUE (raises) here */ + exp = get_eh_value (); + exp = expr_tree_cons (NULL_TREE, + build_eh_type_type (match_type), + expr_tree_cons (NULL_TREE, + get_eh_type (), + expr_tree_cons (NULL_TREE, exp, NULL_TREE))); + exp = build_function_call (CatchMatch, exp); + assemble_external (TREE_OPERAND (CatchMatch, 0)); + + jumpif (exp, cont); + } - tmp = tree_cons - (NULL_TREE, integer_type_node, tree_cons - (NULL_TREE, TREE_TYPE (decl), void_list_node)); - tmp = build_function_type (void_type_node, tmp); - - fn = build_lang_decl (FUNCTION_DECL, fn, tmp); - DECL_EXTERNAL (fn) = 1; - TREE_PUBLIC (fn) = 1; - DECL_ARTIFICIAL (fn) = 1; - TREE_THIS_VOLATILE (fn) = 1; - pushdecl_top_level (fn); - make_function_rtl (fn); - assemble_external (fn); - pop_obstacks (); + raises = TREE_CHAIN (raises); } - - tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons - (NULL_TREE, decl, NULL_TREE)); - tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp); - expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); - - expand_end_catch_block (); - expand_end_all_catch (); + emit_move_insn (flag, const0_rtx); + emit_label (cont); + emit_indirect_jump (ret); + emit_label (end); + + do_pending_stack_adjust (); + RTL_EXPR_SEQUENCE (expr) = get_insns (); + end_sequence (); + + expand_eh_region_end (expr); } /* This is called to expand all the toplevel exception handling diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc index 28071183c0f5..2d1ae0812470 100644 --- a/gcc/cp/exception.cc +++ b/gcc/cp/exception.cc @@ -47,8 +47,7 @@ __default_unexpected () terminate (); } -static unexpected_handler __unexpected_func __attribute__((__noreturn__)) - = __default_unexpected; +static unexpected_handler __unexpected_func = __default_unexpected; terminate_handler set_terminate (terminate_handler func) @@ -160,54 +159,6 @@ __uncatch_exception (void) /* otherwise __throw will call terminate(); don't crash here. */ } -/* 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_exception_info (); - - for (int i = 0; i < n; ++i) - { - if (__throw_type_match_rtti (spec[i], p->type, p->value)) - throw; - } - - try - { - unexpected (); - } - catch (...) - { - // __exception_info is an artificial var pushed into each catch block. - p = __exception_info; - for (int i = 0; i < n; ++i) - { - if (__throw_type_match_rtti (spec[i], p->type, p->value)) - throw; - } - - const type_info &bad_exc = typeid (bad_exception); - for (int i = 0; i < n; ++i) - { - if (__throw_type_match_rtti (spec[i], &bad_exc, p->value)) - throw bad_exception (); - } - - terminate (); - } -} - extern "C" void __throw_bad_cast (void) { diff --git a/gcc/cp/new.cc b/gcc/cp/new.cc index 33cf190108cb..0db3497f1fa2 100644 --- a/gcc/cp/new.cc +++ b/gcc/cp/new.cc @@ -29,13 +29,3 @@ #include "new" const nothrow_t nothrow = { }; - -new_handler __new_handler; - -new_handler -set_new_handler (new_handler handler) -{ - new_handler prev_handler = __new_handler; - __new_handler = handler; - return prev_handler; -} diff --git a/gcc/cp/new1.cc b/gcc/cp/new1.cc index 98c2a4a955e2..0ee111d29395 100644 --- a/gcc/cp/new1.cc +++ b/gcc/cp/new1.cc @@ -1,4 +1,4 @@ -// Support routines for the -*- C++ -*- dynamic memory management. +// Support routine for the -*- C++ -*- dynamic memory management. // Copyright (C) 1997 Free Software Foundation // This file is part of GNU CC. @@ -28,16 +28,15 @@ #include "new" extern "C" void *malloc (size_t); -extern new_handler __new_handler; -#define WEAK(x) \ - x __attribute__ ((weak)); \ - x +typedef void (*vfp)(void); +extern vfp __new_handler; +extern void __default_new_handler (void); -#ifdef L_op_newnt -WEAK (void * operator new (size_t sz, const nothrow_t&) throw()) +void *operator new (size_t sz, const nothrow_t&) throw() { void *p; + vfp handler = __new_handler; /* malloc (0) is unpredictable; avoid it. */ if (sz == 0) @@ -45,43 +44,11 @@ WEAK (void * operator new (size_t sz, const nothrow_t&) throw()) 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; -} -#endif - -#ifdef L_op_new -WEAK (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 (); + (*handler) (); p = (void *) malloc (sz); } - + return p; } -#endif diff --git a/gcc/cp/new2.cc b/gcc/cp/new2.cc index d5320f99502c..5aca49d21d11 100644 --- a/gcc/cp/new2.cc +++ b/gcc/cp/new2.cc @@ -1,4 +1,4 @@ -// Boilerplate support routines for -*- C++ -*- dynamic memory management. +// Support routine for the -*- C++ -*- dynamic memory management. // Copyright (C) 1997 Free Software Foundation // This file is part of GNU CC. @@ -27,54 +27,7 @@ #include "new" -extern "C" void free (void *); - -#define WEAK(x) \ - x __attribute__ ((weak)); \ - x - -#ifdef L_op_vnew -WEAK(void * operator new[] (size_t sz) throw (std::bad_alloc)) -{ - return ::operator new(sz); -} -#endif - -#ifdef L_op_vnewnt -WEAK(void *operator new[] (size_t sz, const nothrow_t& nothrow) throw()) +void *operator new[] (size_t sz, const nothrow_t& nothrow) throw() { return ::operator new(sz, nothrow); } -#endif - -#ifdef L_op_delete -WEAK (void operator delete (void *ptr) throw ()) -{ - if (ptr) - free (ptr); -} -#endif - -#ifdef L_op_vdel -WEAK (void operator delete[] (void *ptr) throw ()) -{ - if (ptr) - free (ptr); -} -#endif - -#ifdef L_op_delnt -WEAK (void operator delete (void *ptr, const std::nothrow_t&) throw ()) -{ - if (ptr) - free (ptr); -} -#endif - -#ifdef L_op_vdelnt -WEAK (void operator delete[] (void *ptr, const std::nothrow_t&) throw ()) -{ - if (ptr) - free (ptr); -} -#endif diff --git a/gcc/cp/tinfo2.cc b/gcc/cp/tinfo2.cc index 531348895271..128661c1cd2e 100644 --- a/gcc/cp/tinfo2.cc +++ b/gcc/cp/tinfo2.cc @@ -119,8 +119,7 @@ struct __array_type_info : public type_info { variables and thrown objects. */ extern "C" void* -__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, - void *objptr) +__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr) { const type_info &catch_type = *(const type_info *)catch_type_r; const type_info &throw_type = *(const type_info *)throw_type_r; diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 7fec5cdd45ed..6c34da7acf52 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -42,6 +42,10 @@ Boston, MA 02111-1307, USA. */ #undef abort #endif +#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS)) +#define WEAK_ALIAS +#endif + /* Permit the tm.h file to select the endianness to use just for this file. This is used when the endianness is determined when the compiler is run. */ @@ -2432,6 +2436,157 @@ stack_overflow:; #endif /* not BLOCK_PROFILER_CODE */ #endif /* L_bb */ +/* Default free-store management functions for C++, per sections 12.5 and + 17.3.3 of the Working Paper. */ + +#ifdef L_op_new +/* operator new (size_t), described in 17.3.3.5. This function is used by + C++ programs to allocate a block of memory to hold a single object. */ + +typedef void (*vfp)(void); +extern vfp __new_handler; +extern void __default_new_handler (void); + +#ifdef WEAK_ALIAS +void * __builtin_new (size_t sz) + __attribute__ ((weak, alias ("___builtin_new"))); +void * +___builtin_new (size_t sz) +#else +void * +__builtin_new (size_t sz) +#endif +{ + void *p; + vfp handler = (__new_handler) ? __new_handler : __default_new_handler; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + (*handler) (); + p = (void *) malloc (sz); + } + + return p; +} +#endif /* L_op_new */ + +#ifdef L_op_vnew +/* void * operator new [] (size_t), described in 17.3.3.6. This function + is used by C++ programs to allocate a block of memory for an array. */ + +extern void * __builtin_new (size_t); + +#ifdef WEAK_ALIAS +void * __builtin_vec_new (size_t sz) + __attribute__ ((weak, alias ("___builtin_vec_new"))); +void * +___builtin_vec_new (size_t sz) +#else +void * +__builtin_vec_new (size_t sz) +#endif +{ + return __builtin_new (sz); +} +#endif /* L_op_vnew */ + +#ifdef L_new_handler +/* set_new_handler (fvoid_t *) and the default new handler, described in + 17.3.3.2 and 17.3.3.5. These functions define the result of a failure + to allocate the amount of memory requested from operator new or new []. */ + +#ifndef inhibit_libc +/* This gets us __GNU_LIBRARY__. */ +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include + +#ifdef __GNU_LIBRARY__ + /* Avoid forcing the library's meaning of `write' on the user program + by using the "internal" name (for use within the library) */ +#define write(fd, buf, n) __write((fd), (buf), (n)) +#endif +#endif /* inhibit_libc */ + +typedef void (*vfp)(void); +void __default_new_handler (void); + +vfp __new_handler = (vfp) 0; + +vfp +set_new_handler (vfp handler) +{ + vfp prev_handler; + + prev_handler = __new_handler; + if (handler == 0) handler = __default_new_handler; + __new_handler = handler; + return prev_handler; +} + +#define MESSAGE "Virtual memory exceeded in `new'\n" + +void +__default_new_handler () +{ +#ifndef inhibit_libc + /* don't use fprintf (stderr, ...) because it may need to call malloc. */ + /* This should really print the name of the program, but that is hard to + do. We need a standard, clean way to get at the name. */ + write (2, MESSAGE, sizeof (MESSAGE)); +#endif + /* don't call exit () because that may call global destructors which + may cause a loop. */ + _exit (-1); +} +#endif + +#ifdef L_op_delete +/* operator delete (void *), described in 17.3.3.3. This function is used + by C++ programs to return to the free store a block of memory allocated + as a single object. */ + +#ifdef WEAK_ALIAS +void __builtin_delete (void *ptr) + __attribute__ ((weak, alias ("___builtin_delete"))); +void +___builtin_delete (void *ptr) +#else +void +__builtin_delete (void *ptr) +#endif +{ + if (ptr) + free (ptr); +} +#endif + +#ifdef L_op_vdel +/* operator delete [] (void *), described in 17.3.3.4. This function is + used by C++ programs to return to the free store a block of memory + allocated as an array. */ + +extern void __builtin_delete (void *); + +#ifdef WEAK_ALIAS +void __builtin_vec_delete (void *ptr) + __attribute__ ((weak, alias ("___builtin_vec_delete"))); +void +___builtin_vec_delete (void *ptr) +#else +void +__builtin_vec_delete (void *ptr) +#endif +{ + __builtin_delete (ptr); +} +#endif + +/* End of C++ free-store management functions */ + #ifdef L_shtab unsigned int __shtab[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008,