OSDN Git Service

* config/mcore/mcore.c Don't include assert.h.
[pf3gnuchains/gcc-fork.git] / gcc / cp / rtti.c
index 6d60d4c..0feaf07 100644 (file)
@@ -1,6 +1,6 @@
 /* RunTime Type Identification
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005
+   2005, 2006, 2007, 2008, 2009, 2010
    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
-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,
@@ -17,21 +17,21 @@ 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
-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 "intl.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "output.h"
-#include "assert.h"
-#include "toplev.h"
 #include "convert.h"
+#include "target.h"
+#include "c-family/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
@@ -63,8 +63,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.  */
-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
@@ -79,7 +78,7 @@ DEF_VEC_ALLOC_O(tinfo_s,gc);
 
 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 */
@@ -89,8 +88,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_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.  */
@@ -101,10 +100,9 @@ VEC(tree,gc) *unemitted_tinfo_decls;
    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 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);
@@ -116,7 +114,7 @@ static tree tinfo_base_init (tinfo_s *, tree);
 static tree generic_initializer (tinfo_s *, tree);
 static tree ptr_initializer (tinfo_s *, tree);
 static tree ptm_initializer (tinfo_s *, tree);
-static tree class_initializer (tinfo_s *, tree, tree);
+static tree class_initializer (tinfo_s *, tree, unsigned, ...);
 static void create_pseudo_type_info (int, const char *, ...);
 static tree get_pseudo_ti_init (tree, unsigned);
 static unsigned get_pseudo_ti_index (tree);
@@ -125,6 +123,19 @@ static bool typeinfo_in_lib_p (tree);
 
 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
@@ -142,7 +153,7 @@ init_rtti_processing (void)
                             /*tag_scope=*/ts_current, false);
   pop_namespace ();
   const_type_info_type_node
-    = build_qualified_type (type_info_type, TYPE_QUAL_CONST);
+    = cp_build_qualified_type (type_info_type, TYPE_QUAL_CONST);
   type_info_ptr_type = build_pointer_type (const_type_info_type_node);
 
   unemitted_tinfo_decls = VEC_alloc (tree, gc, 124);
@@ -155,7 +166,7 @@ init_rtti_processing (void)
    virtual functions (TYPE_POLYMORPHIC_P), else just return the
    expression.  */
 
-static tree
+tree
 build_headof (tree exp)
 {
   tree type = TREE_TYPE (exp);
@@ -175,12 +186,14 @@ build_headof (tree exp)
   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)));
-  return build2 (PLUS_EXPR, type, exp,
-                convert_to_integer (ptrdiff_type_node, offset));
+  type = cp_build_qualified_type (ptr_type_node,
+                                 cp_type_quals (TREE_TYPE (exp)));
+  return build2 (POINTER_PLUS_EXPR, type, exp,
+                convert_to_integer (sizetype, offset));
 }
 
 /* Get a bad_cast node for the program to throw...
@@ -192,10 +205,10 @@ throw_bad_cast (void)
 {
   tree fn = get_identifier ("__cxa_bad_cast");
   if (!get_global_value_if_present (fn, &fn))
-    fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
-                                                        void_list_node));
+    fn = push_throw_library_fn (fn, build_function_type_list (ptr_type_node,
+                                                             NULL_TREE));
 
-  return build_cxx_call (fn, NULL_TREE);
+  return build_cxx_call (fn, 0, NULL);
 }
 
 /* Return an expression for "__cxa_bad_typeid()".  The expression
@@ -210,11 +223,11 @@ throw_bad_typeid (void)
       tree t;
 
       t = build_reference_type (const_type_info_type_node);
-      t = build_function_type (t, void_list_node);
+      t = build_function_type_list (t, NULL_TREE);
       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"
@@ -228,16 +241,20 @@ get_tinfo_decl_dynamic (tree exp)
   tree type;
   tree t;
 
-  if (exp == error_mark_node)
+  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 (!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)
@@ -259,12 +276,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));
 
-  return build_indirect_ref (t, NULL);
+  return cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
 }
 
 static bool
 typeid_ok_p (void)
 {
+  tree pseudo_type_info, type_info_type;
+
   if (! flag_rtti)
     {
       error ("cannot use typeid with -fno-rtti");
@@ -277,6 +296,18 @@ typeid_ok_p (void)
       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;
 }
 
@@ -286,7 +317,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 ())
@@ -295,12 +326,17 @@ build_typeid (tree exp)
   if (processing_template_decl)
     return build_min (TYPEID_EXPR, const_type_info_type_node, exp);
 
+  /* FIXME when integrating with c_fully_fold, mark
+     resolves_to_fixed_type_p case as a non-constant expression.  */
   if (TREE_CODE (exp) == INDIRECT_REF
       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
       && TYPE_POLYMORPHIC_P (TREE_TYPE (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));
     }
@@ -316,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
@@ -342,11 +394,10 @@ get_tinfo_decl (tree type)
   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 "
-            "its size is variable",
+            "it involves types of variable size",
             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;
+      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;
-      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);
@@ -430,13 +482,16 @@ get_typeid (tree 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;
 
-  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
@@ -456,7 +511,7 @@ ifnonnull (tree test, tree result)
    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);
@@ -464,6 +519,9 @@ build_dynamic_cast_1 (tree type, tree expr)
   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)
@@ -473,20 +531,20 @@ build_dynamic_cast_1 (tree type, tree expr)
        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))))
        {
-         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;
     }
 
@@ -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.  */
 
+      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 (! 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))))
        {
-         errstr = "source is a pointer to incomplete type";
+         errstr = _("source is a pointer to incomplete type");
          goto fail;
        }
     }
   else
     {
-      /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
+      expr = mark_lvalue_use (expr);
+
       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.  */
 
-      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))))
        {
-         errstr = "source is of incomplete class type";
+         errstr = _("source is of incomplete class type");
          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)))
     {
-      errstr = "conversion casts away constness";
+      errstr = _("conversion casts away constness");
       goto fail;
     }
 
@@ -584,7 +646,8 @@ build_dynamic_cast_1 (tree type, tree expr)
       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,
@@ -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 ();
-                 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;
@@ -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)
                {
-                 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;
                }
            }
 
+         /* 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);
-         td2 = build_unary_op (ADDR_EXPR, td2, 0);
+         td2 = cp_build_addr_expr (td2, complain);
          td3 = get_tinfo_decl (static_type);
          mark_used (td3);
-         td3 = build_unary_op (ADDR_EXPR, td3, 0);
+         td3 = cp_build_addr_expr (td3, complain);
 
          /* Determine how T and V are related.  */
          boff = dcast_base_hint (static_type, target_type);
@@ -633,50 +706,50 @@ build_dynamic_cast_1 (tree type, tree expr)
 
          expr1 = expr;
          if (tc == REFERENCE_TYPE)
-           expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
+           expr1 = cp_build_addr_expr (expr1, 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;
-             tree ns = abi_node;
              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 = build_pointer_type
-               (build_qualified_type
+               (cp_build_qualified_type
                 (tinfo_ptr, TYPE_QUAL_CONST));
              name = "__dynamic_cast";
-             tmp = tree_cons
-               (NULL_TREE, const_ptr_type_node, tree_cons
-                (NULL_TREE, tinfo_ptr, tree_cons
-                 (NULL_TREE, tinfo_ptr, tree_cons
-                  (NULL_TREE, ptrdiff_type_node, void_list_node))));
-             tmp = build_function_type (ptr_type_node, tmp);
+             tmp = build_function_type_list (ptr_type_node,
+                                             const_ptr_type_node,
+                                             tinfo_ptr, tinfo_ptr,
+                                             ptrdiff_type_node, NULL_TREE);
              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;
            }
-         result = build_cxx_call (dcast_fn, elems);
+         result = build_cxx_call (dcast_fn, 4, elems);
 
          if (tc == REFERENCE_TYPE)
            {
              tree bad = throw_bad_cast ();
+             tree neq;
 
              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*.  */
@@ -685,16 +758,17 @@ build_dynamic_cast_1 (tree type, tree expr)
        }
     }
   else
-    errstr = "source type is not polymorphic";
+    errstr = _("source type is not polymorphic");
 
  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
-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;
@@ -703,11 +777,10 @@ build_dynamic_cast (tree type, tree expr)
     {
       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.  */
@@ -787,18 +860,18 @@ involves_incomplete_p (tree type)
 static tree
 tinfo_base_init (tinfo_s *ti, tree target)
 {
-  tree init = NULL_TREE;
+  tree init;
   tree name_decl;
   tree vtable_ptr;
+  VEC(constructor_elt,gc) *v;
 
   {
-    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),
+                    (cp_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.  */
@@ -813,14 +886,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;
-    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);
+    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);
@@ -830,10 +898,10 @@ tinfo_base_init (tinfo_s *ti, tree target)
   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);
-      pop_nested_namespace (abi_node);
+      pop_abi_namespace ();
 
       if (!COMPLETE_TYPE_P (real_type))
        {
@@ -845,27 +913,25 @@ tinfo_base_init (tinfo_s *ti, tree target)
        }
 
       vtable_ptr = get_vtable_decl (real_type, /*complete=*/1);
-      vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0);
+      vtable_ptr = cp_build_addr_expr (vtable_ptr, tf_warning_or_error);
 
       /* 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)));
-      
+
       ti->vtable = vtable_ptr;
     }
 
-  init = tree_cons (NULL_TREE, vtable_ptr, init);
+  v = VEC_alloc (constructor_elt, gc, 2);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, vtable_ptr);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, decay_conversion (name_decl));
 
-  init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
-
-  init = build_constructor_from_list (NULL_TREE, nreverse (init));
+  init = build_constructor (init_list_type_node, v);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
-  init = tree_cons (NULL_TREE, init, NULL_TREE);
 
   return init;
 }
@@ -878,10 +944,9 @@ static tree
 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_single (init_list_type_node, NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -897,17 +962,17 @@ ptr_initializer (tinfo_s *ti, tree target)
   tree to = TREE_TYPE (target);
   int flags = qualifier_flags (to);
   bool incomplete = target_incomplete_p (to);
+  VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 3);
 
   if (incomplete)
     flags |= 8;
-  init = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), init);
-  init = tree_cons (NULL_TREE,
-                   get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
-                   init);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+                          get_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
 
-  init = build_constructor_from_list (NULL_TREE, nreverse (init));
+  init = build_constructor (init_list_type_node, v);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -925,39 +990,44 @@ ptm_initializer (tinfo_s *ti, tree target)
   tree klass = TYPE_PTRMEM_CLASS_TYPE (target);
   int flags = qualifier_flags (to);
   bool incomplete = target_incomplete_p (to);
+  VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4);
 
   if (incomplete)
     flags |= 0x8;
   if (!COMPLETE_TYPE_P (klass))
     flags |= 0x10;
-  init = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), init);
-  init = tree_cons (NULL_TREE,
-                   get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
-                   init);
-  init = tree_cons (NULL_TREE,
-                   get_tinfo_ptr (klass),
-                   init);
-  
-  init = build_constructor_from_list (NULL_TREE, nreverse (init));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+                          get_tinfo_ptr (TYPE_MAIN_VARIANT (to)));
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_tinfo_ptr (klass));
+
+  init = build_constructor (init_list_type_node, v);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
 
 /* Return the CONSTRUCTOR expr for a type_info of class TYPE.
    TI provides information about the particular __class_type_info derivation,
-   which adds hint flags and TRAIL initializers to the type_info base.  */
+   which adds hint flags and N extra initializers to the type_info base.  */
 
 static tree
-class_initializer (tinfo_s *ti, tree target, tree trail)
+class_initializer (tinfo_s *ti, tree target, unsigned n, ...)
 {
   tree init = tinfo_base_init (ti, target);
+  va_list extra_inits;
+  unsigned i;
+  VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, n+1);
 
-  TREE_CHAIN (init) = trail;
-  init = build_constructor_from_list (NULL_TREE, init);
+  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
+  va_start (extra_inits, n);
+  for (i = 0; i < n; i++)
+    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, va_arg (extra_inits, tree));
+  va_end (extra_inits);
+
+  init = build_constructor (init_list_type_node, v);
   TREE_CONSTANT (init) = 1;
-  TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
   return init;
 }
@@ -979,11 +1049,14 @@ typeinfo_in_lib_p (tree type)
     {
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
-    case CHAR_TYPE:
     case REAL_TYPE:
     case VOID_TYPE:
+    case NULLPTR_TYPE:
       return true;
 
+    case LANG_TYPE:
+      /* fall through.  */
+
     default:
       return false;
     }
@@ -996,16 +1069,16 @@ static tree
 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);
-      
+
     case TK_POINTER_TYPE:
       return ptr_initializer (ti, type);
-      
+
     case TK_BUILTIN_TYPE:
     case TK_ENUMERAL_TYPE:
     case TK_FUNCTION_TYPE:
@@ -1013,15 +1086,16 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
       return generic_initializer (ti, type);
 
     case TK_CLASS_TYPE:
-      return class_initializer (ti, type, NULL_TREE);
+      return class_initializer (ti, type, 0);
 
     case TK_SI_CLASS_TYPE:
       {
        tree base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), 0);
        tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
-       tree base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE);
-       
-       return class_initializer (ti, type, base_inits);
+
+       /* get_tinfo_ptr might have reallocated the tinfo_descs vector.  */
+       ti = VEC_index (tinfo_s, tinfo_descs, tk_index);
+       return class_initializer (ti, type, 1, tinfo);
       }
 
     default:
@@ -1031,55 +1105,62 @@ 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 offset_type = integer_types[itk_long];
        tree base_inits = NULL_TREE;
        int ix;
-          
+       VEC(constructor_elt,gc) *init_vec = NULL;
+       constructor_elt *e;
+
        gcc_assert (tk_index >= TK_FIXED);
-      
+
+       VEC_safe_grow (constructor_elt, gc, init_vec, nbases);
        /* Generate the base information initializer.  */
        for (ix = nbases; ix--;)
          {
            tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
-           tree base_init = NULL_TREE;
+           tree base_init;
            int flags = 0;
            tree tinfo;
            tree offset;
-           
+           VEC(constructor_elt,gc) *v;
+
            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 = convert (sizetype, offset);
                flags |= 1;
              }
            else
              offset = BINFO_OFFSET (base_binfo);
-           
+
            /* 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));
-           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_inits = tree_cons (NULL_TREE, base_init, base_inits);
+           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));
+           v = VEC_alloc (constructor_elt, gc, 2);
+           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo);
+           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset);
+           base_init = build_constructor (init_list_type_node, v);
+           e = VEC_index (constructor_elt, init_vec, ix);
+           e->index = NULL_TREE;
+           e->value = base_init;
          }
-       base_inits = build_constructor_from_list (NULL_TREE, base_inits);
-       base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
-       /* Prepend the number of bases.  */
-       base_inits = tree_cons (NULL_TREE,
-                               build_int_cst (NULL_TREE, nbases),
-                               base_inits);
-       /* Prepend the hint flags.  */
-       base_inits = tree_cons (NULL_TREE,
-                               build_int_cst (NULL_TREE, hint),
-                               base_inits);
-       return class_initializer (ti, type, base_inits);
+       base_inits = build_constructor (init_list_type_node, init_vec);
+
+       /* get_tinfo_ptr might have reallocated the tinfo_descs vector.  */
+       ti = VEC_index (tinfo_s, tinfo_descs, tk_index);
+       return class_initializer (ti, type, 3,
+                                 build_int_cst (NULL_TREE, hint),
+                                 build_int_cst (NULL_TREE, nbases),
+                                 base_inits);
       }
     }
 }
@@ -1112,26 +1193,27 @@ create_pseudo_type_info (int tk, const char *real_name, ...)
   va_start (ap, real_name);
 
   /* Generate the pseudo type name.  */
-  pseudo_name = alloca (strlen (real_name) + 30);
+  pseudo_name = (char *) alloca (strlen (real_name) + 30);
   strcpy (pseudo_name, real_name);
   strcat (pseudo_name, "_pseudo");
   if (tk >= TK_FIXED)
     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);
 
   /* Now add the derived fields.  */
   while ((field_decl = va_arg (ap, tree)))
     {
-      TREE_CHAIN (field_decl) = fields;
+      DECL_CHAIN (field_decl) = fields;
       fields = field_decl;
     }
 
   /* 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;
 
@@ -1140,6 +1222,10 @@ create_pseudo_type_info (int tk, const char *real_name, ...)
   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);
 }
 
@@ -1151,29 +1237,29 @@ static unsigned
 get_pseudo_ti_index (tree type)
 {
   unsigned ix;
-  
+
   switch (TREE_CODE (type))
     {
     case OFFSET_TYPE:
       ix = TK_POINTER_MEMBER_TYPE;
       break;
-      
+
     case POINTER_TYPE:
       ix = TK_POINTER_TYPE;
       break;
-      
+
     case ENUMERAL_TYPE:
       ix = TK_ENUMERAL_TYPE;
       break;
-      
+
     case FUNCTION_TYPE:
       ix = TK_FUNCTION_TYPE;
       break;
-      
+
     case ARRAY_TYPE:
       ix = TK_ARRAY_TYPE;
       break;
-      
+
     case UNION_TYPE:
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (type))
@@ -1219,7 +1305,7 @@ get_pseudo_ti_index (tree type)
                {
                  /* 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;
@@ -1241,14 +1327,17 @@ get_pseudo_ti_index (tree type)
                                             TK_BASE_TYPE)->type,
                                  array_domain);
 
-             push_nested_namespace (abi_node);
+             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_nested_namespace (abi_node);
+             pop_abi_namespace ();
              break;
            }
        }
@@ -1266,32 +1355,33 @@ static void
 create_tinfo_types (void)
 {
   tinfo_s *ti;
-  
+
   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;
 
-    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);
-    TREE_CHAIN (field) = fields;
+    field = build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, const_string_type_node);
+    DECL_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);
-    TYPE_HAS_CONSTRUCTOR (ti->type) = 1;
   }
 
   /* Fundamental type_info */
@@ -1301,44 +1391,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);
-  
+
   /* 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",
-            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;
 
-    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]);
-    TREE_CHAIN (field) = fields;
+    field = build_decl (BUILTINS_LOCATION,
+                       FIELD_DECL, NULL_TREE, integer_types[itk_long]);
+    DECL_CHAIN (field) = fields;
     fields = field;
-  
+
     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);
-    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",
-       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,
@@ -1346,12 +1440,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",
-        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
@@ -1363,27 +1460,32 @@ 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,
+    &int128_integer_type_node, &int128_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;
 
-  push_nested_namespace (abi_node);
+  push_abi_namespace ();
   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);
@@ -1396,10 +1498,12 @@ emit_support_tinfos (void)
       tree types[3];
       int i;
 
+      if (bltn == NULL_TREE)
+       continue;
       types[0] = bltn;
       types[1] = build_pointer_type (bltn);
-      types[2] = build_pointer_type (build_qualified_type (bltn,
-                                                          TYPE_QUAL_CONST));
+      types[2] = build_pointer_type (cp_build_qualified_type (bltn,
+                                                             TYPE_QUAL_CONST));
 
       for (i = 0; i < 3; ++i)
        {
@@ -1414,8 +1518,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
-            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;
@@ -1466,12 +1573,12 @@ emit_tinfo_decl (tree decl)
   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);
-      cp_finish_decl (decl, init, NULL_TREE, 0);
+      cp_finish_decl (decl, init, false, NULL_TREE, 0);
       return true;
     }
   else