// 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-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -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-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -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-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -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: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[LINE_300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
// CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[UINT8:.*]] = {{.*}} c"'uint8_t' (aka 'unsigned char')\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 1 }
// ========================================================================== //
// The expected true-positives. These are implicit conversions, and they truncate.
// ========================================================================== //
// CHECK-LABEL: @unsigned_int_to_unsigned_char
unsigned char
// CHECK-LABEL: @signed_int_to_unsigned_char
unsigned char
// CHECK-LABEL: @unsigned_int_to_signed_char
signed char
// CHECK-LABEL: @signed_int_to_signed_char
signed char
// ========================================================================== //
// Check canonical type stuff
// ========================================================================== //
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
// CHECK-LABEL: @uint32_to_uint8
uint8_t
// ========================================================================== //
// Check that explicit conversion does not interfere with implicit conversion
// ========================================================================== //
// These contain one implicit truncating conversion, and one explicit truncating conversion.
// We want to make sure that we still diagnose the implicit conversion.
// Implicit truncation after explicit truncation.
// CHECK-LABEL: @explicit_conversion_interference0
unsigned char
// Implicit truncation before explicit truncation.
// CHECK-LABEL: @explicit_conversion_interference1
unsigned char
// ========================================================================== //
// The expected true-negatives.
// ========================================================================== //
// Sanitization is explicitly disabled.
// ========================================================================== //
// CHECK-LABEL: @ignorelist_0
unsigned char
// CHECK-LABEL: @ignorelist_1
unsigned char
// CHECK-LABEL: @ignorelist_2
unsigned char
// CHECK-LABEL: @ignorelist_3
unsigned char
// Explicit truncating conversions.
// ========================================================================== //
// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
unsigned char
// CHECK-LABEL: @explicit_signed_int_to_unsigned_char
unsigned char
// CHECK-LABEL: @explicit_unsigned_int_to_signed_char
signed char
// CHECK-LABEL: @explicit_signed_int_to_signed_char
signed char
// Explicit NOP conversions.
// ========================================================================== //
// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
unsigned int
// CHECK-LABEL: @explicit_signed_int_to_signed_int
signed int
// CHECK-LABEL: @explicit_unsigned_char_to_signed_char
unsigned char
// CHECK-LABEL: @explicit_signed_char_to_signed_char
signed char
// upcasts.
// ========================================================================== //
// CHECK-LABEL: @unsigned_char_to_unsigned_int
unsigned int
// CHECK-LABEL: @signed_char_to_unsigned_int
unsigned int
// CHECK-LABEL: @unsigned_char_to_signed_int
signed int
// CHECK-LABEL: @signed_char_to_signed_int
signed int
// Explicit upcasts.
// ========================================================================== //
// CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int
unsigned int
// CHECK-LABEL: @explicit_signed_char_to_unsigned_int
unsigned int
// CHECK-LABEL: @explicit_unsigned_char_to_signed_int
signed int
// CHECK-LABEL: @explicit_signed_char_to_signed_int
signed int
// conversions to to boolean type are not counted as truncation.
// ========================================================================== //
// CHECK-LABEL: @unsigned_int_to_bool
_Bool
// CHECK-LABEL: @signed_int_to_bool
_Bool
// CHECK-LABEL: @explicit_unsigned_int_to_bool
_Bool
// CHECK-LABEL: @explicit_signed_int_to_bool
_Bool
// Explicit truncating conversions from pointer to a much-smaller integer.
// Can not have an implicit conversion from pointer to an integer.
// Can not have an implicit conversion between two enums.
// ========================================================================== //
// CHECK-LABEL: @explicit_voidptr_to_unsigned_char
unsigned char
// CHECK-LABEL: @explicit_voidptr_to_signed_char
signed char
// Implicit truncating conversions from floating-point may result in precision loss.
// ========================================================================== //
// CHECK-LABEL: @float_to_unsigned_int
unsigned int
// CHECK-LABEL: @float_to_signed_int
signed int
// CHECK-LABEL: @double_to_unsigned_int
unsigned int
// CHECK-LABEL: @double_to_signed_int
signed int
// Implicit truncating conversions between fp may result in precision loss.
// ========================================================================== //
// CHECK-LABEL: @double_to_float
float