C++ PATCH: rtti generalization
Nathan Sidwell
sidwell@codesourcery.com
Tue Jan 18 02:33:00 GMT 2000
Hi,
I've installed the attached patch, which generalizes & cleans up the
rtti interface. This is necessary for the new-abi work, which will
deal with type_info objects directly, rather than indirectly using
functions.
The patch also cleans out some cruft in rtti.c, which can now be
handled by other functions (checking incomplete types & cond_exprs
which throw on one side).
As ever, Mark's approved it. [Mark, I removed the behavioural
change to do with dynamic cast and -fno-rtti.]
nathan
--
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
Never hand someone a gun unless you are sure where they will point it
nathan@acm.org http://www.cs.bris.ac.uk/~nathan/ nathan@cs.bris.ac.uk
2000-01-18 Nathan Sidwell <sidwell@codesourcery.com>
* cp-tree.h (get_tinfo_fn_dynamic): Remove prototype.
(build_x_typeid): Likewise.
(get_tinfo_fn): Likewise.
(get_tinfo_fn_unused): Rename to ...
(get_tinfo_decl): ... here.
* rtti.c (build_headof): Replace logic error with assertion.
(get_tinfo_fn_dynamic): Rename to ...
(get_tinfo_decl_dynamic): ... here. Make static. Use
complete_type_or_else.
(build_x_typeid): Move into ...
(build_typeid): ... here. Adjust call to
get_tinfo_decl_dynamic. Use tinfo_from_decl. Simplify
throw_bad_typeid expression.
(get_tinfo_fn_unused): Rename to ...
(get_tinfo_decl): ... here. Adjust comment.
(get_tinfo_fn): Delete.
(tinfo_from_decl): New static function.
(get_typeid_1): Call get_tinfo_decl and tinfo_from_decl.
(get_typeid): Use complete_type_or_else.
(build_dynamic_cast_1): Adjust calls to
get_tinfo_decl_dynamic. Simplify throw_bad_cast expression.
* parse.y (primary): Adjust call to build_typeid.
* except.c (build_eh_type_type_ref): Adjust call to
get_tinfo_decl. Mark as used.
* class.c (set_rtti_entry): Adjust call to get_tinfo_decl.
* decl2.c (build_expr_from_tree): Adjust call to build_typeid.
* parse.c: Regenerated.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.387
diff -c -3 -p -r1.387 cp-tree.h
*** cp-tree.h 2000/01/17 22:54:23 1.387
--- cp-tree.h 2000/01/18 10:20:19
*************** extern void finish_repo PROTO((void))
*** 3961,3971 ****
/* in rtti.c */
extern void init_rtti_processing PROTO((void));
- extern tree get_tinfo_fn_dynamic PROTO((tree));
extern tree build_typeid PROTO((tree));
! extern tree build_x_typeid PROTO((tree));
! extern tree get_tinfo_fn PROTO((tree));
! extern tree get_tinfo_fn_unused PROTO((tree));
extern tree get_typeid PROTO((tree));
extern tree get_typeid_1 PROTO((tree));
extern tree build_dynamic_cast PROTO((tree, tree));
--- 3961,3968 ----
/* in rtti.c */
extern void init_rtti_processing PROTO((void));
extern tree build_typeid PROTO((tree));
! extern tree get_tinfo_decl PROTO((tree));
extern tree get_typeid PROTO((tree));
extern tree get_typeid_1 PROTO((tree));
extern tree build_dynamic_cast PROTO((tree, tree));
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/rtti.c,v
retrieving revision 1.54
diff -c -3 -p -r1.54 rtti.c
*** rtti.c 2000/01/18 04:52:50 1.54
--- rtti.c 2000/01/18 10:20:19
*************** static void expand_ptr_desc PROTO((tree,
*** 48,53 ****
--- 48,55 ----
static void expand_generic_desc PROTO((tree, tree, const char *));
static tree throw_bad_cast PROTO((void));
static tree throw_bad_typeid PROTO((void));
+ static tree get_tinfo_decl_dynamic PROTO((tree));
+ static tree tinfo_from_decl PROTO((tree));
void
init_rtti_processing ()
*************** build_headof (exp)
*** 95,105 ****
tree aref;
tree offset;
! if (TREE_CODE (type) != POINTER_TYPE)
! {
! error ("`headof' applied to non-pointer type");
! return error_mark_node;
! }
type = TREE_TYPE (type);
if (!TYPE_POLYMORPHIC_P (type))
--- 97,103 ----
tree aref;
tree offset;
! my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112);
type = TREE_TYPE (type);
if (!TYPE_POLYMORPHIC_P (type))
*************** throw_bad_typeid ()
*** 172,196 ****
return call_void_fn ("__throw_bad_typeid");
}
! /* Return the type_info function associated with the expression EXP. If
! EXP is a reference to a polymorphic class, return the dynamic type;
otherwise return the static type of the expression. */
! tree
! get_tinfo_fn_dynamic (exp)
tree exp;
{
tree type;
!
if (exp == error_mark_node)
return error_mark_node;
- if (type_unknown_p (exp))
- {
- error ("typeid of overloaded function");
- return error_mark_node;
- }
-
type = TREE_TYPE (exp);
/* peel back references, so they match. */
--- 170,188 ----
return call_void_fn ("__throw_bad_typeid");
}
! /* Return a pointer to type_info function associated with the expression EXP.
! If EXP is a reference to a polymorphic class, return the dynamic type;
otherwise return the static type of the expression. */
! static tree
! get_tinfo_decl_dynamic (exp)
tree exp;
{
tree type;
!
if (exp == error_mark_node)
return error_mark_node;
type = TREE_TYPE (exp);
/* peel back references, so they match. */
*************** get_tinfo_fn_dynamic (exp)
*** 199,210 ****
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
!
! if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
! {
! cp_error ("taking typeid of incomplete type `%T'", type);
! return error_mark_node;
! }
/* If exp is a reference to polymorphic type, get the real type_info. */
if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0))
--- 191,202 ----
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
!
! if (type != void_type_node)
! type = complete_type_or_else (type, exp);
!
! if (!type)
! return error_mark_node;
/* If exp is a reference to polymorphic type, get the real type_info. */
if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0))
*************** get_tinfo_fn_dynamic (exp)
*** 223,229 ****
/* If we don't have rtti stuff, get to a sub-object that does. */
if (! CLASSTYPE_VFIELDS (type))
{
! exp = build_unary_op (ADDR_EXPR, exp, 0);
exp = build_headof_sub (exp);
exp = build_indirect_ref (exp, NULL_PTR);
}
--- 215,221 ----
/* If we don't have rtti stuff, get to a sub-object that does. */
if (! CLASSTYPE_VFIELDS (type))
{
! exp = build_unary_op (ADDR_EXPR, exp, 0);
exp = build_headof_sub (exp);
exp = build_indirect_ref (exp, NULL_PTR);
}
*************** get_tinfo_fn_dynamic (exp)
*** 237,258 ****
}
/* otherwise return the type_info for the static type of the expr. */
! return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
}
tree
build_typeid (exp)
tree exp;
{
- exp = get_tinfo_fn_dynamic (exp);
- exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
- return convert_from_reference (exp);
- }
-
- tree
- build_x_typeid (exp)
- tree exp;
- {
tree cond = NULL_TREE;
tree type;
int nonnull = 0;
--- 229,242 ----
}
/* otherwise return the type_info for the static type of the expr. */
! exp = get_tinfo_decl (TYPE_MAIN_VARIANT (type));
! return build_unary_op (ADDR_EXPR, exp, 0);
}
tree
build_typeid (exp)
tree exp;
{
tree cond = NULL_TREE;
tree type;
int nonnull = 0;
*************** build_x_typeid (exp)
*** 282,303 ****
cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
}
! exp = get_tinfo_fn_dynamic (exp);
if (exp == error_mark_node)
return error_mark_node;
! type = TREE_TYPE (tinfo_fn_type);
! exp = build_call (exp, type, NULL_TREE);
if (cond)
{
tree bad = throw_bad_typeid ();
! bad = build_compound_expr
! (tree_cons (NULL_TREE, bad, build_tree_list
! (NULL_TREE, cp_convert (type, integer_zero_node))));
! exp = build (COND_EXPR, type, cond, exp, bad);
}
return convert_from_reference (exp);
--- 266,283 ----
cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
}
! exp = get_tinfo_decl_dynamic (exp);
if (exp == error_mark_node)
return error_mark_node;
! exp = tinfo_from_decl (exp);
if (cond)
{
tree bad = throw_bad_typeid ();
! exp = build (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
}
return convert_from_reference (exp);
*************** get_tinfo_var (type)
*** 345,363 ****
return declare_global_var (tname, arrtype);
}
! /* Returns the decl for a function which will return a type_info node for
! TYPE. This version does not mark the function used, for use in
! set_rtti_entry; for the vtable case, we'll get marked in
! finish_vtable_vardecl, when we know that we want to be emitted.
!
! We do this to avoid emitting the tinfo node itself, since we don't
! currently support DECL_DEFER_OUTPUT for variables. Also, we don't
! associate constant pools with their functions properly, so we would
! emit string constants and such even though we don't emit the actual
! function. When those bugs are fixed, this function should go away. */
tree
! get_tinfo_fn_unused (type)
tree type;
{
tree name;
--- 325,340 ----
return declare_global_var (tname, arrtype);
}
! /* Returns a decl for a function or variable which can be used to obtain a
! type_info object for TYPE. The old-abi uses functions, the new-abi will
! use the type_info object directly. You can take the address of the
! returned decl, to save the decl. To use the generator call
! tinfo_from_generator. You must arrange that the decl is mark_used, if
! actually use it --- decls in vtables are only used if the vtable is
! output. */
tree
! get_tinfo_decl (type)
tree type;
{
tree name;
*************** get_tinfo_fn_unused (type)
*** 385,403 ****
pushdecl_top_level (d);
make_function_rtl (d);
mark_inline_for_output (d);
!
return d;
}
! /* Likewise, but also mark it used. Called by various EH and RTTI code. */
! tree
! get_tinfo_fn (type)
! tree type;
{
! tree d = get_tinfo_fn_unused (type);
! mark_used (d);
! return d;
}
tree
--- 362,381 ----
pushdecl_top_level (d);
make_function_rtl (d);
mark_inline_for_output (d);
!
return d;
}
! /* Given an expr produced by get_tinfo_decl, return an expr which
! produces a reference to the type_info object. */
! static tree
! tinfo_from_decl (expr)
! tree expr;
{
! tree t = build_call (expr, TREE_TYPE (tinfo_fn_type), NULL_TREE);
!
! return t;
}
tree
*************** get_typeid_1 (type)
*** 406,417 ****
{
tree t;
! t = build_call
! (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
return convert_from_reference (t);
}
! /* Return the type_info object for TYPE, creating it if necessary. */
tree
get_typeid (type)
--- 384,395 ----
{
tree t;
! t = get_tinfo_decl (type);
! t = tinfo_from_decl (t);
return convert_from_reference (t);
}
! /* Return the type_info object for TYPE. */
tree
get_typeid (type)
*************** get_typeid (type)
*** 439,449 ****
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
! if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
! {
! cp_error ("taking typeid of incomplete type `%T'", type);
! return error_mark_node;
! }
return get_typeid_1 (type);
}
--- 417,427 ----
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
! if (type != void_type_node)
! type = complete_type_or_else (type, NULL_TREE);
!
! if (!type)
! return error_mark_node;
return get_typeid_1 (type);
}
*************** build_dynamic_cast_1 (type, expr)
*** 627,641 ****
expr2 = build_headof (expr1);
if (ec == POINTER_TYPE)
! td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
else
! td1 = get_tinfo_fn_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_fn (target_type));
! td3 = decay_conversion (get_tinfo_fn (static_type));
/* Determine how T and V are related. */
boff = get_dynamic_cast_base_type (static_type, target_type);
--- 605,619 ----
expr2 = build_headof (expr1);
if (ec == POINTER_TYPE)
! 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));
/* Determine how T and V are related. */
boff = get_dynamic_cast_base_type (static_type, target_type);
*************** build_dynamic_cast_1 (type, expr)
*** 678,687 ****
if (tc == REFERENCE_TYPE)
{
expr1 = throw_bad_cast ();
- expr1 = build_compound_expr
- (tree_cons (NULL_TREE, expr1,
- build_tree_list (NULL_TREE, cp_convert (type, integer_zero_node))));
- TREE_TYPE (expr1) = type;
result = save_expr (result);
return build (COND_EXPR, type, result, result, expr1);
}
--- 656,661 ----
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.158
diff -c -3 -p -r1.158 parse.y
*** parse.y 2000/01/17 20:18:43 1.158
--- parse.y 2000/01/18 10:20:20
*************** primary:
*** 1457,1463 ****
check_for_new_type ("const_cast", $3);
$$ = build_const_cast (type, $6); }
| TYPEID '(' expr ')'
! { $$ = build_x_typeid ($3); }
| TYPEID '(' type_id ')'
{ tree type = groktypename ($3.t);
check_for_new_type ("typeid", $3);
--- 1457,1463 ----
check_for_new_type ("const_cast", $3);
$$ = build_const_cast (type, $6); }
| TYPEID '(' expr ')'
! { $$ = build_typeid ($3); }
| TYPEID '(' type_id ')'
{ tree type = groktypename ($3.t);
check_for_new_type ("typeid", $3);
Index: cp/except.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/except.c,v
retrieving revision 1.93
diff -c -3 -p -r1.93 except.c
*** except.c 1999/12/17 07:40:08 1.93
--- except.c 2000/01/18 10:20:20
*************** build_eh_type_type (type)
*** 343,349 ****
return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
}
! /* Build the address of a typeinfo function for use in the runtime
matching field of the new exception model */
static tree
--- 343,349 ----
return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
}
! /* Build the address of a typeinfo decl for use in the runtime
matching field of the new exception model */
static tree
*************** build_eh_type_type_ref (type)
*** 362,368 ****
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
! exp = get_tinfo_fn (type);
exp = build1 (ADDR_EXPR, ptr_type_node, exp);
return (exp);
--- 362,369 ----
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
! exp = get_tinfo_decl (type);
! mark_used (exp);
exp = build1 (ADDR_EXPR, ptr_type_node, exp);
return (exp);
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.239
diff -c -3 -p -r1.239 class.c
*** class.c 2000/01/18 04:52:50 1.239
--- class.c 2000/01/18 10:20:22
*************** set_rtti_entry (virtuals, offset, type)
*** 829,835 ****
return;
if (flag_rtti)
! fn = get_tinfo_fn_unused (type);
else
/* If someone tries to get RTTI information for a type compiled
without RTTI, they're out of luck. By calling __pure_virtual
--- 829,835 ----
return;
if (flag_rtti)
! fn = get_tinfo_decl (type);
else
/* If someone tries to get RTTI information for a type compiled
without RTTI, they're out of luck. By calling __pure_virtual
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.298
diff -c -3 -p -r1.298 decl2.c
*** decl2.c 2000/01/17 20:18:40 1.298
--- decl2.c 2000/01/18 10:20:23
*************** build_expr_from_tree (t)
*** 3999,4005 ****
case TYPEID_EXPR:
if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
return get_typeid (TREE_OPERAND (t, 0));
! return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
case VAR_DECL:
return convert_from_reference (t);
--- 3999,4005 ----
case TYPEID_EXPR:
if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
return get_typeid (TREE_OPERAND (t, 0));
! return build_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
case VAR_DECL:
return convert_from_reference (t);
Index: cp/parse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.c,v
retrieving revision 1.147
diff -c -3 -p -r1.147 parse.c
*** parse.c 2000/01/17 20:18:41 1.147
--- parse.c 2000/01/18 10:20:27
*************** case 327:
*** 5748,5754 ****
break;}
case 328:
#line 1460 "parse.y"
! { yyval.ttype = build_x_typeid (yyvsp[-1].ttype); ;
break;}
case 329:
#line 1462 "parse.y"
--- 5748,5754 ----
break;}
case 328:
#line 1460 "parse.y"
! { yyval.ttype = build_typeid (yyvsp[-1].ttype); ;
break;}
case 329:
#line 1462 "parse.y"
More information about the Gcc-patches
mailing list