1 extern void free (void *);
2 
3 struct foo
4 {
5   int m_int;
6 };
7 
8 extern void foo_release (struct foo *);
9 extern struct foo *foo_acquire (void)
10   __attribute__ ((malloc (foo_release)));
11 extern void use_foo (const struct foo *)
12   __attribute__((nonnull));
13 
test_1(void)14 void test_1 (void)
15 {
16   struct foo *p = foo_acquire ();
17   foo_release (p);
18 }
19 
test_2(void)20 void test_2 (void)
21 {
22   struct foo *p = foo_acquire (); /* { dg-message "this call could return NULL" } */
23   p->m_int = 42; /* { dg-warning "dereference of possibly-NULL 'p'" } */
24   foo_release (p);
25 }
26 
test_2a(void)27 void test_2a (void)
28 {
29   struct foo *p = foo_acquire (); /* { dg-message "this call could return NULL" } */
30   use_foo (p); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" } */
31   foo_release (p);
32 }
33 
test_3(void)34 void test_3 (void)
35 {
36   struct foo *p = foo_acquire (); /* { dg-message "allocated here" } */
37 } /* { dg-warning "leak of 'p'" } */
38 
test_4(struct foo * p)39 void test_4 (struct foo *p)
40 {
41   foo_release (p);
42   foo_release (p); /* { dg-warning "double-'foo_release' of 'p'" } */
43 }
44 
test_4a(void)45 void test_4a (void)
46 {
47   struct foo *p = foo_acquire ();
48   foo_release (p);
49   foo_release (p); /* { dg-warning "double-'foo_release' of 'p'" } */
50 }
51 
test_5(void)52 void test_5 (void)
53 {
54   struct foo *p = foo_acquire (); /* { dg-message "allocated here \\(expects deallocation with 'foo_release'\\)" } */
55   free (p); /* { dg-warning "'p' should have been deallocated with 'foo_release' but was deallocated with 'free'" } */
56 }
57 
test_6(struct foo * p)58 void test_6 (struct foo *p)
59 {
60   foo_release (p);
61   free (p); // TODO: double-release warning!
62 }
63 
test_7()64 void test_7 ()
65 {
66   struct foo f;
67   foo_release (&f); /* { dg-warning "not on the heap" "analyzer" } */
68   /* { dg-warning "'foo_release' called on unallocated object 'f'" "non-analyzer" { target *-*-* } .-1 } */
69 }
70 
test_8(struct foo * p)71 int test_8 (struct foo *p)
72 {
73   foo_release (p);
74   return p->m_int; /* { dg-warning "use after 'foo_release' of 'p'" } */
75 }
76