Skip to content

Commit a01ed12

Browse files
committed
SILGen: Handle nested functions in shouldSkipDecl().
Functions that are nested within other functions are not exportable to clients since they cannot be called directly by clients. However, they need still to be emitted during SILGen when -experimental-skip-non-exportable-decls is specified so walk the decl context hierarchy when determining whether to skip emitting a function. Resolves rdar://117440503
1 parent 30982f9 commit a01ed12

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

lib/SILGen/SILGen.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -801,11 +801,28 @@ bool SILGenModule::shouldSkipDecl(Decl *D) {
801801
if (!D->isAvailableDuringLowering())
802802
return true;
803803

804-
if (getASTContext().SILOpts.SkipNonExportableDecls &&
805-
!D->isExposedToClients())
804+
if (!getASTContext().SILOpts.SkipNonExportableDecls)
805+
return false;
806+
807+
if (auto *afd = dyn_cast<AbstractFunctionDecl>(D)) {
808+
do {
809+
if (afd->isExposedToClients())
810+
return false;
811+
812+
// If this function is nested within another function that is exposed to
813+
// clients then it should be emitted.
814+
auto dc = afd->getDeclContext()->getAsDecl();
815+
afd = dc ? dyn_cast<AbstractFunctionDecl>(dc) : nullptr;
816+
} while (afd);
817+
818+
// We didn't find a parent function that is exposed.
806819
return true;
820+
}
807821

808-
return false;
822+
if (D->isExposedToClients())
823+
return false;
824+
825+
return true;
809826
}
810827

811828
void SILGenModule::visit(Decl *D) {

test/SILGen/skip-non-exportable-decls.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,39 @@ private func privateFunc() {}
1212
// CHECK-SKIP-NOT: s4Test12internalFuncyyF
1313
internal func internalFunc() {}
1414

15+
// CHECK-NO-SKIP: sil hidden{{.*}} @$s4Test022internalFuncWithNestedC0yyF : $@convention(thin) () -> () {
16+
// CHECK-SKIP-NOT: s4Test022internalFuncWithNestedC0yyF
17+
internal func internalFuncWithNestedFunc() {
18+
func nested() {}
19+
nested()
20+
}
21+
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test022internalFuncWithNestedC0yyF6nestedL_yyF : $@convention(thin) () -> () {
22+
// CHECK-SKIP-NOT: s4Test022internalFuncWithNestedC0yyF6nestedL_yyF
23+
1524
// CHECK: sil{{.*}} @$s4Test10publicFuncyyF : $@convention(thin) () -> () {
1625
public func publicFunc() {}
1726

27+
// CHECK: sil{{.*}} @$s4Test25publicFuncWithNestedFuncsyyF : $@convention(thin) () -> () {
28+
public func publicFuncWithNestedFuncs() {
29+
defer { publicFunc() }
30+
func nested() {}
31+
nested()
32+
}
33+
// CHECK: sil private{{.*}} @$s4Test25publicFuncWithNestedFuncsyyF6$deferL_yyF : $@convention(thin) () -> () {
34+
// CHECK: sil private{{.*}} @$s4Test25publicFuncWithNestedFuncsyyF6nestedL_yyF : $@convention(thin) () -> () {
35+
36+
// CHECK: sil [serialized]{{.*}} @$s4Test13inlinableFuncyyF : $@convention(thin) () -> () {
37+
@inlinable internal func inlinableFunc() {}
38+
39+
// CHECK: sil [serialized]{{.*}} @$s4Test023inlinableFuncWithNestedC0yyF : $@convention(thin) () -> () {
40+
@inlinable internal func inlinableFuncWithNestedFunc() {
41+
defer { publicFunc() }
42+
func nested() {}
43+
nested()
44+
}
45+
// CHECK: sil shared [serialized]{{.*}} @$s4Test023inlinableFuncWithNestedC0yyF6$deferL_yyF : $@convention(thin) () -> () {
46+
// CHECK: sil shared [serialized]{{.*}} @$s4Test023inlinableFuncWithNestedC0yyF6nestedL_yyF : $@convention(thin) () -> () {
47+
1848
private class PrivateClass {
1949
// CHECK-NO-SKIP: sil private{{.*}} @$s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCfd : $@convention(method) (@guaranteed PrivateClass) -> @owned Builtin.NativeObject {
2050
// CHECK-SKIP-NOT: s4Test12PrivateClass33_E3F0E1C7B46D05C8067CB98677DE566CLLCfd

0 commit comments

Comments
 (0)