enum built_in_function);
static void maybe_emit_chk_warning (tree, enum built_in_function);
static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
+static void maybe_emit_free_warning (tree);
static tree fold_builtin_object_size (tree, tree);
static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
if (real_identical (&c, &cint)
&& ((n >= -1 && n <= 2)
|| (flag_unsafe_math_optimizations
- && !optimize_size
+ && optimize_insn_for_speed_p ()
&& powi_cost (n) <= POWI_MAX_MULTS)))
{
op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
if (real_identical (&c2, &cint)
&& ((flag_unsafe_math_optimizations
- && !optimize_size
+ && optimize_insn_for_speed_p ()
&& powi_cost (n/2) <= POWI_MAX_MULTS)
|| n == 1))
{
real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
real_convert (&c2, mode, &c2);
if (real_identical (&c2, &c)
- && ((!optimize_size
+ && ((optimize_insn_for_speed_p ()
&& powi_cost (n/3) <= POWI_MAX_MULTS)
|| n == 1))
{
if ((TREE_INT_CST_HIGH (arg1) == 0
|| TREE_INT_CST_HIGH (arg1) == -1)
&& ((n >= -1 && n <= 2)
- || (! optimize_size
+ || (optimize_insn_for_speed_p ()
&& powi_cost (n) <= POWI_MAX_MULTS)))
{
op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
if (p && *p == '\0')
return expand_expr (dst, target, mode, EXPAND_NORMAL);
- if (!optimize_size)
+ if (optimize_insn_for_speed_p ())
{
/* See if we can store by pieces into (dst + strlen(dst)). */
tree newsrc, newdst,
if (!optimize
&& !called_as_built_in (fndecl)
&& DECL_ASSEMBLER_NAME_SET_P (fndecl)
- && fcode != BUILT_IN_ALLOCA)
+ && fcode != BUILT_IN_ALLOCA
+ && fcode != BUILT_IN_FREE)
return expand_call (exp, target, ignore);
/* The built-in function expanders test for target == const0_rtx
maybe_emit_sprintf_chk_warning (exp, fcode);
break;
+ case BUILT_IN_FREE:
+ maybe_emit_free_warning (exp);
+ break;
+
default: /* just do library call, if unknown builtin */
break;
}
}
}
+/* Emit warning if a free is called with address of a variable. */
+
+static void
+maybe_emit_free_warning (tree exp)
+{
+ tree arg = CALL_EXPR_ARG (exp, 0);
+
+ STRIP_NOPS (arg);
+ if (TREE_CODE (arg) != ADDR_EXPR)
+ return;
+
+ arg = get_base_address (TREE_OPERAND (arg, 0));
+ if (arg == NULL || INDIRECT_REF_P (arg))
+ return;
+
+ if (SSA_VAR_P (arg))
+ warning (0, "%Kattempt to free a non-heap object %qD", exp, arg);
+ else
+ warning (0, "%Kattempt to free a non-heap object", exp);
+}
+
/* Fold a call to __builtin_object_size with arguments PTR and OST,
if possible. */