1 // Check -fsanitize=signed-integer-overflow and
2 // -fsanitize=unsigned-integer-overflow with promoted unsigned types
3 //
4 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s \
5 // RUN: -fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKS
6 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s \
7 // RUN: -fsanitize=unsigned-integer-overflow | FileCheck %s --check-prefix=CHECKU
8
9 unsigned short si, sj, sk;
10 unsigned char ci, cj, ck;
11
12 extern void opaqueshort(unsigned short);
13 extern void opaquechar(unsigned char);
14
15 // CHECKS-LABEL: define void @testshortadd()
16 // CHECKU-LABEL: define void @testshortadd()
testshortadd()17 void testshortadd() {
18 // CHECKS: load i16, i16* @sj
19 // CHECKS: load i16, i16* @sk
20 // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
21 // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
22 // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
23 // CHECKS: call void @__ubsan_handle_add_overflow
24 //
25 // CHECKU: [[T1:%.*]] = load i16, i16* @sj
26 // CHECKU: [[T2:%.*]] = zext i16 [[T1]]
27 // CHECKU: [[T3:%.*]] = load i16, i16* @sk
28 // CHECKU: [[T4:%.*]] = zext i16 [[T3]]
29 // CHECKU-NOT: llvm.sadd
30 // CHECKU-NOT: llvm.uadd
31 // CHECKU: [[T5:%.*]] = add nsw i32 [[T2]], [[T4]]
32
33 si = sj + sk;
34 }
35
36 // CHECKS-LABEL: define void @testshortsub()
37 // CHECKU-LABEL: define void @testshortsub()
testshortsub()38 void testshortsub() {
39
40 // CHECKS: load i16, i16* @sj
41 // CHECKS: load i16, i16* @sk
42 // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
43 // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
44 // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
45 // CHECKS: call void @__ubsan_handle_sub_overflow
46 //
47 // CHECKU: [[T1:%.*]] = load i16, i16* @sj
48 // CHECKU: [[T2:%.*]] = zext i16 [[T1]]
49 // CHECKU: [[T3:%.*]] = load i16, i16* @sk
50 // CHECKU: [[T4:%.*]] = zext i16 [[T3]]
51 // CHECKU-NOT: llvm.ssub
52 // CHECKU-NOT: llvm.usub
53 // CHECKU: [[T5:%.*]] = sub nsw i32 [[T2]], [[T4]]
54
55 si = sj - sk;
56 }
57
58 // CHECKS-LABEL: define void @testshortmul()
59 // CHECKU-LABEL: define void @testshortmul()
testshortmul()60 void testshortmul() {
61
62 // CHECKS: load i16, i16* @sj
63 // CHECKS: load i16, i16* @sk
64 // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
65 // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
66 // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
67 // CHECKS: call void @__ubsan_handle_mul_overflow
68 //
69 // CHECKU: [[T1:%.*]] = load i16, i16* @sj
70 // CHECKU: [[T2:%.*]] = zext i16 [[T1]]
71 // CHECKU: [[T3:%.*]] = load i16, i16* @sk
72 // CHECKU: [[T4:%.*]] = zext i16 [[T3]]
73 // CHECKU-NOT: llvm.smul
74 // CHECKU-NOT: llvm.umul
75 // CHECKU: [[T5:%.*]] = mul nsw i32 [[T2]], [[T4]]
76 si = sj * sk;
77 }
78
79 // CHECKS-LABEL: define void @testcharadd()
80 // CHECKU-LABEL: define void @testcharadd()
testcharadd()81 void testcharadd() {
82
83 // CHECKS: load i8, i8* @cj
84 // CHECKS: load i8, i8* @ck
85 // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
86 // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
87 // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
88 // CHECKS: call void @__ubsan_handle_add_overflow
89 //
90 // CHECKU: [[T1:%.*]] = load i8, i8* @cj
91 // CHECKU: [[T2:%.*]] = zext i8 [[T1]]
92 // CHECKU: [[T3:%.*]] = load i8, i8* @ck
93 // CHECKU: [[T4:%.*]] = zext i8 [[T3]]
94 // CHECKU-NOT: llvm.sadd
95 // CHECKU-NOT: llvm.uadd
96 // CHECKU: [[T5:%.*]] = add nsw i32 [[T2]], [[T4]]
97
98 ci = cj + ck;
99 }
100
101 // CHECKS-LABEL: define void @testcharsub()
102 // CHECKU-LABEL: define void @testcharsub()
testcharsub()103 void testcharsub() {
104
105 // CHECKS: load i8, i8* @cj
106 // CHECKS: load i8, i8* @ck
107 // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
108 // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
109 // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
110 // CHECKS: call void @__ubsan_handle_sub_overflow
111 //
112 // CHECKU: [[T1:%.*]] = load i8, i8* @cj
113 // CHECKU: [[T2:%.*]] = zext i8 [[T1]]
114 // CHECKU: [[T3:%.*]] = load i8, i8* @ck
115 // CHECKU: [[T4:%.*]] = zext i8 [[T3]]
116 // CHECKU-NOT: llvm.ssub
117 // CHECKU-NOT: llvm.usub
118 // CHECKU: [[T5:%.*]] = sub nsw i32 [[T2]], [[T4]]
119
120 ci = cj - ck;
121 }
122
123 // CHECKS-LABEL: define void @testcharmul()
124 // CHECKU-LABEL: define void @testcharmul()
testcharmul()125 void testcharmul() {
126
127 // CHECKS: load i8, i8* @cj
128 // CHECKS: load i8, i8* @ck
129 // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]])
130 // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0
131 // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1
132 // CHECKS: call void @__ubsan_handle_mul_overflow
133 //
134 // CHECKU: [[T1:%.*]] = load i8, i8* @cj
135 // CHECKU: [[T2:%.*]] = zext i8 [[T1]]
136 // CHECKU: [[T3:%.*]] = load i8, i8* @ck
137 // CHECKU: [[T4:%.*]] = zext i8 [[T3]]
138 // CHECKU-NOT: llvm.smul
139 // CHECKU-NOT: llvm.umul
140 // CHECKU: [[T5:%.*]] = mul nsw i32 [[T2]], [[T4]]
141
142 ci = cj * ck;
143 }
144