Skip to content

Commit 46d44a8

Browse files
authored
Merge pull request #78759 from swiftlang/gaborh/addressable-references
[cxx-interop] Mark C++ reference parameters @Addressable
2 parents e6c772b + e79e04c commit 46d44a8

File tree

5 files changed

+40
-2
lines changed

5 files changed

+40
-2
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3946,6 +3946,9 @@ namespace {
39463946
}
39473947
if (selfIdx) {
39483948
func->setSelfIndex(selfIdx.value());
3949+
if (Impl.SwiftContext.LangOpts.hasFeature(
3950+
Feature::AddressableParameters))
3951+
func->getImplicitSelfDecl()->setAddressable();
39493952
} else {
39503953
func->setStatic();
39513954
func->setImportAsStaticMember();

lib/ClangImporter/ImportType.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,17 +2676,25 @@ static ParamDecl *getParameterInfo(ClangImporter::Implementation *impl,
26762676
impl->importSourceLoc(param->getLocation()), bodyName,
26772677
impl->ImportedHeaderUnit);
26782678

2679+
auto &ASTContext = paramInfo->getASTContext();
26792680
// If SendingArgsAndResults are enabled and we have a sending argument,
26802681
// set that the param was sending.
2681-
if (paramInfo->getASTContext().LangOpts.hasFeature(
2682-
Feature::SendingArgsAndResults)) {
2682+
if (ASTContext.LangOpts.hasFeature(Feature::SendingArgsAndResults)) {
26832683
if (auto *attr = param->getAttr<clang::SwiftAttrAttr>()) {
26842684
if (attr->getAttribute() == "sending") {
26852685
paramInfo->setSending();
26862686
}
26872687
}
26882688
}
26892689

2690+
// C++ types taking a reference might return a reference/pointer to a
2691+
// subobject of the referenced storage. In those cases we need to prevent the
2692+
// Swift compiler to pass in a temporary copy to prevent dangling.
2693+
if (ASTContext.LangOpts.hasFeature(Feature::AddressableParameters) &&
2694+
!param->getType().isNull() && param->getType()->isReferenceType()) {
2695+
paramInfo->setAddressable();
2696+
}
2697+
26902698
// Parameters of type const T& imported as T, make sure we borrow from them
26912699
// when they have lifetime annotations.
26922700
bool isBorrowing = (param->getAttr<clang::LifetimeBoundAttr>() ||

test/Interop/Cxx/class/method/Inputs/methods.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ struct HasMethods {
3333

3434
NonTrivialInWrapper nonConstPassThroughAsWrapper(int a) { return {a}; }
3535
NonTrivialInWrapper constPassThroughAsWrapper(int a) const { return {a}; }
36+
37+
void nonTrivialTakesConstRef(const NonTrivialInWrapper& w) const {}
38+
void nonTrivialTakesRef(NonTrivialInWrapper& w) const {}
3639
};
3740

3841
struct ReferenceParams {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
// RUN: %target-swift-emit-silgen -I %S/Inputs -enable-experimental-feature AddressableParameters -enable-experimental-cxx-interop %s | %FileCheck %s
3+
4+
import Methods
5+
6+
// REQUIRES: swift_feature_AddressableParameters
7+
8+
public func addressableTest(x: borrowing @_addressable NonTrivialInWrapper, y: inout NonTrivialInWrapper) {
9+
let m = HasMethods()
10+
m.nonTrivialTakesConstRef(x)
11+
// No copy from the argument to the apply.
12+
// CHECK: addressableTest(x:y:)
13+
// CHECK: bb0([[INPUT:%[0-9]+]] : @noImplicitCopy $*NonTrivialInWrapper, [[INPUT2:%[0-9]+]] : $*NonTrivialInWrapper)
14+
// CHECK: [[WRAPPER:%[0-9]+]] = copyable_to_moveonlywrapper_addr [[INPUT]]
15+
// CHECK: [[MARKED:%[0-9]+]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[WRAPPER]]
16+
// CHECK: [[UNWRAPPED:%[0-9]+]] = moveonlywrapper_to_copyable_addr [[MARKED]]
17+
// CHECK: %{{[0-9]+}} = apply %{{[0-9]+}}([[UNWRAPPED]], %{{[0-9]+}}) : $@convention(cxx_method) (@in_guaranteed NonTrivialInWrapper, @in_guaranteed HasMethods) -> ()
18+
var m2 = HasMethods()
19+
// CHECK: [[ACCESS:%[0-9]+]] = begin_access [modify] [unknown] [[INPUT2]]
20+
// CHECK: %{{[0-9]+}} = apply %32([[ACCESS]], %{{[0-9]+}}) : $@convention(cxx_method) (@inout NonTrivialInWrapper, @in_guaranteed HasMethods) -> ()
21+
// CHECK-NEXT: end_access [[ACCESS]]
22+
m2.nonTrivialTakesRef(&y)
23+
}

test/Interop/Cxx/class/nonescapable-lifetimebound.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// RUN: %target-swift-frontend -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs -emit-sil %t/test.swift -enable-experimental-feature LifetimeDependence -cxx-interoperability-mode=default -diagnostic-style llvm 2>&1 | %FileCheck %s
44
// RUN: not %target-swift-frontend -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs -emit-sil %t/test.swift -cxx-interoperability-mode=default -diagnostic-style llvm 2>&1 | %FileCheck %s -check-prefix=CHECK-NO-LIFETIMES
55

6+
// REQUIRES: swift_feature_LifetimeDependence
67

78
//--- Inputs/module.modulemap
89
module Test {

0 commit comments

Comments
 (0)