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
This commit is contained in:
parent
218d1c24bb
commit
0889e9bc68
8 changed files with 97 additions and 0 deletions
|
@ -1,5 +1,16 @@
|
|||
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
|
||||
* 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)
|
|||
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
|
||||
"statement without effect" and the like, caused by removing the
|
||||
call node earlier than the warning is generated. */
|
||||
|
@ -10829,6 +10845,9 @@ fold_call_expr (tree exp, bool ignore)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (avoid_folding_inline_builtin (fndecl))
|
||||
return NULL_TREE;
|
||||
|
||||
/* FIXME: Don't use a list in this interface. */
|
||||
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
|
||||
return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
|
||||
|
@ -10931,6 +10950,8 @@ fold_builtin_call_array (tree type,
|
|||
&& DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
|
||||
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)
|
||||
{
|
||||
tree arglist = NULL_TREE;
|
||||
|
@ -10939,6 +10960,7 @@ fold_builtin_call_array (tree type,
|
|||
ret = targetm.fold_builtin (fndecl, arglist, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
return build_call_array (type, fn, n, argarray);
|
||||
}
|
||||
else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
|
||||
{
|
||||
|
@ -13647,6 +13669,8 @@ fold_call_stmt (gimple stmt, bool ignore)
|
|||
{
|
||||
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. */
|
||||
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
|
||||
{
|
||||
|
|
|
@ -578,6 +578,7 @@ struct function GTY(())
|
|||
unsigned int dont_save_pending_sizes_p : 1;
|
||||
|
||||
unsigned int after_inlining : 1;
|
||||
unsigned int always_inline_functions_inlined : 1;
|
||||
|
||||
/* Fields below this point are not set for abstract functions; see
|
||||
allocate_struct_function. */
|
||||
|
|
|
@ -1528,6 +1528,7 @@ cgraph_early_inlining (void)
|
|||
todo = optimize_inline_calls (current_function_decl);
|
||||
timevar_pop (TV_INTEGRATION);
|
||||
}
|
||||
cfun->always_inline_functions_inlined = true;
|
||||
return todo;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
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>
|
||||
|
||||
PR fortran/35983
|
||||
|
|
25
gcc/testsuite/gcc.dg/memcpy-2.c
Normal file
25
gcc/testsuite/gcc.dg/memcpy-2.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* 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" } } */
|
28
gcc/testsuite/gcc.dg/memset-1.c
Normal file
28
gcc/testsuite/gcc.dg/memset-1.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* { 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)
|
|||
int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
|
||||
|
||||
cfun->after_inlining = true;
|
||||
cfun->always_inline_functions_inlined = true;
|
||||
|
||||
if (cfun->eh)
|
||||
FOR_EACH_BB (bb)
|
||||
|
|
Loading…
Add table
Reference in a new issue