// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
// RUN: %clang_cc1 -no-opaque-pointers -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
// RUN: %clang_cc1 -no-opaque-pointers -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
// RUN: %clang_cc1 -no-opaque-pointers -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
// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_INT]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_INT]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_CHAR]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UNSIGNED_CHAR]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 10 }, {{.*}}* @[[SIGNED_CHAR]], {{.*}}* @[[UNSIGNED_INT]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
// CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[INT32:.*]] = {{.*}} c"'int32_t' (aka 'int')\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[INT32]], i8 3 }
// ========================================================================== //
// The expected true-positives.
// These are implicit, potentially sign-altering, conversions.
// ========================================================================== //
// These 3 result (after optimizations) in simple 'icmp sge i32 %src, 0'.
// CHECK-LABEL: @unsigned_int_to_signed_int
// CHECK-SAME: i32 noundef %[[SRC:.*]])
signed int
// CHECK-LABEL: @signed_int_to_unsigned_int
// CHECK-SAME: i32 noundef %[[SRC:.*]])
unsigned int
// CHECK-LABEL: @signed_int_to_unsigned_char
// CHECK-SAME: i32 noundef %[[SRC:.*]])
unsigned char
// These 3 result (after optimizations) in simple 'icmp sge i8 %src, 0'
// CHECK-LABEL: @signed_char_to_unsigned_char
// CHECK-SAME: (i8 noundef signext %[[SRC:.*]])
unsigned char
// CHECK-LABEL: @unsigned_char_to_signed_char
// CHECK-SAME: (i8 noundef zeroext %[[SRC:.*]])
signed char
// CHECK-LABEL: @signed_char_to_unsigned_int
// CHECK-SAME: (i8 noundef signext %[[SRC:.*]])
unsigned int
// This one result (after optimizations) in 'icmp sge i8 (trunc i32 %src), 0'
// CHECK-LABEL: @unsigned_int_to_signed_char
// CHECK-SAME: i32 noundef %[[SRC:.*]])
signed char
// The worst one: 'xor i1 (icmp sge i8 (trunc i32 %x), 0), (icmp sge i32 %x, 0)'
// CHECK-LABEL: @signed_int_to_signed_char
// CHECK-SAME: i32 noundef %[[SRC:.*]])
signed char
// ========================================================================== //
// Check canonical type stuff
// ========================================================================== //
typedef unsigned int uint32_t;
typedef signed int int32_t;
// CHECK-LABEL: @uint32_t_to_int32_t
// CHECK-SAME: i32 noundef %[[SRC:.*]])
int32_t
// ========================================================================== //
// Check that explicit conversion does not interfere with implicit conversion
// ========================================================================== //
// These contain one implicit and one explicit sign-changing conversion.
// We want to make sure that we still diagnose the implicit conversion.
// Implicit sign-change after explicit sign-change.
// CHECK-LABEL: @explicit_conversion_interference0
unsigned int
// Implicit sign-change before explicit sign-change.
// CHECK-LABEL: @explicit_conversion_interference1
unsigned int