Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 1 | // REQUIRES: asserts |
| 2 | // RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s |
| 3 | |
| 4 | // CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 109, i32 1 {{.*}} i32 100, i32 6 |
| 5 | // CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23 |
| 6 | // CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9 |
| 7 | // CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10 |
| 8 | // CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 505, i32 10 |
| 9 | // CHECK: [[NONNULL_INIT1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 604, i32 25 |
| 10 | // CHECK: [[NONNULL_INIT2_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 26 |
| 11 | // CHECK: [[NONNULL_INIT2_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 29 |
| 12 | // CHECK: [[NONNULL_RV_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 817, i32 1 {{.*}} i32 800, i32 6 |
| 13 | |
| 14 | #define NULL ((void *)0) |
| 15 | |
| 16 | // CHECK-LABEL: define i32* @nonnull_retval1 |
| 17 | #line 100 |
| 18 | int *_Nonnull nonnull_retval1(int *p) { |
| 19 | // CHECK: br i1 true, label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
| 20 | // CHECK: [[NULL]]: |
| 21 | // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize |
| 22 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
Vedant Kumar | 2b9f48a | 2017-03-14 16:48:29 +0000 | [diff] [blame^] | 23 | // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]] |
Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 24 | return p; |
| 25 | // CHECK: [[NONULL]]: |
| 26 | // CHECK-NEXT: ret i32* |
| 27 | } |
| 28 | |
| 29 | #line 190 |
| 30 | void nonnull_arg(int *_Nonnull p) {} |
| 31 | |
| 32 | // CHECK-LABEL: define void @call_func_with_nonnull_arg |
| 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 | |
| 41 | // CHECK-LABEL: define void @nonnull_assign1 |
| 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 | |
| 51 | // CHECK-LABEL: define void @nonnull_assign2 |
| 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 | |
| 65 | // CHECK-LABEL: define void @nonnull_assign3 |
| 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]] |
| 71 | struct S1 s; |
| 72 | s.mptr = p; |
| 73 | } |
| 74 | |
| 75 | // CHECK-LABEL: define void @nonnull_init1 |
| 76 | #line 600 |
| 77 | void nonnull_init1(int *p) { |
| 78 | // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize |
| 79 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
| 80 | // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]] |
| 81 | int *_Nonnull local = p; |
| 82 | } |
| 83 | |
| 84 | // CHECK-LABEL: define void @nonnull_init2 |
| 85 | #line 700 |
| 86 | void nonnull_init2(int *p) { |
| 87 | // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize |
| 88 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
| 89 | // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]] |
| 90 | // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize |
| 91 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
| 92 | // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]] |
| 93 | int *_Nonnull arr[] = {p, p}; |
| 94 | } |
| 95 | |
| 96 | // CHECK-LABEL: define i32* @nonnull_retval2 |
| 97 | #line 800 |
| 98 | int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. |
| 99 | int *_Nonnull arg2, //< Test this. |
| 100 | int *_Nullable arg3, //< Don't test the rest. |
| 101 | int *arg4, |
| 102 | int arg5, ...) { |
| 103 | // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize |
| 104 | // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize |
| 105 | // CHECK: [[ARG2CMP:%.*]] = icmp ne i32* %arg2, null, !nosanitize |
| 106 | // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]] |
| 107 | // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
| 108 | // CHECK: [[NULL]]: |
| 109 | // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize |
| 110 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
Vedant Kumar | 2b9f48a | 2017-03-14 16:48:29 +0000 | [diff] [blame^] | 111 | // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]] |
Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 112 | return arg1; |
| 113 | // CHECK: [[NONULL]]: |
| 114 | // CHECK-NEXT: ret i32* |
| 115 | } |
| 116 | |
| 117 | @interface A |
| 118 | +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1; |
| 119 | -(int *_Nonnull) objc_method: (int *_Nonnull) arg1; |
| 120 | @end |
| 121 | |
| 122 | @implementation A |
| 123 | |
| 124 | // CHECK-LABEL: define internal i32* @"\01+[A objc_clsmethod:]" |
| 125 | +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 { |
| 126 | // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize |
| 127 | // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] |
| 128 | // CHECK: br i1 [[DO_RV_CHECK]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
| 129 | // CHECK: [[NULL]]: |
| 130 | // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize |
| 131 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
Vedant Kumar | 2b9f48a | 2017-03-14 16:48:29 +0000 | [diff] [blame^] | 132 | // CHECK: call void @__ubsan_handle_nullability_return{{.*}} |
Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 133 | return arg1; |
| 134 | // CHECK: [[NONULL]]: |
| 135 | // CHECK-NEXT: ret i32* |
| 136 | } |
| 137 | |
| 138 | // CHECK-LABEL: define internal i32* @"\01-[A objc_method:]" |
| 139 | -(int *_Nonnull) objc_method: (int *_Nonnull) arg1 { |
| 140 | // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize |
| 141 | // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] |
| 142 | // CHECK: br i1 [[DO_RV_CHECK]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
| 143 | // CHECK: [[NULL]]: |
| 144 | // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize |
| 145 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
Vedant Kumar | 2b9f48a | 2017-03-14 16:48:29 +0000 | [diff] [blame^] | 146 | // CHECK: call void @__ubsan_handle_nullability_return{{.*}} |
Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 147 | return arg1; |
| 148 | // CHECK: [[NONULL]]: |
| 149 | // CHECK-NEXT: ret i32* |
| 150 | } |
| 151 | @end |
| 152 | |
| 153 | // CHECK-LABEL: define void @call_A |
| 154 | void call_A(A *a, int *p) { |
| 155 | // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize |
| 156 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
Vedant Kumar | 2b9f48a | 2017-03-14 16:48:29 +0000 | [diff] [blame^] | 157 | // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize |
Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 158 | // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P1]]) |
| 159 | [a objc_method: p]; |
| 160 | |
| 161 | // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize |
| 162 | // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
Vedant Kumar | 2b9f48a | 2017-03-14 16:48:29 +0000 | [diff] [blame^] | 163 | // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize |
Vedant Kumar | 42c17ec | 2017-03-14 01:56:34 +0000 | [diff] [blame] | 164 | // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P2]]) |
| 165 | [A objc_clsmethod: p]; |
| 166 | } |
| 167 | |
| 168 | void dont_crash(int *_Nonnull p, ...) {} |
| 169 | |
| 170 | int main() { |
| 171 | nonnull_retval1(NULL); |
| 172 | nonnull_retval2(NULL, NULL, NULL, NULL, 0, 0, 0, 0); |
| 173 | call_func_with_nonnull_arg(NULL); |
| 174 | nonnull_assign1(NULL); |
| 175 | nonnull_assign2(NULL); |
| 176 | nonnull_assign3(NULL); |
| 177 | nonnull_init1(NULL); |
| 178 | nonnull_init2(NULL); |
| 179 | call_A(NULL, NULL); |
| 180 | dont_crash(NULL, NULL); |
| 181 | return 0; |
| 182 | } |