re PR c/36970 (GCC should display a warning when trying to free a static array)
authorJakub Jelinek <jakub@redhat.com>
Thu, 31 Jul 2008 08:02:49 +0000 (10:02 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 31 Jul 2008 08:02:49 +0000 (10:02 +0200)
PR c/36970
* builtins.c (maybe_emit_free_warning): New function.
(expand_builtin): Process BUILT_IN_FREE even at -O0.  Call
maybe_emit_free_warning for BUILT_IN_FREE.

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

From-SVN: r138362

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/free-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/free-2.c [new file with mode: 0644]

index 49799a84695deb7cc5eab30312590b543aa003d3..7da323b6caedfa26ca963e8daf7b92bd211f7571 100644 (file)
@@ -1,5 +1,10 @@
 2008-07-31  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c/36970
+       * builtins.c (maybe_emit_free_warning): New function.
+       (expand_builtin): Process BUILT_IN_FREE even at -O0.  Call
+       maybe_emit_free_warning for BUILT_IN_FREE.
+
        PR debug/36278
        * dwarf2out.c (get_context_die): New function.
        (force_decl_die, force_type_die): Use it.
index ca551915c50ac0782cf63d105b52913f28ad853a..2dffd53e604b18f00645ca7e20dad95eae5dde8b 100644 (file)
@@ -207,6 +207,7 @@ static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
                                      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);
@@ -6130,7 +6131,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
   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
@@ -7007,6 +7009,10 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       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;
     }
@@ -11981,6 +11987,27 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
     }
 }
 
+/* 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.  */
 
index 0df56e856ee79727bf164ba031c86f90be117405..c4257ea1566f12f5f40c1a070d47a7f13a8aea66 100644 (file)
@@ -1,5 +1,9 @@
 2008-07-31  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c/36970
+       * gcc.dg/free-1.c: New test.
+       * gcc.dg/free-2.c: New test.
+
        PR debug/36278
        * g++.dg/debug/namespace2.C: New test.
 
diff --git a/gcc/testsuite/gcc.dg/free-1.c b/gcc/testsuite/gcc.dg/free-1.c
new file mode 100644 (file)
index 0000000..5496c84
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR c/36970 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern void free (void *);
+
+char *p, buf3[10], d;
+struct S { char a; int b; } *r;
+
+void foo (void)
+{
+  char buf[10], buf2[10], c;
+  static char buf4[10], e;
+  char *q = buf;
+  free (p);
+  free (q);          /* { dg-warning "attempt to free a non-heap object" } */
+  free (buf2);       /* { dg-warning "attempt to free a non-heap object" } */
+  free (&c);         /* { dg-warning "attempt to free a non-heap object" } */
+  free (buf3);       /* { dg-warning "attempt to free a non-heap object" } */
+  free (&d);         /* { dg-warning "attempt to free a non-heap object" } */
+  free (buf4);       /* { dg-warning "attempt to free a non-heap object" } */
+  free (&e);         /* { dg-warning "attempt to free a non-heap object" } */
+  free (&r->a);
+  free ("abcd");      /* { dg-warning "attempt to free a non-heap object" } */
+  free (L"abcd");     /* { dg-warning "attempt to free a non-heap object" } */
+}
diff --git a/gcc/testsuite/gcc.dg/free-2.c b/gcc/testsuite/gcc.dg/free-2.c
new file mode 100644 (file)
index 0000000..eb94651
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR c/36970 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+extern void free (void *);
+
+char *p, buf3[10], d;
+struct S { char a; int b; } *r;
+
+void foo (void)
+{
+  char buf[10], buf2[10], c;
+  static char buf4[10], e;
+  char *q = buf;
+  free (p);
+  free (q);          /* At -O0 no warning is reported here.  */
+  free (buf2);       /* { dg-warning "attempt to free a non-heap object" } */
+  free (&c);         /* { dg-warning "attempt to free a non-heap object" } */
+  free (buf3);       /* { dg-warning "attempt to free a non-heap object" } */
+  free (&d);         /* { dg-warning "attempt to free a non-heap object" } */
+  free (buf4);       /* { dg-warning "attempt to free a non-heap object" } */
+  free (&e);         /* { dg-warning "attempt to free a non-heap object" } */
+  free (&r->a);
+  free ("abcd");      /* { dg-warning "attempt to free a non-heap object" } */
+  free (L"abcd");     /* { dg-warning "attempt to free a non-heap object" } */
+}