Sema: Synthesize materializeForSet with dynamically-dispatched accessors for dynamic properties.

Semantically, a dynamic property must always be dispatched in case it gets replaced at runtime, and an @NSManaged property may not have static accessors at all. Use ordinary access to the computed property accessors in materializeForSet when a property is dynamic or ObjC-originated. More rdar://problem/18706056.

There's still a problem--we try to vtable-dispatch materializeForSet, which is redundant for native classes, but impossible for imported ObjC classes. We should suppress this, but trying to make materializeForSet "final" breaks subclassing if the property is overridden.

This time, update test/SILGen/objc_properties.swift to avoid a false negative test failure.

Swift SVN r24888
This commit is contained in:
Joe Groff
2015-02-01 20:24:57 +00:00
parent 0d2881db78
commit c1db47ed13
4 changed files with 65 additions and 10 deletions

View File

@@ -1111,10 +1111,18 @@ static void synthesizeComputedMaterializeForSet(FuncDecl *materializeForSet,
ASTContext &ctx = TC.Context;
SmallVector<ASTNode, 4> body;
AccessSemantics semantics;
// If the storage is dynamic, we must dynamically redispatch through the
// accessor. Otherwise, we can do a direct peer access.
if (storage->isDynamic())
semantics = AccessSemantics::Ordinary;
else
semantics = AccessSemantics::DirectToAccessor;
// Builtin.initialize(self.property, buffer)
Expr *curValue = buildStorageReference(materializeForSet, storage,
AccessSemantics::DirectToAccessor,
semantics,
SelfAccessKind::Peer, TC);
Expr *bufferRef = new (ctx) DeclRefExpr(bufferDecl, SourceLoc(), IsImplicit);
body.push_back(buildCallToBuiltin(ctx, "initialize",
@@ -1144,7 +1152,7 @@ static void synthesizeComputedMaterializeForSet(FuncDecl *materializeForSet,
Expr *storageRef =
buildStorageReference(
CallbackStorageReferenceContext{selfDecl, callbackStorageDecl},
storage, AccessSemantics::DirectToAccessor,
storage, semantics,
SelfAccessKind::Peer, TC);
body.push_back(new (ctx) AssignExpr(storageRef, SourceLoc(),
value, IsImplicit));
@@ -1362,11 +1370,12 @@ void swift::synthesizeMaterializeForSet(FuncDecl *materializeForSet,
llvm_unreachable("no accessors");
// We can use direct access to stored variables, but not if they're
// weak or unowned.
// weak, unowned, or dynamic.
case AbstractStorageDecl::StoredWithTrivialAccessors: {
// Only variables can be Stored, and only variables can be weak/unowned.
auto var = cast<VarDecl>(storage);
if (var->getType()->is<ReferenceStorageType>()) {
if (var->getType()->is<ReferenceStorageType>()
|| var->isDynamic()) {
synthesizeComputedMaterializeForSet(materializeForSet, storage,
bufferDecl, TC);
return;