OSDN Git Service

PR c++/44157
[pf3gnuchains/gcc-fork.git] / gcc / cp / rtti.c
index 7b1a667..4eb2ba7 100644 (file)
@@ -1,6 +1,6 @@
 /* RunTime Type Identification
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 /* RunTime Type Identification
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006
+   2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Mostly written by Jason Merrill (jason@cygnus.com).
 
    Free Software Foundation, Inc.
    Mostly written by Jason Merrill (jason@cygnus.com).
 
@@ -8,7 +8,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -17,12 +17,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
+#include "intl.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
@@ -32,6 +32,8 @@ Boston, MA 02110-1301, USA.  */
 #include "assert.h"
 #include "toplev.h"
 #include "convert.h"
 #include "assert.h"
 #include "toplev.h"
 #include "convert.h"
+#include "target.h"
+#include "c-pragma.h"
 
 /* C++ returns type information to the user in struct type_info
    objects. We also use type information to implement dynamic_cast and
 
 /* C++ returns type information to the user in struct type_info
    objects. We also use type information to implement dynamic_cast and
@@ -63,8 +65,7 @@ Boston, MA 02110-1301, USA.  */
    translation, when we are emitting the type info objects.  */
 
 /* Auxiliary data we hold for each type_info derived object we need.  */
    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
   tree type;  /* The RECORD_TYPE for this type_info object */
 
   tree vtable; /* The VAR_DECL of the vtable.  Only filled at end of
@@ -79,7 +80,7 @@ DEF_VEC_ALLOC_O(tinfo_s,gc);
 
 typedef enum tinfo_kind
 {
 
 typedef enum tinfo_kind
 {
-  TK_TYPE_INFO_TYPE,    /* std::type_info */
+  TK_TYPE_INFO_TYPE,    /* abi::__type_info_pseudo */
   TK_BASE_TYPE,                /* abi::__base_class_type_info */
   TK_BUILTIN_TYPE,     /* abi::__fundamental_type_info */
   TK_ARRAY_TYPE,       /* abi::__array_type_info */
   TK_BASE_TYPE,                /* abi::__base_class_type_info */
   TK_BUILTIN_TYPE,     /* abi::__fundamental_type_info */
   TK_ARRAY_TYPE,       /* abi::__array_type_info */
@@ -89,8 +90,8 @@ typedef enum tinfo_kind
   TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */
   TK_CLASS_TYPE,       /* abi::__class_type_info */
   TK_SI_CLASS_TYPE,    /* abi::__si_class_type_info */
   TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */
   TK_CLASS_TYPE,       /* abi::__class_type_info */
   TK_SI_CLASS_TYPE,    /* abi::__si_class_type_info */
-  TK_FIXED             /* end of fixed descriptors. */
-  /* ...                  abi::__vmi_type_info<I> */
+  TK_FIXED             /* end of fixed descriptors. */
+  /* ...                  abi::__vmi_type_info<I> */
 } tinfo_kind;
 
 /* A vector of all tinfo decls that haven't yet been emitted.  */
 } tinfo_kind;
 
 /* A vector of all tinfo decls that haven't yet been emitted.  */
@@ -101,10 +102,9 @@ VEC(tree,gc) *unemitted_tinfo_decls;
    and are generated as needed. */
 static GTY (()) VEC(tinfo_s,gc) *tinfo_descs;
 
    and are generated as needed. */
 static GTY (()) VEC(tinfo_s,gc) *tinfo_descs;
 
-static tree build_headof (tree);
 static tree ifnonnull (tree, tree);
 static tree ifnonnull (tree, tree);
-static tree tinfo_name (tree);
-static tree build_dynamic_cast_1 (tree, 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);
 static tree get_tinfo_decl_dynamic (tree);
 static tree throw_bad_cast (void);
 static tree throw_bad_typeid (void);
 static tree get_tinfo_decl_dynamic (tree);
@@ -125,6 +125,19 @@ static bool typeinfo_in_lib_p (tree);
 
 static int doing_runtime = 0;
 \f
 
 static int doing_runtime = 0;
 \f
+static void
+push_abi_namespace (void)
+{
+  push_nested_namespace (abi_node);
+  push_visibility ("default", 2);
+}
+
+static void
+pop_abi_namespace (void)
+{
+  pop_visibility (2);
+  pop_nested_namespace (abi_node);
+}
 
 /* Declare language defined type_info type and a pointer to const
    type_info.  This is incomplete here, and will be completed when
 
 /* Declare language defined type_info type and a pointer to const
    type_info.  This is incomplete here, and will be completed when
@@ -155,7 +168,7 @@ init_rtti_processing (void)
    virtual functions (TYPE_POLYMORPHIC_P), else just return the
    expression.  */
 
    virtual functions (TYPE_POLYMORPHIC_P), else just return the
    expression.  */
 
-static tree
+tree
 build_headof (tree exp)
 {
   tree type = TREE_TYPE (exp);
 build_headof (tree exp)
 {
   tree type = TREE_TYPE (exp);
@@ -175,12 +188,14 @@ build_headof (tree exp)
   index = build_int_cst (NULL_TREE,
                         -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
   index = build_int_cst (NULL_TREE,
                         -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
-  offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index);
+  offset = build_vtbl_ref (cp_build_indirect_ref (exp, RO_NULL, 
+                                                  tf_warning_or_error), 
+                           index);
 
   type = build_qualified_type (ptr_type_node,
                               cp_type_quals (TREE_TYPE (exp)));
 
   type = build_qualified_type (ptr_type_node,
                               cp_type_quals (TREE_TYPE (exp)));
-  return build2 (PLUS_EXPR, type, exp,
-                convert_to_integer (ptrdiff_type_node, offset));
+  return build2 (POINTER_PLUS_EXPR, type, exp,
+                convert_to_integer (sizetype, offset));
 }
 
 /* Get a bad_cast node for the program to throw...
 }
 
 /* Get a bad_cast node for the program to throw...
@@ -195,7 +210,7 @@ throw_bad_cast (void)
     fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
                                                         void_list_node));
 
     fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
                                                         void_list_node));
 
-  return build_cxx_call (fn, NULL_TREE);
+  return build_cxx_call (fn, 0, NULL);
 }
 
 /* Return an expression for "__cxa_bad_typeid()".  The expression
 }
 
 /* Return an expression for "__cxa_bad_typeid()".  The expression
@@ -214,7 +229,7 @@ throw_bad_typeid (void)
       fn = push_throw_library_fn (fn, t);
     }
 
       fn = push_throw_library_fn (fn, t);
     }
 
-  return build_cxx_call (fn, NULL_TREE);
+  return build_cxx_call (fn, 0, NULL);
 }
 \f
 /* Return an lvalue expression whose type is "const std::type_info"
 }
 \f
 /* Return an lvalue expression whose type is "const std::type_info"
@@ -228,16 +243,20 @@ get_tinfo_decl_dynamic (tree exp)
   tree type;
   tree t;
 
   tree type;
   tree t;
 
-  if (exp == error_mark_node)
+  if (error_operand_p (exp))
     return error_mark_node;
 
     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);
 
   /* peel back references, so they match.  */
   type = non_reference (TREE_TYPE (exp));
 
   /* Peel off cv qualifiers.  */
   type = TYPE_MAIN_VARIANT (type);
 
-  if (!VOID_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)
     type = complete_type_or_else (type, exp);
 
   if (!type)
@@ -259,12 +278,14 @@ 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));
 
     /* Otherwise return the type_info for the static type of the expr.  */
     t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
 
-  return build_indirect_ref (t, NULL);
+  return cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
 }
 
 static bool
 typeid_ok_p (void)
 {
 }
 
 static bool
 typeid_ok_p (void)
 {
+  tree pseudo_type_info, type_info_type;
+
   if (! flag_rtti)
     {
       error ("cannot use typeid with -fno-rtti");
   if (! flag_rtti)
     {
       error ("cannot use typeid with -fno-rtti");
@@ -277,6 +298,18 @@ typeid_ok_p (void)
       return false;
     }
 
       return false;
     }
 
+  pseudo_type_info
+    = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE)->type;
+  type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node);
+
+  /* Make sure abi::__type_info_pseudo has the same alias set
+     as std::type_info.  */
+  if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
+    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
+  else
+    gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
+               == get_alias_set (type_info_type));
+
   return true;
 }
 
   return true;
 }
 
@@ -286,7 +319,7 @@ typeid_ok_p (void)
 tree
 build_typeid (tree exp)
 {
 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 ())
   int nonnull = 0;
 
   if (exp == error_mark_node || !typeid_ok_p ())
@@ -301,6 +334,9 @@ build_typeid (tree exp)
       && ! resolves_to_fixed_type_p (exp, &nonnull)
       && ! nonnull)
     {
       && ! 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));
     }
       exp = stabilize_reference (exp);
       cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
     }
@@ -316,20 +352,36 @@ build_typeid (tree exp)
 
       exp = build3 (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
     }
 
       exp = build3 (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
     }
+  else
+    mark_type_use (initial_expr);
 
   return exp;
 }
 
 
   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
 static tree
-tinfo_name (tree type)
+tinfo_name (tree type, bool mark_private)
 {
   const char *name;
 {
   const char *name;
+  int length;
   tree name_string;
 
   name = mangle_type_string (type);
   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
 }
 
 /* Return a VAR_DECL for the internal ABI defined type_info object for
@@ -342,11 +394,10 @@ get_tinfo_decl (tree type)
   tree name;
   tree d;
 
   tree name;
   tree d;
 
-  if (COMPLETE_TYPE_P (type)
-      && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (variably_modified_type_p (type, /*fn=*/NULL_TREE))
     {
       error ("cannot create type information for type %qT because "
     {
       error ("cannot create type information for type %qT because "
-            "its size is variable",
+            "it involves types of variable size",
             type);
       return error_mark_node;
     }
             type);
       return error_mark_node;
     }
@@ -385,10 +436,11 @@ get_tinfo_decl (tree type)
         define it later if we need to do so.  */
       DECL_EXTERNAL (d) = 1;
       DECL_NOT_REALLY_EXTERN (d) = 1;
         define it later if we need to do so.  */
       DECL_EXTERNAL (d) = 1;
       DECL_NOT_REALLY_EXTERN (d) = 1;
+      set_linkage_according_to_type (type, d);
+
+      d = pushdecl_top_level_and_finish (d, NULL_TREE);
       if (CLASS_TYPE_P (type))
        CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
       if (CLASS_TYPE_P (type))
        CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
-      set_linkage_according_to_type (type, d);
-      pushdecl_top_level_and_finish (d, NULL_TREE);
 
       /* Add decl to the global array of tinfo decls.  */
       VEC_safe_push (tree, gc, unemitted_tinfo_decls, d);
 
       /* Add decl to the global array of tinfo decls.  */
       VEC_safe_push (tree, gc, unemitted_tinfo_decls, d);
@@ -430,13 +482,16 @@ get_typeid (tree type)
      that is the operand of typeid are always ignored.  */
   type = TYPE_MAIN_VARIANT (type);
 
      that is the operand of typeid are always ignored.  */
   type = TYPE_MAIN_VARIANT (type);
 
-  if (!VOID_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;
 
     type = complete_type_or_else (type, NULL_TREE);
 
   if (!type)
     return error_mark_node;
 
-  return build_indirect_ref (get_tinfo_ptr (type), NULL);
+  return cp_build_indirect_ref (get_tinfo_ptr (type), RO_NULL, 
+                                tf_warning_or_error);
 }
 
 /* Check whether TEST is null before returning RESULT.  If TEST is used in
 }
 
 /* Check whether TEST is null before returning RESULT.  If TEST is used in
@@ -456,7 +511,7 @@ ifnonnull (tree test, tree result)
    paper.  */
 
 static tree
    paper.  */
 
 static tree
-build_dynamic_cast_1 (tree type, tree expr)
+build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
 {
   enum tree_code tc = TREE_CODE (type);
   tree exprtype = TREE_TYPE (expr);
 {
   enum tree_code tc = TREE_CODE (type);
   tree exprtype = TREE_TYPE (expr);
@@ -464,6 +519,9 @@ build_dynamic_cast_1 (tree type, tree expr)
   tree old_expr = expr;
   const char *errstr = NULL;
 
   tree old_expr = expr;
   const char *errstr = NULL;
 
+  /* Save casted types in the function's used types hash table.  */
+  used_types_insert (type);
+
   /* T shall be a pointer or reference to a complete class type, or
      `pointer to cv void''.  */
   switch (tc)
   /* T shall be a pointer or reference to a complete class type, or
      `pointer to cv void''.  */
   switch (tc)
@@ -473,20 +531,20 @@ build_dynamic_cast_1 (tree type, tree expr)
        break;
       /* Fall through.  */
     case REFERENCE_TYPE:
        break;
       /* Fall through.  */
     case REFERENCE_TYPE:
-      if (! IS_AGGR_TYPE (TREE_TYPE (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))))
        {
          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:
          goto fail;
        }
       break;
 
     default:
-      errstr = "target is not pointer or reference";
+      errstr = _("target is not pointer or reference");
       goto fail;
     }
 
       goto fail;
     }
 
@@ -495,50 +553,54 @@ build_dynamic_cast_1 (tree type, tree expr)
       /* 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 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)
        {
       if (TREE_CODE (exprtype) != POINTER_TYPE)
        {
-         errstr = "source is not a pointer";
+         errstr = _("source is not a pointer");
          goto fail;
        }
          goto fail;
        }
-      if (! IS_AGGR_TYPE (TREE_TYPE (exprtype)))
+      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))))
        {
          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
     {
          goto fail;
        }
     }
   else
     {
-      /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
+      expr = mark_lvalue_use (expr);
+
       exprtype = build_reference_type (exprtype);
       exprtype = build_reference_type (exprtype);
-      expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
-                                  LOOKUP_NORMAL, NULL_TREE);
 
       /* 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.  */
 
 
       /* 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)))
+      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))))
        {
          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;
        }
 
          goto fail;
        }
 
+      /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
+      expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
+                                  LOOKUP_NORMAL, NULL_TREE);
     }
 
   /* The dynamic_cast operator shall not cast away constness.  */
   if (!at_least_as_qualified_p (TREE_TYPE (type),
                                TREE_TYPE (exprtype)))
     {
     }
 
   /* 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";
+      errstr = _("conversion casts away constness");
       goto fail;
     }
 
       goto fail;
     }
 
@@ -584,7 +646,8 @@ build_dynamic_cast_1 (tree type, tree expr)
       else
        {
          tree retval;
       else
        {
          tree retval;
-         tree result, td2, td3, elems;
+         tree result, td2, td3;
+         tree elems[4];
          tree static_type, target_type, boff;
 
          /* If we got here, we can't convert statically.  Therefore,
          tree static_type, target_type, boff;
 
          /* If we got here, we can't convert statically.  Therefore,
@@ -595,8 +658,9 @@ build_dynamic_cast_1 (tree type, tree expr)
                  && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
                {
                  tree expr = throw_bad_cast ();
                  && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
                {
                  tree expr = throw_bad_cast ();
-                 warning (0, "dynamic_cast of %q#D to %q#T can never succeed",
-                          old_expr, type);
+                  if (complain & tf_warning)
+                    warning (0, "dynamic_cast of %q#D to %q#T can never succeed",
+                             old_expr, type);
                  /* Bash it to the expected type.  */
                  TREE_TYPE (expr) = type;
                  return expr;
                  /* Bash it to the expected type.  */
                  TREE_TYPE (expr) = type;
                  return expr;
@@ -609,21 +673,30 @@ build_dynamic_cast_1 (tree type, tree expr)
              if (TREE_CODE (op) == VAR_DECL
                  && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
                {
              if (TREE_CODE (op) == VAR_DECL
                  && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
                {
-                 warning (0, "dynamic_cast of %q#D to %q#T can never succeed",
-                          op, type);
+                  if (complain & tf_warning)
+                    warning (0, "dynamic_cast of %q#D to %q#T can never succeed",
+                             op, type);
                  retval = build_int_cst (type, 0);
                  return retval;
                }
            }
 
                  retval = build_int_cst (type, 0);
                  return retval;
                }
            }
 
+         /* Use of dynamic_cast when -fno-rtti is prohibited.  */
+         if (!flag_rtti)
+           {
+              if (complain & tf_error)
+                error ("%<dynamic_cast%> not permitted with -fno-rtti");
+             return error_mark_node;
+           }
+
          target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
          static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
          td2 = get_tinfo_decl (target_type);
          mark_used (td2);
          target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
          static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
          td2 = get_tinfo_decl (target_type);
          mark_used (td2);
-         td2 = build_unary_op (ADDR_EXPR, td2, 0);
+         td2 = cp_build_unary_op (ADDR_EXPR, td2, 0, complain);
          td3 = get_tinfo_decl (static_type);
          mark_used (td3);
          td3 = get_tinfo_decl (static_type);
          mark_used (td3);
-         td3 = build_unary_op (ADDR_EXPR, td3, 0);
+         td3 = cp_build_unary_op (ADDR_EXPR, td3, 0, complain);
 
          /* Determine how T and V are related.  */
          boff = dcast_base_hint (static_type, target_type);
 
          /* Determine how T and V are related.  */
          boff = dcast_base_hint (static_type, target_type);
@@ -633,23 +706,21 @@ build_dynamic_cast_1 (tree type, tree expr)
 
          expr1 = expr;
          if (tc == REFERENCE_TYPE)
 
          expr1 = expr;
          if (tc == REFERENCE_TYPE)
-           expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
+           expr1 = cp_build_unary_op (ADDR_EXPR, expr1, 0, complain);
 
 
-         elems = tree_cons
-           (NULL_TREE, expr1, tree_cons
-            (NULL_TREE, td3, tree_cons
-             (NULL_TREE, td2, tree_cons
-              (NULL_TREE, boff, NULL_TREE))));
+         elems[0] = expr1;
+         elems[1] = td3;
+         elems[2] = td2;
+         elems[3] = boff;
 
          dcast_fn = dynamic_cast_node;
          if (!dcast_fn)
            {
              tree tmp;
              tree tinfo_ptr;
 
          dcast_fn = dynamic_cast_node;
          if (!dcast_fn)
            {
              tree tmp;
              tree tinfo_ptr;
-             tree ns = abi_node;
              const char *name;
 
              const char *name;
 
-             push_nested_namespace (ns);
+             push_abi_namespace ();
              tinfo_ptr = xref_tag (class_type,
                                    get_identifier ("__class_type_info"),
                                    /*tag_scope=*/ts_current, false);
              tinfo_ptr = xref_tag (class_type,
                                    get_identifier ("__class_type_info"),
                                    /*tag_scope=*/ts_current, false);
@@ -665,18 +736,22 @@ build_dynamic_cast_1 (tree type, tree expr)
                   (NULL_TREE, ptrdiff_type_node, void_list_node))));
              tmp = build_function_type (ptr_type_node, tmp);
              dcast_fn = build_library_fn_ptr (name, tmp);
                   (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;
-             pop_nested_namespace (ns);
+             DECL_PURE_P (dcast_fn) = 1;
+             pop_abi_namespace ();
              dynamic_cast_node = dcast_fn;
            }
              dynamic_cast_node = dcast_fn;
            }
-         result = build_cxx_call (dcast_fn, elems);
+         result = build_cxx_call (dcast_fn, 4, elems);
 
          if (tc == REFERENCE_TYPE)
            {
              tree bad = throw_bad_cast ();
 
          if (tc == REFERENCE_TYPE)
            {
              tree bad = throw_bad_cast ();
+             tree neq;
 
              result = save_expr (result);
 
              result = save_expr (result);
-             return build3 (COND_EXPR, type, result, 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*.  */
            }
 
          /* Now back to the type we want from a void*.  */
@@ -685,36 +760,29 @@ build_dynamic_cast_1 (tree type, tree expr)
        }
     }
   else
        }
     }
   else
-    errstr = "source type is not polymorphic";
+    errstr = _("source type is not polymorphic");
 
  fail:
 
  fail:
-  error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)",
-        expr, exprtype, type, errstr);
+  if (complain & tf_error)
+    error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)",
+           expr, exprtype, type, errstr);
   return error_mark_node;
 }
 
 tree
   return error_mark_node;
 }
 
 tree
-build_dynamic_cast (tree type, tree expr)
+build_dynamic_cast (tree type, tree expr, tsubst_flags_t complain)
 {
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
 
 {
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
 
-  /* Use of dynamic_cast when -fno-rtti is prohibited.  */
-  if (!flag_rtti)
-    {
-      error ("%<dynamic_cast%> not permitted with -fno-rtti");
-      return error_mark_node;
-    }
-
   if (processing_template_decl)
     {
       expr = build_min (DYNAMIC_CAST_EXPR, type, expr);
       TREE_SIDE_EFFECTS (expr) = 1;
   if (processing_template_decl)
     {
       expr = build_min (DYNAMIC_CAST_EXPR, type, expr);
       TREE_SIDE_EFFECTS (expr) = 1;
-
-      return expr;
+      return convert_from_reference (expr);
     }
 
     }
 
-  return convert_from_reference (build_dynamic_cast_1 (type, expr));
+  return convert_from_reference (build_dynamic_cast_1 (type, expr, complain));
 }
 \f
 /* Return the runtime bit mask encoding the qualifiers of TYPE.  */
 }
 \f
 /* Return the runtime bit mask encoding the qualifiers of TYPE.  */
@@ -799,13 +867,12 @@ tinfo_base_init (tinfo_s *ti, tree target)
   tree vtable_ptr;
 
   {
   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);
 
     /* 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.  */
 
     /* Determine the name of the variable -- and remember with which
        type it is associated.  */
@@ -820,14 +887,9 @@ tinfo_base_init (tinfo_s *ti, tree target)
     TREE_STATIC (name_decl) = 1;
     DECL_EXTERNAL (name_decl) = 0;
     DECL_TINFO_P (name_decl) = 1;
     TREE_STATIC (name_decl) = 1;
     DECL_EXTERNAL (name_decl) = 0;
     DECL_TINFO_P (name_decl) = 1;
-    if (involves_incomplete_p (target))
-      {
-       TREE_PUBLIC (name_decl) = 0;
-       DECL_INTERFACE_KNOWN (name_decl) = 1;
-      }
-    else
-      set_linkage_according_to_type (target, name_decl);
+    set_linkage_according_to_type (target, name_decl);
     import_export_decl (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);
     DECL_INITIAL (name_decl) = name_string;
     mark_used (name_decl);
     pushdecl_top_level_and_finish (name_decl, name_string);
@@ -837,10 +899,10 @@ tinfo_base_init (tinfo_s *ti, tree target)
   if (!vtable_ptr)
     {
       tree real_type;
   if (!vtable_ptr)
     {
       tree real_type;
-      push_nested_namespace (abi_node);
+      push_abi_namespace ();
       real_type = xref_tag (class_type, ti->name,
                            /*tag_scope=*/ts_current, false);
       real_type = xref_tag (class_type, ti->name,
                            /*tag_scope=*/ts_current, false);
-      pop_nested_namespace (abi_node);
+      pop_abi_namespace ();
 
       if (!COMPLETE_TYPE_P (real_type))
        {
 
       if (!COMPLETE_TYPE_P (real_type))
        {
@@ -852,15 +914,16 @@ tinfo_base_init (tinfo_s *ti, tree target)
        }
 
       vtable_ptr = get_vtable_decl (real_type, /*complete=*/1);
        }
 
       vtable_ptr = get_vtable_decl (real_type, /*complete=*/1);
-      vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0);
+      vtable_ptr = cp_build_unary_op (ADDR_EXPR, vtable_ptr, 0, 
+                                   tf_warning_or_error);
 
       /* We need to point into the middle of the vtable.  */
       vtable_ptr = build2
 
       /* We need to point into the middle of the vtable.  */
       vtable_ptr = build2
-       (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
+       (POINTER_PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
         size_binop (MULT_EXPR,
                     size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
                     TYPE_SIZE_UNIT (vtable_entry_type)));
         size_binop (MULT_EXPR,
                     size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
                     TYPE_SIZE_UNIT (vtable_entry_type)));
-      
+
       ti->vtable = vtable_ptr;
     }
 
       ti->vtable = vtable_ptr;
     }
 
@@ -868,9 +931,8 @@ tinfo_base_init (tinfo_s *ti, tree target)
 
   init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
 
 
   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_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   init = tree_cons (NULL_TREE, init, NULL_TREE);
 
   TREE_STATIC (init) = 1;
   init = tree_cons (NULL_TREE, init, NULL_TREE);
 
@@ -885,10 +947,9 @@ static tree
 generic_initializer (tinfo_s *ti, tree target)
 {
   tree init = tinfo_base_init (ti, target);
 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_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -912,9 +973,8 @@ ptr_initializer (tinfo_s *ti, tree target)
                    get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
                    init);
 
                    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_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -944,10 +1004,9 @@ ptm_initializer (tinfo_s *ti, tree target)
   init = tree_cons (NULL_TREE,
                    get_tinfo_ptr (klass),
                    init);
   init = tree_cons (NULL_TREE,
                    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_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -962,9 +1021,8 @@ class_initializer (tinfo_s *ti, tree target, tree trail)
   tree init = tinfo_base_init (ti, target);
 
   TREE_CHAIN (init) = 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_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -990,6 +1048,11 @@ typeinfo_in_lib_p (tree type)
     case VOID_TYPE:
       return true;
 
     case VOID_TYPE:
       return true;
 
+    case LANG_TYPE:
+      if (NULLPTR_TYPE_P (type))
+       return true;
+      /* else fall through.  */
+
     default:
       return false;
     }
     default:
       return false;
     }
@@ -1002,16 +1065,16 @@ static tree
 get_pseudo_ti_init (tree type, unsigned tk_index)
 {
   tinfo_s *ti = VEC_index (tinfo_s, tinfo_descs, tk_index);
 get_pseudo_ti_init (tree type, unsigned tk_index)
 {
   tinfo_s *ti = VEC_index (tinfo_s, tinfo_descs, tk_index);
-  
+
   gcc_assert (at_eof);
   switch (tk_index)
     {
     case TK_POINTER_MEMBER_TYPE:
       return ptm_initializer (ti, type);
   gcc_assert (at_eof);
   switch (tk_index)
     {
     case TK_POINTER_MEMBER_TYPE:
       return ptm_initializer (ti, type);
-      
+
     case TK_POINTER_TYPE:
       return ptr_initializer (ti, type);
     case TK_POINTER_TYPE:
       return ptr_initializer (ti, type);
-      
+
     case TK_BUILTIN_TYPE:
     case TK_ENUMERAL_TYPE:
     case TK_FUNCTION_TYPE:
     case TK_BUILTIN_TYPE:
     case TK_ENUMERAL_TYPE:
     case TK_FUNCTION_TYPE:
@@ -1039,11 +1102,12 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
        tree binfo = TYPE_BINFO (type);
        int nbases = BINFO_N_BASE_BINFOS (binfo);
        VEC(tree,gc) *base_accesses = BINFO_BASE_ACCESSES (binfo);
        tree binfo = TYPE_BINFO (type);
        int nbases = BINFO_N_BASE_BINFOS (binfo);
        VEC(tree,gc) *base_accesses = BINFO_BASE_ACCESSES (binfo);
+       tree offset_type = integer_types[itk_long];
        tree base_inits = NULL_TREE;
        int ix;
        tree base_inits = NULL_TREE;
        int ix;
-          
+
        gcc_assert (tk_index >= TK_FIXED);
        gcc_assert (tk_index >= TK_FIXED);
-      
+
        /* Generate the base information initializer.  */
        for (ix = nbases; ix--;)
          {
        /* Generate the base information initializer.  */
        for (ix = nbases; ix--;)
          {
@@ -1052,32 +1116,34 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
            int flags = 0;
            tree tinfo;
            tree offset;
            int flags = 0;
            tree tinfo;
            tree offset;
-           
+
            if (VEC_index (tree, base_accesses, ix) == access_public_node)
              flags |= 2;
            tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
            if (BINFO_VIRTUAL_P (base_binfo))
              {
                /* We store the vtable offset at which the virtual
            if (VEC_index (tree, base_accesses, ix) == access_public_node)
              flags |= 2;
            tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
            if (BINFO_VIRTUAL_P (base_binfo))
              {
                /* We store the vtable offset at which the virtual
-                          base offset can be found.  */
+                  base offset can be found.  */
                offset = BINFO_VPTR_FIELD (base_binfo);
                offset = BINFO_VPTR_FIELD (base_binfo);
-               offset = convert (sizetype, offset);
                flags |= 1;
              }
            else
              offset = BINFO_OFFSET (base_binfo);
                flags |= 1;
              }
            else
              offset = BINFO_OFFSET (base_binfo);
-           
+
            /* Combine offset and flags into one field.  */
            /* Combine offset and flags into one field.  */
-           offset = cp_build_binary_op (LSHIFT_EXPR, offset,
-                                        build_int_cst (NULL_TREE, 8));
-           offset = cp_build_binary_op (BIT_IOR_EXPR, offset,
-                                        build_int_cst (NULL_TREE, flags));
+           offset = fold_convert (offset_type, offset);
+           offset = fold_build2_loc (input_location,
+                                 LSHIFT_EXPR, offset_type, offset,
+                                 build_int_cst (offset_type, 8));
+           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 = 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 = 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,
        base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
        /* Prepend the number of bases.  */
        base_inits = tree_cons (NULL_TREE,
@@ -1130,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.  */
     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);
 
                       VEC_index (tinfo_s, tinfo_descs,
                                  TK_TYPE_INFO_TYPE)->type);
 
@@ -1142,7 +1209,7 @@ create_pseudo_type_info (int tk, const char *real_name, ...)
     }
 
   /* Create the pseudo type.  */
     }
 
   /* Create the pseudo type.  */
-  pseudo_type = make_aggr_type (RECORD_TYPE);
+  pseudo_type = make_class_type (RECORD_TYPE);
   finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
   CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
 
   finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
   CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
 
@@ -1151,6 +1218,10 @@ create_pseudo_type_info (int tk, const char *real_name, ...)
   ti->name = get_identifier (real_name);
   ti->vtable = NULL_TREE;
 
   ti->name = get_identifier (real_name);
   ti->vtable = NULL_TREE;
 
+  /* Pretend this is public so determine_visibility doesn't give vtables
+     internal linkage.  */
+  TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1;
+
   va_end (ap);
 }
 
   va_end (ap);
 }
 
@@ -1162,29 +1233,29 @@ static unsigned
 get_pseudo_ti_index (tree type)
 {
   unsigned ix;
 get_pseudo_ti_index (tree type)
 {
   unsigned ix;
-  
+
   switch (TREE_CODE (type))
     {
     case OFFSET_TYPE:
       ix = TK_POINTER_MEMBER_TYPE;
       break;
   switch (TREE_CODE (type))
     {
     case OFFSET_TYPE:
       ix = TK_POINTER_MEMBER_TYPE;
       break;
-      
+
     case POINTER_TYPE:
       ix = TK_POINTER_TYPE;
       break;
     case POINTER_TYPE:
       ix = TK_POINTER_TYPE;
       break;
-      
+
     case ENUMERAL_TYPE:
       ix = TK_ENUMERAL_TYPE;
       break;
     case ENUMERAL_TYPE:
       ix = TK_ENUMERAL_TYPE;
       break;
-      
+
     case FUNCTION_TYPE:
       ix = TK_FUNCTION_TYPE;
       break;
     case FUNCTION_TYPE:
       ix = TK_FUNCTION_TYPE;
       break;
-      
+
     case ARRAY_TYPE:
       ix = TK_ARRAY_TYPE;
       break;
     case ARRAY_TYPE:
       ix = TK_ARRAY_TYPE;
       break;
-      
+
     case UNION_TYPE:
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (type))
     case UNION_TYPE:
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (type))
@@ -1230,7 +1301,7 @@ get_pseudo_ti_index (tree type)
                {
                  /* too short, extend.  */
                  unsigned len = VEC_length (tinfo_s, tinfo_descs);
                {
                  /* too short, extend.  */
                  unsigned len = VEC_length (tinfo_s, tinfo_descs);
-                 
+
                  VEC_safe_grow (tinfo_s, gc, tinfo_descs, ix + 1);
                  while (VEC_iterate (tinfo_s, tinfo_descs, len++, ti))
                    ti->type = ti->vtable = ti->name = NULL_TREE;
                  VEC_safe_grow (tinfo_s, gc, tinfo_descs, ix + 1);
                  while (VEC_iterate (tinfo_s, tinfo_descs, len++, ti))
                    ti->type = ti->vtable = ti->name = NULL_TREE;
@@ -1252,14 +1323,17 @@ get_pseudo_ti_index (tree type)
                                             TK_BASE_TYPE)->type,
                                  array_domain);
 
                                             TK_BASE_TYPE)->type,
                                  array_domain);
 
-             push_nested_namespace (abi_node);
+             push_abi_namespace ();
              create_pseudo_type_info
                (ix, "__vmi_class_type_info",
              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);
                 NULL);
-             pop_nested_namespace (abi_node);
+             pop_abi_namespace ();
              break;
            }
        }
              break;
            }
        }
@@ -1277,32 +1351,33 @@ static void
 create_tinfo_types (void)
 {
   tinfo_s *ti;
 create_tinfo_types (void)
 {
   tinfo_s *ti;
-  
+
   gcc_assert (!tinfo_descs);
 
   VEC_safe_grow (tinfo_s, gc, tinfo_descs, TK_FIXED);
   gcc_assert (!tinfo_descs);
 
   VEC_safe_grow (tinfo_s, gc, tinfo_descs, TK_FIXED);
-  
-  push_nested_namespace (abi_node);
+
+  push_abi_namespace ();
 
   /* Create the internal type_info structure. This is used as a base for
      the other structures.  */
   {
     tree field, fields;
 
 
   /* Create the internal type_info structure. This is used as a base for
      the other structures.  */
   {
     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;
 
     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;
 
     ti = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE);
     TREE_CHAIN (field) = fields;
     fields = field;
 
     ti = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE);
-    ti->type = make_aggr_type (RECORD_TYPE);
+    ti->type = make_class_type (RECORD_TYPE);
     ti->vtable = NULL_TREE;
     ti->name = NULL_TREE;
     finish_builtin_struct (ti->type, "__type_info_pseudo",
                           fields, NULL_TREE);
     ti->vtable = NULL_TREE;
     ti->name = NULL_TREE;
     finish_builtin_struct (ti->type, "__type_info_pseudo",
                           fields, NULL_TREE);
-    TYPE_HAS_CONSTRUCTOR (ti->type) = 1;
   }
 
   /* Fundamental type_info */
   }
 
   /* Fundamental type_info */
@@ -1312,44 +1387,48 @@ create_tinfo_types (void)
   create_pseudo_type_info (TK_ARRAY_TYPE, "__array_type_info", NULL);
   create_pseudo_type_info (TK_FUNCTION_TYPE, "__function_type_info", NULL);
   create_pseudo_type_info (TK_ENUMERAL_TYPE, "__enum_type_info", NULL);
   create_pseudo_type_info (TK_ARRAY_TYPE, "__array_type_info", NULL);
   create_pseudo_type_info (TK_FUNCTION_TYPE, "__function_type_info", NULL);
   create_pseudo_type_info (TK_ENUMERAL_TYPE, "__enum_type_info", NULL);
-  
+
   /* Class type_info.  No additional fields.  */
   create_pseudo_type_info (TK_CLASS_TYPE, "__class_type_info", NULL);
   /* Class type_info.  No additional fields.  */
   create_pseudo_type_info (TK_CLASS_TYPE, "__class_type_info", NULL);
-  
-  /* Single public non-virtual base class. Add pointer to base class. 
+
+  /* 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",
      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),
-            NULL);
+           build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, type_info_ptr_type),
+           NULL);
 
   /* Base class internal helper. Pointer to base type, offset to base,
      flags.  */
   {
     tree field, fields;
 
 
   /* Base class internal helper. Pointer to base type, offset to base,
      flags.  */
   {
     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;
 
     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;
     TREE_CHAIN (field) = fields;
     fields = field;
-  
+
     ti = VEC_index (tinfo_s, tinfo_descs, TK_BASE_TYPE);
     ti = VEC_index (tinfo_s, tinfo_descs, TK_BASE_TYPE);
-    
-    ti->type = make_aggr_type (RECORD_TYPE);
+
+    ti->type = make_class_type (RECORD_TYPE);
     ti->vtable = NULL_TREE;
     ti->name = NULL_TREE;
     finish_builtin_struct (ti->type, "__base_class_type_info_pseudo",
                           fields, NULL_TREE);
     ti->vtable = NULL_TREE;
     ti->name = NULL_TREE;
     finish_builtin_struct (ti->type, "__base_class_type_info_pseudo",
                           fields, NULL_TREE);
-    TYPE_HAS_CONSTRUCTOR (ti->type) = 1;
   }
 
   /* Pointer type_info. Adds two fields, qualification mask
      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",
   }
 
   /* Pointer type_info. Adds two fields, qualification mask
      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,
        NULL);
 
   /* Pointer to member data type_info.  Add qualifications flags,
@@ -1357,12 +1436,15 @@ 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",
      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),
-        NULL);
-
-  pop_nested_namespace (abi_node);
+       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 ();
 }
 
 /* Emit the type_info descriptors which are guaranteed to be in the runtime
 }
 
 /* Emit the type_info descriptors which are guaranteed to be in the runtime
@@ -1374,27 +1456,31 @@ create_tinfo_types (void)
 void
 emit_support_tinfos (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,
   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,
     &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;
   tree bltn_type, dtor;
 
     0
   };
   int ix;
   tree bltn_type, dtor;
 
-  push_nested_namespace (abi_node);
+  push_abi_namespace ();
   bltn_type = xref_tag (class_type,
                        get_identifier ("__fundamental_type_info"),
                        /*tag_scope=*/ts_current, false);
   bltn_type = xref_tag (class_type,
                        get_identifier ("__fundamental_type_info"),
                        /*tag_scope=*/ts_current, false);
-  pop_nested_namespace (abi_node);
+  pop_abi_namespace ();
   if (!COMPLETE_TYPE_P (bltn_type))
     return;
   dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
   if (!COMPLETE_TYPE_P (bltn_type))
     return;
   dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
@@ -1425,8 +1511,11 @@ emit_support_tinfos (void)
             comdat_linkage for details.)  Since we want these objects
             to have external linkage so that copies do not have to be
             emitted in code outside the runtime library, we make them
             comdat_linkage for details.)  Since we want these objects
             to have external linkage so that copies do not have to be
             emitted in code outside the runtime library, we make them
-            non-COMDAT here.  */
-         if (!flag_weak)
+            non-COMDAT here.  
+
+            It might also not be necessary to follow this detail of the
+            ABI.  */
+         if (!flag_weak || ! targetm.cxx.library_rtti_comdat ())
            {
              gcc_assert (TREE_PUBLIC (tinfo) && !DECL_COMDAT (tinfo));
              DECL_INTERFACE_KNOWN (tinfo) = 1;
            {
              gcc_assert (TREE_PUBLIC (tinfo) && !DECL_COMDAT (tinfo));
              DECL_INTERFACE_KNOWN (tinfo) = 1;
@@ -1477,12 +1566,12 @@ emit_tinfo_decl (tree decl)
   if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
     {
       tree init;
   if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
     {
       tree init;
-      
+
       DECL_EXTERNAL (decl) = 0;
       init = get_pseudo_ti_init (type, get_pseudo_ti_index (type));
       DECL_INITIAL (decl) = init;
       mark_used (decl);
       DECL_EXTERNAL (decl) = 0;
       init = get_pseudo_ti_init (type, get_pseudo_ti_index (type));
       DECL_INITIAL (decl) = init;
       mark_used (decl);
-      cp_finish_decl (decl, init, NULL_TREE, 0);
+      cp_finish_decl (decl, init, false, NULL_TREE, 0);
       return true;
     }
   else
       return true;
     }
   else