OSDN Git Service

gcc
[pf3gnuchains/gcc-fork.git] / gcc / cp / rtti.c
index 6774151..7a8baac 100644 (file)
@@ -273,7 +273,7 @@ build_typeid (exp)
       return error_mark_node;
     }
   
-  if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
+  if (!COMPLETE_TYPE_P (type_info_type_node))
     {
       error ("must #include <typeinfo> before using typeid");
       return error_mark_node;
@@ -462,7 +462,7 @@ get_typeid (type)
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
+  if (!COMPLETE_TYPE_P (type_info_type_node))
     {
       error ("must #include <typeinfo> before using typeid");
       return error_mark_node;
@@ -524,8 +524,7 @@ get_base_offset (binfo, parent)
     
       FORMAT_VBASE_NAME (name, t);
       field = lookup_field (parent, get_identifier (name), 0, 0);
-      offset = size_binop (FLOOR_DIV_EXPR, 
-                          DECL_FIELD_BITPOS (field), 
+      offset = size_binop (FLOOR_DIV_EXPR, bit_position (field), 
                           bitsize_int (BITS_PER_UNIT));
       offset = convert (sizetype, offset);
     }
@@ -548,69 +547,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 (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
-       goto fail;
+      if (! IS_AGGR_TYPE (TREE_TYPE (type)))
+       {
+         errstr = "target is not pointer or reference to class";
+         goto fail;
+       }
+      if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
+       {
+         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 (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (exprtype))))
+       {
+         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 (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (exprtype))))
+       {
+         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)))
     {
-      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;
+      errstr = "conversion casts away constness";
+      goto fail;
     }
 
   /* If *type is an unambiguous accessible base class of *exprtype,
@@ -669,7 +697,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 +745,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);
          
@@ -741,10 +769,10 @@ build_dynamic_cast_1 (type, expr)
            {
              tree tmp;
              tree tinfo_ptr;
-             tree ns = global_namespace;
+             tree ns = new_abi_rtti_p () ? abi_node : global_namespace;
              const char *name;
              
-              push_nested_namespace (ns);
+             push_nested_namespace (ns);
              if (!new_abi_rtti_p ())
                {
                  tinfo_ptr = build_pointer_type (tinfo_decl_type);
@@ -759,11 +787,6 @@ build_dynamic_cast_1 (type, expr)
                }
              else
                {
-                 if (flag_honor_std)
-                   {
-                      push_namespace (get_identifier ("std"));
-                      ns = current_namespace;
-                   }
                   tinfo_ptr = xref_tag (class_type_node,
                                         get_identifier ("__class_type_info"),
                                         1);
@@ -802,13 +825,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 +1297,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);
   
@@ -1444,7 +1466,7 @@ synthesize_tinfo_var (target_type, real_name)
       break;
     case UNION_TYPE:
     case RECORD_TYPE:
-      if (!TYPE_SIZE (target_type))
+      if (!COMPLETE_TYPE_P (target_type))
         {
           /* FIXME: incomplete type. Awaiting specification.  */
           return NULL_TREE;
@@ -1648,8 +1670,7 @@ get_vmi_pseudo_type_info (num_bases)
   array_domain = build_index_type (build_int_2 (num_bases, 0));
   base_array = build_array_type (base_desc_type_node, array_domain);
 
-  if (flag_honor_std)
-    push_namespace (get_identifier ("std"));
+  push_nested_namespace (abi_node);
 
   desc = create_pseudo_type_info
             ("__vmi_class_type_info", num_bases,
@@ -1658,8 +1679,7 @@ get_vmi_pseudo_type_info (num_bases)
              build_lang_decl (FIELD_DECL, NULL_TREE, base_array),
              NULL);
 
-  if (flag_honor_std)
-    pop_namespace ();
+  pop_nested_namespace (abi_node);
 
   TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = desc;
   return desc;
@@ -1675,8 +1695,7 @@ create_tinfo_types ()
   
   if (bltn_desc_type_node)
     return;
-  if (flag_honor_std)
-    push_namespace (get_identifier ("std"));
+  push_nested_namespace (abi_node);
 
   ptr_type_info = build_pointer_type
                     (build_qualified_type
@@ -1752,14 +1771,13 @@ create_tinfo_types ()
   /* Pointer to member data type_info.  Add pointer to the class, pointer
      to the member's type info and qualifications flags.  */
   ptmd_desc_type_node = create_pseudo_type_info
-       ("__ptr_to_member_type_info", 0,
+       ("__pointer_to_member_type_info", 0,
         build_lang_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
         build_lang_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
         build_lang_decl (FIELD_DECL, NULL_TREE, integer_type_node),
         NULL);
 
-  if (flag_honor_std)
-    pop_namespace ();
+  pop_nested_namespace (abi_node);
 }
 
 /* Emit the type_info descriptors which are guaranteed to be in the runtime
@@ -1798,13 +1816,11 @@ emit_support_tinfos ()
   int ix;
   tree bltn_type, dtor;
   
-  if (flag_honor_std)
-    push_namespace (get_identifier ("std"));
+  push_nested_namespace (abi_node);
   bltn_type = xref_tag (class_type_node,
                         get_identifier ("__fundamental_type_info"), 1);
-  if (flag_honor_std)
-    pop_namespace ();
-  if (!TYPE_SIZE (bltn_type))
+  pop_nested_namespace (abi_node);
+  if (!COMPLETE_TYPE_P (bltn_type))
     return;
   dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (bltn_type), 1);
   if (DECL_EXTERNAL (dtor))