]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtti.c (build_dynamic_cast_1): Improve diagnostics.
authorSteven Grady <grady@digitaldeck.com>
Fri, 17 Mar 2000 00:56:12 +0000 (00:56 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 17 Mar 2000 00:56:12 +0000 (19:56 -0500)
        * rtti.c (build_dynamic_cast_1): Improve diagnostics.

Co-Authored-By: Jason Merrill <jason@casey.cygnus.com>
From-SVN: r32599

gcc/cp/ChangeLog
gcc/cp/rtti.c

index 02d7de871b51110825079b4aa52dbc3191c6c05f..425bc6308656750c5c1485fd12e7e26e2ba88928 100644 (file)
@@ -1,3 +1,8 @@
+2000-03-16  Steven Grady <grady@digitaldeck.com>
+           Jason Merrill  <jason@casey.cygnus.com>
+
+       * rtti.c (build_dynamic_cast_1): Improve diagnostics.
+
 2000-03-16  Nathan Sidwell  <nathan@codesourcery.com>
 
        * decl2.c (grokfield): Bail out if type is error_mark_node.
index e8034c3840ead475290598e58240dba7f466428b..0c1986dbfd18d3cd9bd77e5b7bf0fae5f9d3c814 100644 (file)
@@ -548,69 +548,98 @@ build_dynamic_cast_1 (type, expr)
 {
   enum tree_code tc = TREE_CODE (type);
   tree exprtype;
-  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);
-  
-  exprtype = TREE_TYPE (expr);
-  assert (exprtype != NULL_TREE);
-  ec = TREE_CODE (exprtype);
-
+  /* T shall be a pointer or reference to a complete class type, or
+     `pointer to cv void''.  */
   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)
+      if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
        break;
-      /* else fall through */
     case REFERENCE_TYPE:
-      if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
-       goto fail;
+      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)
-       goto fail;
+       {
+         errstr = "target is not pointer or reference to complete type";
+         goto fail;
+       }
       break;
-      /* else fall through */
+
     default:
+      errstr = "target is not pointer or reference";
       goto fail;
     }
 
-  /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
-  if (ec == RECORD_TYPE)
+  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);
-      ec = REFERENCE_TYPE;
     }
 
-  if (tc == REFERENCE_TYPE)
+  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
     {
-      if (ec != REFERENCE_TYPE)
-       goto fail;
-      if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
-       goto fail;
+      /* 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)
-       goto fail;
-      if (!at_least_as_qualified_p (TREE_TYPE (type),
-                                   TREE_TYPE (exprtype)))
-       goto fail;
+       {
+         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,
@@ -669,7 +698,7 @@ build_dynamic_cast_1 (type, expr)
 
          /* If we got here, we can't convert statically.  Therefore,
             dynamic_cast<D&>(b) (b an object) cannot succeed.  */
-         if (ec == REFERENCE_TYPE)
+         if (tc == REFERENCE_TYPE)
            {
              if (TREE_CODE (old_expr) == VAR_DECL
                  && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
@@ -717,7 +746,7 @@ build_dynamic_cast_1 (type, expr)
              tree expr2 = build_headof (expr1);
              tree td1 = expr;
 
-             if (ec == POINTER_TYPE)
+             if (tc == POINTER_TYPE)
                td1 = build_indirect_ref (td1, NULL_PTR);
              td1 = get_tinfo_decl_dynamic (td1);
          
@@ -802,13 +831,12 @@ build_dynamic_cast_1 (type, expr)
           return ifnonnull (expr, result);
        }
     }
-
-  cp_error ("dynamic_cast from non-polymorphic type `%#T'", exprtype);
-  return error_mark_node;
+  else
+    errstr = "source type is not polymorphic";
 
  fail:
-  cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
-           expr, exprtype, type);
+  cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T' (%s)",
+           expr, exprtype, type, errstr);
   return error_mark_node;
 }
 
@@ -1275,7 +1303,7 @@ tinfo_base_init (desc, target)
   
   init = tree_cons (NULL_TREE, decay_conversion (name_string), init);
   
-  init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse(init));
+  init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
   TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
   init = tree_cons (NULL_TREE, init, NULL_TREE);