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