--- /dev/null
+/* 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). */