]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/c-family/c-common.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / c-family / c-common.c
index bb18c39cd6ba1ba8c62ba14f2429525939b0f244..4eea22711ea2ea9be345f2aa89347cbbeeb2441b 100644 (file)
@@ -1,7 +1,5 @@
 /* Subroutines shared by all languages that are variants of C.
-   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1992-2013 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -25,6 +23,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "intl.h"
 #include "tree.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "varasm.h"
+#include "trans-mem.h"
 #include "flags.h"
 #include "c-pragma.h"
 #include "ggc.h"
@@ -41,10 +46,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "tree-iterator.h"
 #include "hashtab.h"
-#include "tree-mudflap.h"
 #include "opts.h"
 #include "cgraph.h"
 #include "target-def.h"
+#include "gimple.h"
+#include "gimplify.h"
+#include "wide-int-print.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -193,15 +200,6 @@ const char *pch_file;
    user's namespace.  */
 int flag_iso;
 
-/* Warn about #pragma directives that are not recognized.  */
-
-int warn_unknown_pragmas; /* Tri state variable.  */
-
-/* Warn about format/argument anomalies in calls to formatted I/O functions
-   (*printf, *scanf, strftime, strfmon, etc.).  */
-
-int warn_format;
-
 /* C/ObjC language option variables.  */
 
 
@@ -318,6 +316,12 @@ static tree handle_common_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
 static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
+static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
+                                                 int, bool *);
+static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
+                                                        int, bool *);
+static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
+                                                   bool *);
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
@@ -375,6 +379,14 @@ static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
 static tree ignore_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
+                                              bool *);
+static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
+                                                bool *);
+static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *);
+static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
 
 static void check_function_nonnull (tree, int, tree *);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -407,8 +419,11 @@ const struct c_common_resword c_common_reswords[] =
 {
   { "_Alignas",                RID_ALIGNAS,   D_CONLY },
   { "_Alignof",                RID_ALIGNOF,   D_CONLY },
+  { "_Atomic",         RID_ATOMIC,    D_CONLY },
   { "_Bool",           RID_BOOL,      D_CONLY },
   { "_Complex",                RID_COMPLEX,    0 },
+  { "_Cilk_spawn",      RID_CILK_SPAWN, 0 },
+  { "_Cilk_sync",       RID_CILK_SYNC,  0 },
   { "_Imaginary",      RID_IMAGINARY, D_CONLY },
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
@@ -418,6 +433,8 @@ const struct c_common_resword c_common_reswords[] =
   { "_Sat",             RID_SAT,       D_CONLY | D_EXT },
   { "_Static_assert",   RID_STATIC_ASSERT, D_CONLY },
   { "_Noreturn",        RID_NORETURN,  D_CONLY },
+  { "_Generic",         RID_GENERIC,   D_CONLY },
+  { "_Thread_local",    RID_THREAD,    D_CONLY },
   { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
   { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
   { "__alignof",       RID_ALIGNOF,    0 },
@@ -426,6 +443,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__asm__",         RID_ASM,        0 },
   { "__attribute",     RID_ATTRIBUTE,  0 },
   { "__attribute__",   RID_ATTRIBUTE,  0 },
+  { "__auto_type",     RID_AUTO_TYPE,  D_CONLY },
   { "__bases",          RID_BASES, D_CXXONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
@@ -720,6 +738,16 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_cold_attribute, false },
   { "hot",                    0, 0, true,  false, false,
                              handle_hot_attribute, false },
+  { "no_address_safety_analysis",
+                             0, 0, true, false, false,
+                             handle_no_address_safety_analysis_attribute,
+                             false },
+  { "no_sanitize_address",    0, 0, true, false, false,
+                             handle_no_sanitize_address_attribute,
+                             false },
+  { "no_sanitize_undefined",  0, 0, true, false, false,
+                             handle_no_sanitize_undefined_attribute,
+                             false },
   { "warning",               1, 1, true,  false, false,
                              handle_error_attribute, false },
   { "error",                 1, 1, true,  false, false,
@@ -738,6 +766,18 @@ const struct attribute_spec c_common_attribute_table[] =
      The name contains space to prevent its usage in source code.  */
   { "fn spec",               1, 1, false, true, true,
                              handle_fnspec_attribute, false },
+  { "warn_unused",            0, 0, false, false, false,
+                             handle_warn_unused_attribute, false },
+  { "returns_nonnull",        0, 0, false, true, true,
+                             handle_returns_nonnull_attribute, false },
+  { "omp declare simd",       0, -1, true,  false, false,
+                             handle_omp_declare_simd_attribute, false },
+  { "omp declare target",     0, 0, true, false, false,
+                             handle_omp_declare_target_attribute, false },
+  { "bnd_variable_size",      0, 0, true,  false, false,
+                             handle_bnd_variable_size_attribute, false },
+  { "bnd_legacy",             0, 0, true, false, false,
+                             handle_bnd_legacy, false },
   { NULL,                     0, 0, false, false, false, NULL, false }
 };
 
@@ -1272,6 +1312,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
          && !TREE_OVERFLOW_P (op0)
          && !TREE_OVERFLOW_P (op1))
        overflow_warning (EXPR_LOCATION (expr), ret);
+      if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+         && TREE_CODE (orig_op1) != INTEGER_CST
+         && TREE_CODE (op1) == INTEGER_CST
+         && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
+             || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
+         && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
+         && c_inhibit_evaluation_warnings == 0)
+       {
+         if (tree_int_cst_sgn (op1) < 0)
+           warning_at (loc, 0, (code == LSHIFT_EXPR
+                                ? G_("left shift count is negative")
+                                : G_("right shift count is negative")));
+         else if (compare_tree_int (op1,
+                                    TYPE_PRECISION (TREE_TYPE (orig_op0)))
+                  >= 0)
+           warning_at (loc, 0, (code == LSHIFT_EXPR
+                                ? G_("left shift count >= width of type")
+                                : G_("right shift count >= width of type")));
+       }
       goto out;
 
     case INDIRECT_REF:
@@ -1847,52 +1906,105 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
    sizeof as last operand of certain builtins.  */
 
 void
-sizeof_pointer_memaccess_warning (location_t loc, tree callee,
-                                 VEC(tree, gc) *params, tree sizeof_arg,
+sizeof_pointer_memaccess_warning (location_t *sizeof_arg_loc, tree callee,
+                                 vec<tree, va_gc> *params, tree *sizeof_arg,
                                  bool (*comp_types) (tree, tree))
 {
   tree type, dest = NULL_TREE, src = NULL_TREE, tem;
-  bool strop = false;
+  bool strop = false, cmp = false;
+  unsigned int idx = ~0;
+  location_t loc;
 
   if (TREE_CODE (callee) != FUNCTION_DECL
       || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
-      || sizeof_arg == error_mark_node
-      || VEC_length (tree, params) <= 1)
-    return;
-
-  type = TYPE_P (sizeof_arg) ? sizeof_arg : TREE_TYPE (sizeof_arg);
-  if (!POINTER_TYPE_P (type))
+      || vec_safe_length (params) <= 1)
     return;
 
   switch (DECL_FUNCTION_CODE (callee))
     {
     case BUILT_IN_STRNCMP:
     case BUILT_IN_STRNCASECMP:
+      cmp = true;
+      /* FALLTHRU */
     case BUILT_IN_STRNCPY:
+    case BUILT_IN_STRNCPY_CHK:
     case BUILT_IN_STRNCAT:
+    case BUILT_IN_STRNCAT_CHK:
+    case BUILT_IN_STPNCPY:
+    case BUILT_IN_STPNCPY_CHK:
       strop = true;
       /* FALLTHRU */
     case BUILT_IN_MEMCPY:
+    case BUILT_IN_MEMCPY_CHK:
     case BUILT_IN_MEMMOVE:
+    case BUILT_IN_MEMMOVE_CHK:
+      if (params->length () < 3)
+       return;
+      src = (*params)[1];
+      dest = (*params)[0];
+      idx = 2;
+      break;
+    case BUILT_IN_BCOPY:
+      if (params->length () < 3)
+       return;
+      src = (*params)[0];
+      dest = (*params)[1];
+      idx = 2;
+      break;
     case BUILT_IN_MEMCMP:
-      if (VEC_length (tree, params) < 3)
+    case BUILT_IN_BCMP:
+      if (params->length () < 3)
        return;
-      src = VEC_index (tree, params, 1);
-      dest = VEC_index (tree, params, 0);
+      src = (*params)[1];
+      dest = (*params)[0];
+      idx = 2;
+      cmp = true;
       break;
     case BUILT_IN_MEMSET:
-      if (VEC_length (tree, params) < 3)
+    case BUILT_IN_MEMSET_CHK:
+      if (params->length () < 3)
        return;
-      dest = VEC_index (tree, params, 0);
+      dest = (*params)[0];
+      idx = 2;
+      break;
+    case BUILT_IN_BZERO:
+      dest = (*params)[0];
+      idx = 1;
       break;
     case BUILT_IN_STRNDUP:
-      src = VEC_index (tree, params, 0);
+      src = (*params)[0];
+      strop = true;
+      idx = 1;
+      break;
+    case BUILT_IN_MEMCHR:
+      if (params->length () < 3)
+       return;
+      src = (*params)[0];
+      idx = 2;
+      break;
+    case BUILT_IN_SNPRINTF:
+    case BUILT_IN_SNPRINTF_CHK:
+    case BUILT_IN_VSNPRINTF:
+    case BUILT_IN_VSNPRINTF_CHK:
+      dest = (*params)[0];
+      idx = 1;
       strop = true;
       break;
     default:
       break;
     }
 
+  if (idx >= 3)
+    return;
+
+  if (sizeof_arg[idx] == NULL || sizeof_arg[idx] == error_mark_node)
+    return;
+
+  type = TYPE_P (sizeof_arg[idx])
+        ? sizeof_arg[idx] : TREE_TYPE (sizeof_arg[idx]);
+  if (!POINTER_TYPE_P (type))
+    return;
+
   if (dest
       && (tem = tree_strip_nop_conversions (dest))
       && POINTER_TYPE_P (TREE_TYPE (tem))
@@ -1905,13 +2017,15 @@ sizeof_pointer_memaccess_warning (location_t loc, tree callee,
       && comp_types (TREE_TYPE (TREE_TYPE (tem)), type))
     return;
 
-  if (dest)
+  loc = sizeof_arg_loc[idx];
+
+  if (dest && !cmp)
     {
-      if (!TYPE_P (sizeof_arg)
-         && operand_equal_p (dest, sizeof_arg, 0)
+      if (!TYPE_P (sizeof_arg[idx])
+         && operand_equal_p (dest, sizeof_arg[idx], 0)
          && comp_types (TREE_TYPE (dest), type))
        {
-         if (TREE_CODE (sizeof_arg) == ADDR_EXPR && !strop)
+         if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
            warning_at (loc, OPT_Wsizeof_pointer_memaccess,
                        "argument to %<sizeof%> in %qD call is the same "
                        "expression as the destination; did you mean to "
@@ -1945,13 +2059,13 @@ sizeof_pointer_memaccess_warning (location_t loc, tree callee,
        }
     }
 
-  if (src)
+  if (src && !cmp)
     {
-      if (!TYPE_P (sizeof_arg)
-         && operand_equal_p (src, sizeof_arg, 0)
+      if (!TYPE_P (sizeof_arg[idx])
+         && operand_equal_p (src, sizeof_arg[idx], 0)
          && comp_types (TREE_TYPE (src), type))
        {
-         if (TREE_CODE (sizeof_arg) == ADDR_EXPR && !strop)
+         if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
            warning_at (loc, OPT_Wsizeof_pointer_memaccess,
                        "argument to %<sizeof%> in %qD call is the same "
                        "expression as the source; did you mean to "
@@ -1984,6 +2098,87 @@ sizeof_pointer_memaccess_warning (location_t loc, tree callee,
          return;
        }
     }
+
+  if (dest)
+    {
+      if (!TYPE_P (sizeof_arg[idx])
+         && operand_equal_p (dest, sizeof_arg[idx], 0)
+         && comp_types (TREE_TYPE (dest), type))
+       {
+         if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
+           warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                       "argument to %<sizeof%> in %qD call is the same "
+                       "expression as the first source; did you mean to "
+                       "remove the addressof?", callee);
+         else if ((TYPE_PRECISION (TREE_TYPE (type))
+                   == TYPE_PRECISION (char_type_node))
+                  || strop)
+           warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                       "argument to %<sizeof%> in %qD call is the same "
+                       "expression as the first source; did you mean to "
+                       "provide an explicit length?", callee);
+         else
+           warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                       "argument to %<sizeof%> in %qD call is the same "
+                       "expression as the first source; did you mean to "
+                       "dereference it?", callee);
+         return;
+       }
+
+      if (POINTER_TYPE_P (TREE_TYPE (dest))
+         && !strop
+         && comp_types (TREE_TYPE (dest), type)
+         && !VOID_TYPE_P (TREE_TYPE (type)))
+       {
+         warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                     "argument to %<sizeof%> in %qD call is the same "
+                     "pointer type %qT as the first source; expected %qT "
+                     "or an explicit length", callee, TREE_TYPE (dest),
+                     TREE_TYPE (TREE_TYPE (dest)));
+         return;
+       }
+    }
+
+  if (src)
+    {
+      if (!TYPE_P (sizeof_arg[idx])
+         && operand_equal_p (src, sizeof_arg[idx], 0)
+         && comp_types (TREE_TYPE (src), type))
+       {
+         if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
+           warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                       "argument to %<sizeof%> in %qD call is the same "
+                       "expression as the second source; did you mean to "
+                       "remove the addressof?", callee);
+         else if ((TYPE_PRECISION (TREE_TYPE (type))
+                   == TYPE_PRECISION (char_type_node))
+                  || strop)
+           warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                       "argument to %<sizeof%> in %qD call is the same "
+                       "expression as the second source; did you mean to "
+                       "provide an explicit length?", callee);
+         else
+           warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                       "argument to %<sizeof%> in %qD call is the same "
+                       "expression as the second source; did you mean to "
+                       "dereference it?", callee);
+         return;
+       }
+
+      if (POINTER_TYPE_P (TREE_TYPE (src))
+         && !strop
+         && comp_types (TREE_TYPE (src), type)
+         && !VOID_TYPE_P (TREE_TYPE (type)))
+       {
+         warning_at (loc, OPT_Wsizeof_pointer_memaccess,
+                     "argument to %<sizeof%> in %qD call is the same "
+                     "pointer type %qT as the second source; expected %qT "
+                     "or an explicit length", callee, TREE_TYPE (src),
+                     TREE_TYPE (TREE_TYPE (src)));
+         return;
+       }
+    }
+
 }
 
 /* Warn for unlikely, improbable, or stupid DECL declarations
@@ -2040,6 +2235,14 @@ check_main_parameter_types (tree decl)
             "%q+D takes only zero or two arguments", decl);
 }
 
+/* vector_targets_convertible_p is used for vector pointer types.  The
+   callers perform various checks that the qualifiers are satisfactory,
+   while OTOH vector_targets_convertible_p ignores the number of elements
+   in the vectors.  That's fine with vector pointers as we can consider,
+   say, a vector of 8 elements as two consecutive vectors of 4 elements,
+   and that does not require and conversion of the pointer values.
+   In contrast, vector_types_convertible_p and
+   vector_types_compatible_elements_p are used for vector value types.  */
 /* True if pointers to distinct types T1 and T2 can be converted to
    each other without an explicit cast.  Only returns true for opaque
    vector types.  */
@@ -2054,6 +2257,17 @@ vector_targets_convertible_p (const_tree t1, const_tree t2)
   return false;
 }
 
+/* vector_types_convertible_p is used for vector value types.
+   It could in principle call vector_targets_convertible_p as a subroutine,
+   but then the check for vector type would be duplicated with its callers,
+   and also the purpose of vector_targets_convertible_p would become
+   muddled.
+   Where vector_types_convertible_p returns true, a conversion might still be
+   needed to make the types match.
+   In contrast, vector_targets_convertible_p is used for vector pointer
+   values, and vector_types_compatible_elements_p is used specifically
+   in the context for binary operators, as a check if use is possible without
+   conversion.  */
 /* True if vector types T1 and T2 can be converted to each other
    without an explicit cast.  If EMIT_LAX_NOTE is true, and T1 and T2
    can only be converted with -flax-vector-conversions yet that is not
@@ -2072,7 +2286,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
   convertible_lax =
     (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
      && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE ||
-        TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+        TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2))
      && (INTEGRAL_TYPE_P (TREE_TYPE (t1))
         == INTEGRAL_TYPE_P (TREE_TYPE (t2))));
 
@@ -2105,7 +2319,8 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
    an implementation accident and this semantics is not guaranteed to
    the user.  */
 tree
-c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
+c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask,
+                      bool complain)
 {
   tree ret;
   bool wrap = true;
@@ -2125,22 +2340,25 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
   if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE
       || TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE)
     {
-      error_at (loc, "__builtin_shuffle last argument must "
-                    "be an integer vector");
+      if (complain)
+       error_at (loc, "__builtin_shuffle last argument must "
+                      "be an integer vector");
       return error_mark_node;
     }
 
   if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE
       || TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE)
     {
-      error_at (loc, "__builtin_shuffle arguments must be vectors");
+      if (complain)
+       error_at (loc, "__builtin_shuffle arguments must be vectors");
       return error_mark_node;
     }
 
   if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1)))
     {
-      error_at (loc, "__builtin_shuffle argument vectors must be of "
-                    "the same type");
+      if (complain)
+       error_at (loc, "__builtin_shuffle argument vectors must be of "
+                      "the same type");
       return error_mark_node;
     }
 
@@ -2149,17 +2367,19 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
       && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1))
         != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
     {
-      error_at (loc, "__builtin_shuffle number of elements of the "
-                    "argument vector(s) and the mask vector should "
-                    "be the same");
+      if (complain)
+       error_at (loc, "__builtin_shuffle number of elements of the "
+                      "argument vector(s) and the mask vector should "
+                      "be the same");
       return error_mark_node;
     }
 
   if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
       != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
     {
-      error_at (loc, "__builtin_shuffle argument vector(s) inner type "
-                    "must have the same size as inner type of the mask");
+      if (complain)
+       error_at (loc, "__builtin_shuffle argument vector(s) inner type "
+                      "must have the same size as inner type of the mask");
       return error_mark_node;
     }
 
@@ -2180,6 +2400,8 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
       mask = c_fully_fold (mask, false, &maybe_const);
       wrap &= maybe_const;
     }
+  else if (two_arguments)
+    v1 = v0 = save_expr (v0);
 
   ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask);
 
@@ -2316,7 +2538,7 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
 }
 
 /* Checks if expression EXPR of real/integer type cannot be converted 
-   to the real/integer type TYPE. Function returns true when:
+   to the real/integer type TYPE. Function returns non-zero when:
        * EXPR is a constant which cannot be exactly converted to TYPE 
        * EXPR is not a constant and size of EXPR's type > than size of TYPE, 
          for EXPR type and TYPE being both integers or both real.
@@ -2324,12 +2546,12 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
        * EXPR is not a constant of integer type which cannot be 
          exactly converted to real type.  
    Function allows conversions between types of different signedness and
-   does not return true in that case.  Function can produce signedness
-   warnings if PRODUCE_WARNS is true.  */
-bool
+   can return SAFE_CONVERSION (zero) in that case.  Function can produce
+   signedness warnings if PRODUCE_WARNS is true.  */
+enum conversion_safety
 unsafe_conversion_p (tree type, tree expr, bool produce_warns)
 {
-  bool give_warning = false;
+  enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
   tree expr_type = TREE_TYPE (expr);
   location_t loc = EXPR_LOC_OR_HERE (expr);
 
@@ -2341,7 +2563,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
          && TREE_CODE (type) == INTEGER_TYPE)
        {
          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
-           give_warning = true;
+           give_warning = UNSAFE_REAL;
        }
       /* Warn for an integer constant that does not fit into integer type.  */
       else if (TREE_CODE (expr_type) == INTEGER_TYPE
@@ -2362,7 +2584,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
                            " constant value to negative integer");
            }
          else
-           give_warning = true;
+           give_warning = UNSAFE_OTHER;
        }
       else if (TREE_CODE (type) == REAL_TYPE)
        {
@@ -2371,7 +2593,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
            {
              REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
              if (!exact_real_truncate (TYPE_MODE (type), &a))
-               give_warning = true;
+               give_warning = UNSAFE_REAL;
            }
          /* Warn for a real constant that does not fit into a smaller
             real type.  */
@@ -2380,7 +2602,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
            {
              REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
              if (!exact_real_truncate (TYPE_MODE (type), &a))
-               give_warning = true;
+               give_warning = UNSAFE_REAL;
            }
        }
     }
@@ -2389,7 +2611,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
       /* Warn for real types converted to integer types.  */
       if (TREE_CODE (expr_type) == REAL_TYPE
          && TREE_CODE (type) == INTEGER_TYPE)
-       give_warning = true;
+       give_warning = UNSAFE_REAL;
 
       else if (TREE_CODE (expr_type) == INTEGER_TYPE
               && TREE_CODE (type) == INTEGER_TYPE)
@@ -2427,7 +2649,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
                          && int_fits_type_p (op1, c_common_signed_type (type))
                          && int_fits_type_p (op1,
                                              c_common_unsigned_type (type))))
-                   return false;
+                   return SAFE_CONVERSION;
                  /* If constant is unsigned and fits in the target
                     type, then the result will also fit.  */
                  else if ((TREE_CODE (op0) == INTEGER_CST
@@ -2436,12 +2658,12 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
                           || (TREE_CODE (op1) == INTEGER_CST
                               && unsigned1
                               && int_fits_type_p (op1, type)))
-                   return false;
+                   return SAFE_CONVERSION;
                }
            }
          /* Warn for integer types converted to smaller integer types.  */
          if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
-           give_warning = true;
+           give_warning = UNSAFE_OTHER;
 
          /* When they are the same width but different signedness,
             then the value may change.  */
@@ -2477,14 +2699,14 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
 
          if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
              || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
-           give_warning = true;
+           give_warning = UNSAFE_OTHER;
        }
 
       /* Warn for real types converted to smaller real types.  */
       else if (TREE_CODE (expr_type) == REAL_TYPE
               && TREE_CODE (type) == REAL_TYPE
               && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
-       give_warning = true;
+       give_warning = UNSAFE_REAL;
     }
 
   return give_warning;
@@ -2498,8 +2720,9 @@ conversion_warning (tree type, tree expr)
 {
   tree expr_type = TREE_TYPE (expr);
   location_t loc = EXPR_LOC_OR_HERE (expr);
+  enum conversion_safety conversion_kind;
 
-  if (!warn_conversion && !warn_sign_conversion)
+  if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion)
     return;
 
   switch (TREE_CODE (expr))
@@ -2526,7 +2749,12 @@ conversion_warning (tree type, tree expr)
 
     case REAL_CST:
     case INTEGER_CST:
-      if (unsafe_conversion_p (type, expr, true))
+      conversion_kind = unsafe_conversion_p (type, expr, true);
+      if (conversion_kind == UNSAFE_REAL)
+       warning_at (loc, OPT_Wfloat_conversion,
+                   "conversion to %qT alters %qT constant value",
+                   type, expr_type);
+      else if (conversion_kind)
        warning_at (loc, OPT_Wconversion,
                    "conversion to %qT alters %qT constant value",
                    type, expr_type);
@@ -2534,26 +2762,23 @@ conversion_warning (tree type, tree expr)
 
     case COND_EXPR:
       {
-       /* In case of COND_EXPR, if both operands are constants or
-          COND_EXPR, then we do not care about the type of COND_EXPR,
-          only about the conversion of each operand.  */
-       tree op1 = TREE_OPERAND (expr, 1);
-       tree op2 = TREE_OPERAND (expr, 2);
-
-       if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
-            || TREE_CODE (op1) == COND_EXPR)
-           && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
-               || TREE_CODE (op2) == COND_EXPR))
-         {
-           conversion_warning (type, op1);
-           conversion_warning (type, op2);
-           return;
-         }
-       /* Fall through.  */
+        /* In case of COND_EXPR, we do not care about the type of
+           COND_EXPR, only about the conversion of each operand.  */
+        tree op1 = TREE_OPERAND (expr, 1);
+        tree op2 = TREE_OPERAND (expr, 2);
+        
+        conversion_warning (type, op1);
+        conversion_warning (type, op2);
+        return;
       }
 
     default: /* 'expr' is not a constant.  */
-      if (unsafe_conversion_p (type, expr, true))
+      conversion_kind = unsafe_conversion_p (type, expr, true);
+      if (conversion_kind == UNSAFE_REAL)
+       warning_at (loc, OPT_Wfloat_conversion,
+                   "conversion to %qT from %qT may alter its value",
+                   type, expr_type);
+      else if (conversion_kind)
        warning_at (loc, OPT_Wconversion,
                    "conversion to %qT from %qT may alter its value",
                    type, expr_type);
@@ -2885,6 +3110,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
   switch (code)
     {
     case CONSTRUCTOR:
+    case SIZEOF_EXPR:
       return;
 
     case COMPOUND_EXPR:
@@ -3892,9 +4118,12 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
        {
          /* Convert primop1 to target type, but do not introduce
             additional overflow.  We know primop1 is an int_cst.  */
-         primop1 = force_fit_type_double (*restype_ptr,
-                                          tree_to_double_int (primop1),
-                                          0, TREE_OVERFLOW (primop1));
+         primop1 = force_fit_type (*restype_ptr,
+                                   wide_int::from
+                                     (primop1,
+                                      TYPE_PRECISION (*restype_ptr),
+                                      TYPE_SIGN (TREE_TYPE (primop1))),
+                                   0, TREE_OVERFLOW (primop1));
        }
       if (type != *restype_ptr)
        {
@@ -3902,20 +4131,10 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
          maxval = convert (*restype_ptr, maxval);
        }
 
-      if (unsignedp && unsignedp0)
-       {
-         min_gt = INT_CST_LT_UNSIGNED (primop1, minval);
-         max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);
-         min_lt = INT_CST_LT_UNSIGNED (minval, primop1);
-         max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);
-       }
-      else
-       {
-         min_gt = INT_CST_LT (primop1, minval);
-         max_gt = INT_CST_LT (primop1, maxval);
-         min_lt = INT_CST_LT (minval, primop1);
-         max_lt = INT_CST_LT (maxval, primop1);
-       }
+      min_gt = INT_CST_LT (primop1, minval);
+      max_gt = INT_CST_LT (primop1, maxval);
+      min_lt = INT_CST_LT (minval, primop1);
+      max_lt = INT_CST_LT (maxval, primop1);
 
       val = 0;
       /* This used to be a switch, but Genix compiler can't handle that.  */
@@ -4124,7 +4343,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
 
 tree
 pointer_int_sum (location_t loc, enum tree_code resultcode,
-                tree ptrop, tree intop)
+                tree ptrop, tree intop, bool complain)
 {
   tree size_exp, ret;
 
@@ -4133,20 +4352,20 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
-      pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-              "pointer of type %<void *%> used in arithmetic");
+      if (complain && warn_pointer_arith)
+       pedwarn (loc, OPT_Wpointer_arith,
+                "pointer of type %<void *%> used in arithmetic");
+      else if (!complain)
+       return error_mark_node;
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
     {
-      pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-              "pointer to a function used in arithmetic");
-      size_exp = integer_one_node;
-    }
-  else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
-    {
-      pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-              "pointer to member function used in arithmetic");
+      if (complain && warn_pointer_arith)
+       pedwarn (loc, OPT_Wpointer_arith,
+                "pointer to a function used in arithmetic");
+      else if (!complain)
+       return error_mark_node;
       size_exp = integer_one_node;
     }
   else
@@ -4206,8 +4425,7 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
                              convert (TREE_TYPE (intop), size_exp), 1);
     intop = convert (sizetype, t);
     if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
-      intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
-                                 TREE_INT_CST_HIGH (intop));
+      intop = wide_int_to_tree (TREE_TYPE (intop), intop);
   }
 
   /* Create the sum or difference.  */
@@ -4723,8 +4941,8 @@ c_sizeof_or_alignof_type (location_t loc,
     {
       if (is_sizeof)
        {
-         if (complain && (pedantic || warn_pointer_arith))
-           pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+         if (complain && warn_pointer_arith)
+           pedwarn (loc, OPT_Wpointer_arith,
                     "invalid application of %<sizeof%> to a function type");
           else if (!complain)
             return error_mark_node;
@@ -4747,8 +4965,8 @@ c_sizeof_or_alignof_type (location_t loc,
   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
     {
       if (type_code == VOID_TYPE
-         && complain && (pedantic || warn_pointer_arith))
-       pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+         && complain && warn_pointer_arith)
+       pedwarn (loc, OPT_Wpointer_arith,
                 "invalid application of %qs to a void type", op_name);
       else if (!complain)
         return error_mark_node;
@@ -4870,6 +5088,7 @@ enum c_builtin_type
 #define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
 #define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
 #define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) NAME,
 #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
 #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
 #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
@@ -4888,6 +5107,7 @@ enum c_builtin_type
 #undef DEF_FUNCTION_TYPE_5
 #undef DEF_FUNCTION_TYPE_6
 #undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
 #undef DEF_FUNCTION_TYPE_VAR_0
 #undef DEF_FUNCTION_TYPE_VAR_1
 #undef DEF_FUNCTION_TYPE_VAR_2
@@ -4970,6 +5190,10 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
 #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
                            ARG6, ARG7)                                 \
   def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+                           ARG6, ARG7, ARG8)                           \
+  def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
+              ARG7, ARG8);
 #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
   def_fn_type (ENUM, RETURN, 1, 0);
 #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
@@ -5020,8 +5244,8 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
 
   build_common_builtin_nodes ();
 
-  if (flag_mudflap)
-    mudflap_init ();
+  if (flag_enable_cilkplus)
+    cilk_init_builtins ();
 }
 
 /* Like get_identifier, but avoid warnings about null arguments when
@@ -5259,7 +5483,7 @@ c_common_nodes_and_builtins (void)
   }
 
   /* This node must not be shared.  */
-  void_zero_node = make_node (INTEGER_CST);
+  void_zero_node = make_int_cst (1, 1);
   TREE_TYPE (void_zero_node) = void_type_node;
 
   void_list_node = build_void_list_node ();
@@ -5312,7 +5536,7 @@ c_common_nodes_and_builtins (void)
     {
       char16_type_node = make_unsigned_type (char16_type_size);
 
-      if (cxx_dialect >= cxx0x)
+      if (cxx_dialect >= cxx11)
        record_builtin_type (RID_CHAR16, "char16_t", char16_type_node);
     }
 
@@ -5328,7 +5552,7 @@ c_common_nodes_and_builtins (void)
     {
       char32_type_node = make_unsigned_type (char32_type_size);
 
-      if (cxx_dialect >= cxx0x)
+      if (cxx_dialect >= cxx11)
        record_builtin_type (RID_CHAR32, "char32_t", char32_type_node);
     }
 
@@ -5470,7 +5694,7 @@ c_common_nodes_and_builtins (void)
 
   /* Create the built-in __null node.  It is important that this is
      not shared.  */
-  null_node = make_node (INTEGER_CST);
+  null_node = make_int_cst (1, 1);
   TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
 
   /* Since builtin_types isn't gc'ed, don't export these nodes.  */
@@ -5848,22 +6072,14 @@ c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
 static void
 match_case_to_enum_1 (tree key, tree type, tree label)
 {
-  char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
-
-  /* ??? Not working too hard to print the double-word value.
-     Should perhaps be done with %lwd in the diagnostic routines?  */
-  if (TREE_INT_CST_HIGH (key) == 0)
-    snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
-             TREE_INT_CST_LOW (key));
-  else if (!TYPE_UNSIGNED (type)
-          && TREE_INT_CST_HIGH (key) == -1
-          && TREE_INT_CST_LOW (key) != 0)
-    snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
-             -TREE_INT_CST_LOW (key));
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+
+  if (tree_fits_uhwi_p (key))
+    print_dec (key, buf, UNSIGNED);
+  else if (tree_fits_shwi_p (key))
+    print_dec (key, buf, SIGNED);
   else
-    snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
-             (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (key),
-             (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
+    print_hex (key, buf);
 
   if (TYPE_NAME (type) == 0)
     warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
@@ -6363,6 +6579,55 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Handle a "no_sanitize_address" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_no_sanitize_address_attribute (tree *node, tree name, tree, int,
+                                     bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "no_address_safety_analysis" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int,
+                                            bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    warning (OPT_Wattributes, "%qE attribute ignored", name);
+  else if (!lookup_attribute ("no_sanitize_address", DECL_ATTRIBUTES (*node)))
+    DECL_ATTRIBUTES (*node)
+      = tree_cons (get_identifier ("no_sanitize_address"),
+                  NULL_TREE, DECL_ATTRIBUTES (*node));
+  *no_add_attrs = true;
+  return NULL_TREE;
+}
+
+/* Handle a "no_sanitize_undefined" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
+                                     bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "noinline" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -6520,7 +6785,7 @@ handle_error_attribute (tree *node, tree name, tree args,
                        int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL
-      || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+      && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
     /* Do nothing else, just set the attribute.  We'll get at
        it later with lookup_attribute.  */
     ;
@@ -6737,11 +7002,11 @@ get_priority (tree args, bool is_destructor)
 
   arg = TREE_VALUE (args);
   arg = default_conversion (arg);
-  if (!host_integerp (arg, /*pos=*/0)
+  if (!tree_fits_shwi_p (arg)
       || !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
     goto invalid;
 
-  pri = tree_low_cst (arg, /*pos=*/0);
+  pri = tree_to_shwi (arg);
   if (pri < 0 || pri > MAX_INIT_PRIORITY)
     goto invalid;
 
@@ -7120,17 +7385,18 @@ check_user_alignment (const_tree align, bool allow_zero)
 {
   int i;
 
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (align))
-      || TREE_CODE (align) != INTEGER_CST)
+  if (TREE_CODE (align) != INTEGER_CST
+      || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
     {
       error ("requested alignment is not an integer constant");
       return -1;
     }
   else if (allow_zero && integer_zerop (align))
     return -1;
-  else if ((i = tree_log2 (align)) == -1)
+  else if (tree_int_cst_sgn (align) == -1
+           || (i = tree_log2 (align)) == -1)
     {
-      error ("requested alignment is not a power of 2");
+      error ("requested alignment is not a positive power of 2");
       return -1;
     }
   else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
@@ -7400,13 +7666,7 @@ handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
       if (TREE_CODE (decl) == FUNCTION_DECL)
        DECL_INITIAL (decl) = error_mark_node;
       else
-       {
-         if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
-           DECL_EXTERNAL (decl) = 1;
-         else
-           DECL_EXTERNAL (decl) = 0;
-         TREE_STATIC (decl) = 1;
-       }
+       TREE_STATIC (decl) = 1;
 
       if (!is_alias)
        /* ifuncs are also aliases, so set that attribute too. */
@@ -7745,9 +8005,8 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       tree position = TREE_VALUE (args);
 
       if (TREE_CODE (position) != INTEGER_CST
-         || TREE_INT_CST_HIGH (position)
-         || TREE_INT_CST_LOW (position) < 1
-         || TREE_INT_CST_LOW (position) > arg_count )
+         || wi::ltu_p (position, 1)
+         || wi::gtu_p (position, arg_count))
        {
          warning (OPT_Wattributes,
                   "alloc_size parameter outside range");
@@ -7772,6 +8031,77 @@ handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
   return NULL_TREE;
 }
 
+/* Handle a "bnd_variable_size" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+                                   int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FIELD_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "bnd_legacy" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_bnd_legacy (tree *node, tree name, tree ARG_UNUSED (args),
+                  int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "warn_unused" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_warn_unused_attribute (tree *node, tree name,
+                             tree args ATTRIBUTE_UNUSED,
+                             int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  if (TYPE_P (*node))
+    /* Do nothing else, just set the attribute.  We'll get at
+       it later with lookup_attribute.  */
+    ;
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle an "omp declare simd" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
+{
+  return NULL_TREE;
+}
+
+/* Handle an "omp declare target" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
+{
+  return NULL_TREE;
+}
+
 /* Handle a "returns_twice" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -8149,14 +8479,14 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 
   size = TREE_VALUE (args);
 
-  if (!host_integerp (size, 1))
+  if (!tree_fits_uhwi_p (size))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
   /* Get the vector size (in bytes).  */
-  vecsize = tree_low_cst (size, 1);
+  vecsize = tree_to_uhwi (size);
 
   /* We need to provide for vector pointers, vector arrays, and
      functions returning vectors.  For example:
@@ -8182,14 +8512,14 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
       || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT
          && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
-      || !host_integerp (TYPE_SIZE_UNIT (type), 1)
+      || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
       || TREE_CODE (type) == BOOLEAN_TYPE)
     {
       error ("invalid vector type for attribute %qE", name);
       return NULL_TREE;
     }
 
-  if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
+  if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type)))
     {
       error ("vector size not an integral multiple of component size");
       return NULL;
@@ -8202,7 +8532,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
     }
 
   /* Calculate how many units fit in the vector.  */
-  nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+  nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type));
   if (nunits & (nunits - 1))
     {
       error ("number of components of the vector not a power of two");
@@ -8371,7 +8701,7 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray)
         in position >= the number of fixed arguments.  */
       if ((nargs - 1 - pos) < len)
        {
-         warning (OPT_Wformat,
+         warning (OPT_Wformat_,
                   "not enough variable arguments to fit a sentinel");
          return;
        }
@@ -8386,7 +8716,7 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray)
             users to cast the NULL they have written there.
             We warn with -Wstrict-null-sentinel, though.  */
          && (warn_strict_null_sentinel || null_node != sentinel))
-       warning (OPT_Wformat, "missing sentinel in function call");
+       warning (OPT_Wformat_, "missing sentinel in function call");
     }
 }
 
@@ -8437,13 +8767,14 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
 static bool
 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
 {
-  /* Verify the arg number is a constant.  */
-  if (TREE_CODE (arg_num_expr) != INTEGER_CST
-      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+  /* Verify the arg number is a small constant.  */
+  if (cst_fits_uhwi_p (arg_num_expr))
+    {
+      *valp = TREE_INT_CST_LOW (arg_num_expr);
+      return true;
+    }
+  else
     return false;
-
-  *valp = TREE_INT_CST_LOW (arg_num_expr);
-  return true;
 }
 
 /* Handle a "nothrow" attribute; arguments as in
@@ -8610,9 +8941,7 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
 
 /* Arguments being collected for optimization.  */
 typedef const char *const_char_p;              /* For DEF_VEC_P.  */
-DEF_VEC_P(const_char_p);
-DEF_VEC_ALLOC_P(const_char_p, gc);
-static GTY(()) VEC(const_char_p, gc) *optimize_args;
+static GTY(()) vec<const_char_p, va_gc> *optimize_args;
 
 
 /* Inner function to convert a TREE_LIST to argv string to parse the optimize
@@ -8633,8 +8962,8 @@ parse_optimize_options (tree args, bool attr_p)
 
   /* Build up argv vector.  Just in case the string is stored away, use garbage
      collected strings.  */
-  VEC_truncate (const_char_p, optimize_args, 0);
-  VEC_safe_push (const_char_p, gc, optimize_args, NULL);
+  vec_safe_truncate (optimize_args, 0);
+  vec_safe_push (optimize_args, (const char *) NULL);
 
   for (ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
     {
@@ -8644,7 +8973,7 @@ parse_optimize_options (tree args, bool attr_p)
        {
          char buffer[20];
          sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
-         VEC_safe_push (const_char_p, gc, optimize_args, ggc_strdup (buffer));
+         vec_safe_push (optimize_args, ggc_strdup (buffer));
        }
 
       else if (TREE_CODE (value) == STRING_CST)
@@ -8706,17 +9035,17 @@ parse_optimize_options (tree args, bool attr_p)
 
              memcpy (r, p, len2);
              r[len2] = '\0';
-             VEC_safe_push (const_char_p, gc, optimize_args, q);
+             vec_safe_push (optimize_args, (const char *) q);
            }
 
        }
     }
 
-  opt_argc = VEC_length (const_char_p, optimize_args);
+  opt_argc = optimize_args->length ();
   opt_argv = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
 
   for (i = 1; i < opt_argc; i++)
-    opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
+    opt_argv[i] = (*optimize_args)[i];
 
   saved_flag_strict_aliasing = flag_strict_aliasing;
 
@@ -8733,7 +9062,7 @@ parse_optimize_options (tree args, bool attr_p)
   /* Don't allow changing -fstrict-aliasing.  */
   flag_strict_aliasing = saved_flag_strict_aliasing;
 
-  VEC_truncate (const_char_p, optimize_args, 0);
+  optimize_args->truncate (0);
   return ret;
 }
 
@@ -8767,7 +9096,7 @@ handle_optimize_attribute (tree *node, tree name, tree args,
       /* Parse options, and update the vector.  */
       parse_optimize_options (args, true);
       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
-       = build_optimization_node ();
+       = build_optimization_node (&global_options);
 
       /* Restore current options.  */
       cl_optimization_restore (&global_options, &cur_opts);
@@ -8801,6 +9130,23 @@ handle_no_split_stack_attribute (tree *node, tree name,
 
   return NULL_TREE;
 }
+
+/* Handle a "returns_nonnull" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_returns_nonnull_attribute (tree *node, tree, tree, int,
+                                 bool *no_add_attrs)
+{
+  // Even without a prototype we still have a return type we can check.
+  if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
+    {
+      error ("returns_nonnull attribute on a function not returning a pointer");
+      *no_add_attrs = true;
+    }
+  return NULL_TREE;
+}
+
 \f
 /* Check for valid arguments being passed to a function with FNTYPE.
    There are NARGS arguments in the array ARGARRAY.  */
@@ -8865,11 +9211,8 @@ check_function_arguments_recurse (void (*callback)
            /* Extract the argument number, which was previously checked
               to be valid.  */
            format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
-
-           gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
-                       && !TREE_INT_CST_HIGH (format_num_expr));
-
-           format_num = TREE_INT_CST_LOW (format_num_expr);
+           
+           format_num = tree_to_uhwi (format_num_expr);
 
            for (inner_arg = first_call_expr_arg (param, &iter), i = 1;
                 inner_arg != 0;
@@ -9151,6 +9494,18 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
       free (message);
       message = NULL;
     }
+  else if (token_type == CPP_CHAR_USERDEF
+          || token_type == CPP_WCHAR_USERDEF
+          || token_type == CPP_CHAR16_USERDEF
+          || token_type == CPP_CHAR32_USERDEF)
+    message = catenate_messages (gmsgid,
+                                " before user-defined character literal");
+  else if (token_type == CPP_STRING_USERDEF
+          || token_type == CPP_WSTRING_USERDEF
+          || token_type == CPP_STRING16_USERDEF
+          || token_type == CPP_STRING32_USERDEF
+          || token_type == CPP_UTF8STRING_USERDEF)
+    message = catenate_messages (gmsgid, " before user-defined string literal");
   else if (token_type == CPP_STRING
           || token_type == CPP_WSTRING
           || token_type == CPP_STRING16
@@ -9215,6 +9570,7 @@ static const struct reason_option_codes_t option_codes[] = {
   {CPP_W_INVALID_PCH,                  OPT_Winvalid_pch},
   {CPP_W_WARNING_DIRECTIVE,            OPT_Wcpp},
   {CPP_W_LITERAL_SUFFIX,               OPT_Wliteral_suffix},
+  {CPP_W_DATE_TIME,                    OPT_Wdate_time},
   {CPP_W_NONE,                         0}
 };
 
@@ -9365,8 +9721,7 @@ fold_offsetof_1 (tree expr)
          return error_mark_node;
        }
       off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
-                           size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
-                                                   1)
+                           size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
                                      / BITS_PER_UNIT));
       break;
 
@@ -9460,7 +9815,7 @@ warn_for_omitted_condop (location_t location, tree cond)
    how ARG was being used.  */
 
 void
-readonly_error (tree arg, enum lvalue_use use)
+readonly_error (location_t loc, tree arg, enum lvalue_use use)
 {
   gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
              || use == lv_asm);
@@ -9473,59 +9828,59 @@ readonly_error (tree arg, enum lvalue_use use)
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-        error (READONLY_MSG (G_("assignment of member "
-                               "%qD in read-only object"),
-                            G_("increment of member "
-                               "%qD in read-only object"),
-                            G_("decrement of member "
-                               "%qD in read-only object"),
-                            G_("member %qD in read-only object "
-                               "used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
+        error_at (loc, READONLY_MSG (G_("assignment of member "
+                                       "%qD in read-only object"),
+                                    G_("increment of member "
+                                       "%qD in read-only object"),
+                                    G_("decrement of member "
+                                       "%qD in read-only object"),
+                                    G_("member %qD in read-only object "
+                                       "used as %<asm%> output")),
+                 TREE_OPERAND (arg, 1));
       else
-       error (READONLY_MSG (G_("assignment of read-only member %qD"),
-                            G_("increment of read-only member %qD"),
-                            G_("decrement of read-only member %qD"),
-                            G_("read-only member %qD used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
+       error_at (loc, READONLY_MSG (G_("assignment of read-only member %qD"),
+                                    G_("increment of read-only member %qD"),
+                                    G_("decrement of read-only member %qD"),
+                                    G_("read-only member %qD used as %<asm%> output")),
+                 TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
-                        G_("increment of read-only variable %qD"),
-                        G_("decrement of read-only variable %qD"),
-                        G_("read-only variable %qD used as %<asm%> output")),
-          arg);
+    error_at (loc, READONLY_MSG (G_("assignment of read-only variable %qD"),
+                                G_("increment of read-only variable %qD"),
+                                G_("decrement of read-only variable %qD"),
+                                G_("read-only variable %qD used as %<asm%> output")),
+             arg);
   else if (TREE_CODE (arg) == PARM_DECL)
-    error (READONLY_MSG (G_("assignment of read-only parameter %qD"),
-                        G_("increment of read-only parameter %qD"),
-                        G_("decrement of read-only parameter %qD"),
-                        G_("read-only parameter %qD use as %<asm%> output")),
-          arg);  
+    error_at (loc, READONLY_MSG (G_("assignment of read-only parameter %qD"),
+                                G_("increment of read-only parameter %qD"),
+                                G_("decrement of read-only parameter %qD"),
+                                G_("read-only parameter %qD use as %<asm%> output")),
+             arg);
   else if (TREE_CODE (arg) == RESULT_DECL)
     {
       gcc_assert (c_dialect_cxx ());
-      error (READONLY_MSG (G_("assignment of "
-                             "read-only named return value %qD"),
-                          G_("increment of "
-                             "read-only named return value %qD"),
-                          G_("decrement of "
-                             "read-only named return value %qD"),
-                          G_("read-only named return value %qD "
-                             "used as %<asm%>output")),
-            arg);
+      error_at (loc, READONLY_MSG (G_("assignment of "
+                                     "read-only named return value %qD"),
+                                  G_("increment of "
+                                     "read-only named return value %qD"),
+                                  G_("decrement of "
+                                     "read-only named return value %qD"),
+                                  G_("read-only named return value %qD "
+                                     "used as %<asm%>output")),
+               arg);
     }
   else if (TREE_CODE (arg) == FUNCTION_DECL)
-    error (READONLY_MSG (G_("assignment of function %qD"),
-                        G_("increment of function %qD"),
-                        G_("decrement of function %qD"),
-                        G_("function %qD used as %<asm%> output")),
-          arg);
+    error_at (loc, READONLY_MSG (G_("assignment of function %qD"),
+                                G_("increment of function %qD"),
+                                G_("decrement of function %qD"),
+                                G_("function %qD used as %<asm%> output")),
+             arg);
   else
-    error (READONLY_MSG (G_("assignment of read-only location %qE"),
-                        G_("increment of read-only location %qE"),
-                        G_("decrement of read-only location %qE"),
-                        G_("read-only location %qE used as %<asm%> output")),
-          arg);
+    error_at (loc, READONLY_MSG (G_("assignment of read-only location %qE"),
+                                G_("increment of read-only location %qE"),
+                                G_("decrement of read-only location %qE"),
+                                G_("read-only location %qE used as %<asm%> output")),
+             arg);
 }
 
 /* Print an error message for an invalid lvalue.  USE says
@@ -9584,6 +9939,11 @@ invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
                "invalid type argument of %<->%> (have %qT)",
                type);
       break;
+    case RO_ARROW_STAR:
+      error_at (loc,
+               "invalid type argument of %<->*%> (have %qT)",
+               type);
+      break;
     case RO_IMPLICIT_CONVERSION:
       error_at (loc,
                "invalid type argument of implicit conversion (have %qT)",
@@ -9605,6 +9965,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
   tree maxindex, type, main_type, elt, unqual_elt;
   int failure = 0, quals;
   hashval_t hashcode = 0;
+  bool overflow_p = false;
 
   maxindex = size_zero_node;
   if (initial_value)
@@ -9617,9 +9978,9 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
-         VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
+         vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value);
 
-         if (VEC_empty (constructor_elt, v))
+         if (vec_safe_is_empty (v))
            {
              if (pedantic)
                failure = 3;
@@ -9632,15 +9993,12 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
              constructor_elt *ce;
              bool fold_p = false;
 
-             if (VEC_index (constructor_elt, v, 0).index)
-               maxindex = fold_convert_loc (input_location, sizetype,
-                                            VEC_index (constructor_elt,
-                                                       v, 0).index);
+             if ((*v)[0].index)
+               maxindex = (*v)[0].index, fold_p = true;
+
              curindex = maxindex;
 
-             for (cnt = 1;
-                  VEC_iterate (constructor_elt, v, cnt, ce);
-                  cnt++)
+             for (cnt = 1; vec_safe_iterate (v, cnt, &ce); cnt++)
                {
                  bool curfold_p = false;
                  if (ce->index)
@@ -9648,15 +10006,26 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
                  else
                    {
                      if (fold_p)
-                       curindex = fold_convert (sizetype, curindex);
+                       {
+                         /* Since we treat size types now as ordinary
+                            unsigned types, we need an explicit overflow
+                            check.  */
+                         tree orig = curindex;
+                         curindex = fold_convert (sizetype, curindex);
+                         overflow_p |= tree_int_cst_lt (curindex, orig);
+                       }
                      curindex = size_binop (PLUS_EXPR, curindex,
                                             size_one_node);
                    }
                  if (tree_int_cst_lt (maxindex, curindex))
                    maxindex = curindex, fold_p = curfold_p;
                }
-              if (fold_p)
-                maxindex = fold_convert (sizetype, maxindex);
+             if (fold_p)
+               {
+                 tree orig = maxindex;
+                 maxindex = fold_convert (sizetype, maxindex);
+                 overflow_p |= tree_int_cst_lt (maxindex, orig);
+               }
            }
        }
       else
@@ -9717,11 +10086,11 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
 
   if (COMPLETE_TYPE_P (type)
       && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
-      && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
+      && (overflow_p || TREE_OVERFLOW (TYPE_SIZE_UNIT (type))))
     {
       error ("size of array is too large");
       /* If we proceed with the array type as it is, we'll eventually
-        crash in tree_low_cst().  */
+        crash in tree_to_[su]hwi().  */
       type = error_mark_node;
     }
 
@@ -9760,18 +10129,18 @@ builtin_type_for_size (int size, bool unsignedp)
    Returns 0 if an error is encountered.  */
 
 static int
-sync_resolve_size (tree function, VEC(tree,gc) *params)
+sync_resolve_size (tree function, vec<tree, va_gc> *params)
 {
   tree type;
   int size;
 
-  if (VEC_empty (tree, params))
+  if (!params)
     {
       error ("too few arguments to function %qE", function);
       return 0;
     }
 
-  type = TREE_TYPE (VEC_index (tree, params, 0));
+  type = TREE_TYPE ((*params)[0]);
   if (TREE_CODE (type) != POINTER_TYPE)
     goto incompatible;
 
@@ -9779,7 +10148,7 @@ sync_resolve_size (tree function, VEC(tree,gc) *params)
   if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
     goto incompatible;
 
-  size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+  size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
   if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
     return size;
 
@@ -9795,7 +10164,7 @@ sync_resolve_size (tree function, VEC(tree,gc) *params)
 
 static bool
 sync_resolve_params (location_t loc, tree orig_function, tree function,
-                    VEC(tree, gc) *params, bool orig_format)
+                    vec<tree, va_gc> *params, bool orig_format)
 {
   function_args_iterator iter;
   tree ptype;
@@ -9806,7 +10175,8 @@ sync_resolve_params (location_t loc, tree orig_function, tree function,
      as the pointer parameter, so we shouldn't get any complaints from the
      call to check_function_arguments what ever type the user used.  */
   function_args_iter_next (&iter);
-  ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0)));
+  ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
+  ptype = TYPE_MAIN_VARIANT (ptype);
 
   /* For the rest of the values, we need to cast these to FTYPE, so that we
      don't get warnings for passing pointer types, etc.  */
@@ -9821,7 +10191,7 @@ sync_resolve_params (location_t loc, tree orig_function, tree function,
        break;
 
       ++parmnum;
-      if (VEC_length (tree, params) <= parmnum)
+      if (params->length () <= parmnum)
        {
          error_at (loc, "too few arguments to function %qE", orig_function);
          return false;
@@ -9837,17 +10207,17 @@ sync_resolve_params (location_t loc, tree orig_function, tree function,
          /* Ideally for the first conversion we'd use convert_for_assignment
             so that we get warnings for anything that doesn't match the pointer
             type.  This isn't portable across the C and C++ front ends atm.  */
-         val = VEC_index (tree, params, parmnum);
+         val = (*params)[parmnum];
          val = convert (ptype, val);
          val = convert (arg_type, val);
-         VEC_replace (tree, params, parmnum, val);
+         (*params)[parmnum] = val;
        }
 
       function_args_iter_next (&iter);
     }
 
   /* __atomic routines are not variadic.  */
-  if (!orig_format && VEC_length (tree, params) != parmnum + 1)
+  if (!orig_format && params->length () != parmnum + 1)
     {
       error_at (loc, "too many arguments to function %qE", orig_function);
       return false;
@@ -9857,7 +10227,7 @@ sync_resolve_params (location_t loc, tree orig_function, tree function,
      being "an optional list of variables protected by the memory barrier".
      No clue what that's supposed to mean, precisely, but we consider all
      call-clobbered variables to be protected so we're safe.  */
-  VEC_truncate (tree, params, parmnum + 1);
+  params->truncate (parmnum + 1);
 
   return true;
 }
@@ -9885,7 +10255,8 @@ sync_resolve_return (tree first_param, tree result, bool orig_format)
    0 is returned if the parameters are invalid.  */
 
 static int
-get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
+get_atomic_generic_size (location_t loc, tree function,
+                        vec<tree, va_gc> *params)
 {
   unsigned int n_param;
   unsigned int n_model;
@@ -9913,14 +10284,14 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
       gcc_unreachable ();
     }
 
-  if (VEC_length (tree, params) != n_param)
+  if (vec_safe_length (params) != n_param)
     {
       error_at (loc, "incorrect number of arguments to function %qE", function);
       return 0;
     }
 
   /* Get type of first parameter, and determine its size.  */
-  type_0 = TREE_TYPE (VEC_index (tree, params, 0));
+  type_0 = TREE_TYPE ((*params)[0]);
   if (TREE_CODE (type_0) != POINTER_TYPE || VOID_TYPE_P (TREE_TYPE (type_0)))
     {
       error_at (loc, "argument 1 of %qE must be a non-void pointer type",
@@ -9937,7 +10308,7 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
       return 0;
     }
 
-  size_0 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type_0)), 1);
+  size_0 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type_0)));
 
   /* Zero size objects are not allowed.  */
   if (size_0 == 0)
@@ -9952,8 +10323,8 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
   for (x = 0; x < n_param - n_model; x++)
     {
       int size;
-      tree type = TREE_TYPE (VEC_index (tree, params, x));
-      /* __atomic_compare_exchange has a bool in the 4th postion, skip it.  */
+      tree type = TREE_TYPE ((*params)[x]);
+      /* __atomic_compare_exchange has a bool in the 4th position, skip it.  */
       if (n_param == 6 && x == 3)
         continue;
       if (!POINTER_TYPE_P (type))
@@ -9962,7 +10333,7 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
                    function);
          return 0;
        }
-      size = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
+      size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
       if (size != size_0)
        {
          error_at (loc, "size mismatch in argument %d of %qE", x + 1,
@@ -9974,11 +10345,11 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
   /* Check memory model parameters for validity.  */
   for (x = n_param - n_model ; x < n_param; x++)
     {
-      tree p = VEC_index (tree, params, x);
+      tree p = (*params)[x];
       if (TREE_CODE (p) == INTEGER_CST)
         {
-         int i = tree_low_cst (p, 1);
-         if (i < 0 || i >= MEMMODEL_LAST)
+         int i = tree_to_uhwi (p);
+         if (i < 0 || (i & MEMMODEL_MASK) >= MEMMODEL_LAST)
            {
              warning_at (loc, OPT_Winvalid_memory_model,
                          "invalid memory model argument %d of %qE", x + 1,
@@ -10007,34 +10378,55 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
 
 static tree
 add_atomic_size_parameter (unsigned n, location_t loc, tree function, 
-                          VEC(tree,gc) *params)
+                          vec<tree, va_gc> *params)
 {
   tree size_node;
 
   /* Insert a SIZE_T parameter as the first param.  If there isn't
      enough space, allocate a new vector and recursively re-build with that.  */
-  if (!VEC_space (tree, params, 1))
+  if (!params->space (1))
     {
       unsigned int z, len;
-      VEC(tree,gc) *vec;
+      vec<tree, va_gc> *v;
       tree f;
 
-      len = VEC_length (tree, params);
-      vec = VEC_alloc (tree, gc, len + 1);
+      len = params->length ();
+      vec_alloc (v, len + 1);
       for (z = 0; z < len; z++)
-       VEC_quick_push (tree, vec, VEC_index (tree, params, z));
-      f = build_function_call_vec (loc, function, vec, NULL);
-      VEC_free (tree, gc, vec);
+       v->quick_push ((*params)[z]);
+      f = build_function_call_vec (loc, function, v, NULL);
+      vec_free (v);
       return f;
     }
 
   /* Add the size parameter and leave as a function call for processing.  */
   size_node = build_int_cst (size_type_node, n);
-  VEC_quick_insert (tree, params, 0, size_node);
+  params->quick_insert (0, size_node);
   return NULL_TREE;
 }
 
 
+/* Return whether atomic operations for naturally aligned N-byte
+   arguments are supported, whether inline or through libatomic.  */
+static bool
+atomic_size_supported_p (int n)
+{
+  switch (n)
+    {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+      return true;
+
+    case 16:
+      return targetm.scalar_mode_supported_p (TImode);
+
+    default:
+      return false;
+    }
+}
+
 /* This will process an __atomic_exchange function call, determine whether it
    needs to be mapped to the _N variation, or turned into a library call.
    LOC is the location of the builtin call.
@@ -10046,7 +10438,7 @@ add_atomic_size_parameter (unsigned n, location_t loc, tree function,
    NEW_RETURN is set to the the return value the result is copied into.  */
 static bool
 resolve_overloaded_atomic_exchange (location_t loc, tree function, 
-                                   VEC(tree,gc) *params, tree *new_return)
+                                   vec<tree, va_gc> *params, tree *new_return)
 {      
   tree p0, p1, p2, p3;
   tree I_type, I_type_ptr;
@@ -10060,7 +10452,7 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
     }
 
   /* If not a lock-free size, change to the library generic format.  */
-  if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+  if (!atomic_size_supported_p (n))
     {
       *new_return = add_atomic_size_parameter (n, loc, function, params);
       return true;
@@ -10071,10 +10463,10 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
      into
        *return = (T) (fn (In* mem, (In) *desired, model))  */
 
-  p0 = VEC_index (tree, params, 0);
-  p1 = VEC_index (tree, params, 1);
-  p2 = VEC_index (tree, params, 2);
-  p3 = VEC_index (tree, params, 3);
+  p0 = (*params)[0];
+  p1 = (*params)[1];
+  p2 = (*params)[2];
+  p3 = (*params)[3];
   
   /* Create pointer to appropriate size.  */
   I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
@@ -10082,15 +10474,15 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
 
   /* Convert object pointer to required type.  */
   p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-  VEC_replace (tree, params, 0, p0)
+  (*params)[0] = p0
   /* Convert new value to required type, and dereference it.  */
   p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
   p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
-  VEC_replace (tree, params, 1, p1);
+  (*params)[1] = p1;
 
   /* Move memory model to the 3rd position, and end param list.  */
-  VEC_replace (tree, params, 2, p3);
-  VEC_truncate (tree, params, 3);
+  (*params)[2] = p3;
+  params->truncate (3);
 
   /* Convert return pointer and dereference it for later assignment.  */
   *new_return = build_indirect_ref (loc, p2, RO_UNARY_STAR);
@@ -10110,7 +10502,7 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
 
 static bool
 resolve_overloaded_atomic_compare_exchange (location_t loc, tree function, 
-                                           VEC(tree,gc) *params, 
+                                           vec<tree, va_gc> *params, 
                                            tree *new_return)
 {      
   tree p0, p1, p2;
@@ -10125,7 +10517,7 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
     }
 
   /* If not a lock-free size, change to the library generic format.  */
-  if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+  if (!atomic_size_supported_p (n))
     {
       /* The library generic format does not have the weak parameter, so 
         remove it from the param list.  Since a parameter has been removed,
@@ -10134,9 +10526,9 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
         there is no danger this will be done twice.  */
       if (n > 0)
         {
-         VEC_replace (tree, params, 3, VEC_index (tree, params, 4));
-         VEC_replace (tree, params, 4, VEC_index (tree, params, 5));
-         VEC_truncate (tree, params, 5);
+         (*params)[3] = (*params)[4];
+         (*params)[4] = (*params)[5];
+         params->truncate (5);
        }
       *new_return = add_atomic_size_parameter (n, loc, function, params);
       return true;
@@ -10147,9 +10539,9 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
      into
        bool fn ((In *)mem, (In *)expected, (In) *desired, weak, succ, fail)  */
 
-  p0 = VEC_index (tree, params, 0);
-  p1 = VEC_index (tree, params, 1);
-  p2 = VEC_index (tree, params, 2);
+  p0 = (*params)[0];
+  p1 = (*params)[1];
+  p2 = (*params)[2];
   
   /* Create pointer to appropriate size.  */
   I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
@@ -10157,16 +10549,16 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
 
   /* Convert object pointer to required type.  */
   p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-  VEC_replace (tree, params, 0, p0);
+  (*params)[0] = p0;
 
   /* Convert expected pointer to required type.  */
   p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
-  VEC_replace (tree, params, 1, p1);
+  (*params)[1] = p1;
 
   /* Convert desired value to required type, and dereference it.  */
   p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
   p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
-  VEC_replace (tree, params, 2, p2);
+  (*params)[2] = p2;
 
   /* The rest of the parameters are fine. NULL means no special return value
      processing.*/
@@ -10187,7 +10579,7 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
 
 static bool
 resolve_overloaded_atomic_load (location_t loc, tree function, 
-                               VEC(tree,gc) *params, tree *new_return)
+                               vec<tree, va_gc> *params, tree *new_return)
 {      
   tree p0, p1, p2;
   tree I_type, I_type_ptr;
@@ -10201,7 +10593,7 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
     }
 
   /* If not a lock-free size, change to the library generic format.  */
-  if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+  if (!atomic_size_supported_p (n))
     {
       *new_return = add_atomic_size_parameter (n, loc, function, params);
       return true;
@@ -10212,9 +10604,9 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
      into
        *return = (T) (fn ((In *) mem, model))  */
 
-  p0 = VEC_index (tree, params, 0);
-  p1 = VEC_index (tree, params, 1);
-  p2 = VEC_index (tree, params, 2);
+  p0 = (*params)[0];
+  p1 = (*params)[1];
+  p2 = (*params)[2];
   
   /* Create pointer to appropriate size.  */
   I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
@@ -10222,11 +10614,11 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
 
   /* Convert object pointer to required type.  */
   p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-  VEC_replace (tree, params, 0, p0);
+  (*params)[0] = p0;
 
   /* Move memory model to the 2nd position, and end param list.  */
-  VEC_replace (tree, params, 1, p2);
-  VEC_truncate (tree, params, 2);
+  (*params)[1] = p2;
+  params->truncate (2);
 
   /* Convert return pointer and dereference it for later assignment.  */
   *new_return = build_indirect_ref (loc, p1, RO_UNARY_STAR);
@@ -10247,7 +10639,7 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
 
 static bool
 resolve_overloaded_atomic_store (location_t loc, tree function, 
-                                VEC(tree,gc) *params, tree *new_return)
+                                vec<tree, va_gc> *params, tree *new_return)
 {      
   tree p0, p1;
   tree I_type, I_type_ptr;
@@ -10261,7 +10653,7 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
     }
 
   /* If not a lock-free size, change to the library generic format.  */
-  if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+  if (!atomic_size_supported_p (n))
     {
       *new_return = add_atomic_size_parameter (n, loc, function, params);
       return true;
@@ -10272,8 +10664,8 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
      into
        fn ((In *) mem, (In) *value, model)  */
 
-  p0 = VEC_index (tree, params, 0);
-  p1 = VEC_index (tree, params, 1);
+  p0 = (*params)[0];
+  p1 = (*params)[1];
   
   /* Create pointer to appropriate size.  */
   I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
@@ -10281,12 +10673,12 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
 
   /* Convert object pointer to required type.  */
   p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
-  VEC_replace (tree, params, 0, p0);
+  (*params)[0] = p0;
 
   /* Convert new value to required type, and dereference it.  */
   p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
   p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
-  VEC_replace (tree, params, 1, p1);
+  (*params)[1] = p1;
   
   /* The memory model is in the right spot already. Return is void.  */
   *new_return = NULL_TREE;
@@ -10307,7 +10699,8 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
    continue.  */
 
 tree
-resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
+resolve_overloaded_builtin (location_t loc, tree function,
+                           vec<tree, va_gc> *params)
 {
   enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
   bool orig_format = true;
@@ -10431,7 +10824,7 @@ resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
                                  orig_format))
          return error_mark_node;
 
-       first_param = VEC_index (tree, params, 0);
+       first_param = (*params)[0];
        result = build_function_call_vec (loc, new_function, params, NULL);
        if (result == error_mark_node)
          return result;
@@ -10460,20 +10853,45 @@ resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
     }
 }
 
-/* Ignoring their sign, return true if two scalar types are the same.  */
+/* vector_types_compatible_elements_p is used in type checks of vectors
+   values used as operands of binary operators.  Where it returns true, and
+   the other checks of the caller succeed (being vector types in he first
+   place, and matching number of elements), we can just treat the types
+   as essentially the same.
+   Contrast with vector_targets_convertible_p, which is used for vector
+   pointer types,  and vector_types_convertible_p, which will allow
+   language-specific matches under the control of flag_lax_vector_conversions,
+   and might still require a conversion.  */
+/* True if vector types T1 and T2 can be inputs to the same binary
+   operator without conversion.
+   We don't check the overall vector size here because some of our callers
+   want to give different error messages when the vectors are compatible
+   except for the element count.  */
+
 bool
-same_scalar_type_ignoring_signedness (tree t1, tree t2)
+vector_types_compatible_elements_p (tree t1, tree t2)
 {
+  bool opaque = TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2);
+  t1 = TREE_TYPE (t1);
+  t2 = TREE_TYPE (t2);
+
   enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
 
   gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE)
              && (c2 == INTEGER_TYPE || c2 == REAL_TYPE
                  || c2 == FIXED_POINT_TYPE));
 
+  t1 = c_common_signed_type (t1);
+  t2 = c_common_signed_type (t2);
   /* Equality works here because c_common_signed_type uses
      TYPE_MAIN_VARIANT.  */
-  return c_common_signed_type (t1)
-    == c_common_signed_type (t2);
+  if (t1 == t2)
+    return true;
+  if (opaque && c1 == c2
+      && (c1 == INTEGER_TYPE || c1 == REAL_TYPE)
+      && TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+    return true;
+  return false;
 }
 
 /* Check for missing format attributes on function pointers.  LTYPE is
@@ -10527,7 +10945,7 @@ warn_array_subscript_with_type_char (tree index)
    was enclosed in parentheses.  */
 
 void
-warn_about_parentheses (enum tree_code code,
+warn_about_parentheses (location_t loc, enum tree_code code,
                        enum tree_code code_left, tree arg_left,
                        enum tree_code code_right, tree arg_right)
 {
@@ -10547,104 +10965,147 @@ warn_about_parentheses (enum tree_code code,
   switch (code)
     {
     case LSHIFT_EXPR:
-      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<+%> inside %<<<%>");
-      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<-%> inside %<<<%>");
+      if (code_left == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<<<%>");
+      else if (code_right == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<<<%>");
+      else if (code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<<<%>");
+      else if (code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<<<%>");
       return;
 
     case RSHIFT_EXPR:
-      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<+%> inside %<>>%>");
-      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<-%> inside %<>>%>");
+      if (code_left == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<>>%>");
+      else if (code_right == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<>>%>");
+      else if (code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<>>%>");
+      else if (code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<>>%>");
       return;
 
     case TRUTH_ORIF_EXPR:
-      if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<&&%> within %<||%>");
+      if (code_left == TRUTH_ANDIF_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<&&%> within %<||%>");
+      else if (code_right == TRUTH_ANDIF_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<&&%> within %<||%>");
       return;
 
     case BIT_IOR_EXPR:
       if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR
-         || code_left == PLUS_EXPR || code_left == MINUS_EXPR
-         || code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
-         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
+         || code_left == PLUS_EXPR || code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around arithmetic in operand of %<|%>");
+      else if (code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
+              || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around arithmetic in operand of %<|%>");
       /* Check cases like x|y==z */
-      else if (TREE_CODE_CLASS (code_left) == tcc_comparison
-              || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<|%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<|%>");
       /* Check cases like !x | y */
       else if (code_left == TRUTH_NOT_EXPR
               && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
-       warning (OPT_Wparentheses, "suggest parentheses around operand of "
-                "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around operand of "
+                   "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
       return;
 
     case BIT_XOR_EXPR:
       if (code_left == BIT_AND_EXPR
-         || code_left == PLUS_EXPR || code_left == MINUS_EXPR
-         || code_right == BIT_AND_EXPR
-         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
+         || code_left == PLUS_EXPR || code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around arithmetic in operand of %<^%>");
+      else if (code_right == BIT_AND_EXPR
+              || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around arithmetic in operand of %<^%>");
       /* Check cases like x^y==z */
-      else if (TREE_CODE_CLASS (code_left) == tcc_comparison
-              || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<^%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<^%>");
       return;
 
     case BIT_AND_EXPR:
-      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
+      if (code_left == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around %<+%> in operand of %<&%>");
+      else if (code_right == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around %<+%> in operand of %<&%>");
-      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
+      else if (code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around %<-%> in operand of %<&%>");
+      else if (code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around %<-%> in operand of %<&%>");
       /* Check cases like x&y==z */
-      else if (TREE_CODE_CLASS (code_left) == tcc_comparison
-              || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<&%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<&%>");
       /* Check cases like !x & y */
       else if (code_left == TRUTH_NOT_EXPR
               && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
-       warning (OPT_Wparentheses, "suggest parentheses around operand of "
-                "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around operand of "
+                   "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
       return;
 
     case EQ_EXPR:
-      if (TREE_CODE_CLASS (code_left) == tcc_comparison
-          || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+      if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<==%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<==%>");
       return;
     case NE_EXPR:
-      if (TREE_CODE_CLASS (code_left) == tcc_comparison
-          || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+      if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<!=%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<!=%>");
       return;
 
     default:
-      if (TREE_CODE_CLASS (code) == tcc_comparison
-          && ((TREE_CODE_CLASS (code_left) == tcc_comparison
+      if (TREE_CODE_CLASS (code) == tcc_comparison)
+       {
+         if (TREE_CODE_CLASS (code_left) == tcc_comparison
                && code_left != NE_EXPR && code_left != EQ_EXPR
                && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
-              || (TREE_CODE_CLASS (code_right) == tcc_comparison
+           warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                       "comparisons like %<X<=Y<=Z%> do not "
+                       "have their mathematical meaning");
+         else if (TREE_CODE_CLASS (code_right) == tcc_comparison
                   && code_right != NE_EXPR && code_right != EQ_EXPR
-                  && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))))
-       warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
-                "have their mathematical meaning");
+                  && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))
+           warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                       "comparisons like %<X<=Y<=Z%> do not "
+                       "have their mathematical meaning");
+       }
       return;
     }
 #undef NOT_A_BOOLEAN_EXPR_P
@@ -10781,24 +11242,24 @@ warn_for_sign_compare (location_t location,
       if (TREE_CODE (op1) == BIT_NOT_EXPR)
        op1 = c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
 
-      if (host_integerp (op0, 0) || host_integerp (op1, 0))
+      if (tree_fits_shwi_p (op0) || tree_fits_shwi_p (op1))
         {
           tree primop;
           HOST_WIDE_INT constant, mask;
           int unsignedp;
           unsigned int bits;
 
-          if (host_integerp (op0, 0))
+          if (tree_fits_shwi_p (op0))
             {
               primop = op1;
               unsignedp = unsignedp1;
-              constant = tree_low_cst (op0, 0);
+              constant = tree_to_shwi (op0);
             }
           else
             {
               primop = op0;
               unsignedp = unsignedp0;
-              constant = tree_low_cst (op1, 0);
+              constant = tree_to_shwi (op1);
             }
 
           bits = TYPE_PRECISION (TREE_TYPE (primop));
@@ -10935,9 +11396,9 @@ record_types_used_by_current_var_decl (tree decl)
 {
   gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
 
-  while (!VEC_empty (tree, types_used_by_cur_var_decl))
+  while (types_used_by_cur_var_decl && !types_used_by_cur_var_decl->is_empty ())
     {
-      tree type = VEC_pop (tree, types_used_by_cur_var_decl);
+      tree type = types_used_by_cur_var_decl->pop ();
       types_used_by_var_decl_insert (type, decl);
     }
 }
@@ -10959,7 +11420,7 @@ record_locally_defined_typedef (tree decl)
     return;
 
   l = (struct c_language_function *) cfun->language;
-  VEC_safe_push (tree, gc, l->local_typedefs, decl);
+  vec_safe_push (l->local_typedefs, decl);
 }
 
 /* If T is a TYPE_DECL declared locally, mark it as used.  */
@@ -10997,7 +11458,7 @@ maybe_warn_unused_local_typedefs (void)
   if (warn_unused_local_typedefs
       && errorcount == unused_local_typedefs_warn_count)
     {
-      FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
+      FOR_EACH_VEC_SAFE_ELT (l->local_typedefs, i, decl)
        if (!TREE_USED (decl))
          warning_at (DECL_SOURCE_LOCATION (decl),
                      OPT_Wunused_local_typedefs,
@@ -11005,86 +11466,82 @@ maybe_warn_unused_local_typedefs (void)
       unused_local_typedefs_warn_count = errorcount;
     }
 
-  if (l->local_typedefs)
-    {
-      VEC_free (tree, gc, l->local_typedefs);
-      l->local_typedefs = NULL;
-    }
+  vec_free (l->local_typedefs);
 }
 
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
 
-typedef VEC(tree,gc)* tree_gc_vec;
-DEF_VEC_P(tree_gc_vec);
-DEF_VEC_ALLOC_P(tree_gc_vec,gc);
-static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache;
+typedef vec<tree, va_gc> *tree_gc_vec;
+static GTY((deletable)) vec<tree_gc_vec, va_gc> *tree_vector_cache;
 
 /* Return a new vector from the cache.  If the cache is empty,
    allocate a new vector.  These vectors are GC'ed, so it is OK if the
    pointer is not released..  */
 
-VEC(tree,gc) *
+vec<tree, va_gc> *
 make_tree_vector (void)
 {
-  if (!VEC_empty (tree_gc_vec, tree_vector_cache))
-    return VEC_pop (tree_gc_vec, tree_vector_cache);
+  if (tree_vector_cache && !tree_vector_cache->is_empty ())
+    return tree_vector_cache->pop ();
   else
     {
-      /* Passing 0 to VEC_alloc returns NULL, and our callers require
+      /* Passing 0 to vec::alloc returns NULL, and our callers require
         that we always return a non-NULL value.  The vector code uses
         4 when growing a NULL vector, so we do too.  */
-      return VEC_alloc (tree, gc, 4);
+      vec<tree, va_gc> *v;
+      vec_alloc (v, 4);
+      return v;
     }
 }
 
 /* Release a vector of trees back to the cache.  */
 
 void
-release_tree_vector (VEC(tree,gc) *vec)
+release_tree_vector (vec<tree, va_gc> *vec)
 {
   if (vec != NULL)
     {
-      VEC_truncate (tree, vec, 0);
-      VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec);
+      vec->truncate (0);
+      vec_safe_push (tree_vector_cache, vec);
     }
 }
 
 /* Get a new tree vector holding a single tree.  */
 
-VEC(tree,gc) *
+vec<tree, va_gc> *
 make_tree_vector_single (tree t)
 {
-  VEC(tree,gc) *ret = make_tree_vector ();
-  VEC_quick_push (tree, ret, t);
+  vec<tree, va_gc> *ret = make_tree_vector ();
+  ret->quick_push (t);
   return ret;
 }
 
 /* Get a new tree vector of the TREE_VALUEs of a TREE_LIST chain.  */
 
-VEC(tree,gc) *
+vec<tree, va_gc> *
 make_tree_vector_from_list (tree list)
 {
-  VEC(tree,gc) *ret = make_tree_vector ();
+  vec<tree, va_gc> *ret = make_tree_vector ();
   for (; list; list = TREE_CHAIN (list))
-    VEC_safe_push (tree, gc, ret, TREE_VALUE (list));
+    vec_safe_push (ret, TREE_VALUE (list));
   return ret;
 }
 
 /* Get a new tree vector which is a copy of an existing one.  */
 
-VEC(tree,gc) *
-make_tree_vector_copy (const VEC(tree,gc) *orig)
+vec<tree, va_gc> *
+make_tree_vector_copy (const vec<tree, va_gc> *orig)
 {
-  VEC(tree,gc) *ret;
+  vec<tree, va_gc> *ret;
   unsigned int ix;
   tree t;
 
   ret = make_tree_vector ();
-  VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
-  FOR_EACH_VEC_ELT (tree, orig, ix, t)
-    VEC_quick_push (tree, ret, t);
+  vec_safe_reserve (ret, vec_safe_length (orig));
+  FOR_EACH_VEC_SAFE_ELT (orig, ix, t)
+    ret->quick_push (t);
   return ret;
 }
 
@@ -11095,6 +11552,7 @@ keyword_begins_type_specifier (enum rid keyword)
 {
   switch (keyword)
     {
+    case RID_AUTO_TYPE:
     case RID_INT:
     case RID_CHAR:
     case RID_FLOAT:
@@ -11137,6 +11595,7 @@ keyword_is_type_qualifier (enum rid keyword)
     case RID_CONST:
     case RID_VOLATILE:
     case RID_RESTRICT:
+    case RID_ATOMIC:
       return true;
     default:
       return false;
@@ -11212,17 +11671,20 @@ c_common_init_ts (void)
 {
   MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
   MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
+  MARK_TS_TYPED (ARRAY_NOTATION_REF);
 }
 
 /* Build a user-defined numeric literal out of an integer constant type VALUE
    with identifier SUFFIX.  */
 
 tree
-build_userdef_literal (tree suffix_id, tree value, tree num_string)
+build_userdef_literal (tree suffix_id, tree value,
+                      enum overflow_type overflow, tree num_string)
 {
   tree literal = make_node (USERDEF_LITERAL);
   USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
   USERDEF_LITERAL_VALUE (literal) = value;
+  USERDEF_LITERAL_OVERFLOW (literal) = overflow;
   USERDEF_LITERAL_NUM_STRING (literal) = num_string;
   return literal;
 }
@@ -11239,9 +11701,8 @@ convert_vector_to_pointer_for_subscript (location_t loc,
       tree type1;
 
       if (TREE_CODE (index) == INTEGER_CST)
-        if (!host_integerp (index, 1)
-            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
-               >= TYPE_VECTOR_SUBPARTS (type)))
+        if (!tree_fits_uhwi_p (index)
+            || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type))
           warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
 
       c_common_mark_addressable_vec (*vecp);
@@ -11253,6 +11714,111 @@ convert_vector_to_pointer_for_subscript (location_t loc,
     }
 }
 
+/* Determine which of the operands, if any, is a scalar that needs to be
+   converted to a vector, for the range of operations.  */
+enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
+                 bool complain)
+{
+  tree type0 = TREE_TYPE (op0);
+  tree type1 = TREE_TYPE (op1);
+  bool integer_only_op = false;
+  enum stv_conv ret = stv_firstarg;
+
+  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+             || TREE_CODE (type1) == VECTOR_TYPE);
+  switch (code)
+    {
+      /* Most GENERIC binary expressions require homogeneous arguments.
+        LSHIFT_EXPR and RSHIFT_EXPR are exceptions and accept a first
+        argument that is a vector and a second one that is a scalar, so
+        we never return stv_secondarg for them.  */
+      case RSHIFT_EXPR:
+      case LSHIFT_EXPR:
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               if (complain)
+                 error_at (loc, "conversion of scalar %qT to vector %qT "
+                           "involves truncation", type0, type1);
+               return stv_error;
+             }
+           else
+             return stv_firstarg;
+         }
+       break;
+
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+      case BIT_AND_EXPR:
+       integer_only_op = true;
+       /* ... fall through ...  */
+
+      case VEC_COND_EXPR:
+
+      case PLUS_EXPR:
+      case MINUS_EXPR:
+      case MULT_EXPR:
+      case TRUNC_DIV_EXPR:
+      case CEIL_DIV_EXPR:
+      case FLOOR_DIV_EXPR:
+      case ROUND_DIV_EXPR:
+      case EXACT_DIV_EXPR:
+      case TRUNC_MOD_EXPR:
+      case FLOOR_MOD_EXPR:
+      case RDIV_EXPR:
+      case EQ_EXPR:
+      case NE_EXPR:
+      case LE_EXPR:
+      case GE_EXPR:
+      case LT_EXPR:
+      case GT_EXPR:
+      /* What about UNLT_EXPR?  */
+       if (TREE_CODE (type0) == VECTOR_TYPE)
+         {
+           tree tmp;
+           ret = stv_secondarg;
+           /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
+           tmp = type0; type0 = type1; type1 = tmp;
+           tmp = op0; op0 = op1; op1 = tmp;
+         }
+
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               if (complain)
+                 error_at (loc, "conversion of scalar %qT to vector %qT "
+                           "involves truncation", type0, type1);
+               return stv_error;
+             }
+           return ret;
+         }
+       else if (!integer_only_op
+                   /* Allow integer --> real conversion if safe.  */
+                && (TREE_CODE (type0) == REAL_TYPE
+                    || TREE_CODE (type0) == INTEGER_TYPE)
+                && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               if (complain)
+                 error_at (loc, "conversion of scalar %qT to vector %qT "
+                           "involves truncation", type0, type1);
+               return stv_error;
+             }
+           return ret;
+         }
+      default:
+       break;
+    }
+
+  return stv_nothing;
+}
+
 /* Return true iff ALIGN is an integral constant that is a fundamental
    alignment, as defined by [basic.align] in the c++-11
    specifications.