| /* { dg-additional-options "-fanalyzer-call-summaries" } */ |
| |
| typedef __SIZE_TYPE__ size_t; |
| #include "../../gcc.dg/analyzer/analyzer-decls.h" |
| |
| /* 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 = (struct screen_s *) __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 = (char **) __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); |
| } |
| |
| 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" "PR 108045" { xfail *-*-* } } */ |
| 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 = (struct context_s *) __builtin_calloc(1, sizeof(*ctx)); |
| if (!ctx) |
| __builtin_abort(); |
| |
| ctx->scr = screen_create(80, 25); /* { dg-bogus "leak" "PR 108045" { xfail *-*-* } } */ |
| resize_screen(100, 20); |
| |
| /* tidy up and quit */ |
| screen_destroy(ctx->scr); |
| __builtin_free(ctx); |
| ctx = NULL; |
| return 0; |
| } |