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