Skip to content

Commit e0b0f8b

Browse files
committed
[5.2] SILGen: Fix withoutActuallyEscaping of 'c' closures
They don't have a context and therefore are not consumed. Fixes a failing assert. * Description: The compiler asserts on code that uses withoutActuallyEscaping on a ‘c’ convention closure. * Scope: Compiling source code that uses that combination will assert and fail to compile. In no asserts build the compilation succeeds and generates correct code (i.e the assert failure is inconsequential). The problem existed in previously released version of the compiler. * Testing: A swift regression test was added. * Reviewed: Andrew T Original PR: #29569 rdar://59046275
1 parent fab20c6 commit e0b0f8b

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5024,13 +5024,17 @@ RValue RValueEmitter::visitMakeTemporarilyEscapableExpr(
50245024
return visit(E->getSubExpr(), C);
50255025
};
50265026

5027-
// Handle @convention(block). No withoutActuallyEscaping verification yet.
5028-
if (silFnTy->getExtInfo().getRepresentation() !=
5029-
SILFunctionTypeRepresentation::Thick) {
5027+
// Handle @convention(block) an @convention(c). No withoutActuallyEscaping
5028+
// verification yet.
5029+
auto closureRepresentation = silFnTy->getExtInfo().getRepresentation();
5030+
if (closureRepresentation != SILFunctionTypeRepresentation::Thick) {
50305031
auto escapingClosure =
50315032
SGF.B.createConvertFunction(E, functionValue, escapingFnTy,
50325033
/*WithoutActuallyEscaping=*/true);
5033-
return visitSubExpr(escapingClosure, true /*isClosureConsumable*/);
5034+
bool isBlockConvention =
5035+
closureRepresentation == SILFunctionTypeRepresentation::Block;
5036+
return visitSubExpr(escapingClosure,
5037+
isBlockConvention /*isClosureConsumable*/);
50345038
}
50355039

50365040
// Convert it to an escaping function value.

test/SILGen/without_actually_escaping.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,16 @@ func withoutActuallyEscapingConflict() {
100100
modifyAndPerform(&localVar, closure: $0)
101101
}
102102
}
103+
104+
// CHECK-LABEL: sil [ossa] @$s25without_actually_escaping0A25ActuallyEscapingCFunction8functionyyyXC_tF
105+
// CHECK: bb0([[ARG:%.*]] : $@convention(c) @noescape () -> ()):
106+
// CHECK: [[E:%.*]] = convert_function [[ARG]] : $@convention(c) @noescape () -> () to [without_actually_escaping] $@convention(c) () -> ()
107+
// CHECK: [[F:%.*]] = function_ref @$s25without_actually_escaping0A25ActuallyEscapingCFunction8functionyyyXC_tFyyyXCXEfU_ : $@convention(thin) (@convention(c) () -> ()) -> ()
108+
// CHECK: apply [[F]]([[E]]) : $@convention(thin) (@convention(c) () -> ()) -> ()
109+
public func withoutActuallyEscapingCFunction(function: (@convention(c) () -> Void)) {
110+
withoutActuallyEscaping(function) { f in
111+
var pointer: UnsafeRawPointer? = nil
112+
pointer = unsafeBitCast(f, to: UnsafeRawPointer.self)
113+
print(pointer)
114+
}
115+
}

0 commit comments

Comments
 (0)