]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/38454 (memcpy folding breaks -D_FORTIFY_SOURCE=2 protection)
authorJakub Jelinek <jakub@redhat.com>
Tue, 9 Dec 2008 23:01:15 +0000 (00:01 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 9 Dec 2008 23:01:15 +0000 (00:01 +0100)
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

gcc/ChangeLog
gcc/builtins.c
gcc/function.h
gcc/ipa-inline.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/memcpy-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/memset-1.c [new file with mode: 0644]
gcc/tree-optimize.c

index 431a97a1aaa53d1d1df15a9775f61e9223bee7d0..95b8e98eb07eb4cbb9580b7a4343aa2ebf101d0c 100644 (file)
@@ -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.
 
index 745a125fe70772f540f93633d9813f3e2dbce315..afb3b3fdb328a31b5fd1b20047313b9faf9fdf6b 100644 (file)
@@ -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)
         {
index 16f2324abffbb3e7f659c62fa7d35a2126b19f0e..68df55e1a6e0e033150ddcda132b8a0ff069375a 100644 (file)
@@ -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.  */
index 662cff60b507ea0a30edd9e026083c3b1dae6552..35ec9a60f869d6087f82c0f02cd45fa0b889e3af 100644 (file)
@@ -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;
 }
 
index bcee032920385c92235fc3f17cd28b01621160c4..6f8449a5ea37291be4aeef98e1a5ce8df048a230 100644 (file)
@@ -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
diff --git a/gcc/testsuite/gcc.dg/memcpy-2.c b/gcc/testsuite/gcc.dg/memcpy-2.c
new file mode 100644 (file)
index 0000000..24464ab
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/memset-1.c b/gcc/testsuite/gcc.dg/memset-1.c
new file mode 100644 (file)
index 0000000..677ae91
--- /dev/null
@@ -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;
+}
index ba3d0fcc9e0f8b08c779cc898922374d88e6752b..0802e5af82552e03365ccb9781b0d646813048e1 100644 (file)
@@ -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)