]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/builtins.c
Wrap option names in gcc internal messages with %< and %>.
[thirdparty/gcc.git] / gcc / builtins.c
index 0eb3df9ccc171479881f5d80112594e3b9ec2eef..a65eb88bc492d898718d90874092e92f8fec5aef 100644 (file)
@@ -1,5 +1,5 @@
 /* Expand builtin functions.
-   Copyright (C) 1988-2018 Free Software Foundation, Inc.
+   Copyright (C) 1988-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -95,7 +95,6 @@ builtin_info_type builtin_info[(int)END_BUILTINS];
 /* Non-zero if __builtin_constant_p should be folded right away.  */
 bool force_folding_builtin_constant_p;
 
-static rtx c_readstr (const char *, scalar_int_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree, tree);
 static int apply_args_size (void);
@@ -577,11 +576,11 @@ unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */)
      structure if EXP references a unterminated array.  */
   c_strlen_data lendata = { };
   tree len = c_strlen (exp, 1, &lendata);
-  if (len == NULL_TREE && lendata.len && lendata.decl)
+  if (len == NULL_TREE && lendata.minlen && lendata.decl)
      {
        if (size)
        {
-         len = lendata.len;
+         len = lendata.minlen;
          if (lendata.off)
            {
              /* Constant offsets are already accounted for in LENDATA.MINLEN,
@@ -720,7 +719,7 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
        {
          data->decl = decl;
          data->off = byteoff;
-         data->len = ssize_int (len);
+         data->minlen = ssize_int (len);
          return NULL_TREE;
        }
 
@@ -761,15 +760,13 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
      runtime.  */
   if (eltoff < 0 || eltoff >= maxelts)
     {
-     /* Suppress multiple warnings for propagated constant strings.  */
+      /* Suppress multiple warnings for propagated constant strings.  */
       if (only_value != 2
-         && !TREE_NO_WARNING (src))
-        {
-         warning_at (loc, OPT_Warray_bounds,
-                     "offset %qwi outside bounds of constant string",
-                     eltoff);
-          TREE_NO_WARNING (src) = 1;
-        }
+         && !TREE_NO_WARNING (src)
+         && warning_at (loc, OPT_Warray_bounds,
+                        "offset %qwi outside bounds of constant string",
+                        eltoff))
+       TREE_NO_WARNING (src) = 1;
       return NULL_TREE;
     }
 
@@ -794,7 +791,7 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
     {
       data->decl = decl;
       data->off = byteoff;
-      data->len = ssize_int (len);
+      data->minlen = ssize_int (len);
       return NULL_TREE;
     }
 
@@ -802,10 +799,14 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
 }
 
 /* Return a constant integer corresponding to target reading
-   GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
+   GET_MODE_BITSIZE (MODE) bits from string constant STR.  If
+   NULL_TERMINATED_P, reading stops after '\0' character, all further ones
+   are assumed to be zero, otherwise it reads as many characters
+   as needed.  */
 
-static rtx
-c_readstr (const char *str, scalar_int_mode mode)
+rtx
+c_readstr (const char *str, scalar_int_mode mode,
+          bool null_terminated_p/*=true*/)
 {
   HOST_WIDE_INT ch;
   unsigned int i, j;
@@ -830,7 +831,7 @@ c_readstr (const char *str, scalar_int_mode mode)
        j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
       j *= BITS_PER_UNIT;
 
-      if (ch)
+      if (ch || !null_terminated_p)
        ch = (unsigned char) str[i];
       tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
     }
@@ -3096,7 +3097,7 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
                         "%K%qD specified bound %E "
                         "exceeds maximum object size %E",
                         exp, func, bound, maxobjsize))
-         TREE_NO_WARNING (exp) = true;
+       TREE_NO_WARNING (exp) = true;
 
       bool exact = true;
       if (!len || TREE_CODE (len) != INTEGER_CST)
@@ -3155,7 +3156,7 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
                     "%K%qD specified bound [%wu, %wu] "
                     "exceeds maximum object size %E",
                     exp, func, min.to_uhwi (), max.to_uhwi (), maxobjsize))
-      TREE_NO_WARNING (exp) = true;
+    TREE_NO_WARNING (exp) = true;
 
   bool exact = true;
   if (!len || TREE_CODE (len) != INTEGER_CST)
@@ -3341,7 +3342,10 @@ check_access (tree exp, tree, tree, tree dstwrite,
             the upper bound given by MAXREAD add one to it for
             the terminating nul.  Otherwise, set it to one for
             the same reason, or to MAXREAD as appropriate.  */
-         get_range_strlen (srcstr, range);
+         c_strlen_data lendata = { };
+         get_range_strlen (srcstr, &lendata, /* eltsize = */ 1);
+         range[0] = lendata.minlen;
+         range[1] = lendata.maxbound;
          if (range[0] && (!maxread || TREE_CODE (maxread) == INTEGER_CST))
            {
              if (maxread && tree_int_cst_le (maxread, range[0]))
@@ -3939,7 +3943,8 @@ expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
       dest_mem = replace_equiv_address (dest_mem, target);
     }
 
-  create_output_operand (&ops[0], retmode ? target : NULL_RTX, Pmode);
+  create_output_operand (&ops[0],
+                        retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
   create_fixed_operand (&ops[1], dest_mem);
   create_fixed_operand (&ops[2], src_mem);
   if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
@@ -4208,8 +4213,8 @@ check_strncat_sizes (tree exp, tree objsize)
 
   /* Try to determine the range of lengths that the source expression
      refers to.  */
-  tree lenrange[2];
-  get_range_strlen (src, lenrange);
+  c_strlen_data lendata = { };
+  get_range_strlen (src, &lendata, /* eltsize = */ 1);
 
   /* Try to verify that the destination is big enough for the shortest
      string.  */
@@ -4223,8 +4228,8 @@ check_strncat_sizes (tree exp, tree objsize)
     }
 
   /* Add one for the terminating nul.  */
-  tree srclen = (lenrange[0]
-                ? fold_build2 (PLUS_EXPR, size_type_node, lenrange[0],
+  tree srclen = (lendata.minlen
+                ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
                                size_one_node)
                 : NULL_TREE);
 
@@ -4276,12 +4281,15 @@ expand_builtin_strncat (tree exp, rtx)
   tree slen = c_strlen (src, 1);
 
   /* Try to determine the range of lengths that the source expression
-     refers to.  */
-  tree lenrange[2];
-  if (slen)
-    lenrange[0] = lenrange[1] = slen;
-  else
-    get_range_strlen (src, lenrange);
+     refers to.  Since the lengths are only used for warning and not
+     for code generation disable strict mode below.  */
+  tree maxlen = slen;
+  if (!maxlen)
+    {
+      c_strlen_data lendata = { };
+      get_range_strlen (src, &lendata, /* eltsize = */ 1);
+      maxlen = lendata.maxbound;
+    }
 
   /* Try to verify that the destination is big enough for the shortest
      string.  First try to determine the size of the destination object
@@ -4289,8 +4297,8 @@ expand_builtin_strncat (tree exp, rtx)
   tree destsize = compute_objsize (dest, warn_stringop_overflow - 1);
 
   /* Add one for the terminating nul.  */
-  tree srclen = (lenrange[0]
-                ? fold_build2 (PLUS_EXPR, size_type_node, lenrange[0],
+  tree srclen = (maxlen
+                ? fold_build2 (PLUS_EXPR, size_type_node, maxlen,
                                size_one_node)
                 : NULL_TREE);
 
@@ -6522,7 +6530,7 @@ expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
   gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
   TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
 
-  /* If we will emit code after the call, the call can not be a tail call.
+  /* If we will emit code after the call, the call cannot be a tail call.
      If it is emitted as a tail call, a barrier is emitted after it, and
      then all trailing code is removed.  */
   if (!ignore)
@@ -6881,7 +6889,7 @@ expand_builtin_thread_pointer (tree exp, rtx target)
       expand_insn (icode, 1, &op);
       return target;
     }
-  error ("__builtin_thread_pointer is not supported on this target");
+  error ("%<__builtin_thread_pointer%> is not supported on this target");
   return const0_rtx;
 }
 
@@ -6901,7 +6909,7 @@ expand_builtin_set_thread_pointer (tree exp)
       expand_insn (icode, 1, &op);
       return;
     }
-  error ("__builtin_set_thread_pointer is not supported on this target");
+  error ("%<__builtin_set_thread_pointer%> is not supported on this target");
 }
 
 \f
@@ -9292,8 +9300,7 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
                             tree arg0, tree arg1, tree arg2)
 {
   enum internal_fn ifn = IFN_LAST;
-  /* The code of the expression corresponding to the type-generic
-     built-in, or ERROR_MARK for the type-specific ones.  */
+  /* The code of the expression corresponding to the built-in.  */
   enum tree_code opcode = ERROR_MARK;
   bool ovf_only = false;
 
@@ -9303,42 +9310,39 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
       ovf_only = true;
       /* FALLTHRU */
     case BUILT_IN_ADD_OVERFLOW:
-      opcode = PLUS_EXPR;
-      /* FALLTHRU */
     case BUILT_IN_SADD_OVERFLOW:
     case BUILT_IN_SADDL_OVERFLOW:
     case BUILT_IN_SADDLL_OVERFLOW:
     case BUILT_IN_UADD_OVERFLOW:
     case BUILT_IN_UADDL_OVERFLOW:
     case BUILT_IN_UADDLL_OVERFLOW:
+      opcode = PLUS_EXPR;
       ifn = IFN_ADD_OVERFLOW;
       break;
     case BUILT_IN_SUB_OVERFLOW_P:
       ovf_only = true;
       /* FALLTHRU */
     case BUILT_IN_SUB_OVERFLOW:
-      opcode = MINUS_EXPR;
-      /* FALLTHRU */
     case BUILT_IN_SSUB_OVERFLOW:
     case BUILT_IN_SSUBL_OVERFLOW:
     case BUILT_IN_SSUBLL_OVERFLOW:
     case BUILT_IN_USUB_OVERFLOW:
     case BUILT_IN_USUBL_OVERFLOW:
     case BUILT_IN_USUBLL_OVERFLOW:
+      opcode = MINUS_EXPR;
       ifn = IFN_SUB_OVERFLOW;
       break;
     case BUILT_IN_MUL_OVERFLOW_P:
       ovf_only = true;
       /* FALLTHRU */
     case BUILT_IN_MUL_OVERFLOW:
-      opcode = MULT_EXPR;
-      /* FALLTHRU */
     case BUILT_IN_SMUL_OVERFLOW:
     case BUILT_IN_SMULL_OVERFLOW:
     case BUILT_IN_SMULLL_OVERFLOW:
     case BUILT_IN_UMUL_OVERFLOW:
     case BUILT_IN_UMULL_OVERFLOW:
     case BUILT_IN_UMULLL_OVERFLOW:
+      opcode = MULT_EXPR;
       ifn = IFN_MUL_OVERFLOW;
       break;
     default:
@@ -9363,13 +9367,27 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
                                 ? boolean_true_node : boolean_false_node,
                                 arg2);
 
-  tree ctype = build_complex_type (type);
-  tree call = build_call_expr_internal_loc (loc, ifn, ctype,
-                                           2, arg0, arg1);
-  tree tgt = save_expr (call);
-  tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
-  tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
-  ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
+  tree intres, ovfres;
+  if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
+    {
+      intres = fold_binary_loc (loc, opcode, type,
+                               fold_convert_loc (loc, type, arg0),
+                               fold_convert_loc (loc, type, arg1));
+      if (TREE_OVERFLOW (intres))
+       intres = drop_tree_overflow (intres);
+      ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
+               ? boolean_true_node : boolean_false_node);
+    }
+  else
+    {
+      tree ctype = build_complex_type (type);
+      tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
+                                               arg0, arg1);
+      tree tgt = save_expr (call);
+      intres = build1_loc (loc, REALPART_EXPR, type, tgt);
+      ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
+      ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
+    }
 
   if (ovf_only)
     return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
@@ -10584,6 +10602,9 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
 static void
 maybe_emit_free_warning (tree exp)
 {
+  if (call_expr_nargs (exp) != 1)
+    return;
+
   tree arg = CALL_EXPR_ARG (exp, 0);
 
   STRIP_NOPS (arg);
@@ -11203,12 +11224,3 @@ target_char_cst_p (tree t, char *p)
   *p = (char)tree_to_uhwi (t);
   return true;
 }
-
-/* Return the maximum object size.  */
-
-tree
-max_object_size (void)
-{
-  /* To do: Make this a configurable parameter.  */
-  return TYPE_MAX_VALUE (ptrdiff_type_node);
-}