Skip to content

Commit c7af94b

Browse files
committed
[Swiftify] Don't drop bounds checks when mixing std::span and counted_by
When an imported function combines std::span and __counted_by, std::span would override bounds checks emitted for __counted_by (if it occurred later in the the parameter list) resulting in no bounds checks being emitted. rdar://147883384
1 parent 98d6480 commit c7af94b

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ struct CxxSpanThunkBuilder: ParamPointerBoundsThunkBuilder {
411411
let isSizedBy: Bool = false
412412

413413
func buildBoundsChecks() throws -> [CodeBlockItemSyntax.Item] {
414-
return []
414+
return try base.buildBoundsChecks()
415415
}
416416

417417
func buildFunctionSignature(_ argTypes: [Int: TypeSyntax?], _ returnType: TypeSyntax?) throws
@@ -447,7 +447,7 @@ struct CxxSpanReturnThunkBuilder: BoundsCheckedThunkBuilder {
447447
public let node: SyntaxProtocol
448448

449449
func buildBoundsChecks() throws -> [CodeBlockItemSyntax.Item] {
450-
return []
450+
return try base.buildBoundsChecks()
451451
}
452452

453453
func buildFunctionSignature(_ argTypes: [Int: TypeSyntax?], _ returnType: TypeSyntax?) throws

test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11

22
// REQUIRES: swift_swift_parser
33

4-
// RUN: %target-swift-frontend %s -enable-experimental-cxx-interop -I %S/Inputs -Xcc -std=c++20 -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions -verify -strict-memory-safety 2>&1 | %FileCheck --match-full-lines %s
4+
// FIXME: buggy sort order for return value transformation gives compilation error in expansion
5+
// RUN: not %target-swift-frontend %s -enable-experimental-cxx-interop -I %S/Inputs -Xcc -std=c++20 -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions -verify -strict-memory-safety 2>&1 | %FileCheck --match-full-lines %s
56

67
// FIXME swift-ci linux tests do not support std::span
78
// UNSUPPORTED: OS=linux-gnu
@@ -32,6 +33,13 @@ struct X {
3233
func myFunc5() -> SpanOfInt {}
3334
}
3435

36+
@_SwiftifyImport(.lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy),
37+
.sizedBy(pointer: .param(2), size: "count * size"),
38+
.nonescaping(pointer: .param(2)),
39+
typeMappings: ["SpanOfInt" : "std.span<CInt>"])
40+
func myFunc6(_ span: SpanOfInt, _ ptr: UnsafeRawPointer, _ count: CInt, _ size: CInt) -> SpanOfInt {
41+
}
42+
3543
// CHECK: @_alwaysEmitIntoClient @lifetime(copy span)
3644
// CHECK-NEXT: func myFunc(_ span: Span<CInt>) -> Span<CInt> {
3745
// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: myFunc(SpanOfInt(span))), copying: ())
@@ -56,3 +64,14 @@ struct X {
5664
// CHECK-NEXT: func myFunc5() -> Span<CInt> {
5765
// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: myFunc5()), copying: ())
5866
// CHECK-NEXT: }
67+
68+
// CHECK: @_alwaysEmitIntoClient @lifetime(copy span)
69+
// CHECK-NEXT: func myFunc6(_ span: Span<CInt>, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span<CInt> {
70+
// CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size
71+
// CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 {
72+
// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function")
73+
// CHECK-NEXT: }
74+
// CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in
75+
// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: myFunc6(SpanOfInt(span), _ptrPtr.baseAddress!, count, size)), copying: ())
76+
// CHECK-NEXT: }
77+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)