1 /* { dg-additional-options "-fno-analyzer-call-summaries" } */
2 /* { dg-additional-options "-Wno-analyzer-too-complex" } */
3
4 typedef __SIZE_TYPE__ size_t;
5 #define NULL ((void *)0)
6
7 /* data structures */
8
9 struct screen_s {
10 size_t rows;
11 size_t cols;
12 char **data;
13 };
14
15 struct context_s {
16 struct screen_s *scr;
17 };
18
19 /* global context variable */
20
21 static struct context_s *ctx;
22
23 /* prototypes */
24
25 struct screen_s *screen_create(size_t cols, size_t rows);
26 void screen_destroy(struct screen_s *scr);
27 void resize_screen(size_t cols, size_t rows);
28
29 /* functions */
30
31 struct screen_s *screen_create(size_t cols, size_t rows)
32 {
33 struct screen_s *result = NULL;
34
35 result = __builtin_calloc(1, sizeof(*result));
36 if (!result)
37 return NULL;
38
39 result->cols = cols;
40 result->rows = rows;
41
42 /* make one allocation which will be accessed like a 2D array */
43 result->data = __builtin_calloc(rows, sizeof(result->data) + sizeof(*result->data) * cols);
44 if (!result->data) {
45 __builtin_free(result);
46 return NULL;
47 }
48
49 /* obtain pointer to start of data area */
50 char *ptr = (char *)(result->data + rows);
51
52 /* setup pointers for each row of data to allow 2D array access */
53 for (size_t row = 0; row < rows; row++)
54 result->data[row] = (ptr + row * cols);
55 /* array can now be accessed like data[row][col] */
56
57 return result;
58 }
59
60 void screen_destroy(struct screen_s *scr)
61 {
62 if (!scr)
63 return;
64
65 __builtin_free(scr->data);
66
67 scr->data = NULL;
68 scr->rows = 0;
69 scr->cols = 0;
70
71 __builtin_free(scr); /* { dg-bogus "leak" } */
72 }
73
74 void resize_screen(size_t cols, size_t rows)
75 {
76 /* create a new screen */
77 struct screen_s *new_scr = NULL;
78 new_scr = screen_create(cols, rows); /* { dg-bogus "leak" } */
79 if (!new_scr) {
80 return;
81 }
82
83 /* swap the old screen with the new one */
84 struct screen_s *old_scr = ctx->scr;
85 ctx->scr = new_scr;
86
87 /* omitted: copy the old screen contents to the new screen */
88
89 /* free the old screen */
90 screen_destroy(old_scr);
91 }
92
93 int main(void)
94 {
95 ctx = __builtin_calloc(1, sizeof(*ctx));
96 if (!ctx)
97 __builtin_abort();
98
99 ctx->scr = screen_create(80, 25); /* { dg-bogus "leak" } */
100 resize_screen(100, 20);
101
102 /* tidy up and quit */
103 screen_destroy(ctx->scr);
104 __builtin_free(ctx);
105 ctx = NULL;
106 return 0;
107 }