1// RUN: %clang_analyze_cc1 -analyzer-checker=core -w -verify %s
2
3@interface MyObject
4- (void)takePointer:(void *)ptr __attribute__((nonnull(1)));
5- (void)takePointerArg:(void *)__attribute__((nonnull)) ptr;
6
7@end
8
9void testNonNullMethod(int *p, MyObject *obj) {
10  if (p)
11    return;
12  [obj takePointer:p]; // expected-warning{{nonnull}}
13}
14
15
16@interface Subclass : MyObject
17// [[nonnull]] is an inherited attribute.
18- (void)takePointer:(void *)ptr;
19@end
20
21void testSubclass(int *p, Subclass *obj) {
22  if (p)
23    return;
24  [obj takePointer:p]; // expected-warning{{nonnull}}
25}
26
27void testSubclassArg(int *p, Subclass *obj) {
28  if (p)
29    return;
30  [obj takePointerArg:p]; // expected-warning{{nonnull}}
31}
32
33
34union rdar16153464_const_cp_t {
35  const struct rdar16153464_cczp *zp;
36  const struct rdar16153464_cczp_prime *prime;
37} __attribute__((transparent_union));
38
39struct rdar16153464_header {
40  union rdar16153464_const_cp_t cp;
41  unsigned char pad[16 - sizeof(union rdar16153464_const_cp_t *)];
42} __attribute__((aligned(16)));
43
44
45struct rdar16153464_full_ctx {
46  struct rdar16153464_header hdr;
47} __attribute__((aligned(16)));
48
49
50struct rdar16153464_pub_ctx {
51  struct rdar16153464_header hdr;
52} __attribute__((aligned(16)));
53
54
55union rdar16153464_full_ctx_t {
56  struct rdar16153464_full_ctx *_full;
57  struct rdar16153464_header *hdr;
58  struct rdar16153464_body *body;
59  struct rdar16153464_public *pub;
60} __attribute__((transparent_union));
61
62union rdar16153464_pub_ctx_t {
63  struct rdar16153464_pub_ctx *_pub;
64  struct rdar16153464_full_ctx *_full;
65  struct rdar16153464_header *hdr;
66  struct rdar16153464_body *body;
67  struct rdar16153464_public *pub;
68  union rdar16153464_full_ctx_t innert;
69} __attribute__((transparent_union));
70
71int rdar16153464(union rdar16153464_full_ctx_t inner)
72{
73  extern void rdar16153464_check(union rdar16153464_pub_ctx_t outer) __attribute((nonnull(1)));
74  rdar16153464_check((union rdar16153464_pub_ctx_t){ .innert = inner }); // no-warning
75  rdar16153464_check(inner); // no-warning
76  rdar16153464_check(0); // expected-warning{{nonnull}}
77}
78
79// Multiple attributes, the basic case
80void multipleAttributes_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(2)));
81
82void testMultiple_1(void) {
83  char c;
84  multipleAttributes_1(&c, &c); // no-warning
85}
86
87void testMultiple_2(void) {
88  char c;
89  multipleAttributes_1(0, &c); // expected-warning{{nonnull}}
90}
91
92void testMultiple_3(void) {
93  char c;
94  multipleAttributes_1(&c, 0); // expected-warning{{nonnull}}
95}
96
97void testMultiple_4(void) {
98  multipleAttributes_1(0, 0);// expected-warning{{nonnull}}
99}
100
101// Multiple attributes, multiple prototypes
102void multipleAttributes_2(char *p, char *q) __attribute((nonnull(1)));
103void multipleAttributes_2(char *p, char *q) __attribute((nonnull(2)));
104
105void testMultiple_5(void) {
106  char c;
107  multipleAttributes_2(0, &c);// expected-warning{{nonnull}}
108}
109
110void testMultiple_6(void) {
111  char c;
112  multipleAttributes_2(&c, 0);// expected-warning{{nonnull}}
113}
114
115void testMultiple_7(void) {
116  multipleAttributes_2(0, 0);// expected-warning{{nonnull}}
117}
118
119// Multiple attributes, same index
120void multipleAttributes_3(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(1)));
121
122void testMultiple_8(void) {
123  char c;
124  multipleAttributes_3(0, &c); // expected-warning{{nonnull}}
125}
126
127void testMultiple_9(void) {
128  char c;
129  multipleAttributes_3(&c, 0); // no-warning
130}
131
132// Multiple attributes, the middle argument is missing an attribute
133void multipleAttributes_4(char *p, char *q, char *r) __attribute((nonnull(1))) __attribute((nonnull(3)));
134
135void testMultiple_10(void) {
136  char c;
137  multipleAttributes_4(0, &c, &c); // expected-warning{{nonnull}}
138}
139
140void testMultiple_11(void) {
141  char c;
142  multipleAttributes_4(&c, 0, &c); // no-warning
143}
144
145void testMultiple_12(void) {
146  char c;
147  multipleAttributes_4(&c, &c, 0); // expected-warning{{nonnull}}
148}
149
150
151// Multiple attributes, when the last is without index
152void multipleAttributes_all_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull));
153
154void testMultiple_13(void) {
155  char c;
156  multipleAttributes_all_1(0, &c); // expected-warning{{nonnull}}
157}
158
159void testMultiple_14(void) {
160  char c;
161  multipleAttributes_all_1(&c, 0); // expected-warning{{nonnull}}
162}
163
164// Multiple attributes, when the first is without index
165void multipleAttributes_all_2(char *p, char *q) __attribute((nonnull)) __attribute((nonnull(2)));
166
167void testMultiple_15(void) {
168  char c;
169  multipleAttributes_all_2(0, &c); // expected-warning{{nonnull}}
170}
171
172void testMultiple_16(void) {
173  char c;
174  multipleAttributes_all_2(&c, 0); // expected-warning{{nonnull}}
175}
176
177void testVararg(int k, void *p) {
178  extern void testVararg_check(int, ...) __attribute__((nonnull));
179  void *n = 0;
180  testVararg_check(0);
181  testVararg_check(1, p);
182  if (k == 1)
183    testVararg_check(1, n); // expected-warning{{nonnull}}
184  testVararg_check(2, p, p);
185  if (k == 2)
186    testVararg_check(2, n, p); // expected-warning{{nonnull}}
187  if (k == 3)
188    testVararg_check(2, p, n); // expected-warning{{nonnull}}
189}
190
191void testNotPtr() {
192  struct S { int a; int b; int c; } s = {};
193  extern void testNotPtr_check(struct S, int) __attribute__((nonnull(1, 2)));
194  testNotPtr_check(s, 0);
195}
196