Skip to content

Commit ed7372b

Browse files
committed
[Clang importer] Import @_unsafeSendable on C function/ObjC method params
1 parent b68f855 commit ed7372b

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,7 +1711,7 @@ static Type applyToFunctionType(
17111711
}
17121712

17131713
Type ClangImporter::Implementation::applyParamAttributes(
1714-
const clang::ParmVarDecl *param, Type type) {
1714+
const clang::ParmVarDecl *param, Type type, bool &isUnsafeSendable) {
17151715
if (!param->hasAttrs())
17161716
return type;
17171717

@@ -1748,6 +1748,12 @@ Type ClangImporter::Implementation::applyParamAttributes(
17481748

17491749
continue;
17501750
}
1751+
1752+
// Map @_unsafeSendable.
1753+
if (swiftAttr->getAttribute() == "@_unsafeSendable") {
1754+
isUnsafeSendable = true;
1755+
continue;
1756+
}
17511757
}
17521758

17531759
return type;
@@ -1928,7 +1934,8 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
19281934
}
19291935

19301936
// Apply attributes to the type.
1931-
swiftParamTy = applyParamAttributes(param, swiftParamTy);
1937+
bool isUnsafeSendable = false;
1938+
swiftParamTy = applyParamAttributes(param, swiftParamTy, isUnsafeSendable);
19321939

19331940
// Figure out the name for this parameter.
19341941
Identifier bodyName = importFullName(param, CurrentVersion)
@@ -1949,6 +1956,7 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
19491956
paramInfo->setSpecifier(ParamSpecifier::Default);
19501957
paramInfo->setInterfaceType(swiftParamTy);
19511958
recordImplicitUnwrapForDecl(paramInfo, isParamTypeImplicitlyUnwrapped);
1959+
recordUnsafeSendableForDecl(paramInfo, isUnsafeSendable);
19521960
parameters.push_back(paramInfo);
19531961
++index;
19541962
}
@@ -2426,7 +2434,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
24262434
}
24272435

24282436
// Apply Clang attributes to the parameter type.
2429-
swiftParamTy = applyParamAttributes(param, swiftParamTy);
2437+
bool isUnsafeSendable = false;
2438+
swiftParamTy = applyParamAttributes(param, swiftParamTy, isUnsafeSendable);
24302439

24312440
// Figure out the name for this parameter.
24322441
Identifier bodyName = importFullName(param, CurrentVersion)
@@ -2450,6 +2459,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
24502459
paramInfo->setSpecifier(ParamSpecifier::Default);
24512460
paramInfo->setInterfaceType(swiftParamTy);
24522461
recordImplicitUnwrapForDecl(paramInfo, paramIsIUO);
2462+
recordUnsafeSendableForDecl(paramInfo, isUnsafeSendable);
24532463

24542464
// Determine whether we have a default argument.
24552465
if (kind == SpecialMethodKind::Regular ||

lib/ClangImporter/ImporterImpl.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,14 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
683683
decl->setImplicitlyUnwrappedOptional(true);
684684
}
685685

686+
void recordUnsafeSendableForDecl(ValueDecl *decl, bool isUnsafeSendable) {
687+
if (!isUnsafeSendable)
688+
return;
689+
690+
decl->getAttrs().add(
691+
new (SwiftContext) UnsafeSendableAttr(/*implicit=*/true));
692+
}
693+
686694
/// Retrieve the Clang AST context.
687695
clang::ASTContext &getClangASTContext() const {
688696
return Instance->getASTContext();
@@ -833,7 +841,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
833841
void importAttributes(const clang::NamedDecl *ClangDecl, Decl *MappedDecl,
834842
const clang::ObjCContainerDecl *NewContext = nullptr);
835843

836-
Type applyParamAttributes(const clang::ParmVarDecl *param, Type type);
844+
Type applyParamAttributes(const clang::ParmVarDecl *param, Type type,
845+
bool &isUnsafeSendable);
837846

838847
/// If we already imported a given decl, return the corresponding Swift decl.
839848
/// Otherwise, return nullptr.

test/ClangImporter/objc_async.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func testSlowServerOldSchool(slowServer: SlowServer) {
8585
func testSendable(fn: () -> Void) { // expected-note{{parameter 'fn' is implicitly non-concurrent}}
8686
doSomethingConcurrently(fn)
8787
// expected-error@-1{{passing non-concurrent parameter 'fn' to function expecting a @Sendable closure}}
88+
doSomethingConcurrentlyButUnsafe(fn) // okay, @Sendable not part of the type
8889

8990
var x = 17
9091
doSomethingConcurrently {
@@ -94,6 +95,14 @@ func testSendable(fn: () -> Void) { // expected-note{{parameter 'fn' is implicit
9495
}
9596
}
9697

98+
func testSendableInAsync() async {
99+
var x = 17
100+
doSomethingConcurrentlyButUnsafe {
101+
x = 42 // expected-error{{mutation of captured var 'x' in concurrently-executing code}}
102+
}
103+
print(x)
104+
}
105+
97106
// Check import of attributes
98107
func globalAsync() async { }
99108

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,8 @@ __attribute__((__swift_attr__("@MainActor(unsafe)")))
150150
// Do something concurrently, but without escaping.
151151
void doSomethingConcurrently(__attribute__((noescape)) __attribute__((swift_attr("@Sendable"))) void (^block)(void));
152152

153+
154+
155+
void doSomethingConcurrentlyButUnsafe(__attribute__((noescape)) __attribute__((swift_attr("@_unsafeSendable"))) void (^block)(void));
156+
153157
#pragma clang assume_nonnull end

0 commit comments

Comments
 (0)