// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: %S/../../utils/gyb %s -o %t/ArrayTraps.swift // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-build-swift %t/ArrayTraps.swift -o %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-build-swift %t/ArrayTraps.swift -o %t/a.out_Release -O // // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-run %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-run %t/a.out_Release // REQUIRES: executable_test import StdlibUnittest // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif %{ # We test for bounds-checking traps for both reading and writing # both single elements and slices of all three different array # types. array_types = ('Array', 'ContiguousArray', 'ArraySlice') def bounds_trap(index, expr_to_write): global io return 'expectCrashLater()\n' + ( 'let x = a[%s]' % index if io == 'read' else 'a[%s] = %s' % (index, expr_to_write)) }% % for ArrayTy in array_types: var ${ArrayTy}Traps = TestSuite("${ArrayTy}Traps") % for io in ['read', 'write']: ${ArrayTy}Traps.test("bounds1/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [] ${bounds_trap(index='0', expr_to_write='1')} } ${ArrayTy}Traps.test("bounds2/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [] ${bounds_trap(index='100', expr_to_write='1')} } ${ArrayTy}Traps.test("bounds3/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [ 10, 20, 30 ] ${bounds_trap(index='3', expr_to_write='1')} } ${ArrayTy}Traps.test("sliceBounds0/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [] ${bounds_trap(index='-1..<1', expr_to_write='ArraySlice()')} } ${ArrayTy}Traps.test("sliceBounds1/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [ 1 ] ${bounds_trap(index='-1..<1', expr_to_write='ArraySlice()')} } ${ArrayTy}Traps.test("sliceBounds2/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [ 1 ] ${bounds_trap(index='0..<2', expr_to_write='ArraySlice()')} } ${ArrayTy}Traps.test("sliceBounds3/${io}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [ 1 ] ${bounds_trap(index='1..<2', expr_to_write='ArraySlice()')} } % end ${ArrayTy}Traps.test("PopFromEmpty") { var a: ${ArrayTy} = [] expectCrashLater() a.removeLast() } % for index in -1, 2: ${ArrayTy}Traps.test("${'insert(_:at:)/%s' % index}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [42] expectCrashLater() a.insert(3, at: ${index}) } % end % for index in -1, 1, 2: ${ArrayTy}Traps.test("${'remove(at:)/%s' % index}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a: ${ArrayTy} = [42] expectCrashLater() a.remove(at: ${index}) } % end % end ArrayTraps.test("unsafeLength") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { var a = [ 42, 77, 88 ] expectEqual(42, a.withUnsafeBufferPointer({ $0[0] })) expectCrashLater() a.withUnsafeBufferPointer { UnsafeBufferPointer(start: $0.baseAddress, count: -1) } } runAllTests()