mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-14 23:00:32 +08:00
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
This commit is contained in:
parent
f1c9d505f9
commit
059fa5e776
@ -1,3 +1,18 @@
|
||||
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.
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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? */
|
||||
|
@ -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<D*>(&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);
|
||||
|
Loading…
Reference in New Issue
Block a user