Skip to content

Commit d30aa32

Browse files
authored
Merge pull request #18581 from rjmccall/opaque-accessors-cleanup
Various cleanups for opaque accessors
2 parents e23c681 + ebed6af commit d30aa32

File tree

10 files changed

+209
-159
lines changed

10 files changed

+209
-159
lines changed

include/swift/AST/Decl.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4263,6 +4263,13 @@ class AbstractStorageDecl : public ValueDecl {
42634263
return {};
42644264
}
42654265

4266+
/// Visit all the opaque accessors that this storage is expected to have.
4267+
void visitExpectedOpaqueAccessors(
4268+
llvm::function_ref<void (AccessorKind)>) const;
4269+
4270+
/// Visit all the opaque accessors of this storage declaration.
4271+
void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
4272+
42664273
void setAccessors(StorageImplInfo storageImpl,
42674274
SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
42684275
SourceLoc rbraceLoc);
@@ -4284,6 +4291,9 @@ class AbstractStorageDecl : public ValueDecl {
42844291
/// \brief Add a synthesized materializeForSet accessor.
42854292
void setSynthesizedMaterializeForSet(AccessorDecl *materializeForSet);
42864293

4294+
/// Does this storage require a materializeForSet accessor?
4295+
bool requiresMaterializeForSet() const;
4296+
42874297
SourceRange getBracesRange() const {
42884298
if (auto info = Accessors.getPointer())
42894299
return info->getBracesRange();
@@ -6506,6 +6516,8 @@ AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
65066516
setter->overwriteAccess(accessLevel);
65076517
if (auto materializeForSet = getMaterializeForSetFunc())
65086518
materializeForSet->overwriteAccess(accessLevel);
6519+
if (auto modify = getModifyCoroutine())
6520+
modify->overwriteAccess(accessLevel);
65096521
if (auto mutableAddressor = getMutableAddressor())
65106522
mutableAddressor->overwriteAccess(accessLevel);
65116523
}

include/swift/SIL/SILWitnessVisitor.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,9 @@ template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
133133
}
134134

135135
void visitAbstractStorageDecl(AbstractStorageDecl *sd) {
136-
asDerived().addMethod(SILDeclRef(sd->getGetter(),
137-
SILDeclRef::Kind::Func));
138-
if (sd->isSettable(sd->getDeclContext())) {
139-
asDerived().addMethod(SILDeclRef(sd->getSetter(),
140-
SILDeclRef::Kind::Func));
141-
if (sd->getMaterializeForSetFunc())
142-
asDerived().addMethod(SILDeclRef(sd->getMaterializeForSetFunc(),
143-
SILDeclRef::Kind::Func));
144-
}
136+
sd->visitOpaqueAccessors([&](AccessorDecl *accessor) {
137+
asDerived().addMethod(SILDeclRef(accessor, SILDeclRef::Kind::Func));
138+
});
145139
}
146140

147141
void visitConstructorDecl(ConstructorDecl *cd) {

lib/AST/Decl.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,6 +1624,56 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
16241624
llvm_unreachable("bad access semantics");
16251625
}
16261626

1627+
bool AbstractStorageDecl::requiresMaterializeForSet() const {
1628+
// Only for mutable storage.
1629+
if (!supportsMutation())
1630+
return false;
1631+
1632+
// We only need materializeForSet in type contexts.
1633+
// TODO: resilient global variables?
1634+
auto *dc = getDeclContext();
1635+
if (!dc->isTypeContext())
1636+
return false;
1637+
1638+
// Requirements of ObjC protocols don't need materializeForSet.
1639+
if (auto protoDecl = dyn_cast<ProtocolDecl>(dc))
1640+
if (protoDecl->isObjC())
1641+
return false;
1642+
1643+
// Members of structs imported by Clang don't need an eagerly-synthesized
1644+
// materializeForSet.
1645+
if (auto structDecl = dyn_cast<StructDecl>(dc))
1646+
if (structDecl->hasClangNode())
1647+
return false;
1648+
1649+
return true;
1650+
}
1651+
1652+
void AbstractStorageDecl::visitExpectedOpaqueAccessors(
1653+
llvm::function_ref<void (AccessorKind)> visit) const {
1654+
// For now, always assume storage declarations should have getters
1655+
// instead of read accessors.
1656+
visit(AccessorKind::Get);
1657+
1658+
if (supportsMutation()) {
1659+
// All mutable storage should have a setter.
1660+
visit(AccessorKind::Set);
1661+
1662+
// Include materializeForSet if necessary.
1663+
if (requiresMaterializeForSet())
1664+
visit(AccessorKind::MaterializeForSet);
1665+
}
1666+
}
1667+
1668+
void AbstractStorageDecl::visitOpaqueAccessors(
1669+
llvm::function_ref<void (AccessorDecl*)> visit) const {
1670+
visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1671+
auto accessor = getAccessor(kind);
1672+
assert(accessor && "didn't have expected opaque accessor");
1673+
visit(accessor);
1674+
});
1675+
}
1676+
16271677
static bool hasPrivateOrFilePrivateFormalAccess(const ValueDecl *D) {
16281678
return D->hasAccess() && D->getFormalAccess() <= AccessLevel::FilePrivate;
16291679
}

lib/SILGen/SILGen.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,14 +1184,13 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
11841184
if (vd->getImplInfo().isSimpleStored()) {
11851185
// If the global variable has storage, it might also have synthesized
11861186
// accessors. Emit them here, since they won't appear anywhere else.
1187-
if (auto getter = vd->getGetter())
1188-
emitFunction(getter);
1189-
if (auto setter = vd->getSetter())
1190-
emitFunction(setter);
1191-
if (auto materializeForSet = vd->getMaterializeForSetFunc())
1192-
emitFunction(materializeForSet);
1187+
vd->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1188+
auto accessor = vd->getAccessor(kind);
1189+
if (accessor)
1190+
emitFunction(accessor);
1191+
});
11931192
}
1194-
1193+
11951194
tryEmitPropertyDescriptor(vd);
11961195
}
11971196

0 commit comments

Comments
 (0)