tree-core.h (tree_type_non_common): Rename binfo to lang_1.
[platform/upstream/gcc.git] / gcc / tree.c
index c565337..31fe31f 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987-2016 Free Software Foundation, Inc.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -61,6 +61,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "print-tree.h"
 #include "ipa-utils.h"
+#include "selftest.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 /* Tree code classes.  */
 
@@ -150,7 +153,7 @@ static const char * const tree_node_kind_names[] = {
 /* Unique id for next decl created.  */
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
-static GTY(()) int next_type_uid = 1;
+static GTY(()) unsigned next_type_uid = 1;
 /* Unique id for next debug decl created.  Use negative numbers,
    to catch erroneous uses.  */
 static GTY(()) int next_debug_decl_uid;
@@ -247,8 +250,6 @@ static void set_type_quals (tree, int);
 static void print_type_hash_statistics (void);
 static void print_debug_expr_statistics (void);
 static void print_value_expr_statistics (void);
-static void type_hash_list (const_tree, inchash::hash &);
-static void attribute_hash_list (const_tree, inchash::hash &);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
@@ -281,7 +282,6 @@ unsigned const char omp_clause_num_ops[] =
   1, /* OMP_CLAUSE_USE_DEVICE_PTR  */
   1, /* OMP_CLAUSE_IS_DEVICE_PTR  */
   2, /* OMP_CLAUSE__CACHE_  */
-  1, /* OMP_CLAUSE_DEVICE_RESIDENT  */
   2, /* OMP_CLAUSE_GANG  */
   1, /* OMP_CLAUSE_ASYNC  */
   1, /* OMP_CLAUSE_WAIT  */
@@ -320,6 +320,7 @@ unsigned const char omp_clause_num_ops[] =
   1, /* OMP_CLAUSE_HINT  */
   0, /* OMP_CLAUSE_DEFALTMAP  */
   1, /* OMP_CLAUSE__SIMDUID_  */
+  0, /* OMP_CLAUSE__SIMT_  */
   1, /* OMP_CLAUSE__CILK_FOR_COUNT_  */
   0, /* OMP_CLAUSE_INDEPENDENT  */
   1, /* OMP_CLAUSE_WORKER  */
@@ -327,7 +328,7 @@ unsigned const char omp_clause_num_ops[] =
   1, /* OMP_CLAUSE_NUM_GANGS  */
   1, /* OMP_CLAUSE_NUM_WORKERS  */
   1, /* OMP_CLAUSE_VECTOR_LENGTH  */
-  1, /* OMP_CLAUSE_TILE  */
+  3, /* OMP_CLAUSE_TILE  */
   2, /* OMP_CLAUSE__GRIDDIM_  */
 };
 
@@ -353,7 +354,6 @@ const char * const omp_clause_code_name[] =
   "use_device_ptr",
   "is_device_ptr",
   "_cache_",
-  "device_resident",
   "gang",
   "async",
   "wait",
@@ -392,6 +392,7 @@ const char * const omp_clause_code_name[] =
   "hint",
   "defaultmap",
   "_simduid_",
+  "_simt_",
   "_Cilk_for_count_",
   "independent",
   "worker",
@@ -507,6 +508,8 @@ initialize_tree_contains_struct (void)
        {
        case TS_TYPED:
        case TS_BLOCK:
+       case TS_OPTIMIZATION:
+       case TS_TARGET_OPTION:
          MARK_TS_BASE (code);
          break;
 
@@ -531,8 +534,6 @@ initialize_tree_contains_struct (void)
        case TS_VEC:
        case TS_BINFO:
        case TS_OMP_CLAUSE:
-       case TS_OPTIMIZATION:
-       case TS_TARGET_OPTION:
          MARK_TS_COMMON (code);
          break;
 
@@ -717,7 +718,7 @@ set_decl_section_name (tree node, const char *value)
       if (!snode)
        return;
     }
-  else if (TREE_CODE (node) == VAR_DECL)
+  else if (VAR_P (node))
     snode = varpool_node::get_create (node);
   else
     snode = cgraph_node::get_create (node);
@@ -998,7 +999,7 @@ allocate_decl_uid (void)
    Achoo!  I got a code in the node.  */
 
 tree
-make_node_stat (enum tree_code code MEM_STAT_DECL)
+make_node (enum tree_code code MEM_STAT_DECL)
 {
   tree t;
   enum tree_code_class type = TREE_CODE_CLASS (code);
@@ -1020,8 +1021,8 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        {
          if (code == FUNCTION_DECL)
            {
-             SET_DECL_ALIGN (t, FUNCTION_BOUNDARY);
-             DECL_MODE (t) = FUNCTION_MODE;
+             SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
+             SET_DECL_MODE (t, FUNCTION_MODE);
            }
          else
            SET_DECL_ALIGN (t, 1);
@@ -1129,7 +1130,7 @@ free_node (tree node)
    TREE_CHAIN, if it has one, is zero and it has a fresh uid.  */
 
 tree
-copy_node_stat (tree node MEM_STAT_DECL)
+copy_node (tree node MEM_STAT_DECL)
 {
   tree t;
   enum tree_code code = TREE_CODE (node);
@@ -1157,19 +1158,19 @@ copy_node_stat (tree node MEM_STAT_DECL)
          if (DECL_PT_UID_SET_P (node))
            SET_DECL_PT_UID (t, DECL_PT_UID (node));
        }
-      if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
+      if ((TREE_CODE (node) == PARM_DECL || VAR_P (node))
          && DECL_HAS_VALUE_EXPR_P (node))
        {
          SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
          DECL_HAS_VALUE_EXPR_P (t) = 1;
        }
       /* DECL_DEBUG_EXPR is copied explicitely by callers.  */
-      if (TREE_CODE (node) == VAR_DECL)
+      if (VAR_P (node))
        {
          DECL_HAS_DEBUG_EXPR_P (t) = 0;
          t->decl_with_vis.symtab_node = NULL;
        }
-      if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node))
+      if (VAR_P (node) && DECL_HAS_INIT_PRIORITY_P (node))
        {
          SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node));
          DECL_HAS_INIT_PRIORITY_P (t) = 1;
@@ -1423,7 +1424,7 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst)
     {
       if (pcst.elt (l - 1) == 0)
        gcc_checking_assert (pcst.elt (l - 2) < 0);
-      if (pcst.elt (l - 1) == (HOST_WIDE_INT) -1)
+      if (pcst.elt (l - 1) == HOST_WIDE_INT_M1)
        gcc_checking_assert (pcst.elt (l - 2) >= 0);
     }
 
@@ -1676,13 +1677,13 @@ bool
 cst_and_fits_in_hwi (const_tree x)
 {
   return (TREE_CODE (x) == INTEGER_CST
-         && TYPE_PRECISION (TREE_TYPE (x)) <= HOST_BITS_PER_WIDE_INT);
+         && (tree_fits_shwi_p (x) || tree_fits_uhwi_p (x)));
 }
 
 /* Build a newly constructed VECTOR_CST node of length LEN.  */
 
 tree
-make_vector_stat (unsigned len MEM_STAT_DECL)
+make_vector (unsigned len MEM_STAT_DECL)
 {
   tree t;
   unsigned length = (len - 1) * sizeof (tree) + sizeof (struct tree_vector);
@@ -1701,7 +1702,7 @@ make_vector_stat (unsigned len MEM_STAT_DECL)
    are in a list pointed to by VALS.  */
 
 tree
-build_vector_stat (tree type, tree *vals MEM_STAT_DECL)
+build_vector (tree type, tree *vals MEM_STAT_DECL)
 {
   int over = 0;
   unsigned cnt = 0;
@@ -2194,7 +2195,7 @@ build_zero_cst (tree type)
 /* Build a BINFO with LEN language slots.  */
 
 tree
-make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
+make_tree_binfo (unsigned base_binfos MEM_STAT_DECL)
 {
   tree t;
   size_t length = (offsetof (struct tree_binfo, base_binfos)
@@ -2236,7 +2237,7 @@ build_case_label (tree low_value, tree high_value, tree label_decl)
    The latter determines the length of the HOST_WIDE_INT vector.  */
 
 tree
-make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
+make_int_cst (int len, int ext_len MEM_STAT_DECL)
 {
   tree t;
   int length = ((ext_len - 1) * sizeof (HOST_WIDE_INT)
@@ -2266,10 +2267,10 @@ make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
 /* Build a newly constructed TREE_VEC node of length LEN.  */
 
 tree
-make_tree_vec_stat (int len MEM_STAT_DECL)
+make_tree_vec (int len MEM_STAT_DECL)
 {
   tree t;
-  int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
+  size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
 
   record_node_allocation_statistics (TREE_VEC, length);
 
@@ -2284,15 +2285,15 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
 /* Grow a TREE_VEC node to new length LEN.  */
 
 tree
-grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
+grow_tree_vec (tree v, int len MEM_STAT_DECL)
 {
   gcc_assert (TREE_CODE (v) == TREE_VEC);
 
   int oldlen = TREE_VEC_LENGTH (v);
   gcc_assert (len > oldlen);
 
-  int oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec);
-  int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
+  size_t oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec);
+  size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
 
   record_node_allocation_statistics (TREE_VEC, length - oldlength);
 
@@ -2869,9 +2870,9 @@ nreverse (tree t)
    purpose and value fields are PARM and VALUE.  */
 
 tree
-build_tree_list_stat (tree parm, tree value MEM_STAT_DECL)
+build_tree_list (tree parm, tree value MEM_STAT_DECL)
 {
-  tree t = make_node_stat (TREE_LIST PASS_MEM_STAT);
+  tree t = make_node (TREE_LIST PASS_MEM_STAT);
   TREE_PURPOSE (t) = parm;
   TREE_VALUE (t) = value;
   return t;
@@ -2880,7 +2881,7 @@ build_tree_list_stat (tree parm, tree value MEM_STAT_DECL)
 /* Build a chain of TREE_LIST nodes from a vector.  */
 
 tree
-build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL)
+build_tree_list_vec (const vec<tree, va_gc> *vec MEM_STAT_DECL)
 {
   tree ret = NULL_TREE;
   tree *pp = &ret;
@@ -2888,7 +2889,7 @@ build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL)
   tree t;
   FOR_EACH_VEC_SAFE_ELT (vec, i, t)
     {
-      *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT);
+      *pp = build_tree_list (NULL, t PASS_MEM_STAT);
       pp = &TREE_CHAIN (*pp);
     }
   return ret;
@@ -2899,7 +2900,7 @@ build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL)
    and whose TREE_CHAIN is CHAIN.  */
 
 tree 
-tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
+tree_cons (tree purpose, tree value, tree chain MEM_STAT_DECL)
 {
   tree node;
 
@@ -2939,7 +2940,7 @@ ctor_to_vec (tree ctor)
    make_unsigned_type).  */
 
 tree
-size_in_bytes (const_tree type)
+size_in_bytes_loc (location_t loc, const_tree type)
 {
   tree t;
 
@@ -2951,7 +2952,7 @@ size_in_bytes (const_tree type)
 
   if (t == 0)
     {
-      lang_hooks.types.incomplete_type_error (NULL_TREE, type);
+      lang_hooks.types.incomplete_type_error (loc, NULL_TREE, type);
       return size_zero_node;
     }
 
@@ -3338,7 +3339,6 @@ tree_invariant_p (tree t)
 tree
 save_expr (tree expr)
 {
-  tree t = fold (expr);
   tree inner;
 
   /* If the tree evaluates to a constant, then we don't want to hide that
@@ -3346,33 +3346,32 @@ save_expr (tree expr)
      However, a read-only object that has side effects cannot be bypassed.
      Since it is no problem to reevaluate literals, we just return the
      literal node.  */
-  inner = skip_simple_arithmetic (t);
+  inner = skip_simple_arithmetic (expr);
   if (TREE_CODE (inner) == ERROR_MARK)
     return inner;
 
   if (tree_invariant_p_1 (inner))
-    return t;
+    return expr;
 
   /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
      it means that the size or offset of some field of an object depends on
      the value within another field.
 
-     Note that it must not be the case that T contains both a PLACEHOLDER_EXPR
+     Note that it must not be the case that EXPR contains both a PLACEHOLDER_EXPR
      and some variable since it would then need to be both evaluated once and
      evaluated more than once.  Front-ends must assure this case cannot
      happen by surrounding any such subexpressions in their own SAVE_EXPR
      and forcing evaluation at the proper time.  */
   if (contains_placeholder_p (inner))
-    return t;
+    return expr;
 
-  t = build1 (SAVE_EXPR, TREE_TYPE (expr), t);
-  SET_EXPR_LOCATION (t, EXPR_LOCATION (expr));
+  expr = build1_loc (EXPR_LOCATION (expr), SAVE_EXPR, TREE_TYPE (expr), expr);
 
   /* 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
      eliminated as dead.  */
-  TREE_SIDE_EFFECTS (t) = 1;
-  return t;
+  TREE_SIDE_EFFECTS (expr) = 1;
+  return expr;
 }
 
 /* Look inside EXPR into any simple arithmetic operations.  Return the
@@ -3728,7 +3727,7 @@ find_placeholder_in_expr (tree exp, vec<tree> *refs)
            break;
          }
 
-        /* Fall through...  */
+        /* Fall through.  */
 
       case tcc_exceptional:
       case tcc_unary:
@@ -3817,7 +3816,7 @@ substitute_in_expr (tree exp, tree f, tree r)
        if (exp == f)
          return r;
 
-        /* Fall through...  */
+        /* Fall through.  */
 
       case tcc_exceptional:
       case tcc_unary:
@@ -3885,15 +3884,29 @@ substitute_in_expr (tree exp, tree f, tree r)
 
          new_tree = NULL_TREE;
 
-         /* If we are trying to replace F with a constant, inline back
+         /* If we are trying to replace F with a constant or with another
+            instance of one of the arguments of the call, inline back
             functions which do nothing else than computing a value from
             the arguments they are passed.  This makes it possible to
             fold partially or entirely the replacement expression.  */
-         if (CONSTANT_CLASS_P (r) && code == CALL_EXPR)
+         if (code == CALL_EXPR)
            {
-             tree t = maybe_inline_call_in_expr (exp);
-             if (t)
-               return SUBSTITUTE_IN_EXPR (t, f, r);
+             bool maybe_inline = false;
+             if (CONSTANT_CLASS_P (r))
+               maybe_inline = true;
+             else
+               for (i = 3; i < TREE_OPERAND_LENGTH (exp); i++)
+                 if (operand_equal_p (TREE_OPERAND (exp, i), r, 0))
+                   {
+                     maybe_inline = true;
+                     break;
+                   }
+             if (maybe_inline)
+               {
+                 tree t = maybe_inline_call_in_expr (exp);
+                 if (t)
+                   return SUBSTITUTE_IN_EXPR (t, f, r);
+               }
            }
 
          for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
@@ -4354,20 +4367,20 @@ do { tree _node = (NODE); \
    enough for all extant tree codes.  */
 
 tree
-build0_stat (enum tree_code code, tree tt MEM_STAT_DECL)
+build0 (enum tree_code code, tree tt MEM_STAT_DECL)
 {
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 0);
 
-  t = make_node_stat (code PASS_MEM_STAT);
+  t = make_node (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
   return t;
 }
 
 tree
-build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
+build1 (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 {
   int length = sizeof (struct tree_exp);
   tree t;
@@ -4443,9 +4456,9 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
   } while (0)
 
 tree
-build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
+build2 (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects;
+  bool constant, read_only, side_effects, div_by_zero;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 2);
@@ -4463,7 +4476,7 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
     gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
                && ptrofftype_p (TREE_TYPE (arg1)));
 
-  t = make_node_stat (code PASS_MEM_STAT);
+  t = make_node (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
   /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the
@@ -4478,6 +4491,23 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
 
+  switch (code)
+    {
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case CEIL_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+    case TRUNC_MOD_EXPR:
+      div_by_zero = integer_zerop (arg1);
+      break;
+    default:
+      div_by_zero = false;
+    }
+
   PROCESS_ARG (0);
   PROCESS_ARG (1);
 
@@ -4494,7 +4524,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   else
     {
       TREE_READONLY (t) = read_only;
-      TREE_CONSTANT (t) = constant;
+      /* Don't mark X / 0 as constant.  */
+      TREE_CONSTANT (t) = constant && !div_by_zero;
       TREE_THIS_VOLATILE (t)
        = (TREE_CODE_CLASS (code) == tcc_reference
           && arg0 && TREE_THIS_VOLATILE (arg0));
@@ -4505,8 +4536,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 
 
 tree
-build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
-            tree arg2 MEM_STAT_DECL)
+build3 (enum tree_code code, tree tt, tree arg0, tree arg1,
+       tree arg2 MEM_STAT_DECL)
 {
   bool constant, read_only, side_effects;
   tree t;
@@ -4514,7 +4545,7 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   gcc_assert (TREE_CODE_LENGTH (code) == 3);
   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
 
-  t = make_node_stat (code PASS_MEM_STAT);
+  t = make_node (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
   read_only = 1;
@@ -4546,15 +4577,15 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 }
 
 tree
-build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
-            tree arg2, tree arg3 MEM_STAT_DECL)
+build4 (enum tree_code code, tree tt, tree arg0, tree arg1,
+       tree arg2, tree arg3 MEM_STAT_DECL)
 {
   bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 4);
 
-  t = make_node_stat (code PASS_MEM_STAT);
+  t = make_node (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
   side_effects = TREE_SIDE_EFFECTS (t);
@@ -4573,15 +4604,15 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
 }
 
 tree
-build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
-            tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
+build5 (enum tree_code code, tree tt, tree arg0, tree arg1,
+       tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
 {
   bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 5);
 
-  t = make_node_stat (code PASS_MEM_STAT);
+  t = make_node (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
 
   side_effects = TREE_SIDE_EFFECTS (t);
@@ -4711,12 +4742,12 @@ build_nt_call_vec (tree fn, vec<tree, va_gc> *args)
    Other slots are initialized to 0 or null pointers.  */
 
 tree
-build_decl_stat (location_t loc, enum tree_code code, tree name,
+build_decl (location_t loc, enum tree_code code, tree name,
                 tree type MEM_STAT_DECL)
 {
   tree t;
 
-  t = make_node_stat (code PASS_MEM_STAT);
+  t = make_node (code PASS_MEM_STAT);
   DECL_SOURCE_LOCATION (t) = loc;
 
 /*  if (type == error_mark_node)
@@ -4793,314 +4824,6 @@ protected_set_expr_location (tree t, location_t loc)
     SET_EXPR_LOCATION (t, loc);
 }
 \f
-/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
-   is ATTRIBUTE.  */
-
-tree
-build_decl_attribute_variant (tree ddecl, tree attribute)
-{
-  DECL_ATTRIBUTES (ddecl) = attribute;
-  return ddecl;
-}
-
-/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
-   is ATTRIBUTE and its qualifiers are QUALS.
-
-   Record such modified types already made so we don't make duplicates.  */
-
-tree
-build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
-{
-  if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
-    {
-      inchash::hash hstate;
-      tree ntype;
-      int i;
-      tree t;
-      enum tree_code code = TREE_CODE (ttype);
-
-      /* Building a distinct copy of a tagged type is inappropriate; it
-        causes breakage in code that expects there to be a one-to-one
-        relationship between a struct and its fields.
-        build_duplicate_type is another solution (as used in
-        handle_transparent_union_attribute), but that doesn't play well
-        with the stronger C++ type identity model.  */
-      if (TREE_CODE (ttype) == RECORD_TYPE
-         || TREE_CODE (ttype) == UNION_TYPE
-         || TREE_CODE (ttype) == QUAL_UNION_TYPE
-         || TREE_CODE (ttype) == ENUMERAL_TYPE)
-       {
-         warning (OPT_Wattributes,
-                  "ignoring attributes applied to %qT after definition",
-                  TYPE_MAIN_VARIANT (ttype));
-         return build_qualified_type (ttype, quals);
-       }
-
-      ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
-      ntype = build_distinct_type_copy (ttype);
-
-      TYPE_ATTRIBUTES (ntype) = attribute;
-
-      hstate.add_int (code);
-      if (TREE_TYPE (ntype))
-       hstate.add_object (TYPE_HASH (TREE_TYPE (ntype)));
-      attribute_hash_list (attribute, hstate);
-
-      switch (TREE_CODE (ntype))
-       {
-       case FUNCTION_TYPE:
-         type_hash_list (TYPE_ARG_TYPES (ntype), hstate);
-         break;
-       case ARRAY_TYPE:
-         if (TYPE_DOMAIN (ntype))
-           hstate.add_object (TYPE_HASH (TYPE_DOMAIN (ntype)));
-         break;
-       case INTEGER_TYPE:
-         t = TYPE_MAX_VALUE (ntype);
-         for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
-           hstate.add_object (TREE_INT_CST_ELT (t, i));
-         break;
-       case REAL_TYPE:
-       case FIXED_POINT_TYPE:
-         {
-           unsigned int precision = TYPE_PRECISION (ntype);
-           hstate.add_object (precision);
-         }
-         break;
-       default:
-         break;
-       }
-
-      ntype = type_hash_canon (hstate.end(), ntype);
-
-      /* If the target-dependent attributes make NTYPE different from
-        its canonical type, we will need to use structural equality
-        checks for this type. */
-      if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
-          || !comp_type_attributes (ntype, ttype))
-       SET_TYPE_STRUCTURAL_EQUALITY (ntype);
-      else if (TYPE_CANONICAL (ntype) == ntype)
-       TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
-
-      ttype = build_qualified_type (ntype, quals);
-    }
-  else if (TYPE_QUALS (ttype) != quals)
-    ttype = build_qualified_type (ttype, quals);
-
-  return ttype;
-}
-
-/* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
-   the same.  */
-
-static bool
-omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
-{
-  tree cl1, cl2;
-  for (cl1 = clauses1, cl2 = clauses2;
-       cl1 && cl2;
-       cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2))
-    {
-      if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2))
-       return false;
-      if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN)
-       {
-         if (simple_cst_equal (OMP_CLAUSE_DECL (cl1),
-                               OMP_CLAUSE_DECL (cl2)) != 1)
-           return false;
-       }
-      switch (OMP_CLAUSE_CODE (cl1))
-       {
-       case OMP_CLAUSE_ALIGNED:
-         if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1),
-                               OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1)
-           return false;
-         break;
-       case OMP_CLAUSE_LINEAR:
-         if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1),
-                               OMP_CLAUSE_LINEAR_STEP (cl2)) != 1)
-           return false;
-         break;
-       case OMP_CLAUSE_SIMDLEN:
-         if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1),
-                               OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1)
-           return false;
-       default:
-         break;
-       }
-    }
-  return true;
-}
-
-/* Compare two constructor-element-type constants.  Return 1 if the lists
-   are known to be equal; otherwise return 0.  */
-
-static bool
-simple_cst_list_equal (const_tree l1, const_tree l2)
-{
-  while (l1 != NULL_TREE && l2 != NULL_TREE)
-    {
-      if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
-       return false;
-
-      l1 = TREE_CHAIN (l1);
-      l2 = TREE_CHAIN (l2);
-    }
-
-  return l1 == l2;
-}
-
-/* Compare two identifier nodes representing attributes.  Either one may
-   be in wrapped __ATTR__ form.  Return true if they are the same, false
-   otherwise.  */
-
-static bool
-cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
-{
-  /* Make sure we're dealing with IDENTIFIER_NODEs.  */
-  gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
-                      && TREE_CODE (attr2) == IDENTIFIER_NODE);
-
-  /* Identifiers can be compared directly for equality.  */
-  if (attr1 == attr2)
-    return true;
-
-  /* If they are not equal, they may still be one in the form
-     'text' while the other one is in the form '__text__'.  TODO:
-     If we were storing attributes in normalized 'text' form, then
-     this could all go away and we could take full advantage of
-     the fact that we're comparing identifiers. :-)  */
-  const size_t attr1_len = IDENTIFIER_LENGTH (attr1);
-  const size_t attr2_len = IDENTIFIER_LENGTH (attr2);
-
-  if (attr2_len == attr1_len + 4)
-    {
-      const char *p = IDENTIFIER_POINTER (attr2);
-      const char *q = IDENTIFIER_POINTER (attr1);
-      if (p[0] == '_' && p[1] == '_'
-         && p[attr2_len - 2] == '_' && p[attr2_len - 1] == '_'
-         && strncmp (q, p + 2, attr1_len) == 0)
-       return true;;
-    }
-  else if (attr2_len + 4 == attr1_len)
-    {
-      const char *p = IDENTIFIER_POINTER (attr2);
-      const char *q = IDENTIFIER_POINTER (attr1);
-      if (q[0] == '_' && q[1] == '_'
-         && q[attr1_len - 2] == '_' && q[attr1_len - 1] == '_'
-         && strncmp (q + 2, p, attr2_len) == 0)
-       return true;
-    }
-
-  return false;
-}
-
-/* Compare two attributes for their value identity.  Return true if the
-   attribute values are known to be equal; otherwise return false.  */
-
-bool
-attribute_value_equal (const_tree attr1, const_tree attr2)
-{
-  if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
-    return true;
-
-  if (TREE_VALUE (attr1) != NULL_TREE
-      && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
-      && TREE_VALUE (attr2) != NULL_TREE
-      && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
-    {
-      /* Handle attribute format.  */
-      if (is_attribute_p ("format", TREE_PURPOSE (attr1)))
-       {
-         attr1 = TREE_VALUE (attr1);
-         attr2 = TREE_VALUE (attr2);
-         /* Compare the archetypes (printf/scanf/strftime/...).  */
-         if (!cmp_attrib_identifiers (TREE_VALUE (attr1),
-                                      TREE_VALUE (attr2)))
-           return false;
-         /* Archetypes are the same.  Compare the rest.  */
-         return (simple_cst_list_equal (TREE_CHAIN (attr1),
-                                        TREE_CHAIN (attr2)) == 1);
-       }
-      return (simple_cst_list_equal (TREE_VALUE (attr1),
-                                    TREE_VALUE (attr2)) == 1);
-    }
-
-  if ((flag_openmp || flag_openmp_simd)
-      && TREE_VALUE (attr1) && TREE_VALUE (attr2)
-      && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
-      && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)
-    return omp_declare_simd_clauses_equal (TREE_VALUE (attr1),
-                                          TREE_VALUE (attr2));
-
-  return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
-}
-
-/* Return 0 if the attributes for two types are incompatible, 1 if they
-   are compatible, and 2 if they are nearly compatible (which causes a
-   warning to be generated).  */
-int
-comp_type_attributes (const_tree type1, const_tree type2)
-{
-  const_tree a1 = TYPE_ATTRIBUTES (type1);
-  const_tree a2 = TYPE_ATTRIBUTES (type2);
-  const_tree a;
-
-  if (a1 == a2)
-    return 1;
-  for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
-    {
-      const struct attribute_spec *as;
-      const_tree attr;
-
-      as = lookup_attribute_spec (get_attribute_name (a));
-      if (!as || as->affects_type_identity == false)
-        continue;
-
-      attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
-      if (!attr || !attribute_value_equal (a, attr))
-        break;
-    }
-  if (!a)
-    {
-      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
-       {
-         const struct attribute_spec *as;
-
-         as = lookup_attribute_spec (get_attribute_name (a));
-         if (!as || as->affects_type_identity == false)
-           continue;
-
-         if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
-           break;
-         /* We don't need to compare trees again, as we did this
-            already in first loop.  */
-       }
-      /* All types - affecting identity - are equal, so
-         there is no need to call target hook for comparison.  */
-      if (!a)
-        return 1;
-    }
-  if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a)))
-    return 0;
-  /* As some type combinations - like default calling-convention - might
-     be compatible, we have to call the target hook to get the final result.  */
-  return targetm.comp_type_attributes (type1, type2);
-}
-
-/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
-   is ATTRIBUTE.
-
-   Record such modified types already made so we don't make duplicates.  */
-
-tree
-build_type_attribute_variant (tree ttype, tree attribute)
-{
-  return build_type_attribute_qual_variant (ttype, attribute,
-                                           TYPE_QUALS (ttype));
-}
-
-
 /* Reset the expression *EXPR_P, a size or position.
 
    ??? We could reset all non-constant sizes or positions.  But it's cheap
@@ -5167,9 +4890,7 @@ free_lang_data_in_type (tree type)
         leading to false ODR violation errors when merging two
         instances of the same function signature compiled by
         different front ends.  */
-      tree p;
-
-      for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+      for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
        {
          tree arg_type = TREE_VALUE (p);
 
@@ -5184,72 +4905,31 @@ free_lang_data_in_type (tree type)
          /* C++ FE uses TREE_PURPOSE to store initial values.  */
          TREE_PURPOSE (p) = NULL;
        }
-      /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE.  */
-      TYPE_MINVAL (type) = NULL;
-    }
-  if (TREE_CODE (type) == METHOD_TYPE)
-    {
-      tree p;
-
-      for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
-       {
-         /* C++ FE uses TREE_PURPOSE to store initial values.  */
-         TREE_PURPOSE (p) = NULL;
-       }
-      /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE.  */
-      TYPE_MINVAL (type) = NULL;
     }
-
-  /* Remove members that are not actually FIELD_DECLs from the field
-     list of an aggregate.  These occur in C++.  */
-  if (RECORD_OR_UNION_TYPE_P (type))
-    {
-      tree prev, member;
-
-      /* Note that TYPE_FIELDS can be shared across distinct
-        TREE_TYPEs.  Therefore, if the first field of TYPE_FIELDS is
-        to be removed, we cannot set its TREE_CHAIN to NULL.
-        Otherwise, we would not be able to find all the other fields
-        in the other instances of this TREE_TYPE.
-
-        This was causing an ICE in testsuite/g++.dg/lto/20080915.C.  */
-      prev = NULL_TREE;
-      member = TYPE_FIELDS (type);
-      while (member)
-       {
-         if (TREE_CODE (member) == FIELD_DECL
-             || (TREE_CODE (member) == TYPE_DECL
-                 && !DECL_IGNORED_P (member)
-                 && debug_info_level > DINFO_LEVEL_TERSE
-                 && !is_redundant_typedef (member)))
-           {
-             if (prev)
-               TREE_CHAIN (prev) = member;
-             else
-               TYPE_FIELDS (type) = member;
-             prev = member;
-           }
-
-         member = TREE_CHAIN (member);
-       }
-
-      if (prev)
-       TREE_CHAIN (prev) = NULL_TREE;
-      else
-       TYPE_FIELDS (type) = NULL_TREE;
+  else if (TREE_CODE (type) == METHOD_TYPE)
+    for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+      /* C++ FE uses TREE_PURPOSE to store initial values.  */
+      TREE_PURPOSE (p) = NULL;
+  else if (RECORD_OR_UNION_TYPE_P (type))
+    {
+      /* Remove members that are not FIELD_DECLs (and maybe
+        TYPE_DECLs) from the field list of an aggregate.  These occur
+        in C++.  */
+      for (tree *prev = &TYPE_FIELDS (type), member; (member = *prev);)
+       if (TREE_CODE (member) == FIELD_DECL
+           || (TREE_CODE (member) == TYPE_DECL
+               && !DECL_IGNORED_P (member)
+               && debug_info_level > DINFO_LEVEL_TERSE
+               && !is_redundant_typedef (member)))
+         prev = &DECL_CHAIN (member);
+       else
+         *prev = DECL_CHAIN (member);
 
       /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
         and danagle the pointer from time to time.  */
       if (TYPE_VFIELD (type) && TREE_CODE (TYPE_VFIELD (type)) != FIELD_DECL)
         TYPE_VFIELD (type) = NULL_TREE;
 
-      /* Remove TYPE_METHODS list.  While it would be nice to keep it
-        to enable ODR warnings about different method lists, doing so
-        seems to impractically increase size of LTO data streamed.
-        Keep the information if TYPE_METHODS was non-NULL. This is used
-        by function.c and pretty printers.  */
-      if (TYPE_METHODS (type))
-        TYPE_METHODS (type) = error_mark_node;
       if (TYPE_BINFO (type))
        {
          free_lang_data_in_binfo (TYPE_BINFO (type));
@@ -5266,21 +4946,16 @@ free_lang_data_in_type (tree type)
            TYPE_BINFO (type) = NULL;
        }
     }
-  else
+  else if (INTEGRAL_TYPE_P (type)
+          || SCALAR_FLOAT_TYPE_P (type)
+          || FIXED_POINT_TYPE_P (type))
     {
-      /* For non-aggregate types, clear out the language slot (which
-        overloads TYPE_BINFO).  */
-      TYPE_LANG_SLOT_1 (type) = NULL_TREE;
-
-      if (INTEGRAL_TYPE_P (type)
-         || SCALAR_FLOAT_TYPE_P (type)
-         || FIXED_POINT_TYPE_P (type))
-       {
-         free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type));
-         free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type));
-       }
+      free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type));
+      free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type));
     }
 
+  TYPE_LANG_SLOT_1 (type) = NULL_TREE;
+
   free_lang_data_in_one_sizepos (&TYPE_SIZE (type));
   free_lang_data_in_one_sizepos (&TYPE_SIZE_UNIT (type));
 
@@ -5331,8 +5006,7 @@ need_assembler_name_p (tree decl)
       && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
     return !DECL_ASSEMBLER_NAME_SET_P (decl);
   /* Only FUNCTION_DECLs and VAR_DECLs are considered.  */
-  if (TREE_CODE (decl) != FUNCTION_DECL
-      && TREE_CODE (decl) != VAR_DECL)
+  if (!VAR_OR_FUNCTION_DECL_P (decl))
     return false;
 
   /* If DECL already has its assembler name set, it does not need a
@@ -5347,7 +5021,7 @@ need_assembler_name_p (tree decl)
 
   /* For VAR_DECLs, only static, public and external symbols need an
      assembler name.  */
-  if (TREE_CODE (decl) == VAR_DECL
+  if (VAR_P (decl)
       && !TREE_STATIC (decl)
       && !TREE_PUBLIC (decl)
       && !DECL_EXTERNAL (decl))
@@ -5418,7 +5092,7 @@ free_lang_data_in_decl (tree decl)
              DECL_INITIAL (decl) = error_mark_node;
            }
        }
-      if (gimple_has_body_p (decl))
+      if (gimple_has_body_p (decl) || (node && node->thunk.thunk_p))
        {
          tree t;
 
@@ -5445,9 +5119,10 @@ free_lang_data_in_decl (tree decl)
         At this point, it is not needed anymore.  */
       DECL_SAVED_TREE (decl) = NULL_TREE;
 
-      /* Clear the abstract origin if it refers to a method.  Otherwise
-         dwarf2out.c will ICE as we clear TYPE_METHODS and thus the
-        origin will not be output correctly.  */
+      /* Clear the abstract origin if it refers to a method.
+         Otherwise dwarf2out.c will ICE as we splice functions out of
+         TYPE_FIELDS and thus the origin will not be output
+         correctly.  */
       if (DECL_ABSTRACT_ORIGIN (decl)
          && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
          && RECORD_OR_UNION_TYPE_P
@@ -5461,7 +5136,7 @@ free_lang_data_in_decl (tree decl)
       if (DECL_VINDEX (decl) && !tree_fits_shwi_p (DECL_VINDEX (decl)))
        DECL_VINDEX (decl) = NULL_TREE;
     }
-  else if (TREE_CODE (decl) == VAR_DECL)
+  else if (VAR_P (decl))
     {
       if ((DECL_EXTERNAL (decl)
           && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
@@ -5501,17 +5176,19 @@ free_lang_data_in_decl (tree decl)
 
 struct free_lang_data_d
 {
+  free_lang_data_d () : decls (100), types (100) {}
+
   /* Worklist to avoid excessive recursion.  */
-  vec<tree> worklist;
+  auto_vec<tree> worklist;
 
   /* Set of traversed objects.  Used to avoid duplicate visits.  */
-  hash_set<tree> *pset;
+  hash_set<tree> pset;
 
   /* Array of symbols to process with free_lang_data_in_decl.  */
-  vec<tree> decls;
+  auto_vec<tree> decls;
 
   /* Array of types to process with free_lang_data_in_type.  */
-  vec<tree> types;
+  auto_vec<tree> types;
 };
 
 
@@ -5570,7 +5247,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
 static inline void
 fld_worklist_push (tree t, struct free_lang_data_d *fld)
 {
-  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
+  if (t && !is_lang_specific (t) && !fld->pset.contains (t))
     fld->worklist.safe_push ((t));
 }
 
@@ -5631,7 +5308,7 @@ find_decls_types_r (tree *tp, int *ws, void *data)
          fld_worklist_push (DECL_FCONTEXT (t), fld);
        }
 
-      if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+      if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL)
          && DECL_HAS_VALUE_EXPR_P (t))
        fld_worklist_push (DECL_VALUE_EXPR (t), fld);
 
@@ -5658,9 +5335,10 @@ find_decls_types_r (tree *tp, int *ws, void *data)
         them and thus do not and want not to reach unused pointer types
         this way.  */
       if (!POINTER_TYPE_P (t))
-       fld_worklist_push (TYPE_MINVAL (t), fld);
+       fld_worklist_push (TYPE_MIN_VALUE_RAW (t), fld);
+      /* TYPE_MAX_VALUE_RAW is TYPE_BINFO for record types.  */
       if (!RECORD_OR_UNION_TYPE_P (t))
-       fld_worklist_push (TYPE_MAXVAL (t), fld);
+       fld_worklist_push (TYPE_MAX_VALUE_RAW (t), fld);
       fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
       /* Do not walk TYPE_NEXT_VARIANT.  We do not stream it and thus
          do not and want not to reach unused variants this way.  */
@@ -5682,16 +5360,7 @@ find_decls_types_r (tree *tp, int *ws, void *data)
          tree tem;
          FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (TYPE_BINFO (t)), i, tem)
            fld_worklist_push (TREE_TYPE (tem), fld);
-         tem = BINFO_VIRTUALS (TYPE_BINFO (t));
-         if (tem
-             /* The Java FE overloads BINFO_VIRTUALS for its own purpose.  */
-             && TREE_CODE (tem) == TREE_LIST)
-           do
-             {
-               fld_worklist_push (TREE_VALUE (tem), fld);
-               tem = TREE_CHAIN (tem);
-             }
-           while (tem);
+         fld_worklist_push (BINFO_VIRTUALS (TYPE_BINFO (t)), fld);
        }
       if (RECORD_OR_UNION_TYPE_P (t))
        {
@@ -5739,8 +5408,8 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
 {
   while (1)
     {
-      if (!fld->pset->contains (t))
-       walk_tree (&t, find_decls_types_r, fld, fld->pset);
+      if (!fld->pset.contains (t))
+       walk_tree (&t, find_decls_types_r, fld, &fld->pset);
       if (fld->worklist.is_empty ())
        break;
       t = fld->worklist.pop ();
@@ -5794,7 +5463,7 @@ find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
        for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
          {
            c->type_list = get_eh_types_for_runtime (c->type_list);
-           walk_tree (&c->type_list, find_decls_types_r, fld, fld->pset);
+           walk_tree (&c->type_list, find_decls_types_r, fld, &fld->pset);
          }
       }
       break;
@@ -5802,12 +5471,12 @@ find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
     case ERT_ALLOWED_EXCEPTIONS:
       r->u.allowed.type_list
        = get_eh_types_for_runtime (r->u.allowed.type_list);
-      walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
+      walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, &fld->pset);
       break;
 
     case ERT_MUST_NOT_THROW:
       walk_tree (&r->u.must_not_throw.failure_decl,
-                find_decls_types_r, fld, fld->pset);
+                find_decls_types_r, fld, &fld->pset);
       break;
     }
 }
@@ -5897,7 +5566,7 @@ find_decls_types_in_var (varpool_node *v, struct free_lang_data_d *fld)
 /* If T needs an assembler name, have one created for it.  */
 
 void
-assign_assembler_name_if_neeeded (tree t)
+assign_assembler_name_if_needed (tree t)
 {
   if (need_assembler_name_p (t))
     {
@@ -5949,12 +5618,6 @@ free_lang_data_in_cgraph (void)
   unsigned i;
   alias_pair *p;
 
-  /* Initialize sets and arrays to store referenced decls and types.  */
-  fld.pset = new hash_set<tree>;
-  fld.worklist.create (0);
-  fld.decls.create (100);
-  fld.types.create (100);
-
   /* Find decls and types in the body of every function in the callgraph.  */
   FOR_EACH_FUNCTION (n)
     find_decls_types_in_node (n, &fld);
@@ -5970,7 +5633,7 @@ free_lang_data_in_cgraph (void)
      now because free_lang_data_in_decl will invalidate data needed
      for mangling.  This breaks mangling on interdependent decls.  */
   FOR_EACH_VEC_ELT (fld.decls, i, t)
-    assign_assembler_name_if_neeeded (t);
+    assign_assembler_name_if_needed (t);
 
   /* Traverse every decl found freeing its language data.  */
   FOR_EACH_VEC_ELT (fld.decls, i, t)
@@ -5984,11 +5647,6 @@ free_lang_data_in_cgraph (void)
       FOR_EACH_VEC_ELT (fld.types, i, t)
        verify_type (t);
     }
-
-  delete fld.pset;
-  fld.worklist.release ();
-  fld.decls.release ();
-  fld.types.release ();
 }
 
 
@@ -6015,8 +5673,10 @@ free_lang_data (void)
   free_lang_data_in_cgraph ();
 
   /* Create gimple variants for common types.  */
-  ptrdiff_type_node = integer_type_node;
-  fileptr_type_node = ptr_type_node;
+  for (unsigned i = 0;
+       i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
+       ++i)
+    builtin_structptr_types[i].node = builtin_structptr_types[i].base;
 
   /* Reset some langhooks.  Do not reset types_compatible_p, it may
      still be used indirectly via the get_alias_set langhook.  */
@@ -6072,492 +5732,82 @@ make_pass_ipa_free_lang_data (gcc::context *ctxt)
 {
   return new pass_ipa_free_lang_data (ctxt);
 }
+\f
+/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
+   of the various TYPE_QUAL values.  */
 
-/* The backbone of is_attribute_p().  ATTR_LEN is the string length of
-   ATTR_NAME.  Also used internally by remove_attribute().  */
-bool
-private_is_attribute_p (const char *attr_name, size_t attr_len, const_tree ident)
+static void
+set_type_quals (tree type, int type_quals)
 {
-  size_t ident_len = IDENTIFIER_LENGTH (ident);
+  TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
+  TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
+  TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+  TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
+  TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
+}
 
-  if (ident_len == attr_len)
-    {
-      if (strcmp (attr_name, IDENTIFIER_POINTER (ident)) == 0)
-       return true;
-    }
-  else if (ident_len == attr_len + 4)
-    {
-      /* There is the possibility that ATTR is 'text' and IDENT is
-        '__text__'.  */
-      const char *p = IDENTIFIER_POINTER (ident);      
-      if (p[0] == '_' && p[1] == '_'
-         && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
-         && strncmp (attr_name, p + 2, attr_len) == 0)
-       return true;
-    }
+/* Returns true iff CAND and BASE have equivalent language-specific
+   qualifiers.  */
 
-  return false;
+bool
+check_lang_type (const_tree cand, const_tree base)
+{
+  if (lang_hooks.types.type_hash_eq == NULL)
+    return true;
+  /* type_hash_eq currently only applies to these types.  */
+  if (TREE_CODE (cand) != FUNCTION_TYPE
+      && TREE_CODE (cand) != METHOD_TYPE)
+    return true;
+  return lang_hooks.types.type_hash_eq (cand, base);
 }
 
-/* The backbone of lookup_attribute().  ATTR_LEN is the string length
-   of ATTR_NAME, and LIST is not NULL_TREE.  */
-tree
-private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
+/* Returns true iff unqualified CAND and BASE are equivalent.  */
+
+bool
+check_base_type (const_tree cand, const_tree base)
 {
-  while (list)
-    {
-      size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
+  return (TYPE_NAME (cand) == TYPE_NAME (base)
+         /* Apparently this is needed for Objective-C.  */
+         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+         /* Check alignment.  */
+         && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
+         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
+                                  TYPE_ATTRIBUTES (base)));
+}
 
-      if (ident_len == attr_len)
-       {
-         if (!strcmp (attr_name,
-                      IDENTIFIER_POINTER (get_attribute_name (list))))
-           break;
-       }
-      /* TODO: If we made sure that attributes were stored in the
-        canonical form without '__...__' (ie, as in 'text' as opposed
-        to '__text__') then we could avoid the following case.  */
-      else if (ident_len == attr_len + 4)
-       {
-         const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
-         if (p[0] == '_' && p[1] == '_'
-             && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
-             && strncmp (attr_name, p + 2, attr_len) == 0)
-           break;
-       }
-      list = TREE_CHAIN (list);
-    }
+/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
 
-  return list;
+bool
+check_qualified_type (const_tree cand, const_tree base, int type_quals)
+{
+  return (TYPE_QUALS (cand) == type_quals
+         && check_base_type (cand, base)
+         && check_lang_type (cand, base));
 }
 
-/* Given an attribute name ATTR_NAME and a list of attributes LIST,
-   return a pointer to the attribute's list first element if the attribute
-   starts with ATTR_NAME. ATTR_NAME must be in the form 'text' (not
-   '__text__').  */
+/* Returns true iff CAND is equivalent to BASE with ALIGN.  */
 
-tree
-private_lookup_attribute_by_prefix (const char *attr_name, size_t attr_len,
-                                   tree list)
+static bool
+check_aligned_type (const_tree cand, const_tree base, unsigned int align)
 {
-  while (list)
-    {
-      size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
-
-      if (attr_len > ident_len)
-       {
-         list = TREE_CHAIN (list);
-         continue;
-       }
+  return (TYPE_QUALS (cand) == TYPE_QUALS (base)
+         && TYPE_NAME (cand) == TYPE_NAME (base)
+         /* Apparently this is needed for Objective-C.  */
+         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+         /* Check alignment.  */
+         && TYPE_ALIGN (cand) == align
+         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
+                                  TYPE_ATTRIBUTES (base))
+         && check_lang_type (cand, base));
+}
 
-      const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
+/* This function checks to see if TYPE matches the size one of the built-in 
+   atomic types, and returns that core atomic type.  */
 
-      if (strncmp (attr_name, p, attr_len) == 0)
-       break;
-
-      /* TODO: If we made sure that attributes were stored in the
-        canonical form without '__...__' (ie, as in 'text' as opposed
-        to '__text__') then we could avoid the following case.  */
-      if (p[0] == '_' && p[1] == '_' &&
-         strncmp (attr_name, p + 2, attr_len) == 0)
-       break;
-
-      list = TREE_CHAIN (list);
-    }
-
-  return list;
-}
-
-
-/* A variant of lookup_attribute() that can be used with an identifier
-   as the first argument, and where the identifier can be either
-   'text' or '__text__'.
-
-   Given an attribute ATTR_IDENTIFIER, and a list of attributes LIST,
-   return a pointer to the attribute's list element if the attribute
-   is part of the list, or NULL_TREE if not found.  If the attribute
-   appears more than once, this only returns the first occurrence; the
-   TREE_CHAIN of the return value should be passed back in if further
-   occurrences are wanted.  ATTR_IDENTIFIER must be an identifier but
-   can be in the form 'text' or '__text__'.  */
-static tree
-lookup_ident_attribute (tree attr_identifier, tree list)
-{
-  gcc_checking_assert (TREE_CODE (attr_identifier) == IDENTIFIER_NODE);
-
-  while (list)
-    {
-      gcc_checking_assert (TREE_CODE (get_attribute_name (list))
-                          == IDENTIFIER_NODE);
-
-      if (cmp_attrib_identifiers (attr_identifier,
-                                 get_attribute_name (list)))
-       /* Found it.  */
-       break;
-      list = TREE_CHAIN (list);
-    }
-
-  return list;
-}
-
-/* Remove any instances of attribute ATTR_NAME in LIST and return the
-   modified list.  */
-
-tree
-remove_attribute (const char *attr_name, tree list)
-{
-  tree *p;
-  size_t attr_len = strlen (attr_name);
-
-  gcc_checking_assert (attr_name[0] != '_');
-
-  for (p = &list; *p; )
-    {
-      tree l = *p;
-      /* TODO: If we were storing attributes in normalized form, here
-        we could use a simple strcmp().  */
-      if (private_is_attribute_p (attr_name, attr_len, get_attribute_name (l)))
-       *p = TREE_CHAIN (l);
-      else
-       p = &TREE_CHAIN (l);
-    }
-
-  return list;
-}
-
-/* Return an attribute list that is the union of a1 and a2.  */
-
-tree
-merge_attributes (tree a1, tree a2)
-{
-  tree attributes;
-
-  /* Either one unset?  Take the set one.  */
-
-  if ((attributes = a1) == 0)
-    attributes = a2;
-
-  /* One that completely contains the other?  Take it.  */
-
-  else if (a2 != 0 && ! attribute_list_contained (a1, a2))
-    {
-      if (attribute_list_contained (a2, a1))
-       attributes = a2;
-      else
-       {
-         /* Pick the longest list, and hang on the other list.  */
-
-         if (list_length (a1) < list_length (a2))
-           attributes = a2, a2 = a1;
-
-         for (; a2 != 0; a2 = TREE_CHAIN (a2))
-           {
-             tree a;
-             for (a = lookup_ident_attribute (get_attribute_name (a2),
-                                              attributes);
-                  a != NULL_TREE && !attribute_value_equal (a, a2);
-                  a = lookup_ident_attribute (get_attribute_name (a2),
-                                              TREE_CHAIN (a)))
-               ;
-             if (a == NULL_TREE)
-               {
-                 a1 = copy_node (a2);
-                 TREE_CHAIN (a1) = attributes;
-                 attributes = a1;
-               }
-           }
-       }
-    }
-  return attributes;
-}
-
-/* Given types T1 and T2, merge their attributes and return
-  the result.  */
-
-tree
-merge_type_attributes (tree t1, tree t2)
-{
-  return merge_attributes (TYPE_ATTRIBUTES (t1),
-                          TYPE_ATTRIBUTES (t2));
-}
-
-/* Given decls OLDDECL and NEWDECL, merge their attributes and return
-   the result.  */
-
-tree
-merge_decl_attributes (tree olddecl, tree newdecl)
-{
-  return merge_attributes (DECL_ATTRIBUTES (olddecl),
-                          DECL_ATTRIBUTES (newdecl));
-}
-
-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
-
-/* Specialization of merge_decl_attributes for various Windows targets.
-
-   This handles the following situation:
-
-     __declspec (dllimport) int foo;
-     int foo;
-
-   The second instance of `foo' nullifies the dllimport.  */
-
-tree
-merge_dllimport_decl_attributes (tree old, tree new_tree)
-{
-  tree a;
-  int delete_dllimport_p = 1;
-
-  /* What we need to do here is remove from `old' dllimport if it doesn't
-     appear in `new'.  dllimport behaves like extern: if a declaration is
-     marked dllimport and a definition appears later, then the object
-     is not dllimport'd.  We also remove a `new' dllimport if the old list
-     contains dllexport:  dllexport always overrides dllimport, regardless
-     of the order of declaration.  */
-  if (!VAR_OR_FUNCTION_DECL_P (new_tree))
-    delete_dllimport_p = 0;
-  else if (DECL_DLLIMPORT_P (new_tree)
-          && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
-    {
-      DECL_DLLIMPORT_P (new_tree) = 0;
-      warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: "
-             "dllimport ignored", new_tree);
-    }
-  else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new_tree))
-    {
-      /* Warn about overriding a symbol that has already been used, e.g.:
-           extern int __attribute__ ((dllimport)) foo;
-          int* bar () {return &foo;}
-          int foo;
-      */
-      if (TREE_USED (old))
-       {
-         warning (0, "%q+D redeclared without dllimport attribute "
-                  "after being referenced with dll linkage", new_tree);
-         /* If we have used a variable's address with dllimport linkage,
-             keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
-             decl may already have had TREE_CONSTANT computed.
-             We still remove the attribute so that assembler code refers
-             to '&foo rather than '_imp__foo'.  */
-         if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
-           DECL_DLLIMPORT_P (new_tree) = 1;
-       }
-
-      /* Let an inline definition silently override the external reference,
-        but otherwise warn about attribute inconsistency.  */
-      else if (TREE_CODE (new_tree) == VAR_DECL
-              || !DECL_DECLARED_INLINE_P (new_tree))
-       warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
-                 "previous dllimport ignored", new_tree);
-    }
-  else
-    delete_dllimport_p = 0;
-
-  a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
-
-  if (delete_dllimport_p)
-    a = remove_attribute ("dllimport", a);
-
-  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;
-  bool is_dllimport;
-
-  /* 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)
-       {
-         node = TYPE_NAME (node);
-         if (!node)
-           return NULL_TREE;
-       }
-      else
-       {
-         warning (OPT_Wattributes, "%qE attribute ignored",
-                  name);
-         *no_add_attrs = true;
-         return NULL_TREE;
-       }
-    }
-
-  if (TREE_CODE (node) != FUNCTION_DECL
-      && TREE_CODE (node) != VAR_DECL
-      && TREE_CODE (node) != TYPE_DECL)
-    {
-      *no_add_attrs = true;
-      warning (OPT_Wattributes, "%qE attribute ignored",
-              name);
-      return NULL_TREE;
-    }
-
-  if (TREE_CODE (node) == TYPE_DECL
-      && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE
-      && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE)
-    {
-      *no_add_attrs = true;
-      warning (OPT_Wattributes, "%qE attribute ignored",
-              name);
-      return NULL_TREE;
-    }
-
-  is_dllimport = is_attribute_p ("dllimport", name);
-
-  /* Report error on dllimport ambiguities seen now before they cause
-     any damage.  */
-  if (is_dllimport)
-    {
-      /* Honor any target-specific overrides. */
-      if (!targetm.valid_dllimport_attribute_p (node))
-       *no_add_attrs = true;
-
-     else if (TREE_CODE (node) == FUNCTION_DECL
-               && DECL_DECLARED_INLINE_P (node))
-       {
-         warning (OPT_Wattributes, "inline function %q+D declared as "
-                 " dllimport: attribute ignored", node);
-         *no_add_attrs = true;
-       }
-      /* Like MS, treat definition of dllimported variables and
-        non-inlined functions on declaration as syntax errors. */
-     else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
-       {
-         error ("function %q+D definition is marked dllimport", node);
-         *no_add_attrs = true;
-       }
-
-     else if (TREE_CODE (node) == VAR_DECL)
-       {
-         if (DECL_INITIAL (node))
-           {
-             error ("variable %q+D definition is marked dllimport",
-                    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;
-       }
-
-      if (*no_add_attrs == false)
-        DECL_DLLIMPORT_P (node) = 1;
-    }
-  else if (TREE_CODE (node) == FUNCTION_DECL
-          && DECL_DECLARED_INLINE_P (node)
-          && flag_keep_inline_dllexport)
-    /* An exported function, even if inline, must be emitted.  */
-    DECL_EXTERNAL (node) = 0;
-
-  /*  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 ("external linkage required for symbol %q+D because of "
-            "%qE attribute", node, name);
-      *no_add_attrs = true;
-    }
-
-  /* A dllexport'd entity must have default visibility so that other
-     program units (shared libraries or the main executable) can see
-     it.  A dllimport'd entity must have default visibility so that
-     the linker knows that undefined references within this program
-     unit can be resolved by the dynamic linker.  */
-  if (!*no_add_attrs)
-    {
-      if (DECL_VISIBILITY_SPECIFIED (node)
-         && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT)
-       error ("%qE implies default visibility, but %qD has already "
-              "been declared with a different visibility",
-              name, node);
-      DECL_VISIBILITY (node) = VISIBILITY_DEFAULT;
-      DECL_VISIBILITY_SPECIFIED (node) = 1;
-    }
-
-  return NULL_TREE;
-}
-
-#endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES  */
-\f
-/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
-   of the various TYPE_QUAL values.  */
-
-static void
-set_type_quals (tree type, int type_quals)
-{
-  TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
-  TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
-  TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
-  TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
-  TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
-}
-
-/* Returns true iff unqualified CAND and BASE are equivalent.  */
-
-bool
-check_base_type (const_tree cand, const_tree base)
-{
-  return (TYPE_NAME (cand) == TYPE_NAME (base)
-         /* Apparently this is needed for Objective-C.  */
-         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
-         /* Check alignment.  */
-         && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
-         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
-                                  TYPE_ATTRIBUTES (base)));
-}
-
-/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
-
-bool
-check_qualified_type (const_tree cand, const_tree base, int type_quals)
-{
-  return (TYPE_QUALS (cand) == type_quals
-         && check_base_type (cand, base));
-}
-
-/* Returns true iff CAND is equivalent to BASE with ALIGN.  */
-
-static bool
-check_aligned_type (const_tree cand, const_tree base, unsigned int align)
-{
-  return (TYPE_QUALS (cand) == TYPE_QUALS (base)
-         && TYPE_NAME (cand) == TYPE_NAME (base)
-         /* Apparently this is needed for Objective-C.  */
-         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
-         /* Check alignment.  */
-         && TYPE_ALIGN (cand) == align
-         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
-                                  TYPE_ATTRIBUTES (base)));
-}
-
-/* This function checks to see if TYPE matches the size one of the built-in 
-   atomic types, and returns that core atomic type.  */
-
-static tree
-find_atomic_core_type (tree type)
-{
-  tree base_atomic_type;
+static tree
+find_atomic_core_type (tree type)
+{
+  tree base_atomic_type;
 
   /* Only handle complete types.  */
   if (TYPE_SIZE (type) == NULL_TREE)
@@ -6619,7 +5869,7 @@ get_qualified_type (tree type, int type_quals)
    exist.  This function never returns NULL_TREE.  */
 
 tree
-build_qualified_type (tree type, int type_quals)
+build_qualified_type (tree type, int type_quals MEM_STAT_DECL)
 {
   tree t;
 
@@ -6629,7 +5879,7 @@ build_qualified_type (tree type, int type_quals)
   /* If not, build it.  */
   if (!t)
     {
-      t = build_variant_type_copy (type);
+      t = build_variant_type_copy (type PASS_MEM_STAT);
       set_type_quals (t, type_quals);
 
       if (((type_quals & TYPE_QUAL_ATOMIC) == TYPE_QUAL_ATOMIC))
@@ -6681,6 +5931,7 @@ build_aligned_type (tree type, unsigned int align)
 
   t = build_variant_type_copy (type);
   SET_TYPE_ALIGN (t, align);
+  TYPE_USER_ALIGN (t) = 1;
 
   return t;
 }
@@ -6691,9 +5942,9 @@ build_aligned_type (tree type, unsigned int align)
    TYPE_CANONICAL points to itself. */
 
 tree
-build_distinct_type_copy (tree type)
+build_distinct_type_copy (tree type MEM_STAT_DECL)
 {
-  tree t = copy_node (type);
+  tree t = copy_node (type PASS_MEM_STAT);
 
   TYPE_POINTER_TO (t) = 0;
   TYPE_REFERENCE_TO (t) = 0;
@@ -6709,12 +5960,6 @@ build_distinct_type_copy (tree type)
   TYPE_MAIN_VARIANT (t) = t;
   TYPE_NEXT_VARIANT (t) = 0;
 
-  /* We do not record methods in type copies nor variants
-     so we do not need to keep them up to date when new method
-     is inserted.  */
-  if (RECORD_OR_UNION_TYPE_P (t))
-    TYPE_METHODS (t) = NULL_TREE;
-
   /* Note that it is now possible for TYPE_MIN_VALUE to be a value
      whose TREE_TYPE is not t.  This can also happen in the Ada
      frontend when using subtypes.  */
@@ -6729,11 +5974,11 @@ build_distinct_type_copy (tree type)
    require structural equality checks). */
 
 tree
-build_variant_type_copy (tree type)
+build_variant_type_copy (tree type MEM_STAT_DECL)
 {
   tree t, m = TYPE_MAIN_VARIANT (type);
 
-  t = build_distinct_type_copy (type);
+  t = build_distinct_type_copy (type PASS_MEM_STAT);
 
   /* Since we're building a variant, assume that it is a non-semantic
      variant. This also propagates TYPE_STRUCTURAL_EQUALITY_P. */
@@ -6832,7 +6077,7 @@ decl_init_priority_insert (tree decl, priority_type priority)
       if (!snode)
        return;
     }
-  else if (TREE_CODE (decl) == VAR_DECL)
+  else if (VAR_P (decl))
     snode = varpool_node::get_create (decl);
   else
     snode = cgraph_node::get_create (decl);
@@ -6976,18 +6221,80 @@ decl_debug_args_insert (tree from)
 /* Hashing of types so that we don't make duplicates.
    The entry point is `type_hash_canon'.  */
 
-/* Compute a hash code for a list of types (chain of TREE_LIST nodes
-   with types in the TREE_VALUE slots), by adding the hash codes
-   of the individual types.  */
+/* Generate the default hash code for TYPE.  This is designed for
+   speed, rather than maximum entropy.  */
 
-static void
-type_hash_list (const_tree list, inchash::hash &hstate)
+hashval_t
+type_hash_canon_hash (tree type)
 {
-  const_tree tail;
+  inchash::hash hstate;
+
+  hstate.add_int (TREE_CODE (type));
+
+  if (TREE_TYPE (type))
+    hstate.add_object (TYPE_HASH (TREE_TYPE (type)));
+
+  for (tree t = TYPE_ATTRIBUTES (type); t; t = TREE_CHAIN (t))
+    /* Just the identifier is adequate to distinguish.  */
+    hstate.add_object (IDENTIFIER_HASH_VALUE (get_attribute_name (t)));
+
+  switch (TREE_CODE (type))
+    {
+    case METHOD_TYPE:
+      hstate.add_object (TYPE_HASH (TYPE_METHOD_BASETYPE (type)));
+      /* FALLTHROUGH. */
+    case FUNCTION_TYPE:
+      for (tree t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+       if (TREE_VALUE (t) != error_mark_node)
+         hstate.add_object (TYPE_HASH (TREE_VALUE (t)));
+      break;
+
+    case OFFSET_TYPE:
+      hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type)));
+      break;
+
+    case ARRAY_TYPE:
+      {
+       if (TYPE_DOMAIN (type))
+         hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type)));
+       if (!AGGREGATE_TYPE_P (TREE_TYPE (type)))
+         {
+           unsigned typeless = TYPE_TYPELESS_STORAGE (type);
+           hstate.add_object (typeless);
+         }
+      }
+      break;
+
+    case INTEGER_TYPE:
+      {
+       tree t = TYPE_MAX_VALUE (type);
+       if (!t)
+         t = TYPE_MIN_VALUE (type);
+       for (int i = 0; i < TREE_INT_CST_NUNITS (t); i++)
+         hstate.add_object (TREE_INT_CST_ELT (t, i));
+       break;
+      }
+      
+    case REAL_TYPE:
+    case FIXED_POINT_TYPE:
+      {
+       unsigned prec = TYPE_PRECISION (type);
+       hstate.add_object (prec);
+       break;
+      }
+
+    case VECTOR_TYPE:
+      {
+       unsigned nunits = TYPE_VECTOR_SUBPARTS (type);
+       hstate.add_object (nunits);
+       break;
+      }
+
+    default:
+      break;
+    }
 
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    if (TREE_VALUE (tail) != error_mark_node)
-      hstate.add_object (TYPE_HASH (TREE_VALUE (tail)));
+  return hstate.end ();
 }
 
 /* These are the Hashtable callback functions.  */
@@ -7037,7 +6344,7 @@ type_cache_hasher::equal (type_hash *a, type_hash *b)
                                   TYPE_VALUES (b->type))))
        return 0;
 
-      /* ... fall through ... */
+      /* fall through */
 
     case INTEGER_TYPE:
     case REAL_TYPE:
@@ -7069,7 +6376,16 @@ type_cache_hasher::equal (type_hash *a, type_hash *b)
         break;
       return 0;
     case ARRAY_TYPE:
-      return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
+      /* Don't compare TYPE_TYPELESS_STORAGE flag on aggregates,
+        where the flag should be inherited from the element type
+        and can change after ARRAY_TYPEs are created; on non-aggregates
+        compare it and hash it, scalars will never have that flag set
+        and we need to differentiate between arrays created by different
+        front-ends or middle-end created arrays.  */
+      return (TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type)
+             && (AGGREGATE_TYPE_P (TREE_TYPE (a->type))
+                 || (TYPE_TYPELESS_STORAGE (a->type)
+                     == TYPE_TYPELESS_STORAGE (b->type))));
 
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -7134,6 +6450,22 @@ type_hash_canon (unsigned int hashcode, tree type)
     {
       tree t1 = ((type_hash *) *loc)->type;
       gcc_assert (TYPE_MAIN_VARIANT (t1) == t1);
+      if (TYPE_UID (type) + 1 == next_type_uid)
+       --next_type_uid;
+      /* Free also min/max values and the cache for integer
+        types.  This can't be done in free_node, as LTO frees
+        those on its own.  */
+      if (TREE_CODE (type) == INTEGER_TYPE)
+       {
+         if (TYPE_MIN_VALUE (type)
+             && TREE_TYPE (TYPE_MIN_VALUE (type)) == type)
+           ggc_free (TYPE_MIN_VALUE (type));
+         if (TYPE_MAX_VALUE (type)
+             && TREE_TYPE (TYPE_MAX_VALUE (type)) == type)
+           ggc_free (TYPE_MAX_VALUE (type));
+         if (TYPE_CACHED_VALUES_P (type))
+           ggc_free (TYPE_CACHED_VALUES (type));
+       }
       free_node (type);
       return t1;
     }
@@ -7159,82 +6491,6 @@ print_type_hash_statistics (void)
           type_hash_table->collisions ());
 }
 
-/* Compute a hash code for a list of attributes (chain of TREE_LIST nodes
-   with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots),
-   by adding the hash codes of the individual attributes.  */
-
-static void
-attribute_hash_list (const_tree list, inchash::hash &hstate)
-{
-  const_tree tail;
-
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    /* ??? Do we want to add in TREE_VALUE too? */
-    hstate.add_object (IDENTIFIER_HASH_VALUE (get_attribute_name (tail)));
-}
-
-/* Given two lists of attributes, return true if list l2 is
-   equivalent to l1.  */
-
-int
-attribute_list_equal (const_tree l1, const_tree l2)
-{
-  if (l1 == l2)
-    return 1;
-
-  return attribute_list_contained (l1, l2)
-        && attribute_list_contained (l2, l1);
-}
-
-/* Given two lists of attributes, return true if list L2 is
-   completely contained within L1.  */
-/* ??? This would be faster if attribute names were stored in a canonicalized
-   form.  Otherwise, if L1 uses `foo' and L2 uses `__foo__', the long method
-   must be used to show these elements are equivalent (which they are).  */
-/* ??? It's not clear that attributes with arguments will always be handled
-   correctly.  */
-
-int
-attribute_list_contained (const_tree l1, const_tree l2)
-{
-  const_tree t1, t2;
-
-  /* First check the obvious, maybe the lists are identical.  */
-  if (l1 == l2)
-    return 1;
-
-  /* Maybe the lists are similar.  */
-  for (t1 = l1, t2 = l2;
-       t1 != 0 && t2 != 0
-        && get_attribute_name (t1) == get_attribute_name (t2)
-        && TREE_VALUE (t1) == TREE_VALUE (t2);
-       t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
-    ;
-
-  /* Maybe the lists are equal.  */
-  if (t1 == 0 && t2 == 0)
-    return 1;
-
-  for (; t2 != 0; t2 = TREE_CHAIN (t2))
-    {
-      const_tree attr;
-      /* This CONST_CAST is okay because lookup_attribute does not
-        modify its argument and the return value is assigned to a
-        const_tree.  */
-      for (attr = lookup_ident_attribute (get_attribute_name (t2),
-                                         CONST_CAST_TREE (l1));
-          attr != NULL_TREE && !attribute_value_equal (t2, attr);
-          attr = lookup_ident_attribute (get_attribute_name (t2),
-                                         TREE_CHAIN (attr)))
-       ;
-
-      if (attr == NULL_TREE)
-       return 0;
-    }
-
-  return 1;
-}
-
 /* Given two lists of types
    (chains of TREE_LIST nodes with types in the TREE_VALUE slots)
    return 1 if the lists contain the same types in the same order.
@@ -7770,7 +7026,7 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
   enum tree_code code;
   enum tree_code_class tclass;
 
-  if (t == NULL_TREE)
+  if (t == NULL_TREE || t == error_mark_node)
     {
       hstate.merge_hash (0);
       return;
@@ -7861,6 +7117,10 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
          inchash::add_expr (tsi_stmt (i), hstate, flags);
        return;
       }
+    case TREE_VEC:
+      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
+       inchash::add_expr (TREE_VEC_ELT (t, i), hstate, flags);
+      return;
     case FUNCTION_DECL:
       /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
         Otherwise nodes that compare equal according to operand_equal_p might
@@ -8233,7 +7493,6 @@ static tree
 build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
 {
   tree itype = make_node (INTEGER_TYPE);
-  inchash::hash hstate;
 
   TREE_TYPE (itype) = type;
 
@@ -8261,10 +7520,8 @@ build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
       return itype;
     }
 
-  inchash::add_expr (TYPE_MIN_VALUE (itype), hstate);
-  inchash::add_expr (TYPE_MAX_VALUE (itype), hstate);
-  hstate.merge_hash (TYPE_HASH (type));
-  itype = type_hash_canon (hstate.end (), itype);
+  hashval_t hash = type_hash_canon_hash (itype);
+  itype = type_hash_canon (hash, itype);
 
   return itype;
 }
@@ -8342,10 +7599,12 @@ subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval)
 
 /* Construct, lay out and return the type of arrays of elements with ELT_TYPE
    and number of elements specified by the range of values of INDEX_TYPE.
+   If TYPELESS_STORAGE is true, TYPE_TYPELESS_STORAGE flag is set on the type.
    If SHARED is true, reuse such a type that has already been constructed.  */
 
 static tree
-build_array_type_1 (tree elt_type, tree index_type, bool shared)
+build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
+                   bool shared)
 {
   tree t;
 
@@ -8359,6 +7618,7 @@ build_array_type_1 (tree elt_type, tree index_type, bool shared)
   TREE_TYPE (t) = elt_type;
   TYPE_DOMAIN (t) = index_type;
   TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type);
+  TYPE_TYPELESS_STORAGE (t) = typeless_storage;
   layout_type (t);
 
   /* If the element type is incomplete at this point we get marked for
@@ -8369,11 +7629,8 @@ build_array_type_1 (tree elt_type, tree index_type, bool shared)
 
   if (shared)
     {
-      inchash::hash hstate;
-      hstate.add_object (TYPE_HASH (elt_type));
-      if (index_type)
-       hstate.add_object (TYPE_HASH (index_type));
-      t = type_hash_canon (hstate.end (), t);
+      hashval_t hash = type_hash_canon_hash (t);
+      t = type_hash_canon (hash, t);
     }
 
   if (TYPE_CANONICAL (t) == t)
@@ -8388,7 +7645,7 @@ build_array_type_1 (tree elt_type, tree index_type, bool shared)
          = build_array_type_1 (TYPE_CANONICAL (elt_type),
                                index_type
                                ? TYPE_CANONICAL (index_type) : NULL_TREE,
-                               shared);
+                               typeless_storage, shared);
     }
 
   return t;
@@ -8397,9 +7654,9 @@ build_array_type_1 (tree elt_type, tree index_type, bool shared)
 /* Wrapper around build_array_type_1 with SHARED set to true.  */
 
 tree
-build_array_type (tree elt_type, tree index_type)
+build_array_type (tree elt_type, tree index_type, bool typeless_storage)
 {
-  return build_array_type_1 (elt_type, index_type, true);
+  return build_array_type_1 (elt_type, index_type, typeless_storage, true);
 }
 
 /* Wrapper around build_array_type_1 with SHARED set to false.  */
@@ -8407,7 +7664,7 @@ build_array_type (tree elt_type, tree index_type)
 tree
 build_nonshared_array_type (tree elt_type, tree index_type)
 {
-  return build_array_type_1 (elt_type, index_type, false);
+  return build_array_type_1 (elt_type, index_type, false, false);
 }
 
 /* Return a representation of ELT_TYPE[NELTS], using indices of type
@@ -8530,9 +7787,8 @@ build_function_type (tree value_type, tree arg_types)
   TYPE_ARG_TYPES (t) = arg_types;
 
   /* If we already have such a type, use the old one.  */
-  hstate.add_object (TYPE_HASH (value_type));
-  type_hash_list (arg_types, hstate);
-  t = type_hash_canon (hstate.end (), t);
+  hashval_t hash = type_hash_canon_hash (t);
+  t = type_hash_canon (hash, t);
 
   /* Set up the canonical type. */
   any_structural_p   = TYPE_STRUCTURAL_EQUALITY_P (value_type);
@@ -8669,7 +7925,6 @@ build_method_type_directly (tree basetype,
 {
   tree t;
   tree ptype;
-  inchash::hash hstate;
   bool any_structural_p, any_noncanonical_p;
   tree canon_argtypes;
 
@@ -8686,10 +7941,8 @@ build_method_type_directly (tree basetype,
   TYPE_ARG_TYPES (t) = argtypes;
 
   /* If we already have such a type, use the old one.  */
-  hstate.add_object (TYPE_HASH (basetype));
-  hstate.add_object (TYPE_HASH (rettype));
-  type_hash_list (argtypes, hstate);
-  t = type_hash_canon (hstate.end (), t);
+  hashval_t hash = type_hash_canon_hash (t);
+  t = type_hash_canon (hash, t);
 
   /* Set up the canonical type. */
   any_structural_p
@@ -8737,7 +7990,6 @@ tree
 build_offset_type (tree basetype, tree type)
 {
   tree t;
-  inchash::hash hstate;
 
   /* Make a node of the sort we want.  */
   t = make_node (OFFSET_TYPE);
@@ -8746,9 +7998,8 @@ build_offset_type (tree basetype, tree type)
   TREE_TYPE (t) = type;
 
   /* If we already have such a type, use the old one.  */
-  hstate.add_object (TYPE_HASH (basetype));
-  hstate.add_object (TYPE_HASH (type));
-  t = type_hash_canon (hstate.end (), t);
+  hashval_t hash = type_hash_canon_hash (t);
+  t = type_hash_canon (hash, t);
 
   if (!COMPLETE_TYPE_P (t))
     layout_type (t);
@@ -8768,13 +8019,17 @@ build_offset_type (tree basetype, tree type)
   return t;
 }
 
-/* Create a complex type whose components are COMPONENT_TYPE.  */
+/* Create a complex type whose components are COMPONENT_TYPE.
+
+   If NAMED is true, the type is given a TYPE_NAME.  We do not always
+   do so because this creates a DECL node and thus make the DECL_UIDs
+   dependent on the type canonicalization hashtable, which is GC-ed,
+   so the DECL_UIDs would not be stable wrt garbage collection.  */
 
 tree
-build_complex_type (tree component_type)
+build_complex_type (tree component_type, bool named)
 {
   tree t;
-  inchash::hash hstate;
 
   gcc_assert (INTEGRAL_TYPE_P (component_type)
              || SCALAR_FLOAT_TYPE_P (component_type)
@@ -8784,11 +8039,10 @@ build_complex_type (tree component_type)
   t = make_node (COMPLEX_TYPE);
 
   TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
-  SET_TYPE_MODE (t, GET_MODE_COMPLEX_MODE (TYPE_MODE (component_type)));
 
   /* If we already have such a type, use the old one.  */
-  hstate.add_object (TYPE_HASH (component_type));
-  t = type_hash_canon (hstate.end (), t);
+  hashval_t hash = type_hash_canon_hash (t);
+  t = type_hash_canon (hash, t);
 
   if (!COMPLETE_TYPE_P (t))
     layout_type (t);
@@ -8799,11 +8053,11 @@ build_complex_type (tree component_type)
        SET_TYPE_STRUCTURAL_EQUALITY (t);
       else if (TYPE_CANONICAL (component_type) != component_type)
        TYPE_CANONICAL (t)
-         = build_complex_type (TYPE_CANONICAL (component_type));
+         = build_complex_type (TYPE_CANONICAL (component_type), named);
     }
 
   /* We need to create a name, since complex is a fundamental type.  */
-  if (! TYPE_NAME (t))
+  if (!TYPE_NAME (t) && named)
     {
       const char *name;
       if (component_type == char_type_node)
@@ -8847,50 +8101,99 @@ build_complex_type (tree component_type)
 tree
 excess_precision_type (tree type)
 {
-  if (flag_excess_precision != EXCESS_PRECISION_FAST)
+  /* The target can give two different responses to the question of
+     which excess precision mode it would like depending on whether we
+     are in -fexcess-precision=standard or -fexcess-precision=fast.  */
+
+  enum excess_precision_type requested_type
+    = (flag_excess_precision == EXCESS_PRECISION_FAST
+       ? EXCESS_PRECISION_TYPE_FAST
+       : EXCESS_PRECISION_TYPE_STANDARD);
+
+  enum flt_eval_method target_flt_eval_method
+    = targetm.c.excess_precision (requested_type);
+
+  /* The target should not ask for unpredictable float evaluation (though
+     it might advertise that implicitly the evaluation is unpredictable,
+     but we don't care about that here, it will have been reported
+     elsewhere).  If it does ask for unpredictable evaluation, we have
+     nothing to do here.  */
+  gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
+
+  /* Nothing to do.  The target has asked for all types we know about
+     to be computed with their native precision and range.  */
+  if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return NULL_TREE;
+
+  /* The target will promote this type in a target-dependent way, so excess
+     precision ought to leave it alone.  */
+  if (targetm.promoted_type (type) != NULL_TREE)
+    return NULL_TREE;
+
+  machine_mode float16_type_mode = (float16_type_node
+                                   ? TYPE_MODE (float16_type_node)
+                                   : VOIDmode);
+  machine_mode float_type_mode = TYPE_MODE (float_type_node);
+  machine_mode double_type_mode = TYPE_MODE (double_type_node);
+
+  switch (TREE_CODE (type))
     {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (TREE_CODE (type))
-       {
-       case REAL_TYPE:
-         switch (flt_eval_method)
-           {
-           case 1:
-             if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
-               return double_type_node;
-             break;
-           case 2:
-             if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
-                 || TYPE_MODE (type) == TYPE_MODE (double_type_node))
-               return long_double_type_node;
-             break;
-           default:
-             gcc_unreachable ();
-           }
-         break;
-       case COMPLEX_TYPE:
-         if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
-           return NULL_TREE;
-         switch (flt_eval_method)
-           {
-           case 1:
-             if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
-               return complex_double_type_node;
-             break;
-           case 2:
-             if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
-                 || (TYPE_MODE (TREE_TYPE (type))
-                     == TYPE_MODE (double_type_node)))
-               return complex_long_double_type_node;
-             break;
-           default:
-             gcc_unreachable ();
-           }
-         break;
-       default:
-         break;
-       }
+    case REAL_TYPE:
+      {
+       machine_mode type_mode = TYPE_MODE (type);
+       switch (target_flt_eval_method)
+         {
+         case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+           if (type_mode == float16_type_mode)
+             return float_type_node;
+           break;
+         case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+           if (type_mode == float16_type_mode
+               || type_mode == float_type_mode)
+             return double_type_node;
+           break;
+         case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+           if (type_mode == float16_type_mode
+               || type_mode == float_type_mode
+               || type_mode == double_type_mode)
+             return long_double_type_node;
+           break;
+         default:
+           gcc_unreachable ();
+         }
+       break;
+      }
+    case COMPLEX_TYPE:
+      {
+       if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+         return NULL_TREE;
+       machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
+       switch (target_flt_eval_method)
+         {
+         case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+           if (type_mode == float16_type_mode)
+             return complex_float_type_node;
+           break;
+         case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+           if (type_mode == float16_type_mode
+               || type_mode == float_type_mode)
+             return complex_double_type_node;
+           break;
+         case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+           if (type_mode == float16_type_mode
+               || type_mode == float_type_mode
+               || type_mode == double_type_mode)
+             return complex_long_double_type_node;
+           break;
+         default:
+           gcc_unreachable ();
+         }
+       break;
+      }
+    default:
+      break;
     }
+
   return NULL_TREE;
 }
 \f
@@ -8972,13 +8275,21 @@ get_unwidened (tree op, tree for_type)
        }
     }
 
-  /* If we finally reach a constant see if it fits in for_type and
+  /* If we finally reach a constant see if it fits in sth smaller and
      in that case convert it.  */
-  if (for_type
-      && TREE_CODE (win) == INTEGER_CST
-      && TREE_TYPE (win) != for_type
-      && int_fits_type_p (win, for_type))
-    win = fold_convert (for_type, win);
+  if (TREE_CODE (win) == INTEGER_CST)
+    {
+      tree wtype = TREE_TYPE (win);
+      unsigned prec = wi::min_precision (win, TYPE_SIGN (wtype));
+      if (for_type)
+       prec = MAX (prec, final_prec);
+      if (prec < TYPE_PRECISION (wtype))
+       {
+         tree t = lang_hooks.types.type_for_size (prec, TYPE_UNSIGNED (wtype));
+         if (t && TYPE_PRECISION (t) < TYPE_PRECISION (wtype))
+           win = fold_convert (t, win);
+       }
+    }
 
   return win;
 }
@@ -9077,8 +8388,8 @@ get_narrower (tree op, int *unsignedp_ptr)
   return win;
 }
 \f
-/* Returns true if integer constant C has a value that is permissible
-   for type TYPE (an INTEGER_TYPE).  */
+/* Return true if integer constant C has a value that is permissible
+   for TYPE, an integral type.  */
 
 bool
 int_fits_type_p (const_tree c, const_tree type)
@@ -9087,6 +8398,11 @@ int_fits_type_p (const_tree c, const_tree type)
   bool ok_for_low_bound, ok_for_high_bound;
   signop sgn_c = TYPE_SIGN (TREE_TYPE (c));
 
+  /* Non-standard boolean types can have arbitrary precision but various
+     transformations assume that they can only take values 0 and +/-1.  */
+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    return wi::fits_to_boolean_p (c, type);
+
 retry:
   type_low_bound = TYPE_MIN_VALUE (type);
   type_high_bound = TYPE_MAX_VALUE (type);
@@ -9207,7 +8523,7 @@ bool
 auto_var_in_fn_p (const_tree var, const_tree fn)
 {
   return (DECL_P (var) && DECL_CONTEXT (var) == fn
-         && ((((TREE_CODE (var) == VAR_DECL && ! DECL_EXTERNAL (var))
+         && ((((VAR_P (var) && ! DECL_EXTERNAL (var))
                || TREE_CODE (var) == PARM_DECL)
               && ! TREE_STATIC (var))
              || TREE_CODE (var) == LABEL_DECL
@@ -9531,38 +8847,34 @@ dump_tree_statistics (void)
 \f
 #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
 
-/* Generate a crc32 of a byte.  */
+/* Generate a crc32 of the low BYTES bytes of VALUE.  */
 
-static unsigned
-crc32_unsigned_bits (unsigned chksum, unsigned value, unsigned bits)
+unsigned
+crc32_unsigned_n (unsigned chksum, unsigned value, unsigned bytes)
 {
-  unsigned ix;
-
-  for (ix = bits; ix--; value <<= 1)
+  /* This relies on the raw feedback's top 4 bits being zero.  */
+#define FEEDBACK(X) ((X) * 0x04c11db7)
+#define SYNDROME(X) (FEEDBACK ((X) & 1) ^ FEEDBACK ((X) & 2) \
+                    ^ FEEDBACK ((X) & 4) ^ FEEDBACK ((X) & 8))
+  static const unsigned syndromes[16] =
     {
-      unsigned feedback;
-      
-      feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
-      chksum <<= 1;
-      chksum ^= feedback;
-    }
-  return chksum;
-}
-
-/* Generate a crc32 of a 32-bit unsigned.  */
+      SYNDROME(0x0), SYNDROME(0x1), SYNDROME(0x2), SYNDROME(0x3),
+      SYNDROME(0x4), SYNDROME(0x5), SYNDROME(0x6), SYNDROME(0x7),
+      SYNDROME(0x8), SYNDROME(0x9), SYNDROME(0xa), SYNDROME(0xb),
+      SYNDROME(0xc), SYNDROME(0xd), SYNDROME(0xe), SYNDROME(0xf),
+    };
+#undef FEEDBACK
+#undef SYNDROME
 
-unsigned
-crc32_unsigned (unsigned chksum, unsigned value)
-{
-  return crc32_unsigned_bits (chksum, value, 32);
-}
+  value <<= (32 - bytes * 8);
+  for (unsigned ix = bytes * 2; ix--; value <<= 4)
+    {
+      unsigned feedback = syndromes[((value ^ chksum) >> 28) & 0xf];
 
-/* Generate a crc32 of a byte.  */
+      chksum = (chksum << 4) ^ feedback;
+    }
 
-unsigned
-crc32_byte (unsigned chksum, char byte)
-{
-  return crc32_unsigned_bits (chksum, (unsigned) byte << 24, 8);
+  return chksum;
 }
 
 /* Generate a crc32 of a string.  */
@@ -9571,9 +8883,7 @@ unsigned
 crc32_string (unsigned chksum, const char *string)
 {
   do
-    {
-      chksum = crc32_byte (chksum, *string);
-    }
+    chksum = crc32_byte (chksum, *string);
   while (*string++);
   return chksum;
 }
@@ -9685,10 +8995,10 @@ get_file_function_name (const char *type)
        file = LOCATION_FILE (input_location);
 
       len = strlen (file);
-      q = (char *) alloca (9 + 17 + len + 1);
+      q = (char *) alloca (9 + 19 + len + 1);
       memcpy (q, file, len + 1);
 
-      snprintf (q + len, 9 + 17 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX, 
+      snprintf (q + len, 9 + 19 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX,
                crc32_string (0, name), get_random_seed (false));
 
       p = q;
@@ -9987,7 +9297,6 @@ static tree
 make_vector_type (tree innertype, int nunits, machine_mode mode)
 {
   tree t;
-  inchash::hash hstate;
   tree mv_innertype = TYPE_MAIN_VARIANT (innertype);
 
   t = make_node (VECTOR_TYPE);
@@ -10005,11 +9314,8 @@ make_vector_type (tree innertype, int nunits, machine_mode mode)
 
   layout_type (t);
 
-  hstate.add_wide_int (VECTOR_TYPE);
-  hstate.add_wide_int (nunits);
-  hstate.add_wide_int (mode);
-  hstate.add_object (TYPE_HASH (TREE_TYPE (t)));
-  t = type_hash_canon (hstate.end (), t);
+  hashval_t hash = type_hash_canon_hash (t);
+  t = type_hash_canon (hash, t);
 
   /* We have built a main variant, based on the main variant of the
      inner type. Use it to build the variant we return.  */
@@ -10151,6 +9457,20 @@ build_atomic_base (tree type, unsigned int align)
   return t;
 }
 
+/* Information about the _FloatN and _FloatNx types.  This must be in
+   the same order as the corresponding TI_* enum values.  */
+const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES] =
+  {
+    { 16, false },
+    { 32, false },
+    { 64, false },
+    { 128, false },
+    { 32, true },
+    { 64, true },
+    { 128, true },
+  };
+
+
 /* Create nodes for all integer types (and error_mark_node) using the sizes
    of C datatypes.  SIGNED_CHAR specifies whether char is signed.  */
 
@@ -10238,6 +9558,30 @@ build_common_tree_nodes (bool signed_char)
        gcc_unreachable ();
     }
 
+  /* Define what type to use for ptrdiff_t.  */
+  if (strcmp (PTRDIFF_TYPE, "int") == 0)
+    ptrdiff_type_node = integer_type_node;
+  else if (strcmp (PTRDIFF_TYPE, "long int") == 0)
+    ptrdiff_type_node = long_integer_type_node;
+  else if (strcmp (PTRDIFF_TYPE, "long long int") == 0)
+    ptrdiff_type_node = long_long_integer_type_node;
+  else if (strcmp (PTRDIFF_TYPE, "short int") == 0)
+    ptrdiff_type_node = short_integer_type_node;
+  else
+    {
+      ptrdiff_type_node = NULL_TREE;
+      for (int i = 0; i < NUM_INT_N_ENTS; i++)
+       if (int_n_enabled_p[i])
+         {
+           char name[50];
+           sprintf (name, "__int%d", int_n_data[i].bitsize);
+           if (strcmp (name, PTRDIFF_TYPE) == 0)
+             ptrdiff_type_node = int_n_trees[i].signed_type;
+         }
+      if (ptrdiff_type_node == NULL_TREE)
+       gcc_unreachable ();
+    }
+
   /* Fill in the rest of the sized types.  Reuse existing type nodes
      when possible.  */
   intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
@@ -10307,7 +9651,10 @@ build_common_tree_nodes (bool signed_char)
   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;
+  for (unsigned i = 0;
+       i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
+       ++i)
+    builtin_structptr_types[i].node = builtin_structptr_types[i].base;
 
   pointer_sized_int_node = build_nonstandard_integer_type (POINTER_SIZE, 1);
 
@@ -10323,6 +9670,29 @@ build_common_tree_nodes (bool signed_char)
   TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
   layout_type (long_double_type_node);
 
+  for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+    {
+      int n = floatn_nx_types[i].n;
+      bool extended = floatn_nx_types[i].extended;
+      machine_mode mode = targetm.floatn_mode (n, extended);
+      if (mode == VOIDmode)
+       continue;
+      int precision = GET_MODE_PRECISION (mode);
+      /* Work around the rs6000 KFmode having precision 113 not
+        128.  */
+      const struct real_format *fmt = REAL_MODE_FORMAT (mode);
+      gcc_assert (fmt->b == 2 && fmt->emin + fmt->emax == 3);
+      int min_precision = fmt->p + ceil_log2 (fmt->emax - fmt->emin);
+      if (!extended)
+       gcc_assert (min_precision == n);
+      if (precision < min_precision)
+       precision = min_precision;
+      FLOATN_NX_TYPE_NODE (i) = make_node (REAL_TYPE);
+      TYPE_PRECISION (FLOATN_NX_TYPE_NODE (i)) = precision;
+      layout_type (FLOATN_NX_TYPE_NODE (i));
+      SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
+    }
+
   float_ptr_type_node = build_pointer_type (float_type_node);
   double_ptr_type_node = build_pointer_type (double_type_node);
   long_double_ptr_type_node = build_pointer_type (long_double_type_node);
@@ -10336,26 +9706,34 @@ build_common_tree_nodes (bool signed_char)
   /* Decimal float types. */
   dfloat32_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
-  layout_type (dfloat32_type_node);
   SET_TYPE_MODE (dfloat32_type_node, SDmode);
+  layout_type (dfloat32_type_node);
   dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node);
 
   dfloat64_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
-  layout_type (dfloat64_type_node);
   SET_TYPE_MODE (dfloat64_type_node, DDmode);
+  layout_type (dfloat64_type_node);
   dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node);
 
   dfloat128_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
-  layout_type (dfloat128_type_node);
   SET_TYPE_MODE (dfloat128_type_node, TDmode);
+  layout_type (dfloat128_type_node);
   dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
 
-  complex_integer_type_node = build_complex_type (integer_type_node);
-  complex_float_type_node = build_complex_type (float_type_node);
-  complex_double_type_node = build_complex_type (double_type_node);
-  complex_long_double_type_node = build_complex_type (long_double_type_node);
+  complex_integer_type_node = build_complex_type (integer_type_node, true);
+  complex_float_type_node = build_complex_type (float_type_node, true);
+  complex_double_type_node = build_complex_type (double_type_node, true);
+  complex_long_double_type_node = build_complex_type (long_double_type_node,
+                                                     true);
+
+  for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+    {
+      if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
+       COMPLEX_FLOATN_NX_TYPE_NODE (i)
+         = build_complex_type (FLOATN_NX_TYPE_NODE (i));
+    }
 
 /* Make fixed-point nodes based on sat/non-sat and signed/unsigned.  */
 #define MAKE_FIXED_TYPE_NODE(KIND,SIZE) \
@@ -10451,6 +9829,14 @@ set_call_expr_flags (tree decl, int flags)
   if (flags & ECF_LEAF)
     DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
                                        NULL, DECL_ATTRIBUTES (decl));
+  if (flags & ECF_COLD)
+    DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("cold"),
+                                       NULL, DECL_ATTRIBUTES (decl));
+  if (flags & ECF_RET1)
+    DECL_ATTRIBUTES (decl)
+      = tree_cons (get_identifier ("fn spec"),
+                  build_tree_list (NULL_TREE, build_string (1, "1")),
+                  DECL_ATTRIBUTES (decl));
   if ((flags & ECF_TM_PURE) && flag_tm)
     apply_tm_attr (decl, get_identifier ("transaction_pure"));
   /* Looping const or pure is implied by noreturn.
@@ -10486,13 +9872,20 @@ build_common_builtin_nodes (void)
   tree tmp, ftype;
   int ecf_flags;
 
-  if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
+  if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
+      || !builtin_decl_explicit_p (BUILT_IN_ABORT))
     {
       ftype = build_function_type (void_type_node, void_list_node);
-      local_define_builtin ("__builtin_unreachable", ftype, BUILT_IN_UNREACHABLE,
-                           "__builtin_unreachable",
-                           ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
-                           | ECF_CONST);
+      if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
+       local_define_builtin ("__builtin_unreachable", ftype,
+                             BUILT_IN_UNREACHABLE,
+                             "__builtin_unreachable",
+                             ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
+                             | ECF_CONST | ECF_COLD);
+      if (!builtin_decl_explicit_p (BUILT_IN_ABORT))
+       local_define_builtin ("__builtin_abort", ftype, BUILT_IN_ABORT,
+                             "abort",
+                             ECF_LEAF | ECF_NORETURN | ECF_CONST | ECF_COLD);
     }
 
   if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
@@ -10504,10 +9897,10 @@ build_common_builtin_nodes (void)
 
       if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
        local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
-                             "memcpy", ECF_NOTHROW | ECF_LEAF);
+                             "memcpy", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
       if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
        local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
-                             "memmove", ECF_NOTHROW | ECF_LEAF);
+                             "memmove", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
     }
 
   if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
@@ -10525,15 +9918,19 @@ build_common_builtin_nodes (void)
                                        ptr_type_node, integer_type_node,
                                        size_type_node, NULL_TREE);
       local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
-                           "memset", ECF_NOTHROW | ECF_LEAF);
+                           "memset", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
     }
 
+  /* If we're checking the stack, `alloca' can throw.  */
+  const int alloca_flags
+    = ECF_MALLOC | ECF_LEAF | (flag_stack_check ? 0 : ECF_NOTHROW);
+
   if (!builtin_decl_explicit_p (BUILT_IN_ALLOCA))
     {
       ftype = build_function_type_list (ptr_type_node,
                                        size_type_node, NULL_TREE);
       local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
-                           "alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
+                           "alloca", alloca_flags);
     }
 
   ftype = build_function_type_list (ptr_type_node, size_type_node,
@@ -10541,14 +9938,7 @@ build_common_builtin_nodes (void)
   local_define_builtin ("__builtin_alloca_with_align", ftype,
                        BUILT_IN_ALLOCA_WITH_ALIGN,
                        "__builtin_alloca_with_align",
-                       ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
-
-  /* If we're checking the stack, `alloca' can throw.  */
-  if (flag_stack_check)
-    {
-      TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA)) = 0;
-      TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN)) = 0;
-    }
+                       alloca_flags);
 
   ftype = build_function_type_list (void_type_node,
                                    ptr_type_node, ptr_type_node,
@@ -10560,12 +9950,19 @@ build_common_builtin_nodes (void)
                        BUILT_IN_INIT_HEAP_TRAMPOLINE,
                        "__builtin_init_heap_trampoline",
                        ECF_NOTHROW | ECF_LEAF);
+  local_define_builtin ("__builtin_init_descriptor", ftype,
+                       BUILT_IN_INIT_DESCRIPTOR,
+                       "__builtin_init_descriptor", ECF_NOTHROW | ECF_LEAF);
 
   ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
   local_define_builtin ("__builtin_adjust_trampoline", ftype,
                        BUILT_IN_ADJUST_TRAMPOLINE,
                        "__builtin_adjust_trampoline",
                        ECF_CONST | ECF_NOTHROW);
+  local_define_builtin ("__builtin_adjust_descriptor", ftype,
+                       BUILT_IN_ADJUST_DESCRIPTOR,
+                       "__builtin_adjust_descriptor",
+                       ECF_CONST | ECF_NOTHROW);
 
   ftype = build_function_type_list (void_type_node,
                                    ptr_type_node, ptr_type_node, NULL_TREE);
@@ -10594,8 +9991,15 @@ build_common_builtin_nodes (void)
                        BUILT_IN_STACK_RESTORE,
                        "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF);
 
+  ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
+                                   const_ptr_type_node, size_type_node,
+                                   NULL_TREE);
+  local_define_builtin ("__builtin_memcmp_eq", ftype, BUILT_IN_MEMCMP_EQ,
+                       "__builtin_memcmp_eq",
+                       ECF_PURE | ECF_NOTHROW | ECF_LEAF);
+
   /* If there's a possibility that we might use the ARM EABI, build the
-    alternate __cxa_end_cleanup node used to resume from C++ and Java.  */
+    alternate __cxa_end_cleanup node used to resume from C++.  */
   if (targetm.arm_eabi_unwinder)
     {
       ftype = build_function_type_list (void_type_node, NULL_TREE);
@@ -11042,7 +10446,7 @@ build_omp_clause (location_t loc, enum omp_clause_code code)
    object is initialized to zeros.  */
 
 tree
-build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL)
+build_vl_exp (enum tree_code code, int len MEM_STAT_DECL)
 {
   tree t;
   int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp);
@@ -11333,9 +10737,9 @@ int_cst_value (const_tree x)
     {
       bool negative = ((val >> (bits - 1)) & 1) != 0;
       if (negative)
-       val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
+       val |= HOST_WIDE_INT_M1U << (bits - 1) << 1;
       else
-       val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+       val &= ~(HOST_WIDE_INT_M1U << (bits - 1) << 1);
     }
 
   return val;
@@ -11559,7 +10963,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
          break;
        }
 
-      /* ... fall through ... */
+      /* fall through */
 
     case COMPLEX_TYPE:
       WALK_SUBTREE (TREE_TYPE (type));
@@ -11755,7 +11159,6 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
          WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
          /* FALLTHRU */
 
-       case OMP_CLAUSE_DEVICE_RESIDENT:
        case OMP_CLAUSE_ASYNC:
        case OMP_CLAUSE_WAIT:
        case OMP_CLAUSE_WORKER:
@@ -11814,6 +11217,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_AUTO:
        case OMP_CLAUSE_SEQ:
        case OMP_CLAUSE_TILE:
+       case OMP_CLAUSE__SIMT_:
          WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
 
        case OMP_CLAUSE_LASTPRIVATE:
@@ -12941,6 +12345,25 @@ drop_tree_overflow (tree t)
      and drop the flag.  */
   t = copy_node (t);
   TREE_OVERFLOW (t) = 0;
+
+  /* For constants that contain nested constants, drop the flag
+     from those as well.  */
+  if (TREE_CODE (t) == COMPLEX_CST)
+    {
+      if (TREE_OVERFLOW (TREE_REALPART (t)))
+       TREE_REALPART (t) = drop_tree_overflow (TREE_REALPART (t));
+      if (TREE_OVERFLOW (TREE_IMAGPART (t)))
+       TREE_IMAGPART (t) = drop_tree_overflow (TREE_IMAGPART (t));
+    }
+  if (TREE_CODE (t) == VECTOR_CST)
+    {
+      for (unsigned i = 0; i < VECTOR_CST_NELTS (t); ++i)
+       {
+         tree& elt = VECTOR_CST_ELT (t, i);
+         if (TREE_OVERFLOW (elt))
+           elt = drop_tree_overflow (elt);
+       }
+    }
   return t;
 }
 
@@ -13038,15 +12461,26 @@ array_ref_up_bound (tree exp)
   return NULL_TREE;
 }
 
-/* Returns true if REF is an array reference to an array at the end of
-   a structure.  If this is the case, the array may be allocated larger
+/* Returns true if REF is an array reference or a component reference
+   to an array at the end of a structure.
+   If this is the case, the array may be allocated larger
    than its upper bound implies.  */
 
 bool
 array_at_struct_end_p (tree ref)
 {
-  if (TREE_CODE (ref) != ARRAY_REF
-      && TREE_CODE (ref) != ARRAY_RANGE_REF)
+  tree atype;
+
+  if (TREE_CODE (ref) == ARRAY_REF
+      || TREE_CODE (ref) == ARRAY_RANGE_REF)
+    {
+      atype = TREE_TYPE (TREE_OPERAND (ref, 0));
+      ref = TREE_OPERAND (ref, 0);
+    }
+  else if (TREE_CODE (ref) == COMPONENT_REF
+          && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
+    atype = TREE_TYPE (TREE_OPERAND (ref, 1));
+  else
     return false;
 
   while (handled_component_p (ref))
@@ -13054,24 +12488,67 @@ array_at_struct_end_p (tree ref)
       /* If the reference chain contains a component reference to a
          non-union type and there follows another field the reference
         is not at the end of a structure.  */
-      if (TREE_CODE (ref) == COMPONENT_REF
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+      if (TREE_CODE (ref) == COMPONENT_REF)
        {
-         tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
-         while (nextf && TREE_CODE (nextf) != FIELD_DECL)
-           nextf = DECL_CHAIN (nextf);
-         if (nextf)
-           return false;
+         if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+           {
+             tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
+             while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+               nextf = DECL_CHAIN (nextf);
+             if (nextf)
+               return false;
+           }
        }
+      /* If we have a multi-dimensional array we do not consider
+         a non-innermost dimension as flex array if the whole
+        multi-dimensional array is at struct end.
+        Same for an array of aggregates with a trailing array
+        member.  */
+      else if (TREE_CODE (ref) == ARRAY_REF)
+       return false;
+      else if (TREE_CODE (ref) == ARRAY_RANGE_REF)
+       ;
+      /* If we view an underlying object as sth else then what we
+         gathered up to now is what we have to rely on.  */
+      else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
+       break;
+      else
+       gcc_unreachable ();
 
       ref = TREE_OPERAND (ref, 0);
     }
 
+  /* The array now is at struct end.  Treat flexible arrays as
+     always subject to extend, even into just padding constrained by
+     an underlying decl.  */
+  if (! TYPE_SIZE (atype))
+    return true;
+
+  tree size = NULL;
+
+  if (TREE_CODE (ref) == MEM_REF
+      && TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR)
+    {
+      size = TYPE_SIZE (TREE_TYPE (ref));
+      ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
+    }
+
   /* If the reference is based on a declared entity, the size of the array
      is constrained by its given domain.  (Do not trust commons PR/69368).  */
   if (DECL_P (ref)
+      /* Be sure the size of MEM_REF target match.  For example:
+
+          char buf[10];
+          struct foo *str = (struct foo *)&buf;
+
+          str->trailin_array[2] = 1;
+
+        is valid because BUF allocate enough space.  */
+
+      && (!size || (DECL_SIZE (ref) != NULL
+                   && operand_equal_p (DECL_SIZE (ref), size, 0)))
       && !(flag_unconstrained_commons
-          && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref)))
+          && VAR_P (ref) && DECL_COMMON (ref)))
     return false;
 
   return true;
@@ -13146,8 +12623,6 @@ verify_type_variant (const_tree t, tree tv)
      - aggregates may have new TYPE_FIELDS list that list variants of
        the main variant TYPE_FIELDS.
      - vector types may differ by TYPE_VECTOR_OPAQUE
-     - TYPE_METHODS is always NULL for vairant types and maintained for
-       main variant only.
    */
 
   /* Convenience macro for matching individual fields.  */
@@ -13171,7 +12646,6 @@ verify_type_variant (const_tree t, tree tv)
     verify_variant_match (TYPE_REF_CAN_ALIAS_ALL);
   /* FIXME: TYPE_SIZES_GIMPLIFIED may differs for Ada build.  */
   verify_variant_match (TYPE_UNSIGNED);
-  verify_variant_match (TYPE_ALIGN_OK);
   verify_variant_match (TYPE_PACKED);
   if (TREE_CODE (t) == REFERENCE_TYPE)
     verify_variant_match (TYPE_REF_IS_RVALUE);
@@ -13187,14 +12661,16 @@ verify_type_variant (const_tree t, tree tv)
 
   if (COMPLETE_TYPE_P (t))
     {
-      verify_variant_match (TYPE_SIZE);
       verify_variant_match (TYPE_MODE);
-      if (TYPE_SIZE_UNIT (t) != TYPE_SIZE_UNIT (tv)
-         /* FIXME: ideally we should compare pointer equality, but java FE
-            produce variants where size is INTEGER_CST of different type (int
-            wrt size_type) during libjava biuld.  */
-         && !operand_equal_p (TYPE_SIZE_UNIT (t), TYPE_SIZE_UNIT (tv), 0))
-       {
+      if (TREE_CODE (TYPE_SIZE (t)) != PLACEHOLDER_EXPR
+         && TREE_CODE (TYPE_SIZE (tv)) != PLACEHOLDER_EXPR)
+       verify_variant_match (TYPE_SIZE);
+      if (TREE_CODE (TYPE_SIZE_UNIT (t)) != PLACEHOLDER_EXPR
+         && TREE_CODE (TYPE_SIZE_UNIT (tv)) != PLACEHOLDER_EXPR
+         && TYPE_SIZE_UNIT (t) != TYPE_SIZE_UNIT (tv))
+       {
+         gcc_assert (!operand_equal_p (TYPE_SIZE_UNIT (t),
+                                       TYPE_SIZE_UNIT (tv), 0));
          error ("type variant has different TYPE_SIZE_UNIT");
          debug_tree (tv);
          error ("type variant's TYPE_SIZE_UNIT");
@@ -13247,12 +12723,6 @@ verify_type_variant (const_tree t, tree tv)
     }
   if (TREE_CODE (t) == METHOD_TYPE)
     verify_variant_match (TYPE_METHOD_BASETYPE);
-  if (RECORD_OR_UNION_TYPE_P (t) && TYPE_METHODS (t))
-    {
-      error ("type variant has TYPE_METHODS");
-      debug_tree (tv);
-      return false;
-    }
   if (TREE_CODE (t) == OFFSET_TYPE)
     verify_variant_match (TYPE_OFFSET_BASETYPE);
   if (TREE_CODE (t) == ARRAY_TYPE)
@@ -13348,7 +12818,7 @@ verify_type_variant (const_tree t, tree tv)
   if (type_with_alias_set_p (t)
       && !gimple_canonical_types_compatible_p (t, tv, false))
     {
-      error ("type is not compatible with its vairant");
+      error ("type is not compatible with its variant");
       debug_tree (tv);
       error ("type variant's TREE_TYPE");
       debug_tree (TREE_TYPE (tv));
@@ -13605,10 +13075,14 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
             f1 || f2;
             f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
          {
-           /* Skip non-fields.  */
-           while (f1 && TREE_CODE (f1) != FIELD_DECL)
+           /* Skip non-fields and zero-sized fields.  */
+           while (f1 && (TREE_CODE (f1) != FIELD_DECL
+                         || (DECL_SIZE (f1)
+                             && integer_zerop (DECL_SIZE (f1)))))
              f1 = TREE_CHAIN (f1);
-           while (f2 && TREE_CODE (f2) != FIELD_DECL)
+           while (f2 && (TREE_CODE (f2) != FIELD_DECL
+                         || (DECL_SIZE (f2)
+                             && integer_zerop (DECL_SIZE (f2)))))
              f2 = TREE_CHAIN (f2);
            if (!f1 || !f2)
              break;
@@ -13705,7 +13179,7 @@ verify_type (const_tree t)
    }
 
 
-  /* Check various uses of TYPE_MINVAL.  */
+  /* Check various uses of TYPE_MIN_VALUE_RAW.  */
   if (RECORD_OR_UNION_TYPE_P (t))
     {
       /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
@@ -13747,25 +13221,22 @@ verify_type (const_tree t)
                                     TREE_TYPE (TYPE_MIN_VALUE (t))
         but does not for C sizetypes in LTO.  */
     }
-  /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE.  */
-  else if (TYPE_MINVAL (t)
-          && ((TREE_CODE (t) != METHOD_TYPE && TREE_CODE (t) != FUNCTION_TYPE)
-              || in_lto_p))
-    {
-      error ("TYPE_MINVAL non-NULL");
-      debug_tree (TYPE_MINVAL (t));
-      error_found = true;
-    }
 
-  /* Check various uses of TYPE_MAXVAL.  */
+  /* Check various uses of TYPE_MAXVAL_RAW.  */
   if (RECORD_OR_UNION_TYPE_P (t))
     {
-      if (TYPE_METHODS (t) && TREE_CODE (TYPE_METHODS (t)) != FUNCTION_DECL
-         && TREE_CODE (TYPE_METHODS (t)) != TEMPLATE_DECL
-         && TYPE_METHODS (t) != error_mark_node)
+      if (!TYPE_BINFO (t))
+       ;
+      else if (TREE_CODE (TYPE_BINFO (t)) != TREE_BINFO)
+       {
+         error ("TYPE_BINFO is not TREE_BINFO");
+         debug_tree (TYPE_BINFO (t));
+         error_found = true;
+       }
+      else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t))
        {
-         error ("TYPE_METHODS is not FUNCTION_DECL, TEMPLATE_DECL nor error_mark_node");
-         debug_tree (TYPE_METHODS (t));
+         error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
+         debug_tree (TREE_TYPE (TYPE_BINFO (t)));
          error_found = true;
        }
     }
@@ -13809,34 +13280,14 @@ verify_type (const_tree t)
          error_found = true;
         } 
     }
-  else if (TYPE_MAXVAL (t))
+  else if (TYPE_MAX_VALUE_RAW (t))
     {
-      error ("TYPE_MAXVAL non-NULL");
-      debug_tree (TYPE_MAXVAL (t));
+      error ("TYPE_MAX_VALUE_RAW non-NULL");
+      debug_tree (TYPE_MAX_VALUE_RAW (t));
       error_found = true;
     }
 
-  /* Check various uses of TYPE_BINFO.  */
-  if (RECORD_OR_UNION_TYPE_P (t))
-    {
-      if (!TYPE_BINFO (t))
-       ;
-      else if (TREE_CODE (TYPE_BINFO (t)) != TREE_BINFO)
-       {
-         error ("TYPE_BINFO is not TREE_BINFO");
-         debug_tree (TYPE_BINFO (t));
-         error_found = true;
-       }
-      /* FIXME: Java builds invalid empty binfos that do not have
-         TREE_TYPE set.  */
-      else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t) && 0)
-       {
-         error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
-         debug_tree (TREE_TYPE (TYPE_BINFO (t)));
-         error_found = true;
-       }
-    }
-  else if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
+  if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
     {
       error ("TYPE_LANG_SLOT_1 (binfo) field is non-NULL");
       debug_tree (TYPE_LANG_SLOT_1 (t));
@@ -13900,12 +13351,14 @@ verify_type (const_tree t)
            ;
          else if (TREE_CODE (fld) == CONST_DECL)
            ;
-         else if (TREE_CODE (fld) == VAR_DECL)
+         else if (VAR_P (fld))
            ;
          else if (TREE_CODE (fld) == TEMPLATE_DECL)
            ;
          else if (TREE_CODE (fld) == USING_DECL)
            ;
+         else if (TREE_CODE (fld) == FUNCTION_DECL)
+           ;
          else
            {
              error ("Wrong tree in TYPE_FIELDS list");
@@ -13989,20 +13442,6 @@ verify_type (const_tree t)
       error ("TYPE_STRING_FLAG is set on wrong type code");
       error_found = true;
     }
-  else if (TYPE_STRING_FLAG (t))
-    {
-      const_tree b = t;
-      if (TREE_CODE (b) == ARRAY_TYPE)
-       b = TREE_TYPE (t);
-      /* Java builds arrays with TYPE_STRING_FLAG of promoted_char_type
-        that is 32bits.  */
-      if (TREE_CODE (b) != INTEGER_TYPE)
-       {
-         error ("TYPE_STRING_FLAG is set on type that does not look like "
-                "char nor array of chars");
-         error_found = true;
-       }
-    }
   
   /* ipa-devirt makes an assumption that TYPE_METHOD_BASETYPE is always
      TYPE_MAIN_VARIANT and it would be odd to add methods only to variatns
@@ -14022,6 +13461,88 @@ verify_type (const_tree t)
 }
 
 
+/* Return 1 if ARG interpreted as signed in its precision is known to be
+   always positive or 2 if ARG is known to be always negative, or 3 if
+   ARG may be positive or negative.  */
+
+int
+get_range_pos_neg (tree arg)
+{
+  if (arg == error_mark_node)
+    return 3;
+
+  int prec = TYPE_PRECISION (TREE_TYPE (arg));
+  int cnt = 0;
+  if (TREE_CODE (arg) == INTEGER_CST)
+    {
+      wide_int w = wi::sext (arg, prec);
+      if (wi::neg_p (w))
+       return 2;
+      else
+       return 1;
+    }
+  while (CONVERT_EXPR_P (arg)
+        && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
+        && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
+    {
+      arg = TREE_OPERAND (arg, 0);
+      /* Narrower value zero extended into wider type
+        will always result in positive values.  */
+      if (TYPE_UNSIGNED (TREE_TYPE (arg))
+         && TYPE_PRECISION (TREE_TYPE (arg)) < prec)
+       return 1;
+      prec = TYPE_PRECISION (TREE_TYPE (arg));
+      if (++cnt > 30)
+       return 3;
+    }
+
+  if (TREE_CODE (arg) != SSA_NAME)
+    return 3;
+  wide_int arg_min, arg_max;
+  while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+    {
+      gimple *g = SSA_NAME_DEF_STMT (arg);
+      if (is_gimple_assign (g)
+         && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
+       {
+         tree t = gimple_assign_rhs1 (g);
+         if (INTEGRAL_TYPE_P (TREE_TYPE (t))
+             && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
+           {
+             if (TYPE_UNSIGNED (TREE_TYPE (t))
+                 && TYPE_PRECISION (TREE_TYPE (t)) < prec)
+               return 1;
+             prec = TYPE_PRECISION (TREE_TYPE (t));
+             arg = t;
+             if (++cnt > 30)
+               return 3;
+             continue;
+           }
+       }
+      return 3;
+    }
+  if (TYPE_UNSIGNED (TREE_TYPE (arg)))
+    {
+      /* For unsigned values, the "positive" range comes
+        below the "negative" range.  */
+      if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
+       return 1;
+      if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
+       return 2;
+    }
+  else
+    {
+      if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
+       return 1;
+      if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
+       return 2;
+    }
+  return 3;
+}
+
+
+
+
 /* Return true if ARG is marked with the nonnull attribute in the
    current function signature.  */
 
@@ -14085,28 +13606,6 @@ nonnull_arg_p (const_tree arg)
   return false;
 }
 
-/* Given location LOC, strip away any packed range information
-   or ad-hoc information.  */
-
-location_t
-get_pure_location (location_t loc)
-{
-  if (IS_ADHOC_LOC (loc))
-    loc
-      = line_table->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
-
-  if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
-    return loc;
-
-  if (loc < RESERVED_LOCATION_COUNT)
-    return loc;
-
-  const line_map *map = linemap_lookup (line_table, loc);
-  const line_map_ordinary *ordmap = linemap_check_ordinary (map);
-
-  return loc & ~((1 << ordmap->m_range_bits) - 1);
-}
-
 /* Combine LOC and BLOCK to a combined adhoc loc, retaining any range
    information.  */
 
@@ -14142,20 +13641,6 @@ set_source_range (tree expr, source_range src_range)
   return adhoc;
 }
 
-location_t
-make_location (location_t caret, location_t start, location_t finish)
-{
-  location_t pure_loc = get_pure_location (caret);
-  source_range src_range;
-  src_range.m_start = start;
-  src_range.m_finish = finish;
-  location_t combined_loc = COMBINE_LOCATION_DATA (line_table,
-                                                  pure_loc,
-                                                  src_range,
-                                                  NULL);
-  return combined_loc;
-}
-
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
@@ -14170,4 +13655,129 @@ combined_fn_name (combined_fn fn)
     return internal_fn_name (as_internal_fn (fn));
 }
 
+/* Return a bitmap with a bit set corresponding to each argument in
+   a function call type FNTYPE declared with attribute nonnull,
+   or null if none of the function's argument are nonnull.  The caller
+   must free the bitmap.  */
+
+bitmap
+get_nonnull_args (const_tree fntype)
+{
+  if (fntype == NULL_TREE)
+    return NULL;
+
+  tree attrs = TYPE_ATTRIBUTES (fntype);
+  if (!attrs)
+    return NULL;
+
+  bitmap argmap = NULL;
+
+  /* A function declaration can specify multiple attribute nonnull,
+     each with zero or more arguments.  The loop below creates a bitmap
+     representing a union of all the arguments.  An empty (but non-null)
+     bitmap means that all arguments have been declaraed nonnull.  */
+  for ( ; attrs; attrs = TREE_CHAIN (attrs))
+    {
+      attrs = lookup_attribute ("nonnull", attrs);
+      if (!attrs)
+       break;
+
+      if (!argmap)
+       argmap = BITMAP_ALLOC (NULL);
+
+      if (!TREE_VALUE (attrs))
+       {
+         /* Clear the bitmap in case a previous attribute nonnull
+            set it and this one overrides it for all arguments.  */
+         bitmap_clear (argmap);
+         return argmap;
+       }
+
+      /* Iterate over the indices of the format arguments declared nonnull
+        and set a bit for each.  */
+      for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
+       {
+         unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
+         bitmap_set_bit (argmap, val);
+       }
+    }
+
+  return argmap;
+}
+
+/* List of pointer types used to declare builtins before we have seen their
+   real declaration.
+
+   Keep the size up to date in tree.h !  */
+const builtin_structptr_type builtin_structptr_types[6] = 
+{
+  { fileptr_type_node, ptr_type_node, "FILE" },
+  { const_tm_ptr_type_node, const_ptr_type_node, "tm" },
+  { fenv_t_ptr_type_node, ptr_type_node, "fenv_t" },
+  { const_fenv_t_ptr_type_node, const_ptr_type_node, "fenv_t" },
+  { fexcept_t_ptr_type_node, ptr_type_node, "fexcept_t" },
+  { const_fexcept_t_ptr_type_node, const_ptr_type_node, "fexcept_t" }
+};
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for tree.  */
+
+/* Verify that integer constants are sane.  */
+
+static void
+test_integer_constants ()
+{
+  ASSERT_TRUE (integer_type_node != NULL);
+  ASSERT_TRUE (build_int_cst (integer_type_node, 0) != NULL);
+
+  tree type = integer_type_node;
+
+  tree zero = build_zero_cst (type);
+  ASSERT_EQ (INTEGER_CST, TREE_CODE (zero));
+  ASSERT_EQ (type, TREE_TYPE (zero));
+
+  tree one = build_int_cst (type, 1);
+  ASSERT_EQ (INTEGER_CST, TREE_CODE (one));
+  ASSERT_EQ (type, TREE_TYPE (zero));
+}
+
+/* Verify identifiers.  */
+
+static void
+test_identifiers ()
+{
+  tree identifier = get_identifier ("foo");
+  ASSERT_EQ (3, IDENTIFIER_LENGTH (identifier));
+  ASSERT_STREQ ("foo", IDENTIFIER_POINTER (identifier));
+}
+
+/* Verify LABEL_DECL.  */
+
+static void
+test_labels ()
+{
+  tree identifier = get_identifier ("err");
+  tree label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
+                               identifier, void_type_node);
+  ASSERT_EQ (-1, LABEL_DECL_UID (label_decl));
+  ASSERT_FALSE (FORCED_LABEL (label_decl));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+tree_c_tests ()
+{
+  test_integer_constants ();
+  test_identifiers ();
+  test_labels ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
+
 #include "gt-tree.h"