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-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER 3 // RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER 4 // RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP 5 6 // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" } 7 // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" } 8 9 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 } 10 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" } 11 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 } 12 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" } 13 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 } 14 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 } 15 16 // CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" } 17 // CHECK-SANITIZE-ANYRECOVER: @[[UINT8:.*]] = {{.*}} c"'uint8_t' (aka 'unsigned char')\00" } 18 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 0 } 19 20 // ========================================================================== // 21 // The expected true-positives. These are implicit conversions, and they truncate. 22 // ========================================================================== // 23 24 // CHECK-LABEL: @unsigned_int_to_unsigned_char 25 unsigned char unsigned_int_to_unsigned_char(unsigned int src) { 26 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8 27 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize 28 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize 29 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize 30 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: 31 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize 32 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize 33 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 34 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 35 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 36 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize 37 // CHECK-SANITIZE: [[CONT]]: 38 // CHECK: ret i8 %[[DST]] 39 #line 100 40 return src; 41 } 42 43 // CHECK-LABEL: @signed_int_to_unsigned_char 44 unsigned char signed_int_to_unsigned_char(signed int src) { 45 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8 46 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize 47 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize 48 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize 49 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: 50 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize 51 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize 52 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 53 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 54 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 55 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize 56 // CHECK-SANITIZE: [[CONT]]: 57 // CHECK: ret i8 %[[DST]] 58 #line 200 59 return src; 60 } 61 62 // CHECK-LABEL: @unsigned_int_to_signed_char 63 signed char unsigned_int_to_signed_char(unsigned int src) { 64 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8 65 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize 66 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize 67 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize 68 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: 69 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize 70 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize 71 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 72 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 73 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 74 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize 75 // CHECK-SANITIZE: [[CONT]]: 76 // CHECK: ret i8 %[[DST]] 77 #line 300 78 return src; 79 } 80 81 // CHECK-LABEL: @signed_int_to_signed_char 82 signed char signed_int_to_signed_char(signed int src) { 83 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8 84 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize 85 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize 86 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize 87 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: 88 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize 89 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize 90 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 91 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 92 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 93 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize 94 // CHECK-SANITIZE: [[CONT]]: 95 // CHECK: ret i8 %[[DST]] 96 #line 400 97 return src; 98 } 99 100 // ========================================================================== // 101 // Check canonical type stuff 102 // ========================================================================== // 103 104 typedef unsigned int uint32_t; 105 typedef unsigned char uint8_t; 106 107 // CHECK-LABEL: @uint32_to_uint8 108 uint8_t uint32_to_uint8(uint32_t src) { 109 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8 110 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize 111 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize 112 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize 113 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: 114 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize 115 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize 116 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 117 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 118 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 119 // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize 120 // CHECK-SANITIZE: [[CONT]]: 121 // CHECK: ret i8 %[[DST]] 122 #line 500 123 return src; 124 } 125 126 // ========================================================================== // 127 // Check that explicit conversion does not interfere with implicit conversion 128 // ========================================================================== // 129 // These contain one implicit truncating conversion, and one explicit truncating conversion. 130 // We want to make sure that we still diagnose the implicit conversion. 131 132 // Implicit truncation after explicit truncation. 133 // CHECK-LABEL: @explicit_conversion_interference0 134 unsigned char explicit_conversion_interference0(unsigned int c) { 135 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize 136 // CHECK-SANITIZE: call 137 // CHECK-SANITIZE-NOT: call 138 // CHECK: } 139 return (unsigned short)c; 140 } 141 142 // Implicit truncation before explicit truncation. 143 // CHECK-LABEL: @explicit_conversion_interference1 144 unsigned char explicit_conversion_interference1(unsigned int c) { 145 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize 146 // CHECK-SANITIZE: call 147 // CHECK-SANITIZE-NOT: call 148 // CHECK: } 149 unsigned short b; 150 return (unsigned char)(b = c); 151 } 152 153 // ========================================================================== // 154 // The expected true-negatives. 155 // ========================================================================== // 156 157 // Sanitization is explicitly disabled. 158 // ========================================================================== // 159 160 // CHECK-LABEL: @blacklist_0 161 __attribute__((no_sanitize("undefined"))) unsigned char blacklist_0(unsigned int src) { 162 // We are not in "undefined" group, so that doesn't work. 163 // CHECK-SANITIZE: call 164 // CHECK: } 165 return src; 166 } 167 168 // CHECK-LABEL: @blacklist_1 169 __attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_1(unsigned int src) { 170 // CHECK-SANITIZE-NOT: call 171 // CHECK: } 172 return src; 173 } 174 175 // CHECK-LABEL: @blacklist_2 176 __attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_2(unsigned int src) { 177 // CHECK-SANITIZE-NOT: call 178 // CHECK: } 179 return src; 180 } 181 182 // Explicit truncating conversions. 183 // ========================================================================== // 184 185 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char 186 unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) { 187 // CHECK-SANITIZE-NOT: call 188 // CHECK: } 189 return (unsigned char)src; 190 } 191 192 // CHECK-LABEL: @explicit_signed_int_to_unsigned_char 193 unsigned char explicit_signed_int_to_unsigned_char(signed int src) { 194 // CHECK-SANITIZE-NOT: call 195 // CHECK: } 196 return (unsigned char)src; 197 } 198 199 // CHECK-LABEL: @explicit_unsigned_int_to_signed_char 200 signed char explicit_unsigned_int_to_signed_char(unsigned int src) { 201 // CHECK-SANITIZE-NOT: call 202 // CHECK: } 203 return (signed char)src; 204 } 205 206 // CHECK-LABEL: @explicit_signed_int_to_signed_char 207 signed char explicit_signed_int_to_signed_char(signed int src) { 208 // CHECK-SANITIZE-NOT: call 209 // CHECK: } 210 return (signed char)src; 211 } 212 213 // Explicit NOP conversions. 214 // ========================================================================== // 215 216 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int 217 unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) { 218 // CHECK-SANITIZE-NOT: call 219 // CHECK: } 220 return (unsigned int)src; 221 } 222 223 // CHECK-LABEL: @explicit_signed_int_to_signed_int 224 signed int explicit_signed_int_to_signed_int(signed int src) { 225 // CHECK-SANITIZE-NOT: call 226 // CHECK: } 227 return (signed int)src; 228 } 229 230 // CHECK-LABEL: @explicit_unsigned_char_to_signed_char 231 unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) { 232 // CHECK-SANITIZE-NOT: call 233 // CHECK: } 234 return (unsigned char)src; 235 } 236 237 // CHECK-LABEL: @explicit_signed_char_to_signed_char 238 signed char explicit_signed_char_to_signed_char(signed char src) { 239 // CHECK-SANITIZE-NOT: call 240 // CHECK: } 241 return (signed char)src; 242 } 243 244 // upcasts. 245 // ========================================================================== // 246 247 // CHECK-LABEL: @unsigned_char_to_unsigned_int 248 unsigned int unsigned_char_to_unsigned_int(unsigned char src) { 249 // CHECK-SANITIZE-NOT: call 250 // CHECK: } 251 return src; 252 } 253 254 // CHECK-LABEL: @signed_char_to_unsigned_int 255 unsigned int signed_char_to_unsigned_int(signed char src) { 256 // CHECK-SANITIZE-NOT: call 257 // CHECK: } 258 return src; 259 } 260 261 // CHECK-LABEL: @unsigned_char_to_signed_int 262 signed int unsigned_char_to_signed_int(unsigned char src) { 263 // CHECK-SANITIZE-NOT: call 264 // CHECK: } 265 return src; 266 } 267 268 // CHECK-LABEL: @signed_char_to_signed_int 269 signed int signed_char_to_signed_int(signed char src) { 270 // CHECK-SANITIZE-NOT: call 271 // CHECK: } 272 return src; 273 } 274 275 // Explicit upcasts. 276 // ========================================================================== // 277 278 // CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int 279 unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src) { 280 // CHECK-SANITIZE-NOT: call 281 // CHECK: } 282 return (unsigned int)src; 283 } 284 285 // CHECK-LABEL: @explicit_signed_char_to_unsigned_int 286 unsigned int explicit_signed_char_to_unsigned_int(signed char src) { 287 // CHECK-SANITIZE-NOT: call 288 // CHECK: } 289 return (unsigned int)src; 290 } 291 292 // CHECK-LABEL: @explicit_unsigned_char_to_signed_int 293 signed int explicit_unsigned_char_to_signed_int(unsigned char src) { 294 // CHECK-SANITIZE-NOT: call 295 // CHECK: } 296 return (signed int)src; 297 } 298 299 // CHECK-LABEL: @explicit_signed_char_to_signed_int 300 signed int explicit_signed_char_to_signed_int(signed char src) { 301 // CHECK-SANITIZE-NOT: call 302 // CHECK: } 303 return (signed int)src; 304 } 305 306 // conversions to to boolean type are not counted as truncation. 307 // ========================================================================== // 308 309 // CHECK-LABEL: @unsigned_int_to_bool 310 _Bool unsigned_int_to_bool(unsigned int src) { 311 // CHECK-SANITIZE-NOT: call 312 // CHECK: } 313 return src; 314 } 315 316 // CHECK-LABEL: @signed_int_to_bool 317 _Bool signed_int_to_bool(signed int src) { 318 // CHECK-SANITIZE-NOT: call 319 // CHECK: } 320 return src; 321 } 322 323 // CHECK-LABEL: @explicit_unsigned_int_to_bool 324 _Bool explicit_unsigned_int_to_bool(unsigned int src) { 325 // CHECK-SANITIZE-NOT: call 326 // CHECK: } 327 return (_Bool)src; 328 } 329 330 // CHECK-LABEL: @explicit_signed_int_to_bool 331 _Bool explicit_signed_int_to_bool(signed int src) { 332 // CHECK-SANITIZE-NOT: call 333 // CHECK: } 334 return (_Bool)src; 335 } 336 337 // Explicit truncating conversions from pointer to a much-smaller integer. 338 // Can not have an implicit conversion from pointer to an integer. 339 // Can not have an implicit conversion between two enums. 340 // ========================================================================== // 341 342 // CHECK-LABEL: @explicit_voidptr_to_unsigned_char 343 unsigned char explicit_voidptr_to_unsigned_char(void *src) { 344 // CHECK-SANITIZE-NOT: call 345 // CHECK: } 346 return (unsigned char)src; 347 } 348 349 // CHECK-LABEL: @explicit_voidptr_to_signed_char 350 signed char explicit_voidptr_to_signed_char(void *src) { 351 // CHECK-SANITIZE-NOT: call 352 // CHECK: } 353 return (signed char)src; 354 } 355 356 // Implicit truncating conversions from floating-point may result in precision loss. 357 // ========================================================================== // 358 359 // CHECK-LABEL: @float_to_unsigned_int 360 unsigned int float_to_unsigned_int(float src) { 361 // CHECK-SANITIZE-NOT: call 362 // CHECK: } 363 return src; 364 } 365 366 // CHECK-LABEL: @float_to_signed_int 367 signed int float_to_signed_int(float src) { 368 // CHECK-SANITIZE-NOT: call 369 // CHECK: } 370 return src; 371 } 372 373 // CHECK-LABEL: @double_to_unsigned_int 374 unsigned int double_to_unsigned_int(double src) { 375 // CHECK-SANITIZE-NOT: call 376 // CHECK: } 377 return src; 378 } 379 380 // CHECK-LABEL: @double_to_signed_int 381 signed int double_to_signed_int(double src) { 382 // CHECK-SANITIZE-NOT: call 383 // CHECK: } 384 return src; 385 } 386 387 // Implicit truncating conversions between fp may result in precision loss. 388 // ========================================================================== // 389 390 // CHECK-LABEL: @double_to_float 391 float double_to_float(double src) { 392 // CHECK-SANITIZE-NOT: call 393 // CHECK: } 394 return src; 395 } 396