Skip to content

Commit f156420

Browse files
committed
SILGen: Properly copy a nonunique OpaqueValueExpr when it's needed at +1.
emitManagedRetain only retains things; use ManagedValue::copyUnmanaged instead. Swift SVN r27185
1 parent d61dd21 commit f156420

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3166,8 +3166,10 @@ RValue RValueEmitter::visitOpenExistentialExpr(OpenExistentialExpr *E,
31663166
break;
31673167
case ExistentialRepresentation::Boxed:
31683168
assert(existentialValue.getValue().getType().isObject());
3169+
// NB: Don't forward the cleanup, because consuming a boxed value won't
3170+
// consume the box reference.
31693171
archetypeValue = SGF.B.createOpenExistentialBox(
3170-
E, existentialValue.forward(SGF),
3172+
E, existentialValue.getValue(),
31713173
SGF.getLoweredType(opaqueValueType));
31723174
// The boxed value can't be assumed to be uniquely referenced.
31733175
isUnique = false;
@@ -3202,9 +3204,10 @@ RValue RValueEmitter::visitOpaqueValueExpr(OpaqueValueExpr *E, SGFContext C) {
32023204
return RValue(SGF, E, SGF.emitManagedRValueWithCleanup(entry.value));
32033205
}
32043206

3205-
// Retain the value.
3207+
// Otherwise, copy the value.
32063208
entry.hasBeenConsumed = true;
3207-
return RValue(SGF, E, SGF.emitManagedRetain(E, entry.value));
3209+
return RValue(SGF, E,
3210+
ManagedValue::forUnmanaged(entry.value).copyUnmanaged(SGF, E));
32083211
}
32093212

32103213
ProtocolDecl *SILGenFunction::getPointerProtocol() {

test/SILGen/boxed_existentials.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,27 @@ func test_property(x: _ErrorType) -> String {
5555
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[VALUE]])
5656
// CHECK: strong_release %0
5757
// CHECK: return [[RESULT]]
58+
59+
extension _ErrorType {
60+
final func extensionMethod() { }
61+
}
62+
63+
// CHECK-LABEL: sil hidden @_TF18boxed_existentials21test_extension_methodFPSs10_ErrorType_T_
64+
func test_extension_method(error: _ErrorType) {
65+
// -- TODO: could avoid an r/r here by guaranteeing the box, even if
66+
// the value inside is still wanted at +1
67+
// CHECK: strong_retain %0
68+
// CHECK: [[VALUE:%.*]] = open_existential_box %0
69+
// CHECK: [[METHOD:%.*]] = function_ref
70+
// CHECK: copy_addr [[VALUE]] to [initialization] [[COPY:%.*]]#1 :
71+
// CHECK: apply [[METHOD]]<{{.*}}>([[COPY]]#1)
72+
// CHECK-NOT: destroy_addr [[COPY]]
73+
// CHECK-NOT: destroy_addr [[VALUE]]
74+
// CHECK: dealloc_stack [[COPY]]#0
75+
// CHECK-NOT: destroy_addr [[VALUE]]
76+
// -- release the guarantee (TODO: redundant; see above)
77+
// CHECK: strong_release %0
78+
// -- release the owned argument
79+
// CHECK: strong_release %0
80+
error.extensionMethod()
81+
}

0 commit comments

Comments
 (0)