Skip to content

Commit 2a5439a

Browse files
committed
[interop][SwiftToCxx] ensure that buffers for heap allocated Swift values are released after parameter copy is consumed
1 parent c86184e commit 2a5439a

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

lib/PrintAsClang/_SwiftCxxInteroperability.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ extern "C" void _fatalError_Cxx_move_of_Swift_value_type_not_supported_yet();
110110

111111
SWIFT_INLINE_THUNK void *_Nonnull opaqueAlloc(size_t size,
112112
size_t align) noexcept {
113+
#if defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc) && \
114+
defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free)
115+
// Allow the user to provide custom allocator for heap-allocated Swift
116+
// value types.
117+
return SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc(size, align);
118+
#else
113119
#if defined(_WIN32)
114120
void *r = _aligned_malloc(size, align);
115121
#else
@@ -120,14 +126,22 @@ SWIFT_INLINE_THUNK void *_Nonnull opaqueAlloc(size_t size,
120126
(void)res;
121127
#endif
122128
return r;
129+
#endif
123130
}
124131

125132
SWIFT_INLINE_THUNK void opaqueFree(void *_Nonnull p) noexcept {
133+
#if defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc) && \
134+
defined(SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free)
135+
// Allow the user to provide custom allocator for heap-allocated Swift
136+
// value types.
137+
SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free(p);
138+
#else
126139
#if defined(_WIN32)
127140
_aligned_free(p);
128141
#else
129142
free(p);
130143
#endif
144+
#endif
131145
}
132146

133147
/// Base class for a container for an opaque Swift value, like resilient struct.

test/Interop/SwiftToCxx/ownership/consuming-parameter-in-cxx-execution.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,25 @@
1111
// REQUIRES: executable_test
1212

1313
#include <assert.h>
14+
#include <stdint.h>
15+
#include <stdlib.h>
16+
17+
size_t allocCount = 0;
18+
size_t totalAllocs = 0;
19+
20+
void * _Nonnull trackedAlloc(size_t size, size_t align) {
21+
++allocCount;
22+
++totalAllocs;
23+
return malloc(size);
24+
}
25+
void trackedFree(void *_Nonnull p) {
26+
--allocCount;
27+
free(p);
28+
}
29+
30+
#define SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_alloc trackedAlloc
31+
#define SWIFT_CXX_INTEROPERABILITY_OVERRIDE_OPAQUE_STORAGE_free trackedFree
32+
1433
#include "consuming.h"
1534

1635
extern "C" size_t swift_retainCount(void * _Nonnull obj);
@@ -45,5 +64,8 @@ int main() {
4564
assert(getRetainCount(k) == 3);
4665
}
4766
// CHECK-NEXT: destroy AKlass
67+
// verify that all of the opaque buffers are freed.
68+
assert(allocCount == 0);
69+
assert(totalAllocs != 0);
4870
return 0;
4971
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend %S/consuming-parameter-in-cxx.swift -typecheck -module-name Init -clang-header-expose-decls=all-public -emit-clang-header-path %t/consuming.h -enable-library-evolution
4+
5+
// RUN: %target-interop-build-clangxx -c %S/consuming-parameter-in-cxx-execution.cpp -I %t -o %t/swift-consume-execution.o
6+
// RUN: %target-interop-build-swift %S/consuming-parameter-in-cxx.swift -o %t/swift-consume-execution-evo -Xlinker %t/swift-consume-execution.o -module-name Init -Xfrontend -entry-point-function-name -Xfrontend swiftMain -enable-library-evolution
7+
8+
// RUN: %target-codesign %t/swift-consume-execution-evo
9+
// RUN: %target-run %t/swift-consume-execution-evo | %FileCheck %S/consuming-parameter-in-cxx-execution.cpp
10+
11+
// REQUIRES: executable_test

0 commit comments

Comments
 (0)