289 lines
18 KiB
C
289 lines
18 KiB
C
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
|
|
//
|
|
// We can't use -fsanitize-skip-hot-cutoff because that includes both -ubsan-guard-checks and
|
|
//-lower-allow-check-percentile-cutoff.
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null,local-bounds -mllvm -ubsan-guard-checks | FileCheck %s
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null,local-bounds -mllvm -ubsan-guard-checks -fsanitize-trap=signed-integer-overflow,integer-divide-by-zero,null,local-bounds | FileCheck %s --check-prefixes=TR
|
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null,local-bounds -mllvm -ubsan-guard-checks -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,null,local-bounds | FileCheck %s --check-prefixes=REC
|
|
|
|
|
|
// CHECK-LABEL: define dso_local noundef i32 @div(
|
|
// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = icmp ne i32 [[Y]], 0, !nosanitize [[META2:![0-9]+]]
|
|
// CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X]], -2147483648, !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[Y]], -1, !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[OR:%.*]] = or i1 [[TMP1]], [[TMP2]], !nosanitize [[META2]]
|
|
//
|
|
// 27 == SO_IntegerDivideByZero
|
|
// CHECK-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 27), !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true, !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP0]], [[TMP4]], !nosanitize [[META2]]
|
|
//
|
|
// 41 == SO_SignedIntegerOverflow
|
|
// CHECK-NEXT: [[TMP6:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 41), !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP7:%.*]] = xor i1 [[TMP6]], true, !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP8:%.*]] = or i1 [[OR]], [[TMP7]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP9:%.*]] = and i1 [[TMP5]], [[TMP8]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: br i1 [[TMP9]], label %[[CONT:.*]], label %[[HANDLER_DIVREM_OVERFLOW:.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
|
|
// CHECK: [[HANDLER_DIVREM_OVERFLOW]]:
|
|
// CHECK-NEXT: [[TMP10:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP11:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
|
|
// CHECK-NEXT: tail call void @__ubsan_handle_divrem_overflow_abort(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[TMP10]], i64 [[TMP11]]) #[[ATTR6:[0-9]+]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
|
|
// CHECK: [[CONT]]:
|
|
// CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]]
|
|
// CHECK-NEXT: ret i32 [[DIV]]
|
|
//
|
|
// TR-LABEL: define dso_local noundef i32 @div(
|
|
// TR-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
|
|
// TR-NEXT: [[ENTRY:.*:]]
|
|
// TR-NEXT: [[TMP0:%.*]] = icmp ne i32 [[Y]], 0, !nosanitize [[META2:![0-9]+]]
|
|
// TR-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X]], -2147483648, !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP2:%.*]] = icmp ne i32 [[Y]], -1, !nosanitize [[META2]]
|
|
// TR-NEXT: [[OR:%.*]] = or i1 [[TMP1]], [[TMP2]], !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 27), !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true, !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP5:%.*]] = or i1 [[TMP0]], [[TMP4]], !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP6:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 41), !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP7:%.*]] = xor i1 [[TMP6]], true, !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP8:%.*]] = or i1 [[OR]], [[TMP7]], !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP9:%.*]] = and i1 [[TMP5]], [[TMP8]], !nosanitize [[META2]]
|
|
// TR-NEXT: br i1 [[TMP9]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
|
|
// TR: [[TRAP]]:
|
|
// TR-NEXT: tail call void @llvm.ubsantrap(i8 3) #[[ATTR5:[0-9]+]], !nosanitize [[META2]]
|
|
// TR-NEXT: unreachable, !nosanitize [[META2]]
|
|
// TR: [[CONT]]:
|
|
// TR-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]]
|
|
// TR-NEXT: ret i32 [[DIV]]
|
|
//
|
|
// REC-LABEL: define dso_local noundef i32 @div(
|
|
// REC-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
|
|
// REC-NEXT: [[ENTRY:.*:]]
|
|
// REC-NEXT: [[TMP0:%.*]] = icmp ne i32 [[Y]], 0, !nosanitize [[META2:![0-9]+]]
|
|
// REC-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X]], -2147483648, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP2:%.*]] = icmp ne i32 [[Y]], -1, !nosanitize [[META2]]
|
|
// REC-NEXT: [[OR:%.*]] = or i1 [[TMP1]], [[TMP2]], !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 27), !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP5:%.*]] = or i1 [[TMP0]], [[TMP4]], !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP6:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 41), !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP7:%.*]] = xor i1 [[TMP6]], true, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP8:%.*]] = or i1 [[OR]], [[TMP7]], !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP9:%.*]] = and i1 [[TMP5]], [[TMP8]], !nosanitize [[META2]]
|
|
// REC-NEXT: br i1 [[TMP9]], label %[[CONT:.*]], label %[[HANDLER_DIVREM_OVERFLOW:.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
|
|
// REC: [[HANDLER_DIVREM_OVERFLOW]]:
|
|
// REC-NEXT: [[TMP10:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP11:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
|
|
// REC-NEXT: tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[TMP10]], i64 [[TMP11]]) #[[ATTR6:[0-9]+]], !nosanitize [[META2]]
|
|
// REC-NEXT: br label %[[CONT]], !nosanitize [[META2]]
|
|
// REC: [[CONT]]:
|
|
// REC-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]]
|
|
// REC-NEXT: ret i32 [[DIV]]
|
|
//
|
|
int div(int x, int y) {
|
|
return x / y;
|
|
}
|
|
|
|
// CHECK-LABEL: define dso_local i32 @null(
|
|
// CHECK-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
|
|
//
|
|
// 29 == SO_Null
|
|
// CHECK-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[DOTNOT1:%.*]] = and i1 [[TMP0]], [[TMP1]]
|
|
// CHECK-NEXT: br i1 [[DOTNOT1]], label %[[HANDLER_TYPE_MISMATCH:.*]], label %[[CONT:.*]], !prof [[PROF4:![0-9]+]], !nosanitize [[META2]]
|
|
// CHECK: [[HANDLER_TYPE_MISMATCH]]:
|
|
// CHECK-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 0) #[[ATTR6]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
|
|
// CHECK: [[CONT]]:
|
|
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA5:![0-9]+]]
|
|
// CHECK-NEXT: ret i32 [[TMP2]]
|
|
//
|
|
// TR-LABEL: define dso_local i32 @null(
|
|
// TR-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// TR-NEXT: [[ENTRY:.*:]]
|
|
// TR-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]]
|
|
// TR-NEXT: [[DOTNOT1:%.*]] = and i1 [[TMP0]], [[TMP1]]
|
|
// TR-NEXT: br i1 [[DOTNOT1]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF4:![0-9]+]], !nosanitize [[META2]]
|
|
// TR: [[TRAP]]:
|
|
// TR-NEXT: tail call void @llvm.ubsantrap(i8 22) #[[ATTR5]], !nosanitize [[META2]]
|
|
// TR-NEXT: unreachable, !nosanitize [[META2]]
|
|
// TR: [[CONT]]:
|
|
// TR-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA5:![0-9]+]]
|
|
// TR-NEXT: ret i32 [[TMP2]]
|
|
//
|
|
// REC-LABEL: define dso_local i32 @null(
|
|
// REC-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// REC-NEXT: [[ENTRY:.*:]]
|
|
// REC-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]]
|
|
// REC-NEXT: [[DOTNOT1:%.*]] = and i1 [[TMP0]], [[TMP1]]
|
|
// REC-NEXT: br i1 [[DOTNOT1]], label %[[HANDLER_TYPE_MISMATCH:.*]], label %[[CONT:.*]], !prof [[PROF4:![0-9]+]], !nosanitize [[META2]]
|
|
// REC: [[HANDLER_TYPE_MISMATCH]]:
|
|
// REC-NEXT: tail call void @__ubsan_handle_type_mismatch_v1(ptr nonnull @[[GLOB2:[0-9]+]], i64 0) #[[ATTR6]], !nosanitize [[META2]]
|
|
// REC-NEXT: br label %[[CONT]], !nosanitize [[META2]]
|
|
// REC: [[CONT]]:
|
|
// REC-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA5:![0-9]+]]
|
|
// REC-NEXT: ret i32 [[TMP2]]
|
|
//
|
|
int null(int* x) {
|
|
return *x;
|
|
}
|
|
|
|
// CHECK-LABEL: define dso_local noundef i32 @overflow(
|
|
// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X]], i32 [[Y]]), !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]]
|
|
//
|
|
// 41 == SO_SignedIntegerOverflow
|
|
// CHECK-NEXT: [[TMP2:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 41), !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[DOTDEMORGAN:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
// CHECK-NEXT: br i1 [[DOTDEMORGAN]], label %[[HANDLER_ADD_OVERFLOW:.*]], label %[[CONT:.*]], !prof [[PROF4]], !nosanitize [[META2]]
|
|
// CHECK: [[HANDLER_ADD_OVERFLOW]]:
|
|
// CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
|
|
// CHECK-NEXT: tail call void @__ubsan_handle_add_overflow_abort(ptr nonnull @[[GLOB3:[0-9]+]], i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
|
|
// CHECK: [[CONT]]:
|
|
// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
|
|
// CHECK-NEXT: ret i32 [[TMP5]]
|
|
//
|
|
// TR-LABEL: define dso_local noundef i32 @overflow(
|
|
// TR-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// TR-NEXT: [[ENTRY:.*:]]
|
|
// TR-NEXT: [[TMP0:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X]], i32 [[Y]]), !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP2:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 41), !nosanitize [[META2]]
|
|
// TR-NEXT: [[DOTDEMORGAN:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
// TR-NEXT: br i1 [[DOTDEMORGAN]], label %[[TRAP:.*]], label %[[CONT:.*]], !prof [[PROF4]], !nosanitize [[META2]]
|
|
// TR: [[TRAP]]:
|
|
// TR-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR5]], !nosanitize [[META2]]
|
|
// TR-NEXT: unreachable, !nosanitize [[META2]]
|
|
// TR: [[CONT]]:
|
|
// TR-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
|
|
// TR-NEXT: ret i32 [[TMP3]]
|
|
//
|
|
// REC-LABEL: define dso_local noundef i32 @overflow(
|
|
// REC-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// REC-NEXT: [[ENTRY:.*:]]
|
|
// REC-NEXT: [[TMP0:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X]], i32 [[Y]]), !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP2:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 41), !nosanitize [[META2]]
|
|
// REC-NEXT: [[DOTDEMORGAN:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
// REC-NEXT: br i1 [[DOTDEMORGAN]], label %[[HANDLER_ADD_OVERFLOW:.*]], label %[[CONT:.*]], !prof [[PROF4]], !nosanitize [[META2]]
|
|
// REC: [[HANDLER_ADD_OVERFLOW]]:
|
|
// REC-NEXT: [[TMP3:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP4:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
|
|
// REC-NEXT: tail call void @__ubsan_handle_add_overflow(ptr nonnull @[[GLOB3:[0-9]+]], i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META2]]
|
|
// REC-NEXT: br label %[[CONT]], !nosanitize [[META2]]
|
|
// REC: [[CONT]]:
|
|
// REC-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
|
|
// REC-NEXT: ret i32 [[TMP5]]
|
|
//
|
|
int overflow(int x, int y) {
|
|
return x + y;
|
|
}
|
|
|
|
void use(double*);
|
|
|
|
// CHECK-LABEL: define dso_local double @lbounds(
|
|
// CHECK-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B]] to i64
|
|
// CHECK-NEXT: [[VLA:%.*]] = alloca double, i64 [[TMP0]], align 16
|
|
// CHECK-NEXT: call void @use(ptr noundef nonnull [[VLA]]) #[[ATTR7:[0-9]+]]
|
|
// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
|
|
// CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[TMP0]], [[IDXPROM]]
|
|
//
|
|
// 71 == SO_LocalBounds
|
|
// CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.allow.ubsan.check(i8 71), !nosanitize [[META2]]
|
|
// CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: br i1 [[TMP3]], label %[[TRAP:.*]], label %[[BB4:.*]]
|
|
// CHECK: [[BB4]]:
|
|
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[VLA]], i64 [[IDXPROM]]
|
|
// CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA9:![0-9]+]]
|
|
// CHECK-NEXT: ret double [[TMP5]]
|
|
// CHECK: [[TRAP]]:
|
|
// CHECK-NEXT: call void @__ubsan_handle_local_out_of_bounds_abort() #[[ATTR6]], !nosanitize [[META2]]
|
|
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
|
|
//
|
|
// TR-LABEL: define dso_local double @lbounds(
|
|
// TR-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// TR-NEXT: [[ENTRY:.*:]]
|
|
// TR-NEXT: [[TMP0:%.*]] = zext i32 [[B]] to i64
|
|
// TR-NEXT: [[VLA:%.*]] = alloca double, i64 [[TMP0]], align 16
|
|
// TR-NEXT: call void @use(ptr noundef nonnull [[VLA]]) #[[ATTR6:[0-9]+]]
|
|
// TR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
|
|
// TR-NEXT: [[TMP1:%.*]] = icmp ule i64 [[TMP0]], [[IDXPROM]]
|
|
// TR-NEXT: [[TMP2:%.*]] = call i1 @llvm.allow.ubsan.check(i8 71), !nosanitize [[META2]]
|
|
// TR-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]], !nosanitize [[META2]]
|
|
// TR-NEXT: br i1 [[TMP3]], label %[[TRAP:.*]], label %[[BB4:.*]]
|
|
// TR: [[BB4]]:
|
|
// TR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[VLA]], i64 [[IDXPROM]]
|
|
// TR-NEXT: [[TMP5:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA9:![0-9]+]]
|
|
// TR-NEXT: ret double [[TMP5]]
|
|
// TR: [[TRAP]]:
|
|
// TR-NEXT: call void @llvm.ubsantrap(i8 71) #[[ATTR5]], !nosanitize [[META2]]
|
|
// TR-NEXT: unreachable, !nosanitize [[META2]]
|
|
//
|
|
// REC-LABEL: define dso_local double @lbounds(
|
|
// REC-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// REC-NEXT: [[ENTRY:.*:]]
|
|
// REC-NEXT: [[TMP0:%.*]] = zext i32 [[B]] to i64
|
|
// REC-NEXT: [[VLA:%.*]] = alloca double, i64 [[TMP0]], align 16
|
|
// REC-NEXT: call void @use(ptr noundef nonnull [[VLA]]) #[[ATTR5:[0-9]+]]
|
|
// REC-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
|
|
// REC-NEXT: [[TMP1:%.*]] = icmp ule i64 [[TMP0]], [[IDXPROM]]
|
|
// REC-NEXT: [[TMP2:%.*]] = call i1 @llvm.allow.ubsan.check(i8 71), !nosanitize [[META2]]
|
|
// REC-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]], !nosanitize [[META2]]
|
|
// REC-NEXT: br i1 [[TMP3]], label %[[TRAP:.*]], label %[[BB4:.*]]
|
|
// REC: [[BB4]]:
|
|
// REC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[VLA]], i64 [[IDXPROM]]
|
|
// REC-NEXT: [[TMP5:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA9:![0-9]+]]
|
|
// REC-NEXT: ret double [[TMP5]]
|
|
// REC: [[TRAP]]:
|
|
// REC-NEXT: call void @__ubsan_handle_local_out_of_bounds() #[[ATTR6]], !nosanitize [[META2]]
|
|
// REC-NEXT: br label %[[BB4]], !nosanitize [[META2]]
|
|
//
|
|
double lbounds(int b, int i) {
|
|
double a[b];
|
|
use(a);
|
|
return a[i];
|
|
}
|
|
|
|
//.
|
|
// CHECK: [[META2]] = !{}
|
|
// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
|
|
// CHECK: [[PROF4]] = !{!"branch_weights", i32 1, i32 1048575}
|
|
// CHECK: [[TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0}
|
|
// CHECK: [[META6]] = !{!"int", [[META7:![0-9]+]], i64 0}
|
|
// CHECK: [[META7]] = !{!"omnipotent char", [[META8:![0-9]+]], i64 0}
|
|
// CHECK: [[META8]] = !{!"Simple C/C++ TBAA"}
|
|
// CHECK: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
|
|
// CHECK: [[META10]] = !{!"double", [[META7]], i64 0}
|
|
//.
|
|
// TR: [[META2]] = !{}
|
|
// TR: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
|
|
// TR: [[PROF4]] = !{!"branch_weights", i32 1, i32 1048575}
|
|
// TR: [[TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0}
|
|
// TR: [[META6]] = !{!"int", [[META7:![0-9]+]], i64 0}
|
|
// TR: [[META7]] = !{!"omnipotent char", [[META8:![0-9]+]], i64 0}
|
|
// TR: [[META8]] = !{!"Simple C/C++ TBAA"}
|
|
// TR: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
|
|
// TR: [[META10]] = !{!"double", [[META7]], i64 0}
|
|
//.
|
|
// REC: [[META2]] = !{}
|
|
// REC: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
|
|
// REC: [[PROF4]] = !{!"branch_weights", i32 1, i32 1048575}
|
|
// REC: [[TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0}
|
|
// REC: [[META6]] = !{!"int", [[META7:![0-9]+]], i64 0}
|
|
// REC: [[META7]] = !{!"omnipotent char", [[META8:![0-9]+]], i64 0}
|
|
// REC: [[META8]] = !{!"Simple C/C++ TBAA"}
|
|
// REC: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
|
|
// REC: [[META10]] = !{!"double", [[META7]], i64 0}
|
|
//.
|