Skip to content

Commit f592747

Browse files
authored
Merge pull request swiftlang#84104 from susmonteiro/6.2-nonescapable-std-optional
🍒 [cxx-interop] Prevent crash when importing a std::optional of nonescapable
2 parents 5bc14ff + 29e5549 commit f592747

File tree

2 files changed

+81
-23
lines changed

2 files changed

+81
-23
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,8 +2377,18 @@ namespace {
23772377
}
23782378

23792379
auto *vd = cast<VarDecl>(member);
2380-
if (!isNonEscapable) {
2381-
if (const auto *fd = dyn_cast<clang::FieldDecl>(nd))
2380+
auto getFieldDecl =
2381+
[](const clang::NamedDecl *decl) -> const clang::FieldDecl * {
2382+
if (const clang::FieldDecl *fd = dyn_cast<clang::FieldDecl>(decl))
2383+
return fd;
2384+
if (const clang::IndirectFieldDecl *ind =
2385+
dyn_cast<clang::IndirectFieldDecl>(decl))
2386+
return ind->getAnonField();
2387+
return nullptr;
2388+
};
2389+
2390+
if (!isNonEscapable && !decl->isAnonymousStructOrUnion()) {
2391+
if (const auto *fd = getFieldDecl(nd)) {
23822392
if (evaluateOrDefault(
23832393
Impl.SwiftContext.evaluator,
23842394
ClangTypeEscapability({fd->getType().getTypePtr(), &Impl}),
@@ -2391,6 +2401,7 @@ namespace {
23912401
decl->getLocation());
23922402
return nullptr;
23932403
}
2404+
}
23942405
}
23952406
members.push_back(vd);
23962407
}

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

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Test {
1414
//--- Inputs/nonescapable.h
1515
#include "swift/bridging"
1616
#include <vector>
17+
#include <optional>
1718

1819
struct SWIFT_NONESCAPABLE View {
1920
View() : member(nullptr) {}
@@ -99,54 +100,87 @@ struct SWIFT_ESCAPABLE Invalid {
99100
View v;
100101
};
101102

103+
struct SWIFT_NONESCAPABLE NonEscapable {};
104+
105+
template<typename T>
106+
struct HasAnonUnion {
107+
union {
108+
int known;
109+
T unknown;
110+
};
111+
};
112+
113+
template<typename T>
114+
struct HasAnonStruct {
115+
struct {
116+
int known;
117+
T unknown;
118+
};
119+
};
120+
121+
template<typename T>
122+
struct SWIFT_NONESCAPABLE NonEscapableHasAnonUnion {
123+
union {
124+
int known;
125+
T unknown;
126+
};
127+
};
128+
129+
using HasAnonUnionNonEscapable = HasAnonUnion<NonEscapable>;
130+
using HasAnonStructNonEscapable = HasAnonStruct<NonEscapable>;
131+
using NonEscapableHasAnonUnionNonEscapable = NonEscapableHasAnonUnion<NonEscapable>;
132+
using NonEscapableOptional = std::optional<NonEscapable>;
133+
102134
//--- test.swift
103135
import Test
104136
import CxxStdlib
105137

106138
// CHECK: error: cannot find type 'Invalid' in scope
107139
// CHECK: note: escapable record 'Invalid' cannot have non-escapable field 'v'
140+
// CHECK-NO-LIFETIMES: error: cannot find type 'Invalid' in scope
141+
// CHECK-NO-LIFETIMES: note: escapable record 'Invalid' cannot have non-escapable field 'v'
108142
public func importInvalid(_ x: Invalid) {
109143
}
110144

111145
// CHECK: error: a function with a ~Escapable result needs a parameter to depend on
112-
// CHECK-NO-LIFETIMES: test.swift:11:32: error: a function cannot return a ~Escapable result
146+
// CHECK-NO-LIFETIMES: test.swift:13:32: error: a function cannot return a ~Escapable result
113147
public func noAnnotations() -> View {
114-
// CHECK: nonescapable.h:16:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
115-
// CHECK-NO-LIFETIMES: nonescapable.h:16:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
148+
// CHECK: nonescapable.h:17:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
149+
// CHECK-NO-LIFETIMES: nonescapable.h:17:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
116150
f(nil)
117-
// CHECK: nonescapable.h:20:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
118-
// CHECK-NO-LIFETIMES: nonescapable.h:20:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
151+
// CHECK: nonescapable.h:21:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
152+
// CHECK-NO-LIFETIMES: nonescapable.h:21:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies [#ClangDeclarationImport]
119153
// No duplicate warning for f2:
120-
// CHECK-NOT: nonescapable.h:20
154+
// CHECK-NOT: nonescapable.h:21
121155
f2(nil, nil)
122-
// CHECK: nonescapable.h:24:6: warning: the returned type 'View' is annotated as non-escapable; its lifetime dependencies must be annotated [#ClangDeclarationImport]
123-
// CHECK-NO-LIFETIMES: nonescapable.h:24:6: warning: the returned type 'View' is annotated as non-escapable; its lifetime dependencies must be annotated [#ClangDeclarationImport]
124-
// CHECK-NO-LIFETIMES: nonescapable.h:24:6: error: a function cannot return a ~Escapable result
156+
// CHECK: nonescapable.h:25:6: warning: the returned type 'View' is annotated as non-escapable; its lifetime dependencies must be annotated [#ClangDeclarationImport]
157+
// CHECK-NO-LIFETIMES: nonescapable.h:25:6: warning: the returned type 'View' is annotated as non-escapable; its lifetime dependencies must be annotated [#ClangDeclarationImport]
158+
// CHECK-NO-LIFETIMES: nonescapable.h:25:6: error: a function cannot return a ~Escapable result
125159
g(nil)
126160
h1(nil)
127-
// CHECK-NO-LIFETIMES: nonescapable.h:34:21: error: a function cannot return a ~Escapable result
128-
h2(nil)
129161
// CHECK-NO-LIFETIMES: nonescapable.h:35:21: error: a function cannot return a ~Escapable result
162+
h2(nil)
163+
// CHECK-NO-LIFETIMES: nonescapable.h:36:21: error: a function cannot return a ~Escapable result
130164
h3(nil)
131165
i1()
132-
// CHECK: nonescapable.h:39:39: error: template parameter 'Missing' does not exist
133-
// CHECK-NO-LIFETIMES: nonescapable.h:39:39: error: template parameter 'Missing' does not exist
166+
// CHECK: nonescapable.h:40:39: error: template parameter 'Missing' does not exist
167+
// CHECK-NO-LIFETIMES: nonescapable.h:40:39: error: template parameter 'Missing' does not exist
134168
i2()
135-
// CHECK: nonescapable.h:45:33: error: template parameter 'S' expected to be a type parameter
136-
// CHECK-NO-LIFETIMES: nonescapable.h:45:33: error: template parameter 'S' expected to be a type parameter
169+
// CHECK: nonescapable.h:46:33: error: template parameter 'S' expected to be a type parameter
170+
// CHECK-NO-LIFETIMES: nonescapable.h:46:33: error: template parameter 'S' expected to be a type parameter
137171
j1()
138-
// CHECK-NO-LIFETIMES: nonescapable.h:63:41: error: a function cannot return a ~Escapable result
139-
j2()
140172
// CHECK-NO-LIFETIMES: nonescapable.h:64:41: error: a function cannot return a ~Escapable result
173+
j2()
174+
// CHECK-NO-LIFETIMES: nonescapable.h:65:41: error: a function cannot return a ~Escapable result
141175
j3()
142176
k1();
143-
// CHECK-NO-LIFETIMES: nonescapable.h:70:15: error: a function cannot return a ~Escapable result
177+
// CHECK-NO-LIFETIMES: nonescapable.h:71:15: error: a function cannot return a ~Escapable result
144178
k2();
145-
// CHECK-NO-LIFETIMES: nonescapable.h:71:22: error: a function cannot return a ~Escapable result
179+
// CHECK-NO-LIFETIMES: nonescapable.h:72:22: error: a function cannot return a ~Escapable result
146180
k3();
147181
l1();
148-
// CHECK: nonescapable.h:77:12: error: a function with a ~Escapable result needs a parameter to depend on
149-
// CHECK-NO-LIFETIMES: nonescapable.h:77:12: error: a function cannot return a ~Escapable result
182+
// CHECK: nonescapable.h:78:12: error: a function with a ~Escapable result needs a parameter to depend on
183+
// CHECK-NO-LIFETIMES: nonescapable.h:78:12: error: a function cannot return a ~Escapable result
150184
l2();
151185
return View()
152186
}
@@ -162,6 +196,19 @@ public func test3(_ x: inout View) {
162196
// CHECK-NO-LIFETIMES: note: return type unavailable (cannot import)
163197
// CHECK-NO-LIFETIMES: pointer to non-escapable type 'View' cannot be imported
164198
}
199+
200+
public func anonymousUnions() {
201+
_ = HasAnonUnionNonEscapable()
202+
// CHECK: error: cannot find 'HasAnonUnionNonEscapable' in scope
203+
// CHECK-NO-LIFETIMES: error: cannot find 'HasAnonUnionNonEscapable' in scope
204+
_ = HasAnonStructNonEscapable()
205+
// CHECK: error: cannot find 'HasAnonStructNonEscapable' in scope
206+
// CHECK-NO-LIFETIMES: error: cannot find 'HasAnonStructNonEscapable' in scope
207+
_ = NonEscapableHasAnonUnionNonEscapable()
208+
_ = NonEscapableOptional()
209+
// CHECK-NO-LIFETIMES: error: an initializer cannot return a ~Escapable result
210+
}
211+
165212
// CHECK-NOT: error
166213
// CHECK-NOT: warning
167214
// CHECK-NO-LIFETIMES-NOT: error

0 commit comments

Comments
 (0)