OSDN Git Service

PR c++/44157
[pf3gnuchains/gcc-fork.git] / gcc / cp / rtti.c
index 2d2ef5b..4eb2ba7 100644 (file)
@@ -1,6 +1,6 @@
 /* RunTime Type Identification
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008
+   2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Mostly written by Jason Merrill (jason@cygnus.com).
 
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "config.h"
 #include "system.h"
+#include "intl.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
@@ -64,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
    translation, when we are emitting the type info objects.  */
 
 /* Auxiliary data we hold for each type_info derived object we need.  */
-typedef struct tinfo_s GTY (())
-{
+typedef struct GTY (()) tinfo_s {
   tree type;  /* The RECORD_TYPE for this type_info object */
 
   tree vtable; /* The VAR_DECL of the vtable.  Only filled at end of
@@ -103,7 +103,7 @@ VEC(tree,gc) *unemitted_tinfo_decls;
 static GTY (()) VEC(tinfo_s,gc) *tinfo_descs;
 
 static tree ifnonnull (tree, tree);
-static tree tinfo_name (tree);
+static tree tinfo_name (tree, bool);
 static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t);
 static tree throw_bad_cast (void);
 static tree throw_bad_typeid (void);
@@ -129,13 +129,13 @@ static void
 push_abi_namespace (void)
 {
   push_nested_namespace (abi_node);
-  push_visibility ("default");
+  push_visibility ("default", 2);
 }
 
 static void
 pop_abi_namespace (void)
 {
-  pop_visibility ();
+  pop_visibility (2);
   pop_nested_namespace (abi_node);
 }
 
@@ -188,7 +188,7 @@ build_headof (tree exp)
   index = build_int_cst (NULL_TREE,
                         -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
-  offset = build_vtbl_ref (cp_build_indirect_ref (exp, NULL, 
+  offset = build_vtbl_ref (cp_build_indirect_ref (exp, RO_NULL, 
                                                   tf_warning_or_error), 
                            index);
 
@@ -246,13 +246,17 @@ get_tinfo_decl_dynamic (tree exp)
   if (error_operand_p (exp))
     return error_mark_node;
 
+  exp = resolve_nondeduced_context (exp);
+
   /* peel back references, so they match.  */
   type = non_reference (TREE_TYPE (exp));
 
   /* Peel off cv qualifiers.  */
   type = TYPE_MAIN_VARIANT (type);
 
-  if (CLASS_TYPE_P (type))
+  /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics.  */
+  if (CLASS_TYPE_P (type) || type == unknown_type_node
+      || type == init_list_type_node)
     type = complete_type_or_else (type, exp);
 
   if (!type)
@@ -274,7 +278,7 @@ get_tinfo_decl_dynamic (tree exp)
     /* Otherwise return the type_info for the static type of the expr.  */
     t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
 
-  return cp_build_indirect_ref (t, NULL, tf_warning_or_error);
+  return cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
 }
 
 static bool
@@ -315,7 +319,7 @@ typeid_ok_p (void)
 tree
 build_typeid (tree exp)
 {
-  tree cond = NULL_TREE;
+  tree cond = NULL_TREE, initial_expr = exp;
   int nonnull = 0;
 
   if (exp == error_mark_node || !typeid_ok_p ())
@@ -330,6 +334,9 @@ build_typeid (tree exp)
       && ! resolves_to_fixed_type_p (exp, &nonnull)
       && ! nonnull)
     {
+      /* So we need to look into the vtable of the type of exp.
+         This is an lvalue use of expr then.  */
+      exp = mark_lvalue_use (exp);
       exp = stabilize_reference (exp);
       cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
     }
@@ -345,20 +352,36 @@ build_typeid (tree exp)
 
       exp = build3 (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
     }
+  else
+    mark_type_use (initial_expr);
 
   return exp;
 }
 
-/* Generate the NTBS name of a type.  */
+/* Generate the NTBS name of a type.  If MARK_PRIVATE, put a '*' in front so that
+   comparisons will be done by pointer rather than string comparison.  */
 static tree
-tinfo_name (tree type)
+tinfo_name (tree type, bool mark_private)
 {
   const char *name;
+  int length;
   tree name_string;
 
   name = mangle_type_string (type);
-  name_string = fix_string_type (build_string (strlen (name) + 1, name));
-  return name_string;
+  length = strlen (name);
+
+  if (mark_private)
+    {
+      /* Inject '*' at beginning of name to force pointer comparison.  */
+      char* buf = (char*) XALLOCAVEC (char, length + 2);
+      buf[0] = '*';
+      memcpy (buf + 1, name, length + 1);
+      name_string = build_string (length + 2, buf);
+    }
+  else
+    name_string = build_string (length + 1, name);
+
+  return fix_string_type (name_string);
 }
 
 /* Return a VAR_DECL for the internal ABI defined type_info object for
@@ -459,13 +482,15 @@ get_typeid (tree type)
      that is the operand of typeid are always ignored.  */
   type = TYPE_MAIN_VARIANT (type);
 
-  if (CLASS_TYPE_P (type))
+  /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics.  */
+  if (CLASS_TYPE_P (type) || type == unknown_type_node
+      || type == init_list_type_node)
     type = complete_type_or_else (type, NULL_TREE);
 
   if (!type)
     return error_mark_node;
 
-  return cp_build_indirect_ref (get_tinfo_ptr (type), NULL, 
+  return cp_build_indirect_ref (get_tinfo_ptr (type), RO_NULL, 
                                 tf_warning_or_error);
 }
 
@@ -508,18 +533,18 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
     case REFERENCE_TYPE:
       if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (type)))
        {
-         errstr = "target is not pointer or reference to class";
+         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";
+         errstr = _("target is not pointer or reference to complete type");
          goto fail;
        }
       break;
 
     default:
-      errstr = "target is not pointer or reference";
+      errstr = _("target is not pointer or reference");
       goto fail;
     }
 
@@ -528,24 +553,28 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
       /* 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.  */
 
+      expr = mark_rvalue_use (expr);
+
       if (TREE_CODE (exprtype) != POINTER_TYPE)
        {
-         errstr = "source is not a pointer";
+         errstr = _("source is not a pointer");
          goto fail;
        }
       if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (exprtype)))
        {
-         errstr = "source is not a pointer to class";
+         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";
+         errstr = _("source is a pointer to incomplete type");
          goto fail;
        }
     }
   else
     {
+      expr = mark_lvalue_use (expr);
+
       exprtype = build_reference_type (exprtype);
 
       /* T is a reference type, v shall be an lvalue of a complete class
@@ -553,12 +582,12 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
 
       if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (exprtype)))
        {
-         errstr = "source is not of class type";
+         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";
+         errstr = _("source is of incomplete class type");
          goto fail;
        }
 
@@ -571,7 +600,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
   if (!at_least_as_qualified_p (TREE_TYPE (type),
                                TREE_TYPE (exprtype)))
     {
-      errstr = "conversion casts away constness";
+      errstr = _("conversion casts away constness");
       goto fail;
     }
 
@@ -707,7 +736,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
                   (NULL_TREE, ptrdiff_type_node, void_list_node))));
              tmp = build_function_type (ptr_type_node, tmp);
              dcast_fn = build_library_fn_ptr (name, tmp);
-             DECL_IS_PURE (dcast_fn) = 1;
+             DECL_PURE_P (dcast_fn) = 1;
              pop_abi_namespace ();
              dynamic_cast_node = dcast_fn;
            }
@@ -719,8 +748,10 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
              tree neq;
 
              result = save_expr (result);
-             neq = c_common_truthvalue_conversion (result);
-             return build3 (COND_EXPR, type, neq, result, bad);
+             neq = c_common_truthvalue_conversion (input_location, result);
+             return cp_convert (type,
+                                build3 (COND_EXPR, TREE_TYPE (result),
+                                        neq, result, bad));
            }
 
          /* Now back to the type we want from a void*.  */
@@ -729,7 +760,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
        }
     }
   else
-    errstr = "source type is not polymorphic";
+    errstr = _("source type is not polymorphic");
 
  fail:
   if (complain & tf_error)
@@ -836,13 +867,12 @@ tinfo_base_init (tinfo_s *ti, tree target)
   tree vtable_ptr;
 
   {
-    tree name_name;
+    tree name_name, name_string;
 
     /* Generate the NTBS array variable.  */
     tree name_type = build_cplus_array_type
                     (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
                     NULL_TREE);
-    tree name_string = tinfo_name (target);
 
     /* Determine the name of the variable -- and remember with which
        type it is associated.  */
@@ -859,6 +889,7 @@ tinfo_base_init (tinfo_s *ti, tree target)
     DECL_TINFO_P (name_decl) = 1;
     set_linkage_according_to_type (target, name_decl);
     import_export_decl (name_decl);
+    name_string = tinfo_name (target, !TREE_PUBLIC (name_decl));
     DECL_INITIAL (name_decl) = name_string;
     mark_used (name_decl);
     pushdecl_top_level_and_finish (name_decl, name_string);
@@ -900,7 +931,7 @@ tinfo_base_init (tinfo_s *ti, tree target)
 
   init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
 
-  init = build_constructor_from_list (NULL_TREE, nreverse (init));
+  init = build_constructor_from_list (init_list_type_node, nreverse (init));
   TREE_CONSTANT (init) = 1;
   TREE_STATIC (init) = 1;
   init = tree_cons (NULL_TREE, init, NULL_TREE);
@@ -917,7 +948,7 @@ generic_initializer (tinfo_s *ti, tree target)
 {
   tree init = tinfo_base_init (ti, target);
 
-  init = build_constructor_from_list (NULL_TREE, init);
+  init = build_constructor_from_list (init_list_type_node, init);
   TREE_CONSTANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
@@ -942,7 +973,7 @@ ptr_initializer (tinfo_s *ti, tree target)
                    get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
                    init);
 
-  init = build_constructor_from_list (NULL_TREE, nreverse (init));
+  init = build_constructor_from_list (init_list_type_node, nreverse (init));
   TREE_CONSTANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
@@ -974,7 +1005,7 @@ ptm_initializer (tinfo_s *ti, tree target)
                    get_tinfo_ptr (klass),
                    init);
 
-  init = build_constructor_from_list (NULL_TREE, nreverse (init));
+  init = build_constructor_from_list (init_list_type_node, nreverse (init));
   TREE_CONSTANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
@@ -990,7 +1021,7 @@ class_initializer (tinfo_s *ti, tree target, tree trail)
   tree init = tinfo_base_init (ti, target);
 
   TREE_CHAIN (init) = trail;
-  init = build_constructor_from_list (NULL_TREE, init);
+  init = build_constructor_from_list (init_list_type_node, init);
   TREE_CONSTANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
@@ -1017,6 +1048,11 @@ typeinfo_in_lib_p (tree type)
     case VOID_TYPE:
       return true;
 
+    case LANG_TYPE:
+      if (NULLPTR_TYPE_P (type))
+       return true;
+      /* else fall through.  */
+
     default:
       return false;
     }
@@ -1096,16 +1132,18 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
 
            /* Combine offset and flags into one field.  */
            offset = fold_convert (offset_type, offset);
-           offset = fold_build2 (LSHIFT_EXPR, offset_type, offset,
+           offset = fold_build2_loc (input_location,
+                                 LSHIFT_EXPR, offset_type, offset,
                                  build_int_cst (offset_type, 8));
-           offset = fold_build2 (BIT_IOR_EXPR, offset_type, offset,
+           offset = fold_build2_loc (input_location,
+                                 BIT_IOR_EXPR, offset_type, offset,
                                  build_int_cst (offset_type, flags));
            base_init = tree_cons (NULL_TREE, offset, base_init);
            base_init = tree_cons (NULL_TREE, tinfo, base_init);
-           base_init = build_constructor_from_list (NULL_TREE, base_init);
+           base_init = build_constructor_from_list (init_list_type_node, base_init);
            base_inits = tree_cons (NULL_TREE, base_init, base_inits);
          }
-       base_inits = build_constructor_from_list (NULL_TREE, base_inits);
+       base_inits = build_constructor_from_list (init_list_type_node, base_inits);
        base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
        /* Prepend the number of bases.  */
        base_inits = tree_cons (NULL_TREE,
@@ -1158,7 +1196,8 @@ create_pseudo_type_info (int tk, const char *real_name, ...)
     sprintf (pseudo_name + strlen (pseudo_name), "%d", tk - TK_FIXED);
 
   /* First field is the pseudo type_info base class.  */
-  fields = build_decl (FIELD_DECL, NULL_TREE,
+  fields = build_decl (input_location,
+                      FIELD_DECL, NULL_TREE,
                       VEC_index (tinfo_s, tinfo_descs,
                                  TK_TYPE_INFO_TYPE)->type);
 
@@ -1287,9 +1326,12 @@ get_pseudo_ti_index (tree type)
              push_abi_namespace ();
              create_pseudo_type_info
                (ix, "__vmi_class_type_info",
-                build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
-                build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
-                build_decl (FIELD_DECL, NULL_TREE, base_array),
+                build_decl (input_location,
+                            FIELD_DECL, NULL_TREE, integer_type_node),
+                build_decl (input_location,
+                            FIELD_DECL, NULL_TREE, integer_type_node),
+                build_decl (input_location,
+                            FIELD_DECL, NULL_TREE, base_array),
                 NULL);
              pop_abi_namespace ();
              break;
@@ -1321,10 +1363,12 @@ create_tinfo_types (void)
   {
     tree field, fields;
 
-    field = build_decl (FIELD_DECL, NULL_TREE, const_ptr_type_node);
+    field = build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, const_ptr_type_node);
     fields = field;
 
-    field = build_decl (FIELD_DECL, NULL_TREE, const_string_type_node);
+    field = build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, const_string_type_node);
     TREE_CHAIN (field) = fields;
     fields = field;
 
@@ -1350,7 +1394,8 @@ create_tinfo_types (void)
   /* Single public non-virtual base class. Add pointer to base class.
      This is really a descendant of __class_type_info.  */
   create_pseudo_type_info (TK_SI_CLASS_TYPE, "__si_class_type_info",
-           build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
+           build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, type_info_ptr_type),
            NULL);
 
   /* Base class internal helper. Pointer to base type, offset to base,
@@ -1358,10 +1403,12 @@ create_tinfo_types (void)
   {
     tree field, fields;
 
-    field = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type);
+    field = build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, type_info_ptr_type);
     fields = field;
 
-    field = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
+    field = build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, integer_types[itk_long]);
     TREE_CHAIN (field) = fields;
     fields = field;
 
@@ -1378,8 +1425,10 @@ create_tinfo_types (void)
      and pointer to the pointed to type.  This is really a descendant of
      __pbase_type_info.  */
   create_pseudo_type_info (TK_POINTER_TYPE, "__pointer_type_info",
-       build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
-       build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
+       build_decl (BUILTINS_LOCATION, 
+                  FIELD_DECL, NULL_TREE, integer_type_node),
+       build_decl (BUILTINS_LOCATION,
+                  FIELD_DECL, NULL_TREE, type_info_ptr_type),
        NULL);
 
   /* Pointer to member data type_info.  Add qualifications flags,
@@ -1387,9 +1436,12 @@ create_tinfo_types (void)
      This is really a descendant of __pbase_type_info.  */
   create_pseudo_type_info (TK_POINTER_MEMBER_TYPE,
        "__pointer_to_member_type_info",
-       build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
-       build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
-       build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
+       build_decl (BUILTINS_LOCATION,
+                   FIELD_DECL, NULL_TREE, integer_type_node),
+       build_decl (BUILTINS_LOCATION,
+                   FIELD_DECL, NULL_TREE, type_info_ptr_type),
+       build_decl (BUILTINS_LOCATION,
+                   FIELD_DECL, NULL_TREE, type_info_ptr_type),
        NULL);
 
   pop_abi_namespace ();
@@ -1404,17 +1456,21 @@ create_tinfo_types (void)
 void
 emit_support_tinfos (void)
 {
+  /* Dummy static variable so we can put nullptr in the array; it will be
+     set before we actually start to walk the array.  */
   static tree *const fundamentals[] =
   {
     &void_type_node,
     &boolean_type_node,
-    &wchar_type_node,
+    &wchar_type_node, &char16_type_node, &char32_type_node,
     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
     &short_integer_type_node, &short_unsigned_type_node,
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
+    &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
+    &nullptr_type_node,
     0
   };
   int ix;
@@ -1515,7 +1571,7 @@ emit_tinfo_decl (tree decl)
       init = get_pseudo_ti_init (type, get_pseudo_ti_index (type));
       DECL_INITIAL (decl) = init;
       mark_used (decl);
-      finish_decl (decl, init, NULL_TREE);
+      cp_finish_decl (decl, init, false, NULL_TREE, 0);
       return true;
     }
   else