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