Skip to content

Commit c335b80

Browse files
authored
[Swiftify] Don't create safe wrapper for autoreleasing pointers (#81568) (#81590)
_SwiftifyImport doesn't know how to handle AutoreleasingUnsafeMutablePointer, so we should not attach any .countedBy information for pointers that are imported as this type. This also adds defensive checks against adding .countedBy to any pointer type that _SwiftifyImport doesn't know how to transform. rdar://151479521
1 parent c2ce908 commit c335b80

File tree

7 files changed

+52
-8
lines changed

7 files changed

+52
-8
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9166,6 +9166,14 @@ static bool SwiftifiableCAT(const clang::CountAttributedType *CAT) {
91669166
return CAT && CATExprValidator().Visit(CAT->getCountExpr());
91679167
}
91689168

9169+
static bool SwiftifiablePointerType(Type swiftType) {
9170+
// don't try to transform any Swift types that _SwiftifyImport doesn't know how to handle
9171+
Type nonnullType = swiftType->lookThroughSingleOptionalType();
9172+
PointerTypeKind PTK;
9173+
return nonnullType->isOpaquePointer() ||
9174+
(nonnullType->getAnyPointerElementType(PTK) && PTK != PTK_AutoreleasingUnsafeMutablePointer);
9175+
}
9176+
91699177
void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
91709178
if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers))
91719179
return;
@@ -9201,10 +9209,11 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
92019209
return false;
92029210
};
92039211
SwiftifyInfoPrinter printer(getClangASTContext(), SwiftContext, out);
9212+
Type swiftReturnTy = MappedDecl->getResultInterfaceType();
92049213
bool returnIsStdSpan = registerStdSpanTypeMapping(
9205-
MappedDecl->getResultInterfaceType(), ClangDecl->getReturnType());
9214+
swiftReturnTy, ClangDecl->getReturnType());
92069215
auto *CAT = ClangDecl->getReturnType()->getAs<clang::CountAttributedType>();
9207-
if (SwiftifiableCAT(CAT)) {
9216+
if (SwiftifiableCAT(CAT) && SwiftifiablePointerType(swiftReturnTy)) {
92089217
printer.printCountedBy(CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX);
92099218
attachMacro = true;
92109219
}
@@ -9218,14 +9227,15 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
92189227
for (auto [index, clangParam] : llvm::enumerate(ClangDecl->parameters())) {
92199228
auto clangParamTy = clangParam->getType();
92209229
auto swiftParam = MappedDecl->getParameters()->get(index);
9230+
Type swiftParamTy = swiftParam->getInterfaceType();
92219231
bool paramHasBoundsInfo = false;
92229232
auto *CAT = clangParamTy->getAs<clang::CountAttributedType>();
9223-
if (SwiftifiableCAT(CAT)) {
9233+
if (SwiftifiableCAT(CAT) && SwiftifiablePointerType(swiftParamTy)) {
92249234
printer.printCountedBy(CAT, index);
92259235
attachMacro = paramHasBoundsInfo = true;
92269236
}
92279237
bool paramIsStdSpan = registerStdSpanTypeMapping(
9228-
swiftParam->getInterfaceType(), clangParamTy);
9238+
swiftParamTy, clangParamTy);
92299239
paramHasBoundsInfo |= paramIsStdSpan;
92309240

92319241
bool paramHasLifetimeInfo = false;
@@ -9236,7 +9246,7 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
92369246
if (clangParam->hasAttr<clang::LifetimeBoundAttr>()) {
92379247
printer.printLifetimeboundReturn(
92389248
index, !paramHasBoundsInfo &&
9239-
swiftParam->getInterfaceType()->isEscapable());
9249+
swiftParamTy->isEscapable());
92409250
paramHasLifetimeInfo = true;
92419251
returnHasLifetimeInfo = true;
92429252
}

test/Interop/C/swiftify-import/Inputs/module.modulemap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,3 @@ module SizedByNoEscapeClang {
1414
header "sized-by-noescape.h"
1515
export *
1616
}
17-

test/Interop/ObjC/lit.local.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if 'objc_interop' not in config.available_features:
2+
config.unsupported = True
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module NoSwiftifyClang {
2+
header "objc-no-swiftify.h"
3+
export *
4+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#define __counted_by(x) __attribute__((__counted_by__(x)))
2+
3+
@interface SomeClass
4+
- (int)numberOfSegments;
5+
@end
6+
7+
void autoreleaseParam(SomeClass * __autoreleasing * __counted_by(len) p, int len); // expected-note{{declared here}}
8+
9+
SomeClass * __autoreleasing * __counted_by(len) autoreleaseReturn(int len);

test/Interop/ObjC/swiftify-import/counted-by-in-class.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
// RUN: %target-swift-ide-test -plugin-path %swift-plugin-dir -I %t/Inputs -enable-experimental-feature SafeInteropWrappers -print-module -module-to-print=Method -source-filename=x | %FileCheck %s
66
// RUN: %target-swift-frontend -plugin-path %swift-plugin-dir -I %t/Inputs -enable-experimental-feature SafeInteropWrappers %t/method.swift -dump-macro-expansions -typecheck -verify
77

8-
// REQUIRES: objc_interop
9-
108
// CHECK: class Foo {
119
// CHECK: func bar(_ p: UnsafeMutableBufferPointer<Float>)
1210

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// REQUIRES: swift_feature_SafeInteropWrappers
2+
3+
// RUN: %target-swift-ide-test -print-module -module-to-print=NoSwiftifyClang -plugin-path %swift-plugin-dir -I %S/Inputs -source-filename=x -enable-experimental-feature SafeInteropWrappers | %FileCheck %s
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/NoSwiftify.swiftmodule -I %S/Inputs -enable-experimental-feature SafeInteropWrappers %s -verify -verify-additional-file %S/Inputs/objc-no-swiftify.h
7+
8+
import NoSwiftifyClang
9+
10+
// CHECK-NOT: @_alwaysEmitIntoClient public func callAutoreleaseParam
11+
// CHECK-NOT: @_alwaysEmitIntoClient public func callAutoreleaseReturn
12+
13+
public func callAutoreleaseParam(_ p: UnsafeMutableBufferPointer<SomeClass>) {
14+
// expected-error@+2{{missing argument for parameter #2 in call}}
15+
// expected-error@+1{{cannot convert value of type 'UnsafeMutableBufferPointer<SomeClass>' to expected argument type 'AutoreleasingUnsafeMutablePointer<SomeClass?>'}}
16+
autoreleaseParam(p)
17+
}
18+
19+
public func callAutoreleaseReturn() {
20+
// expected-error@+1{{cannot convert value of type 'AutoreleasingUnsafeMutablePointer<SomeClass?>?' to specified type 'UnsafeMutableBufferPointer<SomeClass>'}}
21+
let p: UnsafeMutableBufferPointer<SomeClass> = autoreleaseReturn(10)
22+
}

0 commit comments

Comments
 (0)