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)14void test_1 (void) 15 { 16 struct foo *p = foo_acquire (); 17 foo_release (p); 18 } 19 test_2(void)20void 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)27void 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)34void 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)39void 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)45void 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)52void 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)58void test_6 (struct foo *p) 59 { 60 foo_release (p); 61 free (p); // TODO: double-release warning! 62 } 63 test_7()64void 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)71int 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