patch to improve error messages for dynamic_cast

Jason Merrill jason@cygnus.com
Thu Mar 16 16:55:00 GMT 2000


I applied this:

2000-03-16  Steven Grady <grady@digitaldeck.com>
	    Jason Merrill  <jason@casey.cygnus.com>

	* rtti.c (build_dynamic_cast_1): Improve diagnostics.

Index: rtti.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/rtti.c,v
retrieving revision 1.69
diff -c -p -r1.69 rtti.c
*** rtti.c	2000/03/15 17:17:45	1.69
--- rtti.c	2000/03/17 00:53:49
*************** build_dynamic_cast_1 (type, expr)
*** 548,618 ****
  {
    enum tree_code tc = TREE_CODE (type);
    tree exprtype;
-   enum tree_code ec;
    tree dcast_fn;
    tree old_expr = expr;
  
!   if (TREE_CODE (expr) == OFFSET_REF)
!     expr = resolve_offset_ref (expr);
!   
!   exprtype = TREE_TYPE (expr);
!   assert (exprtype != NULL_TREE);
!   ec = TREE_CODE (exprtype);
! 
    switch (tc)
      {
      case POINTER_TYPE:
!       if (ec == REFERENCE_TYPE)
! 	{
! 	  expr = convert_from_reference (expr);
! 	  exprtype = TREE_TYPE (expr);
! 	  ec = TREE_CODE (exprtype);
! 	}
!       if (ec != POINTER_TYPE)
! 	goto fail;
!       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
! 	goto fail;
!       if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
! 	goto fail;
!       if (!at_least_as_qualified_p (TREE_TYPE (type),
! 				    TREE_TYPE (exprtype)))
! 	goto fail;
!       if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
  	break;
-       /* else fall through */
      case REFERENCE_TYPE:
!       if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
! 	goto fail;
        if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
! 	goto fail;
        break;
!       /* else fall through */
      default:
        goto fail;
      }
  
!   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
!   if (ec == RECORD_TYPE)
      {
        exprtype = build_reference_type (exprtype);
        expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
  				   LOOKUP_NORMAL, NULL_TREE);
-       ec = REFERENCE_TYPE;
      }
  
!   if (tc == REFERENCE_TYPE)
      {
!       if (ec != REFERENCE_TYPE)
! 	goto fail;
!       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
! 	goto fail;
        if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
! 	goto fail;
!       if (!at_least_as_qualified_p (TREE_TYPE (type),
! 				    TREE_TYPE (exprtype)))
! 	goto fail;
      }
  
    /* If *type is an unambiguous accessible base class of *exprtype,
       convert statically.  */
    {
--- 548,647 ----
  {
    enum tree_code tc = TREE_CODE (type);
    tree exprtype;
    tree dcast_fn;
    tree old_expr = expr;
+   char* errstr = NULL;
  
!   /* T shall be a pointer or reference to a complete class type, or
!      `pointer to cv void''.  */
    switch (tc)
      {
      case POINTER_TYPE:
!       if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
  	break;
      case REFERENCE_TYPE:
!       if (! IS_AGGR_TYPE (TREE_TYPE (type)))
! 	{
! 	  errstr = "target is not pointer or reference to class";
! 	  goto fail;
! 	}
        if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
! 	{
! 	  errstr = "target is not pointer or reference to complete type";
! 	  goto fail;
! 	}
        break;
! 
      default:
+       errstr = "target is not pointer or reference";
        goto fail;
      }
+ 
+   if (TREE_CODE (expr) == OFFSET_REF)
+     expr = resolve_offset_ref (expr);
+ 
+   exprtype = TREE_TYPE (expr);
+   assert (exprtype != NULL_TREE);
  
!   if (tc == POINTER_TYPE)
!     expr = convert_from_reference (expr);
!   else if (TREE_CODE (exprtype) != REFERENCE_TYPE)
      {
+       /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
        exprtype = build_reference_type (exprtype);
        expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
  				   LOOKUP_NORMAL, NULL_TREE);
      }
+ 
+   exprtype = TREE_TYPE (expr);
  
!   if (tc == POINTER_TYPE)
      {
!       /* If T is a pointer type, v shall be an rvalue of a pointer to
! 	 complete class type, and the result is an rvalue of type T.  */
! 
!       if (TREE_CODE (exprtype) != POINTER_TYPE)
! 	{
! 	  errstr = "source is not a pointer";
! 	  goto fail;
! 	}
!       if (! IS_AGGR_TYPE (TREE_TYPE (exprtype)))
! 	{
! 	  errstr = "source is not a pointer to class";
! 	  goto fail;
! 	}
        if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
! 	{
! 	  errstr = "source is a pointer to incomplete type";
! 	  goto fail;
! 	}
      }
+   else
+     {
+       /* T is a reference type, v shall be an lvalue of a complete class
+ 	 type, and the result is an lvalue of the type referred to by T.  */
  
+       if (! IS_AGGR_TYPE (TREE_TYPE (exprtype)))
+ 	{
+ 	  errstr = "source is not of class type";
+ 	  goto fail;
+ 	}
+       if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
+ 	{
+ 	  errstr = "source is of incomplete class type";
+ 	  goto fail;
+ 	}
+       
+     }
+ 
+   /* The dynamic_cast operator shall not cast away constness.  */
+   if (!at_least_as_qualified_p (TREE_TYPE (type),
+ 				TREE_TYPE (exprtype)))
+     {
+       errstr = "conversion casts away constness";
+       goto fail;
+     }
+ 
    /* If *type is an unambiguous accessible base class of *exprtype,
       convert statically.  */
    {
*************** build_dynamic_cast_1 (type, expr)
*** 669,675 ****
  
   	  /* If we got here, we can't convert statically.  Therefore,
  	     dynamic_cast<D&>(b) (b an object) cannot succeed.  */
! 	  if (ec == REFERENCE_TYPE)
  	    {
  	      if (TREE_CODE (old_expr) == VAR_DECL
  		  && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
--- 698,704 ----
  
   	  /* If we got here, we can't convert statically.  Therefore,
  	     dynamic_cast<D&>(b) (b an object) cannot succeed.  */
! 	  if (tc == REFERENCE_TYPE)
  	    {
  	      if (TREE_CODE (old_expr) == VAR_DECL
  		  && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
*************** build_dynamic_cast_1 (type, expr)
*** 717,723 ****
  	      tree expr2 = build_headof (expr1);
  	      tree td1 = expr;
  
! 	      if (ec == POINTER_TYPE)
  	        td1 = build_indirect_ref (td1, NULL_PTR);
    	      td1 = get_tinfo_decl_dynamic (td1);
  	  
--- 746,752 ----
  	      tree expr2 = build_headof (expr1);
  	      tree td1 = expr;
  
! 	      if (tc == POINTER_TYPE)
  	        td1 = build_indirect_ref (td1, NULL_PTR);
    	      td1 = get_tinfo_decl_dynamic (td1);
  	  
*************** build_dynamic_cast_1 (type, expr)
*** 802,814 ****
            return ifnonnull (expr, result);
  	}
      }
! 
!   cp_error ("dynamic_cast from non-polymorphic type `%#T'", exprtype);
!   return error_mark_node;
  
   fail:
!   cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
! 	    expr, exprtype, type);
    return error_mark_node;
  }
  
--- 831,842 ----
            return ifnonnull (expr, result);
  	}
      }
!   else
!     errstr = "source type is not polymorphic";
  
   fail:
!   cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T' (%s)",
! 	    expr, exprtype, type, errstr);
    return error_mark_node;
  }
  


More information about the Gcc-patches mailing list