aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/analyzer/leak-pr108045-without-call-summaries.c
blob: ae7a7d5c1594a6c0282406b875d5c60b08638815 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* { dg-additional-options "-fno-analyzer-call-summaries" } */
/* { dg-additional-options "-Wno-analyzer-too-complex" } */

typedef __SIZE_TYPE__ size_t;
#define NULL ((void *)0)

/* data structures */

struct screen_s {
	size_t rows;
	size_t cols;
	char **data;
};

struct context_s {
	struct screen_s *scr;
};

/* global context variable */

static struct context_s *ctx;

/* prototypes */

struct screen_s *screen_create(size_t cols, size_t rows);
void screen_destroy(struct screen_s *scr);
void resize_screen(size_t cols, size_t rows);

/* functions */

struct screen_s *screen_create(size_t cols, size_t rows)
{
	struct screen_s *result = NULL;

	result = __builtin_calloc(1, sizeof(*result));
	if (!result)
		return NULL;

	result->cols = cols;
	result->rows = rows;

	/* make one allocation which will be accessed like a 2D array */
	result->data = __builtin_calloc(rows, sizeof(result->data) + sizeof(*result->data) * cols);
	if (!result->data) {
		__builtin_free(result);
		return NULL;
	}

	/* obtain pointer to start of data area */
	char *ptr = (char *)(result->data + rows);

	/* setup pointers for each row of data to allow 2D array access */
	for (size_t row = 0; row < rows; row++)
		result->data[row] = (ptr + row * cols);
	/* array can now be accessed like data[row][col] */

	return result;
}

void screen_destroy(struct screen_s *scr)
{
	if (!scr)
		return;

	__builtin_free(scr->data);

	scr->data = NULL;
	scr->rows = 0;
	scr->cols = 0;

	__builtin_free(scr); /* { dg-bogus "leak" } */
}

void resize_screen(size_t cols, size_t rows)
{
	/* create a new screen */
	struct screen_s *new_scr = NULL;
	new_scr = screen_create(cols, rows); /* { dg-bogus "leak" } */
	if (!new_scr) {
		return;
	}

	/* swap the old screen with the new one */
	struct screen_s *old_scr = ctx->scr;
	ctx->scr = new_scr;

	/* omitted: copy the old screen contents to the new screen */

	/* free the old screen */
	screen_destroy(old_scr);
}

int main(void)
{
	ctx = __builtin_calloc(1, sizeof(*ctx));
	if (!ctx)
		__builtin_abort();

	ctx->scr = screen_create(80, 25); /* { dg-bogus "leak" } */
	resize_screen(100, 20);

	/* tidy up and quit */
	screen_destroy(ctx->scr);
	__builtin_free(ctx);
	ctx = NULL;
	return 0;
}