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