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() 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() 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() 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() 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() 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() 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