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