patch to improve error messages for dynamic_cast

Steven Grady grady@digitaldeck.com
Tue Mar 7 19:48:00 GMT 2000


This patch is in response to the following exchange of messages:

>> According to the code (cp/rtti.c: build_dynamic_cast_1), almost all
>> errors result in
>> the same message:
>>     cannot dynamic_cast `%E' (of type `%#T') to type `%#T
>
>> This message is not particularly explanatory. In particular, it took
>> me a couple of hours to figure out that a dynamic cast was failing
>> because the type of the expr being cast did not have a vtbl. (I
>> figured out the problem only by looking at the above gcc source
>> code.)
>
>Thanks for your bug report; I fail to see the bug, though. It is not
>the compiler's job to teach the user C++.
>
>Of course, if you can suggest specific patches to improve the quality
>of the g++ diagnostics, they would be much appreciated. Please send
>them to gcc-patches@gcc.gnu.org.
>
>Regards,
>Martin
>

Since I don't understand the internals of gcc, some of the messages
could no doubt be more helpful.

	Steven

*** cp/rtti.c.old	Tue Apr 27 02:41:31 1999
--- cp/rtti.c	Tue Mar  7 15:16:22 2000
***************
*** 476,481 ****
--- 476,482 ----
    enum tree_code ec;
    tree dcast_fn;
    tree old_expr = expr;
+   char* errstr = NULL;
  
    if (TREE_CODE (expr) == OFFSET_REF)
      expr = resolve_offset_ref (expr);
***************
*** 493,518 ****
  	  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;
      }
  
--- 494,532 ----
  	  exprtype = TREE_TYPE (expr);
  	  ec = TREE_CODE (exprtype);
  	}
!       if (ec != POINTER_TYPE) {
! 	errstr = "type is pointer, expr is non-pointer";
  	goto fail;
!       }
!       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) {
! 	errstr = "type is pointer, expr is not record";
  	goto fail;
!       }
!       if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE) {
! 	errstr = "type is pointer, expr has null tree";
  	goto fail;
+       }
        if (!at_least_as_qualified_p (TREE_TYPE (type),
! 				    TREE_TYPE (exprtype))) {
! 	errstr = "type is pointer, but not as qualified as 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) {
! 	errstr = "type is reference, expr is not record";
  	goto fail;
!       }
!       if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) {
! 	errstr = "type is reference, expr has null tree";
  	goto fail;
+       }
        break;
        /* else fall through */
      default:
+       errstr = "type is neither pointer nor reference";
        goto fail;
      }
  
***************
*** 527,541 ****
  
    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,
--- 541,563 ----
  
    if (tc == REFERENCE_TYPE)
      {
!       if (ec != REFERENCE_TYPE) {
! 	errstr = "type is reference, expr is not reference";
  	goto fail;
!       }
!       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) {
! 	errstr = "type is reference, expr is not record";
  	goto fail;
!       }
!       if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE) {
! 	errstr = "type is reference, expr has null tree";
  	goto fail;
+       }
        if (!at_least_as_qualified_p (TREE_TYPE (type),
! 				    TREE_TYPE (exprtype))) {
! 	errstr = "type is reference, but not as qualified as exprtype";
  	goto fail;
+       }
      }
  
    /* If *type is an unambiguous accessible base class of *exprtype,
***************
*** 691,701 ****
  	  result = cp_convert (type, result);
            return ifnonnull (expr, result);
  	}
      }
  
   fail:
!   cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
! 	    expr, exprtype, type);
    return error_mark_node;
  }
  
--- 713,725 ----
  	  result = cp_convert (type, result);
            return ifnonnull (expr, result);
  	}
+     } else {
+       errstr = "expr is not polymorphic type";
      }
  
   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