/* Various tests of memory leak detection. */ #include /* Example of an leak due to incomplete cleanup when freeing a struct. */ struct s1 { void *ptr; }; void test_1 (void) { struct s1 *a = malloc (sizeof (struct s1)); if (!a) return; a->ptr = malloc (1024); /* { dg-message "allocated here" } */ free (a); /* { dg-warning "leak of ''" } */ /* TODO: we should print "a->ptr' here, rather than '' (PR analyzer/99771). */ } /* Examples involving arrays. */ struct s2 { void *m_arr[10]; }; void test_2a (void) { struct s2 arr[5]; arr[3].m_arr[4] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[3\\\].m_arr\\\[4\\\]'" } */ void test_2b (int i) { struct s2 arr[5]; arr[3].m_arr[i] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[3\\\].m_arr\\\[i\\\]'" } */ void test_2c (int i) { struct s2 arr[5]; arr[i].m_arr[4] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[i\\\].m_arr\\\[4\\\]'" } */ void test_2d (int i, int j) { struct s2 arr[5]; arr[i].m_arr[j] = malloc (1024); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'arr\\\[i\\\].m_arr\\\[j\\\]'" } */ /* Example involving fields. */ struct s3 { struct s3 *m_left; struct s3 *m_right; }; void test_3 (void) { struct s3 *a = malloc (sizeof (struct s3)); a->m_right = malloc (sizeof (struct s3)); /* { dg-warning "dereference of possibly-NULL 'a'" } */ a->m_right->m_left = malloc (sizeof (struct s3)); /* { dg-warning "dereference of possibly-NULL '\\*a.m_right'" } */ } /* { dg-warning "leak of 'a'" "leak of a" } */ /* { dg-warning "leak of ''" "leak of unknown" { target *-*-* } .-1 } */ /* TODO: rather than '', we should print 'a->m_right' and 'a->m_right->m_left' (PR analyzer/99771). */ /* Example involving faking inheritance via casts. */ struct s4_base { int m_placeholder; }; struct s4_sub { void *m_buffer; }; static struct s4_sub * make_s4_sub (void) { struct s4_sub *sub = malloc (sizeof (struct s4_sub)); /* { dg-message "allocated here" } */ if (!sub) return NULL; sub->m_buffer = malloc (1024); /* { dg-message "allocated here" } */ return sub; } void test_4 (void) { struct s4_base *base = (struct s4_base *)make_s4_sub (); } /* { dg-warning "leak of 'base'" "leak of base" } */ /* { dg-warning "leak of ''" "leak of sub buffer" { target *-*-* } .-1 } */ /* TODO: rather than 'unknown', we should print something like '((struct s4_sub *)base)->m_buffer' (PR analyzer/99771). */