1
1
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
2
- // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed- integer-overflow -O3 %s -o - -fsanitize-recover=signed- integer-overflow | FileCheck %s --check-prefixes=RECOVER
3
- // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed- integer-overflow -O3 %s -o - | FileCheck %s --check-prefixes=ABORT
2
+ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=integer-divide-by-zero -O3 %s -o - -fsanitize-recover=integer-divide-by-zero | FileCheck %s --check-prefixes=RECOVER
3
+ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=integer-divide-by-zero -O3 %s -o - | FileCheck %s --check-prefixes=ABORT
4
4
5
5
// RECOVER: Function Attrs: mustprogress nounwind willreturn memory(read, argmem: readwrite, inaccessiblemem: readwrite)
6
6
// RECOVER-LABEL: define dso_local noundef range(i32 -32768, 32768) i32 @_Z4testRiRs(
7
7
// RECOVER-SAME: ptr noundef nonnull align 4 captures(none) dereferenceable(4) [[A:%.*]], ptr noundef nonnull readonly align 2 captures(none) dereferenceable(2) [[C:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
8
8
// RECOVER-NEXT: [[ENTRY:.*:]]
9
9
// RECOVER-NEXT: [[TMP0:%.*]] = load i16, ptr [[C]], align 2, !tbaa [[TBAA2:![0-9]+]]
10
- // RECOVER-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32
11
10
// RECOVER-NEXT: [[TMP1:%.*]] = load i32, ptr [[A]], align 4, !tbaa [[TBAA6:![0-9]+]]
12
- // RECOVER-NEXT: [[TMP2:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP1]], i32 [[CONV]]), !nosanitize [[META8:![0-9]+]]
13
- // RECOVER-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META8]]
14
- // RECOVER-NEXT: br i1 [[TMP3]], label %[[HANDLER_ADD_OVERFLOW:.*]], label %[[CONT:.*]], !prof [[PROF9:![0-9]+]], !nosanitize [[META8]]
15
- // RECOVER: [[HANDLER_ADD_OVERFLOW]]:
16
- // RECOVER-NEXT: [[TMP4:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META8]]
17
- // RECOVER-NEXT: [[TMP5:%.*]] = zext i32 [[CONV]] to i64, !nosanitize [[META8]]
18
- // RECOVER-NEXT: tail call void @__ubsan_handle_add_overflow(ptr nonnull @{{.+}}, i64 [[TMP4]], i64 [[TMP5]]) #[[ATTR3:[0-9]+]], !nosanitize [[META8]]
19
- // RECOVER-NEXT: br label %[[CONT]], !nosanitize [[META8]]
11
+ // RECOVER-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[TMP0]], 0
12
+ // RECOVER-NEXT: br i1 [[DOTNOT]], label %[[HANDLER_DIVREM_OVERFLOW:.*]], label %[[CONT:.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META9:![0-9]+]]
13
+ // RECOVER: [[HANDLER_DIVREM_OVERFLOW]]:
14
+ // RECOVER-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META9]]
15
+ // RECOVER-NEXT: tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @{{.+}}, i64 [[TMP2]], i64 0) #[[ATTR3:[0-9]+]], !nosanitize [[META9]]
16
+ // RECOVER-NEXT: br label %[[CONT]], !nosanitize [[META9]]
20
17
// RECOVER: [[CONT]]:
21
- // RECOVER-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META8]]
22
- // RECOVER-NEXT: store i32 [[TMP6]], ptr [[A]], align 4, !tbaa [[TBAA6]]
18
+ // RECOVER-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32
19
+ // RECOVER-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP1]], [[CONV]]
20
+ // RECOVER-NEXT: store i32 [[DIV]], ptr [[A]], align 4, !tbaa [[TBAA6]]
23
21
// RECOVER-NEXT: ret i32 [[CONV]]
24
22
//
25
23
// ABORT: Function Attrs: mustprogress nounwind
26
24
// ABORT-LABEL: define dso_local noundef range(i32 -32768, 32768) i32 @_Z4testRiRs(
27
25
// ABORT-SAME: ptr noundef nonnull align 4 captures(none) dereferenceable(4) [[A:%.*]], ptr noundef nonnull readonly align 2 captures(none) dereferenceable(2) [[C:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
28
26
// ABORT-NEXT: [[ENTRY:.*:]]
29
27
// ABORT-NEXT: [[TMP0:%.*]] = load i16, ptr [[C]], align 2, !tbaa [[TBAA2:![0-9]+]]
30
- // ABORT-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32
31
28
// ABORT-NEXT: [[TMP1:%.*]] = load i32, ptr [[A]], align 4, !tbaa [[TBAA6:![0-9]+]]
32
- // ABORT-NEXT: [[TMP2:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP1]], i32 [[CONV]]), !nosanitize [[META8:![0-9]+]]
33
- // ABORT-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META8]]
34
- // ABORT-NEXT: br i1 [[TMP3]], label %[[HANDLER_ADD_OVERFLOW:.*]], label %[[CONT:.*]], !prof [[PROF9:![0-9]+]], !nosanitize [[META8]]
35
- // ABORT: [[HANDLER_ADD_OVERFLOW]]:
36
- // ABORT-NEXT: [[TMP4:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META8]]
37
- // ABORT-NEXT: [[TMP5:%.*]] = zext i32 [[CONV]] to i64, !nosanitize [[META8]]
38
- // ABORT-NEXT: tail call void @__ubsan_handle_add_overflow_abort(ptr nonnull @{{.+}}, i64 [[TMP4]], i64 [[TMP5]]) #[[ATTR3:[0-9]+]], !nosanitize [[META8]]
39
- // ABORT-NEXT: unreachable, !nosanitize [[META8]]
29
+ // ABORT-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[TMP0]], 0
30
+ // ABORT-NEXT: br i1 [[DOTNOT]], label %[[HANDLER_DIVREM_OVERFLOW:.*]], label %[[CONT:.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META9:![0-9]+]]
31
+ // ABORT: [[HANDLER_DIVREM_OVERFLOW]]:
32
+ // ABORT-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META9]]
33
+ // ABORT-NEXT: tail call void @__ubsan_handle_divrem_overflow_abort(ptr nonnull @{{.+}}, i64 [[TMP2]], i64 0) #[[ATTR3:[0-9]+]], !nosanitize [[META9]]
34
+ // ABORT-NEXT: unreachable, !nosanitize [[META9]]
40
35
// ABORT: [[CONT]]:
41
- // ABORT-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META8]]
42
- // ABORT-NEXT: store i32 [[TMP6]], ptr [[A]], align 4, !tbaa [[TBAA6]]
36
+ // ABORT-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32
37
+ // ABORT-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP1]], [[CONV]]
38
+ // ABORT-NEXT: store i32 [[DIV]], ptr [[A]], align 4, !tbaa [[TBAA6]]
43
39
// ABORT-NEXT: ret i32 [[CONV]]
44
40
//
45
41
int test (int &a, short &c) {
46
- a + = c;
42
+ a / = c;
47
43
return c;
48
44
}
45
+
46
+ // Make sure that we don't eliminate the call to ubsan handler.
47
+ // RECOVER: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
48
+ // RECOVER-LABEL: define dso_local noundef i32 @_Z16test_unreachablev(
49
+ // RECOVER-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] {
50
+ // RECOVER-NEXT: [[ENTRY:.*:]]
51
+ // RECOVER-NEXT: unreachable
52
+ //
53
+ // ABORT: Function Attrs: mustprogress noreturn nounwind
54
+ // ABORT-LABEL: define dso_local noundef i32 @_Z16test_unreachablev(
55
+ // ABORT-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] {
56
+ // ABORT-NEXT: [[ENTRY:.*:]]
57
+ // ABORT-NEXT: tail call void @__ubsan_handle_divrem_overflow_abort(ptr nonnull @{{.+}}, i64 1, i64 0) #[[ATTR3]], !nosanitize [[META9]]
58
+ // ABORT-NEXT: unreachable, !nosanitize [[META9]]
59
+ //
60
+ int test_unreachable () {
61
+ int a = 1 ;
62
+ int b = 0 ;
63
+ if (a / b) return 1 ;
64
+ return 0 ;
65
+ }
66
+
49
67
// .
50
68
// RECOVER: attributes #[[ATTR0]] = { mustprogress nounwind willreturn memory(read, argmem: readwrite, inaccessiblemem: readwrite) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
51
- // RECOVER: attributes #[[ATTR1:[0-9]+]] = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
52
- // RECOVER: attributes #[[ATTR2:[0-9]+]] = { mustprogress willreturn memory(argmem: read, inaccessiblemem: readwrite) uwtable }
69
+ // RECOVER: attributes #[[ATTR1:[0-9]+]] = { mustprogress willreturn memory(argmem: read, inaccessiblemem: readwrite) uwtable }
70
+ // RECOVER: attributes #[[ATTR2]] = { mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
53
71
// RECOVER: attributes #[[ATTR3]] = { nomerge nounwind }
54
72
// .
55
73
// ABORT: attributes #[[ATTR0]] = { mustprogress nounwind "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
56
- // ABORT: attributes #[[ATTR1:[0-9]+]] = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
57
- // ABORT: attributes #[[ATTR2:[0-9]+]] = { noreturn nounwind uwtable }
74
+ // ABORT: attributes #[[ATTR1:[0-9]+]] = { noreturn nounwind uwtable }
75
+ // ABORT: attributes #[[ATTR2]] = { mustprogress noreturn nounwind "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
58
76
// ABORT: attributes #[[ATTR3]] = { nomerge noreturn nounwind }
59
77
// .
60
78
// RECOVER: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
@@ -65,8 +83,8 @@ int test(int &a, short &c) {
65
83
// RECOVER: [[META5]] = !{!"Simple C++ TBAA"}
66
84
// RECOVER: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
67
85
// RECOVER: [[META7]] = !{!"int", [[META4]], i64 0}
68
- // RECOVER: [[META8 ]] = !{}
69
- // RECOVER: [[PROF9 ]] = !{!"branch_weights", i32 1, i32 1048575 }
86
+ // RECOVER: [[PROF8 ]] = !{!"branch_weights", i32 1, i32 1048575 }
87
+ // RECOVER: [[META9 ]] = !{}
70
88
// .
71
89
// ABORT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
72
90
// ABORT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
@@ -76,6 +94,6 @@ int test(int &a, short &c) {
76
94
// ABORT: [[META5]] = !{!"Simple C++ TBAA"}
77
95
// ABORT: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
78
96
// ABORT: [[META7]] = !{!"int", [[META4]], i64 0}
79
- // ABORT: [[META8 ]] = !{}
80
- // ABORT: [[PROF9 ]] = !{!"branch_weights", i32 1, i32 1048575 }
97
+ // ABORT: [[PROF8 ]] = !{!"branch_weights", i32 1, i32 1048575 }
98
+ // ABORT: [[META9 ]] = !{}
81
99
// .
0 commit comments