Files
swift-mirror/test/Interop/Cxx/class/Inputs/closure.h
Gábor Horváth c3a7203221 [6.2][cxx-interop] Fix runtime crash passing FRTs as const FRT*
Explanation: There was an inconsistency between non-const and const FRT
pointers. The former used Direct_Unowned the latter used Indirect
calling convention. We want to use Direct_Unowned for both cases. The
crash was the result of a calling convention mismatch between the
SILFunctionType of a Swift closure and the SILFunctionType of the C++
function's formal parameter that is taking a function pointer. The
compiler tried to insert a conversion between the two function types
that does not exist and caused an assertion in debug compilers and
miscompilation in production compilers.
Issue: rdar://149398905
Risk: Low, the fix is targeted and we change to a well-tested behavior
with non-const FRT pointers.
Testing: Regression test added.
Original PR: #81070
Reviewer: @j-hui
2025-04-25 10:59:45 +01:00

79 lines
1.9 KiB
C++

#ifndef __CLOSURE__
#define __CLOSURE__
struct NonTrivial {
NonTrivial() noexcept { p = new int(123); }
~NonTrivial() { delete p; }
NonTrivial(const NonTrivial &other) noexcept {
p = new int(*other.p);
}
int *p;
};
void cfunc(void (^ _Nonnull block)(NonTrivial)) noexcept {
block(NonTrivial());
}
void cfunc2(void (*_Nonnull fp)(NonTrivial)) noexcept { (*fp)(NonTrivial()); }
NonTrivial cfunc3(NonTrivial, int, NonTrivial);
#if __OBJC__
struct ARCStrong {
id a;
};
void cfuncARCStrong(void (*_Nonnull)(ARCStrong)) noexcept ;
#endif
void cfuncReturnNonTrivial(NonTrivial (^_Nonnull)()) noexcept;
void cfuncReturnNonTrivial2(NonTrivial (*_Nonnull)()) noexcept;
struct ARCWeak {
#if __OBJC__
__weak _Nullable id m;
#endif
};
void cfuncARCWeak(void (^ _Nonnull block)(ARCWeak)) noexcept {
block(ARCWeak());
}
void cfunc(NonTrivial) noexcept;
void cfuncARCWeak(ARCWeak) noexcept;
void (* _Nonnull getFnPtr() noexcept)(NonTrivial) noexcept;
void (* _Nonnull getFnPtr2() noexcept)(ARCWeak) noexcept;
class SharedRef {
public:
static SharedRef *_Nonnull makeSharedRef() { return new SharedRef(); }
int _refCount = 1;
private:
SharedRef() = default;
SharedRef(const SharedRef &other) = delete;
SharedRef &operator=(const SharedRef &other) = delete;
SharedRef(SharedRef &&other) = delete;
SharedRef &operator=(SharedRef &&other) = delete;
} __attribute__((swift_attr("import_reference")))
__attribute__((swift_attr("retain:retainSharedRef")))
__attribute__((swift_attr("release:releaseSharedRef")));
inline void
cppGo(void (*_Nonnull takeConstSharedRef)(const SharedRef *_Nonnull x)) {
SharedRef *ref = SharedRef::makeSharedRef();
takeConstSharedRef(ref);
}
inline void retainSharedRef(SharedRef *_Nonnull x) { x->_refCount += 1; }
inline void releaseSharedRef(SharedRef *_Nonnull x) {
x->_refCount -= 1;
if (x->_refCount == 0) {
delete x;
}
}
#endif // __CLOSURE__