Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4263,6 +4263,13 @@ class AbstractStorageDecl : public ValueDecl {
return {};
}

/// Visit all the opaque accessors that this storage is expected to have.
void visitExpectedOpaqueAccessors(
llvm::function_ref<void (AccessorKind)>) const;

/// Visit all the opaque accessors of this storage declaration.
void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

void setAccessors(StorageImplInfo storageImpl,
SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
SourceLoc rbraceLoc);
Expand All @@ -4284,6 +4291,9 @@ class AbstractStorageDecl : public ValueDecl {
/// \brief Add a synthesized materializeForSet accessor.
void setSynthesizedMaterializeForSet(AccessorDecl *materializeForSet);

/// Does this storage require a materializeForSet accessor?
bool requiresMaterializeForSet() const;

SourceRange getBracesRange() const {
if (auto info = Accessors.getPointer())
return info->getBracesRange();
Expand Down Expand Up @@ -6506,6 +6516,8 @@ AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
setter->overwriteAccess(accessLevel);
if (auto materializeForSet = getMaterializeForSetFunc())
materializeForSet->overwriteAccess(accessLevel);
if (auto modify = getModifyCoroutine())
modify->overwriteAccess(accessLevel);
if (auto mutableAddressor = getMutableAddressor())
mutableAddressor->overwriteAccess(accessLevel);
}
Expand Down
12 changes: 3 additions & 9 deletions include/swift/SIL/SILWitnessVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,9 @@ template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
}

void visitAbstractStorageDecl(AbstractStorageDecl *sd) {
asDerived().addMethod(SILDeclRef(sd->getGetter(),
SILDeclRef::Kind::Func));
if (sd->isSettable(sd->getDeclContext())) {
asDerived().addMethod(SILDeclRef(sd->getSetter(),
SILDeclRef::Kind::Func));
if (sd->getMaterializeForSetFunc())
asDerived().addMethod(SILDeclRef(sd->getMaterializeForSetFunc(),
SILDeclRef::Kind::Func));
}
sd->visitOpaqueAccessors([&](AccessorDecl *accessor) {
asDerived().addMethod(SILDeclRef(accessor, SILDeclRef::Kind::Func));
});
}

void visitConstructorDecl(ConstructorDecl *cd) {
Expand Down
50 changes: 50 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,56 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
llvm_unreachable("bad access semantics");
}

bool AbstractStorageDecl::requiresMaterializeForSet() const {
// Only for mutable storage.
if (!supportsMutation())
return false;

// We only need materializeForSet in type contexts.
// TODO: resilient global variables?
auto *dc = getDeclContext();
if (!dc->isTypeContext())
return false;

// Requirements of ObjC protocols don't need materializeForSet.
if (auto protoDecl = dyn_cast<ProtocolDecl>(dc))
if (protoDecl->isObjC())
return false;

// Members of structs imported by Clang don't need an eagerly-synthesized
// materializeForSet.
if (auto structDecl = dyn_cast<StructDecl>(dc))
if (structDecl->hasClangNode())
return false;

return true;
}

void AbstractStorageDecl::visitExpectedOpaqueAccessors(
llvm::function_ref<void (AccessorKind)> visit) const {
// For now, always assume storage declarations should have getters
// instead of read accessors.
visit(AccessorKind::Get);

if (supportsMutation()) {
// All mutable storage should have a setter.
visit(AccessorKind::Set);

// Include materializeForSet if necessary.
if (requiresMaterializeForSet())
visit(AccessorKind::MaterializeForSet);
}
}

void AbstractStorageDecl::visitOpaqueAccessors(
llvm::function_ref<void (AccessorDecl*)> visit) const {
visitExpectedOpaqueAccessors([&](AccessorKind kind) {
auto accessor = getAccessor(kind);
assert(accessor && "didn't have expected opaque accessor");
visit(accessor);
});
}

static bool hasPrivateOrFilePrivateFormalAccess(const ValueDecl *D) {
return D->hasAccess() && D->getFormalAccess() <= AccessLevel::FilePrivate;
}
Expand Down
13 changes: 6 additions & 7 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1184,14 +1184,13 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
if (vd->getImplInfo().isSimpleStored()) {
// If the global variable has storage, it might also have synthesized
// accessors. Emit them here, since they won't appear anywhere else.
if (auto getter = vd->getGetter())
emitFunction(getter);
if (auto setter = vd->getSetter())
emitFunction(setter);
if (auto materializeForSet = vd->getMaterializeForSetFunc())
emitFunction(materializeForSet);
vd->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
auto accessor = vd->getAccessor(kind);
if (accessor)
emitFunction(accessor);
});
}

tryEmitPropertyDescriptor(vd);
}

Expand Down
Loading