// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: %gyb %s -o %t/FixedPointArithmeticTraps.swift // RUN: %line-directive %t/FixedPointArithmeticTraps.swift -- %target-build-swift %t/FixedPointArithmeticTraps.swift -o %t/a.out_Debug // RUN: %line-directive %t/FixedPointArithmeticTraps.swift -- %target-build-swift %t/FixedPointArithmeticTraps.swift -o %t/a.out_Release -O // // RUN: %line-directive %t/FixedPointArithmeticTraps.swift -- %target-run %t/a.out_Debug // RUN: %line-directive %t/FixedPointArithmeticTraps.swift -- %target-run %t/a.out_Release // REQUIRES: executable_test import StdlibUnittest // Note: in this file, we need to go through opaque functions to load // constants. This is to check runtime behavior and ensure the constant is // not folded. func expectOverflow( _ res: (T, overflow: Bool), //===--- TRACE boilerplate ----------------------------------------------===// _ message: @autoclosure () -> 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 ----------------------------------------------===// _ message: @autoclosure () -> 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 all_integer_types # 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 += 1 x = get${IntTy}(${IntTy}.min) expectCrashLater() // IntTy.min -= 1 x -= 1 _blackHole(x) } FixedPointArithmeticTraps.test("PreIncrement/${IntTy}") { var x = get${IntTy}(${IntTy}.max) x -= 1 x = get${IntTy}(${IntTy}.max) expectCrashLater() // IntTy.max += 1 x += 1 _blackHole(x) } FixedPointArithmeticTraps.test("PostDecrement/${IntTy}") { var x = get${IntTy}(${IntTy}.min) x += 1 x = get${IntTy}(${IntTy}.min) expectCrashLater() // IntTy.min -= 1 x -= 1 _blackHole(x) } FixedPointArithmeticTraps.test("PostIncrement/${IntTy}") { var x = get${IntTy}(${IntTy}.max) x -= 1 x = get${IntTy}(${IntTy}.max) expectCrashLater() // IntTy.max += 1 x += 1 _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("Multiplication/${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}(MemoryLayout<${IntTy}>.size * 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}(MemoryLayout<${IntTy}>.size * 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 runAllTests()