(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
unknown-fns-2.c
       1  /* Tests for data model handling of unknown fns.  */
       2  
       3  #include <stddef.h>
       4  #include "analyzer-decls.h"
       5  
       6  void unknown_fn (void *);
       7  
       8  void test_1 (void)
       9  {
      10    int i;
      11  
      12    i = 42;
      13    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      14  
      15    unknown_fn (NULL);
      16    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      17    
      18    unknown_fn (&i);
      19    __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */
      20  
      21    i = 17;
      22    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
      23  
      24    /* Even though we're not passing &i to unknown_fn, it escaped
      25       above, so unknown_fn could write to it.  */
      26    unknown_fn (NULL);
      27    __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */
      28  }
      29  
      30  /* As test_1, but with an unknown fn_ptr.  */
      31  
      32  void test_1a (void (*fn_ptr) (void *))
      33  {
      34    int i;
      35  
      36    i = 42;
      37    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      38  
      39    fn_ptr (NULL);
      40    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      41    
      42    fn_ptr (&i);
      43    __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */
      44  
      45    i = 17;
      46    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
      47  
      48    /* Even though we're not passing &i to unknown_fn, it escaped
      49       above, so fn_ptr (NULL) could write to it.  */
      50    fn_ptr (NULL);
      51    __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */
      52  }
      53  
      54  int *global_for_test_2;
      55  
      56  void test_2 (void)
      57  {
      58    int i;
      59  
      60    i = 42;
      61    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      62  
      63    global_for_test_2 = &i;
      64    unknown_fn (NULL);
      65    __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */
      66  
      67    global_for_test_2 = NULL;
      68  
      69    i = 17;
      70    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
      71  
      72    /* Even though the global no longer points to i, it escaped
      73       above, so unknown_fn could write to it.  */
      74    unknown_fn (NULL);
      75    __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */
      76  }
      77  
      78  struct used_by_test_3
      79  {
      80    int *int_ptr;
      81  };
      82  
      83  void test_3 (void)
      84  {
      85    int i;
      86  
      87    struct used_by_test_3 s;
      88    s.int_ptr = &i;
      89  
      90    i = 42;
      91    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      92  
      93    unknown_fn (NULL);
      94    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
      95    __analyzer_eval (s.int_ptr == &i); /* { dg-warning "TRUE" } */
      96  
      97    /* i should escape here.  */
      98    unknown_fn (&s);
      99    __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */
     100    __analyzer_eval (s.int_ptr == &i); /* { dg-warning "UNKNOWN" } */
     101  
     102    s.int_ptr = NULL;
     103    __analyzer_eval (s.int_ptr == NULL); /* { dg-warning "TRUE" } */
     104  
     105    i = 17;
     106    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     107  
     108    /* Even though nothing we know about points to i, it escaped
     109       above, so unknown_fn could write to it.  */
     110    unknown_fn (NULL);
     111    __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */
     112  }
     113  
     114  struct used_by_test_4
     115  {
     116    int *int_ptr;
     117  };
     118  
     119  void test_4 (struct used_by_test_4 *st4_ptr)
     120  {
     121    /* Something unknown called "test_4", and hence *st4_ptr has
     122       effectively already escaped.  */
     123  
     124    int i = 42;
     125    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     126  
     127    unknown_fn (NULL);
     128    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     129  
     130    /* Given that *st4_ptr has effectively already escaped, calling
     131       an unknown fn should invalidate our knowledge of i".  */
     132    st4_ptr->int_ptr = &i;
     133    unknown_fn (NULL);
     134    __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */
     135  
     136    /* ...and "&i" should now be treated as having escaped.  */
     137    i = 17;
     138    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     139    st4_ptr->int_ptr = NULL;
     140    unknown_fn (NULL);
     141    __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */
     142  }
     143  
     144  static void __attribute__((noinline))
     145  known_fn (void *ptr)
     146  {
     147    /* Empty.  */
     148  }
     149  
     150  void test_5 (void)
     151  {
     152    int i;
     153  
     154    i = 42;
     155    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     156  
     157    known_fn (&i);
     158    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     159  
     160    i = 17;
     161    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     162  
     163    /* Ensure that we don't consider &i to have escaped.  */
     164    unknown_fn (NULL);
     165    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     166  }
     167  
     168  extern int __attribute__ ((__pure__))
     169  unknown_pure_fn (void *);
     170  
     171  void test_6 (void)
     172  {
     173    int i;
     174  
     175    i = 42;
     176    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     177  
     178    unknown_pure_fn (&i);
     179    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     180  
     181    i = 17;
     182    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     183  
     184    /* Ensure that we don't consider &i to have escaped.  */
     185    unknown_fn (NULL);
     186    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     187  }
     188  
     189  extern void unknown_const_fn (const void *);
     190  
     191  void test_7 (void)
     192  {
     193    int i;
     194  
     195    i = 42;
     196    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     197  
     198    /* &i is passed as a const void *, so i shouldn't be clobbered by
     199       the call.  */
     200    unknown_const_fn (&i);
     201    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     202  
     203    i = 17;
     204    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     205  
     206    /* Ensure that we don't consider &i to have escaped.  */
     207    unknown_fn (NULL);
     208    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     209  }
     210  
     211  struct used_by_test_8
     212  {
     213    int *int_ptr;
     214  };
     215  
     216  void test_8 (void)
     217  {
     218    int i;
     219  
     220    i = 42;
     221    __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */
     222  
     223    struct used_by_test_8 st8;
     224    st8.int_ptr = &i;
     225  
     226    /* Although unknown_const_fn takes a const void *, the
     227       int_ptr is a non-const int *, and so &i should be considered
     228       writable.  */
     229    unknown_const_fn (&st8);
     230    __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */
     231  
     232    i = 17;
     233    __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */
     234  
     235    /* &i should be considered to have escaped.  */
     236    unknown_fn (NULL);
     237    __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */
     238  }