blob: d4b7a65249fae582b8774cbfd6a5dc4490136d37 [file] [log] [blame]
//===--- ParameterPassing.swift -------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// RUN: %empty-directory(%t)
// RUN: %gyb %s -o %t/ParameterPassing.swift
// RUN: %line-directive %t/ParameterPassing.swift -- %target-build-swift %t/ParameterPassing.swift -o %t/a.out_Release -O
// RUN: %target-run %t/a.out_Release
// REQUIRES: executable_test
// REQUIRES: long_test
import StdlibUnittest
let tests = TestSuite("ParameterPassing")
struct MyError : Error {
let val = 127
}
%{
errorMethodTypes = [
('Throwing', 'throws', True, 'true'),
('Throws', 'throws', True, 'false'),
('', '', False, 'false'),
]
}%
// Float values.
% for TestType in 'Float', 'Double':
% for Num in range(0, 10):
@inline(__always)
func value${TestType}${Num}() -> ${TestType} {
return 1.${Num+1}
}
% end
% end
// Integer values.
% for TestType in 'UInt8', 'UInt16', 'UInt32', 'UInt64', 'Int8', 'Int16', 'Int32', 'Int64':
enum Enum${TestType} : Equatable {
case Empty
case Value(${TestType})
}
func == (lhs: Enum${TestType}, rhs: Enum${TestType}) -> Bool {
switch lhs {
case .Empty:
switch rhs {
case .Empty:
return true
case .Value(_):
return false
}
case .Value(let lhsVal):
switch lhs {
case .Empty:
return false
case .Value(let rhsVal):
return lhsVal == rhsVal
}
}
}
struct Struct${TestType} : Equatable {
let f0 : ${TestType}
let f1: Float
let f2: Double
init(f0: ${TestType}, f1: Float, f2: Double) {
self.f0 = f0
self.f1 = f1
self.f2 = f2
}
}
func ==(lhs: Struct${TestType}, rhs: Struct${TestType}) -> Bool {
return lhs.f0 == rhs.f0 && lhs.f1 == rhs.f1 && lhs.f2 == rhs.f2
}
% for Num in range(0, 10):
@inline(__always)
func value${TestType}${Num}() -> ${TestType} {
return ${Num+1}
}
@inline(__always)
func valueEnum${TestType}${Num}() -> Enum${TestType} {
return Enum${TestType}.Value(${Num+1})
}
func valueStruct${TestType}${Num}() -> Struct${TestType} {
return Struct${TestType}(f0: ${Num+1}, f1: 1.${Num}, f2: 2.${Num})
}
% end
% end
// Float80 values.
#if arch(i386) || arch(x86_64)
% for Num in range(0, 10):
@inline(__always)
func valueFloat80${Num}() -> Float80 {
return 1.${Num+1}
}
% end
#endif
% for (FuncName, Throw, MayThrow, DoesThrow) in errorMethodTypes:
@inline(never)
func clobber${FuncName}(
_ d0: Double, _ d1: Double, _ d2: Double, _ d3: Double, _ d4: Double, _ d5: Double,
_ d6: Double, _ d7: Double, _ d8: Double, _ d9: Double, _ i0: Int, _ i1: Int,
_ i2: Int, _ i3: Int, _ i4: Int, _ i5: Int, _ i6: Int, _ i7: Int, _ i8: Int,
_ i9: Int
) ${Throw} -> (Double, Int) {
let sumD = d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9
let sumI = i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9
% if MayThrow:
var shouldThrow = ${DoesThrow}
withUnsafeMutablePointer(to: &shouldThrow, { _blackHole($0) })
if shouldThrow {
throw MyError()
}
% end
return (sumD, sumI)
}
%end
%{ testTypes = [
'Float', 'Float80', 'Double', 'UInt8', 'UInt16', 'UInt32', 'UInt64',
'Int8', 'Int16', 'Int32', 'Int64',
'EnumUInt8', 'EnumUInt16', 'EnumUInt32', 'EnumUInt64', 'EnumInt8',
'EnumInt16', 'EnumInt32', 'EnumInt64',
'StructUInt8', 'StructUInt16', 'StructUInt32', 'StructUInt64',
'StructInt8', 'StructInt16', 'StructInt32', 'StructInt64',
]
}%
% for TestType in testTypes:
% if TestType == 'Float80':
#if arch(i386) || arch(x86_64)
% end
% for (FuncName, Throw, MayThrow, DoesThrow) in errorMethodTypes:
@inline(never)
func verifyParameters${TestType}${FuncName}(
_ p0: ${TestType}, _ p1: ${TestType}, _ p2: ${TestType}, _ p3: ${TestType}, _ p4: ${TestType}, _ p5: ${TestType},
_ p6: ${TestType}, _ p7: ${TestType}, _ p8: ${TestType}, _ p9 : ${TestType}
) ${Throw} {
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
% if MayThrow:
let res = try clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% else:
let res = clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% end
2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
precondition(res.0 == 5.5)
precondition(res.1 == 129)
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
}
@inline(never)
func verifyReturn${TestType}${FuncName}() ${Throw} -> (
% for Num in range(0, 9):
${TestType},
% end
${TestType}
)
{
% if MayThrow:
var shouldThrow = ${DoesThrow}
withUnsafeMutablePointer(to: &shouldThrow, { _blackHole($0) })
if shouldThrow {
throw MyError()
}
% end
return (
% for Num in range(0, 9):
value${TestType}${Num}(),
% end
value${TestType}9()
)
}
@inline(never)
func verifyReturnAndParameters${TestType}${FuncName}(
_ p0: ${TestType}, _ p1: ${TestType}, _ p2: ${TestType}, _ p3: ${TestType}, _ p4: ${TestType}, _ p5: ${TestType},
_ p6: ${TestType}, _ p7: ${TestType}, _ p8: ${TestType}, _ p9 : ${TestType}
) ${Throw} -> (
% for Num in range(0, 9):
${TestType},
% end
${TestType}
)
{
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
% if MayThrow:
let res = try clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% else:
let res = clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% end
2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
precondition(res.0 == 5.5)
precondition(res.1 == 129)
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
return (
% for Num in range(0, 9):
value${TestType}${Num}(),
% end
value${TestType}9()
)
}
% end
protocol Proto${TestType} {
% for (FuncName, Throw, _, _) in errorMethodTypes:
func verifyParameters${FuncName}(
_ p0: ${TestType}, _ p1: ${TestType}, _ p2: ${TestType}, _ p3: ${TestType}, _ p4: ${TestType}, _ p5: ${TestType},
_ p6: ${TestType}, _ p7: ${TestType}, _ p8: ${TestType}, _ p9 : ${TestType}
) ${Throw}
func verifyReturn${FuncName}() ${Throw} -> (
% for Num in range(0, 9):
${TestType},
% end
${TestType}
)
@inline(never)
func verifyReturnAndParameters${FuncName}(
_ p0: ${TestType}, _ p1: ${TestType}, _ p2: ${TestType}, _ p3: ${TestType}, _ p4: ${TestType}, _ p5: ${TestType},
_ p6: ${TestType}, _ p7: ${TestType}, _ p8: ${TestType}, _ p9 : ${TestType}
) ${Throw} -> (
% for Num in range(0, 9):
${TestType},
% end
${TestType}
)
%end
}
public class A${TestType} : Proto${TestType} {
var dontStripSelfArg: Int = 7
init() {}
% for (FuncName, Throw, MayThrow, _) in errorMethodTypes:
@inline(never)
func verifyParameters${FuncName}(
_ p0: ${TestType}, _ p1: ${TestType}, _ p2: ${TestType}, _ p3: ${TestType}, _ p4: ${TestType}, _ p5: ${TestType},
_ p6: ${TestType}, _ p7: ${TestType}, _ p8: ${TestType}, _ p9 : ${TestType}
) ${Throw} {
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
% if MayThrow:
let res = try clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% else:
let res = clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% end
2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
precondition(dontStripSelfArg == 7)
precondition(res.0 == 5.5)
precondition(res.1 == 129)
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
}
func verifyReturn${FuncName}() ${Throw} -> (
% for Num in range(0, 9):
${TestType},
% end
${TestType}
)
{
% if MayThrow:
var shouldThrow = ${DoesThrow}
withUnsafeMutablePointer(to: &shouldThrow, { _blackHole($0) })
if shouldThrow {
throw MyError()
}
% end
return (
% for Num in range(0, 9):
value${TestType}${Num}(),
% end
value${TestType}9()
)
}
@inline(never)
func verifyReturnAndParameters${FuncName}(
_ p0: ${TestType}, _ p1: ${TestType}, _ p2: ${TestType}, _ p3: ${TestType}, _ p4: ${TestType}, _ p5: ${TestType},
_ p6: ${TestType}, _ p7: ${TestType}, _ p8: ${TestType}, _ p9 : ${TestType}
) ${Throw} -> (
% for Num in range(0, 9):
${TestType},
% end
${TestType}
)
{
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
% if MayThrow:
let res = try clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% else:
let res = clobber${FuncName}(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
% end
2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
precondition(res.0 == 5.5)
precondition(res.1 == 129)
% for Num in range(0, 10):
precondition(p${Num} == value${TestType}${Num}())
% end
return (
% for Num in range(0, 9):
value${TestType}${Num}(),
% end
value${TestType}9()
)
}
% end
}
% for (FuncName, throw, MayThrow, DoesThrow) in errorMethodTypes:
tests.test("${TestType}/Fun${FuncName}") {
// Test a regular function call.
% if MayThrow:
do {
try verifyParameters${TestType}${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
verifyParameters${TestType}${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% end
}
tests.test("${TestType}/RetFun${FuncName}") {
// Test a regular function call.
% if MayThrow:
do {
let res = try verifyReturn${TestType}${FuncName}()
% for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
let res = verifyReturn${TestType}${FuncName}()
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% end
}
tests.test("${TestType}/RetAndParamFun${FuncName}") {
// Test a regular function call.
% if MayThrow:
do {
let res = try verifyReturnAndParameters${TestType}${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
let res = verifyReturnAndParameters${TestType}${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% end
}
tests.test("${TestType}/Method${FuncName}") {
var klazz = A${TestType}()
// Defeat type analysis such that the call below remains a method call.
withUnsafeMutablePointer(to: &klazz, { _blackHole($0) })
// Test a method call.
% if MayThrow:
do {
try klazz.verifyParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
klazz.verifyParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% end
}
tests.test("${TestType}/RetMethod${FuncName}") {
var klazz = A${TestType}()
// Defeat type analysis such that the call below remains a method call.
withUnsafeMutablePointer(to: &klazz, { _blackHole($0) })
// Test a method call.
% if MayThrow:
do {
let res = try klazz.verifyReturn${FuncName}()
% for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
let res = klazz.verifyReturn${FuncName}()
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% end
}
tests.test("${TestType}/RetAndParamMethod${FuncName}") {
var klazz = A${TestType}()
// Defeat type analysis such that the call below remains a method call.
withUnsafeMutablePointer(to: &klazz, { _blackHole($0) })
// Test a method call.
% if MayThrow:
do {
let res = try klazz.verifyReturnAndParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
let res = klazz.verifyReturnAndParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% end
}
tests.test("${TestType}/WitnessMethod${FuncName}") {
var p : Proto${TestType} = A${TestType}()
withUnsafeMutablePointer(to: &p, { _blackHole($0) })
// Test a witness method call.
% if MayThrow:
do {
try p.verifyParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
p.verifyParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
% end
}
tests.test("${TestType}/RetWitnessMethod${FuncName}") {
var p : Proto${TestType} = A${TestType}()
withUnsafeMutablePointer(to: &p, { _blackHole($0) })
// Test a witness method call.
% if MayThrow:
do {
let res = try p.verifyReturn${FuncName}()
% for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
let res = p.verifyReturn${FuncName}()
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% end
}
tests.test("${TestType}/RetAndParamWitnessMethod${FuncName}") {
var p : Proto${TestType} = A${TestType}()
withUnsafeMutablePointer(to: &p, { _blackHole($0) })
// Test a method call.
% if MayThrow:
do {
let res = try p.verifyReturnAndParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% if DoesThrow == 'true':
} catch let e as MyError {
expectEqual(127, e.val)
% end
} catch {
preconditionFailure("Should not get there")
}
% else:
let res = p.verifyReturnAndParameters${FuncName}(
%for Num in range(0, 9):
value${TestType}${Num}(),
%end
value${TestType}9()
)
%for Num in range(0, 10):
expectEqual(value${TestType}${Num}(), res.${Num})
% end
% end
}
% end
% if TestType == 'Float80':
#endif
% end
% end
runAllTests()