Commit 059fa5e7 by Nathan Sidwell Committed by Nathan Sidwell

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
parent f1c9d505
2000-01-24 Nathan Sidwell <sidwell@codesourcery.com> 2000-01-24 Nathan Sidwell <sidwell@codesourcery.com>
* 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 <sidwell@codesourcery.com>
* cp-tree.h (get_vtable_decl): Prototype new function. * cp-tree.h (get_vtable_decl): Prototype new function.
* class.c (get_vtable_decl): New function. Broken out from ... * class.c (get_vtable_decl): New function. Broken out from ...
(build_vtable): ... here. Use it. (build_vtable): ... here. Use it.
......
...@@ -557,6 +557,9 @@ enum cp_tree_index ...@@ -557,6 +557,9 @@ enum cp_tree_index
CPTI_TERMINATE, CPTI_TERMINATE,
CPTI_ATEXIT, CPTI_ATEXIT,
CPTI_DSO_HANDLE, CPTI_DSO_HANDLE,
CPTI_BAD_CAST,
CPTI_BAD_TYPEID,
CPTI_DCAST,
CPTI_MAX CPTI_MAX
}; };
...@@ -659,6 +662,15 @@ extern tree cp_global_trees[CPTI_MAX]; ...@@ -659,6 +662,15 @@ extern tree cp_global_trees[CPTI_MAX];
/* A pointer to `__dso_handle'. */ /* A pointer to `__dso_handle'. */
#define dso_handle_node cp_global_trees[CPTI_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. */ /* The type of a destructor. */
#define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE] #define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE]
......
...@@ -317,16 +317,21 @@ __check_eh_spec (int n, const void **spec) ...@@ -317,16 +317,21 @@ __check_eh_spec (int n, const void **spec)
} }
} }
extern "C" void // Helpers for rtti. Although these don't return, we give them return types so
__throw_bad_cast (void) // that the type system is not broken.
extern "C" void *
__throw_bad_cast ()
{ {
throw std::bad_cast (); throw std::bad_cast ();
return 0;
} }
extern "C" void extern "C" type_info const &
__throw_bad_typeid (void) __throw_bad_typeid ()
{ {
throw std::bad_typeid (); throw std::bad_typeid ();
return typeid (void);
} }
/* Has the current exception been caught? */ /* Has the current exception been caught? */
......
...@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
extern struct obstack permanent_obstack; 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_sub PROTO((tree));
static tree build_headof PROTO((tree)); static tree build_headof PROTO((tree));
static tree get_tinfo_var PROTO((tree)); static tree get_tinfo_var PROTO((tree));
...@@ -133,20 +133,22 @@ build_headof (exp) ...@@ -133,20 +133,22 @@ build_headof (exp)
cp_convert (ptrdiff_type_node, offset)); 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 static tree
call_void_fn (name) build_runtime_decl (name, type)
const char *name; const char *name;
tree type;
{ {
tree d = get_identifier (name); tree d = get_identifier (name);
tree type;
if (IDENTIFIER_GLOBAL_VALUE (d)) if (IDENTIFIER_GLOBAL_VALUE (d))
d = IDENTIFIER_GLOBAL_VALUE (d); d = IDENTIFIER_GLOBAL_VALUE (d);
else 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); d = build_lang_decl (FUNCTION_DECL, d, type);
DECL_EXTERNAL (d) = 1; DECL_EXTERNAL (d) = 1;
TREE_PUBLIC (d) = 1; TREE_PUBLIC (d) = 1;
...@@ -156,7 +158,7 @@ call_void_fn (name) ...@@ -156,7 +158,7 @@ call_void_fn (name)
} }
mark_used (d); mark_used (d);
return build_call (d, void_type_node, NULL_TREE); return d;
} }
/* Get a bad_cast node for the program to throw... /* Get a bad_cast node for the program to throw...
...@@ -166,13 +168,28 @@ call_void_fn (name) ...@@ -166,13 +168,28 @@ call_void_fn (name)
static tree static tree
throw_bad_cast () 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 static tree
throw_bad_typeid () 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. /* Return a pointer to type_info function associated with the expression EXP.
...@@ -624,9 +641,12 @@ build_dynamic_cast_1 (type, expr) ...@@ -624,9 +641,12 @@ build_dynamic_cast_1 (type, expr)
if (TREE_CODE (old_expr) == VAR_DECL if (TREE_CODE (old_expr) == VAR_DECL
&& TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
{ {
tree expr = throw_bad_cast ();
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
old_expr, type); old_expr, type);
return throw_bad_cast (); /* Bash it to the expected type. */
TREE_TYPE (expr) = type;
return expr;
} }
} }
/* Ditto for dynamic_cast<D*>(&b). */ /* Ditto for dynamic_cast<D*>(&b). */
...@@ -658,12 +678,11 @@ build_dynamic_cast_1 (type, expr) ...@@ -658,12 +678,11 @@ build_dynamic_cast_1 (type, expr)
td1 = get_tinfo_decl_dynamic (build_indirect_ref (expr, NULL_PTR)); td1 = get_tinfo_decl_dynamic (build_indirect_ref (expr, NULL_PTR));
else else
td1 = get_tinfo_decl_dynamic (expr); td1 = get_tinfo_decl_dynamic (expr);
td1 = decay_conversion (td1);
target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)); static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
td2 = decay_conversion (get_tinfo_decl (target_type)); td2 = build_unary_op (ADDR_EXPR, get_tinfo_decl (target_type), 0);
td3 = decay_conversion (get_tinfo_decl (static_type)); td3 = build_unary_op (ADDR_EXPR, get_tinfo_decl (static_type), 0);
/* Determine how T and V are related. */ /* Determine how T and V are related. */
boff = get_dynamic_cast_base_type (static_type, target_type); boff = get_dynamic_cast_base_type (static_type, target_type);
...@@ -676,29 +695,32 @@ build_dynamic_cast_1 (type, expr) ...@@ -676,29 +695,32 @@ build_dynamic_cast_1 (type, expr)
(NULL_TREE, td3, tree_cons (NULL_TREE, td3, tree_cons
(NULL_TREE, expr1, NULL_TREE)))))); (NULL_TREE, expr1, NULL_TREE))))));
dcast_fn = get_identifier ("__dynamic_cast_2"); dcast_fn = dynamic_cast_node;
if (IDENTIFIER_GLOBAL_VALUE (dcast_fn)) if (!dcast_fn)
dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
else
{ {
tree tmp; tree tmp;
tree tinfo_ptr = build_pointer_type (tinfo_decl_type);
tmp = tree_cons tmp = tree_cons
(NULL_TREE, TREE_TYPE (td1), tree_cons (NULL_TREE, tinfo_ptr, tree_cons
(NULL_TREE, TREE_TYPE (td1), tree_cons (NULL_TREE, tinfo_ptr, tree_cons
(NULL_TREE, integer_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons
(NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, tree_cons
(NULL_TREE, TREE_TYPE (td1), tree_cons (NULL_TREE, tinfo_ptr, tree_cons
(NULL_TREE, ptr_type_node, void_list_node)))))); (NULL_TREE, ptr_type_node, void_list_node))))));
tmp = build_function_type (ptr_type_node, tmp); 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; DECL_EXTERNAL (dcast_fn) = 1;
TREE_PUBLIC (dcast_fn) = 1; TREE_PUBLIC (dcast_fn) = 1;
DECL_ARTIFICIAL (dcast_fn) = 1; DECL_ARTIFICIAL (dcast_fn) = 1;
pushdecl_top_level (dcast_fn); pushdecl_top_level (dcast_fn);
make_function_rtl (dcast_fn); make_function_rtl (dcast_fn);
dynamic_cast_node = dcast_fn;
} }
mark_used (dcast_fn); mark_used (dcast_fn);
result = build_call result = build_call
(dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems); (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment