OSDN Git Service

Fix linux make profiledbootstrap.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 791cc22..12aa391 100644 (file)
@@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-iterator.h"
 #include "basic-block.h"
 #include "tree-flow.h"
+#include "params.h"
 
 /* obstack.[ch] explicitly declined to prototype this.  */
 extern int _obstack_allocated_p (struct obstack *h, void *obj);
@@ -71,6 +72,7 @@ static const char * const tree_node_kind_names[] = {
   "perm_tree_lists",
   "temp_tree_lists",
   "vecs",
+  "binfos",
   "phi_nodes",
   "ssa names",
   "random kinds",
@@ -110,7 +112,7 @@ static void set_type_quals (tree, int);
 static int type_hash_eq (const void *, const void *);
 static hashval_t type_hash_hash (const void *);
 static void print_type_hash_statistics (void);
-static void finish_vector_type (tree);
+static tree make_vector_type (tree, int, enum machine_mode);
 static int type_hash_marked_p (const void *);
 static unsigned int type_hash_list (tree, hashval_t);
 static unsigned int attribute_hash_list (tree, hashval_t);
@@ -192,18 +194,11 @@ tree_size (tree node)
                                        + (PHI_ARG_CAPACITY (node) - 1) *
                                        sizeof (struct phi_arg_d));
 
-       case EPHI_NODE:         return (sizeof (struct tree_ephi_node)
-                                       + (EPHI_ARG_CAPACITY (node) - 1) *
-                                       sizeof (struct ephi_arg_d));
-
        case SSA_NAME:          return sizeof (struct tree_ssa_name);
-       case EUSE_NODE:         return sizeof (struct tree_euse_node);
-
-       case EKILL_NODE:
-       case EEXIT_NODE:        return sizeof (struct tree_eref_common);
 
        case STATEMENT_LIST:    return sizeof (struct tree_statement_list);
        case BLOCK:             return sizeof (struct tree_block);
+       case VALUE_HANDLE:      return sizeof (struct tree_value_handle);
 
        default:
          return lang_hooks.tree_size (code);
@@ -231,9 +226,9 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 #endif
   struct tree_common ttmp;
 
-  /* We can't allocate a TREE_VEC, PHI_NODE, EPHI_NODE or STRING_CST
+  /* We can't allocate a TREE_VEC, PHI_NODE, or STRING_CST
      without knowing how many elements it will have.  */
-  if (code == TREE_VEC || code == PHI_NODE || code == EPHI_NODE)
+  if (code == TREE_VEC || code == PHI_NODE)
     abort ();
 
   TREE_SET_CODE ((tree)&ttmp, code);
@@ -274,6 +269,8 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        kind = id_kind;
       else if (code == TREE_VEC)
        kind = vec_kind;
+      else if (code == TREE_BINFO)
+       kind = binfo_kind;
       else if (code == PHI_NODE)
        kind = phi_kind;
       else if (code == SSA_NAME)
@@ -341,7 +338,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        case INIT_EXPR:
        case MODIFY_EXPR:
        case VA_ARG_EXPR:
-       case RTL_EXPR:
        case PREDECREMENT_EXPR:
        case PREINCREMENT_EXPR:
        case POSTDECREMENT_EXPR:
@@ -396,6 +392,13 @@ copy_node_stat (tree node MEM_STAT_DECL)
         but the optimizer should catch that.  */
       TYPE_SYMTAB_POINTER (t) = 0;
       TYPE_SYMTAB_ADDRESS (t) = 0;
+      
+      /* Do not copy the values cache.  */
+      if (TYPE_CACHED_VALUES_P(t))
+       {
+         TYPE_CACHED_VALUES_P (t) = 0;
+         TYPE_CACHED_VALUES (t) = NULL_TREE;
+       }
     }
 
   return t;
@@ -425,20 +428,91 @@ copy_list (tree list)
 }
 
 \f
-/* Return a newly constructed INTEGER_CST node whose constant value
-   is specified by the two ints LOW and HI.
-   The TREE_TYPE is set to `int'.
-
-   This function should be used via the `build_int_2' macro.  */
+/* Create an INT_CST node of TYPE and value HI:LOW.  If TYPE is NULL,
+   integer_type_node is used.  */
 
 tree
-build_int_2_wide (unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
+build_int_cst (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 {
-  tree t = make_node (INTEGER_CST);
+  tree t;
+  int ix = -1;
+  int limit = 0;
+
+  if (!type)
+    type = integer_type_node;
+
+  switch (TREE_CODE (type))
+    {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* Cache NULL pointer.  */
+      if (!hi && !low)
+       {
+         limit = 1;
+         ix = 0;
+       }
+      break;
+
+    case BOOLEAN_TYPE:
+      /* Cache false or true.  */
+      limit = 2;
+      if (!hi && low < 2)
+       ix = low;
+      break;
+
+    case INTEGER_TYPE:
+    case CHAR_TYPE:
+    case OFFSET_TYPE:
+      if (TYPE_UNSIGNED (type))
+       {
+         /* Cache 0..N */
+         limit = INTEGER_SHARE_LIMIT;
+         if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
+           ix = low;
+       }
+      else
+       {
+         /* Cache -1..N */
+         limit = INTEGER_SHARE_LIMIT + 1;
+         if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
+           ix = low + 1;
+         else if (hi == -1 && low == -(unsigned HOST_WIDE_INT)1)
+           ix = 0;
+       }
+      break;
+    default:
+      break;
+    }
+
+  if (ix >= 0)
+    {
+      if (!TYPE_CACHED_VALUES_P (type))
+       {
+         TYPE_CACHED_VALUES_P (type) = 1;
+         TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
+       }
+
+      t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
+      if (t)
+       {
+         /* Make sure no one is clobbering the shared constant.  */
+         if (TREE_TYPE (t) != type)
+           abort ();
+         if (TREE_INT_CST_LOW (t) != low || TREE_INT_CST_HIGH (t) != hi)
+           abort ();
+         return t;
+       }
+    }
+
+  t = make_node (INTEGER_CST);
 
   TREE_INT_CST_LOW (t) = low;
   TREE_INT_CST_HIGH (t) = hi;
-  TREE_TYPE (t) = integer_type_node;
+  TREE_TYPE (t) = type;
+
+  if (ix >= 0)
+    TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+
   return t;
 }
 
@@ -581,6 +655,32 @@ build_complex (tree type, tree real, tree imag)
   return t;
 }
 
+/* Build a BINFO with LEN language slots.  */
+
+tree
+make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
+{
+  tree t;
+  size_t length = (offsetof (struct tree_binfo, base_binfos)
+                  + VEC_embedded_size (tree, base_binfos));
+
+#ifdef GATHER_STATISTICS
+  tree_node_counts[(int) binfo_kind]++;
+  tree_node_sizes[(int) binfo_kind] += length;
+#endif
+
+  t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
+
+  memset (t, 0, offsetof (struct tree_binfo, base_binfos));
+
+  TREE_SET_CODE (t, TREE_BINFO);
+
+  VEC_embedded_init (tree, BINFO_BASE_BINFOS (t), base_binfos);
+
+  return t;
+}
+
+
 /* Build a newly constructed TREE_VEC node of length LEN.  */
 
 tree
@@ -932,21 +1032,6 @@ purpose_member (tree elem, tree list)
   return NULL_TREE;
 }
 
-/* Return first list element whose BINFO_TYPE is ELEM.
-   Return 0 if ELEM is not in LIST.  */
-
-tree
-binfo_member (tree elem, tree list)
-{
-  while (list)
-    {
-      if (elem == BINFO_TYPE (list))
-       return list;
-      list = TREE_CHAIN (list);
-    }
-  return NULL_TREE;
-}
-
 /* Return nonzero if ELEM is part of the chain CHAIN.  */
 
 int
@@ -1126,7 +1211,7 @@ size_in_bytes (tree type)
     }
 
   if (TREE_CODE (t) == INTEGER_CST)
-    force_fit_type (t, 0);
+    t = force_fit_type (t, 0, false, false);
 
   return t;
 }
@@ -1213,7 +1298,7 @@ expr_align (tree t)
 
     case SAVE_EXPR:         case COMPOUND_EXPR:       case MODIFY_EXPR:
     case INIT_EXPR:         case TARGET_EXPR:         case WITH_CLEANUP_EXPR:
-    case CLEANUP_POINT_EXPR:  case UNSAVE_EXPR:
+    case CLEANUP_POINT_EXPR:
       /* These don't change the alignment of an object.  */
       return expr_align (TREE_OPERAND (t, 0));
 
@@ -1260,13 +1345,13 @@ array_type_nelts (tree type)
 
   return (integer_zerop (min)
          ? max
-         : fold (build (MINUS_EXPR, TREE_TYPE (max), max, min)));
+         : fold (build2 (MINUS_EXPR, TREE_TYPE (max), max, min)));
 }
 \f
-/* Return nonzero if arg is static -- a reference to an object in
+/* Return true if arg is static -- a reference to an object in
    static storage.  This is not the same as the C meaning of `static'.  */
 
-int
+bool
 staticp (tree arg)
 {
   switch (TREE_CODE (arg))
@@ -1287,10 +1372,10 @@ staticp (tree arg)
 
     case LABEL_DECL:
     case STRING_CST:
-      return 1;
+      return true;
 
     case COMPONENT_REF:
-      /* If the thing being referenced is not a field, then it is 
+      /* If the thing being referenced is not a field, then it is
         something language specific.  */
       if (TREE_CODE (TREE_OPERAND (arg, 1)) != FIELD_DECL)
        return (*lang_hooks.staticp) (arg);
@@ -1298,12 +1383,12 @@ staticp (tree arg)
       /* If we are referencing a bitfield, we can't evaluate an
         ADDR_EXPR at compile time and so it isn't a constant.  */
       if (DECL_BIT_FIELD (TREE_OPERAND (arg, 1)))
-       return 0;
+       return false;
 
       return staticp (TREE_OPERAND (arg, 0));
 
     case BIT_FIELD_REF:
-      return 0;
+      return false;
 
 #if 0
        /* This case is technically correct, but results in setting
@@ -1319,14 +1404,14 @@ staticp (tree arg)
          && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
        return staticp (TREE_OPERAND (arg, 0));
       else
-       return 0;
+       return false;
 
     default:
       if ((unsigned int) TREE_CODE (arg)
          >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
        return lang_hooks.staticp (arg);
       else
-       return 0;
+       return false;
     }
 }
 \f
@@ -1383,7 +1468,7 @@ save_expr (tree expr)
   if (contains_placeholder_p (inner))
     return t;
 
-  t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
+  t = build1 (SAVE_EXPR, TREE_TYPE (expr), t);
 
   /* This expression might be placed ahead of a jump to ensure that the
      value was computed on both sides of the jump.  So make sure it isn't
@@ -1432,33 +1517,6 @@ skip_simple_arithmetic (tree expr)
   return inner;
 }
 
-/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
-   SAVE_EXPR.  Return FALSE otherwise.  */
-
-bool
-saved_expr_p (tree expr)
-{
-  return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR;
-}
-
-/* Arrange for an expression to be expanded multiple independent
-   times.  This is useful for cleanup actions, as the backend can
-   expand them multiple times in different places.  */
-
-tree
-unsave_expr (tree expr)
-{
-  tree t;
-
-  /* If this is already protected, no sense in protecting it again.  */
-  if (TREE_CODE (expr) == UNSAVE_EXPR)
-    return expr;
-
-  t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
-  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
-  return t;
-}
-
 /* Returns the index of the first non-tree operand for CODE, or the number
    of operands if all are trees.  */
 
@@ -1467,13 +1525,6 @@ first_rtl_op (enum tree_code code)
 {
   switch (code)
     {
-    case SAVE_EXPR:
-      return 2;
-    case GOTO_SUBROUTINE_EXPR:
-    case RTL_EXPR:
-      return 0;
-    case WITH_CLEANUP_EXPR:
-      return 2;
     default:
       return TREE_CODE_LENGTH (code);
     }
@@ -1509,159 +1560,17 @@ tree_node_structure (tree t)
     case TREE_LIST:            return TS_LIST;
     case TREE_VEC:             return TS_VEC;
     case PHI_NODE:             return TS_PHI_NODE;
-    case EPHI_NODE:            return TS_EPHI_NODE;
-    case EUSE_NODE:             return TS_EUSE_NODE;
-    case EKILL_NODE:            return TS_EREF_NODE;
-    case EEXIT_NODE:            return TS_EREF_NODE;
     case SSA_NAME:             return TS_SSA_NAME;
     case PLACEHOLDER_EXPR:     return TS_COMMON;
     case STATEMENT_LIST:       return TS_STATEMENT_LIST;
     case BLOCK:                        return TS_BLOCK;
+    case TREE_BINFO:           return TS_BINFO;
+    case VALUE_HANDLE:         return TS_VALUE_HANDLE;
 
     default:
       abort ();
     }
 }
-
-/* Perform any modifications to EXPR required when it is unsaved.  Does
-   not recurse into EXPR's subtrees.  */
-
-void
-unsave_expr_1 (tree expr)
-{
-  switch (TREE_CODE (expr))
-    {
-    case SAVE_EXPR:
-      if (! SAVE_EXPR_PERSISTENT_P (expr))
-       SAVE_EXPR_RTL (expr) = 0;
-      break;
-
-    case TARGET_EXPR:
-      /* Don't mess with a TARGET_EXPR that hasn't been expanded.
-         It's OK for this to happen if it was part of a subtree that
-         isn't immediately expanded, such as operand 2 of another
-         TARGET_EXPR.  */
-      if (TREE_OPERAND (expr, 1))
-       break;
-
-      TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
-      TREE_OPERAND (expr, 3) = NULL_TREE;
-      break;
-
-    case RTL_EXPR:
-      /* I don't yet know how to emit a sequence multiple times.  */
-      if (RTL_EXPR_SEQUENCE (expr) != 0)
-       abort ();
-      break;
-
-    default:
-      break;
-    }
-}
-
-/* Return 0 if it is safe to evaluate EXPR multiple times,
-   return 1 if it is safe if EXPR is unsaved afterward, or
-   return 2 if it is completely unsafe.
-
-   This assumes that CALL_EXPRs and TARGET_EXPRs are never replicated in
-   an expression tree, so that it safe to unsave them and the surrounding
-   context will be correct.
-
-   SAVE_EXPRs basically *only* appear replicated in an expression tree,
-   occasionally across the whole of a function.  It is therefore only
-   safe to unsave a SAVE_EXPR if you know that all occurrences appear
-   below the UNSAVE_EXPR.
-
-   RTL_EXPRs consume their rtl during evaluation.  It is therefore
-   never possible to unsave them.  */
-
-int
-unsafe_for_reeval (tree expr)
-{
-  int unsafeness = 0;
-  enum tree_code code;
-  int i, tmp, tmp2;
-  tree exp;
-  int first_rtl;
-
-  if (expr == NULL_TREE)
-    return 1;
-
-  code = TREE_CODE (expr);
-  first_rtl = first_rtl_op (code);
-
-  switch (code)
-    {
-    case SAVE_EXPR:
-    case RTL_EXPR:
-      return 2;
-
-      /* A label can only be emitted once.  */
-    case LABEL_EXPR:
-      return 1;
-
-    case BIND_EXPR:
-      unsafeness = 1;
-      break;
-
-    case TREE_LIST:
-      for (exp = expr; exp != 0; exp = TREE_CHAIN (exp))
-       {
-         tmp = unsafe_for_reeval (TREE_VALUE (exp));
-         unsafeness = MAX (tmp, unsafeness);
-       }
-
-      return unsafeness;
-
-    case CALL_EXPR:
-      tmp2 = unsafe_for_reeval (TREE_OPERAND (expr, 0));
-      tmp = unsafe_for_reeval (TREE_OPERAND (expr, 1));
-      return MAX (MAX (tmp, 1), tmp2);
-
-    case TARGET_EXPR:
-      unsafeness = 1;
-      break;
-
-    case EXIT_BLOCK_EXPR:
-      /* EXIT_BLOCK_LABELED_BLOCK, a.k.a. TREE_OPERAND (expr, 0), holds
-        a reference to an ancestor LABELED_BLOCK, so we need to avoid
-        unbounded recursion in the 'e' traversal code below.  */
-      exp = EXIT_BLOCK_RETURN (expr);
-      return exp ? unsafe_for_reeval (exp) : 0;
-
-    default:
-      tmp = lang_hooks.unsafe_for_reeval (expr);
-      if (tmp >= 0)
-       return tmp;
-      break;
-    }
-
-  switch (TREE_CODE_CLASS (code))
-    {
-    case 'c':  /* a constant */
-    case 't':  /* a type node */
-    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
-    case 'd':  /* A decl node */
-      return 0;
-
-    case 'e':  /* an expression */
-    case 'r':  /* a reference */
-    case 's':  /* an expression with side effects */
-    case '<':  /* a comparison expression */
-    case '2':  /* a binary arithmetic expression */
-    case '1':  /* a unary arithmetic expression */
-      for (i = first_rtl - 1; i >= 0; i--)
-       {
-         tmp = unsafe_for_reeval (TREE_OPERAND (expr, i));
-         unsafeness = MAX (tmp, unsafeness);
-       }
-
-      return unsafeness;
-
-    default:
-      return 2;
-    }
-}
 \f
 /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
    or offset that depends on a field within a record.  */
@@ -1670,7 +1579,6 @@ bool
 contains_placeholder_p (tree exp)
 {
   enum tree_code code;
-  int result;
 
   if (!exp)
     return 0;
@@ -1708,19 +1616,6 @@ contains_placeholder_p (tree exp)
                  || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
                  || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
 
-       case SAVE_EXPR:
-         /* If we already know this doesn't have a placeholder, don't
-            check again.  */
-         if (SAVE_EXPR_NOPLACEHOLDER (exp) || SAVE_EXPR_RTL (exp) != 0)
-           return 0;
-
-         SAVE_EXPR_NOPLACEHOLDER (exp) = 1;
-         result = CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
-         if (result)
-           SAVE_EXPR_NOPLACEHOLDER (exp) = 0;
-
-         return result;
-
        default:
          break;
        }
@@ -1858,7 +1753,6 @@ has_cleanups (tree exp)
   switch (TREE_CODE (exp))
     {
     case TARGET_EXPR:
-    case GOTO_SUBROUTINE_EXPR:
     case WITH_CLEANUP_EXPR:
       return 1;
 
@@ -1874,6 +1768,10 @@ has_cleanups (tree exp)
        }
       return 0;
 
+    case DECL_EXPR:
+      return (DECL_INITIAL (DECL_EXPR_DECL (exp))
+             && has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp))));
+
     default:
       break;
     }
@@ -1938,8 +1836,7 @@ substitute_in_expr (tree exp, tree f, tree r)
         && TREE_OPERAND (exp, 1) == f)
        return r;
 
-     /* If this expression hasn't been completed let, leave it
-       alone.  */
+     /* If this expression hasn't been completed let, leave it alone.  */
      if (TREE_CODE (inner) == PLACEHOLDER_EXPR && TREE_TYPE (inner) == 0)
        return exp;
 
@@ -1947,7 +1844,8 @@ substitute_in_expr (tree exp, tree f, tree r)
      if (op0 == TREE_OPERAND (exp, 0))
        return exp;
 
-     new = fold (build (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1)));
+     new = fold (build3 (COMPONENT_REF, TREE_TYPE (exp),
+                        op0, TREE_OPERAND (exp, 1), NULL_TREE));
    }
   else
     switch (TREE_CODE_CLASS (code))
@@ -2177,7 +2075,7 @@ stabilize_reference (tree ref)
     case COMPONENT_REF:
       result = build_nt (COMPONENT_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        TREE_OPERAND (ref, 1));
+                        TREE_OPERAND (ref, 1), NULL_TREE);
       break;
 
     case BIT_FIELD_REF:
@@ -2190,13 +2088,15 @@ stabilize_reference (tree ref)
     case ARRAY_REF:
       result = build_nt (ARRAY_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
+                        TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
       break;
 
     case ARRAY_RANGE_REF:
       result = build_nt (ARRAY_RANGE_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
+                        TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
       break;
 
     case COMPOUND_EXPR:
@@ -2205,13 +2105,6 @@ stabilize_reference (tree ref)
         volatiles.  */
       return stabilize_reference_1 (ref);
 
-    case RTL_EXPR:
-      result = build1 (INDIRECT_REF, TREE_TYPE (ref),
-                      save_expr (build1 (ADDR_EXPR,
-                                         build_pointer_type (TREE_TYPE (ref)),
-                                         ref)));
-      break;
-
       /* If arg isn't a kind of lvalue we recognize, make no change.
         Caller should recognize the error for an invalid lvalue.  */
     default:
@@ -2312,41 +2205,81 @@ stabilize_reference_1 (tree e)
 \f
 /* Low-level constructors for expressions.  */
 
-/* A helper function for build1 and constant folders.
-   Set TREE_CONSTANT and TREE_INVARIANT for an ADDR_EXPR.  */
+/* A helper function for build1 and constant folders.  Set TREE_CONSTANT,
+   TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
 
 void
 recompute_tree_invarant_for_addr_expr (tree t)
 {
-  tree node = TREE_OPERAND (t, 0);
-  bool tc = false, ti = false;
+  tree node;
+  bool tc = true, ti = true, se = false;
 
-  /* Addresses of constants and static variables are constant;
-     all other decl addresses are invariant.  */
-  if (staticp (node))
-    tc = ti = true;
-  else
+  /* We started out assuming this address is both invariant and constant, but
+     does not have side effects.  Now go down any handled components and see if
+     any of them involve offsets that are either non-constant or non-invariant.
+     Also check for side-effects.
+
+     ??? Note that this code makes no attempt to deal with the case where
+     taking the address of something causes a copy due to misalignment.  */
+
+#define UPDATE_TITCSE(NODE)  \
+do { tree _node = (NODE); \
+     if (_node && !TREE_INVARIANT (_node)) ti = false; \
+     if (_node && !TREE_CONSTANT (_node)) tc = false; \
+     if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
+
+  for (node = TREE_OPERAND (t, 0); handled_component_p (node);
+       node = TREE_OPERAND (node, 0))
     {
-      /* Step past constant offsets.  */
-      while (1)
+      /* If the first operand doesn't have an ARRAY_TYPE, this is a bogus
+        array reference (probably made temporarily by the G++ front end),
+        so ignore all the operands.  */
+      if ((TREE_CODE (node) == ARRAY_REF
+          || TREE_CODE (node) == ARRAY_RANGE_REF)
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
        {
-         if (TREE_CODE (node) == COMPONENT_REF
-             && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL
-             && ! DECL_BIT_FIELD (TREE_OPERAND (node, 1)))
-           ;
-         else if (TREE_CODE (node) == ARRAY_REF
-                  && TREE_CONSTANT (TREE_OPERAND (node, 1)))
-           ;
-         else
-           break;
-         node = TREE_OPERAND (node, 0);
+         UPDATE_TITCSE (TREE_OPERAND (node, 1));
+         UPDATE_TITCSE (array_ref_low_bound (node));
+         UPDATE_TITCSE (array_ref_element_size (node));
        }
-      if (DECL_P (node))
-        ti = true;
+      /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
+        FIELD_DECL, apparently.  The G++ front end can put something else
+        there, at least temporarily.  */
+      else if (TREE_CODE (node) == COMPONENT_REF
+              && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
+       UPDATE_TITCSE (component_ref_field_offset (node));
+      else if (TREE_CODE (node) == BIT_FIELD_REF)
+       UPDATE_TITCSE (TREE_OPERAND (node, 2));
+    }
+
+  /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
+     it.  If it's a decl, it's invariant and constant if the decl is static.
+     It's also invariant if it's a decl in the current function.  (Taking the
+     address of a volatile variable is not volatile.)  If it's a constant,
+     the address is both invariant and constant.  Otherwise it's neither.  */
+  if (TREE_CODE (node) == INDIRECT_REF)
+    UPDATE_TITCSE (node);
+  else if (DECL_P (node))
+    {
+      if (staticp (node))
+       ;
+      else if (decl_function_context (node) == current_function_decl)
+       tc = false;
+      else
+       ti = tc = false;
+    }
+  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c')
+    ;
+  else
+    {
+      ti = tc = false;
+      se |= TREE_SIDE_EFFECTS (node);
     }
 
   TREE_CONSTANT (t) = tc;
   TREE_INVARIANT (t) = ti;
+  TREE_SIDE_EFFECTS (t) = se;
+#undef UPDATE_TITCSE
 }
 
 /* Build an expression of code CODE, data type TYPE, and operands as
@@ -2354,7 +2287,7 @@ recompute_tree_invarant_for_addr_expr (tree t)
    Constants, decls, types and misc nodes cannot be.
 
    We define 5 non-variadic functions, from 0 to 4 arguments.  This is
-   enough for all extant tree codes.  These functions can be called 
+   enough for all extant tree codes.  These functions can be called
    directly (preferably!), but can also be obtained via GCC preprocessor
    magic within the build macro.  */
 
@@ -2413,7 +2346,11 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
   TREE_SET_CODE (t, code);
 
   TREE_TYPE (t) = type;
+#ifdef USE_MAPPED_LOCATION
+  SET_EXPR_LOCATION (t, UNKNOWN_LOCATION);
+#else
   SET_EXPR_LOCUS (t, NULL);
+#endif
   TREE_COMPLEXITY (t) = 0;
   TREE_OPERAND (t, 0) = node;
   TREE_BLOCK (t) = NULL_TREE;
@@ -2430,7 +2367,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
     case INIT_EXPR:
     case MODIFY_EXPR:
     case VA_ARG_EXPR:
-    case RTL_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -2449,27 +2385,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 
     case ADDR_EXPR:
       if (node)
-       {
-         recompute_tree_invarant_for_addr_expr (t);
-
-         /* The address of a volatile decl or reference does not have
-            side-effects.  But be careful not to ignore side-effects from
-            other sources deeper in the expression--if node is a _REF and
-            one of its operands has side-effects, so do we.  */
-         if (TREE_THIS_VOLATILE (node))
-           {
-             TREE_SIDE_EFFECTS (t) = 0;
-             if (!DECL_P (node))
-               {
-                 int i = first_rtl_op (TREE_CODE (node)) - 1;
-                 for (; i >= 0; --i)
-                   {
-                     if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i)))
-                       TREE_SIDE_EFFECTS (t) = 1;
-                   }
-               }
-           }
-       }
+       recompute_tree_invarant_for_addr_expr (t);
       break;
 
     default:
@@ -2478,6 +2394,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
        TREE_CONSTANT (t) = 1;
       if (TREE_CODE_CLASS (code) == '1' && node && TREE_INVARIANT (node))
        TREE_INVARIANT (t) = 1;
+      if (TREE_CODE_CLASS (code) == 'r' && node && TREE_THIS_VOLATILE (node))
+       TREE_THIS_VOLATILE (t) = 1;
       break;
     }
 
@@ -2535,7 +2453,9 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   TREE_READONLY (t) = read_only;
   TREE_CONSTANT (t) = constant;
   TREE_INVARIANT (t) = invariant;
-  TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_SIDE_EFFECTS (t) = side_effects;
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2584,7 +2504,9 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
          }
     }
 
-  TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_SIDE_EFFECTS (t) = side_effects;
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2614,7 +2536,9 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   PROCESS_ARG(2);
   PROCESS_ARG(3);
 
-  TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_SIDE_EFFECTS (t) = side_effects;
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2715,6 +2639,11 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
   else if (code == FUNCTION_DECL)
     DECL_MODE (t) = FUNCTION_MODE;
 
+  /* Set default visibility to whatever the user supplied with
+     visibility_specified depending on #pragma GCC visibility.  */
+  DECL_VISIBILITY (t) = default_visibility;
+  DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma;
+
   return t;
 }
 \f
@@ -2735,7 +2664,29 @@ build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks,
   return block;
 }
 
+#if 1 /* ! defined(USE_MAPPED_LOCATION) */
+/* ??? gengtype doesn't handle conditionals */
 static GTY(()) tree last_annotated_node;
+#endif
+
+#ifdef USE_MAPPED_LOCATION
+
+expanded_location
+expand_location (source_location loc)
+{
+  expanded_location xloc;
+  if (loc == 0) { xloc.file = NULL; xloc.line = 0;  xloc.column = 0; }
+  else
+    {
+      const struct line_map *map = linemap_lookup (&line_table, loc);
+      xloc.file = map->to_file;
+      xloc.line = SOURCE_LINE (map, loc);
+      xloc.column = SOURCE_COLUMN (map, loc);
+    };
+  return xloc;
+}
+
+#else
 
 /* Record the exact location where an expression or an identifier were
    encountered.  */
@@ -2779,6 +2730,7 @@ annotate_with_locus (tree node, location_t locus)
 {
   annotate_with_file_line (node, locus.file, locus.line);
 }
+#endif
 \f
 /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
    is ATTRIBUTE.  */
@@ -2991,7 +2943,7 @@ merge_decl_attributes (tree olddecl, tree newdecl)
                           DECL_ATTRIBUTES (newdecl));
 }
 
-#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 
 /* Specialization of merge_decl_attributes for various Windows targets.
 
@@ -3044,6 +2996,81 @@ merge_dllimport_decl_attributes (tree old, tree new)
   return a;
 }
 
+/* Handle a "dllimport" or "dllexport" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+tree
+handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
+                     bool *no_add_attrs)
+{
+  tree node = *pnode;
+
+  /* These attributes may apply to structure and union types being created,
+     but otherwise should pass to the declaration involved.  */
+  if (!DECL_P (node))
+    {
+      if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
+                  | (int) ATTR_FLAG_ARRAY_NEXT))
+       {
+         *no_add_attrs = true;
+         return tree_cons (name, args, NULL_TREE);
+       }
+      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
+       {
+         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+         *no_add_attrs = true;
+       }
+
+      return NULL_TREE;
+    }
+
+  /* Report error on dllimport ambiguities seen now before they cause
+     any damage.  */
+  if (is_attribute_p ("dllimport", name))
+    {
+      /* Like MS, treat definition of dllimported variables and
+        non-inlined functions on declaration as syntax errors.  We
+        allow the attribute for function definitions if declared
+        inline.  */
+      if (TREE_CODE (node) == FUNCTION_DECL  && DECL_INITIAL (node)
+          && !DECL_DECLARED_INLINE_P (node))
+       {
+         error ("%Jfunction `%D' definition is marked dllimport.", node, node);
+         *no_add_attrs = true;
+       }
+
+      else if (TREE_CODE (node) == VAR_DECL)
+       {
+         if (DECL_INITIAL (node))
+           {
+             error ("%Jvariable `%D' definition is marked dllimport.",
+                    node, node);
+             *no_add_attrs = true;
+           }
+
+         /* `extern' needn't be specified with dllimport.
+            Specify `extern' now and hope for the best.  Sigh.  */
+         DECL_EXTERNAL (node) = 1;
+         /* Also, implicitly give dllimport'd variables declared within
+            a function global scope, unless declared static.  */
+         if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
+           TREE_PUBLIC (node) = 1;
+       }
+    }
+
+  /*  Report error if symbol is not accessible at global scope.  */
+  if (!TREE_PUBLIC (node)
+      && (TREE_CODE (node) == VAR_DECL
+         || TREE_CODE (node) == FUNCTION_DECL))
+    {
+      error ("%Jexternal linkage required for symbol '%D' because of "
+            "'%s' attribute.", node, node, IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES  */
 \f
 /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
@@ -3106,29 +3133,45 @@ build_qualified_type (tree type, int type_quals)
   /* If not, build it.  */
   if (!t)
     {
-      t = build_type_copy (type);
+      t = build_variant_type_copy (type);
       set_type_quals (t, type_quals);
     }
 
   return t;
 }
 
+/* Create a new distinct copy of TYPE.  The new type is made its own
+   MAIN_VARIANT.  */
+
+tree
+build_distinct_type_copy (tree type)
+{
+  tree t = copy_node (type);
+  
+  TYPE_POINTER_TO (t) = 0;
+  TYPE_REFERENCE_TO (t) = 0;
+
+  /* Make it its own variant.  */
+  TYPE_MAIN_VARIANT (t) = t;
+  TYPE_NEXT_VARIANT (t) = 0;
+  
+  return t;
+}
+
 /* Create a new variant of TYPE, equivalent but distinct.
    This is so the caller can modify it.  */
 
 tree
-build_type_copy (tree type)
+build_variant_type_copy (tree type)
 {
   tree t, m = TYPE_MAIN_VARIANT (type);
 
-  t = copy_node (type);
-
-  TYPE_POINTER_TO (t) = 0;
-  TYPE_REFERENCE_TO (t) = 0;
-
-  /* Add this type to the chain of variants of TYPE.  */
+  t = build_distinct_type_copy (type);
+  
+  /* Add the new type to the chain of variants of TYPE.  */
   TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
   TYPE_NEXT_VARIANT (m) = t;
+  TYPE_MAIN_VARIANT (t) = m;
 
   return t;
 }
@@ -3201,7 +3244,7 @@ type_hash_eq (const void *va, const void *vb)
               || tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
                                      TYPE_MAX_VALUE (b->type)))
              && (TYPE_MIN_VALUE (a->type) == TYPE_MIN_VALUE (b->type)
-                 && tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
+                 || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
                                         TYPE_MIN_VALUE (b->type))));
 
     case OFFSET_TYPE:
@@ -3216,7 +3259,7 @@ type_hash_eq (const void *va, const void *vb)
                      && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
                      && type_list_equal (TYPE_ARG_TYPES (a->type),
                                          TYPE_ARG_TYPES (b->type)))));
-                                                                     
+
     case ARRAY_TYPE:
     case SET_TYPE:
       return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
@@ -3669,7 +3712,7 @@ simple_cst_equal (tree t1, tree t2)
                         TREE_STRING_LENGTH (t1)));
 
     case CONSTRUCTOR:
-      return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1), 
+      return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1),
                                    CONSTRUCTOR_ELTS (t2));
 
     case SAVE_EXPR:
@@ -3812,6 +3855,13 @@ commutative_tree_code (enum tree_code code)
     case BIT_AND_EXPR:
     case NE_EXPR:
     case EQ_EXPR:
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_XOR_EXPR:
+    case TRUTH_OR_EXPR:
       return true;
 
     default:
@@ -3839,7 +3889,8 @@ iterative_hash_expr (tree t, hashval_t val)
   code = TREE_CODE (t);
   class = TREE_CODE_CLASS (code);
 
-  if (class == 'd')
+  if (class == 'd'
+      || TREE_CODE (t) == VALUE_HANDLE)
     {
       /* Decls we can just compare by pointer.  */
       val = iterative_hash_object (t, val);
@@ -3854,8 +3905,11 @@ iterative_hash_expr (tree t, hashval_t val)
          val = iterative_hash_object (TREE_INT_CST_HIGH (t), val);
        }
       else if (code == REAL_CST)
-       val = iterative_hash (TREE_REAL_CST_PTR (t),
-                             sizeof (REAL_VALUE_TYPE), val);
+       {
+         unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
+
+         val = iterative_hash (&val2, sizeof (unsigned int), val);
+       }
       else if (code == STRING_CST)
        val = iterative_hash (TREE_STRING_POINTER (t),
                              TREE_STRING_LENGTH (t), val);
@@ -4082,6 +4136,28 @@ build_index_type (tree maxval)
     return itype;
 }
 
+/* Builds a signed or unsigned integer type of precision PRECISION.
+   Used for C bitfields whose precision does not match that of
+   built-in target types.  */
+tree
+build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
+                               int unsignedp)
+{
+  tree itype = make_node (INTEGER_TYPE);
+
+  TYPE_PRECISION (itype) = precision;
+
+  if (unsignedp)
+    fixup_unsigned_type (itype);
+  else
+    fixup_signed_type (itype);
+
+  if (host_integerp (TYPE_MAX_VALUE (itype), 1))
+    return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
+
+  return itype;
+}
+
 /* Create a range of some discrete type TYPE (an INTEGER_TYPE,
    ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with
    low bound LOWVAL and high bound HIGHVAL.
@@ -4278,7 +4354,7 @@ build_method_type (tree basetype, tree type)
   if (TREE_CODE (type) != FUNCTION_TYPE)
     abort ();
 
-  return build_method_type_directly (basetype, 
+  return build_method_type_directly (basetype,
                                     TREE_TYPE (type),
                                     TYPE_ARG_TYPES (type));
 }
@@ -4467,8 +4543,8 @@ get_unwidened (tree op, tree for_type)
          && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1)))
          && (! uns || final_prec <= innerprec || unsignedp))
        {
-         win = build (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                      TREE_OPERAND (op, 1));
+         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
+                       TREE_OPERAND (op, 1), NULL_TREE);
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
@@ -4488,6 +4564,7 @@ get_narrower (tree op, int *unsignedp_ptr)
   int uns = 0;
   int first = 1;
   tree win = op;
+  bool integral_p = INTEGRAL_TYPE_P (TREE_TYPE (op));
 
   while (TREE_CODE (op) == NOP_EXPR)
     {
@@ -4524,6 +4601,10 @@ get_narrower (tree op, int *unsignedp_ptr)
            uns = TYPE_UNSIGNED (TREE_TYPE (op));
          first = 0;
          op = TREE_OPERAND (op, 0);
+         /* Keep trying to narrow, but don't assign op to win if it
+            would turn an integral type into something else.  */
+         if (INTEGRAL_TYPE_P (TREE_TYPE (op)) != integral_p)
+           continue;
        }
 
       win = op;
@@ -4533,7 +4614,8 @@ get_narrower (tree op, int *unsignedp_ptr)
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
       /* Ensure field is laid out already.  */
-      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
+      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
+      && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
     {
       unsigned HOST_WIDE_INT innerprec
        = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
@@ -4556,8 +4638,8 @@ get_narrower (tree op, int *unsignedp_ptr)
        {
          if (first)
            uns = DECL_UNSIGNED (TREE_OPERAND (op, 1));
-         win = build (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                      TREE_OPERAND (op, 1));
+         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
+                       TREE_OPERAND (op, 1), NULL_TREE);
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
@@ -4628,25 +4710,55 @@ int_fits_type_p (tree c, tree type)
     {
       c = copy_node (c);
       TREE_TYPE (c) = type;
-      return !force_fit_type (c, 0);
+      c = force_fit_type (c, -1, false, false);
+      return !TREE_OVERFLOW (c);
     }
 }
 
+/* Subprogram of following function.  Called by walk_tree.
+
+   Return *TP if it is an automatic variable or parameter of the
+   function passed in as DATA.  */
+
+static tree
+find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
+{
+  tree fn = (tree) data;
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
+  else if (DECL_P (*tp) && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+    return *tp;
+
+  return NULL_TREE;
+}
+
 /* Returns true if T is, contains, or refers to a type with variable
-   size.  This concept is more general than that of C99 'variably
-   modified types': in C99, a struct type is never variably modified
-   because a VLA may not appear as a structure member.  However, in
-   GNU C code like:
+   size.  If FN is nonzero, only return true if a modifier of the type
+   or position of FN is a variable or parameter inside FN.
+
+   This concept is more general than that of C99 'variably modified types':
+   in C99, a struct type is never variably modified because a VLA may not
+   appear as a structure member.  However, in GNU C code like:
 
      struct S { int i[f()]; };
 
    is valid, and other languages may define similar constructs.  */
 
 bool
-variably_modified_type_p (tree type)
+variably_modified_type_p (tree type, tree fn)
 {
   tree t;
 
+/* Test if T is either variable (if FN is zero) or an expression containing
+   a variable in FN.  */
+#define RETURN_TRUE_IF_VAR(T)                                          \
+  do { tree _t = (T);                                                  \
+    if (_t && _t != error_mark_node && TREE_CODE (_t) != INTEGER_CST   \
+        && (!fn || walk_tree (&_t, find_var_from_fn, fn, NULL)))       \
+      return true;  } while (0)
+
   if (type == error_mark_node)
     return false;
 
@@ -4655,9 +4767,8 @@ variably_modified_type_p (tree type)
      We do not yet have a representation of the C99 '[*]' syntax.
      When a representation is chosen, this function should be modified
      to test for that case as well.  */
-  t = TYPE_SIZE (type);
-  if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-    return true;
+  RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
+  RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type));
 
   switch (TREE_CODE (type))
     {
@@ -4666,7 +4777,7 @@ variably_modified_type_p (tree type)
     case ARRAY_TYPE:
     case SET_TYPE:
     case VECTOR_TYPE:
-      if (variably_modified_type_p (TREE_TYPE (type)))
+      if (variably_modified_type_p (TREE_TYPE (type), fn))
        return true;
       break;
 
@@ -4674,13 +4785,13 @@ variably_modified_type_p (tree type)
     case METHOD_TYPE:
       /* If TYPE is a function type, it is variably modified if any of the
          parameters or the return type are variably modified.  */
-      if (variably_modified_type_p (TREE_TYPE (type)))
+      if (variably_modified_type_p (TREE_TYPE (type), fn))
          return true;
 
       for (t = TYPE_ARG_TYPES (type);
           t && t != void_list_node;
           t = TREE_CHAIN (t))
-       if (variably_modified_type_p (TREE_VALUE (t)))
+       if (variably_modified_type_p (TREE_VALUE (t), fn))
          return true;
       break;
 
@@ -4691,13 +4802,8 @@ variably_modified_type_p (tree type)
     case CHAR_TYPE:
       /* Scalar types are variably modified if their end points
         aren't constant.  */
-      t = TYPE_MIN_VALUE (type);
-      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-       return true;
-
-      t = TYPE_MAX_VALUE (type);
-      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
-       return true;
+      RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type));
+      RETURN_TRUE_IF_VAR (TYPE_MAX_VALUE (type));
       break;
 
     case RECORD_TYPE:
@@ -4710,14 +4816,12 @@ variably_modified_type_p (tree type)
       for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
        if (TREE_CODE (t) == FIELD_DECL)
          {
-           tree t1 = DECL_FIELD_OFFSET (t);
-
-           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
-             return true;
+           RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t));
+           RETURN_TRUE_IF_VAR (DECL_SIZE (t));
+           RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t));
 
-           t1 = DECL_SIZE (t);
-           if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
-             return true;
+           if (TREE_CODE (type) == QUAL_UNION_TYPE)
+             RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t));
          }
        break;
 
@@ -4727,7 +4831,9 @@ variably_modified_type_p (tree type)
 
   /* The current language may have other cases to check, but in general,
      all other types are not variably modified.  */
-  return lang_hooks.tree_inlining.var_mod_type_p (type);
+  return lang_hooks.tree_inlining.var_mod_type_p (type, fn);
+
+#undef RETURN_TRUE_IF_VAR
 }
 
 /* Given a DECL or TYPE, return the scope in which it was declared, or
@@ -4750,9 +4856,6 @@ decl_function_context (tree decl)
   if (TREE_CODE (decl) == ERROR_MARK)
     return 0;
 
-  if (TREE_CODE (decl) == SAVE_EXPR)
-    context = SAVE_EXPR_CONTEXT (decl);
-
   /* C++ virtual functions use DECL_CONTEXT for the class of the vtable
      where we look up the function at runtime.  Such functions always take
      a first argument of type 'pointer to real context'.
@@ -4797,16 +4900,16 @@ decl_type_context (tree decl)
       case UNION_TYPE:
       case QUAL_UNION_TYPE:
        return context;
-       
+
       case TYPE_DECL:
       case FUNCTION_DECL:
        context = DECL_CONTEXT (context);
        break;
-       
+
       case BLOCK:
        context = BLOCK_SUPERCONTEXT (context);
        break;
-       
+
       default:
        abort ();
       }
@@ -4845,7 +4948,7 @@ get_callee_fndecl (tree call)
   if (TREE_CODE (addr) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
     return TREE_OPERAND (addr, 0);
-  
+
   /* We couldn't figure out what was being called.  Maybe the front
      end has some idea.  */
   return lang_hooks.lang_get_callee_fndecl (call);
@@ -4897,11 +5000,11 @@ crc32_string (unsigned chksum, const char *string)
     {
       unsigned value = *string << 24;
       unsigned ix;
-      
+
       for (ix = 8; ix--; value <<= 1)
        {
          unsigned feedback;
-         
+
          feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
          chksum <<= 1;
          chksum ^= feedback;
@@ -5085,75 +5188,80 @@ get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
 \f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 
-/* Complain that the tree code of NODE does not match the expected CODE.
-   FILE, LINE, and FUNCTION are of the caller.  */
+/* Complain that the tree code of NODE does not match the expected 0
+   terminated list of trailing codes. FILE, LINE, and FUNCTION are of
+   the caller.  */
 
 void
-tree_check_failed (const tree node, enum tree_code code, const char *file,
-                  int line, const char *function)
-{
+tree_check_failed (const tree node, const char *file,
+                  int line, const char *function, ...)
+{
+  va_list args;
+  char *buffer;
+  unsigned length = 0;
+  int code;
+
+  va_start (args, function);
+  while ((code = va_arg (args, int)))
+    length += 4 + strlen (tree_code_name[code]);
+  va_end (args);
+  va_start (args, function);
+  buffer = alloca (length);
+  length = 0;
+  while ((code = va_arg (args, int)))
+    {
+      if (length)
+       {
+         strcpy (buffer + length, " or ");
+         length += 4;
+       }
+      strcpy (buffer + length, tree_code_name[code]);
+      length += strlen (tree_code_name[code]);
+    }
+  va_end (args);
+
   internal_error ("tree check: expected %s, have %s in %s, at %s:%d",
-                 tree_code_name[code], tree_code_name[TREE_CODE (node)],
+                 buffer, tree_code_name[TREE_CODE (node)],
                  function, trim_filename (file), line);
 }
 
-/* Similar to above except that we allowed the code to be one of two
-   different codes.  */
+/* Complain that the tree code of NODE does match the expected 0
+   terminated list of trailing codes. FILE, LINE, and FUNCTION are of
+   the caller.  */
 
 void
-tree_check2_failed (const tree node, enum tree_code code1,
-                   enum tree_code code2, const char *file,
-                   int line, const char *function)
-{
-  internal_error ("tree check: expected %s or %s, have %s in %s, at %s:%d",
-                 tree_code_name[code1], tree_code_name[code2],
-                 tree_code_name[TREE_CODE (node)],
-                 function, trim_filename (file), line);
-}
-
-/* Likewise for three different codes.  */
+tree_not_check_failed (const tree node, const char *file,
+                      int line, const char *function, ...)
+{
+  va_list args;
+  char *buffer;
+  unsigned length = 0;
+  int code;
+
+  va_start (args, function);
+  while ((code = va_arg (args, int)))
+    length += 4 + strlen (tree_code_name[code]);
+  va_end (args);
+  va_start (args, function);
+  buffer = alloca (length);
+  length = 0;
+  while ((code = va_arg (args, int)))
+    {
+      if (length)
+       {
+         strcpy (buffer + length, " or ");
+         length += 4;
+       }
+      strcpy (buffer + length, tree_code_name[code]);
+      length += strlen (tree_code_name[code]);
+    }
+  va_end (args);
 
-void
-tree_check3_failed (const tree node, enum tree_code code1,
-                   enum tree_code code2, enum tree_code code3,
-                   const char *file, int line, const char *function)
-{
-  internal_error ("tree check: expected %s, %s or %s; have %s in %s, at %s:%d",
-                 tree_code_name[code1], tree_code_name[code2],
-                 tree_code_name[code3], tree_code_name[TREE_CODE (node)],
+  internal_error ("tree check: expected none of %s, have %s in %s, at %s:%d",
+                 buffer, tree_code_name[TREE_CODE (node)],
                  function, trim_filename (file), line);
 }
 
-/* ... and for four different codes.  */
-
-void
-tree_check4_failed (const tree node, enum tree_code code1,
-                   enum tree_code code2, enum tree_code code3,
-                   enum tree_code code4, const char *file, int line,
-                   const char *function)
-{
-  internal_error
-    ("tree check: expected %s, %s, %s or %s; have %s in %s, at %s:%d",
-     tree_code_name[code1], tree_code_name[code2], tree_code_name[code3],
-     tree_code_name[code4], tree_code_name[TREE_CODE (node)], function,
-     trim_filename (file), line);
-}
-
-/* ... and for five different codes.  */
-
-void
-tree_check5_failed (const tree node, enum tree_code code1,
-                   enum tree_code code2, enum tree_code code3,
-                   enum tree_code code4, enum tree_code code5,
-                   const char *file, int line, const char *function)
-{
-  internal_error
-    ("tree check: expected %s, %s, %s, %s or %s; have %s in %s, at %s:%d",
-     tree_code_name[code1], tree_code_name[code2], tree_code_name[code3],
-     tree_code_name[code4], tree_code_name[code5],
-     tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
-}
-
 /* Similar to tree_check_failed, except that we check for a class of tree
    code, given in CL.  */
 
@@ -5179,18 +5287,6 @@ tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
      idx + 1, len, function, trim_filename (file), line);
 }
 
-/* Similar to above, except that the check is for the bounds of a EPHI_NODE's
-   (dynamically sized) vector.  */
-
-void
-ephi_node_elt_check_failed (int idx, int len, const char *file, int line,
-                           const char *function)
-{
-  internal_error
-    ("tree check: accessed elt %d of ephi_node with %d elts in %s, at %s:%d",
-     idx + 1, len, function, trim_filename (file), line);
-}
-
 /* Similar to above, except that the check is for the bounds of a PHI_NODE's
    (dynamically sized) vector.  */
 
@@ -5217,18 +5313,23 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file,
 }
 #endif /* ENABLE_TREE_CHECKING */
 \f
-/* For a new vector type node T, build the information necessary for
-   debugging output.  */
+/* Create a new vector type node holding SUBPARTS units of type INNERTYPE,
+   and mapped to the machine mode MODE.  Initialize its fields and build
+   the information necessary for debugging output.  */
 
-static void
-finish_vector_type (tree t)
+static tree
+make_vector_type (tree innertype, int nunits, enum machine_mode mode)
 {
+  tree t = make_node (VECTOR_TYPE);
+
+  TREE_TYPE (t) = innertype;
+  TYPE_VECTOR_SUBPARTS (t) = nunits;
+  TYPE_MODE (t) = mode;
   layout_type (t);
 
   {
-    tree index = build_int_2 (TYPE_VECTOR_SUBPARTS (t) - 1, 0);
-    tree array = build_array_type (TREE_TYPE (t),
-                                  build_index_type (index));
+    tree index = build_int_cst (NULL_TREE, nunits - 1, 0);
+    tree array = build_array_type (innertype, build_index_type (index));
     tree rt = make_node (RECORD_TYPE);
 
     TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
@@ -5241,6 +5342,8 @@ finish_vector_type (tree t)
        numbers equal.  */
     TYPE_UID (rt) = TYPE_UID (t);
   }
+
+  return t;
 }
 
 static tree
@@ -5269,12 +5372,12 @@ make_or_reuse_type (unsigned size, int unsignedp)
    this function to select one of the types as sizetype.  */
 
 void
-build_common_tree_nodes (int signed_char)
+build_common_tree_nodes (bool signed_char, bool signed_sizetype)
 {
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
-  initialize_sizetypes ();
+  initialize_sizetypes (signed_sizetype);
 
   /* Define both `signed char' and `unsigned char'.  */
   signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
@@ -5302,8 +5405,7 @@ build_common_tree_nodes (int signed_char)
      boolean_type_node before calling build_common_tree_nodes_2.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
-  TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0);
-  TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
+  TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1, 0);
   TYPE_PRECISION (boolean_type_node) = 1;
 
   /* Fill in the rest of the sized types.  Reuse existing type nodes
@@ -5319,7 +5421,7 @@ build_common_tree_nodes (int signed_char)
   unsigned_intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 1);
   unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
   unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
-  
+
   access_public_node = get_identifier ("public");
   access_protected_node = get_identifier ("protected");
   access_private_node = get_identifier ("private");
@@ -5332,9 +5434,9 @@ void
 build_common_tree_nodes_2 (int short_double)
 {
   /* Define these next since types below may used them.  */
-  integer_zero_node = build_int_2 (0, 0);
-  integer_one_node = build_int_2 (1, 0);
-  integer_minus_one_node = build_int_2 (-1, -1);
+  integer_zero_node = build_int_cst (NULL_TREE, 0, 0);
+  integer_one_node = build_int_cst (NULL_TREE, 1, 0);
+  integer_minus_one_node = build_int_cst (NULL_TREE, -1, -1);
 
   size_zero_node = size_int (0);
   size_one_node = size_int (1);
@@ -5353,13 +5455,14 @@ build_common_tree_nodes_2 (int short_double)
   TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
   TYPE_USER_ALIGN (void_type_node) = 0;
 
-  null_pointer_node = build_int_2 (0, 0);
-  TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
+  null_pointer_node = build_int_cst (build_pointer_type (void_type_node),
+                                    0, 0);
   layout_type (TREE_TYPE (null_pointer_node));
 
   ptr_type_node = build_pointer_type (void_type_node);
   const_ptr_type_node
     = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+  fileptr_type_node = ptr_type_node;
 
   float_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -5406,7 +5509,7 @@ build_common_tree_nodes_2 (int short_double)
        don't copy record types and let c_common_nodes_and_builtins()
        declare the type to be __builtin_va_list.  */
     if (TREE_CODE (t) != RECORD_TYPE)
-      t = build_type_copy (t);
+      t = build_variant_type_copy (t);
 
     va_list_type_node = t;
   }
@@ -5446,7 +5549,7 @@ reconstruct_complex_type (tree type, tree bottom)
     {
       inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
       outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner, 
+                                         inner,
                                          TYPE_ARG_TYPES (type));
     }
   else
@@ -5458,36 +5561,39 @@ reconstruct_complex_type (tree type, tree bottom)
   return outer;
 }
 
-/* Returns a vector tree node given a vector mode and inner type.  */
+/* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
+   the inner type.  */
 tree
 build_vector_type_for_mode (tree innertype, enum machine_mode mode)
 {
-  tree t;
-  t = make_node (VECTOR_TYPE);
-  TREE_TYPE (t) = innertype;
-  TYPE_MODE (t) = mode;
-  finish_vector_type (t);
-  return t;
-}
+  int nunits;
 
-/* Similarly, but takes inner type and units.  */
+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+      || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+    nunits = GET_MODE_NUNITS (mode);
 
-tree
-build_vector_type (tree innertype, int nunits)
-{
-  enum machine_mode innermode = TYPE_MODE (innertype);
-  enum machine_mode mode;
+  else if (GET_MODE_CLASS (mode) == MODE_INT)
+    {
+      /* Check that there are no leftover bits.  */
+      if (GET_MODE_BITSIZE (mode) % TREE_INT_CST_LOW (TYPE_SIZE (innertype)))
+       abort ();
 
-  if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
-    mode = MIN_MODE_VECTOR_FLOAT;
+      nunits = GET_MODE_BITSIZE (mode)
+              / TREE_INT_CST_LOW (TYPE_SIZE (innertype));
+    }
   else
-    mode = MIN_MODE_VECTOR_INT;
+    abort ();
 
-  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_NUNITS (mode) == nunits && GET_MODE_INNER (mode) == innermode)
-      return build_vector_type_for_mode (innertype, mode);
+  return make_vector_type (innertype, nunits, mode);
+}
 
-  return NULL_TREE;
+/* Similarly, but takes the inner type and number of units, which must be
+   a power of two.  */
+
+tree
+build_vector_type (tree innertype, int nunits)
+{
+  return make_vector_type (innertype, nunits, VOIDmode);
 }
 
 /* Given an initializer INIT, return TRUE if INIT is zero or some
@@ -5560,15 +5666,42 @@ build_empty_stmt (void)
   return build1 (NOP_EXPR, void_type_node, size_zero_node);
 }
 
+
+/* Returns true if it is possible to prove that the index of
+   an array access REF (an ARRAY_REF expression) falls into the
+   array bounds.  */
+
 bool
-is_essa_node (tree t)
+in_array_bounds_p (tree ref)
 {
-  if (TREE_CODE (t) == EPHI_NODE || TREE_CODE (t) == EUSE_NODE 
-      || TREE_CODE (t) == EEXIT_NODE || TREE_CODE (t) == EKILL_NODE)
-    return true;
-  return false;
+  tree idx = TREE_OPERAND (ref, 1);
+  tree min, max;
+
+  if (TREE_CODE (idx) != INTEGER_CST)
+    return false;
+
+  min = array_ref_low_bound (ref);
+  max = array_ref_up_bound (ref);
+  if (!min
+      || !max
+      || TREE_CODE (min) != INTEGER_CST
+      || TREE_CODE (max) != INTEGER_CST)
+    return false;
+
+  if (tree_int_cst_lt (idx, min)
+      || tree_int_cst_lt (max, idx))
+    return false;
+
+  return true;
 }
 
+/* Return true if T (assumed to be a DECL) is a global variable.  */
+
+bool
+is_global_var (tree t)
+{
+  return (TREE_STATIC (t) || DECL_EXTERNAL (t));
+}
 
 /* Return true if T (assumed to be a DECL) must be assigned a memory
    location.  */
@@ -5576,13 +5709,116 @@ is_essa_node (tree t)
 bool
 needs_to_live_in_memory (tree t)
 {
-  return (DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (t)
-         || TREE_STATIC (t)
-          || DECL_EXTERNAL (t)
-         || DECL_NONLOCAL (t)
+  return (TREE_ADDRESSABLE (t)
+         || is_global_var (t)
          || (TREE_CODE (t) == RESULT_DECL
-             && aggregate_value_p (t, current_function_decl))
-         || decl_function_context (t) != current_function_decl);
+             && aggregate_value_p (t, current_function_decl)));
+}
+
+/* There are situations in which a language considers record types
+   compatible which have different field lists.  Decide if two fields
+   are compatible.  It is assumed that the parent records are compatible.  */
+
+bool
+fields_compatible_p (tree f1, tree f2)
+{
+  if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1),
+                       DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST))
+    return false;
+
+  if (!operand_equal_p (DECL_FIELD_OFFSET (f1),
+                        DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
+    return false;
+
+  if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+    return false;
+
+  return true;
+}
+
+/* Locate within RECORD a field that is compatible with ORIG_FIELD.  */
+
+tree
+find_compatible_field (tree record, tree orig_field)
+{
+  tree f;
+
+  for (f = TYPE_FIELDS (record); f ; f = TREE_CHAIN (f))
+    if (TREE_CODE (f) == FIELD_DECL
+       && fields_compatible_p (f, orig_field))
+      return f;
+
+  /* ??? Why isn't this on the main fields list?  */
+  f = TYPE_VFIELD (record);
+  if (f && TREE_CODE (f) == FIELD_DECL
+      && fields_compatible_p (f, orig_field))
+    return f;
+
+  /* ??? We should abort here, but Java appears to do Bad Things
+     with inherited fields.  */
+  return orig_field;
+}
+
+/* Return value of a constant X.  */
+
+HOST_WIDE_INT
+int_cst_value (tree x)
+{
+  unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
+  unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
+  bool negative = ((val >> (bits - 1)) & 1) != 0;
+
+  if (bits > HOST_BITS_PER_WIDE_INT)
+    abort ();
+
+  if (negative)
+    val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
+  else
+    val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+
+  return val;
+}
+
+/* Returns the greatest common divisor of A and B, which must be
+   INTEGER_CSTs.  */
+
+tree
+tree_fold_gcd (tree a, tree b)
+{
+  tree a_mod_b;
+  tree type = TREE_TYPE (a);
+
+#if defined ENABLE_CHECKING
+  if (TREE_CODE (a) != INTEGER_CST
+      || TREE_CODE (b) != INTEGER_CST)
+    abort ();
+#endif
+
+  if (integer_zerop (a))
+    return b;
+
+  if (integer_zerop (b))
+    return a;
+
+  if (tree_int_cst_sgn (a) == -1)
+    a = fold (build2 (MULT_EXPR, type, a,
+                     convert (type, integer_minus_one_node)));
+
+  if (tree_int_cst_sgn (b) == -1)
+    b = fold (build2 (MULT_EXPR, type, b,
+                     convert (type, integer_minus_one_node)));
+
+  while (1)
+    {
+      a_mod_b = fold (build2 (CEIL_MOD_EXPR, type, a, b));
+
+      if (!TREE_INT_CST_LOW (a_mod_b)
+         && !TREE_INT_CST_HIGH (a_mod_b))
+       return b;
+
+      a = b;
+      b = a_mod_b;
+    }
 }
 
 #include "gt-tree.h"