Skip to content

Commit 738b4c6

Browse files
author
Gabor Horvath
committed
[cxx-interop] Add a SWIFT_NONESCAPABLE attribute to the bridging header
This makes it easier to experiment with noescapable types in interop. Moreover, we always wanted to have this annotation for completeness, similar to SWIFT_NONCOPYABLE.
1 parent 39b8b3c commit 738b4c6

File tree

5 files changed

+46
-2
lines changed

5 files changed

+46
-2
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7374,6 +7374,10 @@ static bool hasNonCopyableAttr(const clang::RecordDecl *decl) {
73747374
return hasSwiftAttribute(decl, "~Copyable");
73757375
}
73767376

7377+
bool importer::hasNonEscapableAttr(const clang::RecordDecl *decl) {
7378+
return hasSwiftAttribute(decl, "~Escapable");
7379+
}
7380+
73777381
/// Recursively checks that there are no pointers in any fields or base classes.
73787382
/// Does not check C++ records with specific API annotations.
73797383
static bool hasPointerInSubobjects(const clang::CXXRecordDecl *decl) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,6 +2202,12 @@ namespace {
22022202
MoveOnlyAttr(/*Implicit=*/true));
22032203
}
22042204

2205+
if (Impl.SwiftContext.LangOpts.hasFeature(Feature::NonescapableTypes) &&
2206+
importer::hasNonEscapableAttr(decl)) {
2207+
result->getAttrs().add(new (Impl.SwiftContext)
2208+
NonEscapableAttr(/*Implicit=*/true));
2209+
}
2210+
22052211
// FIXME: Figure out what to do with superclasses in C++. One possible
22062212
// solution would be to turn them into members and add conversion
22072213
// functions.

lib/ClangImporter/ImporterImpl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,9 +2029,11 @@ inline std::string getPrivateOperatorName(const std::string &OperatorToken) {
20292029

20302030
bool hasUnsafeAPIAttr(const clang::Decl *decl);
20312031

2032+
bool hasNonEscapableAttr(const clang::RecordDecl *decl);
2033+
20322034
bool isViewType(const clang::CXXRecordDecl *decl);
20332035

2034-
}
2035-
}
2036+
} // end namespace importer
2037+
} // end namespace swift
20362038

20372039
#endif

lib/ClangImporter/SwiftBridging/swift/bridging

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@
158158
#define SWIFT_NONCOPYABLE \
159159
__attribute__((swift_attr("~Copyable")))
160160

161+
/// Specifies that a specific c++ type such class or struct should be imported
162+
/// as a non-escapable Swift value type when the non-escapable language feature
163+
/// is enabled.
164+
#define SWIFT_NONESCAPABLE \
165+
__attribute__((swift_attr("~Escapable")))
166+
161167
#else // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
162168

163169
// Empty defines for compilers that don't support `attribute(swift_attr)`.
@@ -172,6 +178,7 @@
172178
#define SWIFT_MUTATING
173179
#define SWIFT_UNCHECKED_SENDABLE
174180
#define SWIFT_NONCOPYABLE
181+
#define SWIFT_NONESCAPABLE
175182

176183
#endif // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
177184

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: not %target-swift-frontend -typecheck -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs %t/test.swift -enable-experimental-feature NonescapableTypes -cxx-interoperability-mode=default -diagnostic-style llvm 2>&1 | %FileCheck %s
4+
5+
//--- Inputs/module.modulemap
6+
module Test {
7+
header "nonescapable.h"
8+
requires cplusplus
9+
}
10+
11+
//--- Inputs/nonescapable.h
12+
#include "swift/bridging"
13+
14+
struct SWIFT_NONESCAPABLE A {
15+
int a;
16+
};
17+
18+
//--- test.swift
19+
20+
import Test
21+
22+
// CHECK: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
23+
public func test() -> A {
24+
A()
25+
}

0 commit comments

Comments
 (0)