From 059fa5e776a738f956ad62692a1a143ba34d86b0 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 24 Jan 2000 12:16:59 +0000 Subject: [PATCH] cp-tree.h (CPTI_BAD_CAST, [...]): New cp_tree_index values. * cp-tree.h (CPTI_BAD_CAST, CPTI_BAD_TYPEID, CPTI_DCAST): New cp_tree_index values. (throw_bad_cast_node, throw_bad_typeid_node, dynamic_cast_node): New global node #defines for them. * rtti.c (call_void_fn): Replace with ... (build_runtime_decl): ... new static function. (throw_bad_cast): Use throw_bad_cast_node and build_runtime_decl. (throw_bad_typeid): Use throw_bad_typeid_node and build_runtime_decl. (build_dynamic_cast_1): Always produce correctly typed result. Explicitly produce type_info addresses. Use dynamic_cast_node. * exception.cc (__throw_bad_cast): Return `void *'. (__throw_bad_typeid): Return `const type_info &'. From-SVN: r31585 --- gcc/cp/ChangeLog | 15 ++++++++++ gcc/cp/cp-tree.h | 12 ++++++++ gcc/cp/exception.cc | 13 +++++--- gcc/cp/rtti.c | 72 +++++++++++++++++++++++++++++---------------- 4 files changed, 83 insertions(+), 29 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c50831b139f..0b2cda1c921 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2000-01-24 Nathan Sidwell + + * cp-tree.h (CPTI_BAD_CAST, CPTI_BAD_TYPEID, CPTI_DCAST): New + cp_tree_index values. + (throw_bad_cast_node, throw_bad_typeid_node, dynamic_cast_node): + New global node #defines for them. + * rtti.c (call_void_fn): Replace with ... + (build_runtime_decl): ... new static function. + (throw_bad_cast): Use throw_bad_cast_node and build_runtime_decl. + (throw_bad_typeid): Use throw_bad_typeid_node and build_runtime_decl. + (build_dynamic_cast_1): Always produce correctly typed result. + Explicitly produce type_info addresses. Use dynamic_cast_node. + * exception.cc (__throw_bad_cast): Return `void *'. + (__throw_bad_typeid): Return `const type_info &'. + 2000-01-24 Nathan Sidwell * cp-tree.h (get_vtable_decl): Prototype new function. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8b2a3df2475..564cbe36bc2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -557,6 +557,9 @@ enum cp_tree_index CPTI_TERMINATE, CPTI_ATEXIT, CPTI_DSO_HANDLE, + CPTI_BAD_CAST, + CPTI_BAD_TYPEID, + CPTI_DCAST, CPTI_MAX }; @@ -659,6 +662,15 @@ extern tree cp_global_trees[CPTI_MAX]; /* A pointer to `__dso_handle'. */ #define dso_handle_node cp_global_trees[CPTI_DSO_HANDLE] +/* The declaration of __throw_bad_cast. */ +#define throw_bad_cast_node cp_global_trees[CPTI_BAD_CAST] + +/* The declaration of __throw_bad_typeid. */ +#define throw_bad_typeid_node cp_global_trees[CPTI_BAD_TYPEID] + +/* The declaration of the dynamic_cast runtime. */ +#define dynamic_cast_node cp_global_trees[CPTI_DCAST] + /* The type of a destructor. */ #define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE] diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc index efc0b1fe83c..d00e0f28a38 100644 --- a/gcc/cp/exception.cc +++ b/gcc/cp/exception.cc @@ -317,16 +317,21 @@ __check_eh_spec (int n, const void **spec) } } -extern "C" void -__throw_bad_cast (void) +// 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" void -__throw_bad_typeid (void) +extern "C" type_info const & +__throw_bad_typeid () { throw std::bad_typeid (); + return typeid (void); } /* Has the current exception been caught? */ diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 71a54c544c3..2341a229d26 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */ extern struct obstack permanent_obstack; -static tree call_void_fn PROTO((const char *)); +static tree build_runtime_decl PROTO((const char *, tree)); static tree build_headof_sub PROTO((tree)); static tree build_headof PROTO((tree)); static tree get_tinfo_var PROTO((tree)); @@ -133,20 +133,22 @@ build_headof (exp) cp_convert (ptrdiff_type_node, offset)); } -/* Build a call to a generic entry point taking and returning void. */ +/* Build a decl to a runtime entry point taking void and returning TYPE. + Although the entry point may never return, making its return type + consistent is necessary. */ static tree -call_void_fn (name) +build_runtime_decl (name, type) const char *name; + tree type; { tree d = get_identifier (name); - tree type; if (IDENTIFIER_GLOBAL_VALUE (d)) d = IDENTIFIER_GLOBAL_VALUE (d); else { - type = build_function_type (void_type_node, void_list_node); + type = build_function_type (type, void_list_node); d = build_lang_decl (FUNCTION_DECL, d, type); DECL_EXTERNAL (d) = 1; TREE_PUBLIC (d) = 1; @@ -156,7 +158,7 @@ call_void_fn (name) } mark_used (d); - return build_call (d, void_type_node, NULL_TREE); + return d; } /* Get a bad_cast node for the program to throw... @@ -166,13 +168,28 @@ call_void_fn (name) static tree throw_bad_cast () { - return call_void_fn ("__throw_bad_cast"); + if (!throw_bad_cast_node) + throw_bad_cast_node = build_runtime_decl + ("__throw_bad_cast", ptr_type_node); + + return build_call (throw_bad_cast_node, + TREE_TYPE (TREE_TYPE (throw_bad_cast_node)), + NULL_TREE); } static tree throw_bad_typeid () { - return call_void_fn ("__throw_bad_typeid"); + if (!throw_bad_typeid_node) + throw_bad_typeid_node = build_runtime_decl + ("__throw_bad_typeid", + build_reference_type + (build_qualified_type + (type_info_type_node, TYPE_QUAL_CONST))); + + return build_call (throw_bad_typeid_node, + TREE_TYPE (TREE_TYPE (throw_bad_typeid_node)), + NULL_TREE); } /* Return a pointer to type_info function associated with the expression EXP. @@ -624,9 +641,12 @@ build_dynamic_cast_1 (type, expr) if (TREE_CODE (old_expr) == VAR_DECL && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) { + tree expr = throw_bad_cast (); cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", old_expr, type); - return throw_bad_cast (); + /* Bash it to the expected type. */ + TREE_TYPE (expr) = type; + return expr; } } /* Ditto for dynamic_cast(&b). */ @@ -658,12 +678,11 @@ build_dynamic_cast_1 (type, expr) td1 = get_tinfo_decl_dynamic (build_indirect_ref (expr, NULL_PTR)); else td1 = get_tinfo_decl_dynamic (expr); - td1 = decay_conversion (td1); target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)); - td2 = decay_conversion (get_tinfo_decl (target_type)); - td3 = decay_conversion (get_tinfo_decl (static_type)); + td2 = build_unary_op (ADDR_EXPR, get_tinfo_decl (target_type), 0); + td3 = build_unary_op (ADDR_EXPR, get_tinfo_decl (static_type), 0); /* Determine how T and V are related. */ boff = get_dynamic_cast_base_type (static_type, target_type); @@ -676,29 +695,32 @@ build_dynamic_cast_1 (type, expr) (NULL_TREE, td3, tree_cons (NULL_TREE, expr1, NULL_TREE)))))); - dcast_fn = get_identifier ("__dynamic_cast_2"); - if (IDENTIFIER_GLOBAL_VALUE (dcast_fn)) - dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn); - else + dcast_fn = dynamic_cast_node; + if (!dcast_fn) { tree tmp; - + tree tinfo_ptr = build_pointer_type (tinfo_decl_type); + tmp = tree_cons - (NULL_TREE, TREE_TYPE (td1), tree_cons - (NULL_TREE, TREE_TYPE (td1), tree_cons - (NULL_TREE, integer_type_node, tree_cons - (NULL_TREE, ptr_type_node, tree_cons - (NULL_TREE, TREE_TYPE (td1), tree_cons - (NULL_TREE, ptr_type_node, void_list_node)))))); + (NULL_TREE, tinfo_ptr, tree_cons + (NULL_TREE, tinfo_ptr, tree_cons + (NULL_TREE, integer_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, tinfo_ptr, tree_cons + (NULL_TREE, ptr_type_node, void_list_node)))))); + tmp = build_function_type (ptr_type_node, tmp); - dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp); + dcast_fn = build_lang_decl (FUNCTION_DECL, + get_identifier ("__dynamic_cast_2"), + tmp); DECL_EXTERNAL (dcast_fn) = 1; TREE_PUBLIC (dcast_fn) = 1; DECL_ARTIFICIAL (dcast_fn) = 1; pushdecl_top_level (dcast_fn); make_function_rtl (dcast_fn); + + dynamic_cast_node = dcast_fn; } - mark_used (dcast_fn); result = build_call (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);