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