Skip to content

Commit e1eb960

Browse files
authored
[Swiftify] Don't create safe wrapper for autoreleasing pointers (#81568)
_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 1823d44 commit e1eb960

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
@@ -9192,6 +9192,14 @@ static bool SwiftifiableCAT(const clang::CountAttributedType *CAT) {
91929192
return CAT && CountedByExpressionValidator().Visit(CAT->getCountExpr());
91939193
}
91949194

9195+
static bool SwiftifiablePointerType(Type swiftType) {
9196+
// don't try to transform any Swift types that _SwiftifyImport doesn't know how to handle
9197+
Type nonnullType = swiftType->lookThroughSingleOptionalType();
9198+
PointerTypeKind PTK;
9199+
return nonnullType->isOpaquePointer() ||
9200+
(nonnullType->getAnyPointerElementType(PTK) && PTK != PTK_AutoreleasingUnsafeMutablePointer);
9201+
}
9202+
91959203
void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
91969204
if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers))
91979205
return;
@@ -9225,10 +9233,11 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
92259233
return false;
92269234
};
92279235
SwiftifyInfoPrinter printer(getClangASTContext(), SwiftContext, out);
9236+
Type swiftReturnTy = MappedDecl->getResultInterfaceType();
92289237
bool returnIsStdSpan = registerStdSpanTypeMapping(
9229-
MappedDecl->getResultInterfaceType(), ClangDecl->getReturnType());
9238+
swiftReturnTy, ClangDecl->getReturnType());
92309239
auto *CAT = ClangDecl->getReturnType()->getAs<clang::CountAttributedType>();
9231-
if (SwiftifiableCAT(CAT)) {
9240+
if (SwiftifiableCAT(CAT) && SwiftifiablePointerType(swiftReturnTy)) {
92329241
printer.printCountedBy(CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX);
92339242
attachMacro = true;
92349243
}
@@ -9242,14 +9251,15 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
92429251
for (auto [index, clangParam] : llvm::enumerate(ClangDecl->parameters())) {
92439252
auto clangParamTy = clangParam->getType();
92449253
auto swiftParam = MappedDecl->getParameters()->get(index);
9254+
Type swiftParamTy = swiftParam->getInterfaceType();
92459255
bool paramHasBoundsInfo = false;
92469256
auto *CAT = clangParamTy->getAs<clang::CountAttributedType>();
9247-
if (SwiftifiableCAT(CAT)) {
9257+
if (SwiftifiableCAT(CAT) && SwiftifiablePointerType(swiftParamTy)) {
92489258
printer.printCountedBy(CAT, index);
92499259
attachMacro = paramHasBoundsInfo = true;
92509260
}
92519261
bool paramIsStdSpan = registerStdSpanTypeMapping(
9252-
swiftParam->getInterfaceType(), clangParamTy);
9262+
swiftParamTy, clangParamTy);
92539263
paramHasBoundsInfo |= paramIsStdSpan;
92549264

92559265
bool paramHasLifetimeInfo = false;
@@ -9260,7 +9270,7 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
92609270
if (clangParam->hasAttr<clang::LifetimeBoundAttr>()) {
92619271
printer.printLifetimeboundReturn(
92629272
index, !paramHasBoundsInfo &&
9263-
swiftParam->getInterfaceType()->isEscapable());
9273+
swiftParamTy->isEscapable());
92649274
paramHasLifetimeInfo = true;
92659275
returnHasLifetimeInfo = true;
92669276
}

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)