1 | #include "nonnull.h" |
2 | |
3 | // RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wno-objc-root-class %s |
4 | // REQUIRES: LP64 |
5 | |
6 | @class NSObject; |
7 | |
8 | NONNULL_ATTR |
9 | int f1(int x); // no warning |
10 | int f2(int *x) __attribute__ ((nonnull (1))); |
11 | int f3(int *x) __attribute__ ((nonnull (0))); // expected-error {{'nonnull' attribute parameter 1 is out of bounds}} |
12 | int f4(int *x, int *y) __attribute__ ((nonnull (1,2))); |
13 | int f5(int *x, int *y) __attribute__ ((nonnull (2,1))); |
14 | int f6(NSObject *x) __attribute__ ((nonnull (1))); // no-warning |
15 | int f7(NSObject *x) __attribute__ ((nonnull)); // no-warning |
16 | |
17 | |
18 | extern void func1 (void (^block1)(), void (^block2)(), int) __attribute__((nonnull)); |
19 | |
20 | extern void func3 (void (^block1)(), int, void (^block2)(), int) |
21 | __attribute__((nonnull(1,3))); |
22 | |
23 | extern void func4 (void (^block1)(), void (^block2)()) __attribute__((nonnull(1))) |
24 | __attribute__((nonnull(2))); |
25 | |
26 | void func6(); |
27 | void func7(); |
28 | |
29 | void |
30 | foo (int i1, int i2, int i3, void (^cp1)(), void (^cp2)(), void (^cp3)()) |
31 | { |
32 | func1(cp1, cp2, i1); |
33 | |
34 | func1(0, cp2, i1); // expected-warning {{null passed to a callee that requires a non-null argument}} |
35 | func1(cp1, 0, i1); // expected-warning {{null passed to a callee that requires a non-null argument}} |
36 | func1(cp1, cp2, 0); |
37 | |
38 | |
39 | func3(0, i2, cp3, i3); // expected-warning {{null passed to a callee that requires a non-null argument}} |
40 | func3(cp3, i2, 0, i3); // expected-warning {{null passed to a callee that requires a non-null argument}} |
41 | |
42 | func4(0, cp1); // expected-warning {{null passed to a callee that requires a non-null argument}} |
43 | func4(cp1, 0); // expected-warning {{null passed to a callee that requires a non-null argument}} |
44 | |
45 | // Shouldn't these emit warnings? Clang doesn't, and neither does GCC. It |
46 | // seems that the checking should handle Objective-C pointers. |
47 | func6((NSObject*) 0); // no-warning |
48 | func7((NSObject*) 0); // no-warning |
49 | } |
50 | |
51 | void func5(int) NONNULL_ATTR; // no warning |
52 | |
53 | // rdar://6857843 |
54 | struct dispatch_object_s { |
55 | int x; |
56 | }; |
57 | |
58 | typedef union { |
59 | long first; |
60 | struct dispatch_object_s *_do; |
61 | } dispatch_object_t __attribute__((transparent_union)); |
62 | |
63 | __attribute__((nonnull)) |
64 | void _dispatch_queue_push_list(dispatch_object_t _head); // no warning |
65 | |
66 | void func6(dispatch_object_t _head) { |
67 | _dispatch_queue_push_list(0); // expected-warning {{null passed to a callee that requires a non-null argument}} |
68 | _dispatch_queue_push_list(_head._do); // no warning |
69 | } |
70 | |
71 | // rdar://9287695 |
72 | #define NULL (void*)0 |
73 | |
74 | @interface NSObject |
75 | - (void)doSomethingWithNonNullPointer:(void *)ptr :(int)iarg : (void*)ptr1 __attribute__((nonnull(1, 3))); |
76 | + (void)doSomethingClassyWithNonNullPointer:(void *)ptr __attribute__((nonnull(1))); |
77 | - (void*)returnsCNonNull __attribute__((returns_nonnull)); // no-warning |
78 | - (id)returnsObjCNonNull __attribute__((returns_nonnull)); // no-warning |
79 | - (int)returnsIntNonNull __attribute__((returns_nonnull)); // expected-warning {{'returns_nonnull' attribute only applies to return values that are pointers}} |
80 | @end |
81 | |
82 | extern void DoSomethingNotNull(void *db) __attribute__((nonnull(1))); |
83 | |
84 | @interface IMP |
85 | { |
86 | void * vp; |
87 | } |
88 | - (void*) testRetNull __attribute__((returns_nonnull)); |
89 | @end |
90 | |
91 | @implementation IMP |
92 | - (void) Meth { |
93 | NSObject *object; |
94 | [object doSomethingWithNonNullPointer:NULL:1:NULL]; // expected-warning 2 {{null passed to a callee that requires a non-null argument}} |
95 | [object doSomethingWithNonNullPointer:vp:1:NULL]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
96 | [NSObject doSomethingClassyWithNonNullPointer:NULL]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
97 | DoSomethingNotNull(NULL); // expected-warning {{null passed to a callee that requires a non-null argument}} |
98 | [object doSomethingWithNonNullPointer:vp:1:vp]; |
99 | } |
100 | - (void*) testRetNull { |
101 | return 0; // expected-warning {{null returned from method that requires a non-null return value}} |
102 | } |
103 | @end |
104 | |
105 | __attribute__((objc_root_class)) |
106 | @interface TestNonNullParameters |
107 | - (void) doNotPassNullParameterNonPointerArg:(int)__attribute__((nonnull))x; // expected-warning {{'nonnull' attribute only applies to pointer arguments}} |
108 | - (void) doNotPassNullParameter:(id)__attribute__((nonnull))x; |
109 | - (void) doNotPassNullParameterArgIndex:(id)__attribute__((nonnull(1)))x; // expected-warning {{'nonnull' attribute when used on parameters takes no arguments}} |
110 | - (void) doNotPassNullOnMethod:(id)x __attribute__((nonnull(1))); |
111 | @end |
112 | |
113 | void test(TestNonNullParameters *f) { |
114 | [f doNotPassNullParameter:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
115 | [f doNotPassNullParameterArgIndex:0]; // no-warning |
116 | [f doNotPassNullOnMethod:0]; // expected-warning {{null passed to a callee that requires a non-null argument}} |
117 | } |
118 | |
119 | |
120 | void PR18795(int (^g)(const char *h, ...) __attribute__((nonnull(1))) __attribute__((nonnull))) { |
121 | g(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
122 | } |
123 | void PR18795_helper() { |
124 | PR18795(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
125 | } |
126 | |
127 | void (^PR23117)(int *) = ^(int *p1) __attribute__((nonnull(1))) {}; |
128 | |
129 | typedef int *intptr; |
130 | #pragma clang assume_nonnull begin |
131 | intptr a, b; |
132 | intptr c, (*d)(); |
133 | #pragma clang assume_nonnull end |
134 | |