1  #define NULL ((void *)0)
       2  
       3  int test_from_pr77432 (int *a)
       4  {
       5      int b = *a; /* { dg-message "pointer 'a' is dereferenced here" } */
       6      if (a) /* { dg-warning "check of 'a' for NULL after already dereferencing it \\\[-Wanalyzer-deref-before-check\\\]" "warning" } */
       7           /* { dg-message "pointer 'a' is checked for NULL here but it was already dereferenced at \\(1\\)" "final event" { target *-*-* } .-1 } */
       8           return b;
       9      return 0;
      10  }
      11  
      12  int test_1a (int *p, int x)
      13  {
      14    *p = x; /* { dg-message "pointer 'p' is dereferenced here" } */
      15  
      16    if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing it \\\[-Wanalyzer-deref-before-check\\\]" "warning" } */
      17      /* { dg-message "pointer 'p' is checked for NULL here but it was already dereferenced at \\(1\\)" "final event" { target *-*-* } .-1 } */
      18      return 1;
      19    else
      20      return 0;
      21  }
      22  
      23  int test_1b (int *p, int *q)
      24  {
      25    *q = *p; /* { dg-message "8: pointer 'p' is dereferenced here" } */
      26  
      27    if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing it \\\[-Wanalyzer-deref-before-check\\\]" "warning" } */
      28      /* { dg-message "pointer 'p' is checked for NULL here but it was already dereferenced at \\(1\\)" "final event" { target *-*-* } .-1 } */
      29      return 1;
      30    else
      31      return 0;
      32  }
      33  
      34  struct s2
      35  {
      36    int x;
      37    int y;
      38  };
      39  
      40  int test_2a (struct s2 *p)
      41  {
      42    int sum = p->x + p->y; /* { dg-message "pointer 'p' is dereferenced here" } */
      43    if (!p) /* { dg-warning "check of 'p' for NULL after already dereferencing it" } */
      44      __builtin_abort ();
      45    return sum;
      46  }
      47  
      48  int test_2b (struct s2 *p)
      49  {
      50    if (!p)
      51      __builtin_abort ();
      52    int sum = p->x + p->y;
      53    return sum;
      54  }
      55  
      56  struct s3
      57  {
      58    int flag;
      59  };
      60  
      61  extern void err (const char *);
      62  
      63  void test_3 (struct s3 *p)
      64  {
      65    if (p->flag) /* { dg-message "pointer 'p' is dereferenced here" } */
      66      err ("p->flag");
      67    if (!p) /* { dg-warning "check of 'p' for NULL after already dereferencing it" } */
      68      err ("p was NULL");
      69  }
      70  
      71  struct s4
      72  {
      73    struct s4 *m_next;
      74    int m_val;
      75  };
      76  
      77  int test_4 (struct s4 *p)
      78  {
      79    if (p->m_next->m_val > 0) /* { dg-message "pointer '\\*p.m_next' is dereferenced here" } */
      80      return -1;
      81    if (!p->m_next) /* { dg-warning "check of '\\*p.m_next' for NULL after already dereferencing it" } */
      82      return -2;
      83    return p->m_next->m_val;
      84  }
      85  
      86  struct s5
      87  {
      88    const char *str;
      89    int val;
      90  };
      91  
      92  int test_5 (struct s5 *p)
      93  {
      94    __builtin_printf ("%s: %i\n", p->str, p->val); /* { dg-message "pointer 'p' is dereferenced here" } */
      95    if (p != NULL) /* { dg-warning "check of 'p' for NULL after already dereferencing it" } */
      96      return p->val;
      97    return -1;
      98  }
      99  
     100  static int  __attribute__((noinline))
     101  __analyzer_check_ptr (int *p)
     102  {
     103    if (p)
     104      return *p;
     105    else
     106      return 42;
     107  }
     108  
     109  int test_calling_check_ptr_after_deref_1 (int *q)
     110  {
     111    int v = *q; /* { dg-bogus "dereferenced here" } */
     112    v += __analyzer_check_ptr (q);
     113    return v;
     114  }
     115  
     116  int test_calling_check_ptr_after_deref_2 (int *q)
     117  {
     118    int v = *q; /* { dg-bogus "dereferenced here" } */
     119    v += __analyzer_check_ptr (q);
     120    *q = 17;
     121    return v;
     122  }
     123  
     124  int test_calling_check_ptr_after_deref_3 (int *q)
     125  {
     126    int v = *q; /* { dg-message "pointer 'q' is dereferenced here" } */
     127    v += __analyzer_check_ptr (q);
     128    if (q) /* { dg-warning "check of 'q' for NULL after already dereferencing it" } */
     129      *q = 17;
     130    return v;
     131  }
     132  
     133  static int  __attribute__((noinline))
     134  __analyzer_deref_ptr (int *p)
     135  {
     136    return *p;
     137  }
     138  
     139  int test_calling_check_ptr_after_calling_deref_1 (int *q)
     140  {
     141    int v = __analyzer_deref_ptr (q);
     142    v += __analyzer_check_ptr (q);
     143    return v;
     144  }
     145  
     146  int test_calling_check_ptr_after_calling_deref_2 (int *q)
     147  {
     148    int v = __analyzer_deref_ptr (q);
     149    v += __analyzer_check_ptr (q);
     150    *q = 17;
     151    return v;
     152  }
     153  
     154  int test_calling_check_ptr_after_calling_deref_3 (int *q)
     155  {
     156    int v =  __analyzer_deref_ptr (q);
     157    v += __analyzer_check_ptr (q);
     158    if (q)
     159      *q = 17;
     160    return v;
     161  }
     162  
     163  int test_checking_ptr_after_calling_deref (int *q)
     164  {
     165    int v = __analyzer_deref_ptr (q);
     166    if (q)
     167      return 0;
     168    return v;
     169  }
     170  
     171  extern void foo ();
     172  extern void bar ();
     173  extern void baz ();
     174  
     175  int test_cfg_diamond_1 (int *p, int flag)
     176  {
     177    int x;
     178    x = *p; /* { dg-message "pointer 'p' is dereferenced here" } */
     179    if (flag)
     180      foo ();
     181    else
     182      bar ();
     183    if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing it" } */
     184      {
     185        baz ();
     186      }
     187    return x;
     188  }
     189  
     190  int test_cfg_diamond_2 (int *p, int flag)
     191  {
     192    int x = 0;
     193    if (flag)
     194      foo ();
     195    else
     196      {
     197        x = *p;
     198        bar ();
     199      }
     200    if (p) /* { dg-bogus "check of 'p' for NULL after already dereferencing it" } */
     201      {
     202        baz ();
     203      }
     204    return x;
     205  }