1  /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -fanalyzer-verbosity=1" } */
       2  /* { dg-enable-nn-line-numbers "" } */
       3  
       4  #include <stdlib.h>
       5  
       6  void calls_free_1 (void *ptr)
       7  {
       8    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
       9  }
      10  
      11  void test_1 (void *ptr, int a, int b)
      12  {
      13    if (a)
      14      calls_free_1 (ptr);
      15  
      16    if (b)
      17      {
      18      }
      19    else
      20      calls_free_1 (ptr);
      21  }
      22  
      23  /* { dg-begin-multiline-output "" }
      24     NN |   free (ptr);
      25        |   ^~~~~~~~~~
      26    'test_1': events 1-2
      27      |
      28      |   NN | void test_1 (void *ptr, int a, int b)
      29      |      |      ^~~~~~
      30      |      |      |
      31      |      |      (1) entry to 'test_1'
      32      |......
      33      |   NN |     calls_free_1 (ptr);
      34      |      |     ~~~~~~~~~~~~~~~~~~
      35      |      |     |
      36      |      |     (2) calling 'calls_free_1' from 'test_1'
      37      |
      38      +--> 'calls_free_1': events 3-4
      39             |
      40             |   NN | void calls_free_1 (void *ptr)
      41             |      |      ^~~~~~~~~~~~
      42             |      |      |
      43             |      |      (3) entry to 'calls_free_1'
      44             |   NN | {
      45             |   NN |   free (ptr);
      46             |      |   ~~~~~~~~~~
      47             |      |   |
      48             |      |   (4) first 'free' here
      49             |
      50      <------+
      51      |
      52    'test_1': events 5-6
      53      |
      54      |   NN |     calls_free_1 (ptr);
      55      |      |     ^~~~~~~~~~~~~~~~~~
      56      |      |     |
      57      |      |     (5) returning to 'test_1' from 'calls_free_1'
      58      |......
      59      |   NN |     calls_free_1 (ptr);
      60      |      |     ~~~~~~~~~~~~~~~~~~
      61      |      |     |
      62      |      |     (6) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
      63      |
      64      +--> 'calls_free_1': events 7-8
      65             |
      66             |   NN | void calls_free_1 (void *ptr)
      67             |      |      ^~~~~~~~~~~~
      68             |      |      |
      69             |      |      (7) entry to 'calls_free_1'
      70             |   NN | {
      71             |   NN |   free (ptr);
      72             |      |   ~~~~~~~~~~
      73             |      |   |
      74             |      |   (8) second 'free' here; first 'free' was at (4)
      75             |
      76    { dg-end-multiline-output "" } */
      77  
      78  void calls_free_2 (void *ptr)
      79  {
      80    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
      81  }
      82  
      83  void test_2 (void *ptr, int a, int b)
      84  {
      85    switch (a)
      86      {
      87      default:
      88        break;
      89      case 1:
      90        break;
      91      case 3:
      92        calls_free_2 (ptr);
      93        break;
      94      }
      95  
      96    switch (b)
      97      {
      98      default:
      99        calls_free_2 (ptr);
     100        break;
     101      case 1:
     102        break;
     103      case 42:
     104        break;
     105      }
     106  }
     107  
     108  /* { dg-begin-multiline-output "" }
     109     NN |   free (ptr);
     110        |   ^~~~~~~~~~
     111    'test_2': events 1-2
     112      |
     113      |   NN | void test_2 (void *ptr, int a, int b)
     114      |      |      ^~~~~~
     115      |      |      |
     116      |      |      (1) entry to 'test_2'
     117      |......
     118      |   NN |       calls_free_2 (ptr);
     119      |      |       ~~~~~~~~~~~~~~~~~~
     120      |      |       |
     121      |      |       (2) calling 'calls_free_2' from 'test_2'
     122      |
     123      +--> 'calls_free_2': events 3-4
     124             |
     125             |   NN | void calls_free_2 (void *ptr)
     126             |      |      ^~~~~~~~~~~~
     127             |      |      |
     128             |      |      (3) entry to 'calls_free_2'
     129             |   NN | {
     130             |   NN |   free (ptr);
     131             |      |   ~~~~~~~~~~
     132             |      |   |
     133             |      |   (4) first 'free' here
     134             |
     135      <------+
     136      |
     137    'test_2': events 5-6
     138      |
     139      |   NN |       calls_free_2 (ptr);
     140      |      |       ^~~~~~~~~~~~~~~~~~
     141      |      |       |
     142      |      |       (5) returning to 'test_2' from 'calls_free_2'
     143      |......
     144      |   NN |       calls_free_2 (ptr);
     145      |      |       ~~~~~~~~~~~~~~~~~~
     146      |      |       |
     147      |      |       (6) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
     148      |
     149      +--> 'calls_free_2': events 7-8
     150             |
     151             |   NN | void calls_free_2 (void *ptr)
     152             |      |      ^~~~~~~~~~~~
     153             |      |      |
     154             |      |      (7) entry to 'calls_free_2'
     155             |   NN | {
     156             |   NN |   free (ptr);
     157             |      |   ~~~~~~~~~~
     158             |      |   |
     159             |      |   (8) second 'free' here; first 'free' was at (4)
     160             |
     161    { dg-end-multiline-output "" } */
     162  
     163  /* The call/return to this function shouldn't appear in the path.  */
     164  
     165  void called_by_test_3 (void)
     166  {
     167  }
     168  
     169  void test_3 (void *ptr)
     170  {
     171    free (ptr);
     172    called_by_test_3 ();
     173    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
     174  }
     175  
     176  /* { dg-begin-multiline-output "" }
     177     NN |   free (ptr);
     178        |   ^~~~~~~~~~
     179    'test_3': events 1-2
     180      |
     181      |   NN |   free (ptr);
     182      |      |   ^~~~~~~~~~
     183      |      |   |
     184      |      |   (1) first 'free' here
     185      |   NN |   called_by_test_3 ();
     186      |   NN |   free (ptr);
     187      |      |   ~~~~~~~~~~
     188      |      |   |
     189      |      |   (2) second 'free' here; first 'free' was at (1)
     190      |
     191    { dg-end-multiline-output "" } */