mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-19 12:11:01 +08:00
analyzer: more test coverage of leak detection [PR99771]
gcc/testsuite/ChangeLog: PR analyzer/99771 * gcc.dg/analyzer/leak-4.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
e1133c0205
commit
b7175f3681
103
gcc/testsuite/gcc.dg/analyzer/leak-4.c
Normal file
103
gcc/testsuite/gcc.dg/analyzer/leak-4.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* Various tests of memory leak detection. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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 '<unknown>'" } */
|
||||
/* TODO: we should print "a->ptr' here, rather than '<unknown>'
|
||||
(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 '<unknown>'" "leak of unknown" { target *-*-* } .-1 } */
|
||||
/* TODO: rather than '<unknown>', 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 '<unknown>'" "leak of sub buffer" { target *-*-* } .-1 } */
|
||||
/* TODO: rather than 'unknown', we should print something
|
||||
like '((struct s4_sub *)base)->m_buffer' (PR analyzer/99771). */
|
Loading…
x
Reference in New Issue
Block a user