Skip to content

Commit d76dbb1

Browse files
authored
[SILGen] Fix a bug where the wrong convention was being used for lowering a closure to a C++ function pointer (#73039)
Use the C function pointer convention instead of the block convention. rdar://122977380
1 parent 6357d12 commit d76dbb1

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3798,8 +3798,14 @@ static CanSILFunctionType getSILFunctionTypeForAbstractCFunction(
37983798
TypeConverter &TC, AbstractionPattern origType,
37993799
CanAnyFunctionType substType, SILExtInfoBuilder extInfoBuilder,
38003800
std::optional<SILDeclRef> constant) {
3801-
if (origType.isClangType()) {
3802-
auto clangType = origType.getClangType();
3801+
const clang::Type *clangType = nullptr;
3802+
3803+
if (origType.isClangType())
3804+
clangType = origType.getClangType();
3805+
else
3806+
clangType = extInfoBuilder.getClangTypeInfo().getType();
3807+
3808+
if (clangType) {
38033809
const clang::FunctionType *fnType;
38043810
if (auto blockPtr = clangType->getAs<clang::BlockPointerType>()) {
38053811
fnType = blockPtr->getPointeeType()->castAs<clang::FunctionType>();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef __CLOSURE__
2+
#define __CLOSURE__
3+
4+
struct NonTrivial {
5+
NonTrivial() { p = new int(123); }
6+
~NonTrivial() { delete p; }
7+
NonTrivial(const NonTrivial &other);
8+
int *p;
9+
};
10+
11+
void cfunc2(void (*fp)(NonTrivial)) {
12+
(*fp)(NonTrivial());
13+
}
14+
15+
#endif // __CLOSURE__

test/Interop/Cxx/class/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,8 @@ module CopyMoveAssignment {
141141
header "copy-move-assignment.h"
142142
requires cplusplus
143143
}
144+
145+
module Closure {
146+
header "closure.h"
147+
requires cplusplus
148+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -cxx-interoperability-mode=default)
2+
//
3+
// REQUIRES: executable_test
4+
5+
// The test is enabled only on windows until https://github.com/apple/swift/pull/73019
6+
// is fixed.
7+
// REQUIRES: OS=windows-msvc
8+
9+
import StdlibUnittest
10+
import Closure
11+
12+
var ClosureTestSuite = TestSuite("Closure")
13+
14+
ClosureTestSuite.test("ConvertToFunctionPointer") {
15+
cfunc2({N in})
16+
}
17+
18+
runAllTests()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swiftxx-frontend -I %S/Inputs -emit-silgen %s | %FileCheck %s
2+
3+
import Closure
4+
5+
// CHECK: sil [ossa] @$s4main20testClosureToFuncPtryyF : $@convention(thin) () -> () {
6+
// CHECK: %[[V0:.*]] = function_ref @$s4main20testClosureToFuncPtryyFySo10NonTrivialVcfU_To : $@convention(c) (@in NonTrivial) -> ()
7+
// CHECK: %[[V1:.*]] = enum $Optional<@convention(c) (@in NonTrivial) -> ()>, #Optional.some!enumelt, %[[V0]] : $@convention(c) (@in NonTrivial) -> ()
8+
// CHECK: %[[V2:.*]] = function_ref @{{.*}}cfunc2{{.*}}NonTrivial{{.*}} : $@convention(c) (Optional<@convention(c) (@in NonTrivial) -> ()>) -> ()
9+
// CHECK: %[[V3:.*]] = apply %[[V2]](%[[V1]]) : $@convention(c) (Optional<@convention(c) (@in NonTrivial) -> ()>) -> ()
10+
11+
// CHECK: sil private [ossa] @$s4main20testClosureToFuncPtryyFySo10NonTrivialVcfU_ : $@convention(thin) (@in_guaranteed NonTrivial) -> () {
12+
13+
// CHECK: sil private [thunk] [ossa] @$s4main20testClosureToFuncPtryyFySo10NonTrivialVcfU_To : $@convention(c) (@in NonTrivial) -> () {
14+
// CHECK: bb0(%[[V0:.*]] : $*NonTrivial):
15+
// CHECK: %[[V1:.*]] = function_ref @$s4main20testClosureToFuncPtryyFySo10NonTrivialVcfU_ : $@convention(thin) (@in_guaranteed NonTrivial) -> ()
16+
// CHECK: %[[V2:.*]] = apply %[[V1]](%[[V0]]) : $@convention(thin) (@in_guaranteed NonTrivial) -> ()
17+
// CHECK: destroy_addr %[[V0]] : $*NonTrivial
18+
19+
public func testClosureToFuncPtr() {
20+
cfunc2({N in})
21+
}

0 commit comments

Comments
 (0)