blob: a1c416e2fdab63a329a1026e3d44a340475a4cc0 [file] [log] [blame]
// RUN: %empty-directory(%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 -Onone
// RUN: %line-directive %t/FixedPointArithmeticTraps.swift -- %target-build-swift %t/FixedPointArithmeticTraps.swift -o %t/a.out_Release -O
// RUN: %target-codesign %t/a.out_Debug
// RUN: %target-codesign %t/a.out_Release
//
// 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<T>(
_ res: (partialValue: 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<T>(
_ res: (partialValue: 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(a.addingReportingOverflow(get${IntTy}(${IntTy}.max / 3)))
a = a + get${IntTy}(${IntTy}.max / 3)
expectNoOverflow(a.addingReportingOverflow(get${IntTy}(${IntTy}.max / 3)))
a = a + get${IntTy}(${IntTy}.max / 3)
// Overflow in addition.
expectOverflow(a.addingReportingOverflow(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(a.subtractingReportingOverflow(get${IntTy}(${IntTy}.max / 3)))
a = a - get${IntTy}(${IntTy}.max / 3)
// Overflow in subtraction.
expectOverflow(a.subtractingReportingOverflow(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(a.multipliedReportingOverflow(by: get${IntTy}(2)))
a = a * get${IntTy}(2)
// Overflow in multiplication.
expectOverflow(a.multipliedReportingOverflow(by: 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(a.dividedReportingOverflow(by: get${IntTy}(3)))
a = a / get${IntTy}(3)
// x / 0
expectOverflow(a.dividedReportingOverflow(by: 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(a.dividedReportingOverflow(by: get${IntTy}(3)))
a = a / get${IntTy}(3)
a = get${IntTy}(${IntTy}.min)
expectOverflow(a.dividedReportingOverflow(by: 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(a.remainderReportingOverflow(dividingBy: get${IntTy}(3)))
a = a % get${IntTy}(3)
// x % 0
expectOverflow(a.remainderReportingOverflow(dividingBy: 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(a.remainderReportingOverflow(dividingBy: get${IntTy}(3)))
a = a % get${IntTy}(3)
// Int.min % -1
a = get${IntTy}(${IntTy}.min)
expectOverflow(a.remainderReportingOverflow(dividingBy: get${IntTy}(-1)))
expectCrashLater()
a = a % get${IntTy}(-1)
_blackHole(a)
}
% end
// This comment prevents gyb from miscompiling this file.
// <rdar://problem/17548877> gyb miscompiles a certain for loop
% end
runAllTests()