1  #include "analyzer-decls.h"
       2  
       3  #include <stdlib.h>
       4  
       5  extern void foo(void *ptrA, void *ptrB, void *ptrC) /* { dg-message "argument 1 of 'foo' must be non-null" } */
       6    __attribute__((nonnull (1, 3)));
       7  
       8  extern void bar(void *ptrA, void *ptrB, void *ptrC) /* { dg-message "argument 1 of 'bar' must be non-null" } */
       9    __attribute__((nonnull));
      10  
      11  // TODO: complain about NULL and possible NULL args
      12  // FIXME: ought to complain about NULL args
      13  
      14  void test_1 (void *p, void *q, void *r)
      15  {
      16    foo(p, q, r);
      17    foo(NULL, q, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */
      18    /* { dg-message "argument 1 NULL where non-null expected" "note" { target *-*-* } .-1 } */
      19  }
      20  
      21  void test_1a (void *q, void *r)
      22  {
      23    void *p = NULL;
      24    foo(p, q, r); /* { dg-warning "use of NULL 'p' where non-null expected" "warning" } */
      25    /* { dg-message "argument 1 \\('p'\\) NULL where non-null expected" "note" { target *-*-* } .-1 } */
      26  }
      27  
      28  void test_1b (void *p, void *r)
      29  {
      30    foo(p, NULL, r);
      31  }
      32  
      33  void test_1c (void *p, void *q, void *r)
      34  {
      35    foo(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" } */
      36  }
      37  
      38  void test_2a (void *p, void *q, void *r)
      39  {
      40    bar(p, q, r);
      41  }
      42  
      43  void test_2b (void *p, void *q, void *r)
      44  {
      45    bar(p, NULL, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */
      46    /* { dg-message "argument 2 NULL where non-null expected" "note" { target *-*-* } .-1 } */
      47  }
      48  
      49  void test_2c (void *p, void *q, void *r)
      50  {
      51    bar(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" "warning" } */
      52  }
      53  
      54  void test_3 (void *q, void *r)
      55  {
      56    void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
      57  
      58    foo(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" "warning" } */
      59    /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "note" { target *-*-* } .-1 } */
      60  
      61    foo(p, q, r);
      62  
      63    free(p);
      64  }
      65  
      66  void test_4 (void *q, void *r)
      67  {
      68    void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
      69  
      70    bar(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" "warning" } */
      71    /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "note" { target *-*-* } .-1 } */
      72  
      73    bar(p, q, r);
      74  
      75    free(p);
      76  }
      77  
      78  /* Verify that we detect passing NULL to a __attribute__((nonnull)) function
      79     when it's called via a function pointer.  */
      80  
      81  typedef void (*bar_t)(void *ptrA, void *ptrB, void *ptrC);
      82  
      83  static bar_t __attribute__((noinline))
      84  get_bar (void)
      85  {
      86    return bar;
      87  }
      88  
      89  void test_5 (void *q, void *r)
      90  {
      91    void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
      92    bar_t cb = get_bar ();
      93    cb(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" "warning" } */
      94    /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "note" { target *-*-* } .-1 } */
      95    /* TODO: do we want an event showing where cb is assigned "bar"?  */
      96  
      97    cb(p, q, r);
      98  
      99    free(p);
     100  }
     101  
     102  __attribute__((nonnull(1, 3)))
     103  void test_6 (void *p, void *q, void *r)
     104  {
     105    __analyzer_eval (p != NULL); /* { dg-warning "TRUE" } */
     106    __analyzer_eval (q != NULL); /* { dg-warning "UNKNOWN" } */
     107    __analyzer_eval (r != NULL); /* { dg-warning "TRUE" } */
     108  }
     109  
     110  __attribute__((nonnull))
     111  void test_7 (void *p, void *q, void *r)
     112  {
     113    __analyzer_eval (p != NULL); /* { dg-warning "TRUE" } */
     114    __analyzer_eval (q != NULL); /* { dg-warning "TRUE" } */
     115    __analyzer_eval (r != NULL); /* { dg-warning "TRUE" } */
     116  }