From 38827c837e0773fa7c95049c2c44638c9f00bdfd Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 15 Dec 2025 14:37:07 -0800 Subject: [PATCH] [Swiftify] don't swiftify functions with sugared parameter lists These cases would trigger an assert in both release and debug builds. With this change they are ignored in release mode, and cases that are both unhandled and unknown trigger an assert in debug mode. rdar://166074719 --- lib/ClangImporter/SwiftifyDecl.cpp | 28 ++++++++++++++----- .../C/swiftify-import/Inputs/counted-by.h | 2 ++ .../counted-by-no-swiftify.swift | 1 + .../swiftify-import/Inputs/objc-no-swiftify.h | 11 ++++++++ .../swiftify-import/objc-no-swiftify.swift | 15 ++++++++-- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/lib/ClangImporter/SwiftifyDecl.cpp b/lib/ClangImporter/SwiftifyDecl.cpp index 9a7770117092f..6d5b40bb655ce 100644 --- a/lib/ClangImporter/SwiftifyDecl.cpp +++ b/lib/ClangImporter/SwiftifyDecl.cpp @@ -414,13 +414,24 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self, } bool isClangInstanceMethod = - isa(ClangDecl) && - !isa(ClangDecl) && - cast(ClangDecl)->isInstance(); - size_t swiftNumParams = MappedDecl->getParameters()->size() - - (ClangDecl->isVariadic() ? 1 : 0); - ASSERT((MappedDecl->isImportAsInstanceMember() == isClangInstanceMethod) == - (getNumParams(ClangDecl) == swiftNumParams)); + (isa(ClangDecl) && + !isa(ClangDecl) && + cast(ClangDecl)->isInstance()) || + (isa(ClangDecl) && + cast(ClangDecl)->isInstanceMethod()); + + size_t swiftNumParams = MappedDecl->getParameters()->size(); + if (MappedDecl->isInstanceMember() && !isClangInstanceMethod) { + ASSERT(MappedDecl->isImportAsInstanceMember()); + swiftNumParams += 1; + } + if (getNumParams(ClangDecl) != swiftNumParams) { + DLOG("mismatching parameter lists"); + assert(ClangDecl->isVariadic() || + MappedDecl->getForeignErrorConvention().has_value() || + MappedDecl->getForeignAsyncConvention().has_value()); + return false; + } size_t selfParamIndex = MappedDecl->isImportAsInstanceMember() ? MappedDecl->getSelfIndex() @@ -531,6 +542,9 @@ class SwiftifyProtocolInfoPrinter : public SwiftifyInfoPrinter { void printMethodSignature(const FuncDecl *Method) { auto options = PrintOptions::printForDiagnostics(AccessLevel::Private, true); + for (const auto *attr : Method->getAttrs()) { + options.ExcludeAttrList.push_back(attr->getKind()); + } StreamPrinter printer(out); Method->print(printer, options); } diff --git a/test/Interop/C/swiftify-import/Inputs/counted-by.h b/test/Interop/C/swiftify-import/Inputs/counted-by.h index 2b855eeffc430..5fde5abf2d285 100644 --- a/test/Interop/C/swiftify-import/Inputs/counted-by.h +++ b/test/Interop/C/swiftify-import/Inputs/counted-by.h @@ -62,3 +62,5 @@ void hexLiteral(int * __counted_by(0xfa) p); void binaryLiteral(int * __counted_by(0b10) p); void octalLiteral(int * __counted_by(0777) p); + +void variadic(int len, int * __counted_by(len) p, ...); diff --git a/test/Interop/C/swiftify-import/counted-by-no-swiftify.swift b/test/Interop/C/swiftify-import/counted-by-no-swiftify.swift index ff565150f4126..7948eeb80f6a5 100644 --- a/test/Interop/C/swiftify-import/counted-by-no-swiftify.swift +++ b/test/Interop/C/swiftify-import/counted-by-no-swiftify.swift @@ -16,3 +16,4 @@ // CHECK-NOT: @_alwaysEmitIntoClient {{.*}} longLiteral // CHECK-NOT: @_alwaysEmitIntoClient {{.*}} sizeofType // CHECK-NOT: @_alwaysEmitIntoClient {{.*}} sizeofParam +// CHECK-NOT: @_alwaysEmitIntoClient {{.*}} variadic diff --git a/test/Interop/ObjC/swiftify-import/Inputs/objc-no-swiftify.h b/test/Interop/ObjC/swiftify-import/Inputs/objc-no-swiftify.h index 4b01f0e94f4f7..0ee95be5d6312 100644 --- a/test/Interop/ObjC/swiftify-import/Inputs/objc-no-swiftify.h +++ b/test/Interop/ObjC/swiftify-import/Inputs/objc-no-swiftify.h @@ -7,3 +7,14 @@ void autoreleaseParam(SomeClass * __autoreleasing * __counted_by(len) p, int len); // expected-note{{declared here}} SomeClass * __autoreleasing * __counted_by(len) autoreleaseReturn(int len); + +@interface NSError +@end + +@interface NSData +@end + +@protocol Foo +- (void)errorAsTry:(int) len : (int * __counted_by(len)) p error:(NSError * *) error; +- (void)completionHandlerAsAsync:(int) len : (int * __counted_by(len)) p completionHandler:(void (^)(NSData * data, NSError *)) completionHandler; +@end diff --git a/test/Interop/ObjC/swiftify-import/objc-no-swiftify.swift b/test/Interop/ObjC/swiftify-import/objc-no-swiftify.swift index 5c918bc4bec5c..4563154e203ed 100644 --- a/test/Interop/ObjC/swiftify-import/objc-no-swiftify.swift +++ b/test/Interop/ObjC/swiftify-import/objc-no-swiftify.swift @@ -7,8 +7,7 @@ import NoSwiftifyClang -// CHECK-NOT: @_alwaysEmitIntoClient @_disfavoredOverload public func callAutoreleaseParam -// CHECK-NOT: @_alwaysEmitIntoClient @_disfavoredOverload public func callAutoreleaseReturn +// CHECK-NOT: @_alwaysEmitIntoClient @_disfavoredOverload public func callAutoreleaseParam(_ p: UnsafeMutableBufferPointer) { // expected-error@+2{{missing argument for parameter #2 in call}} @@ -19,4 +18,14 @@ public func callAutoreleaseParam(_ p: UnsafeMutableBufferPointer) { public func callAutoreleaseReturn() { // expected-error@+1{{cannot convert value of type 'AutoreleasingUnsafeMutablePointer?' to specified type 'UnsafeMutableBufferPointer'}} let p: UnsafeMutableBufferPointer = autoreleaseReturn(10) -} \ No newline at end of file +} + +public func callErrorAsTry(_ x: Foo, _ p: UnsafeMutablePointer, _ error: AutoreleasingUnsafeMutablePointer) { + x.error(asTry: 10, p, error: error) +} + +public func callCompletionHandlerAsAsync(_ x: Foo, _ p: UnsafeMutablePointer) { + x.completionHandler(asAsync: 10, p, completionHandler: { (a: NSData?, b: NSError?) in + print("asdf") + }) +}