llvm-project
226 строк · 8.8 Кб
1// REQUIRES: asserts
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
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
19// CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval1
20#line 100
21int *_Nonnull nonnull_retval1(int *p) {
22// CHECK: nullcheck:
23// CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
24// CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
25// CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]]
26return p;
27// CHECK: ret ptr
28}
29
30#line 190
31void nonnull_arg(int *_Nonnull p) {}
32
33// CHECK-LABEL: define{{.*}} void @{{.*}}call_func_with_nonnull_arg
34#line 200
35void call_func_with_nonnull_arg(int *_Nonnull p) {
36// CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
37// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
38// CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]]
39nonnull_arg(p);
40}
41
42// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign1
43#line 300
44void nonnull_assign1(int *p) {
45// CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
46// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
47// CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]]
48int *_Nonnull local;
49local = p;
50}
51
52// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign2
53#line 400
54void nonnull_assign2(int *p) {
55// CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
56// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
57// CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]]
58int *_Nonnull arr[1];
59arr[0] = p;
60}
61
62struct S1 {
63int *_Nonnull mptr;
64};
65
66// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign3
67#line 500
68void nonnull_assign3(int *p) {
69// CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
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
73struct S1 s;
74s.mptr = p;
75}
76
77// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init1
78#line 600
79void nonnull_init1(int *p) {
80// CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
81// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
82// CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]]
83int *_Nonnull local = p;
84}
85
86// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init2
87#line 700
88void nonnull_init2(int *p) {
89// CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
90// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
91// CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]]
92// CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
93// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
94// CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]]
95int *_Nonnull arr[] = {p, p};
96}
97
98// CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval2
99#line 800
100int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
101int *_Nonnull arg2, //< Test this.
102int *_Nullable arg3, //< Don't test the rest.
103int *arg4,
104int arg5, ...) {
105// CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
106// CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize
107// CHECK: [[ARG2CMP:%.*]] = icmp ne ptr %arg2, null, !nosanitize
108// CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]]
109// CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
110// CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
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]]:
114// CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
115// CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
116// CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]]
117return arg1;
118// CHECK: [[NONULL]]:
119// CHECK-NEXT: ret ptr
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
129// CHECK-LABEL: define internal ptr @"\01+[A objc_clsmethod:]"
130+(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 {
131// CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
132// CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
133// CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
134// CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
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]]:
138// CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
139// CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
140// CHECK: call void @__ubsan_handle_nullability_return{{.*}}
141return arg1;
142// CHECK: [[NONULL]]:
143// CHECK-NEXT: ret ptr
144}
145
146// CHECK-LABEL: define internal ptr @"\01-[A objc_method:]"
147-(int *_Nonnull) objc_method: (int *_Nonnull) arg1 {
148// CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
149// CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
150// CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
151// CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
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]]:
155// CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
156// CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
157// CHECK: call void @__ubsan_handle_nullability_return{{.*}}
158return arg1;
159// CHECK: [[NONULL]]:
160// CHECK-NEXT: ret ptr
161}
162@end
163
164// CHECK-LABEL: define{{.*}} void @{{.*}}call_A
165void call_A(A *a, int *p) {
166// CHECK: [[ICMP:%.*]] = icmp ne ptr [[P1:%.*]], null, !nosanitize
167// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
168// CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
169// CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P1]])
170[a objc_method: p];
171
172// CHECK: [[ICMP:%.*]] = icmp ne ptr [[P2:%.*]], null, !nosanitize
173// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
174// CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
175// CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P2]])
176[A objc_clsmethod: p];
177}
178
179void 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.
190NSObject *get_nonnull_error(void) {
191// Use nil for convenience. The actual object doesn't matter.
192return (NSObject *)NULL;
193}
194
195NSObject *_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
198NSObject *_Nullable (^foo)(void) = ^(void) {
199if (flag) {
200// Clang should not infer a nonnull return value for this block when this
201// call is present.
202return get_nonnull_error();
203} else {
204return (NSObject *)NULL;
205}
206};
207return foo();
208}
209
210#pragma clang assume_nonnull end
211
212int main(void) {
213nonnull_retval1(INULL);
214nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0);
215call_func_with_nonnull_arg(INNULL);
216nonnull_assign1(INULL);
217nonnull_assign2(INULL);
218nonnull_assign3(INULL);
219nonnull_init1(INULL);
220nonnull_init2(INULL);
221call_A((A *)NULL, INULL);
222dont_crash(INNULL, NULL);
223no_null_return_value_diagnostic(0);
224no_null_return_value_diagnostic(1);
225return 0;
226}
227