Skip to content

Commit d0ef976

Browse files
authored
Merge pull request swiftlang#16748 from huonw/tbdgen
[TBDGen] Cover more symbols
2 parents 5b2803a + 4385d90 commit d0ef976

File tree

5 files changed

+132
-5
lines changed

5 files changed

+132
-5
lines changed

lib/TBDGen/TBDGen.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ void TBDGenVisitor::addConformances(DeclContext *DC) {
120120
void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
121121
addSymbol(SILDeclRef(AFD));
122122

123+
if (AFD->getAttrs().hasAttribute<CDeclAttr>()) {
124+
// A @_cdecl("...") function has an extra symbol, with the name from the
125+
// attribute.
126+
addSymbol(SILDeclRef(AFD).asForeign());
127+
}
128+
123129
if (!SwiftModule->getASTContext().isSwiftVersion3())
124130
return;
125131

@@ -216,12 +222,26 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
216222

217223
visitNominalTypeDecl(CD);
218224

219-
// The below symbols are only emitted if the class is resilient.
220-
if (!CD->isResilient())
225+
auto hasResilientAncestor =
226+
CD->isResilient(SwiftModule, ResilienceExpansion::Minimal);
227+
auto ancestor = CD->getSuperclassDecl();
228+
while (ancestor && !hasResilientAncestor) {
229+
hasResilientAncestor |=
230+
ancestor->isResilient(SwiftModule, ResilienceExpansion::Maximal);
231+
ancestor = ancestor->getSuperclassDecl();
232+
}
233+
234+
// Types with resilient superclasses have some extra symbols.
235+
if (!hasResilientAncestor)
221236
return;
222237

223238
addSymbol(LinkEntity::forClassMetadataBaseOffset(CD));
224239

240+
// And classes that are themselves resilient (not just a superclass) have even
241+
// more.
242+
if (!CD->isResilient())
243+
return;
244+
225245
// Emit dispatch thunks for every new vtable entry.
226246
struct VTableVisitor : public SILVTableVisitor<VTableVisitor> {
227247
TBDGenVisitor &TBD;
@@ -300,6 +320,8 @@ void TBDGenVisitor::visitProtocolDecl(ProtocolDecl *PD) {
300320
}
301321

302322
void TBDGenVisitor::visitEnumDecl(EnumDecl *ED) {
323+
visitNominalTypeDecl(ED);
324+
303325
if (!ED->isResilient())
304326
return;
305327

test/TBD/Inputs/subclass_super.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
open class Super {
2+
open func function() {}
3+
4+
open var getter: Int { return 0 }
5+
open var getterSetter: Int {
6+
get { return 0 }
7+
set {}
8+
}
9+
}

test/TBD/enum.swift

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
11
// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
22
// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
3+
// Swift 4:
4+
// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
5+
// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
36

4-
class C {
7+
public protocol P {}
8+
9+
public class C {
510
}
611

7-
enum SinglePayload {
12+
public enum SinglePayload: P {
813
case A
914
case B(C)
1015
case D
1116
}
1217

13-
enum MultiPayload {
18+
public enum MultiPayload {
1419
case A
1520
case B(C)
1621
case D(C)
22+
23+
public func method() {}
24+
}
25+
26+
public enum AutomaticEquatableHashable {
27+
case a, b
28+
}
29+
30+
public enum Synthesized: Equatable, Hashable {
31+
case a(AutomaticEquatableHashable), b
32+
}
33+
public enum ConditionalSynthesized<T> {
34+
case a(T), b
35+
}
36+
37+
#if swift(>=4)
38+
extension ConditionalSynthesized: Equatable where T: Equatable {}
39+
extension ConditionalSynthesized: Hashable where T: Hashable {}
40+
#endif
41+
42+
public enum ZeroCases {}
43+
44+
public enum OneCase {
45+
case a
46+
}
47+
48+
public enum OneCasePayload {
49+
case a(C)
1750
}

test/TBD/function.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@ internal func internalWithDefault(_: Int = 0) {}
1212
private func privateNoArgs() {}
1313
private func privateSomeArgs(_: Int, x: Int) {}
1414
private func privateWithDefault(_: Int = 0) {}
15+
16+
@_cdecl("c_publicNoArgs") public func publicNoArgsCDecl() {}
17+
@_cdecl("c_publicSomeArgs") public func publicSomeArgsCDecl(_: Int, x: Int) {}
18+
@_cdecl("c_publicWithDefault") public func publicWithDefaultCDecl(_: Int = 0) {}
19+
20+
@_cdecl("c_internalNoArgs") internal func internalNoArgsCDecl() {}
21+
@_cdecl("c_internalSomeArgs") internal func internalSomeArgsCDecl(_: Int, x: Int) {}
22+
@_cdecl("c_internalWithDefault") internal func internalWithDefaultCDecl(_: Int = 0) {}

test/TBD/subclass.swift.gyb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %gyb %s > %t/main.swift
3+
4+
// Same-module superclass, both resilient and not:
5+
// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
6+
// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
7+
8+
9+
// Other-module superclass is not resilient:
10+
// RUN: %empty-directory(%t/super)
11+
// RUN: %target-build-swift %S/Inputs/subclass_super.swift -emit-library -emit-module -o %t/super/subclass_super.%target-dylib-extension
12+
// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
13+
// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
14+
15+
// Other-module superclass is resilient:
16+
// RUN: %empty-directory(%t/super)
17+
// RUN: %target-build-swift %S/Inputs/subclass_super.swift -emit-library -emit-module -o %t/super/subclass_super.%target-dylib-extension -Xfrontend -enable-resilience
18+
// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
19+
// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
20+
21+
#if SAME_MODULE
22+
open class Super {
23+
open func function() {}
24+
25+
open var getter: Int { return 0 }
26+
open var getterSetter: Int {
27+
get { return 0 }
28+
set {}
29+
}
30+
}
31+
#else
32+
import subclass_super
33+
#endif
34+
35+
// Create a variety of variations like `open class ... { open override
36+
// func function() }` and `public class ... { public final override
37+
// func function() }`.
38+
% for access in ["open", "public", "internal", "fileprivate"]:
39+
% for class_final in [""] if access == "open" else ["", "final"]:
40+
% for member_final in [""] if access == "open" else ["", "final"]:
41+
% class_mod = "%s %s" % (access, class_final)
42+
% name = "Sub_%s_%s_%s" % (access, class_final, member_final)
43+
% member_mod = "%s %s" % (access, member_final)
44+
${class_mod} class ${name} : Super {
45+
${member_mod} override func function() {}
46+
47+
${member_mod} override var getter: Int { return 0 }
48+
49+
${member_mod} override var getterSetter: Int {
50+
get { return 0 }
51+
set {}
52+
}
53+
}
54+
% end
55+
% end

0 commit comments

Comments
 (0)