Roman Lebedev | 62debd80 | 2018-10-30 21:58:56 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK |
| 2 | // RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fno-sanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE |
| 3 | // RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER |
| 4 | // RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE |
| 5 | |
| 6 | // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" } |
| 7 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" } |
| 8 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_INT]], i8 3 } |
| 9 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_INT]], i8 3 } |
| 10 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" } |
| 11 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 } |
| 12 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" } |
| 13 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_CHAR]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 } |
| 14 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UNSIGNED_CHAR]], {{.*}}* @[[SIGNED_CHAR]], i8 3 } |
| 15 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 10 }, {{.*}}* @[[SIGNED_CHAR]], {{.*}}* @[[UNSIGNED_INT]], i8 3 } |
| 16 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 } |
| 17 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 } |
| 18 | // CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" } |
| 19 | // CHECK-SANITIZE-ANYRECOVER: @[[INT32:.*]] = {{.*}} c"'int32_t' (aka 'int')\00" } |
| 20 | // CHECK-SANITIZE-ANYRECOVER: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[INT32]], i8 3 } |
| 21 | |
| 22 | // ========================================================================== // |
| 23 | // The expected true-positives. |
| 24 | // These are implicit, potentially sign-altering, conversions. |
| 25 | // ========================================================================== // |
| 26 | |
| 27 | // These 3 result (after optimizations) in simple 'icmp sge i32 %src, 0'. |
| 28 | |
| 29 | // CHECK-LABEL: @unsigned_int_to_signed_int |
| 30 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 31 | signed int unsigned_int_to_signed_int(unsigned int src) { |
| 32 | // CHECK: %[[SRC_ADDR:.*]] = alloca i32 |
| 33 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 34 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 35 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize |
| 36 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 37 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 38 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 39 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 40 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 41 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 42 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 43 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 44 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 45 | // CHECK-SANITIZE: [[CONT]]: |
| 46 | // CHECK-NEXT: ret i32 %[[DST]] |
| 47 | // CHECK-NEXT: } |
| 48 | #line 100 |
| 49 | return src; |
| 50 | } |
| 51 | |
| 52 | // CHECK-LABEL: @signed_int_to_unsigned_int |
| 53 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 54 | unsigned int signed_int_to_unsigned_int(signed int src) { |
| 55 | // CHECK: %[[SRC_ADDR:.*]] = alloca i32 |
| 56 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 57 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 58 | // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize |
| 59 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize |
| 60 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 61 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 62 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 63 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 64 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 65 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 66 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 67 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 68 | // CHECK-SANITIZE: [[CONT]]: |
| 69 | // CHECK-NEXT: ret i32 %[[DST]] |
| 70 | // CHECK-NEXT: } |
| 71 | #line 200 |
| 72 | return src; |
| 73 | } |
| 74 | |
| 75 | // CHECK-LABEL: @signed_int_to_unsigned_char |
| 76 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 77 | unsigned char signed_int_to_unsigned_char(signed int src) { |
| 78 | // CHECK: %[[SRC_ADDR:.*]] = alloca i32 |
| 79 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 80 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 81 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 82 | // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize |
| 83 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize |
| 84 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 85 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 86 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 87 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 88 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 89 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 90 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 91 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 92 | // CHECK-SANITIZE: [[CONT]]: |
| 93 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 94 | // CHECK-NEXT: } |
| 95 | #line 300 |
| 96 | return src; |
| 97 | } |
| 98 | |
| 99 | // These 3 result (after optimizations) in simple 'icmp sge i8 %src, 0' |
| 100 | |
| 101 | // CHECK-LABEL: @signed_char_to_unsigned_char |
| 102 | // CHECK-SAME: (i8 signext %[[SRC:.*]]) |
| 103 | unsigned char signed_char_to_unsigned_char(signed char src) { |
| 104 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8 |
| 105 | // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]] |
| 106 | // CHECK-NEXT: %[[DST:.*]] = load i8, i8* %[[SRC_ADDR]] |
| 107 | // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize |
| 108 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize |
| 109 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 110 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 111 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i8 %[[DST]] to i64, !nosanitize |
| 112 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize |
| 113 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 114 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 115 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 116 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 117 | // CHECK-SANITIZE: [[CONT]]: |
| 118 | // CHECK-NEXT: ret i8 %[[DST]] |
| 119 | // CHECK-NEXT: } |
| 120 | #line 400 |
| 121 | return src; |
| 122 | } |
| 123 | |
| 124 | // CHECK-LABEL: @unsigned_char_to_signed_char |
| 125 | // CHECK-SAME: (i8 zeroext %[[SRC:.*]]) |
| 126 | signed char unsigned_char_to_signed_char(unsigned char src) { |
| 127 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8 |
| 128 | // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]] |
| 129 | // CHECK-NEXT: %[[DST:.*]] = load i8, i8* %[[SRC_ADDR]] |
| 130 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize |
| 131 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 132 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 133 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 134 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i8 %[[DST]] to i64, !nosanitize |
| 135 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize |
| 136 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 137 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 138 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 139 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 140 | // CHECK-SANITIZE: [[CONT]]: |
| 141 | // CHECK-NEXT: ret i8 %[[DST]] |
| 142 | // CHECK-NEXT: } |
| 143 | #line 500 |
| 144 | return src; |
| 145 | } |
| 146 | |
| 147 | // CHECK-LABEL: @signed_char_to_unsigned_int |
| 148 | // CHECK-SAME: (i8 signext %[[SRC:.*]]) |
| 149 | unsigned int signed_char_to_unsigned_int(signed char src) { |
| 150 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8 |
| 151 | // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]] |
| 152 | // CHECK-NEXT: %[[DST:.*]] = load i8, i8* %[[SRC_ADDR]] |
| 153 | // CHECK-NEXT: %[[CONV:.*]] = sext i8 %[[DST]] to i32 |
| 154 | // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize |
| 155 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize |
| 156 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 157 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 158 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i8 %[[DST]] to i64, !nosanitize |
| 159 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i32 %[[CONV]] to i64, !nosanitize |
| 160 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 161 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 162 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 163 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 164 | // CHECK-SANITIZE: [[CONT]]: |
| 165 | // CHECK-NEXT: ret i32 %[[CONV]] |
| 166 | // CHECK-NEXT: } |
| 167 | #line 600 |
| 168 | return src; |
| 169 | } |
| 170 | |
| 171 | // This one result (after optimizations) in 'icmp sge i8 (trunc i32 %src), 0' |
| 172 | |
| 173 | // CHECK-LABEL: @unsigned_int_to_signed_char |
| 174 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 175 | signed char unsigned_int_to_signed_char(unsigned int src) { |
| 176 | // CHECK: %[[SRC_ADDR:.*]] = alloca i32 |
| 177 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 178 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 179 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 180 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize |
| 181 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 182 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 183 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 184 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 185 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 186 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 187 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 188 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 189 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 190 | // CHECK-SANITIZE: [[CONT]]: |
| 191 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 192 | // CHECK-NEXT: } |
| 193 | #line 700 |
| 194 | return src; |
| 195 | } |
| 196 | |
| 197 | // The worst one: 'xor i1 (icmp sge i8 (trunc i32 %x), 0), (icmp sge i32 %x, 0)' |
| 198 | |
| 199 | // CHECK-LABEL: @signed_int_to_signed_char |
| 200 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 201 | signed char signed_int_to_signed_char(signed int x) { |
| 202 | // CHECK: %[[SRC_ADDR:.*]] = alloca i32 |
| 203 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 204 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 205 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 206 | // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize |
| 207 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize |
| 208 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 209 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 210 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 211 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 212 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 213 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 214 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 215 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 216 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 217 | // CHECK-SANITIZE: [[CONT]]: |
| 218 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 219 | // CHECK-NEXT: } |
| 220 | #line 800 |
| 221 | return x; |
| 222 | } |
| 223 | |
| 224 | // ========================================================================== // |
| 225 | // Check canonical type stuff |
| 226 | // ========================================================================== // |
| 227 | |
| 228 | typedef unsigned int uint32_t; |
| 229 | typedef signed int int32_t; |
| 230 | |
| 231 | // CHECK-LABEL: @uint32_t_to_int32_t |
| 232 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 233 | int32_t uint32_t_to_int32_t(uint32_t src) { |
| 234 | // CHECK: %[[SRC_ADDR:.*]] = alloca i32 |
| 235 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 236 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 237 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize |
| 238 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 239 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 240 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 241 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 242 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 243 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 244 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize |
| 245 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 246 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 247 | // CHECK-SANITIZE: [[CONT]]: |
| 248 | // CHECK-NEXT: ret i32 %[[DST]] |
| 249 | // CHECK-NEXT: } |
| 250 | #line 900 |
| 251 | return src; |
| 252 | } |
| 253 | |
| 254 | // ========================================================================== // |
| 255 | // Check that explicit conversion does not interfere with implicit conversion |
| 256 | // ========================================================================== // |
| 257 | // These contain one implicit and one explicit sign-changing conversion. |
| 258 | // We want to make sure that we still diagnose the implicit conversion. |
| 259 | |
| 260 | // Implicit sign-change after explicit sign-change. |
| 261 | // CHECK-LABEL: @explicit_conversion_interference0 |
| 262 | unsigned int explicit_conversion_interference0(unsigned int c) { |
| 263 | // CHECK-SANITIZE: call |
| 264 | return (signed int)c; |
| 265 | } |
| 266 | |
| 267 | // Implicit sign-change before explicit sign-change. |
| 268 | // CHECK-LABEL: @explicit_conversion_interference1 |
| 269 | unsigned int explicit_conversion_interference1(unsigned int c) { |
| 270 | // CHECK-SANITIZE: call |
| 271 | signed int b; |
| 272 | return (unsigned int)(b = c); |
| 273 | } |