From bbd0d54ab38bcf23ec5aef1d50c2593d6c39853a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 24 Aug 1999 04:16:06 +0000 Subject: [PATCH] exception.cc (__cplus_type_matcher): Call __throw_type_match_rtti_2. * exception.cc (__cplus_type_matcher): Call __throw_type_match_rtti_2. Return arbitrary pointer or NULL. (check_eh_spec): Call __throw_type_match_rtti_2. * tinfo.h (*::dcast): Return int. Add valp parm. * tinfo.cc (*::dcast): Likewise. Adjust to allow for null pointers. * tinfo2.cc (__throw_type_match_rtti_2): Likewise. (__throw_type_match_rtti): Now just a wrapper. * except.c: Lose CatchMatch, FirstExceptionMatch, and Unwind. (init_exception_processing): Don't initialize them. From-SVN: r28811 --- gcc/cp/ChangeLog | 13 +++++++ gcc/cp/except.c | 44 ++--------------------- gcc/cp/exception.cc | 28 ++++++++------- gcc/cp/tinfo.cc | 87 +++++++++++++++++++++++++++++---------------- gcc/cp/tinfo.h | 14 ++++---- gcc/cp/tinfo2.cc | 72 +++++++++++++++++++------------------ 6 files changed, 132 insertions(+), 126 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f279000acaa..77deef6d25bf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +1999-08-23 Jason Merrill + + * exception.cc (__cplus_type_matcher): Call __throw_type_match_rtti_2. + Return arbitrary pointer or NULL. + (check_eh_spec): Call __throw_type_match_rtti_2. + * tinfo.h (*::dcast): Return int. Add valp parm. + * tinfo.cc (*::dcast): Likewise. Adjust to allow for null pointers. + * tinfo2.cc (__throw_type_match_rtti_2): Likewise. + (__throw_type_match_rtti): Now just a wrapper. + + * except.c: Lose CatchMatch, FirstExceptionMatch, and Unwind. + (init_exception_processing): Don't initialize them. + 1999-08-23 Paul Burchard * decl.c (check_default_argument): Fix typo. diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 0a9bcf54f0fe..100ff2c7b88e 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -155,25 +155,12 @@ asm (TEXT_SECTION_ASM_OP); /* local globals for function calls ====================================================================== */ -/* Used to cache "terminate" and "__throw_type_match*". */ -static tree Terminate, CatchMatch; - -/* Used to cache __find_first_exception_table_match for throw. */ -static tree FirstExceptionMatch; - -/* Used to cache a call to __unwind_function. */ -static tree Unwind; +static tree Terminate; /* ====================================================================== */ - -/* ========================================================================= */ - /* sets up all the global eh stuff that needs to be initialized at the - start of compilation. - - This includes: - - Setting up all the function call trees. */ + start of compilation. */ void init_exception_processing () @@ -189,36 +176,9 @@ init_exception_processing () if (flag_honor_std) pop_namespace (); - push_lang_context (lang_name_c); - set_exception_lang_code (EH_LANG_C_plus_plus); set_exception_version_code (1); - CatchMatch - = builtin_function (flag_rtti - ? "__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, - void_list_node)))), - NOT_BUILT_IN, NULL_PTR); - FirstExceptionMatch - = builtin_function ("__find_first_exception_table_match", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, ptr_type_node, - void_list_node)), - NOT_BUILT_IN, NULL_PTR); - Unwind - = builtin_function ("__unwind_function", - build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - void_list_node)), - NOT_BUILT_IN, NULL_PTR); - - pop_lang_context (); - /* If we use setjmp/longjmp EH, arrange for all cleanup actions to be protected with __terminate. */ protect_cleanup_actions_with_terminate = 1; diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc index 372536ed9520..efc0b1fe83c3 100644 --- a/gcc/cp/exception.cc +++ b/gcc/cp/exception.cc @@ -165,12 +165,14 @@ __eh_free (void *p) free (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) + exception_descriptor *exception_table) { cp_eh_info *info = (cp_eh_info *)info_; - void *ret; /* No exception table implies the old style mechanism, so don't check. */ if (exception_table != NULL @@ -178,18 +180,19 @@ __cplus_type_matcher (__eh_info *info_, void *match_info, return NULL; if (match_info == CATCH_ALL_TYPE) - return info->value; + return (void *)1; /* we don't worry about version info yet, there is only one version! */ void *match_type = ((void *(*)())match_info) (); - ret = __throw_type_match_rtti (match_type, info->type, info->original_value); - /* change value of exception */ - if (ret) - info->value = ret; - return ret; -} + 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(). */ @@ -278,10 +281,11 @@ 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 (spec[i], p->type, p->value)) + if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d)) throw; } @@ -297,7 +301,7 @@ __check_eh_spec (int n, const void **spec) p = __exception_info; for (int i = 0; i < n; ++i) { - if (__throw_type_match_rtti (spec[i], p->type, p->value)) + if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d)) throw; } } @@ -305,7 +309,7 @@ __check_eh_spec (int n, const void **spec) const std::type_info &bad_exc = typeid (std::bad_exception); for (int i = 0; i < n; ++i) { - if (__throw_type_match_rtti (spec[i], &bad_exc, p->value)) + if (__throw_type_match_rtti_2 (spec[i], &bad_exc, p->value, &d)) throw std::bad_exception (); } diff --git a/gcc/cp/tinfo.cc b/gcc/cp/tinfo.cc index 5269cb5940e4..fe22e8de0745 100644 --- a/gcc/cp/tinfo.cc +++ b/gcc/cp/tinfo.cc @@ -1,5 +1,5 @@ // Methods for type_info for -*- C++ -*- Run Time Type Identification. -// Copyright (C) 1994, 1996, 1998 Free Software Foundation +// Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation // This file is part of GNU CC. @@ -63,43 +63,66 @@ __rtti_user (void *addr, const char *name) { new (addr) __user_type_info (name); } // dynamic_cast helper methods. -// Returns a pointer to the desired sub-object or 0. +// Returns 1 if the cast succeeds, 0 otherwise. Stores the adjusted value +// in VALP. -void * __user_type_info:: -dcast (const type_info& to, int, void *addr, const type_info *, void *) const -{ return (*this == to) ? addr : 0; } +int __user_type_info:: +dcast (const type_info& to, int, void *addr, void **valp, + const type_info *, void *) const +{ + *valp = addr; + return (*this == to); +} -void * __si_type_info:: -dcast (const type_info& to, int require_public, void *addr, +int __si_type_info:: +dcast (const type_info& to, int require_public, void *addr, void **valp, const type_info *sub, void *subptr) const { if (*this == to) - return addr; - return base.dcast (to, require_public, addr, sub, subptr); + { + *valp = addr; + return 1; + } + return base.dcast (to, require_public, addr, valp, sub, subptr); } -void* __class_type_info:: -dcast (const type_info& desired, int is_public, void *objptr, +int __class_type_info:: +dcast (const type_info& desired, int is_public, void *objptr, void **valp, const type_info *sub, void *subptr) const { - if (*this == desired) - return objptr; + *valp = objptr; + + if (*this == desired) + return 1; + + int match_found = 0; + void *match = 0; - void *match_found = 0; for (size_t i = 0; i < n_bases; i++) { if (is_public && base_list[i].access != PUBLIC) continue; - void *p = (char *)objptr + base_list[i].offset; - if (base_list[i].is_virtual) - p = *(void **)p; - p = base_list[i].base->dcast (desired, is_public, p, sub, subptr); - if (p) + void *p; + + if (objptr) { - if (match_found == 0) - match_found = p; - else if (match_found != p) + p = (char *)objptr + base_list[i].offset; + if (base_list[i].is_virtual) + p = *(void **)p; + } + else + /* Preserve null pointer. */ + p = objptr; + + if (base_list[i].base->dcast (desired, is_public, p, &p, sub, subptr)) + { + if (! match_found) + { + match_found = 1; + match = p; + } + else if (match != p) { if (sub) { @@ -109,26 +132,30 @@ dcast (const type_info& desired, int is_public, void *objptr, const __user_type_info &d = static_cast (desired); - void *os = d.dcast (*sub, 1, match_found); - void *ns = d.dcast (*sub, 1, p); + void *os; + d.dcast (*sub, 1, match, &os); + void *ns; + d.dcast (*sub, 1, p, &ns); if (os == ns) - /* ambiguous -- subptr is a virtual base */; + // Both have the same subobject, so we can't disambiguate; + // i.e. subptr is a virtual base. + return 0; else if (os == subptr) continue; else if (ns == subptr) { - match_found = p; + match = p; continue; } } - - // base found at two different pointers, - // conversion is not unique - return 0; + else + // We're not downcasting, so we can't disambiguate. + return 0; } } } + *valp = match; return match_found; } diff --git a/gcc/cp/tinfo.h b/gcc/cp/tinfo.h index e0b9eec78970..ffca9c35cf16 100644 --- a/gcc/cp/tinfo.h +++ b/gcc/cp/tinfo.h @@ -1,5 +1,5 @@ // RTTI support internals for -*- C++ -*- -// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation +// Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation #include "typeinfo" @@ -12,8 +12,8 @@ struct __user_type_info : public std::type_info { // If our type can be converted to the desired type, // return the pointer, adjusted accordingly; else return 0. - virtual void* dcast (const type_info &, int, void *, - const type_info * = 0, void * = 0) const; + virtual int dcast (const type_info &, int, void *, void **, + const type_info * = 0, void * = 0) const; }; // type_info for a class with one public, nonvirtual base class. @@ -25,8 +25,8 @@ public: __si_type_info (const char *n, const __user_type_info &b) : __user_type_info (n), base (b) { } - virtual void *dcast (const type_info &, int, void *, - const type_info * = 0, void * = 0) const; + virtual int dcast (const type_info &, int, void *, void **, + const type_info * = 0, void * = 0) const; }; // type_info for a general class. @@ -50,6 +50,6 @@ struct __class_type_info : public __user_type_info { : __user_type_info (name), base_list (bl), n_bases (bn) {} // This is a little complex. - virtual void* dcast (const type_info &, int, void *, - const type_info * = 0, void * = 0) const; + virtual int dcast (const type_info &, int, void *, void **, + const type_info * = 0, void * = 0) const; }; diff --git a/gcc/cp/tinfo2.cc b/gcc/cp/tinfo2.cc index b101db3c0548..877872f4e70a 100644 --- a/gcc/cp/tinfo2.cc +++ b/gcc/cp/tinfo2.cc @@ -1,5 +1,5 @@ // Methods for type_info for -*- C++ -*- Run Time Type Identification. -// Copyright (C) 1994, 96-97, 1998 Free Software Foundation +// Copyright (C) 1994, 96-97, 1998, 1999 Free Software Foundation // This file is part of GNU CC. @@ -93,28 +93,23 @@ struct __array_type_info : public type_info { /* Low level match routine used by compiler to match types of catch variables and thrown objects. */ -extern "C" void* -__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, - void *objptr) +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 (catch_type == throw_type) - return objptr; + return 1; -#if 0 - printf ("We want to match a %s against a %s!\n", - throw_type.name (), catch_type.name ()); -#endif - - void *new_objptr = 0; - if (const __user_type_info *p = dynamic_cast (&throw_type)) { /* The 1 skips conversions to private bases. */ - new_objptr = p->dcast (catch_type, 1, objptr); + return p->dcast (catch_type, 1, objptr, valp); } else if (const __pointer_type_info *fr = dynamic_cast (&throw_type)) @@ -123,7 +118,7 @@ __throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, dynamic_cast (&catch_type); if (! to) - goto fail; + return 0; const type_info *subfr = &fr->type, *subto = &to->type; __attr_type_info::cv cvfrom, cvto; @@ -150,18 +145,18 @@ __throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, > (cvto & __attr_type_info::CONST)) || ((cvfrom & __attr_type_info::VOLATILE) > (cvto & __attr_type_info::VOLATILE))) - goto fail; + return 0; if (*subto == *subfr) - new_objptr = objptr; + return 1; else if (*subto == typeid (void) && dynamic_cast (subfr) == 0) - new_objptr = objptr; + return 1; else if (const __user_type_info *p = dynamic_cast (subfr)) { /* The 1 skips conversions to private bases. */ - new_objptr = p->dcast (*subto, 1, objptr); + return p->dcast (*subto, 1, objptr, valp); } else if (const __pointer_type_info *pfr = dynamic_cast (subfr)) @@ -172,7 +167,7 @@ __throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, = dynamic_cast (subto); if (! pto) - goto fail; + return 0; bool constp = (cvto & __attr_type_info::CONST); for (subto = &pto->type, subfr = &pfr->type; ; @@ -200,38 +195,42 @@ __throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, > (cvto & __attr_type_info::CONST)) || ((cvfrom & __attr_type_info::VOLATILE) > (cvto & __attr_type_info::VOLATILE))) - goto fail; + return 0; if (! constp && (((cvfrom & __attr_type_info::CONST) < (cvto & __attr_type_info::CONST)) || ((cvfrom & __attr_type_info::VOLATILE) < (cvto & __attr_type_info::VOLATILE)))) - goto fail; + return 0; if (*subto == *subfr) - { - new_objptr = objptr; - break; - } + return 1; pto = dynamic_cast (subto); pfr = dynamic_cast (subfr); if (! pto || ! pfr) - goto fail; + return 0; if (! (cvto & __attr_type_info::CONST)) constp = false; } } } - fail: -#if 0 - if (new_objptr) - printf ("It converts, delta is %d\n", new_objptr-objptr); -#endif - return new_objptr; + return 0; +} + +/* 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; } /* Called from __cp_pop_exception. Is P the type_info node for a pointer @@ -278,8 +277,11 @@ __dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void), int require_public, void *address, const type_info & (*sub)(void), void *subptr) { - return static_cast (from ()).dcast - (to (), require_public, address, &(sub ()), subptr); + void *ret; + if (static_cast (from ()).dcast + (to (), require_public, address, &ret, &(sub ()), subptr)) + return ret; + return 0; } // type_info nodes and functions for the builtin types. The mangling here