// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: %S/../../utils/gyb %s -o %t/FixedPointArithmeticTraps.swift // RUN: %S/../../utils/line-directive %t/FixedPointArithmeticTraps.swift -- %target-build-swift %t/FixedPointArithmeticTraps.swift -o %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/FixedPointArithmeticTraps.swift -- %target-build-swift %t/FixedPointArithmeticTraps.swift -o %t/a.out_Release -O // // RUN: %S/../../utils/line-directive %t/FixedPointArithmeticTraps.swift -- %target-run %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/FixedPointArithmeticTraps.swift -- %target-run %t/a.out_Release // XFAIL: linux import StdlibUnittest // Note: in this file, we need to go through opaque functions to load // constants. This is to to check runtime behaviour and ensure the constant is // not folded. func expectOverflow( res: (T, overflow: Bool), file: String = __FILE__, line: UWord = __LINE__ ) { expectTrue( res.overflow, stackTrace: SourceLoc(file, line).withCurrentLoc()) { "expected overflow" } } func expectNoOverflow( res: (T, overflow: Bool), file: String = __FILE__, line: UWord = __LINE__ ) { expectFalse( res.overflow, stackTrace: SourceLoc(file, line).withCurrentLoc()) { "expected no overflow" } } %{ from SwiftIntTypes import * # Test cases are written in a way that they don't depend on the word size. word_bits = 4 }% var FixedPointArithmeticTraps = TestSuite("FixedPointArithmeticTraps") % for self_ty in all_integer_types(word_bits): % IntTy = self_ty.stdlib_name // // Test pre- and post-increment/decrement for ${IntTy} // FixedPointArithmeticTraps.test("PreDecrement/${IntTy}") { var x = get${IntTy}(${IntTy}.min) ++x x = get${IntTy}(${IntTy}.min) expectCrashLater() // --IntTy.min --x } FixedPointArithmeticTraps.test("PreIncrement/${IntTy}") { var x = get${IntTy}(${IntTy}.max) --x x = get${IntTy}(${IntTy}.max) expectCrashLater() // ++IntTy.max ++x } FixedPointArithmeticTraps.test("PostDecrement/${IntTy}") { var x = get${IntTy}(${IntTy}.min) x++ x = get${IntTy}(${IntTy}.min) expectCrashLater() // IntTy.min-- x-- } FixedPointArithmeticTraps.test("PostIncrement/${IntTy}") { var x = get${IntTy}(${IntTy}.max) x-- x = get${IntTy}(${IntTy}.max) expectCrashLater() // IntTy.max++ x++ } // // Test addition for ${IntTy} // FixedPointArithmeticTraps.test("Addition/${IntTy}") { var a = get${IntTy}(${IntTy}.max / 3) expectNoOverflow(${IntTy}.addWithOverflow(a, get${IntTy}(${IntTy}.max / 3))) a = a + get${IntTy}(${IntTy}.max / 3) expectNoOverflow(${IntTy}.addWithOverflow(a, get${IntTy}(${IntTy}.max / 3))) a = a + get${IntTy}(${IntTy}.max / 3) // Overflow in addition. expectOverflow(${IntTy}.addWithOverflow(a, get${IntTy}(${IntTy}.max / 3))) expectCrashLater() a = a + get${IntTy}(${IntTy}.max / 3) } // // Test subtraction for ${IntTy} // FixedPointArithmeticTraps.test("Subtraction/${IntTy}") { var a = get${IntTy}(${IntTy}.min + get${IntTy}(${IntTy}.max / 3)) expectNoOverflow(${IntTy}.subtractWithOverflow(a, get${IntTy}(${IntTy}.max / 3))) a = a - get${IntTy}(${IntTy}.max / 3) // Overflow in subtraction. expectOverflow(${IntTy}.subtractWithOverflow(a, get${IntTy}(${IntTy}.max / 3))) expectCrashLater() a = a - get${IntTy}(${IntTy}.max / 3) } // // Test multiplication for ${IntTy} // FixedPointArithmeticTraps.test("Multplication/${IntTy}") { var a = get${IntTy}(${IntTy}.max / 3) expectNoOverflow(${IntTy}.multiplyWithOverflow(a, get${IntTy}(2))) a = a * get${IntTy}(2) // Overflow in multiplication. expectOverflow(${IntTy}.multiplyWithOverflow(a, get${IntTy}(2))) expectCrashLater() a = a * get${IntTy}(2) } // // Test division for ${IntTy} // FixedPointArithmeticTraps.test("Division/${IntTy}") { var a = get${IntTy}(${IntTy}.max / 3) // x / 3 expectNoOverflow(${IntTy}.divideWithOverflow(a, get${IntTy}(3))) a = a / get${IntTy}(3) // x / 0 expectOverflow(${IntTy}.divideWithOverflow(a, get${IntTy}(0))) expectCrashLater() a = a / get${IntTy}(0) } % if self_ty.is_signed: FixedPointArithmeticTraps.test("Division/${IntTy}.min-over-minus-one") { var a = get${IntTy}(${IntTy}.min) expectNoOverflow(${IntTy}.divideWithOverflow(a, get${IntTy}(3))) a = a / get${IntTy}(3) a = get${IntTy}(${IntTy}.min) expectOverflow(${IntTy}.divideWithOverflow(a, get${IntTy}(-1))) expectCrashLater() a = a / get${IntTy}(-1) // IntTy.min / -1 } % end // // Test remainder computation for ${IntTy} // FixedPointArithmeticTraps.test("Remainder/${IntTy}") { var a = get${IntTy}(${IntTy}.max / 3) // x % 3 expectNoOverflow(${IntTy}.remainderWithOverflow(a, get${IntTy}(3))) a = a % get${IntTy}(3) // x % 0 expectOverflow(${IntTy}.remainderWithOverflow(a, get${IntTy}(0))) expectCrashLater() a = a % get${IntTy}(0) } % if self_ty.is_signed: FixedPointArithmeticTraps.test("Remainder/${IntTy}.min-mod-minus-one") { var a = get${IntTy}(${IntTy}.min) // Int.min % 3 expectNoOverflow(${IntTy}.remainderWithOverflow(a, get${IntTy}(3))) a = a % get${IntTy}(3) // Int.min % -1 a = get${IntTy}(${IntTy}.min) expectOverflow(${IntTy}.remainderWithOverflow(a, get${IntTy}(-1))) expectCrashLater() a = a % get${IntTy}(-1) } % end % for (description, operation) in [("RightShift", ">>"), ("LeftShift", "<<")]: // // Test ${description} for ${IntTy} // % if self_ty.is_signed: FixedPointArithmeticTraps.test("${description}/${IntTy}/Negative") { var a = get${IntTy}(${IntTy}.max / 3) a = get${IntTy}(a ${operation} get${IntTy}(1)) let shiftAmount: ${IntTy} = -1 // Overflow in ${description}. expectCrashLater() a = a ${operation} get${IntTy}(shiftAmount) } % end FixedPointArithmeticTraps.test("${description}/${IntTy}/TypeSize") { var a = get${IntTy}(${IntTy}.max / 3) a = get${IntTy}(a ${operation} get${IntTy}(0)) a = get${IntTy}(a ${operation} get${IntTy}(1)) let shiftAmount = ${IntTy}(sizeof(${IntTy}.self) * 8) // Overflow in ${description}. expectCrashLater() a = a ${operation} get${IntTy}(shiftAmount) } FixedPointArithmeticTraps.test("${description}/${IntTy}/TypeSizePlusOne") { var a = get${IntTy}(${IntTy}.max / 3) a = get${IntTy}(a ${operation} get${IntTy}(0)) let shiftAmount = ${IntTy}(sizeof(${IntTy}.self) * 8 + 1) // Overflow in ${description}. expectCrashLater() a = a ${operation} get${IntTy}(shiftAmount) } FixedPointArithmeticTraps.test("${description}/${IntTy}/Max") { var a = get${IntTy}(${IntTy}.max / 3) a = get${IntTy}(a ${operation} get${IntTy}(0)) let shiftAmount: ${IntTy} = ${IntTy}.max // Overflow in ${description}. expectCrashLater() a = a ${operation} get${IntTy}(shiftAmount) } % end // This comment prevents gyb from miscompiling this file. // gyb miscompiles a certain for loop % end // FIXME: these tests should be more thorough, and test all combinations of // types and error conditions. var FixedPointTruncationTraps = TestSuite("FixedPointTruncationTraps") FixedPointTruncationTraps.test("SignedToSignedTruncation/dest=sign-overflow") { // Test that we check if we overflow on the sign bit. var x = getInt16(128) expectCrashLater() Int8(x) } FixedPointTruncationTraps.test("SignedToUnsignedTruncation/src=-1") { var x = getInt32(-1) expectCrashLater() UInt8(x) } FixedPointTruncationTraps.test("SignedToUnignedSameSize/src=min") { var x = getInt8(-128) expectCrashLater() UInt16(x) } FixedPointTruncationTraps.test("SignedToUnsignedTruncation/src=max") { var x = getInt32(0xFFFFFFF) expectCrashLater() UInt16(x) } FixedPointTruncationTraps.test("UnsignedToSignedTruncation/dest=sign-overflow") { // Test that we check if we overflow on the sign bit. var x = getUInt16(128) expectCrashLater() Int8(x) } FixedPointTruncationTraps.test("UnsignedToUnsignedTruncation/src=max") { var x = getUInt32(0xFFFFFFFF) expectCrashLater() UInt16(x) } // Same size conversions. FixedPointTruncationTraps.test("SignedToUnsignedSameSize") { var x = getInt8(-2) expectCrashLater() UInt8(x) } FixedPointTruncationTraps.test("UnsignedToSignedSameSize") { var x = getUInt8(128) expectCrashLater() Int8(x) } runAllTests()