Skip to content

Commit 109e208

Browse files
authored
Merge pull request #78807 from swiftlang/gaborh/generated-ctors
[cxx-interop] Fix spurious lifetime dependence errors
2 parents c1e0770 + b6fce85 commit 109e208

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,6 +2033,18 @@ namespace {
20332033
return semanticsKind == CxxRecordSemanticsKind::MoveOnly;
20342034
}
20352035

2036+
void markReturnsUnsafeNonescapable(AbstractFunctionDecl *fd) {
2037+
if (Impl.SwiftContext.LangOpts.hasFeature(Feature::LifetimeDependence)) {
2038+
fd->getAttrs().add(new (Impl.SwiftContext)
2039+
UnsafeNonEscapableResultAttr(/*Implicit=*/true));
2040+
if (Impl.SwiftContext.LangOpts.hasFeature(Feature::SafeInterop) &&
2041+
Impl.SwiftContext.LangOpts.hasFeature(
2042+
Feature::AllowUnsafeAttribute))
2043+
fd->getAttrs().add(new (Impl.SwiftContext)
2044+
UnsafeAttr(/*Implicit=*/true));
2045+
}
2046+
}
2047+
20362048
Decl *VisitRecordDecl(const clang::RecordDecl *decl) {
20372049
// Track whether this record contains fields we can't reference in Swift
20382050
// as stored properties.
@@ -2228,12 +2240,14 @@ namespace {
22282240
MoveOnlyAttr(/*Implicit=*/true));
22292241
}
22302242

2243+
bool isNonEscapable = false;
22312244
if (evaluateOrDefault(
22322245
Impl.SwiftContext.evaluator,
22332246
ClangTypeEscapability({decl->getTypeForDecl(), Impl}),
22342247
CxxEscapability::Unknown) == CxxEscapability::NonEscapable) {
22352248
result->getAttrs().add(new (Impl.SwiftContext)
22362249
NonEscapableAttr(/*Implicit=*/true));
2250+
isNonEscapable = true;
22372251
}
22382252

22392253
// FIXME: Figure out what to do with superclasses in C++. One possible
@@ -2378,6 +2392,9 @@ namespace {
23782392
synthesizer.createValueConstructor(result, member,
23792393
/*want param names*/ true,
23802394
/*wantBody=*/true);
2395+
2396+
if (isNonEscapable)
2397+
markReturnsUnsafeNonescapable(valueCtor);
23812398
ctors.push_back(valueCtor);
23822399
}
23832400
// TODO: we have a problem lazily looking up members of an unnamed
@@ -2402,7 +2419,13 @@ namespace {
24022419
(!cxxRecordDecl->hasDefaultConstructor() ||
24032420
cxxRecordDecl->ctors().empty());
24042421
}
2405-
if (hasZeroInitializableStorage && needsEmptyInitializer) {
2422+
2423+
// TODO: builtin "zeroInitializer" does not work with non-escapable
2424+
// types yet. Don't generate an initializer.
2425+
if (hasZeroInitializableStorage && needsEmptyInitializer &&
2426+
(!Impl.SwiftContext.LangOpts.hasFeature(
2427+
Feature::LifetimeDependence) ||
2428+
!isNonEscapable)) {
24062429
// Add default constructor for the struct if compiling in C mode.
24072430
// If we're compiling for C++:
24082431
// 1. If a default constructor is declared, don't synthesize one.
@@ -2415,7 +2438,6 @@ namespace {
24152438
// constructor available in Swift.
24162439
ConstructorDecl *defaultCtor =
24172440
synthesizer.createDefaultConstructor(result);
2418-
ctors.push_back(defaultCtor);
24192441
if (cxxRecordDecl) {
24202442
auto attr = AvailableAttr::createUniversallyDeprecated(
24212443
defaultCtor->getASTContext(),
@@ -2425,6 +2447,7 @@ namespace {
24252447
"");
24262448
defaultCtor->getAttrs().add(attr);
24272449
}
2450+
ctors.push_back(defaultCtor);
24282451
}
24292452

24302453
bool forceMemberwiseInitializer = false;
@@ -2454,6 +2477,9 @@ namespace {
24542477
if (!hasUnreferenceableStorage)
24552478
valueCtor->setIsMemberwiseInitializer();
24562479

2480+
if (isNonEscapable)
2481+
markReturnsUnsafeNonescapable(valueCtor);
2482+
24572483
ctors.push_back(valueCtor);
24582484
}
24592485

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ private:
2323
};
2424

2525
struct SWIFT_NONESCAPABLE OtherView {
26-
OtherView() : member(nullptr) {}
2726
OtherView(View v [[clang::lifetimebound]]) : member(v.member) {}
2827
OtherView(const OtherView&) = default;
2928
private:
@@ -105,6 +104,10 @@ CaptureView getCaptureView(const Owner& owner [[clang::lifetimebound]]) {
105104
return CaptureView(View{&owner.data});
106105
}
107106

107+
struct SWIFT_NONESCAPABLE AggregateView {
108+
const int *member;
109+
};
110+
108111
// CHECK: sil [clang makeOwner] {{.*}}: $@convention(c) () -> Owner
109112
// CHECK: sil [clang getView] {{.*}} : $@convention(c) (@in_guaranteed Owner) -> @lifetime(borrow 0) @owned View
110113
// CHECK: sil [clang getViewFromFirst] {{.*}} : $@convention(c) (@in_guaranteed Owner, @in_guaranteed Owner) -> @lifetime(borrow 0) @owned View
@@ -120,18 +123,20 @@ CaptureView getCaptureView(const Owner& owner [[clang::lifetimebound]]) {
120123
// CHECK: sil [clang CaptureView.captureView] {{.*}} : $@convention(cxx_method) (View, @lifetime(copy 0) @inout CaptureView) -> ()
121124
// CHECK: sil [clang CaptureView.handOut] {{.*}} : $@convention(cxx_method) (@lifetime(copy 1) @inout View, @in_guaranteed CaptureView) -> ()
122125

123-
// CHECK-NO-LIFETIMES: nonescapable.h:36:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
124-
// CHECK-NO-LIFETIMES: nonescapable.h:40:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
125-
// CHECK-NO-LIFETIMES: nonescapable.h:46:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
126-
// CHECK-NO-LIFETIMES: nonescapable.h:53:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
127-
// CHECK-NO-LIFETIMES: nonescapable.h:23:10: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
128-
// CHECK-NO-LIFETIMES: nonescapable.h:27:10: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
126+
// CHECK-NO-LIFETIMES: nonescapable.h:35:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
127+
// CHECK-NO-LIFETIMES: nonescapable.h:39:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
128+
// CHECK-NO-LIFETIMES: nonescapable.h:45:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
129+
// CHECK-NO-LIFETIMES: nonescapable.h:52:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
130+
// CHECK-NO-LIFETIMES: nonescapable.h:22:10: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
131+
// CHECK-NO-LIFETIMES: nonescapable.h:26:10: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
129132
// CHECK-NO-LIFETIMES: nonescapable.h:4:5: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
130133
// CHECK-NO-LIFETIMES: nonescapable.h:5:5: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
131134
// CHECK-NO-LIFETIMES: nonescapable.h:13:5: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
132-
// CHECK-NO-LIFETIMES: nonescapable.h:14:5: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
133-
// CHECK-NO-LIFETIMES: nonescapable.h:68:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
134-
// CHECK-NO-LIFETIMES: nonescapable.h:91:13: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
135+
// CHECK-NO-LIFETIMES: nonescapable.h:12:27: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
136+
// CHECK-NO-LIFETIMES: nonescapable.h:67:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
137+
// CHECK-NO-LIFETIMES: nonescapable.h:90:13: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
138+
// CHECK-NO-LIFETIMES: nonescapable.h:94:27: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
139+
// CHECK-NO-LIFETIMES: nonescapable.h:94:27: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
135140
// CHECK-NO-LIFETIMES-NOT: error
136141

137142
//--- test.swift
@@ -155,3 +160,7 @@ public func test() {
155160
cv.captureView(v1)
156161
cv.handOut(&v1)
157162
}
163+
164+
public func test2(_ x: AggregateView) {
165+
let _ = AggregateView(member: x.member)
166+
}

0 commit comments

Comments
 (0)