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
9unsigned short si, sj, sk;
10unsigned char ci, cj, ck;
11
12extern void opaqueshort(unsigned short);
13extern void opaquechar(unsigned char);
14
15// CHECKS-LABEL:   define void @testshortadd()
16// CHECKU-LABEL: define void @testshortadd()
17void testshortadd() {
18  // CHECKS:        load i16* @sj
19  // CHECKS:        load 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* @sj
26  // CHECKU:      [[T2:%.*]] = zext i16 [[T1]]
27  // CHECKU:      [[T3:%.*]] = load 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()
38void testshortsub() {
39
40  // CHECKS:        load i16* @sj
41  // CHECKS:        load 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* @sj
48  // CHECKU:      [[T2:%.*]] = zext i16 [[T1]]
49  // CHECKU:      [[T3:%.*]] = load 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()
60void testshortmul() {
61
62  // CHECKS:        load i16* @sj
63  // CHECKS:        load 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* @sj
70  // CHECKU:      [[T2:%.*]] = zext i16 [[T1]]
71  // CHECKU:      [[T3:%.*]] = load 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()
81void testcharadd() {
82
83  // CHECKS:        load i8* @cj
84  // CHECKS:        load 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* @cj
91  // CHECKU:      [[T2:%.*]] = zext i8 [[T1]]
92  // CHECKU:      [[T3:%.*]] = load 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()
103void testcharsub() {
104
105  // CHECKS:        load i8* @cj
106  // CHECKS:        load 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* @cj
113  // CHECKU:      [[T2:%.*]] = zext i8 [[T1]]
114  // CHECKU:      [[T3:%.*]] = load 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()
125void testcharmul() {
126
127  // CHECKS:        load i8* @cj
128  // CHECKS:        load 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* @cj
135  // CHECKU:      [[T2:%.*]] = zext i8 [[T1]]
136  // CHECKU:      [[T3:%.*]] = load 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