diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 4c46c4193018d..ea11fa8a06cab 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -15,6 +15,7 @@ #include "ExecutorBreadcrumb.h" #include "Initialization.h" #include "LValue.h" +#include "ManagedValue.h" #include "RValue.h" #include "SILGenFunction.h" #include "SILGenFunctionBuilder.h" @@ -29,7 +30,9 @@ #include "swift/Basic/Generators.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILInstruction.h" +#include "swift/SIL/SILLocation.h" #include "swift/SIL/SILUndef.h" +#include "swift/SIL/SILValue.h" #include "swift/SIL/TypeLowering.h" #include @@ -82,13 +85,14 @@ class LoweredParamsInContextGenerator { } // end anonymous namespace -static ManagedValue emitManagedParameter(SILGenFunction &SGF, - SILValue value, bool isOwned) { +static ManagedValue emitManagedParameter(SILGenFunction &SGF, SILValue value, + bool isOwned, SILLocation loc) { if (isOwned) { return SGF.emitManagedRValueWithCleanup(value); - } else { - return ManagedValue::forBorrowedRValue(value); } + if (value->getOwnershipKind() == OwnershipKind::Unowned) + return ManagedValue::forUnownedObjectValue(value).ensurePlusOne(SGF, loc); + return ManagedValue::forBorrowedRValue(value); } static SILValue emitConstructorMetatypeArg(SILGenFunction &SGF, @@ -216,7 +220,8 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &SGF, [&](Initialization *eltInit) { auto eltAddr = SGF.B.createPackElementGet(loc, packIndex, arg, eltTy); - ManagedValue eltMV = emitManagedParameter(SGF, eltAddr, argIsConsumed); + ManagedValue eltMV = + emitManagedParameter(SGF, eltAddr, argIsConsumed, loc); eltMV = SGF.B.createLoadIfLoadable(loc, eltMV); eltInit->copyOrInitValueInto(SGF, loc, eltMV, argIsConsumed); eltInit->finishInitialization(SGF); @@ -226,7 +231,7 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &SGF, return RValue::forInContext(); } - ManagedValue mvArg = emitManagedParameter(SGF, arg, argIsConsumed); + ManagedValue mvArg = emitManagedParameter(SGF, arg, argIsConsumed, loc); // This can happen if the value is resilient in the calling convention // but not resilient locally. diff --git a/test/Interop/Cxx/foreign-reference/frts-as-fields.swift b/test/Interop/Cxx/foreign-reference/frts-as-fields.swift index b9d2067b5be6c..6bb4609bcfbe2 100644 --- a/test/Interop/Cxx/foreign-reference/frts-as-fields.swift +++ b/test/Interop/Cxx/foreign-reference/frts-as-fields.swift @@ -4,6 +4,31 @@ import LoggingFrts +struct SwiftStruct { + var frt: SharedFRT + var token: MyToken +} + +func go() { + let frt = SharedFRT() + let token = MyToken() + let _ = SwiftStruct(frt: frt, token: token) + let _ = SwiftStruct(frt: frt, token: token) + let _ = SwiftStruct(frt: frt, token: token) +} + +go() + +// CHECK: RefCount: 1, message: Ctor +// CHECK-NEXT: RefCount: 2, message: retain +// CHECK-NEXT: RefCount: 1, message: release +// CHECK-NEXT: RefCount: 2, message: retain +// CHECK-NEXT: RefCount: 1, message: release +// CHECK-NEXT: RefCount: 2, message: retain +// CHECK-NEXT: RefCount: 1, message: release +// CHECK-NEXT: RefCount: 0, message: release +// CHECK-NEXT: RefCount: 0, message: Dtor + func takesLargeStructWithRefCountedField(_ x: LargeStructWithRefCountedField) { var a = x }