Skip to content

Commit 7b884d9

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 1388b80 + 7c5a59f commit 7b884d9

File tree

4 files changed

+58
-5
lines changed

4 files changed

+58
-5
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -741,20 +741,45 @@ namespace {
741741
paramQualType->getPointeeType().isConstQualified())
742742
paramQualType = paramQualType->getPointeeType();
743743

744+
// Mark any `sending` parameters if need be.
745+
ImportTypeAttrs paramAttributes;
746+
if (Impl.SwiftContext.LangOpts.hasFeature(Feature::SendingArgsAndResults)) {
747+
getConcurrencyAttrs(Impl.SwiftContext, ImportTypeKind::Parameter,
748+
paramAttributes, paramQualType);
749+
}
750+
744751
auto swiftParamTy = Impl.importTypeIgnoreIUO(
745752
paramQualType, paramImportKind, addImportDiagnostic,
746753
AllowNSUIntegerAsInt, Bridging, ImportTypeAttrs(), OTK_Optional);
747754
if (!swiftParamTy)
748755
return Type();
749756

757+
ParameterTypeFlags flags;
758+
flags = flags.withSending(
759+
paramAttributes.contains(ImportTypeAttr::Sending));
760+
750761
// FIXME(https://github.com/apple/swift/issues/45134): If we were walking TypeLocs, we could actually get parameter names.
751762
// The probably doesn't matter outside of a FuncDecl, which we'll have
752763
// to special-case, but it's an interesting bit of data loss.
753-
params.push_back(FunctionType::Param(swiftParamTy));
764+
params.emplace_back(swiftParamTy, Identifier(), flags);
765+
}
766+
767+
// Mark any `sending` result types if need be.
768+
auto extInfo = FunctionType::ExtInfo();
769+
ImportTypeAttrs resultAttributes;
770+
if (Impl.SwiftContext.LangOpts.hasFeature(Feature::SendingArgsAndResults)) {
771+
getConcurrencyAttrs(Impl.SwiftContext, ImportTypeKind::Result,
772+
resultAttributes, type->getReturnType());
773+
774+
const bool sending = resultAttributes.contains(ImportTypeAttr::Sending);
775+
extInfo = FunctionType::ExtInfo()
776+
.intoBuilder()
777+
.withSendingResult(sending)
778+
.build();
754779
}
755780

756781
// Form the function type.
757-
return FunctionType::get(params, resultTy, FunctionType::ExtInfo());
782+
return FunctionType::get(params, resultTy, extInfo);
758783
}
759784

760785
ImportResult
@@ -1729,17 +1754,21 @@ void swift::getConcurrencyAttrs(ASTContext &SwiftContext,
17291754
SwiftContext.LangOpts.hasFeature(Feature::SendableCompletionHandlers) &&
17301755
importKind == ImportTypeKind::CompletionHandlerParameter;
17311756
bool isNonSendable = false;
1757+
bool isSending = false;
17321758

17331759
// Consider only immediate attributes, don't look through the typerefs
17341760
// because they are imported separately.
17351761
findSwiftAttributes(type, [&](const clang::SwiftAttrAttr *attr) {
17361762
if (isMainActorAttr(attr)) {
17371763
isMainActor = true;
17381764
isSendable = true; // MainActor implies Sendable
1739-
} else if (attr->getAttribute() == "@Sendable")
1765+
} else if (attr->getAttribute() == "@Sendable") {
17401766
isSendable = true;
1741-
else if (attr->getAttribute() == "@_nonSendable")
1767+
} else if (attr->getAttribute() == "@_nonSendable") {
17421768
isNonSendable = true;
1769+
} else if (attr->getAttribute() == "sending") {
1770+
isSending = true;
1771+
}
17431772
});
17441773

17451774
if (isMainActor)
@@ -1748,6 +1777,8 @@ void swift::getConcurrencyAttrs(ASTContext &SwiftContext,
17481777
attrs |= ImportTypeAttr::Sendable;
17491778
if (isNonSendable)
17501779
attrs -= ImportTypeAttr::Sendable;
1780+
if (isSending)
1781+
attrs |= ImportTypeAttr::Sending;
17511782
}
17521783

17531784
ImportedType ClangImporter::Implementation::importType(

lib/ClangImporter/ImporterImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ enum class ImportTypeAttr : uint8_t {
217217
///
218218
/// This ensures that the parameter is not marked as Unmanaged.
219219
CFUnretainedOutParameter = 1 << 5,
220+
221+
/// Type should be imported as though declaration was marked with
222+
/// \c __attribute__((swift_attr("sending"))) .
223+
Sending = 1 << 6,
220224
};
221225

222226
/// Find and iterate over swift attributes embedded in the type

test/ClangImporter/Inputs/sending.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@ sendUserDefinedFromGlobalFunction(NonSendableCStruct other) SWIFT_SENDING;
4343
void sendUserDefinedIntoGlobalFunction(
4444
NonSendableCStruct arg SWIFT_SENDING);
4545

46+
void sendingWithCompletionHandler(void (^completion)(SWIFT_SENDING NonSendableCStruct arg));
47+
SWIFT_SENDING NonSendableCStruct sendingWithLazyReturn(SWIFT_SENDING NonSendableCStruct (^makeLazily)(void));
48+
4649
#pragma clang assume_nonnull end

test/ClangImporter/sending.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -swift-version 6 -disable-availability-checking -emit-sil -o /dev/null %s -parse-as-library -enable-experimental-feature SendingArgsAndResults -verify -import-objc-header %S/Inputs/sending.h
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -swift-version 6 -disable-availability-checking -emit-sil -o /dev/null %s -parse-as-library -enable-experimental-feature SendingArgsAndResults -verify -import-objc-header %S/Inputs/sending.h
22

33
// REQUIRES: concurrency
44
// REQUIRES: swift_feature_SendingArgsAndResults
@@ -38,3 +38,18 @@ func funcTestSendingArg() async {
3838
// expected-note @-1 {{'x' used after being passed as a 'sending' parameter}}
3939
useValue(x) // expected-note {{access can happen concurrently}}
4040
}
41+
42+
func funcTestSendingClosureArg() async {
43+
sendingWithCompletionHandler { (x: sending NonSendableCStruct) in
44+
sendUserDefinedIntoGlobalFunction(x) // expected-error {{sending 'x' risks causing data races}}
45+
// expected-note @-1 {{'x' used after being passed as a 'sending' parameter}}
46+
useValue(x) // expected-note {{access can happen concurrently}}
47+
}
48+
49+
let x = sendingWithLazyReturn { () -> sending NonSendableCStruct in
50+
NonSendableCStruct()
51+
}
52+
sendUserDefinedIntoGlobalFunction(x) // expected-error {{sending 'x' risks causing data races}}
53+
// expected-note @-1 {{'x' used after being passed as a 'sending' parameter}}
54+
useValue(x) // expected-note {{access can happen concurrently}}
55+
}

0 commit comments

Comments
 (0)