]> 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 8bde6270e7605acffbbed73466b2446e1310e9f9..4eea22711ea2ea9be345f2aa89347cbbeeb2441b 100644 (file)
@@ -23,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"
@@ -39,10 +46,11 @@ 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.  */
@@ -312,6 +320,8 @@ 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 *);
@@ -370,6 +380,13 @@ 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);
@@ -402,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 },
@@ -414,6 +434,7 @@ const struct c_common_resword c_common_reswords[] =
   { "_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 },
@@ -422,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 },
@@ -723,6 +745,9 @@ const struct attribute_spec c_common_attribute_table[] =
   { "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,
@@ -743,6 +768,16 @@ const struct attribute_spec c_common_attribute_table[] =
                              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 }
 };
 
@@ -833,7 +868,7 @@ finish_fname_decls (void)
       for (saved = TREE_PURPOSE (stack); saved; saved = TREE_CHAIN (saved))
        {
          tree decl = TREE_PURPOSE (saved);
-         unsigned ix = tree_to_hwi (TREE_VALUE (saved));
+         unsigned ix = TREE_INT_CST_LOW (TREE_VALUE (saved));
 
          *fname_vars[ix].decl = decl;
        }
@@ -2200,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.  */
@@ -2214,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
@@ -2419,7 +2473,7 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
 
   arg0 = c_common_get_narrower (op0, &unsigned0);
   arg1 = c_common_get_narrower (op1, &unsigned1);
-  
+
   /* UNS is 1 if the operation to be done is an unsigned one.  */
   uns = TYPE_UNSIGNED (result_type);
 
@@ -2484,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.
@@ -2492,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);
 
@@ -2509,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
@@ -2530,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)
        {
@@ -2539,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.  */
@@ -2548,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;
            }
        }
     }
@@ -2557,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)
@@ -2595,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
@@ -2604,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.  */
@@ -2645,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;
@@ -2666,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))
@@ -2694,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);
@@ -2713,7 +2773,12 @@ conversion_warning (tree type, tree expr)
       }
 
     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);
@@ -3452,7 +3517,7 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 
   if (mode == DImode)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
-  
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (mode == TYPE_MODE (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
@@ -3968,7 +4033,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
   /* If one of the operands must be floated, we cannot optimize.  */
   real1 = TREE_CODE (TREE_TYPE (primop0)) == REAL_TYPE;
   real2 = TREE_CODE (TREE_TYPE (primop1)) == REAL_TYPE;
-  
+
   /* If first arg is constant, swap the args (changing operation
      so value is preserved), for canonicalization.  Don't do this if
      the second arg is 0.  */
@@ -4054,8 +4119,10 @@ 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 (*restype_ptr,
-                                   wide_int (primop1).force_to_size (TYPE_PRECISION (*restype_ptr),
-                                                                     TYPE_SIGN (TREE_TYPE (primop1))),
+                                   wide_int::from
+                                     (primop1,
+                                      TYPE_PRECISION (*restype_ptr),
+                                      TYPE_SIGN (TREE_TYPE (primop1))),
                                    0, TREE_OVERFLOW (primop1));
        }
       if (type != *restype_ptr)
@@ -4064,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.  */
@@ -4491,7 +4548,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
 
     case ERROR_MARK:
       return expr;
-      
+
     case INTEGER_CST:
       return integer_zerop (expr) ? truthvalue_false_node
                                  : truthvalue_true_node;
@@ -4741,7 +4798,7 @@ c_type_hash (const void *p)
   if (TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
     size = 0;
   else
-    size = tree_to_hwi (TYPE_SIZE (t));
+    size = TREE_INT_CST_LOW (TYPE_SIZE (t));
   return ((size << 24) | (n_elements << shift));
 }
 
@@ -4749,7 +4806,7 @@ static GTY((param_is (union tree_node))) htab_t type_hash_table;
 
 /* Return the typed-based alias set for T, which may be an expression
    or a type.  Return -1 if we don't do anything special.  */
+
 alias_set_type
 c_common_get_alias_set (tree t)
 {
@@ -5031,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,
@@ -5049,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
@@ -5131,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) \
@@ -5181,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
@@ -5420,7 +5483,7 @@ c_common_nodes_and_builtins (void)
   }
 
   /* This node must not be shared.  */
-  void_zero_node = make_int_cst (1);
+  void_zero_node = make_int_cst (1, 1);
   TREE_TYPE (void_zero_node) = void_type_node;
 
   void_list_node = build_void_list_node ();
@@ -5609,7 +5672,7 @@ c_common_nodes_and_builtins (void)
            (build_decl (UNKNOWN_LOCATION,
                         TYPE_DECL, get_identifier (pname),
                         ptype));
-         
+
        }
     }
 
@@ -5631,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_int_cst (1);
+  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.  */
@@ -6011,8 +6074,10 @@ match_case_to_enum_1 (tree key, tree type, tree label)
 {
   char buf[WIDE_INT_PRINT_BUFFER_SIZE];
 
-  if (tree_fits_hwi_p (key, TYPE_SIGN (type)))
-    print_dec (key, buf, TYPE_SIGN (type));
+  if (tree_fits_uhwi_p (key))
+    print_dec (key, buf, UNSIGNED);
+  else if (tree_fits_shwi_p (key))
+    print_dec (key, buf, SIGNED);
   else
     print_hex (key, buf);
 
@@ -6547,6 +6612,22 @@ handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int,
   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.  */
 
@@ -7059,7 +7140,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
   tree ident = TREE_VALUE (args);
 
   *no_add_attrs = true;
-  
+
   if (TREE_CODE (ident) != IDENTIFIER_NODE)
     warning (OPT_Wattributes, "%qE attribute ignored", name);
   else
@@ -7922,11 +8003,10 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   for (; args; args = TREE_CHAIN (args))
     {
       tree position = TREE_VALUE (args);
-      wide_int p;
 
       if (TREE_CODE (position) != INTEGER_CST
-         || (p = wide_int (position)).ltu_p (1)
-         || p.gtu_p (arg_count) )
+         || wi::ltu_p (position, 1)
+         || wi::gtu_p (position, arg_count))
        {
          warning (OPT_Wattributes,
                   "alloc_size parameter outside range");
@@ -7951,6 +8031,38 @@ 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.  */
 
@@ -7972,6 +8084,24 @@ handle_warn_unused_attribute (tree *node, tree name,
   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.  */
 
@@ -8564,7 +8694,7 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray)
       if (TREE_VALUE (attr))
        {
          tree p = TREE_VALUE (TREE_VALUE (attr));
-         pos = tree_to_hwi (p);
+         pos = TREE_INT_CST_LOW (p);
        }
 
       /* The sentinel must be one of the varargs, i.e.
@@ -8640,7 +8770,7 @@ get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
   /* Verify the arg number is a small constant.  */
   if (cst_fits_uhwi_p (arg_num_expr))
     {
-      *valp = tree_to_hwi (arg_num_expr);
+      *valp = TREE_INT_CST_LOW (arg_num_expr);
       return true;
     }
   else
@@ -8842,7 +8972,7 @@ parse_optimize_options (tree args, bool attr_p)
       if (TREE_CODE (value) == INTEGER_CST)
        {
          char buffer[20];
-         sprintf (buffer, "-O%ld", (long) tree_to_hwi (value));
+         sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
          vec_safe_push (optimize_args, ggc_strdup (buffer));
        }
 
@@ -8966,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);
@@ -9000,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.  */
@@ -9065,8 +9212,6 @@ check_function_arguments_recurse (void (*callback)
               to be valid.  */
            format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
            
-           gcc_assert (tree_fits_uhwi_p (format_num_expr));
-
            format_num = tree_to_uhwi (format_num_expr);
 
            for (inner_arg = first_call_expr_arg (param, &iter), i = 1;
@@ -9321,7 +9466,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
           || token_type == CPP_CHAR16
           || token_type == CPP_CHAR32)
     {
-      unsigned int val = tree_to_hwi (value);
+      unsigned int val = TREE_INT_CST_LOW (value);
       const char *prefix;
 
       switch (token_type)
@@ -9425,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}
 };
 
@@ -9669,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);
@@ -9682,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
@@ -9793,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)",
@@ -9939,7 +10090,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
     {
       error ("size of array is too large");
       /* If we proceed with the array type as it is, we'll eventually
-        crash in tree_to_uhwi().  */
+        crash in tree_to_[su]hwi().  */
       type = error_mark_node;
     }
 
@@ -10025,6 +10176,7 @@ sync_resolve_params (location_t loc, tree orig_function, tree function,
      call to check_function_arguments what ever type the user used.  */
   function_args_iter_next (&iter);
   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.  */
@@ -10254,6 +10406,27 @@ add_atomic_size_parameter (unsigned n, location_t loc, tree function,
 }
 
 
+/* 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.
@@ -10279,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;
@@ -10344,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,
@@ -10365,7 +10538,7 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
        bool fn(T* mem, T* desired, T* return, weak, success, failure)
      into
        bool fn ((In *)mem, (In *)expected, (In) *desired, weak, succ, fail)  */
-  
+
   p0 = (*params)[0];
   p1 = (*params)[1];
   p2 = (*params)[2];
@@ -10420,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;
@@ -10480,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;
@@ -10680,20 +10853,45 @@ resolve_overloaded_builtin (location_t loc, tree function,
     }
 }
 
-/* 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
@@ -11139,7 +11337,7 @@ do_warn_double_promotion (tree result_type, tree type1, tree type2,
    early on, later parts of the compiler can always do the reverse
    translation and get back the corresponding typedef name.  For
    example, given:
-   
+
        typedef struct S MY_TYPE;
        MY_TYPE object;
 
@@ -11354,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:
@@ -11396,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;
@@ -11502,8 +11702,7 @@ convert_vector_to_pointer_for_subscript (location_t loc,
 
       if (TREE_CODE (index) == INTEGER_CST)
         if (!tree_fits_uhwi_p (index)
-            || ((unsigned HOST_WIDE_INT) tree_to_uhwi (index)
-               >= TYPE_VECTOR_SUBPARTS (type)))
+            || 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);