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