]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/cp/tree.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / cp / tree.c
index cdfa49c4572704c8643e0caadd2a8206bc7849f5..45e0c33bd5827917a4403a92d3c554c3f1431c2d 100644 (file)
 /* Language-dependent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+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.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
-#include "obstack.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "cp-tree.h"
 #include "flags.h"
+#include "real.h"
 #include "rtl.h"
 #include "toplev.h"
-#include "ggc.h"
 #include "insn-config.h"
 #include "integrate.h"
 #include "tree-inline.h"
-
-static tree bot_manip PARAMS ((tree *, int *, void *));
-static tree bot_replace PARAMS ((tree *, int *, void *));
-static tree build_cplus_array_type_1 PARAMS ((tree, tree));
-static int list_hash_eq PARAMS ((const void *, const void *));
-static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
-static hashval_t list_hash PARAMS ((const void *));
-static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
-static tree no_linkage_helper PARAMS ((tree *, int *, void *));
-static tree build_srcloc PARAMS ((const char *, int));
-static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
-static tree cp_unsave_r PARAMS ((tree *, int *, void *));
-static void cp_unsave PARAMS ((tree *));
-static tree build_target_expr PARAMS ((tree, tree));
-static tree count_trees_r PARAMS ((tree *, int *, void *));
-static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
-static tree find_tree_r PARAMS ((tree *, int *, void *));
-extern int cp_statement_code_p PARAMS ((enum tree_code));
-
-static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, bool *));
+#include "debug.h"
+#include "target.h"
+#include "convert.h"
+#include "tree-flow.h"
+
+static tree bot_manip (tree *, int *, void *);
+static tree bot_replace (tree *, int *, void *);
+static tree build_cplus_array_type_1 (tree, tree);
+static int list_hash_eq (const void *, const void *);
+static hashval_t list_hash_pieces (tree, tree, tree);
+static hashval_t list_hash (const void *);
+static cp_lvalue_kind lvalue_p_1 (tree);
+static tree build_target_expr (tree, tree);
+static tree count_trees_r (tree *, int *, void *);
+static tree verify_stmt_tree_r (tree *, int *, void *);
+static tree build_local_temp (tree);
+
+static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
+static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
+static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
 
 /* If REF is an lvalue, returns the kind of lvalue that REF is.
-   Otherwise, returns clk_none.  If TREAT_CLASS_RVALUES_AS_LVALUES is
-   non-zero, rvalues of class type are considered lvalues.  */
+   Otherwise, returns clk_none.  */
 
 static cp_lvalue_kind
-lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
-     tree ref;
-     int treat_class_rvalues_as_lvalues;
+lvalue_p_1 (tree ref)
 {
   cp_lvalue_kind op1_lvalue_kind = clk_none;
   cp_lvalue_kind op2_lvalue_kind = clk_none;
 
+  /* Expressions of reference type are sometimes wrapped in
+     INDIRECT_REFs.  INDIRECT_REFs are just internal compiler
+     representation, not part of the language, so we have to look
+     through them.  */
+  if (TREE_CODE (ref) == INDIRECT_REF
+      && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0)))
+         == REFERENCE_TYPE)
+    return lvalue_p_1 (TREE_OPERAND (ref, 0));
+
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
-    return clk_ordinary;
+    {
+      /* unnamed rvalue references are rvalues */
+      if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref))
+         && TREE_CODE (ref) != PARM_DECL
+         && TREE_CODE (ref) != VAR_DECL
+         && TREE_CODE (ref) != COMPONENT_REF)
+       return clk_rvalueref;
+
+      /* lvalue references and named rvalue references are lvalues.  */
+      return clk_ordinary;
+    }
 
   if (ref == current_class_ptr)
     return clk_none;
 
   switch (TREE_CODE (ref))
     {
+    case SAVE_EXPR:
+      return clk_none;
       /* preincrements and predecrements are valid lvals, provided
         what they refer to are valid lvals.  */
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
-    case SAVE_EXPR:
-    case UNSAVE_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
-      /* This shouldn't be here, but there are lots of places in the compiler
-         that are sloppy about tacking on NOP_EXPRs to the same type when
-        no actual conversion is happening.  */
-    case NOP_EXPR:
-      return lvalue_p_1 (TREE_OPERAND (ref, 0),
-                        treat_class_rvalues_as_lvalues);
+      return lvalue_p_1 (TREE_OPERAND (ref, 0));
 
     case COMPONENT_REF:
-      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
-                                   treat_class_rvalues_as_lvalues);
-      if (op1_lvalue_kind 
-         /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
-            situations.  */
-         && TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
-         && DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
+      /* Look at the member designator.  */
+      if (!op1_lvalue_kind)
+       ;
+      else if (is_overloaded_fn (TREE_OPERAND (ref, 1)))
+       /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
+          situations.  If we're seeing a COMPONENT_REF, it's a non-static
+          member, so it isn't an lvalue. */
+       op1_lvalue_kind = clk_none;
+      else if (TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+       /* This can be IDENTIFIER_NODE in a template.  */;
+      else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
        {
          /* Clear the ordinary bit.  If this object was a class
             rvalue we want to preserve that information.  */
          op1_lvalue_kind &= ~clk_ordinary;
-         /* The lvalue is for a btifield.  */
+         /* The lvalue is for a bitfield.  */
          op1_lvalue_kind |= clk_bitfield;
        }
+      else if (DECL_PACKED (TREE_OPERAND (ref, 1)))
+       op1_lvalue_kind |= clk_packed;
+
       return op1_lvalue_kind;
 
     case STRING_CST:
+    case COMPOUND_LITERAL_EXPR:
       return clk_ordinary;
 
+    case CONST_DECL:
+      /* CONST_DECL without TREE_STATIC are enumeration values and
+        thus not lvalues.  With TREE_STATIC they are used by ObjC++
+        in objc_build_string_object and need to be considered as
+        lvalues.  */
+      if (! TREE_STATIC (ref))
+       return clk_none;
     case VAR_DECL:
       if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
          && DECL_LANG_SPECIFIC (ref)
@@ -127,48 +153,59 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
 
       /* A currently unresolved scope ref.  */
     case SCOPE_REF:
-      abort ();
-    case OFFSET_REF:
-      if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
-       return clk_ordinary;
-      /* Fall through.  */
+      gcc_unreachable ();
     case MAX_EXPR:
     case MIN_EXPR:
-      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
-                                   treat_class_rvalues_as_lvalues);
-      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
-                                   treat_class_rvalues_as_lvalues);
+      /* Disallow <? and >? as lvalues if either argument side-effects.  */
+      if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
+         || TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
+       return clk_none;
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
+      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1));
       break;
 
     case COND_EXPR:
-      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
-                                   treat_class_rvalues_as_lvalues);
-      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
-                                   treat_class_rvalues_as_lvalues);
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1)
+                                   ? TREE_OPERAND (ref, 1)
+                                   : TREE_OPERAND (ref, 0));
+      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2));
       break;
 
     case MODIFY_EXPR:
       return clk_ordinary;
 
     case COMPOUND_EXPR:
-      return lvalue_p_1 (TREE_OPERAND (ref, 1),
-                        treat_class_rvalues_as_lvalues);
+      return lvalue_p_1 (TREE_OPERAND (ref, 1));
 
     case TARGET_EXPR:
-      return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
+      return clk_class;
 
-    case CALL_EXPR:
     case VA_ARG_EXPR:
-      return ((treat_class_rvalues_as_lvalues
-              && IS_AGGR_TYPE (TREE_TYPE (ref)))
-             ? clk_class : clk_none);
+      return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
+
+    case CALL_EXPR:
+      /* Any class-valued call would be wrapped in a TARGET_EXPR.  */
+      return clk_none;
 
     case FUNCTION_DECL:
       /* All functions (except non-static-member functions) are
         lvalues.  */
-      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref) 
+      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
              ? clk_none : clk_ordinary);
 
+    case BASELINK:
+      /* We now represent a reference to a single static member function
+        with a BASELINK.  */
+      return lvalue_p_1 (BASELINK_FUNCTIONS (ref));
+
+    case NON_DEPENDENT_EXPR:
+      /* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
+        things like "&E" where "E" is an expression with a
+        non-dependent type work. It is safe to be lenient because an
+        error will be issued when the template is instantiated if "E"
+        is not an lvalue.  */
+      return clk_ordinary;
+
     default:
       break;
     }
@@ -188,54 +225,69 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
   return op1_lvalue_kind;
 }
 
-/* If REF is an lvalue, returns the kind of lvalue that REF is.
-   Otherwise, returns clk_none.  Lvalues can be assigned, unless they
-   have TREE_READONLY, or unless they are FUNCTION_DECLs.  Lvalues can
-   have their address taken, unless they have DECL_REGISTER.  */
+/* Returns the kind of lvalue that REF is, in the sense of
+   [basic.lval].  This function should really be named lvalue_p; it
+   computes the C++ definition of lvalue.  */
 
 cp_lvalue_kind
-real_lvalue_p (ref)
-     tree ref;
+real_lvalue_p (tree ref)
 {
-  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+  cp_lvalue_kind kind = lvalue_p_1 (ref);
+  if (kind & (clk_rvalueref|clk_class))
+    return clk_none;
+  else
+    return kind;
 }
 
-/* This differs from real_lvalue_p in that class rvalues are
-   considered lvalues.  */
+/* This differs from real_lvalue_p in that class rvalues are considered
+   lvalues.  */
 
 int
-lvalue_p (ref)
-     tree ref;
+lvalue_p (tree ref)
 {
-  return 
-    (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
+  return (lvalue_p_1 (ref) != clk_none);
 }
 
-/* Return nonzero if REF is an lvalue valid for this language;
-   otherwise, print an error message and return zero.  */
+/* This differs from real_lvalue_p in that rvalues formed by dereferencing
+   rvalue references are considered rvalues.  */
 
-int
-lvalue_or_else (ref, string)
-     tree ref;
-     const char *string;
+bool
+lvalue_or_rvalue_with_address_p (tree ref)
+{
+  cp_lvalue_kind kind = lvalue_p_1 (ref);
+  if (kind & clk_class)
+    return false;
+  else
+    return (kind != clk_none);
+}
+
+/* Test whether DECL is a builtin that may appear in a
+   constant-expression. */
+
+bool
+builtin_valid_in_constant_expr_p (const_tree decl)
 {
-  int win = lvalue_p (ref);
-  if (! win)
-    error ("non-lvalue in %s", string);
-  return win;
+  /* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
+     in constant-expressions.  We may want to add other builtins later. */
+  return DECL_IS_BUILTIN_CONSTANT_P (decl);
 }
 
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
 
 static tree
-build_target_expr (decl, value)
-     tree decl;
-     tree value;
+build_target_expr (tree decl, tree value)
 {
   tree t;
 
-  t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value, 
-            maybe_build_cleanup (decl), NULL_TREE);
+#ifdef ENABLE_CHECKING
+  gcc_assert (VOID_TYPE_P (TREE_TYPE (value))
+             || TREE_TYPE (decl) == TREE_TYPE (value)
+             || useless_type_conversion_p (TREE_TYPE (decl),
+                                           TREE_TYPE (value)));
+#endif
+
+  t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
+             cxx_maybe_build_cleanup (decl), NULL_TREE);
   /* We always set TREE_SIDE_EFFECTS so that expand_expr does not
      ignore the TARGET_EXPR.  If there really turn out to be no
      side-effects, then the optimizer should be able to get rid of
@@ -245,33 +297,98 @@ build_target_expr (decl, value)
   return t;
 }
 
-/* INIT is a CALL_EXPR which needs info about its target.
-   TYPE is the type that this initialization should appear to have.
+/* Return an undeclared local temporary of type TYPE for use in building a
+   TARGET_EXPR.  */
 
-   Build an encapsulation of the initialization to perform
-   and return it so that it can be processed by language-independent
-   and language-specific expression expanders.  */
+static tree
+build_local_temp (tree type)
+{
+  tree slot = build_decl (VAR_DECL, NULL_TREE, type);
+  DECL_ARTIFICIAL (slot) = 1;
+  DECL_IGNORED_P (slot) = 1;
+  DECL_CONTEXT (slot) = current_function_decl;
+  layout_decl (slot, 0);
+  return slot;
+}
+
+/* Set various status flags when building an AGGR_INIT_EXPR object T.  */
+
+static void
+process_aggr_init_operands (tree t)
+{
+  bool side_effects;
+
+  side_effects = TREE_SIDE_EFFECTS (t);
+  if (!side_effects)
+    {
+      int i, n;
+      n = TREE_OPERAND_LENGTH (t);
+      for (i = 1; i < n; i++)
+       {
+         tree op = TREE_OPERAND (t, i);
+         if (op && TREE_SIDE_EFFECTS (op))
+           {
+             side_effects = 1;
+             break;
+           }
+       }
+    }
+  TREE_SIDE_EFFECTS (t) = side_effects;
+}
+
+/* Build an AGGR_INIT_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE,
+   FN, and SLOT.  NARGS is the number of call arguments which are specified
+   as a tree array ARGS.  */
+
+static tree
+build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
+                      tree *args)
+{
+  tree t;
+  int i;
+
+  t = build_vl_exp (AGGR_INIT_EXPR, nargs + 3);
+  TREE_TYPE (t) = return_type;
+  AGGR_INIT_EXPR_FN (t) = fn;
+  AGGR_INIT_EXPR_SLOT (t) = slot;
+  for (i = 0; i < nargs; i++)
+    AGGR_INIT_EXPR_ARG (t, i) = args[i];
+  process_aggr_init_operands (t);
+  return t;
+}
+
+/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+   target.  TYPE is the type to be initialized.
+
+   Build an AGGR_INIT_EXPR to represent the initialization.  This function
+   differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
+   to initialize another object, whereas a TARGET_EXPR can either
+   initialize another object or create its own temporary object, and as a
+   result building up a TARGET_EXPR requires that the type's destructor be
+   callable.  */
 
 tree
-build_cplus_new (type, init)
-     tree type;
-     tree init;
+build_aggr_init_expr (tree type, tree init)
 {
   tree fn;
   tree slot;
   tree rval;
+  int is_ctor;
 
   /* Make sure that we're not trying to create an instance of an
      abstract class.  */
   abstract_virtuals_error (NULL_TREE, type);
 
-  if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
+  if (TREE_CODE (init) == CALL_EXPR)
+    fn = CALL_EXPR_FN (init);
+  else if (TREE_CODE (init) == AGGR_INIT_EXPR)
+    fn = AGGR_INIT_EXPR_FN (init);
+  else
     return convert (type, init);
 
-  slot = build (VAR_DECL, type);
-  DECL_ARTIFICIAL (slot) = 1;
-  DECL_CONTEXT (slot) = current_function_decl;
-  layout_decl (slot, 0);
+  is_ctor = (TREE_CODE (fn) == ADDR_EXPR
+            && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+            && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
 
   /* We split the CALL_EXPR into its function and its arguments here.
      Then, in expand_expr, we put them back together.  The reason for
@@ -281,218 +398,260 @@ build_cplus_new (type, init)
      replaces every AGGR_INIT_EXPR with a copy that uses a fresh
      temporary slot.  Then, expand_expr builds up a call-expression
      using the new slot.  */
-  fn = TREE_OPERAND (init, 0);
-  rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
-  TREE_SIDE_EFFECTS (rval) = 1;
-  AGGR_INIT_VIA_CTOR_P (rval) 
-    = (TREE_CODE (fn) == ADDR_EXPR
-       && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
-       && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
+
+  /* If we don't need to use a constructor to create an object of this
+     type, don't mess with AGGR_INIT_EXPR.  */
+  if (is_ctor || TREE_ADDRESSABLE (type))
+    {
+      slot = build_local_temp (type);
+
+      if (TREE_CODE(init) == CALL_EXPR)
+       rval = build_aggr_init_array (void_type_node, fn, slot,
+                                     call_expr_nargs (init),
+                                     CALL_EXPR_ARGP (init));
+      else
+       rval = build_aggr_init_array (void_type_node, fn, slot,
+                                     aggr_init_expr_nargs (init),
+                                     AGGR_INIT_EXPR_ARGP (init));
+      TREE_SIDE_EFFECTS (rval) = 1;
+      AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
+    }
+  else
+    rval = init;
+
+  return rval;
+}
+
+/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+   target.  TYPE is the type that this initialization should appear to
+   have.
+
+   Build an encapsulation of the initialization to perform
+   and return it so that it can be processed by language-independent
+   and language-specific expression expanders.  */
+
+tree
+build_cplus_new (tree type, tree init)
+{
+  tree rval = build_aggr_init_expr (type, init);
+  tree slot;
+
+  if (TREE_CODE (rval) == AGGR_INIT_EXPR)
+    slot = AGGR_INIT_EXPR_SLOT (rval);
+  else if (TREE_CODE (rval) == CALL_EXPR)
+    slot = build_local_temp (type);
+  else
+    return rval;
+
   rval = build_target_expr (slot, rval);
+  TARGET_EXPR_IMPLICIT_P (rval) = 1;
 
   return rval;
 }
 
-/* Buidl a TARGET_EXPR using INIT to initialize a new temporary of the
+/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
    indicated TYPE.  */
 
 tree
-build_target_expr_with_type (init, type)
-     tree init;
-     tree type;
+build_target_expr_with_type (tree init, tree type)
 {
-  tree slot;
-  tree rval;
+  gcc_assert (!VOID_TYPE_P (type));
 
   if (TREE_CODE (init) == TARGET_EXPR)
     return init;
+  else if (CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_INIT_REF (type)
+          && !VOID_TYPE_P (TREE_TYPE (init))
+          && TREE_CODE (init) != COND_EXPR
+          && TREE_CODE (init) != CONSTRUCTOR
+          && TREE_CODE (init) != VA_ARG_EXPR)
+    /* We need to build up a copy constructor call.  A void initializer
+       means we're being called from bot_manip.  COND_EXPR is a special
+       case because we already have copies on the arms and we don't want
+       another one here.  A CONSTRUCTOR is aggregate initialization, which
+       is handled separately.  A VA_ARG_EXPR is magic creation of an
+       aggregate; there's no additional work to be done.  */
+    return force_rvalue (init);
+
+  return force_target_expr (type, init);
+}
+
+/* Like the above function, but without the checking.  This function should
+   only be used by code which is deliberately trying to subvert the type
+   system, such as call_builtin_trap.  */
 
-  slot = build (VAR_DECL, type);
-  DECL_ARTIFICIAL (slot) = 1;
-  DECL_CONTEXT (slot) = current_function_decl;
-  layout_decl (slot, 0);
-  rval = build_target_expr (slot, init);
+tree
+force_target_expr (tree type, tree init)
+{
+  tree slot;
 
-  return rval;
+  gcc_assert (!VOID_TYPE_P (type));
+
+  slot = build_local_temp (type);
+  return build_target_expr (slot, init);
 }
 
 /* Like build_target_expr_with_type, but use the type of INIT.  */
 
 tree
-get_target_expr (init)
-     tree init;
+get_target_expr (tree init)
 {
-  return build_target_expr_with_type (init, TREE_TYPE (init));
+  if (TREE_CODE (init) == AGGR_INIT_EXPR)
+    return build_target_expr (AGGR_INIT_EXPR_SLOT (init), init);
+  else
+    return build_target_expr_with_type (init, TREE_TYPE (init));
 }
 
-/* Recursively perform a preorder search EXP for CALL_EXPRs, making
-   copies where they are found.  Returns a deep copy all nodes transitively
-   containing CALL_EXPRs.  */
+/* If EXPR is a bitfield reference, convert it to the declared type of
+   the bitfield, and return the resulting expression.  Otherwise,
+   return EXPR itself.  */
 
 tree
-break_out_calls (exp)
-     tree exp;
+convert_bitfield_to_declared_type (tree expr)
 {
-  register tree t1, t2 = NULL_TREE;
-  register enum tree_code code;
-  register int changed = 0;
-  register int i;
+  tree bitfield_type;
 
-  if (exp == NULL_TREE)
-    return exp;
-
-  code = TREE_CODE (exp);
-
-  if (code == CALL_EXPR)
-    return copy_node (exp);
-
-  /* Don't try and defeat a save_expr, as it should only be done once.  */
-    if (code == SAVE_EXPR)
-       return exp;
+  bitfield_type = is_bitfield_expr_with_lowered_type (expr);
+  if (bitfield_type)
+    expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
+                              expr);
+  return expr;
+}
 
-  switch (TREE_CODE_CLASS (code))
-    {
-    default:
-      abort ();
+/* EXPR is being used in an rvalue context.  Return a version of EXPR
+   that is marked as an rvalue.  */
 
-    case 'c':  /* a constant */
-    case 't':  /* a type node */
-    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
-      return exp;
+tree
+rvalue (tree expr)
+{
+  tree type;
 
-    case 'd':  /* A decl node */
-#if 0                               /* This is bogus.  jason 9/21/94 */
+  if (error_operand_p (expr))
+    return expr;
 
-      t1 = break_out_calls (DECL_INITIAL (exp));
-      if (t1 != DECL_INITIAL (exp))
-       {
-         exp = copy_node (exp);
-         DECL_INITIAL (exp) = t1;
-       }
-#endif
-      return exp;
+  /* [basic.lval]
 
-    case 'b':  /* A block node */
-      {
-       /* Don't know how to handle these correctly yet.   Must do a
-          break_out_calls on all DECL_INITIAL values for local variables,
-          and also break_out_calls on all sub-blocks and sub-statements.  */
-       abort ();
-      }
-      return exp;
+     Non-class rvalues always have cv-unqualified types.  */
+  type = TREE_TYPE (expr);
+  if (!CLASS_TYPE_P (type) && cp_type_quals (type))
+    type = TYPE_MAIN_VARIANT (type);
 
-    case 'e':  /* an expression */
-    case 'r':  /* a reference */
-    case 's':  /* an expression with side effects */
-      for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; i--)
-       {
-         t1 = break_out_calls (TREE_OPERAND (exp, i));
-         if (t1 != TREE_OPERAND (exp, i))
-           {
-             exp = copy_node (exp);
-             TREE_OPERAND (exp, i) = t1;
-           }
-       }
-      return exp;
-
-    case '<':  /* a comparison expression */
-    case '2':  /* a binary arithmetic expression */
-      t2 = break_out_calls (TREE_OPERAND (exp, 1));
-      if (t2 != TREE_OPERAND (exp, 1))
-       changed = 1;
-    case '1':  /* a unary arithmetic expression */
-      t1 = break_out_calls (TREE_OPERAND (exp, 0));
-      if (t1 != TREE_OPERAND (exp, 0))
-       changed = 1;
-      if (changed)
-       {
-         if (TREE_CODE_LENGTH (code) == 1)
-           return build1 (code, TREE_TYPE (exp), t1);
-         else
-           return build (code, TREE_TYPE (exp), t1, t2);
-       }
-      return exp;
-    }
+  /* We need to do this for rvalue refs as well to get the right answer
+     from decltype; see c++/36628.  */
+  if (!processing_template_decl && lvalue_or_rvalue_with_address_p (expr))
+    expr = build1 (NON_LVALUE_EXPR, type, expr);
+  else if (type != TREE_TYPE (expr))
+    expr = build_nop (type, expr);
 
+  return expr;
 }
+
 \f
-/* Construct, lay out and return the type of methods belonging to class
-   BASETYPE and whose arguments are described by ARGTYPES and whose values
-   are described by RETTYPE.  If each type exists already, reuse it.  */
+/* Hash an ARRAY_TYPE.  K is really of type `tree'.  */
 
-tree
-build_cplus_method_type (basetype, rettype, argtypes)
-     tree basetype, rettype, argtypes;
+static hashval_t
+cplus_array_hash (const void* k)
 {
-  register tree t;
-  tree ptype;
-  int hashcode;
+  hashval_t hash;
+  const_tree const t = (const_tree) k;
 
-  /* Make a node of the sort we want.  */
-  t = make_node (METHOD_TYPE);
+  hash = TYPE_UID (TREE_TYPE (t));
+  if (TYPE_DOMAIN (t))
+    hash ^= TYPE_UID (TYPE_DOMAIN (t));
+  return hash;
+}
 
-  TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
-  TREE_TYPE (t) = rettype;
-  ptype = build_pointer_type (basetype);
+typedef struct cplus_array_info {
+  tree type;
+  tree domain;
+} cplus_array_info;
 
-  /* The actual arglist for this function includes a "hidden" argument
-     which is "this".  Put it into the list of argument types.  */
-  argtypes = tree_cons (NULL_TREE, ptype, argtypes);
-  TYPE_ARG_TYPES (t) = argtypes;
-  TREE_SIDE_EFFECTS (argtypes) = 1;  /* Mark first argtype as "artificial".  */
+/* Compare two ARRAY_TYPEs.  K1 is really of type `tree', K2 is really
+   of type `cplus_array_info*'. */
 
-  /* If we already have such a type, use the old one and free this one.
-     Note that it also frees up the above cons cell if found.  */
-  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
-    type_hash_list (argtypes);
+static int
+cplus_array_compare (const void * k1, const void * k2)
+{
+  const_tree const t1 = (const_tree) k1;
+  const cplus_array_info *const t2 = (const cplus_array_info*) k2;
 
-  t = type_hash_canon (hashcode, t);
+  return (TREE_TYPE (t1) == t2->type && TYPE_DOMAIN (t1) == t2->domain);
+}
 
-  if (!COMPLETE_TYPE_P (t))
-    layout_type (t);
+/* Hash table containing all of the C++ array types, including
+   dependent array types and array types whose element type is
+   cv-qualified.  */
+static GTY ((param_is (union tree_node))) htab_t cplus_array_htab;
 
-  return t;
-}
 
 static tree
-build_cplus_array_type_1 (elt_type, index_type)
-     tree elt_type;
-     tree index_type;
+build_cplus_array_type_1 (tree elt_type, tree index_type)
 {
   tree t;
 
   if (elt_type == error_mark_node || index_type == error_mark_node)
     return error_mark_node;
 
-  /* Don't do the minimal thing just because processing_template_decl is
-     set; we want to give string constants the right type immediately, so
-     we don't have to fix them up at instantiation time.  */
-  if ((processing_template_decl
-       && index_type && TYPE_MAX_VALUE (index_type)
-       && TREE_CODE (TYPE_MAX_VALUE (index_type)) != INTEGER_CST)
-      || uses_template_parms (elt_type) 
-      || uses_template_parms (index_type))
+  if (processing_template_decl
+      && (dependent_type_p (elt_type)
+         || (index_type && !TREE_CONSTANT (TYPE_MAX_VALUE (index_type)))))
     {
-      t = make_node (ARRAY_TYPE);
-      TREE_TYPE (t) = elt_type;
-      TYPE_DOMAIN (t) = index_type;
+      void **e;
+      cplus_array_info cai;
+      hashval_t hash;
+
+      if (cplus_array_htab == NULL)
+       cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
+                                           &cplus_array_compare, NULL);
+      
+      hash = TYPE_UID (elt_type);
+      if (index_type)
+       hash ^= TYPE_UID (index_type);
+      cai.type = elt_type;
+      cai.domain = index_type;
+
+      e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash, INSERT); 
+      if (*e)
+       /* We have found the type: we're done.  */
+       return (tree) *e;
+      else
+       {
+         /* Build a new array type.  */
+         t = make_node (ARRAY_TYPE);
+         TREE_TYPE (t) = elt_type;
+         TYPE_DOMAIN (t) = index_type;
+
+         /* Store it in the hash table. */
+         *e = t;
+
+         /* Set the canonical type for this new node.  */
+         if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
+             || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type)))
+           SET_TYPE_STRUCTURAL_EQUALITY (t);
+         else if (TYPE_CANONICAL (elt_type) != elt_type
+                  || (index_type 
+                      && TYPE_CANONICAL (index_type) != index_type))
+           TYPE_CANONICAL (t)
+               = build_cplus_array_type 
+                  (TYPE_CANONICAL (elt_type),
+                   index_type ? TYPE_CANONICAL (index_type) : index_type);
+         else
+           TYPE_CANONICAL (t) = t;
+       }
     }
   else
     t = build_array_type (elt_type, index_type);
 
   /* Push these needs up so that initialization takes place
      more easily.  */
-  TYPE_NEEDS_CONSTRUCTING (t) 
+  TYPE_NEEDS_CONSTRUCTING (t)
     = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
-  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) 
+  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
     = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
   return t;
 }
 
 tree
-build_cplus_array_type (elt_type, index_type)
-     tree elt_type;
-     tree index_type;
+build_cplus_array_type (tree elt_type, tree index_type)
 {
   tree t;
   int type_quals = cp_type_quals (elt_type);
@@ -507,12 +666,75 @@ build_cplus_array_type (elt_type, index_type)
 
   return t;
 }
+
+/* Return an ARRAY_TYPE with element type ELT and length N.  */
+
+tree
+build_array_of_n_type (tree elt, int n)
+{
+  return build_cplus_array_type (elt, build_index_type (size_int (n - 1)));
+}
+
+/* Return a reference type node referring to TO_TYPE.  If RVAL is
+   true, return an rvalue reference type, otherwise return an lvalue
+   reference type.  If a type node exists, reuse it, otherwise create
+   a new one.  */
+tree
+cp_build_reference_type (tree to_type, bool rval)
+{
+  tree lvalue_ref, t;
+  lvalue_ref = build_reference_type (to_type);
+  if (!rval)
+    return lvalue_ref;
+
+  /* This code to create rvalue reference types is based on and tied
+     to the code creating lvalue reference types in the middle-end
+     functions build_reference_type_for_mode and build_reference_type.
+
+     It works by putting the rvalue reference type nodes after the
+     lvalue reference nodes in the TYPE_NEXT_REF_TO linked list, so
+     they will effectively be ignored by the middle end.  */
+
+  for (t = lvalue_ref; (t = TYPE_NEXT_REF_TO (t)); )
+    if (TYPE_REF_IS_RVALUE (t))
+      return t;
+
+  t = copy_node (lvalue_ref);
+
+  TYPE_REF_IS_RVALUE (t) = true;
+  TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (lvalue_ref);
+  TYPE_NEXT_REF_TO (lvalue_ref) = t;
+  TYPE_MAIN_VARIANT (t) = t;
+
+  if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
+    SET_TYPE_STRUCTURAL_EQUALITY (t);
+  else if (TYPE_CANONICAL (to_type) != to_type)
+    TYPE_CANONICAL (t) 
+      = cp_build_reference_type (TYPE_CANONICAL (to_type), rval);
+  else
+    TYPE_CANONICAL (t) = t;
+
+  layout_type (t);
+
+  return t;
+
+}
+
+/* Used by the C++ front end to build qualified array types.  However,
+   the C version of this function does not properly maintain canonical
+   types (which are not used in C).  */
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+  return cp_build_qualified_type (type, type_quals);
+}
+
 \f
 /* Make a variant of TYPE, qualified with the TYPE_QUALS.  Handles
    arrays correctly.  In particular, if TYPE is an array of T's, and
    TYPE_QUALS is non-empty, returns an array of qualified T's.
-  
-   FLAGS determines how to deal with illformed qualifications. If
+
+   FLAGS determines how to deal with ill-formed qualifications. If
    tf_ignore_bad_quals is set, then bad qualifications are dropped
    (this is permitted if TYPE was introduced via a typedef or template
    type parameter). If bad qualifications are dropped and tf_warning
@@ -525,22 +747,16 @@ build_cplus_array_type (elt_type, index_type)
    via a typedef or template type argument. [dcl.ref] No such
    dispensation is provided for qualifying a function type.  [dcl.fct]
    DR 295 queries this and the proposed resolution brings it into line
-   with qualifiying a reference.  We implement the DR.  We also behave
+   with qualifying a reference.  We implement the DR.  We also behave
    in a similar manner for restricting non-pointer types.  */
+
 tree
-cp_build_qualified_type_real (type, type_quals, complain)
-     tree type;
-     int type_quals;
-     tsubst_flags_t complain;
+cp_build_qualified_type_real (tree type,
+                             int type_quals,
+                             tsubst_flags_t complain)
 {
   tree result;
   int bad_quals = TYPE_UNQUALIFIED;
-  /* We keep bad function qualifiers separate, so that we can decide
-     whether to implement DR 295 or not. DR 295 break existing code,
-     unfortunately. Remove this variable to implement the defect
-     report.  */
-  int bad_func_quals = TYPE_UNQUALIFIED;
 
   if (type == error_mark_node)
     return type;
@@ -548,61 +764,13 @@ cp_build_qualified_type_real (type, type_quals, complain)
   if (type_quals == cp_type_quals (type))
     return type;
 
-  /* A reference, fucntion or method type shall not be cv qualified.
-     [dcl.ref], [dct.fct]  */
-  if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
-      && (TREE_CODE (type) == REFERENCE_TYPE
-         || TREE_CODE (type) == FUNCTION_TYPE
-         || TREE_CODE (type) == METHOD_TYPE))
-    {
-      bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-      if (TREE_CODE (type) != REFERENCE_TYPE)
-       bad_func_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-      type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-    }
-  
-  /* A restrict-qualified type must be a pointer (or reference)
-     to object or incomplete type.  */
-  if ((type_quals & TYPE_QUAL_RESTRICT)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (type) != TYPENAME_TYPE
-      && !POINTER_TYPE_P (type))
-    {
-      bad_quals |= TYPE_QUAL_RESTRICT;
-      type_quals &= ~TYPE_QUAL_RESTRICT;
-    }
-
-  if (bad_quals == TYPE_UNQUALIFIED)
-    /*OK*/;
-  else if (!(complain & (tf_error | tf_ignore_bad_quals)))
-    return error_mark_node;
-  else if (bad_func_quals && !(complain & tf_error))
-    return error_mark_node;
-  else
-    {
-      if (complain & tf_ignore_bad_quals)
-       /* We're not going to warn about constifying things that can't
-          be constified.  */
-       bad_quals &= ~TYPE_QUAL_CONST;
-      bad_quals |= bad_func_quals;
-      if (bad_quals)
-       {
-         tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
-         if (!(complain & tf_ignore_bad_quals)
-             || bad_func_quals)
-           error ("`%V' qualifiers cannot be applied to `%T'",
-                  bad_type, type);
-       }
-    }
-  
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
       /* In C++, the qualification really applies to the array element
         type.  Obtain the appropriately qualified element type.  */
       tree t;
-      tree element_type 
-       = cp_build_qualified_type_real (TREE_TYPE (type), 
+      tree element_type
+       = cp_build_qualified_type_real (TREE_TYPE (type),
                                        type_quals,
                                        complain);
 
@@ -610,27 +778,51 @@ cp_build_qualified_type_real (type, type_quals, complain)
        return error_mark_node;
 
       /* See if we already have an identically qualified type.  */
-      t = get_qualified_type (type, type_quals);
+      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       if (cp_type_quals (t) == type_quals
+           && TYPE_NAME (t) == TYPE_NAME (type)
+           && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
+         break;
 
-      /* If we didn't already have it, create it now.  */
       if (!t)
-       {
-         /* Make a new array type, just like the old one, but with the
-            appropriately qualified element type.  */
-         t = build_type_copy (type);
-         TREE_TYPE (t) = element_type;
-       }
+      {
+       t = build_cplus_array_type_1 (element_type, TYPE_DOMAIN (type));
+
+       if (TYPE_MAIN_VARIANT (t) != TYPE_MAIN_VARIANT (type))
+         {
+           /* Set the main variant of the newly-created ARRAY_TYPE
+              (with cv-qualified element type) to the main variant of
+              the unqualified ARRAY_TYPE we started with.  */
+           tree last_variant = t;
+           tree m = TYPE_MAIN_VARIANT (type);
+
+           /* Find the last variant on the new ARRAY_TYPEs list of
+              variants, setting the main variant of each of the other
+              types to the main variant of our unqualified
+              ARRAY_TYPE.  */
+           while (TYPE_NEXT_VARIANT (last_variant))
+             {
+               TYPE_MAIN_VARIANT (last_variant) = m;
+               last_variant = TYPE_NEXT_VARIANT (last_variant);
+             }
+
+           /* Splice in the newly-created variants.  */
+           TYPE_NEXT_VARIANT (last_variant) = TYPE_NEXT_VARIANT (m);
+           TYPE_NEXT_VARIANT (m) = t;
+           TYPE_MAIN_VARIANT (last_variant) = m;
+         }
+      }
 
       /* Even if we already had this variant, we update
         TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
-        they changed since the variant was originally created.  
-        
+        they changed since the variant was originally created.
+
         This seems hokey; if there is some way to use a previous
         variant *without* coming through here,
         TYPE_NEEDS_CONSTRUCTING will never be updated.  */
-      TYPE_NEEDS_CONSTRUCTING (t) 
+      TYPE_NEEDS_CONSTRUCTING (t)
        = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
-      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) 
+      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
        = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
       return t;
     }
@@ -646,18 +838,78 @@ cp_build_qualified_type_real (type, type_quals, complain)
       t = cp_build_qualified_type_real (t, type_quals, complain);
       return build_ptrmemfunc_type (t);
     }
-  
+  else if (TREE_CODE (type) == TYPE_PACK_EXPANSION)
+    {
+      tree t = PACK_EXPANSION_PATTERN (type);
+
+      t = cp_build_qualified_type_real (t, type_quals, complain);
+      return make_pack_expansion (t);
+    }
+
+  /* A reference or method type shall not be cv-qualified.
+     [dcl.ref], [dcl.fct]  */
+  if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
+      && (TREE_CODE (type) == REFERENCE_TYPE
+         || TREE_CODE (type) == METHOD_TYPE))
+    {
+      bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
+      type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
+    }
+
+  /* A restrict-qualified type must be a pointer (or reference)
+     to object or incomplete type. */
+  if ((type_quals & TYPE_QUAL_RESTRICT)
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && TREE_CODE (type) != TYPENAME_TYPE
+      && !POINTER_TYPE_P (type))
+    {
+      bad_quals |= TYPE_QUAL_RESTRICT;
+      type_quals &= ~TYPE_QUAL_RESTRICT;
+    }
+
+  if (bad_quals == TYPE_UNQUALIFIED)
+    /*OK*/;
+  else if (!(complain & (tf_error | tf_ignore_bad_quals)))
+    return error_mark_node;
+  else
+    {
+      if (complain & tf_ignore_bad_quals)
+       /* We're not going to warn about constifying things that can't
+          be constified.  */
+       bad_quals &= ~TYPE_QUAL_CONST;
+      if (bad_quals)
+       {
+         tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
+
+         if (!(complain & tf_ignore_bad_quals))
+           error ("%qV qualifiers cannot be applied to %qT",
+                  bad_type, type);
+       }
+    }
+
   /* Retrieve (or create) the appropriately qualified variant.  */
   result = build_qualified_type (type, type_quals);
 
   /* If this was a pointer-to-method type, and we just made a copy,
-     then we need to clear the cached associated
-     pointer-to-member-function type; it is not valid for the new
-     type.  */
-  if (result != type 
+     then we need to unshare the record that holds the cached
+     pointer-to-member-function type, because these will be distinct
+     between the unqualified and qualified types.  */
+  if (result != type
       && TREE_CODE (type) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
-    TYPE_SET_PTRMEMFUNC_TYPE (result, NULL_TREE);
+      && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
+      && TYPE_LANG_SPECIFIC (result) == TYPE_LANG_SPECIFIC (type))
+    TYPE_LANG_SPECIFIC (result) = NULL;
+
+  /* We may also have ended up building a new copy of the canonical
+     type of a pointer-to-method type, which could have the same
+     sharing problem described above.  */
+  if (TYPE_CANONICAL (result) != TYPE_CANONICAL (type)
+      && TREE_CODE (type) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
+      && (TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) 
+          == TYPE_LANG_SPECIFIC (TYPE_CANONICAL (type))))
+    TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) = NULL;
+      
 
   return result;
 }
@@ -668,45 +920,99 @@ cp_build_qualified_type_real (type, type_quals, complain)
    compatible types.  */
 
 tree
-canonical_type_variant (t)
-     tree t;
+canonical_type_variant (tree t)
 {
-  return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
+  tree r;
+
+  if (t == error_mark_node)
+    return error_mark_node;
+
+  r = cp_build_type_attribute_variant (TYPE_MAIN_VARIANT (t),
+                                      TYPE_ATTRIBUTES (t));
+  return cp_build_qualified_type (r, cp_type_quals (t));
 }
 \f
-/* Makes new binfos for the indirect bases under BINFO, and updates
-   BINFO_OFFSET for them and their bases.  */
+/* Makes a copy of BINFO and TYPE, which is to be inherited into a
+   graph dominated by T.  If BINFO is NULL, TYPE is a dependent base,
+   and we do a shallow copy.  If BINFO is non-NULL, we do a deep copy.
+   VIRT indicates whether TYPE is inherited virtually or not.
+   IGO_PREV points at the previous binfo of the inheritance graph
+   order chain.  The newly copied binfo's TREE_CHAIN forms this
+   ordering.
+
+   The CLASSTYPE_VBASECLASSES vector of T is constructed in the
+   correct order. That is in the order the bases themselves should be
+   constructed in.
+
+   The BINFO_INHERITANCE of a virtual base class points to the binfo
+   of the most derived type. ??? We could probably change this so that
+   BINFO_INHERITANCE becomes synonymous with BINFO_PRIMARY, and hence
+   remove a field.  They currently can only differ for primary virtual
+   virtual bases.  */
 
-void
-unshare_base_binfos (binfo)
-     tree binfo;
+tree
+copy_binfo (tree binfo, tree type, tree t, tree *igo_prev, int virt)
 {
-  tree binfos = BINFO_BASETYPES (binfo);
   tree new_binfo;
-  int j;
 
-  if (binfos == NULL_TREE)
-    return;
+  if (virt)
+    {
+      /* See if we've already made this virtual base.  */
+      new_binfo = binfo_for_vbase (type, t);
+      if (new_binfo)
+       return new_binfo;
+    }
+
+  new_binfo = make_tree_binfo (binfo ? BINFO_N_BASE_BINFOS (binfo) : 0);
+  BINFO_TYPE (new_binfo) = type;
+
+  /* Chain it into the inheritance graph.  */
+  TREE_CHAIN (*igo_prev) = new_binfo;
+  *igo_prev = new_binfo;
+
+  if (binfo)
+    {
+      int ix;
+      tree base_binfo;
+
+      gcc_assert (!BINFO_DEPENDENT_BASE_P (binfo));
+      gcc_assert (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), type));
+
+      BINFO_OFFSET (new_binfo) = BINFO_OFFSET (binfo);
+      BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (binfo);
+
+      /* We do not need to copy the accesses, as they are read only.  */
+      BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (binfo);
+
+      /* Recursively copy base binfos of BINFO.  */
+      for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
+       {
+         tree new_base_binfo;
+
+         gcc_assert (!BINFO_DEPENDENT_BASE_P (base_binfo));
+         new_base_binfo = copy_binfo (base_binfo, BINFO_TYPE (base_binfo),
+                                      t, igo_prev,
+                                      BINFO_VIRTUAL_P (base_binfo));
+
+         if (!BINFO_INHERITANCE_CHAIN (new_base_binfo))
+           BINFO_INHERITANCE_CHAIN (new_base_binfo) = new_binfo;
+         BINFO_BASE_APPEND (new_binfo, new_base_binfo);
+       }
+    }
+  else
+    BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
 
-  /* Now unshare the structure beneath BINFO.  */
-  for (j = TREE_VEC_LENGTH (binfos)-1;
-       j >= 0; j--)
+  if (virt)
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, j);
-      new_binfo = TREE_VEC_ELT (binfos, j)
-       = make_binfo (BINFO_OFFSET (base_binfo),
-                     base_binfo,
-                     BINFO_VTABLE (base_binfo),
-                     BINFO_VIRTUALS (base_binfo));
-      TREE_VIA_PUBLIC (new_binfo) = TREE_VIA_PUBLIC (base_binfo);
-      TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
-      TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
-      BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
-      BINFO_PRIMARY_BASE_OF (new_binfo) = NULL_TREE;
-      unshare_base_binfos (new_binfo);
+      /* Push it onto the list after any virtual bases it contains
+        will have been pushed.  */
+      VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo);
+      BINFO_VIRTUAL_P (new_binfo) = 1;
+      BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
     }
-}
 
+  return new_binfo;
+}
 \f
 /* Hashing of lists so that we don't make duplicates.
    The entry point is `list_hash_canon'.  */
@@ -717,9 +1023,9 @@ unshare_base_binfos (binfo)
    While all these live in the same table, they are completely independent,
    and the hash code is computed differently for each of these.  */
 
-static htab_t list_hash_table;
+static GTY ((param_is (union tree_node))) htab_t list_hash_table;
 
-struct list_proxy 
+struct list_proxy
 {
   tree purpose;
   tree value;
@@ -730,12 +1036,10 @@ struct list_proxy
    for a node we are thinking about adding).  */
 
 static int
-list_hash_eq (entry, data)
-     const void *entry;
-     const void *data;
+list_hash_eq (const void* entry, const void* data)
 {
-  tree t = (tree) entry;
-  struct list_proxy *proxy = (struct list_proxy *) data;
+  const_tree const t = (const_tree) entry;
+  const struct list_proxy *const proxy = (const struct list_proxy *) data;
 
   return (TREE_VALUE (t) == proxy->value
          && TREE_PURPOSE (t) == proxy->purpose
@@ -747,22 +1051,19 @@ list_hash_eq (entry, data)
    TREE_COMMON slots), by adding the hash codes of the individual entries.  */
 
 static hashval_t
-list_hash_pieces (purpose, value, chain)
-     tree purpose;
-     tree value;
-     tree chain;
+list_hash_pieces (tree purpose, tree value, tree chain)
 {
   hashval_t hashcode = 0;
-  
+
   if (chain)
-    hashcode += TYPE_HASH (chain);
-  
+    hashcode += TREE_HASH (chain);
+
   if (value)
-    hashcode += TYPE_HASH (value);
+    hashcode += TREE_HASH (value);
   else
     hashcode += 1007;
   if (purpose)
-    hashcode += TYPE_HASH (purpose);
+    hashcode += TREE_HASH (purpose);
   else
     hashcode += 1009;
   return hashcode;
@@ -771,12 +1072,11 @@ list_hash_pieces (purpose, value, chain)
 /* Hash an already existing TREE_LIST.  */
 
 static hashval_t
-list_hash (p)
-     const void *p;
+list_hash (const void* p)
 {
-  tree t = (tree) p;
-  return list_hash_pieces (TREE_PURPOSE (t), 
-                          TREE_VALUE (t), 
+  const_tree const t = (const_tree) p;
+  return list_hash_pieces (TREE_PURPOSE (t),
+                          TREE_VALUE (t),
                           TREE_CHAIN (t));
 }
 
@@ -785,11 +1085,10 @@ list_hash (p)
    new one, and record it as the canonical object.  */
 
 tree
-hash_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
+hash_tree_cons (tree purpose, tree value, tree chain)
 {
   int hashcode = 0;
-  PTR* slot;
+  void **slot;
   struct list_proxy proxy;
 
   /* Hash the list node.  */
@@ -804,110 +1103,28 @@ hash_tree_cons (purpose, value, chain)
                                   INSERT);
   /* If not, create a new node.  */
   if (!*slot)
-    *slot = (PTR) tree_cons (purpose, value, chain);
-  return *slot;
+    *slot = tree_cons (purpose, value, chain);
+  return (tree) *slot;
 }
 
 /* Constructor for hashed lists.  */
 
 tree
-hash_tree_chain (value, chain)
-     tree value, chain;
+hash_tree_chain (tree value, tree chain)
 {
   return hash_tree_cons (NULL_TREE, value, chain);
 }
-
-/* Similar, but used for concatenating two lists.  */
-
-tree
-hash_chainon (list1, list2)
-     tree list1, list2;
-{
-  if (list2 == 0)
-    return list1;
-  if (list1 == 0)
-    return list2;
-  if (TREE_CHAIN (list1) == NULL_TREE)
-    return hash_tree_chain (TREE_VALUE (list1), list2);
-  return hash_tree_chain (TREE_VALUE (list1),
-                         hash_chainon (TREE_CHAIN (list1), list2));
-}
 \f
-/* Build an association between TYPE and some parameters:
-
-   OFFSET is the offset added to `this' to convert it to a pointer
-   of type `TYPE *'
-
-   BINFO is the base binfo to use, if we are deriving from one.  This
-   is necessary, as we want specialized parent binfos from base
-   classes, so that the VTABLE_NAMEs of bases are for the most derived
-   type, instead of the simple type.
-
-   VTABLE is the virtual function table with which to initialize
-   sub-objects of type TYPE.
-
-   VIRTUALS are the virtual functions sitting in VTABLE.  */
-
-tree
-make_binfo (offset, binfo, vtable, virtuals)
-     tree offset, binfo;
-     tree vtable, virtuals;
-{
-  tree new_binfo = make_tree_vec (11);
-  tree type;
-
-  if (TREE_CODE (binfo) == TREE_VEC)
-    type = BINFO_TYPE (binfo);
-  else
-    {
-      type = binfo;
-      binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE;
-    }
-
-  TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
-  BINFO_OFFSET (new_binfo) = offset;
-  BINFO_VTABLE (new_binfo) = vtable;
-  BINFO_VIRTUALS (new_binfo) = virtuals;
-
-  if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
-    BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));      
-  return new_binfo;
-}
-
-/* Return a TREE_LIST whose TREE_VALUE nodes along the
-   BINFO_INHERITANCE_CHAIN for BINFO, but in the opposite order.  In
-   other words, while the BINFO_INHERITANCE_CHAIN goes from base
-   classes to derived classes, the reversed path goes from derived
-   classes to base classes.  */
-
-tree
-reverse_path (binfo)
-     tree binfo;
-{
-  tree reversed_path;
-
-  reversed_path = NULL_TREE;
-  while (binfo) 
-    {
-      reversed_path = tree_cons (NULL_TREE, binfo, reversed_path);
-      binfo = BINFO_INHERITANCE_CHAIN (binfo);
-    }
-
-  return reversed_path;
-}
-
 void
-debug_binfo (elem)
-     tree elem;
+debug_binfo (tree elem)
 {
   HOST_WIDE_INT n;
   tree virtuals;
 
-  fprintf (stderr, "type \"%s\", offset = ",
-          TYPE_NAME_STRING (BINFO_TYPE (elem)));
-  fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
+  fprintf (stderr, "type \"%s\", offset = " HOST_WIDE_INT_PRINT_DEC
+          "\nvtable type:\n",
+          TYPE_NAME_STRING (BINFO_TYPE (elem)),
           TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
-  fprintf (stderr, "\nvtable type:\n");
   debug_tree (BINFO_TYPE (elem));
   if (BINFO_VTABLE (elem))
     fprintf (stderr, "vtable decl \"%s\"\n",
@@ -929,87 +1146,88 @@ debug_binfo (elem)
     }
 }
 
-int
-count_functions (t)
-     tree t;
-{
-  int i;
-  if (TREE_CODE (t) == FUNCTION_DECL)
-    return 1;
-  else if (TREE_CODE (t) == OVERLOAD)
-    {
-      for (i=0; t; t = OVL_CHAIN (t))
-       i++;
-      return i;
-    }
+/* Build a representation for the qualified name SCOPE::NAME.  TYPE is
+   the type of the result expression, if known, or NULL_TREE if the
+   resulting expression is type-dependent.  If TEMPLATE_P is true,
+   NAME is known to be a template because the user explicitly used the
+   "template" keyword after the "::".
+
+   All SCOPE_REFs should be built by use of this function.  */
 
-  abort ();
-  return 0;
+tree
+build_qualified_name (tree type, tree scope, tree name, bool template_p)
+{
+  tree t;
+  if (type == error_mark_node
+      || scope == error_mark_node
+      || name == error_mark_node)
+    return error_mark_node;
+  t = build2 (SCOPE_REF, type, scope, name);
+  QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
+  if (type)
+    t = convert_from_reference (t);
+  return t;
 }
 
+/* Returns nonzero if X is an expression for a (possibly overloaded)
+   function.  If "f" is a function or function template, "f", "c->f",
+   "c.f", "C::f", and "f<int>" will all be considered possibly
+   overloaded functions.  Returns 2 if the function is actually
+   overloaded, i.e., if it is impossible to know the type of the
+   function without performing overload resolution.  */
 int
-is_overloaded_fn (x)
-     tree x;
+is_overloaded_fn (tree x)
 {
   /* A baselink is also considered an overloaded function.  */
-  if (TREE_CODE (x) == OFFSET_REF)
+  if (TREE_CODE (x) == OFFSET_REF
+      || TREE_CODE (x) == COMPONENT_REF)
     x = TREE_OPERAND (x, 1);
   if (BASELINK_P (x))
-    x = TREE_VALUE (x);
-  return (TREE_CODE (x) == FUNCTION_DECL
-         || TREE_CODE (x) == TEMPLATE_ID_EXPR
-         || DECL_FUNCTION_TEMPLATE_P (x)
-         || TREE_CODE (x) == OVERLOAD);
+    x = BASELINK_FUNCTIONS (x);
+  if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
+    x = TREE_OPERAND (x, 0);
+  if (DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
+      || (TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x)))
+    return 2;
+  return  (TREE_CODE (x) == FUNCTION_DECL
+          || TREE_CODE (x) == OVERLOAD);
 }
 
-int
-really_overloaded_fn (x)
-     tree x;
-{     
-  /* A baselink is also considered an overloaded function.  */
-  if (TREE_CODE (x) == OFFSET_REF)
-    x = TREE_OPERAND (x, 1);
-  if (BASELINK_P (x))
-    x = TREE_VALUE (x);
-  return (TREE_CODE (x) == OVERLOAD 
-         && (TREE_CHAIN (x) != NULL_TREE
-             || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
+/* Returns true iff X is an expression for an overloaded function
+   whose type cannot be known without performing overload
+   resolution.  */
+
+bool
+really_overloaded_fn (tree x)
+{
+  return is_overloaded_fn (x) == 2;
 }
 
 tree
-get_first_fn (from)
-     tree from;
+get_first_fn (tree from)
 {
-  my_friendly_assert (is_overloaded_fn (from), 9);
-  /* A baselink is also considered an overloaded function. */
+  gcc_assert (is_overloaded_fn (from));
+  /* A baselink is also considered an overloaded function.  */
+  if (TREE_CODE (from) == COMPONENT_REF)
+    from = TREE_OPERAND (from, 1);
   if (BASELINK_P (from))
-    from = TREE_VALUE (from);
+    from = BASELINK_FUNCTIONS (from);
+  if (TREE_CODE (from) == TEMPLATE_ID_EXPR)
+    from = TREE_OPERAND (from, 0);
   return OVL_CURRENT (from);
 }
 
-/* Returns nonzero if T is a ->* or .* expression that refers to a
-   member function.  */
-
-int
-bound_pmf_p (t)
-     tree t;
-{
-  return (TREE_CODE (t) == OFFSET_REF
-         && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
-}
-
-/* Return a new OVL node, concatenating it with the old one. */
+/* Return a new OVL node, concatenating it with the old one.  */
 
 tree
-ovl_cons (decl, chain)
-     tree decl;
-     tree chain;
+ovl_cons (tree decl, tree chain)
 {
   tree result = make_node (OVERLOAD);
   TREE_TYPE (result) = unknown_type_node;
   OVL_FUNCTION (result) = decl;
   TREE_CHAIN (result) = chain;
-  
+
   return result;
 }
 
@@ -1017,9 +1235,7 @@ ovl_cons (decl, chain)
    just return it; otherwise, ovl_cons the _DECLs */
 
 tree
-build_overload (decl, chain)
-     tree decl;
-     tree chain;
+build_overload (tree decl, tree chain)
 {
   if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
     return decl;
@@ -1028,47 +1244,13 @@ build_overload (decl, chain)
   return ovl_cons (decl, chain);
 }
 
-int
-is_aggr_type_2 (t1, t2)
-     tree t1, t2;
-{
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return 0;
-  return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
-}
-
-/* Returns non-zero if CODE is the code for a statement.  */
-
-int
-cp_statement_code_p (code)
-     enum tree_code code;
-{
-  switch (code)
-    {
-    case SUBOBJECT:
-    case CTOR_STMT:
-    case CTOR_INITIALIZER:
-    case RETURN_INIT:
-    case TRY_BLOCK:
-    case HANDLER:
-    case EH_SPEC_BLOCK:
-    case USING_STMT:
-    case TAG_DEFN:
-      return 1;
-
-    default:
-      return 0;
-    }
-}
 \f
 #define PRINT_RING_SIZE 4
 
 const char *
-lang_printable_name (decl, v)
-     tree decl;
-     int v;
+cxx_printable_name (tree decl, int v)
 {
-  static tree decl_ring[PRINT_RING_SIZE];
+  static unsigned int uid_ring[PRINT_RING_SIZE];
   static char *print_ring[PRINT_RING_SIZE];
   static int ring_counter;
   int i;
@@ -1081,7 +1263,7 @@ lang_printable_name (decl, v)
 
   /* See if this print name is lying around.  */
   for (i = 0; i < PRINT_RING_SIZE; i++)
-    if (decl_ring[i] == decl)
+    if (uid_ring[i] == DECL_UID (decl))
       /* yes, so return it.  */
       return print_ring[i];
 
@@ -1090,19 +1272,18 @@ lang_printable_name (decl, v)
 
   if (current_function_decl != NULL_TREE)
     {
-      if (decl_ring[ring_counter] == current_function_decl)
+      if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
        ring_counter += 1;
       if (ring_counter == PRINT_RING_SIZE)
        ring_counter = 0;
-      if (decl_ring[ring_counter] == current_function_decl)
-       abort ();
+      gcc_assert (uid_ring[ring_counter] != DECL_UID (current_function_decl));
     }
 
   if (print_ring[ring_counter])
     free (print_ring[ring_counter]);
 
   print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
-  decl_ring[ring_counter] = decl;
+  uid_ring[ring_counter] = DECL_UID (decl);
   return print_ring[ring_counter];
 }
 \f
@@ -1110,20 +1291,18 @@ lang_printable_name (decl, v)
    listed in RAISES.  */
 
 tree
-build_exception_variant (type, raises)
-     tree type;
-     tree raises;
+build_exception_variant (tree type, tree raises)
 {
   tree v = TYPE_MAIN_VARIANT (type);
   int type_quals = TYPE_QUALS (type);
 
   for (; v; v = TYPE_NEXT_VARIANT (v))
-    if (TYPE_QUALS (v) == type_quals
-        && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
+    if (check_qualified_type (v, type, type_quals)
+       && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
       return v;
 
   /* Need to build a new variant.  */
-  v = build_type_copy (type);
+  v = build_variant_type_copy (type);
   TYPE_RAISES_EXCEPTIONS (v) = raises;
   return v;
 }
@@ -1133,14 +1312,12 @@ build_exception_variant (type, raises)
    arguments.  */
 
 tree
-bind_template_template_parm (t, newargs)
-     tree t;
-     tree newargs;
+bind_template_template_parm (tree t, tree newargs)
 {
   tree decl = TYPE_NAME (t);
   tree t2;
 
-  t2 = make_aggr_type (BOUND_TEMPLATE_TEMPLATE_PARM);
+  t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
   decl = build_decl (TYPE_DECL, DECL_NAME (decl), NULL_TREE);
 
   /* These nodes have to be created to reflect new TYPE_DECL and template
@@ -1148,13 +1325,14 @@ bind_template_template_parm (t, newargs)
   TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
   TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
   TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
-    = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), 
+    = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
                 newargs, NULL_TREE);
 
   TREE_TYPE (decl) = t2;
   TYPE_NAME (t2) = decl;
   TYPE_STUB_DECL (t2) = decl;
   TYPE_SIZE (t2) = 0;
+  SET_TYPE_STRUCTURAL_EQUALITY (t2);
 
   return t2;
 }
@@ -1162,12 +1340,13 @@ bind_template_template_parm (t, newargs)
 /* Called from count_trees via walk_tree.  */
 
 static tree
-count_trees_r (tp, walk_subtrees, data)
-     tree *tp ATTRIBUTE_UNUSED;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+count_trees_r (tree *tp, int *walk_subtrees, void *data)
 {
-  ++ *((int*) data);
+  ++*((int *) data);
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
   return NULL_TREE;
 }
 
@@ -1175,34 +1354,31 @@ count_trees_r (tp, walk_subtrees, data)
    representation.  */
 
 int
-count_trees (t)
-     tree t;
+count_trees (tree t)
 {
   int n_trees = 0;
-  walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
+  cp_walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
   return n_trees;
-}  
+}
 
 /* Called from verify_stmt_tree via walk_tree.  */
 
 static tree
-verify_stmt_tree_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+verify_stmt_tree_r (tree* tp,
+                   int* walk_subtrees ATTRIBUTE_UNUSED ,
+                   void* data)
 {
   tree t = *tp;
   htab_t *statements = (htab_t *) data;
   void **slot;
 
-  if (!statement_code_p (TREE_CODE (t)))
+  if (!STATEMENT_CODE_P (TREE_CODE (t)))
     return NULL_TREE;
 
   /* If this statement is already present in the hash table, then
      there is a circularity in the statement tree.  */
-  if (htab_find (*statements, t))
-    abort ();
-  
+  gcc_assert (!htab_find (*statements, t));
+
   slot = htab_find_slot (*statements, t, INSERT);
   *slot = t;
 
@@ -1214,73 +1390,83 @@ verify_stmt_tree_r (tp, walk_subtrees, data)
    circularities.  */
 
 void
-verify_stmt_tree (t)
-     tree t;
+verify_stmt_tree (tree t)
 {
   htab_t statements;
   statements = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
-  walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
+  cp_walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
   htab_delete (statements);
 }
 
-/* Called from find_tree via walk_tree.  */
-
-static tree
-find_tree_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
-{
-  if (*tp == (tree) data)
-    return (tree) data;
-
-  return NULL_TREE;
-}
-
-/* Returns X if X appears in the tree structure rooted at T.  */
-
-tree
-find_tree (t, x)
-     tree t;
-     tree x;
-{
-  return walk_tree_without_duplicates (&t, find_tree_r, x);
-}
-
-/* Passed to walk_tree.  Checks for the use of types with no linkage.  */
-
-static tree
-no_linkage_helper (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
-{
-  tree t = *tp;
-
-  if (TYPE_P (t)
-      && (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE)
-      && (decl_function_context (TYPE_MAIN_DECL (t))
-         || TYPE_ANONYMOUS_P (t)))
-    return t;
-  return NULL_TREE;
-}
-
 /* Check if the type T depends on a type with no linkage and if so, return
-   it.  */
+   it.  If RELAXED_P then do not consider a class type declared within
+   a TREE_PUBLIC function to have no linkage.  */
 
 tree
-no_linkage_check (t)
-     tree t;
+no_linkage_check (tree t, bool relaxed_p)
 {
+  tree r;
+
   /* There's no point in checking linkage on template functions; we
      can't know their complete types.  */
   if (processing_template_decl)
     return NULL_TREE;
 
-  t = walk_tree_without_duplicates (&t, no_linkage_helper, NULL);
-  if (t != error_mark_node)
-    return t;
-  return NULL_TREE;
+  switch (TREE_CODE (t))
+    {
+      tree fn;
+
+    case RECORD_TYPE:
+      if (TYPE_PTRMEMFUNC_P (t))
+       goto ptrmem;
+      /* Fall through.  */
+    case UNION_TYPE:
+      if (!CLASS_TYPE_P (t))
+       return NULL_TREE;
+      /* Fall through.  */
+    case ENUMERAL_TYPE:
+      if (TYPE_ANONYMOUS_P (t))
+       return t;
+      fn = decl_function_context (TYPE_MAIN_DECL (t));
+      if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
+       return t;
+      return NULL_TREE;
+
+    case ARRAY_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      return no_linkage_check (TREE_TYPE (t), relaxed_p);
+
+    case OFFSET_TYPE:
+    ptrmem:
+      r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t),
+                           relaxed_p);
+      if (r)
+       return r;
+      return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t), relaxed_p);
+
+    case METHOD_TYPE:
+      r = no_linkage_check (TYPE_METHOD_BASETYPE (t), relaxed_p);
+      if (r)
+       return r;
+      /* Fall through.  */
+    case FUNCTION_TYPE:
+      {
+       tree parm;
+       for (parm = TYPE_ARG_TYPES (t);
+            parm && parm != void_list_node;
+            parm = TREE_CHAIN (parm))
+         {
+           r = no_linkage_check (TREE_VALUE (parm), relaxed_p);
+           if (r)
+             return r;
+         }
+       return no_linkage_check (TREE_TYPE (t), relaxed_p);
+      }
+
+    default:
+      return NULL_TREE;
+    }
 }
 
 #ifdef GATHER_STATISTICS
@@ -1288,7 +1474,7 @@ extern int depth_reached;
 #endif
 
 void
-cxx_print_statistics ()
+cxx_print_statistics (void)
 {
   print_search_statistics ();
   print_class_statistics ();
@@ -1303,12 +1489,11 @@ cxx_print_statistics ()
    array.  */
 
 tree
-array_type_nelts_top (type)
-     tree type;
+array_type_nelts_top (tree type)
 {
-  return fold (build (PLUS_EXPR, sizetype,
+  return fold_build2 (PLUS_EXPR, sizetype,
                      array_type_nelts (type),
-                     integer_one_node));
+                     size_one_node);
 }
 
 /* Return, as an INTEGER_CST node, the number of elements for TYPE
@@ -1316,15 +1501,14 @@ array_type_nelts_top (type)
    ARRAY_TYPEs that are clumped together.  */
 
 tree
-array_type_nelts_total (type)
-     tree type;
+array_type_nelts_total (tree type)
 {
   tree sz = array_type_nelts_top (type);
   type = TREE_TYPE (type);
   while (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree n = array_type_nelts_top (type);
-      sz = fold (build (MULT_EXPR, sizetype, sz, n));
+      sz = fold_build2 (MULT_EXPR, sizetype, sz, n);
       type = TREE_TYPE (type);
     }
   return sz;
@@ -1333,19 +1517,16 @@ array_type_nelts_total (type)
 /* Called from break_out_target_exprs via mapcar.  */
 
 static tree
-bot_manip (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees;
-     void *data;
+bot_manip (tree* tp, int* walk_subtrees, void* data)
 {
   splay_tree target_remap = ((splay_tree) data);
   tree t = *tp;
 
-  if (TREE_CONSTANT (t))
+  if (!TYPE_P (t) && TREE_CONSTANT (t))
     {
       /* There can't be any TARGET_EXPRs or their slot variables below
-         this point.  We used to check !TREE_SIDE_EFFECTS, but then we
-         failed to copy an ADDR_EXPR of the slot VAR_DECL.  */
+        this point.  We used to check !TREE_SIDE_EFFECTS, but then we
+        failed to copy an ADDR_EXPR of the slot VAR_DECL.  */
       *walk_subtrees = 0;
       return NULL_TREE;
     }
@@ -1354,22 +1535,17 @@ bot_manip (tp, walk_subtrees, data)
       tree u;
 
       if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
-       {
-         mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
-         u = build_cplus_new
-           (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
-       }
-      else 
-       {
-         u = build_target_expr_with_type
-           (break_out_target_exprs (TREE_OPERAND (t, 1)), TREE_TYPE (t));
-       }
+       u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1));
+      else
+       u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t));
 
       /* Map the old variable to the new one.  */
-      splay_tree_insert (target_remap, 
-                        (splay_tree_key) TREE_OPERAND (t, 0), 
+      splay_tree_insert (target_remap,
+                        (splay_tree_key) TREE_OPERAND (t, 0),
                         (splay_tree_value) TREE_OPERAND (u, 0));
 
+      TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1));
+
       /* Replace the old expression with the new version.  */
       *tp = u;
       /* We don't have to go below this point; the recursive call to
@@ -1378,22 +1554,19 @@ bot_manip (tp, walk_subtrees, data)
       *walk_subtrees = 0;
       return NULL_TREE;
     }
-  else if (TREE_CODE (t) == CALL_EXPR)
-    mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
 
   /* Make a copy of this node.  */
   return copy_tree_r (tp, walk_subtrees, NULL);
 }
-  
+
 /* Replace all remapped VAR_DECLs in T with their new equivalents.
    DATA is really a splay-tree mapping old variables to new
    variables.  */
 
 static tree
-bot_replace (t, walk_subtrees, data)
-     tree *t;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+bot_replace (tree* t,
+            int* walk_subtrees ATTRIBUTE_UNUSED ,
+            void* data)
 {
   splay_tree target_remap = ((splay_tree) data);
 
@@ -1407,25 +1580,24 @@ bot_replace (t, walk_subtrees, data)
 
   return NULL_TREE;
 }
-       
+
 /* When we parse a default argument expression, we may create
    temporary variables via TARGET_EXPRs.  When we actually use the
    default-argument expression, we make a copy of the expression, but
    we must replace the temporaries with appropriate local versions.  */
 
 tree
-break_out_target_exprs (t)
-     tree t;
+break_out_target_exprs (tree t)
 {
   static int target_remap_count;
   static splay_tree target_remap;
 
   if (!target_remap_count++)
-    target_remap = splay_tree_new (splay_tree_compare_pointers, 
-                                  /*splay_tree_delete_key_fn=*/NULL, 
+    target_remap = splay_tree_new (splay_tree_compare_pointers,
+                                  /*splay_tree_delete_key_fn=*/NULL,
                                   /*splay_tree_delete_value_fn=*/NULL);
-  walk_tree (&t, bot_manip, target_remap, NULL);
-  walk_tree (&t, bot_replace, target_remap, NULL);
+  cp_walk_tree (&t, bot_manip, target_remap, NULL);
+  cp_walk_tree (&t, bot_replace, target_remap, NULL);
 
   if (!--target_remap_count)
     {
@@ -1436,25 +1608,23 @@ break_out_target_exprs (t)
   return t;
 }
 
-/* Obstack used for allocating nodes in template function and variable
-   definitions.  */
-
-/* Similar to `build_nt', except that we set TREE_COMPLEXITY to be the
-   current line number.  */
+/* Similar to `build_nt', but for template definitions of dependent
+   expressions  */
 
 tree
-build_min_nt VPARAMS ((enum tree_code code, ...))
+build_min_nt (enum tree_code code, ...)
 {
-  register tree t;
-  register int length;
-  register int i;
+  tree t;
+  int length;
+  int i;
+  va_list p;
+
+  gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
 
-  VA_OPEN (p, code);
-  VA_FIXEDARG (p, enum tree_code, code);
+  va_start (p, code);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
-  TREE_COMPLEXITY (t) = lineno;
 
   for (i = 0; i < length; i++)
     {
@@ -1462,99 +1632,106 @@ build_min_nt VPARAMS ((enum tree_code code, ...))
       TREE_OPERAND (t, i) = x;
     }
 
-  VA_CLOSE (p);
+  va_end (p);
   return t;
 }
 
-/* Similar to `build', except we set TREE_COMPLEXITY to the current
-   line-number.  */
+
+/* Similar to `build', but for template definitions.  */
 
 tree
-build_min VPARAMS ((enum tree_code code, tree tt, ...))
+build_min (enum tree_code code, tree tt, ...)
 {
-  register tree t;
-  register int length;
-  register int i;
+  tree t;
+  int length;
+  int i;
+  va_list p;
+
+  gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
 
-  VA_OPEN (p, tt);
-  VA_FIXEDARG (p, enum tree_code, code);
-  VA_FIXEDARG (p, tree, tt);
+  va_start (p, tt);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
   TREE_TYPE (t) = tt;
-  TREE_COMPLEXITY (t) = lineno;
 
   for (i = 0; i < length; i++)
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
+      if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x))
+       TREE_SIDE_EFFECTS (t) = 1;
     }
 
-  VA_CLOSE (p);
+  va_end (p);
   return t;
 }
 
-/* Returns an INTEGER_CST (of type `int') corresponding to I.
-   Multiple calls with the same value of I may or may not yield the
-   same node; therefore, callers should never modify the node
-   returned.  */
+/* Similar to `build', but for template definitions of non-dependent
+   expressions. NON_DEP is the non-dependent expression that has been
+   built.  */
 
 tree
-build_shared_int_cst (i)
-     int i;
+build_min_non_dep (enum tree_code code, tree non_dep, ...)
 {
-  static tree cache[256];
+  tree t;
+  int length;
+  int i;
+  va_list p;
 
-  if (i >= 256)
-    return build_int_2 (i, 0);
-  
-  if (!cache[i])
-    cache[i] = build_int_2 (i, 0);
-  
-  return cache[i];
-}
+  gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
 
-tree
-get_type_decl (t)
-     tree t;
-{
-  if (TREE_CODE (t) == TYPE_DECL)
-    return t;
-  if (TYPE_P (t))
-    return TYPE_STUB_DECL (t);
-  if (t == error_mark_node)
-    return t;
-  
-  abort ();
+  va_start (p, non_dep);
+
+  t = make_node (code);
+  length = TREE_CODE_LENGTH (code);
+  TREE_TYPE (t) = TREE_TYPE (non_dep);
+  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
+
+  for (i = 0; i < length; i++)
+    {
+      tree x = va_arg (p, tree);
+      TREE_OPERAND (t, i) = x;
+    }
 
-  /* Stop compiler from complaining control reaches end of non-void function.  */
-  return 0;
+  if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
+    /* This should not be considered a COMPOUND_EXPR, because it
+       resolves to an overload.  */
+    COMPOUND_EXPR_OVERLOADED (t) = 1;
+
+  va_end (p);
+  return t;
 }
 
-/* Return first vector element whose BINFO_TYPE is ELEM.
-   Return 0 if ELEM is not in VEC.  VEC may be NULL_TREE.  */
+/* Similar to `build_call_list', but for template definitions of non-dependent
+   expressions. NON_DEP is the non-dependent expression that has been
+   built.  */
 
 tree
-vec_binfo_member (elem, vec)
-     tree elem, vec;
+build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist)
 {
-  int i;
-
-  if (vec)
-    for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
-      if (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i))))
-       return TREE_VEC_ELT (vec, i);
+  tree t = build_nt_call_list (fn, arglist);
+  TREE_TYPE (t) = TREE_TYPE (non_dep);
+  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
+  return t;
+}
 
-  return NULL_TREE;
+tree
+get_type_decl (tree t)
+{
+  if (TREE_CODE (t) == TYPE_DECL)
+    return t;
+  if (TYPE_P (t))
+    return TYPE_STUB_DECL (t);
+  gcc_assert (t == error_mark_node);
+  return t;
 }
 
 /* Returns the namespace that contains DECL, whether directly or
    indirectly.  */
 
 tree
-decl_namespace_context (decl)
-     tree decl;
+decl_namespace_context (tree decl)
 {
   while (1)
     {
@@ -1567,40 +1744,60 @@ decl_namespace_context (decl)
     }
 }
 
-/* Return truthvalue of whether T1 is the same tree structure as T2.
-   Return 1 if they are the same.
-   Return 0 if they are understandably different.
-   Return -1 if either contains tree structure not understood by
-   this function.  */
+/* Returns true if decl is within an anonymous namespace, however deeply
+   nested, or false otherwise.  */
 
-int
-cp_tree_equal (t1, t2)
-     tree t1, t2;
+bool
+decl_anon_ns_mem_p (const_tree decl)
 {
-  register enum tree_code code1, code2;
-  int cmp;
-
-  if (t1 == t2)
-    return 1;
-  if (t1 == 0 || t2 == 0)
-    return 0;
-
-  code1 = TREE_CODE (t1);
-  code2 = TREE_CODE (t2);
-
-  if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
+  while (1)
     {
-      if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
-       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      if (decl == NULL_TREE || decl == error_mark_node)
+       return false;
+      if (TREE_CODE (decl) == NAMESPACE_DECL
+         && DECL_NAME (decl) == NULL_TREE)
+       return true;
+      /* Classes and namespaces inside anonymous namespaces have
+         TREE_PUBLIC == 0, so we can shortcut the search.  */
+      else if (TYPE_P (decl))
+       return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
+      else if (TREE_CODE (decl) == NAMESPACE_DECL)
+       return (TREE_PUBLIC (decl) == 0);
       else
-       return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
+       decl = DECL_CONTEXT (decl);
     }
-  else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
-          || code2 == NON_LVALUE_EXPR)
-    return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
+}
+
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+   Return 1 if they are the same. Return 0 if they are different.  */
+
+bool
+cp_tree_equal (tree t1, tree t2)
+{
+  enum tree_code code1, code2;
+
+  if (t1 == t2)
+    return true;
+  if (!t1 || !t2)
+    return false;
+
+  for (code1 = TREE_CODE (t1);
+       CONVERT_EXPR_CODE_P (code1)
+        || code1 == NON_LVALUE_EXPR;
+       code1 = TREE_CODE (t1))
+    t1 = TREE_OPERAND (t1, 0);
+  for (code2 = TREE_CODE (t2);
+       CONVERT_EXPR_CODE_P (code2)
+        || code1 == NON_LVALUE_EXPR;
+       code2 = TREE_CODE (t2))
+    t2 = TREE_OPERAND (t2, 0);
+
+  /* They might have become equal now.  */
+  if (t1 == t2)
+    return true;
 
   if (code1 != code2)
-    return 0;
+    return false;
 
   switch (code1)
     {
@@ -1614,7 +1811,15 @@ cp_tree_equal (t1, t2)
     case STRING_CST:
       return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
        && !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
-                 TREE_STRING_LENGTH (t1));
+                   TREE_STRING_LENGTH (t1));
+
+    case FIXED_CST:
+      return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
+                                    TREE_FIXED_CST (t2));
+
+    case COMPLEX_CST:
+      return cp_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
+       && cp_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
 
     case CONSTRUCTOR:
       /* We need to do this when determining whether or not two
@@ -1623,79 +1828,167 @@ cp_tree_equal (t1, t2)
       if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
            /* The first operand is RTL.  */
            && TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
-       return 0;
+       return false;
       return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
 
     case TREE_LIST:
-      cmp = cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
-      if (cmp <= 0)
-       return cmp;
-      cmp = cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2));
-      if (cmp <= 0)
-       return cmp;
+      if (!cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+       return false;
+      if (!cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+       return false;
       return cp_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
 
     case SAVE_EXPR:
       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
     case CALL_EXPR:
-      cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      if (cmp <= 0)
-       return cmp;
-      return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      {
+       tree arg1, arg2;
+       call_expr_arg_iterator iter1, iter2;
+       if (!cp_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+         return false;
+       for (arg1 = first_call_expr_arg (t1, &iter1),
+              arg2 = first_call_expr_arg (t2, &iter2);
+            arg1 && arg2;
+            arg1 = next_call_expr_arg (&iter1),
+              arg2 = next_call_expr_arg (&iter2))
+         if (!cp_tree_equal (arg1, arg2))
+           return false;
+       return (arg1 || arg2);
+      }
 
     case TARGET_EXPR:
-      /* Special case: if either target is an unallocated VAR_DECL,
-        it means that it's going to be unified with whatever the
-        TARGET_EXPR is really supposed to initialize, so treat it
-        as being equivalent to anything.  */
-      if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
-          && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
-          && !DECL_RTL_SET_P (TREE_OPERAND (t1, 0)))
-         || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
-             && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
-             && !DECL_RTL_SET_P (TREE_OPERAND (t2, 0))))
-       cmp = 1;
-      else
-       cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      if (cmp <= 0)
-       return cmp;
-      return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      {
+       tree o1 = TREE_OPERAND (t1, 0);
+       tree o2 = TREE_OPERAND (t2, 0);
+
+       /* Special case: if either target is an unallocated VAR_DECL,
+          it means that it's going to be unified with whatever the
+          TARGET_EXPR is really supposed to initialize, so treat it
+          as being equivalent to anything.  */
+       if (TREE_CODE (o1) == VAR_DECL && DECL_NAME (o1) == NULL_TREE
+           && !DECL_RTL_SET_P (o1))
+         /*Nop*/;
+       else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE
+                && !DECL_RTL_SET_P (o2))
+         /*Nop*/;
+       else if (!cp_tree_equal (o1, o2))
+         return false;
+
+       return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      }
 
     case WITH_CLEANUP_EXPR:
-      cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      if (cmp <= 0)
-       return cmp;
+      if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+       return false;
       return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
 
     case COMPONENT_REF:
-      if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
-       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      return 0;
+      if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
+       return false;
+      return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
-    case VAR_DECL:
     case PARM_DECL:
+      /* For comparing uses of parameters in late-specified return types
+        with an out-of-class definition of the function.  */
+      if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+       return true;
+      else
+       return false;
+
+    case VAR_DECL:
     case CONST_DECL:
     case FUNCTION_DECL:
-      return 0;
+    case TEMPLATE_DECL:
+    case IDENTIFIER_NODE:
+    case SSA_NAME:
+      return false;
+
+    case BASELINK:
+      return (BASELINK_BINFO (t1) == BASELINK_BINFO (t2)
+             && BASELINK_ACCESS_BINFO (t1) == BASELINK_ACCESS_BINFO (t2)
+             && cp_tree_equal (BASELINK_FUNCTIONS (t1),
+                               BASELINK_FUNCTIONS (t2)));
 
     case TEMPLATE_PARM_INDEX:
-      return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
-       && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
+      return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+             && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+             && (TEMPLATE_PARM_PARAMETER_PACK (t1)
+                 == TEMPLATE_PARM_PARAMETER_PACK (t2))
+             && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
+                             TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
+
+    case TEMPLATE_ID_EXPR:
+      {
+       unsigned ix;
+       tree vec1, vec2;
+
+       if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+         return false;
+       vec1 = TREE_OPERAND (t1, 1);
+       vec2 = TREE_OPERAND (t2, 1);
+
+       if (!vec1 || !vec2)
+         return !vec1 && !vec2;
+
+       if (TREE_VEC_LENGTH (vec1) != TREE_VEC_LENGTH (vec2))
+         return false;
+
+       for (ix = TREE_VEC_LENGTH (vec1); ix--;)
+         if (!cp_tree_equal (TREE_VEC_ELT (vec1, ix),
+                             TREE_VEC_ELT (vec2, ix)))
+           return false;
+
+       return true;
+      }
 
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
-       return 0;
-      if (TYPE_P (TREE_OPERAND (t1, 0)))
-       return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      break;
+      {
+       tree o1 = TREE_OPERAND (t1, 0);
+       tree o2 = TREE_OPERAND (t2, 0);
+
+       if (TREE_CODE (o1) != TREE_CODE (o2))
+         return false;
+       if (TYPE_P (o1))
+         return same_type_p (o1, o2);
+       else
+         return cp_tree_equal (o1, o2);
+      }
+
+    case MODOP_EXPR:
+      {
+       tree t1_op1, t2_op1;
+
+       if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+         return false;
+
+       t1_op1 = TREE_OPERAND (t1, 1);
+       t2_op1 = TREE_OPERAND (t2, 1);
+       if (TREE_CODE (t1_op1) != TREE_CODE (t2_op1))
+         return false;
+
+       return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t2, 2));
+      }
 
     case PTRMEM_CST:
       /* Two pointer-to-members are the same if they point to the same
         field or function in the same class.  */
-      return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
-             && same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2)));
+      if (PTRMEM_CST_MEMBER (t1) != PTRMEM_CST_MEMBER (t2))
+       return false;
+
+      return same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2));
+
+    case OVERLOAD:
+      if (OVL_FUNCTION (t1) != OVL_FUNCTION (t2))
+       return false;
+      return cp_tree_equal (OVL_CHAIN (t1), OVL_CHAIN (t2));
+
+    case TRAIT_EXPR:
+      if (TRAIT_EXPR_KIND (t1) != TRAIT_EXPR_KIND (t2))
+       return false;
+      return same_type_p (TRAIT_EXPR_TYPE1 (t1), TRAIT_EXPR_TYPE1 (t2))
+       && same_type_p (TRAIT_EXPR_TYPE2 (t1), TRAIT_EXPR_TYPE2 (t2));
 
     default:
       break;
@@ -1703,83 +1996,43 @@ cp_tree_equal (t1, t2)
 
   switch (TREE_CODE_CLASS (code1))
     {
-    case '1':
-    case '2':
-    case '<':
-    case 'e':
-    case 'r':
-    case 's':
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_vl_exp:
+    case tcc_reference:
+    case tcc_statement:
       {
-       int i;
-       
-       cmp = 1;
-       for (i = 0; i < TREE_CODE_LENGTH (code1); ++i)
-         {
-           cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
-           if (cmp <= 0)
-             return cmp;
-         }
-       return cmp;
-      }
-    
-      case 't':
-       return same_type_p (t1, t2) ? 1 : 0;
-    }
-
-  return -1;
-}
-
-/* Build a wrapper around some pointer PTR so we can use it as a tree.  */
-
-tree
-build_ptr_wrapper (ptr)
-     void *ptr;
-{
-  tree t = make_node (WRAPPER);
-  WRAPPER_PTR (t) = ptr;
-  return t;
-}
-
-/* Build a wrapper around some integer I so we can use it as a tree.  */
-
-tree
-build_int_wrapper (i)
-     int i;
-{
-  tree t = make_node (WRAPPER);
-  WRAPPER_INT (t) = i;
-  return t;
-}
+       int i, n;
 
-static tree
-build_srcloc (file, line)
-     const char *file;
-     int line;
-{
-  tree t;
+       n = TREE_OPERAND_LENGTH (t1);
+       if (TREE_CODE_CLASS (code1) == tcc_vl_exp
+           && n != TREE_OPERAND_LENGTH (t2))
+         return false;
 
-  t = make_node (SRCLOC);
-  SRCLOC_FILE (t) = file;
-  SRCLOC_LINE (t) = line;
+       for (i = 0; i < n; ++i)
+         if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
+           return false;
 
-  return t;
-}
+       return true;
+      }
 
-tree
-build_srcloc_here ()
-{
-  return build_srcloc (input_filename, lineno);
+    case tcc_type:
+      return same_type_p (t1, t2);
+    default:
+      gcc_unreachable ();
+    }
+  /* We can get here with --disable-checking.  */
+  return false;
 }
 
 /* The type of ARG when used as an lvalue.  */
 
 tree
-lvalue_type (arg)
-     tree arg;
+lvalue_type (tree arg)
 {
   tree type = TREE_TYPE (arg);
-  if (TREE_CODE (arg) == OVERLOAD)
-    type = unknown_type_node;
   return type;
 }
 
@@ -1787,15 +2040,17 @@ lvalue_type (arg)
    reference types.  */
 
 tree
-error_type (arg)
-     tree arg;
+error_type (tree arg)
 {
   tree type = TREE_TYPE (arg);
+
   if (TREE_CODE (type) == ARRAY_TYPE)
     ;
+  else if (TREE_CODE (type) == ERROR_MARK)
+    ;
   else if (real_lvalue_p (arg))
     type = build_reference_type (lvalue_type (arg));
-  else if (IS_AGGR_TYPE (type))
+  else if (MAYBE_CLASS_TYPE_P (type))
     type = lvalue_type (arg);
 
   return type;
@@ -1804,10 +2059,9 @@ error_type (arg)
 /* Does FUNCTION use a variable-length argument list?  */
 
 int
-varargs_function_p (function)
-     tree function;
+varargs_function_p (const_tree function)
 {
-  tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+  const_tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
   for (; parm; parm = TREE_CHAIN (parm))
     if (TREE_VALUE (parm) == void_type_node)
       return 0;
@@ -1817,10 +2071,9 @@ varargs_function_p (function)
 /* Returns 1 if decl is a member of a class.  */
 
 int
-member_p (decl)
-     tree decl;
+member_p (const_tree decl)
 {
-  const tree ctx = DECL_CONTEXT (decl);
+  const_tree const ctx = DECL_CONTEXT (decl);
   return (ctx && TYPE_P (ctx));
 }
 
@@ -1828,11 +2081,10 @@ member_p (decl)
    object that the access is against.  */
 
 tree
-build_dummy_object (type)
-     tree type;
+build_dummy_object (tree type)
 {
   tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
-  return build_indirect_ref (decl, NULL);
+  return cp_build_indirect_ref (decl, NULL, tf_warning_or_error);
 }
 
 /* We've gotten a reference to a member of TYPE.  Return *this if appropriate,
@@ -1840,16 +2092,14 @@ build_dummy_object (type)
    binfo path from current_class_type to TYPE, or 0.  */
 
 tree
-maybe_dummy_object (type, binfop)
-     tree type;
-     tree *binfop;
+maybe_dummy_object (tree type, tree* binfop)
 {
   tree decl, context;
   tree binfo;
-  
+
   if (current_class_type
       && (binfo = lookup_base (current_class_type, type,
-                              ba_ignore | ba_quiet, NULL)))
+                              ba_unique | ba_quiet, NULL)))
     context = current_class_type;
   else
     {
@@ -1860,8 +2110,13 @@ maybe_dummy_object (type, binfop)
 
   if (binfop)
     *binfop = binfo;
-  
-  if (current_class_ref && context == current_class_type)
+
+  if (current_class_ref && context == current_class_type
+      /* Kludge: Make sure that current_class_type is actually
+        correct.  It might not be if we're in the middle of
+        tsubst_default_argument.  */
+      && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+                     current_class_type))
     decl = current_class_ref;
   else
     decl = build_dummy_object (context);
@@ -1872,8 +2127,7 @@ maybe_dummy_object (type, binfop)
 /* Returns 1 if OB is a placeholder object, or a pointer to one.  */
 
 int
-is_dummy_object (ob)
-     tree ob;
+is_dummy_object (const_tree ob)
 {
   if (TREE_CODE (ob) == INDIRECT_REF)
     ob = TREE_OPERAND (ob, 0);
@@ -1884,81 +2138,98 @@ is_dummy_object (ob)
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
 
 int
-pod_type_p (t)
-     tree t;
+pod_type_p (const_tree t)
 {
-  t = strip_array_types (t);
+  /* This CONST_CAST is okay because strip_array_types returns its
+     argument unmodified and we assign it to a const_tree.  */
+  t = strip_array_types (CONST_CAST_TREE(t));
 
+  if (t == error_mark_node)
+    return 1;
   if (INTEGRAL_TYPE_P (t))
     return 1;  /* integral, character or enumeral type */
   if (FLOAT_TYPE_P (t))
     return 1;
   if (TYPE_PTR_P (t))
     return 1; /* pointer to non-member */
-  if (TYPE_PTRMEM_P (t))
-    return 1; /* pointer to member object */
-  if (TYPE_PTRMEMFUNC_P (t))
-    return 1; /* pointer to member function */
-  
-  if (! CLASS_TYPE_P (t))
+  if (TYPE_PTR_TO_MEMBER_P (t))
+    return 1; /* pointer to member */
+
+  if (TREE_CODE (t) == VECTOR_TYPE)
+    return 1; /* vectors are (small) arrays of scalars */
+
+  if (! RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
     return 0; /* other non-class type (reference or function) */
+  if (! CLASS_TYPE_P (t))
+    return 1; /* struct created by the back end */
   if (CLASSTYPE_NON_POD_P (t))
     return 0;
   return 1;
 }
 
+/* Nonzero iff type T is a class template implicit specialization.  */
+
+bool
+class_tmpl_impl_spec_p (const_tree t)
+{
+  return CLASS_TYPE_P (t) && CLASSTYPE_TEMPLATE_INSTANTIATION (t);
+}
+
 /* Returns 1 iff zero initialization of type T means actually storing
    zeros in it.  */
 
 int
-zero_init_p (t)
-     tree t ATTRIBUTE_UNUSED;
+zero_init_p (const_tree t)
 {
-  /* This is not a correct implementation of this function.  As a
-     result, pointers-to-members will not be correctly
-     zero-initialized.
+  /* This CONST_CAST is okay because strip_array_types returns its
+     argument unmodified and we assign it to a const_tree.  */
+  t = strip_array_types (CONST_CAST_TREE(t));
+
+  if (t == error_mark_node)
+    return 1;
+
+  /* NULL pointers to data members are initialized with -1.  */
+  if (TYPE_PTRMEM_P (t))
+    return 0;
 
-     However, using a correct implementation of this function results
-     in many other failures.  Correcting these other failures required
-     a major infrastructure improvement, which was undertaken in the
-     GCC 3.3 source base.  
+  /* Classes that contain types that can't be zero-initialized, cannot
+     be zero-initialized themselves.  */
+  if (CLASS_TYPE_P (t) && CLASSTYPE_NON_ZERO_INIT_P (t))
+    return 0;
 
-     In order to reduce risk, these changes were not ported to the GCC
-     3.2 source base.  */
   return 1;
 }
 
 /* Table of valid C++ attributes.  */
-const struct attribute_spec cp_attribute_table[] =
+const struct attribute_spec cxx_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
   { "com_interface",  0, 0, false, false, false, handle_com_interface_attribute },
   { "init_priority",  1, 1, true,  false, false, handle_init_priority_attribute },
-  { NULL,             0, 0, false, false, false, NULL }
+  { NULL,            0, 0, false, false, false, NULL }
 };
 
 /* Handle a "java_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags;
-     bool *no_add_attrs;
+handle_java_interface_attribute (tree* node,
+                                tree name,
+                                tree args ATTRIBUTE_UNUSED ,
+                                int flags,
+                                bool* no_add_attrs)
 {
   if (DECL_P (*node)
       || !CLASS_TYPE_P (*node)
       || !TYPE_FOR_JAVA (*node))
     {
-      error ("`%s' attribute can only be applied to Java class definitions",
-            IDENTIFIER_POINTER (name));
+      error ("%qE attribute can only be applied to Java class definitions",
+            name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
   if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-    *node = build_type_copy (*node);
+    *node = build_variant_type_copy (*node);
   TYPE_JAVA_INTERFACE (*node) = 1;
 
   return NULL_TREE;
@@ -1967,12 +2238,11 @@ handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
 /* Handle a "com_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+handle_com_interface_attribute (tree* node,
+                               tree name,
+                               tree args ATTRIBUTE_UNUSED ,
+                               int flags ATTRIBUTE_UNUSED ,
+                               bool* no_add_attrs)
 {
   static int warned;
 
@@ -1982,14 +2252,14 @@ handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
       || !CLASS_TYPE_P (*node)
       || *node != TYPE_MAIN_VARIANT (*node))
     {
-      warning ("`%s' attribute can only be applied to class definitions",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute can only be applied "
+              "to class definitions", name);
       return NULL_TREE;
     }
 
   if (!warned++)
-    warning ("`%s' is obsolete; g++ vtables are now COM-compatible by default",
-            IDENTIFIER_POINTER (name));
+    warning (0, "%qE is obsolete; g++ vtables are now COM-compatible by default",
+            name);
 
   return NULL_TREE;
 }
@@ -1997,12 +2267,11 @@ handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
 /* Handle an "init_priority" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+handle_init_priority_attribute (tree* node,
+                               tree name,
+                               tree args,
+                               int flags ATTRIBUTE_UNUSED ,
+                               bool* no_add_attrs)
 {
   tree initp_expr = TREE_VALUE (args);
   tree decl = *node;
@@ -2010,7 +2279,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
   int pri;
 
   STRIP_NOPS (initp_expr);
-         
+
   if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
     {
       error ("requested init_priority is not an integer constant");
@@ -2019,7 +2288,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
     }
 
   pri = TREE_INT_CST_LOW (initp_expr);
-       
+
   type = strip_array_types (type);
 
   if (decl == NULL_TREE
@@ -2031,11 +2300,11 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
       /* Static objects in functions are initialized the
         first time control passes through that
         function. This is not precise enough to pin down an
-        init_priority value, so don't allow it. */
-      || current_function_decl) 
+        init_priority value, so don't allow it.  */
+      || current_function_decl)
     {
-      error ("can only use `%s' attribute on file-scope definitions of objects of class type",
-            IDENTIFIER_POINTER (name));
+      error ("can only use %qE attribute on file-scope definitions "
+            "of objects of class type", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -2051,19 +2320,19 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
      language and runtime support implementations.*/
   if (pri <= MAX_RESERVED_INIT_PRIORITY)
     {
-      warning 
-       ("requested init_priority is reserved for internal use");
+      warning
+       (0, "requested init_priority is reserved for internal use");
     }
 
   if (SUPPORTS_INIT_PRIORITY)
     {
-      DECL_INIT_PRIORITY (decl) = pri;
+      SET_DECL_INIT_PRIORITY (decl, pri);
+      DECL_HAS_INIT_PRIORITY_P (decl) = 1;
       return NULL_TREE;
     }
   else
     {
-      error ("`%s' attribute is not supported on this platform",
-            IDENTIFIER_POINTER (name));
+      error ("%qE attribute is not supported on this platform", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -2073,44 +2342,70 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
    thing pointed to by the constant.  */
 
 tree
-make_ptrmem_cst (type, member)
-     tree type;
-     tree member;
+make_ptrmem_cst (tree type, tree member)
 {
   tree ptrmem_cst = make_node (PTRMEM_CST);
-  /* If would seem a great convenience if make_node would set
-     TREE_CONSTANT for things of class `c', but it does not.  */
-  TREE_CONSTANT (ptrmem_cst) = 1;
   TREE_TYPE (ptrmem_cst) = type;
   PTRMEM_CST_MEMBER (ptrmem_cst) = member;
   return ptrmem_cst;
 }
 
+/* Build a variant of TYPE that has the indicated ATTRIBUTES.  May
+   return an existing type if an appropriate type already exists.  */
+
+tree
+cp_build_type_attribute_variant (tree type, tree attributes)
+{
+  tree new_type;
+
+  new_type = build_type_attribute_variant (type, attributes);
+  if (TREE_CODE (new_type) == FUNCTION_TYPE
+      && (TYPE_RAISES_EXCEPTIONS (new_type)
+         != TYPE_RAISES_EXCEPTIONS (type)))
+    new_type = build_exception_variant (new_type,
+                                       TYPE_RAISES_EXCEPTIONS (type));
+
+  /* Making a new main variant of a class type is broken.  */
+  gcc_assert (!CLASS_TYPE_P (type) || new_type == type);
+    
+  return new_type;
+}
+
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+   Called only after doing all language independent checks.  Only
+   to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
+   compared in type_hash_eq.  */
+
+bool
+cxx_type_hash_eq (const_tree typea, const_tree typeb)
+{
+  gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE);
+
+  return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
+                           TYPE_RAISES_EXCEPTIONS (typeb), 1);
+}
+
 /* Apply FUNC to all language-specific sub-trees of TP in a pre-order
-   traversal.  Called from walk_tree().  */
+   traversal.  Called from walk_tree.  */
 
-tree 
-cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
-     tree *tp;
-     int *walk_subtrees_p;
-     walk_tree_fn func;
-     void *data;
-     void *htab;
+tree
+cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
+                 void *data, struct pointer_set_t *pset)
 {
   enum tree_code code = TREE_CODE (*tp);
   tree result;
-  
+
 #define WALK_SUBTREE(NODE)                             \
   do                                                   \
     {                                                  \
-      result = walk_tree (&(NODE), func, data, htab);  \
-      if (result)                                      \
-       return result;                                  \
+      result = cp_walk_tree (&(NODE), func, data, pset);       \
+      if (result) goto out;                            \
     }                                                  \
   while (0)
 
   /* Not one of the easy cases.  We must explicitly go through the
      children.  */
+  result = NULL_TREE;
   switch (code)
     {
     case DEFAULT_ARG:
@@ -2121,8 +2416,13 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
     case TEMPLATE_TYPE_PARM:
     case TYPENAME_TYPE:
     case TYPEOF_TYPE:
-      /* None of thse have subtrees other than those already walked
-         above.  */
+      /* None of these have subtrees other than those already walked
+        above.  */
+      *walk_subtrees_p = 0;
+      break;
+
+    case BASELINK:
+      WALK_SUBTREE (BASELINK_FUNCTIONS (*tp));
       *walk_subtrees_p = 0;
       break;
 
@@ -2132,9 +2432,7 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
       break;
 
     case TREE_LIST:
-      /* A BASELINK_P's TREE_PURPOSE is a BINFO, and hence circular.  */
-      if (!BASELINK_P (*tp))
-        WALK_SUBTREE (TREE_PURPOSE (*tp));
+      WALK_SUBTREE (TREE_PURPOSE (*tp));
       break;
 
     case OVERLOAD:
@@ -2143,322 +2441,105 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
       *walk_subtrees_p = 0;
       break;
 
+    case USING_DECL:
+      WALK_SUBTREE (DECL_NAME (*tp));
+      WALK_SUBTREE (USING_DECL_SCOPE (*tp));
+      WALK_SUBTREE (USING_DECL_DECLS (*tp));
+      *walk_subtrees_p = 0;
+      break;
+
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (*tp))
        WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
       break;
 
-    default:
+    case TYPE_ARGUMENT_PACK:
+    case NONTYPE_ARGUMENT_PACK:
+      {
+        tree args = ARGUMENT_PACK_ARGS (*tp);
+        int i, len = TREE_VEC_LENGTH (args);
+        for (i = 0; i < len; i++)
+          WALK_SUBTREE (TREE_VEC_ELT (args, i));
+      }
       break;
-    }
-
-  /* We didn't find what we were looking for.  */
-  return NULL_TREE;
-
-#undef WALK_SUBTREE
-}
-
-/* Decide whether there are language-specific reasons to not inline a
-   function as a tree.  */
-
-int
-cp_cannot_inline_tree_fn (fnp)
-     tree *fnp;
-{
-  tree fn = *fnp;
-
-  if (flag_really_no_inline
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
-    return 1;
-
-  /* We can inline a template instantiation only if it's fully
-     instantiated.  */
-  if (DECL_TEMPLATE_INFO (fn)
-      && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
-    {
-      fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
-      if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
-       return 1;
-    }
-
-  if (varargs_function_p (fn))
-    {
-      DECL_UNINLINABLE (fn) = 1;
-      return 1;
-    }
-
-  if (! function_attribute_inlinable_p (fn))
-    {
-      DECL_UNINLINABLE (fn) = 1;
-      return 1;
-    }
-
-  return 0;
-}
 
-/* Add any pending functions other than the current function (already
-   handled by the caller), that thus cannot be inlined, to FNS_P, then
-   return the latest function added to the array, PREV_FN.  */
+    case TYPE_PACK_EXPANSION:
+      WALK_SUBTREE (TREE_TYPE (*tp));
+      *walk_subtrees_p = 0;
+      break;
+      
+    case EXPR_PACK_EXPANSION:
+      WALK_SUBTREE (TREE_OPERAND (*tp, 0));
+      *walk_subtrees_p = 0;
+      break;
 
-tree
-cp_add_pending_fn_decls (fns_p, prev_fn)
-     void *fns_p;
-     tree prev_fn;
-{
-  varray_type *fnsp = (varray_type *)fns_p;
-  struct saved_scope *s;
+    case CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+    case STATIC_CAST_EXPR:
+    case CONST_CAST_EXPR:
+    case DYNAMIC_CAST_EXPR:
+      if (TREE_TYPE (*tp))
+       WALK_SUBTREE (TREE_TYPE (*tp));
 
-  for (s = scope_chain; s; s = s->prev)
-    if (s->function_decl && s->function_decl != prev_fn)
       {
-       VARRAY_PUSH_TREE (*fnsp, s->function_decl);
-       prev_fn = s->function_decl;
+        int i;
+        for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (*tp)); ++i)
+         WALK_SUBTREE (TREE_OPERAND (*tp, i));
       }
+      *walk_subtrees_p = 0;
+      break;
 
-  return prev_fn;
-}
-
-/* Determine whether a tree node is an OVERLOAD node.  Used to decide
-   whether to copy a node or to preserve its chain when inlining a
-   function.  */
-
-int
-cp_is_overload_p (t)
-     tree t;
-{
-  return TREE_CODE (t) == OVERLOAD;
-}
-
-/* Determine whether VAR is a declaration of an automatic variable in
-   function FN.  */
-
-int
-cp_auto_var_in_fn_p (var, fn)
-     tree var, fn;
-{
-  return (DECL_P (var) && DECL_CONTEXT (var) == fn
-         && nonstatic_local_decl_p (var));
-}
-
-/* Tell whether a declaration is needed for the RESULT of a function
-   FN being inlined into CALLER or if the top node of target_exprs is
-   to be used.  */
+    case TRAIT_EXPR:
+      WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp));
+      WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp));
+      *walk_subtrees_p = 0;
+      break;
 
-tree
-cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
-                              need_decl, target_exprs)
-     tree result, fn, caller;
-     void *decl_map_;
-     int *need_decl;
-     void *target_exprs;
-{
-  splay_tree decl_map = (splay_tree)decl_map_;
-  varray_type *texps = (varray_type *)target_exprs;
-  tree var;
-  int aggregate_return_p;
-
-  /* Figure out whether or not FN returns an aggregate.  */
-  aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
-  *need_decl = ! aggregate_return_p;
-
-  /* If FN returns an aggregate then the caller will always create the
-     temporary (using a TARGET_EXPR) and the call will be the
-     initializing expression for the TARGET_EXPR.  If we were just to
-     create a new VAR_DECL here, then the result of this function
-     would be copied (bitwise) into the variable initialized by the
-     TARGET_EXPR.  That's incorrect, so we must transform any
-     references to the RESULT into references to the target.  */
-  if (aggregate_return_p)
-    {
-      if (VARRAY_ACTIVE_SIZE (*texps) == 0)
-       abort ();
-      var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
-      if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
-                                                      TREE_TYPE (result)))
-       abort ();
-    }
-  /* Otherwise, make an appropriate copy.  */
-  else
-    var = copy_decl_for_inlining (result, fn, caller);
+    case DECLTYPE_TYPE:
+      WALK_SUBTREE (DECLTYPE_TYPE_EXPR (*tp));
+      *walk_subtrees_p = 0;
+      break;
 
-  if (DECL_SAVED_FUNCTION_DATA (fn))
-    {
-      tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
-      if (nrv)
-       {
-         /* We have a named return value; copy the name and source
-            position so we can get reasonable debugging information, and
-            register the return variable as its equivalent.  */
-         DECL_NAME (var) = DECL_NAME (nrv);
-         DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
-         DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
-         DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
-         /* Don't lose initialization info.  */
-         DECL_INITIAL (var) = DECL_INITIAL (nrv);
-         /* Don't forget that it needs to go in the stack.  */
-         TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
-
-         splay_tree_insert (decl_map,
-                            (splay_tree_key) nrv,
-                            (splay_tree_value) var);
-       }
+    default:
+      return NULL_TREE;
     }
 
-  return var;
-}
-
-/* Record that we're about to start inlining FN, and return non-zero if
-   that's OK.  Used for lang_hooks.tree_inlining.start_inlining.  */
+  /* We didn't find what we were looking for.  */
+ out:
+  return result;
 
-int
-cp_start_inlining (fn)
-     tree fn;
-{
-  if (DECL_TEMPLATE_INSTANTIATION (fn))
-    return push_tinst_level (fn);
-  else
-    return 1;
+#undef WALK_SUBTREE
 }
 
-/* Record that we're done inlining FN.  Used for
-   lang_hooks.tree_inlining.end_inlining.  */
+/* Like save_expr, but for C++.  */
 
-void
-cp_end_inlining (fn)
-     tree fn ATTRIBUTE_UNUSED;
+tree
+cp_save_expr (tree expr)
 {
-  if (DECL_TEMPLATE_INSTANTIATION (fn))
-    pop_tinst_level ();
+  /* There is no reason to create a SAVE_EXPR within a template; if
+     needed, we can create the SAVE_EXPR when instantiating the
+     template.  Furthermore, the middle-end cannot handle C++-specific
+     tree codes.  */
+  if (processing_template_decl)
+    return expr;
+  return save_expr (expr);
 }
 
 /* Initialize tree.c.  */
 
 void
-init_tree ()
-{
-  make_lang_type_fn = cp_make_lang_type;
-  lang_unsave = cp_unsave;
-  lang_statement_code_p = cp_statement_code_p;
-  lang_set_decl_assembler_name = mangle_decl;
-  list_hash_table = htab_create (31, list_hash, list_hash_eq, NULL);
-  ggc_add_root (&list_hash_table, 1, 
-               sizeof (list_hash_table),
-               mark_tree_hashtable);
-}
-
-/* Called via walk_tree.  If *TP points to a DECL_STMT for a local
-   declaration, copies the declaration and enters it in the splay_tree
-   pointed to by DATA (which is really a `splay_tree *').  */
-
-static tree
-mark_local_for_remap_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
-{
-  tree t = *tp;
-  splay_tree st = (splay_tree) data;
-  tree decl;
-
-  
-  if (TREE_CODE (t) == DECL_STMT
-      && nonstatic_local_decl_p (DECL_STMT_DECL (t)))
-    decl = DECL_STMT_DECL (t);
-  else if (TREE_CODE (t) == LABEL_STMT)
-    decl = LABEL_STMT_LABEL (t);
-  else if (TREE_CODE (t) == TARGET_EXPR
-          && nonstatic_local_decl_p (TREE_OPERAND (t, 0)))
-    decl = TREE_OPERAND (t, 0);
-  else if (TREE_CODE (t) == CASE_LABEL)
-    decl = CASE_LABEL_DECL (t);
-  else
-    decl = NULL_TREE;
-
-  if (decl)
-    {
-      tree copy;
-
-      /* Make a copy.  */
-      copy = copy_decl_for_inlining (decl, 
-                                    DECL_CONTEXT (decl), 
-                                    DECL_CONTEXT (decl));
-
-      /* Remember the copy.  */
-      splay_tree_insert (st,
-                        (splay_tree_key) decl, 
-                        (splay_tree_value) copy);
-    }
-
-  return NULL_TREE;
-}
-
-/* Called via walk_tree when an expression is unsaved.  Using the
-   splay_tree pointed to by ST (which is really a `splay_tree'),
-   remaps all local declarations to appropriate replacements.  */
-
-static tree
-cp_unsave_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees;
-     void *data;
-{
-  splay_tree st = (splay_tree) data;
-  splay_tree_node n;
-
-  /* Only a local declaration (variable or label).  */
-  if (nonstatic_local_decl_p (*tp))
-    {
-      /* Lookup the declaration.  */
-      n = splay_tree_lookup (st, (splay_tree_key) *tp);
-      
-      /* If it's there, remap it.  */
-      if (n)
-       *tp = (tree) n->value;
-    }
-  else if (TREE_CODE (*tp) == SAVE_EXPR)
-    remap_save_expr (tp, st, current_function_decl, walk_subtrees);
-  else
-    {
-      copy_tree_r (tp, walk_subtrees, NULL);
-
-      /* Do whatever unsaving is required.  */
-      unsave_expr_1 (*tp);
-    }
-
-  /* Keep iterating.  */
-  return NULL_TREE;
-}
-
-/* Called by unsave_expr_now whenever an expression (*TP) needs to be
-   unsaved.  */
-
-static void
-cp_unsave (tp)
-     tree *tp;
+init_tree (void)
 {
-  splay_tree st;
-
-  /* Create a splay-tree to map old local variable declarations to new
-     ones.  */
-  st = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
-
-  /* Walk the tree once figuring out what needs to be remapped.  */
-  walk_tree (tp, mark_local_for_remap_r, st, NULL);
-
-  /* Walk the tree again, copying, remapping, and unsaving.  */
-  walk_tree (tp, cp_unsave_r, st, NULL);
-
-  /* Clean up.  */
-  splay_tree_delete (st);
+  list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
 }
 
 /* Returns the kind of special function that DECL (a FUNCTION_DECL)
-   is.  Note that this sfk_none is zero, so this function can be used
-   as a predicate to test whether or not DECL is a special function.  */
+   is.  Note that sfk_none is zero, so this function can be used as a
+   predicate to test whether or not DECL is a special function.  */
 
 special_function_kind
-special_function_p (decl)
-     tree decl;
+special_function_p (const_tree decl)
 {
   /* Rather than doing all this stuff with magic names, we should
      probably have a field of type `special_function_kind' in
@@ -2483,15 +2564,16 @@ special_function_p (decl)
   return sfk_none;
 }
 
-/* Returns non-zero if TYPE is a character type, including wchar_t.  */
+/* Returns nonzero if TYPE is a character type, including wchar_t.  */
 
 int
-char_type_p (type)
-     tree type;
+char_type_p (tree type)
 {
   return (same_type_p (type, char_type_node)
          || same_type_p (type, unsigned_char_type_node)
          || same_type_p (type, signed_char_type_node)
+         || same_type_p (type, char16_type_node)
+         || same_type_p (type, char32_type_node)
          || same_type_p (type, wchar_type_node));
 }
 
@@ -2503,8 +2585,7 @@ char_type_p (type)
    as a global symbol when you run `nm' on the resulting object file.  */
 
 linkage_kind
-decl_linkage (decl)
-     tree decl;
+decl_linkage (tree decl)
 {
   /* This function doesn't attempt to calculate the linkage from first
      principles as given in [basic.link].  Instead, it makes use of
@@ -2517,16 +2598,29 @@ decl_linkage (decl)
   if (!DECL_NAME (decl))
     return lk_none;
 
+  /* Fields have no linkage.  */
+  if (TREE_CODE (decl) == FIELD_DECL)
+    return lk_none;
+
   /* Things that are TREE_PUBLIC have external linkage.  */
   if (TREE_PUBLIC (decl))
     return lk_external;
 
+  if (TREE_CODE (decl) == NAMESPACE_DECL)
+    return lk_external;
+
+  /* Linkage of a CONST_DECL depends on the linkage of the enumeration
+     type.  */
+  if (TREE_CODE (decl) == CONST_DECL)
+    return decl_linkage (TYPE_NAME (TREE_TYPE (decl)));
+
   /* Some things that are not TREE_PUBLIC have external linkage, too.
      For example, on targets that don't have weak symbols, we make all
      template instantiations have internal linkage (in the object
      file), but the symbols should still be treated as having external
      linkage from the point of view of the language.  */
-  if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
+  if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl)
+      && DECL_COMDAT (decl))
     return lk_external;
 
   /* Things in local scope do not have linkage, if they don't have
@@ -2534,6 +2628,232 @@ decl_linkage (decl)
   if (decl_function_context (decl))
     return lk_none;
 
+  /* Members of the anonymous namespace also have TREE_PUBLIC unset, but
+     are considered to have external linkage for language purposes.  DECLs
+     really meant to have internal linkage have DECL_THIS_STATIC set.  */
+  if (TREE_CODE (decl) == TYPE_DECL)
+    return lk_external;
+  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      if (!DECL_THIS_STATIC (decl))
+       return lk_external;
+
+      /* Static data members and static member functions from classes
+        in anonymous namespace also don't have TREE_PUBLIC set.  */
+      if (DECL_CLASS_CONTEXT (decl))
+       return lk_external;
+    }
+
   /* Everything else has internal linkage.  */
   return lk_internal;
 }
+\f
+/* EXP is an expression that we want to pre-evaluate.  Returns (in
+   *INITP) an expression that will perform the pre-evaluation.  The
+   value returned by this function is a side-effect free expression
+   equivalent to the pre-evaluated expression.  Callers must ensure
+   that *INITP is evaluated before EXP.  */
+
+tree
+stabilize_expr (tree exp, tree* initp)
+{
+  tree init_expr;
+
+  if (!TREE_SIDE_EFFECTS (exp))
+    init_expr = NULL_TREE;
+  else if (!real_lvalue_p (exp)
+          || !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
+    {
+      init_expr = get_target_expr (exp);
+      exp = TARGET_EXPR_SLOT (init_expr);
+    }
+  else
+    {
+      exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
+      init_expr = get_target_expr (exp);
+      exp = TARGET_EXPR_SLOT (init_expr);
+      exp = cp_build_indirect_ref (exp, 0, tf_warning_or_error);
+    }
+  *initp = init_expr;
+
+  gcc_assert (!TREE_SIDE_EFFECTS (exp));
+  return exp;
+}
+
+/* Add NEW_EXPR, an expression whose value we don't care about, after the
+   similar expression ORIG.  */
+
+tree
+add_stmt_to_compound (tree orig, tree new_expr)
+{
+  if (!new_expr || !TREE_SIDE_EFFECTS (new_expr))
+    return orig;
+  if (!orig || !TREE_SIDE_EFFECTS (orig))
+    return new_expr;
+  return build2 (COMPOUND_EXPR, void_type_node, orig, new_expr);
+}
+
+/* Like stabilize_expr, but for a call whose arguments we want to
+   pre-evaluate.  CALL is modified in place to use the pre-evaluated
+   arguments, while, upon return, *INITP contains an expression to
+   compute the arguments.  */
+
+void
+stabilize_call (tree call, tree *initp)
+{
+  tree inits = NULL_TREE;
+  int i;
+  int nargs = call_expr_nargs (call);
+
+  if (call == error_mark_node || processing_template_decl)
+    {
+      *initp = NULL_TREE;
+      return;
+    }
+
+  gcc_assert (TREE_CODE (call) == CALL_EXPR);
+
+  for (i = 0; i < nargs; i++)
+    {
+      tree init;
+      CALL_EXPR_ARG (call, i) =
+       stabilize_expr (CALL_EXPR_ARG (call, i), &init);
+      inits = add_stmt_to_compound (inits, init);
+    }
+
+  *initp = inits;
+}
+
+/* Like stabilize_expr, but for an AGGR_INIT_EXPR whose arguments we want
+   to pre-evaluate.  CALL is modified in place to use the pre-evaluated
+   arguments, while, upon return, *INITP contains an expression to
+   compute the arguments.  */
+
+void
+stabilize_aggr_init (tree call, tree *initp)
+{
+  tree inits = NULL_TREE;
+  int i;
+  int nargs = aggr_init_expr_nargs (call);
+
+  if (call == error_mark_node)
+    return;
+
+  gcc_assert (TREE_CODE (call) == AGGR_INIT_EXPR);
+
+  for (i = 0; i < nargs; i++)
+    {
+      tree init;
+      AGGR_INIT_EXPR_ARG (call, i) =
+       stabilize_expr (AGGR_INIT_EXPR_ARG (call, i), &init);
+      inits = add_stmt_to_compound (inits, init);
+    }
+
+  *initp = inits;
+}
+
+/* Like stabilize_expr, but for an initialization.  
+
+   If the initialization is for an object of class type, this function
+   takes care not to introduce additional temporaries.
+
+   Returns TRUE iff the expression was successfully pre-evaluated,
+   i.e., if INIT is now side-effect free, except for, possible, a
+   single call to a constructor.  */
+
+bool
+stabilize_init (tree init, tree *initp)
+{
+  tree t = init;
+
+  *initp = NULL_TREE;
+
+  if (t == error_mark_node || processing_template_decl)
+    return true;
+
+  if (TREE_CODE (t) == INIT_EXPR
+      && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+      && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
+    {
+      TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
+      return true;
+    }
+
+  if (TREE_CODE (t) == INIT_EXPR)
+    t = TREE_OPERAND (t, 1);
+  if (TREE_CODE (t) == TARGET_EXPR)
+    t = TARGET_EXPR_INITIAL (t);
+  if (TREE_CODE (t) == COMPOUND_EXPR)
+    t = expr_last (t);
+  if (TREE_CODE (t) == CONSTRUCTOR
+      && EMPTY_CONSTRUCTOR_P (t))
+    /* Default-initialization.  */
+    return true;
+
+  /* If the initializer is a COND_EXPR, we can't preevaluate
+     anything.  */
+  if (TREE_CODE (t) == COND_EXPR)
+    return false;
+
+  if (TREE_CODE (t) == CALL_EXPR)
+    {
+      stabilize_call (t, initp);
+      return true;
+    }
+
+  if (TREE_CODE (t) == AGGR_INIT_EXPR)
+    {
+      stabilize_aggr_init (t, initp);
+      return true;
+    }
+
+  /* The initialization is being performed via a bitwise copy -- and
+     the item copied may have side effects.  */
+  return TREE_SIDE_EFFECTS (init);
+}
+
+/* Like "fold", but should be used whenever we might be processing the
+   body of a template.  */
+
+tree
+fold_if_not_in_template (tree expr)
+{
+  /* In the body of a template, there is never any need to call
+     "fold".  We will call fold later when actually instantiating the
+     template.  Integral constant expressions in templates will be
+     evaluated via fold_non_dependent_expr, as necessary.  */
+  if (processing_template_decl)
+    return expr;
+
+  /* Fold C++ front-end specific tree codes.  */
+  if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
+    return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
+
+  return fold (expr);
+}
+
+/* Returns true if a cast to TYPE may appear in an integral constant
+   expression.  */
+
+bool
+cast_valid_in_integral_constant_expression_p (tree type)
+{
+  return (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+         || dependent_type_p (type)
+         || type == error_mark_node);
+}
+
+\f
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+/* Complain that some language-specific thing hanging off a tree
+   node has been accessed improperly.  */
+
+void
+lang_check_failed (const char* file, int line, const char* function)
+{
+  internal_error ("lang_* check: failed in %s, at %s:%d",
+                 function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
+
+#include "gt-cp-tree.h"