// 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 // REQUIRES: executable_test import StdlibUnittest // Also import modules which are used by StdlibUnittest internally. This is // needed to link all required libraries in case we serialize StdlibUnittest. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif // 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), //===--- TRACE boilerplate ----------------------------------------------===// @autoclosure _ message: ()->String = "", showFrame: Bool = true, stackTrace: SourceLocStack = SourceLocStack(), file: String = __FILE__, line: UInt = __LINE__ ) { expectTrue( res.overflow, "expected overflow", stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) } func expectNoOverflow( res: (T, overflow: Bool), //===--- TRACE boilerplate ----------------------------------------------===// @autoclosure _ message: ()->String = "", showFrame: Bool = true, stackTrace: SourceLocStack = SourceLocStack(), file: String = __FILE__, line: UInt = __LINE__ ) { expectFalse( res.overflow, "expected no overflow", stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) } %{ 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 _blackHole(x) } FixedPointArithmeticTraps.test("PreIncrement/${IntTy}") { var x = get${IntTy}(${IntTy}.max) --x x = get${IntTy}(${IntTy}.max) expectCrashLater() // ++IntTy.max ++x _blackHole(x) } FixedPointArithmeticTraps.test("PostDecrement/${IntTy}") { var x = get${IntTy}(${IntTy}.min) x++ x = get${IntTy}(${IntTy}.min) expectCrashLater() // IntTy.min-- x-- _blackHole(x) } FixedPointArithmeticTraps.test("PostIncrement/${IntTy}") { var x = get${IntTy}(${IntTy}.max) x-- x = get${IntTy}(${IntTy}.max) expectCrashLater() // IntTy.max++ x++ _blackHole(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) _blackHole(a) } // // 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) _blackHole(a) } // // 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) _blackHole(a) } // // 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 _blackHole(a) } % 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) _blackHole(a) } % 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) _blackHole(a) } % 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) _blackHole(a) } % 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) _blackHole(a) } 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) _blackHole(a) } 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) _blackHole(a) } % 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() var result = Int8(x) _blackHole(result) } FixedPointTruncationTraps.test("SignedToUnsignedTruncation/src=-1") { var x = getInt32(-1) expectCrashLater() var result = UInt8(x) _blackHole(result) } FixedPointTruncationTraps.test("SignedToUnignedSameSize/src=min") { var x = getInt8(-128) expectCrashLater() var result = UInt16(x) _blackHole(result) } FixedPointTruncationTraps.test("SignedToUnsignedTruncation/src=max") { var x = getInt32(0xFFFFFFF) expectCrashLater() var result = UInt16(x) _blackHole(result) } FixedPointTruncationTraps.test("UnsignedToSignedTruncation/dest=sign-overflow") { // Test that we check if we overflow on the sign bit. var x = getUInt16(128) expectCrashLater() var result = Int8(x) _blackHole(result) } FixedPointTruncationTraps.test("UnsignedToUnsignedTruncation/src=max") { var x = getUInt32(0xFFFFFFFF) expectCrashLater() var result = UInt16(x) _blackHole(result) } // Same size conversions. FixedPointTruncationTraps.test("SignedToUnsignedSameSize") { var x = getInt8(-2) expectCrashLater() var result = UInt8(x) _blackHole(result) } FixedPointTruncationTraps.test("UnsignedToSignedSameSize") { var x = getUInt8(128) expectCrashLater() var result = Int8(x) _blackHole(result) } runAllTests()