150
|
1 // REQUIRES: asserts
|
252
|
2 // RUN: %clang_cc1 -no-enable-noundef-analysis -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
|
|
3 // RUN: %clang_cc1 -no-enable-noundef-analysis -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
|
150
|
4
|
|
5 // CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6
|
|
6 // CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23
|
|
7 // CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9
|
|
8 // CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10
|
|
9 // CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 506, i32 10
|
|
10 // CHECK: [[NONNULL_INIT1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 604, i32 25
|
|
11 // CHECK: [[NONNULL_INIT2_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 26
|
|
12 // CHECK: [[NONNULL_INIT2_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 29
|
|
13 // CHECK: [[NONNULL_RV_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 800, i32 6
|
|
14
|
|
15 #define NULL ((void *)0)
|
|
16 #define INULL ((int *)NULL)
|
|
17 #define INNULL ((int *_Nonnull)NULL)
|
|
18
|
252
|
19 // CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval1
|
150
|
20 #line 100
|
|
21 int *_Nonnull nonnull_retval1(int *p) {
|
252
|
22 // CHECK: nullcheck:
|
|
23 // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
|
150
|
24 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
25 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]]
|
|
26 return p;
|
252
|
27 // CHECK: ret ptr
|
150
|
28 }
|
|
29
|
|
30 #line 190
|
|
31 void nonnull_arg(int *_Nonnull p) {}
|
|
32
|
221
|
33 // CHECK-LABEL: define{{.*}} void @{{.*}}call_func_with_nonnull_arg
|
150
|
34 #line 200
|
|
35 void call_func_with_nonnull_arg(int *_Nonnull p) {
|
252
|
36 // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
|
150
|
37 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
38 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]]
|
|
39 nonnull_arg(p);
|
|
40 }
|
|
41
|
221
|
42 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign1
|
150
|
43 #line 300
|
|
44 void nonnull_assign1(int *p) {
|
252
|
45 // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
|
150
|
46 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
47 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]]
|
|
48 int *_Nonnull local;
|
|
49 local = p;
|
|
50 }
|
|
51
|
221
|
52 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign2
|
150
|
53 #line 400
|
|
54 void nonnull_assign2(int *p) {
|
252
|
55 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
|
150
|
56 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
57 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]]
|
|
58 int *_Nonnull arr[1];
|
|
59 arr[0] = p;
|
|
60 }
|
|
61
|
|
62 struct S1 {
|
|
63 int *_Nonnull mptr;
|
|
64 };
|
|
65
|
221
|
66 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign3
|
150
|
67 #line 500
|
|
68 void nonnull_assign3(int *p) {
|
252
|
69 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
|
150
|
70 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
71 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]]
|
|
72 // CHECK-NOT: call void @__ubsan_handle_type_mismatch
|
|
73 struct S1 s;
|
|
74 s.mptr = p;
|
|
75 }
|
|
76
|
221
|
77 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init1
|
150
|
78 #line 600
|
|
79 void nonnull_init1(int *p) {
|
252
|
80 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
|
150
|
81 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
82 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]]
|
|
83 int *_Nonnull local = p;
|
|
84 }
|
|
85
|
221
|
86 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init2
|
150
|
87 #line 700
|
|
88 void nonnull_init2(int *p) {
|
252
|
89 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
|
150
|
90 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
91 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]]
|
252
|
92 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
|
150
|
93 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
94 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]]
|
|
95 int *_Nonnull arr[] = {p, p};
|
|
96 }
|
|
97
|
252
|
98 // CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval2
|
150
|
99 #line 800
|
|
100 int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
|
|
101 int *_Nonnull arg2, //< Test this.
|
|
102 int *_Nullable arg3, //< Don't test the rest.
|
|
103 int *arg4,
|
|
104 int arg5, ...) {
|
252
|
105 // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
|
150
|
106 // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize
|
252
|
107 // CHECK: [[ARG2CMP:%.*]] = icmp ne ptr %arg2, null, !nosanitize
|
150
|
108 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]]
|
252
|
109 // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
|
|
110 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
|
150
|
111 // CHECK-NEXT: [[DO_RV_CHECK_3:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK_2]]
|
|
112 // CHECK: br i1 [[DO_RV_CHECK_3]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
|
|
113 // CHECK: [[NULL]]:
|
252
|
114 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
|
150
|
115 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
116 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]]
|
|
117 return arg1;
|
|
118 // CHECK: [[NONULL]]:
|
252
|
119 // CHECK-NEXT: ret ptr
|
150
|
120 }
|
|
121
|
|
122 @interface A
|
|
123 +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1;
|
|
124 -(int *_Nonnull) objc_method: (int *_Nonnull) arg1;
|
|
125 @end
|
|
126
|
|
127 @implementation A
|
|
128
|
252
|
129 // CHECK-LABEL: define internal ptr @"\01+[A objc_clsmethod:]"
|
150
|
130 +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 {
|
252
|
131 // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
|
150
|
132 // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
|
252
|
133 // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
|
|
134 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
|
150
|
135 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]]
|
|
136 // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
|
|
137 // CHECK: [[NULL]]:
|
252
|
138 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
|
150
|
139 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
140 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
|
|
141 return arg1;
|
|
142 // CHECK: [[NONULL]]:
|
252
|
143 // CHECK-NEXT: ret ptr
|
150
|
144 }
|
|
145
|
252
|
146 // CHECK-LABEL: define internal ptr @"\01-[A objc_method:]"
|
150
|
147 -(int *_Nonnull) objc_method: (int *_Nonnull) arg1 {
|
252
|
148 // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
|
150
|
149 // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
|
252
|
150 // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
|
|
151 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
|
150
|
152 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]]
|
|
153 // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
|
|
154 // CHECK: [[NULL]]:
|
252
|
155 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
|
150
|
156 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
157 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
|
|
158 return arg1;
|
|
159 // CHECK: [[NONULL]]:
|
252
|
160 // CHECK-NEXT: ret ptr
|
150
|
161 }
|
|
162 @end
|
|
163
|
221
|
164 // CHECK-LABEL: define{{.*}} void @{{.*}}call_A
|
150
|
165 void call_A(A *a, int *p) {
|
252
|
166 // CHECK: [[ICMP:%.*]] = icmp ne ptr [[P1:%.*]], null, !nosanitize
|
150
|
167 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
168 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
|
252
|
169 // CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P1]])
|
150
|
170 [a objc_method: p];
|
|
171
|
252
|
172 // CHECK: [[ICMP:%.*]] = icmp ne ptr [[P2:%.*]], null, !nosanitize
|
150
|
173 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
|
|
174 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
|
252
|
175 // CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P2]])
|
150
|
176 [A objc_clsmethod: p];
|
|
177 }
|
|
178
|
|
179 void dont_crash(int *_Nonnull p, ...) {}
|
|
180
|
|
181 @protocol NSObject
|
|
182 - (id)init;
|
|
183 @end
|
|
184 @interface NSObject <NSObject> {}
|
|
185 @end
|
|
186
|
|
187 #pragma clang assume_nonnull begin
|
|
188
|
|
189 /// Create a "NSObject * _Nonnull" instance.
|
236
|
190 NSObject *get_nonnull_error(void) {
|
150
|
191 // Use nil for convenience. The actual object doesn't matter.
|
|
192 return (NSObject *)NULL;
|
|
193 }
|
|
194
|
|
195 NSObject *_Nullable no_null_return_value_diagnostic(int flag) {
|
|
196 // CHECK-LABEL: define internal {{.*}}no_null_return_value_diagnostic{{i?}}_block_invoke
|
|
197 // CHECK-NOT: @__ubsan_handle_nullability_return
|
236
|
198 NSObject *_Nullable (^foo)(void) = ^(void) {
|
150
|
199 if (flag) {
|
|
200 // Clang should not infer a nonnull return value for this block when this
|
|
201 // call is present.
|
|
202 return get_nonnull_error();
|
|
203 } else {
|
|
204 return (NSObject *)NULL;
|
|
205 }
|
|
206 };
|
|
207 return foo();
|
|
208 }
|
|
209
|
|
210 #pragma clang assume_nonnull end
|
|
211
|
236
|
212 int main(void) {
|
150
|
213 nonnull_retval1(INULL);
|
|
214 nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0);
|
|
215 call_func_with_nonnull_arg(INNULL);
|
|
216 nonnull_assign1(INULL);
|
|
217 nonnull_assign2(INULL);
|
|
218 nonnull_assign3(INULL);
|
|
219 nonnull_init1(INULL);
|
|
220 nonnull_init2(INULL);
|
|
221 call_A((A *)NULL, INULL);
|
|
222 dont_crash(INNULL, NULL);
|
|
223 no_null_return_value_diagnostic(0);
|
|
224 no_null_return_value_diagnostic(1);
|
|
225 return 0;
|
|
226 }
|