Skip to content

Commit a913c4e

Browse files
committed
[cxx-interop] fix support for value-only non-copyable type dereference
1 parent 5d2637a commit a913c4e

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,8 +1755,10 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
17551755
? rawElementTy->getAnyPointerElementType()
17561756
: rawElementTy;
17571757
// Use 'address' or 'mutableAddress' accessors for non-copyable
1758-
// types.
1759-
bool useAddress = elementTy->isNoncopyable(dc);
1758+
// types that are returned indirectly.
1759+
bool isImplicit = !elementTy->isNoncopyable(dc);
1760+
bool useAddress =
1761+
rawElementTy->getAnyPointerElementType() && elementTy->isNoncopyable(dc);
17601762

17611763
auto result = new (ctx)
17621764
VarDecl(/*isStatic*/ false, VarDecl::Introducer::Var,
@@ -1773,7 +1775,7 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
17731775
ParameterList::createEmpty(ctx),
17741776
useAddress ? elementTy->wrapInPointer(PTK_UnsafePointer) : elementTy, dc);
17751777
getterDecl->setAccess(AccessLevel::Public);
1776-
if (!useAddress)
1778+
if (isImplicit)
17771779
getterDecl->setImplicit();
17781780
getterDecl->setIsDynamic(false);
17791781
getterDecl->setIsTransparent(true);
@@ -1813,7 +1815,7 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
18131815
: TupleType::getEmpty(ctx),
18141816
dc);
18151817
setterDecl->setAccess(AccessLevel::Public);
1816-
if (!useAddress)
1818+
if (isImplicit)
18171819
setterDecl->setImplicit();
18181820
setterDecl->setIsDynamic(false);
18191821
setterDecl->setIsTransparent(true);

test/Interop/Cxx/operators/move-only/Inputs/move-only-cxx-value-operators.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,16 @@ class NonCopyableHolderMutDeref {
4848
inline NonCopyable & operator *() { return x; }
4949
};
5050

51+
class NonCopyableHolderValueConstDeref {
52+
NONCOPYABLE_HOLDER_WRAPPER(NonCopyableHolderValueConstDeref)
53+
54+
inline NonCopyable operator *() const { return NonCopyable(x.x); }
55+
};
56+
57+
class NonCopyableHolderValueMutDeref {
58+
NONCOPYABLE_HOLDER_WRAPPER(NonCopyableHolderValueMutDeref)
59+
60+
inline NonCopyable operator *() { return NonCopyable(x.x); }
61+
};
62+
5163
#endif // TEST_INTEROP_CXX_OPERATORS_MOVE_ONLY_OPS_H

test/Interop/Cxx/operators/move-only/move-only-synthesized-properties.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,18 @@ MoveOnlyCxxOperators.test("testNonCopyableHolderMutDeref pointee borrow") {
6767
expectEqual(holder.pointee.x, 0)
6868
}
6969

70+
MoveOnlyCxxOperators.test("testNonCopyableHolderValueConstDeref pointee value") {
71+
let holder = NonCopyableHolderValueConstDeref(11)
72+
var k = holder.pointee
73+
var k2 = holder.pointee
74+
expectEqual(k.x, k2.x)
75+
}
76+
77+
MoveOnlyCxxOperators.test("testNonCopyableHolderValueMutDeref pointee value") {
78+
var holder = NonCopyableHolderValueMutDeref(11)
79+
var k = holder.pointee
80+
var k2 = holder.pointee
81+
expectEqual(k.x, k2.x)
82+
}
7083

7184
runAllTests()

test/Interop/Cxx/operators/move-only/move-only-synthesized-property-typecheck.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,27 @@ func testNonCopyableHolderMutDerefPointeeLet() {
6666
#endif
6767
}
6868

69+
func testNonCopyableHolderValueConstDerefPointeeLet() {
70+
let holder = NonCopyableHolderValueConstDeref(11)
71+
let val = holder.pointee // expected-note {{}}
72+
_ = borrowNC(val) // ok
73+
#if NO_CONSUME
74+
val.mutMethod(3) // expected-error {{cannot use mutating member on immutable value: 'val' is a 'let' constant}}
75+
#endif
76+
}
77+
78+
func testNonCopyableHolderValueMutDerefPointeeLet() {
79+
var holder = NonCopyableHolderValueMutDeref(11)
80+
let val = holder.pointee // expected-note {{}}
81+
_ = borrowNC(val) // ok
82+
#if NO_CONSUME
83+
val.mutMethod(3) // expected-error {{cannot use mutating member on immutable value: 'val' is a 'let' constant}}
84+
#endif
85+
}
86+
6987
testNonCopyableHolderConstDerefPointee()
7088
testNonCopyableHolderPairedDerefPointee()
7189
testNonCopyableHolderMutDerefPointee()
7290
testNonCopyableHolderMutDerefPointeeLet()
91+
testNonCopyableHolderValueConstDerefPointeeLet()
92+
testNonCopyableHolderValueMutDerefPointeeLet()

0 commit comments

Comments
 (0)