Skip to content

Commit 4eac5a1

Browse files
authored
Merge pull request swiftlang#31886 from theblixguy/fix/SR-12821-5.3
[5.3] [TBDGen] Fix symbol mismatch for enum case constructors
2 parents c1dac75 + 01106c5 commit 4eac5a1

File tree

9 files changed

+72
-25
lines changed

9 files changed

+72
-25
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "swift/AST/ClangNode.h"
2323
#include "swift/AST/TypeAlignments.h"
24+
#include "swift/SIL/SILLinkage.h"
2425
#include "llvm/ADT/Hashing.h"
2526
#include "llvm/ADT/DenseMap.h"
2627
#include "llvm/ADT/PointerUnion.h"
@@ -42,7 +43,6 @@ namespace swift {
4243
class ASTContext;
4344
class ClassDecl;
4445
class SILFunctionType;
45-
enum class SILLinkage : unsigned char;
4646
enum IsSerialized_t : unsigned char;
4747
enum class SubclassScope : unsigned char;
4848
class SILModule;
@@ -413,6 +413,22 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SILDeclRef C) {
413413
return OS;
414414
}
415415

416+
// FIXME: This should not be necessary, but it looks like visibility rules for
417+
// extension members are slightly bogus, and so some protocol witness thunks
418+
// need to be public.
419+
//
420+
// We allow a 'public' member of an extension to witness a public
421+
// protocol requirement, even if the extended type is not public;
422+
// then SILGen gives the member private linkage, ignoring the more
423+
// visible access level it was given in the AST.
424+
inline bool
425+
fixmeWitnessHasLinkageThatNeedsToBePublic(SILDeclRef witness) {
426+
auto witnessLinkage = witness.getLinkage(ForDefinition);
427+
return !hasPublicVisibility(witnessLinkage)
428+
&& (!hasSharedVisibility(witnessLinkage)
429+
|| !witness.isSerialized());
430+
}
431+
416432
} // end swift namespace
417433

418434
namespace llvm {

include/swift/SIL/SILLinkage.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,6 @@ inline SILLinkage effectiveLinkageForClassMember(SILLinkage linkage,
265265
return linkage;
266266
}
267267

268-
// FIXME: This should not be necessary, but it looks like visibility rules for
269-
// extension members are slightly bogus, and so some protocol witness thunks
270-
// need to be public.
271-
//
272-
// We allow a 'public' member of an extension to witness a public
273-
// protocol requirement, even if the extended type is not public;
274-
// then SILGen gives the member private linkage, ignoring the more
275-
// visible access level it was given in the AST.
276-
inline bool
277-
fixmeWitnessHasLinkageThatNeedsToBePublic(SILLinkage witnessLinkage) {
278-
return !hasPublicVisibility(witnessLinkage) &&
279-
!hasSharedVisibility(witnessLinkage);
280-
}
281-
282268
} // end swift namespace
283269

284270
#endif

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
233233

234234
// Native function-local declarations have shared linkage.
235235
// FIXME: @objc declarations should be too, but we currently have no way
236-
// of marking them "used" other than making them external.
236+
// of marking them "used" other than making them external.
237237
ValueDecl *d = getDecl();
238238
DeclContext *moduleContext = d->getDeclContext();
239239
while (!moduleContext->isModuleScopeContext()) {
@@ -335,6 +335,10 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
335335
}
336336
}
337337

338+
if (isEnumElement()) {
339+
limit = Limit::OnDemand;
340+
}
341+
338342
auto effectiveAccess = d->getEffectiveAccess();
339343

340344
// Private setter implementations for an internal storage declaration should

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
687687
}
688688
llvm::dbgs() << "In function:\n";
689689
F.print(llvm::dbgs());
690+
llvm::dbgs() << "In module:\n";
691+
F.getModule().print(llvm::dbgs());
690692

691693
// We abort by default because we want to always crash in
692694
// the debugger.

lib/SILGen/SILGenType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
567567
auto witnessLinkage = witnessRef.getLinkage(ForDefinition);
568568
auto witnessSerialized = Serialized;
569569
if (witnessSerialized &&
570-
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessLinkage)) {
570+
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef)) {
571571
witnessLinkage = SILLinkage::Public;
572572
witnessSerialized = IsNotSerialized;
573573
} else {

lib/TBDGen/TBDGen.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,11 @@ void TBDGenVisitor::addConformances(DeclContext *DC) {
473473
rootConformance);
474474
auto addSymbolIfNecessary = [&](ValueDecl *requirementDecl,
475475
ValueDecl *witnessDecl) {
476-
auto witnessLinkage = SILDeclRef(witnessDecl).getLinkage(ForDefinition);
476+
auto witnessRef = SILDeclRef(witnessDecl);
477+
auto witnessLinkage = witnessRef.getLinkage(ForDefinition);
477478
if (conformanceIsFixed &&
478479
(isa<SelfProtocolConformance>(rootConformance) ||
479-
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessLinkage))) {
480+
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef))) {
480481
Mangle::ASTMangler Mangler;
481482
addSymbol(
482483
Mangler.mangleWitnessThunk(rootConformance, requirementDecl));
@@ -496,7 +497,8 @@ void TBDGenVisitor::addConformances(DeclContext *DC) {
496497
addSymbolIfNecessary(reqtAccessor, witnessAccessor);
497498
});
498499
} else if (isa<EnumElementDecl>(witnessDecl)) {
499-
addSymbolIfNecessary(valueReq, witnessDecl);
500+
auto getter = storage->getSynthesizedAccessor(AccessorKind::Get);
501+
addSymbolIfNecessary(getter, witnessDecl);
500502
}
501503
}
502504
});
@@ -1016,13 +1018,12 @@ void TBDGenVisitor::visitProtocolDecl(ProtocolDecl *PD) {
10161018

10171019
void TBDGenVisitor::visitEnumDecl(EnumDecl *ED) {
10181020
visitNominalTypeDecl(ED);
1019-
1020-
if (!ED->isResilient())
1021-
return;
10221021
}
10231022

10241023
void TBDGenVisitor::visitEnumElementDecl(EnumElementDecl *EED) {
1025-
addSymbol(LinkEntity::forEnumCase(EED));
1024+
if (EED->getParentEnum()->isResilient())
1025+
addSymbol(LinkEntity::forEnumCase(EED));
1026+
10261027
if (auto *PL = EED->getParameterList())
10271028
visitDefaultArguments(EED, PL);
10281029
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-emit-silgen -verify %s
2+
3+
public protocol A {
4+
@_borrowed
5+
subscript() -> Int { get }
6+
}
7+
8+
protocol B: A { }
9+
10+
extension B {
11+
public subscript() -> Int { return 0 }
12+
}
13+
14+
public struct S: B {
15+
}

test/SILGen/protocol_enum_witness.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ enum AnotherBar: AnotherFoo {
2626
// CHECK-NEXT: return [[TUPLE]] : $()
2727
// CHECK-END: }
2828

29-
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s21protocol_enum_witness3BarO6buttonyA2CmF : $@convention(method) (@thin Bar.Type) -> Bar {
29+
// CHECK-LABEL: sil shared [transparent] [ossa] @$s21protocol_enum_witness3BarO6buttonyA2CmF : $@convention(method) (@thin Bar.Type) -> Bar {
3030
// CHECK: bb0({{%.*}} : $@thin Bar.Type):
3131
// CHECK-NEXT: [[CASE:%.*]] = enum $Bar, #Bar.button!enumelt
3232
// CHECK-NEXT: return [[CASE]] : $Bar
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// REQUIRES: VENDOR=apple
2+
// RUN: %target-swift-frontend -emit-ir -enable-testing -o/dev/null -module-name test -validate-tbd-against-ir=all %s
3+
// RUN: %target-swift-frontend -emit-ir -o/dev/null -module-name test -validate-tbd-against-ir=all %s
4+
5+
protocol ProtoInternal {
6+
static var bar1: Self { get }
7+
static func bar2(arg: Int) -> Self
8+
}
9+
10+
enum EnumInternal: ProtoInternal {
11+
case bar1
12+
case bar2(arg: Int)
13+
}
14+
15+
public protocol ProtoPublic {
16+
static var bar3: Self { get }
17+
static func bar4(arg: Int) -> Self
18+
}
19+
20+
public enum EnumPublic: ProtoPublic {
21+
case bar3
22+
case bar4(arg: Int)
23+
}

0 commit comments

Comments
 (0)