1 #include <stdlib.h>
2 
3 extern void foo(void *ptrA, void *ptrB, void *ptrC) /* { dg-message "argument 1 of 'foo' must be non-null" } */
4   __attribute__((nonnull (1, 3)));
5 
6 extern void bar(void *ptrA, void *ptrB, void *ptrC) /* { dg-message "argument 1 of 'bar' must be non-null" } */
7   __attribute__((nonnull));
8 
9 // TODO: complain about NULL and possible NULL args
10 // FIXME: ought to complain about NULL args
11 
test_1(void * p,void * q,void * r)12 void test_1 (void *p, void *q, void *r)
13 {
14   foo(p, q, r);
15   foo(NULL, q, r);
16   foo(p, NULL, r);
17   foo(p, q, NULL);
18 }
19 
test_1a(void * q,void * r)20 void test_1a (void *q, void *r)
21 {
22   void *p = NULL;
23   foo(p, q, r); /* { dg-warning "use of NULL 'p' where non-null expected" "warning" } */
24   /* { dg-message "argument 1 \\('p'\\) NULL where non-null expected" "note" { target *-*-* } .-1 } */
25 }
26 
test_2(void * p,void * q,void * r)27 void test_2 (void *p, void *q, void *r)
28 {
29   bar(p, q, r);
30   bar(NULL, q, r);
31   bar(p, NULL, r);
32   bar(p, q, NULL);
33 }
34 
test_3(void * q,void * r)35 void test_3 (void *q, void *r)
36 {
37   void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
38 
39   foo(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" "warning" } */
40   /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "note" { target *-*-* } .-1 } */
41 
42   foo(p, q, r);
43 
44   free(p);
45 }
46 
test_4(void * q,void * r)47 void test_4 (void *q, void *r)
48 {
49   void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
50 
51   bar(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" "warning" } */
52   /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "note" { target *-*-* } .-1 } */
53 
54   bar(p, q, r);
55 
56   free(p);
57 }
58 
59 /* Verify that we detect passing NULL to a __attribute__((nonnull)) function
60    when it's called via a function pointer.  */
61 
62 typedef void (*bar_t)(void *ptrA, void *ptrB, void *ptrC);
63 
64 static bar_t __attribute__((noinline))
get_bar(void)65 get_bar (void)
66 {
67   return bar;
68 }
69 
test_5(void * q,void * r)70 void test_5 (void *q, void *r)
71 {
72   void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
73   bar_t cb = get_bar ();
74   cb(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" "warning" } */
75   /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "note" { target *-*-* } .-1 } */
76   /* TODO: do we want an event showing where cb is assigned "bar"?  */
77 
78   cb(p, q, r);
79 
80   free(p);
81 }
82