aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-12-03 15:41:25 -0700
committerMartin Sebor <msebor@redhat.com>2020-12-03 15:43:32 -0700
commitdce6c58db87ebf7f4477bd3126228e73e4eeee97 (patch)
treef89f18c53c2f16c2d39a1951c21f99cdd4773c99 /gcc/testsuite/gcc.dg
parenta3f7a6957a674caf95c4aefa618be51092022e87 (diff)
downloadgcc-dce6c58db87ebf7f4477bd3126228e73e4eeee97.zip
gcc-dce6c58db87ebf7f4477bd3126228e73e4eeee97.tar.gz
gcc-dce6c58db87ebf7f4477bd3126228e73e4eeee97.tar.bz2
Add support for detecting mismatched allocation/deallocation calls.
PR c++/90629 - Support for -Wmismatched-new-delete PR middle-end/94527 - Add an __attribute__ that marks a function as freeing an object gcc/ChangeLog: PR c++/90629 PR middle-end/94527 * builtins.c (access_ref::access_ref): Initialize new member. (compute_objsize): Use access_ref::deref. Handle simple pointer assignment. (expand_builtin): Remove handling of the free built-in. (call_dealloc_argno): Same. (find_assignment_location): New function. (fndecl_alloc_p): Same. (gimple_call_alloc_p): Same. (call_dealloc_p): Same. (matching_alloc_calls_p): Same. (warn_dealloc_offset): Same. (maybe_emit_free_warning): Same. * builtins.h (struct access_ref): Declare new member. (maybe_emit_free_warning): Make extern. Make use of access_ref. Handle -Wmismatched-new-delete. * calls.c (initialize_argument_information): Call maybe_emit_free_warning. * doc/extend.texi (attribute malloc): Update. * doc/invoke.texi (-Wfree-nonheap-object): Expand documentation. (-Wmismatched-new-delete): Document new option. (-Wmismatched-dealloc): Document new option. gcc/c-family/ChangeLog: PR c++/90629 PR middle-end/94527 * c-attribs.c (handle_dealloc_attribute): New function. (handle_malloc_attribute): Handle argument forms of attribute. * c.opt (-Wmismatched-dealloc): New option. (-Wmismatched-new-delete): New option. gcc/testsuite/ChangeLog: PR c++/90629 PR middle-end/94527 * g++.dg/asan/asan_test.cc: Fix a bug. * g++.dg/warn/delete-array-1.C: Add expected warning. * g++.old-deja/g++.other/delete2.C: Add expected warning. * g++.dg/warn/Wfree-nonheap-object-2.C: New test. * g++.dg/warn/Wfree-nonheap-object.C: New test. * g++.dg/warn/Wmismatched-new-delete.C: New test. * g++.dg/warn/Wmismatched-dealloc-2.C: New test. * g++.dg/warn/Wmismatched-dealloc.C: New test. * gcc.dg/Wmismatched-dealloc.c: New test. * gcc.dg/analyzer/malloc-1.c: Prune out expected warning. * gcc.dg/attr-malloc.c: New test. * gcc.dg/free-1.c: Adjust text of expected warning. * gcc.dg/free-2.c: Same. * gcc.dg/torture/pr71816.c: Prune out expected warning. * gcc.dg/tree-ssa/pr19831-2.c: Add an expected warning. * gcc.dg/Wfree-nonheap-object-2.c: New test. * gcc.dg/Wfree-nonheap-object-3.c: New test. * gcc.dg/Wfree-nonheap-object.c: New test. libstdc++-v3/ChangeLog: * testsuite/ext/vstring/modifiers/clear/56166.cc: Suppress a false positive warning.
Diffstat (limited to 'gcc/testsuite/gcc.dg')
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c279
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c57
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object.c273
-rw-r--r--gcc/testsuite/gcc.dg/Wmismatched-dealloc.c252
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-malloc.c75
-rw-r--r--gcc/testsuite/gcc.dg/free-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/free-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr71816.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c2
10 files changed, 961 insertions, 19 deletions
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
new file mode 100644
index 0000000..2b00d77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
@@ -0,0 +1,279 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempting to reallocate unallocated objects referenced
+ either directly or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* alloca (size_t);
+extern void* realloc (void*, size_t);
+
+void sink (void*, ...);
+
+extern void* eparr[];
+extern char *eptr;
+
+extern size_t n;
+
+
+void nowarn_realloc (void *p, size_t n)
+{
+ char *q = realloc (p, n);
+ sink (q);
+
+ q = realloc (0, n);
+ sink (q);
+
+ q = realloc (q, n * 2);
+ sink (q);
+}
+
+/* Verify that calling realloc on a pointer to an unknown object minus
+ some nonzero offset isn't diagnosed, but a pointer plus a positive
+ offset is (a positive offset cannot point at the beginning). */
+
+void test_realloc_offset (char *p1, char *p2, char *p3, size_t n, int i)
+{
+ char *q;
+ q = realloc (p1 - 1, n);
+ sink (q);
+
+ q = realloc (p2 + 1, n); // { dg-warning "'realloc' called on pointer 'p2' with nonzero offset 1" }
+ sink (q);
+
+ q = realloc (p3 + i, n);
+ sink (q);
+}
+
+void warn_realloc_extern_arr (void)
+{
+ extern char ecarr[]; // { gg-message "declared here" }
+ char *p = ecarr;
+ char *q = realloc (p, n); // { dg-warning "'realloc' called on unallocated object 'ecarr'" }
+ sink (q);
+}
+
+void warn_realloc_extern_arr_offset (int i)
+{
+ extern char ecarr[];
+ char *p = ecarr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void warn_realloc_string (int i)
+{
+ char *p, *q;
+ {
+ p = "123";
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "234" + 1;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "123" + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_alloca (int n, int i)
+{
+ char *p, *q;
+ {
+ p = alloca (n);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 1);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 2) + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_local_arr (int i)
+{
+ char *q;
+ {
+ char a[4];
+ sink (a);
+ q = realloc (a, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char b[5];
+ sink (b);
+ q = realloc (b + 1, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char c[6];
+ sink (c);
+ q = realloc (&c[2], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char d[7];
+ sink (d);
+ q = realloc (&d[i], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void warn_realloc_vla (int n1, int n2, int i)
+{
+ char *q;
+ {
+ char vla[n1];
+ sink (vla);
+ q = realloc (vla, n2); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlb[n1 + 1];
+ sink (vlb);
+ q = realloc (vlb + 1, n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlc[n1 + 2];
+ sink (vlc);
+ q = realloc (&vlc[2], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vld[7];
+ sink (vld);
+ q = realloc (&vld[i], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void nowarn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (*eparr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (eparr, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void warn_realloc_extern_ptrarr_offset (int i)
+{
+ void *p = eparr + i;
+ void *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_extern_ptr (void)
+{
+ char *q = realloc (eptr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *p = eptr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void nowarn_realloc_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void nowarn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // The offset is from p, not *p.
+ void *q = *(p + i);
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // Unlike in the function above the offset is from *p.
+ void *q = *p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
new file mode 100644
index 0000000..a472b93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
@@ -0,0 +1,57 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced indirectly through
+ pointers obtained from function calls is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern char* memchr (const void*, int, size_t);
+extern char* strchr (const char*, int);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+
+void warn_free_memchr_ecarr (int x, size_t n)
+{
+ char *p = memchr (ecarr, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_ecarr_offset (int i, int j, int x, size_t n)
+{
+ char *p = memchr (ecarr + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_memchr_local_arr (int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_local_arr_offset (int i, int j, int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
new file mode 100644
index 0000000..bb222cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
@@ -0,0 +1,273 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed. In most cases this doesn't require
+ optimization.
+ { dg-do compile }
+ { dg-options "-Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* malloc (size_t);
+extern void* realloc (void *p, size_t);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = "123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = "456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+// Range information requires optimization.
+#pragma GCC optimize "1"
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
new file mode 100644
index 0000000..7c5d6ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
@@ -0,0 +1,252 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments has the expected
+ effect on diagnostics.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+void free (void*);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+int fclose (FILE*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+
+A (fclose) A (freopen, 3)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3)
+ FILE* freopen (const char*, const char*, FILE*);
+A (pclose) A (freopen, 3)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3)
+ FILE* tmpfile (void);
+
+void sink (FILE*);
+
+
+ void release (void*);
+A (release) FILE* acquire (void);
+
+void nowarn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ q = freopen ("1", "r", q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ sink (q);
+ }
+}
+
+
+void warn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void nowarn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("2", "r");
+ sink (q);
+ q = freopen ("3", "r", q);
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("4", "r");
+ sink (q);
+ }
+}
+
+
+void warn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void test_popen (void)
+{
+ {
+ FILE *p = popen ("1", "r");
+ sink (p);
+ pclose (p);
+ }
+
+ {
+ FILE *p;
+ p = popen ("2", "r"); // { dg-message "returned from a call to 'popen'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ /* freopen() can close a stream open by popen() but pclose() can't
+ close the stream returned from freopen(). */
+ FILE *p = popen ("2", "r");
+ sink (p);
+ p = freopen ("3", "r", p); // { dg-message "returned from a call to 'freopen'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_tmpfile (void)
+{
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ p = freopen ("1", "r", p);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile (); // { dg-message "returned from a call to 'tmpfile'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void warn_malloc (void)
+{
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_acquire (void)
+{
+ {
+ FILE *p = acquire ();
+ release (p);
+ }
+
+ {
+ FILE *p = acquire ();
+ sink (p);
+ release (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p); // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ p = realloc (p, 123); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
index c5bf1227c..26d8288 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
@@ -609,3 +609,5 @@ int test_49 (int i)
*p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
return x;
}
+
+/* { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/attr-malloc.c b/gcc/testsuite/gcc.dg/attr-malloc.c
new file mode 100644
index 0000000..14f1980
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-malloc.c
@@ -0,0 +1,75 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments is accepted where
+ intended and rejected where it's invalid.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+A (0) void* alloc_zero (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+A ("") void* alloc_string (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+int var;
+A (var) void* alloc_var (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+typedef struct Type { int i; } Type;
+A (Type) void* alloc_type (int); // { dg-error "expected expression|identifier" }
+
+A (unknown) void* alloc_unknown (int); // { dg-error "'unknown' undeclared" }
+
+void fv_ (); // { dg-message "declared here" }
+A (fv_) void* alloc_fv_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument" }
+
+void fvi (int); // { dg-message "declared here" }
+A (fvi) void* alloc_fvi (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvv (void); // { dg-message "declared here" }
+A (fvv) void* alloc_fvv (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'void'" }
+
+void fvi_ (int, ...); // { dg-message "declared here" }
+A (fvi_) void* alloc_fvi_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvi_vp (Type, void*); // { dg-message "declared here" }
+A (fvi_vp) void* alloc_fvi_vp (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'Type'" }
+
+
+void fpv (void*);
+A (fpv) void* alloc_fpv (int);
+
+void fpv_i (void*, int);
+A (fpv_i) void* alloc_fpv_i (int);
+
+void fpv_pv (void*, void*);
+A (fpv_i) void* alloc_fpv_pv (int);
+
+
+void gpc (char*);
+void hpi (int*);
+A (fpv) A (gpc) A (hpi) Type* alloc_fpv_gpv (int);
+
+
+/* Verify that the attribute can be applied to <stdio.h> functions. */
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+int fclose (FILE*);
+FILE* fdopen (int);
+FILE* fopen (const char*, const char*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+FILE* popen (const char*, const char*);
+FILE* tmpfile (void);
+
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* freopen (const char*, const char*, FILE*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* tmpfile (void);
diff --git a/gcc/testsuite/gcc.dg/free-1.c b/gcc/testsuite/gcc.dg/free-1.c
index 5496c84..ad49d78 100644
--- a/gcc/testsuite/gcc.dg/free-1.c
+++ b/gcc/testsuite/gcc.dg/free-1.c
@@ -13,14 +13,14 @@ void foo (void)
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 (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-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" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/free-2.c b/gcc/testsuite/gcc.dg/free-2.c
index eb94651..edbcdc7 100644
--- a/gcc/testsuite/gcc.dg/free-2.c
+++ b/gcc/testsuite/gcc.dg/free-2.c
@@ -13,14 +13,14 @@ void foo (void)
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 (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-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" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/torture/pr71816.c b/gcc/testsuite/gcc.dg/torture/pr71816.c
index be37ad9..cc143fa 100644
--- a/gcc/testsuite/gcc.dg/torture/pr71816.c
+++ b/gcc/testsuite/gcc.dg/torture/pr71816.c
@@ -20,3 +20,7 @@ struct ext2_icount_el *insert_icount_el() {
ext2fs_resize_mem(&insert_icount_el_icount_1);
return 0;
}
+
+/* Passing the address of a declared object to realloc triggers
+ -Wfree-nonheap-object unless -flto is used.
+ { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
index 55b4fd0..df4120d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
@@ -5,7 +5,7 @@ void test1(void)
{
int *p = __builtin_malloc (sizeof (int) * 4);
*p++ = 4;
- __builtin_free (p);
+ __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
}
/* Undefined. We can't do anything here. */