Commit 0889e9bc by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/38454 (memcpy folding breaks -D_FORTIFY_SOURCE=2 protection)

	PR middle-end/38454
	* function.h (struct function): Add always_inline_functions_inlined.
	* ipa-inline.c (cgraph_early_inlining): Set it to true.
	* tree-optimize.c (execute_fixup_cfg): Likewise.
	* builtins.c (avoid_folding_inline_builtin): New function.
	(fold_call_expr): Don't optimize always_inline builtins before
	inlining.
	(fold_call_stmt): Likewise.
	(fold_builtin_call_array): Likewise.  Don't call
	fold_builtin_varargs for BUILT_IN_MD builtins.

	* gcc.dg/memset-1.c: New test.
	* gcc.dg/memcpy-2.c: New test.

From-SVN: r142617
parent 218d1c24
2008-12-09 Jakub Jelinek <jakub@redhat.com> 2008-12-09 Jakub Jelinek <jakub@redhat.com>
PR middle-end/38454
* function.h (struct function): Add always_inline_functions_inlined.
* ipa-inline.c (cgraph_early_inlining): Set it to true.
* tree-optimize.c (execute_fixup_cfg): Likewise.
* builtins.c (avoid_folding_inline_builtin): New function.
(fold_call_expr): Don't optimize always_inline builtins before
inlining.
(fold_call_stmt): Likewise.
(fold_builtin_call_array): Likewise. Don't call
fold_builtin_varargs for BUILT_IN_MD builtins.
PR tree-optimization/37416 PR tree-optimization/37416
* tree-scalar-evolution.c (follow_ssa_edge_in_rhs): Handle NOP_EXPR. * tree-scalar-evolution.c (follow_ssa_edge_in_rhs): Handle NOP_EXPR.
...@@ -10797,6 +10797,22 @@ fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED) ...@@ -10797,6 +10797,22 @@ fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED)
return NULL_TREE; return NULL_TREE;
} }
/* Return true if FNDECL shouldn't be folded right now.
If a built-in function has an inline attribute always_inline
wrapper, defer folding it after always_inline functions have
been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
might not be performed. */
static bool
avoid_folding_inline_builtin (tree fndecl)
{
return (DECL_DECLARED_INLINE_P (fndecl)
&& DECL_DISREGARD_INLINE_LIMITS (fndecl)
&& cfun
&& !cfun->always_inline_functions_inlined
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
}
/* A wrapper function for builtin folding that prevents warnings for /* A wrapper function for builtin folding that prevents warnings for
"statement without effect" and the like, caused by removing the "statement without effect" and the like, caused by removing the
call node earlier than the warning is generated. */ call node earlier than the warning is generated. */
...@@ -10829,6 +10845,9 @@ fold_call_expr (tree exp, bool ignore) ...@@ -10829,6 +10845,9 @@ fold_call_expr (tree exp, bool ignore)
return NULL_TREE; return NULL_TREE;
} }
if (avoid_folding_inline_builtin (fndecl))
return NULL_TREE;
/* FIXME: Don't use a list in this interface. */ /* FIXME: Don't use a list in this interface. */
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore); return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
...@@ -10931,6 +10950,8 @@ fold_builtin_call_array (tree type, ...@@ -10931,6 +10950,8 @@ fold_builtin_call_array (tree type,
&& DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK) && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
return build_call_array (type, fn, n, argarray); return build_call_array (type, fn, n, argarray);
} }
if (avoid_folding_inline_builtin (fndecl))
return build_call_array (type, fn, n, argarray);
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
{ {
tree arglist = NULL_TREE; tree arglist = NULL_TREE;
...@@ -10939,6 +10960,7 @@ fold_builtin_call_array (tree type, ...@@ -10939,6 +10960,7 @@ fold_builtin_call_array (tree type,
ret = targetm.fold_builtin (fndecl, arglist, false); ret = targetm.fold_builtin (fndecl, arglist, false);
if (ret) if (ret)
return ret; return ret;
return build_call_array (type, fn, n, argarray);
} }
else if (n <= MAX_ARGS_TO_FOLD_BUILTIN) else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
{ {
...@@ -13647,6 +13669,8 @@ fold_call_stmt (gimple stmt, bool ignore) ...@@ -13647,6 +13669,8 @@ fold_call_stmt (gimple stmt, bool ignore)
{ {
int nargs = gimple_call_num_args (stmt); int nargs = gimple_call_num_args (stmt);
if (avoid_folding_inline_builtin (fndecl))
return NULL_TREE;
/* FIXME: Don't use a list in this interface. */ /* FIXME: Don't use a list in this interface. */
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
{ {
......
...@@ -578,6 +578,7 @@ struct function GTY(()) ...@@ -578,6 +578,7 @@ struct function GTY(())
unsigned int dont_save_pending_sizes_p : 1; unsigned int dont_save_pending_sizes_p : 1;
unsigned int after_inlining : 1; unsigned int after_inlining : 1;
unsigned int always_inline_functions_inlined : 1;
/* Fields below this point are not set for abstract functions; see /* Fields below this point are not set for abstract functions; see
allocate_struct_function. */ allocate_struct_function. */
......
...@@ -1528,6 +1528,7 @@ cgraph_early_inlining (void) ...@@ -1528,6 +1528,7 @@ cgraph_early_inlining (void)
todo = optimize_inline_calls (current_function_decl); todo = optimize_inline_calls (current_function_decl);
timevar_pop (TV_INTEGRATION); timevar_pop (TV_INTEGRATION);
} }
cfun->always_inline_functions_inlined = true;
return todo; return todo;
} }
......
2008-12-09 Jakub Jelinek <jakub@redhat.com>
PR middle-end/38454
* gcc.dg/memset-1.c: New test.
* gcc.dg/memcpy-2.c: New test.
2008-12-09 Mikael Morin <mikael.morin@tele2.fr> 2008-12-09 Mikael Morin <mikael.morin@tele2.fr>
PR fortran/35983 PR fortran/35983
......
/* PR middle-end/38454 */
/* { dg-do compile } */
/* { dg-options "-O2" } */
typedef __SIZE_TYPE__ size_t;
extern inline __attribute__((gnu_inline, always_inline, artificial)) void *
memcpy (void *__restrict dest, const void *__restrict src, size_t len)
{
return __builtin___memcpy_chk (dest, /* { dg-warning "will always overflow destination buffer" } */
src, len, __builtin_object_size (dest, 0));
}
struct S { char buf[10]; } s;
void
foo (void)
{
char buf[12];
char *p = buf + 4;
struct S *q = (struct S *) p;
memcpy (q, &s, sizeof (s));
}
/* { dg-final { scan-assembler "__memcpy_chk" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */
typedef __SIZE_TYPE__ size_t;
extern void warn_memset_zero_len (void)
__attribute__((__warning__ ("memset used with constant zero length parameter;"
" this could be due to transposed parameters")));
extern inline __attribute__((gnu_inline, always_inline, artificial)) void *
memset (void *dest, int ch, size_t len)
{
if (__builtin_constant_p (len) && len == 0)
{
warn_memset_zero_len (); /* { dg-warning "memset used with constant zero" } */
return dest;
}
return __builtin_memset (dest, ch, len);
}
char buf[10];
int
main (void)
{
memset (buf, sizeof (buf), 0);
return 0;
}
...@@ -293,6 +293,7 @@ execute_fixup_cfg (void) ...@@ -293,6 +293,7 @@ execute_fixup_cfg (void)
int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0; int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
cfun->after_inlining = true; cfun->after_inlining = true;
cfun->always_inline_functions_inlined = true;
if (cfun->eh) if (cfun->eh)
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment