Skip to content

Commit b5ef290

Browse files
authored
Merge pull request #84203 from Xazax-hun/handle-unowned-in-impicit-value-init
[cxx-interop] Handle Unowned values in implicit value ctors
2 parents 607abb9 + fe3cc6d commit b5ef290

File tree

4 files changed

+89
-6
lines changed

4 files changed

+89
-6
lines changed

lib/SILGen/SILGenConstructor.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "ExecutorBreadcrumb.h"
1616
#include "Initialization.h"
1717
#include "LValue.h"
18+
#include "ManagedValue.h"
1819
#include "RValue.h"
1920
#include "SILGenFunction.h"
2021
#include "SILGenFunctionBuilder.h"
@@ -29,7 +30,9 @@
2930
#include "swift/Basic/Generators.h"
3031
#include "swift/SIL/SILArgument.h"
3132
#include "swift/SIL/SILInstruction.h"
33+
#include "swift/SIL/SILLocation.h"
3234
#include "swift/SIL/SILUndef.h"
35+
#include "swift/SIL/SILValue.h"
3336
#include "swift/SIL/TypeLowering.h"
3437
#include <map>
3538

@@ -82,13 +85,14 @@ class LoweredParamsInContextGenerator {
8285

8386
} // end anonymous namespace
8487

85-
static ManagedValue emitManagedParameter(SILGenFunction &SGF,
86-
SILValue value, bool isOwned) {
88+
static ManagedValue emitManagedParameter(SILGenFunction &SGF, SILValue value,
89+
bool isOwned, SILLocation loc) {
8790
if (isOwned) {
8891
return SGF.emitManagedRValueWithCleanup(value);
89-
} else {
90-
return ManagedValue::forBorrowedRValue(value);
9192
}
93+
if (value->getOwnershipKind() == OwnershipKind::Unowned)
94+
return ManagedValue::forUnownedObjectValue(value).ensurePlusOne(SGF, loc);
95+
return ManagedValue::forBorrowedRValue(value);
9296
}
9397

9498
static SILValue emitConstructorMetatypeArg(SILGenFunction &SGF,
@@ -216,7 +220,8 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &SGF,
216220
[&](Initialization *eltInit) {
217221
auto eltAddr =
218222
SGF.B.createPackElementGet(loc, packIndex, arg, eltTy);
219-
ManagedValue eltMV = emitManagedParameter(SGF, eltAddr, argIsConsumed);
223+
ManagedValue eltMV =
224+
emitManagedParameter(SGF, eltAddr, argIsConsumed, loc);
220225
eltMV = SGF.B.createLoadIfLoadable(loc, eltMV);
221226
eltInit->copyOrInitValueInto(SGF, loc, eltMV, argIsConsumed);
222227
eltInit->finishInitialization(SGF);
@@ -226,7 +231,7 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &SGF,
226231
return RValue::forInContext();
227232
}
228233

229-
ManagedValue mvArg = emitManagedParameter(SGF, arg, argIsConsumed);
234+
ManagedValue mvArg = emitManagedParameter(SGF, arg, argIsConsumed, loc);
230235

231236
// This can happen if the value is resilient in the calling convention
232237
// but not resilient locally.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
#include <stdio.h>
4+
#include <swift/bridging>
5+
6+
class SharedFRT {
7+
public:
8+
SharedFRT() : _refCount(1) { logMsg("Ctor"); }
9+
10+
private:
11+
void logMsg(const char *s) const {
12+
printf("RefCount: %d, message: %s\n", _refCount, s);
13+
}
14+
15+
~SharedFRT() { logMsg("Dtor"); }
16+
SharedFRT(const SharedFRT &) = delete;
17+
SharedFRT &operator=(const SharedFRT &) = delete;
18+
SharedFRT(SharedFRT &&) = delete;
19+
SharedFRT &operator=(SharedFRT &&) = delete;
20+
21+
int _refCount;
22+
23+
friend void retainSharedFRT(SharedFRT *_Nonnull);
24+
friend void releaseSharedFRT(SharedFRT *_Nonnull);
25+
} SWIFT_SHARED_REFERENCE(retainSharedFRT, releaseSharedFRT);
26+
27+
class MyToken {
28+
public:
29+
MyToken() = default;
30+
MyToken(MyToken const &) {}
31+
};
32+
33+
inline void retainSharedFRT(SharedFRT *_Nonnull x) {
34+
++x->_refCount;
35+
x->logMsg("retain");
36+
}
37+
38+
inline void releaseSharedFRT(SharedFRT *_Nonnull x) {
39+
--x->_refCount;
40+
x->logMsg("release");
41+
if (x->_refCount == 0)
42+
delete x;
43+
}

test/Interop/Cxx/foreign-reference/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,8 @@ module VirtMethodWithRvalRef {
7777
header "virtual-methods-with-rvalue-reference.h"
7878
requires cplusplus
7979
}
80+
81+
module LoggingFrts {
82+
header "logging-frts.h"
83+
requires cplusplus
84+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-run-simple-swift(-I %swift_src_root/lib/ClangImporter/SwiftBridging -I %S/Inputs -cxx-interoperability-mode=default -Xfrontend -disable-availability-checking -Onone) | %FileCheck %s
2+
3+
// REQUIRES: executable_test
4+
5+
import LoggingFrts
6+
7+
struct SwiftStruct {
8+
var frt: SharedFRT
9+
var token: MyToken
10+
}
11+
12+
func go() {
13+
let frt = SharedFRT()
14+
let token = MyToken()
15+
let _ = SwiftStruct(frt: frt, token: token)
16+
let _ = SwiftStruct(frt: frt, token: token)
17+
let _ = SwiftStruct(frt: frt, token: token)
18+
}
19+
20+
go()
21+
22+
// CHECK: RefCount: 1, message: Ctor
23+
// CHECK-NEXT: RefCount: 2, message: retain
24+
// CHECK-NEXT: RefCount: 1, message: release
25+
// CHECK-NEXT: RefCount: 2, message: retain
26+
// CHECK-NEXT: RefCount: 1, message: release
27+
// CHECK-NEXT: RefCount: 2, message: retain
28+
// CHECK-NEXT: RefCount: 1, message: release
29+
// CHECK-NEXT: RefCount: 0, message: release
30+
// CHECK-NEXT: RefCount: 0, message: Dtor

0 commit comments

Comments
 (0)