From c9a62660f3cadae451282153d7eedc1ce95b9f6d Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 20 Oct 2025 16:12:16 -0700 Subject: [PATCH 1/3] [ClangImporter] add implicit import of `Swift` for `__ObjC` module Any safe wrapper expansion originating in a bridging header would fail typechecking because the `__ObjC` module doesn't import the standard implicit imports. This is because the main module is not available to inherit implicit imports from when the `__ObjC` module is created. We don't need all of the implicit modules for safe wrappers, so import `Swift` specifically. rdar://163078116 --- lib/ClangImporter/ClangImporter.cpp | 18 +++++++- .../C/swiftify-import/bridging-header.swift | 43 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/Interop/C/swiftify-import/bridging-header.swift diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index c4d62b0580ef1..3eb1d783e70fd 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1565,9 +1565,25 @@ std::unique_ptr ClangImporter::create( importer->Impl.setObjectForKeyedSubscript = clangContext.Selectors.getSelector(2, setObjectForKeyedSubscriptIdents); + ImplicitImportInfo implicitImportInfo; + // Can't inherit implicit modules from main module, because it isn't loaded yet. + // Add the Swift module, because it is important for safe interop wrappers. + if (auto stdlib = importer->Impl.getStdlibModule()) + implicitImportInfo.AdditionalImports.emplace_back(ImportedModule(stdlib)); + else { + Identifier stdlibName = importer->Impl.SwiftContext.getIdentifier(STDLIB_NAME); + ImportPath::Raw path = + importer->Impl.SwiftContext.AllocateCopy>( + Located(stdlibName, SourceLoc())); + implicitImportInfo.AdditionalUnloadedImports.emplace_back( + UnloadedImportedModule( + ImportPath(path), + ImportKind::Module)); + } + // Set up the imported header module. auto *importedHeaderModule = ModuleDecl::create( - ctx.getIdentifier(CLANG_HEADER_MODULE_NAME), ctx, + ctx.getIdentifier(CLANG_HEADER_MODULE_NAME), ctx, implicitImportInfo, [&](ModuleDecl *importedHeaderModule, auto addFile) { importer->Impl.ImportedHeaderUnit = new (ctx) ClangModuleUnit(*importedHeaderModule, importer->Impl, nullptr); diff --git a/test/Interop/C/swiftify-import/bridging-header.swift b/test/Interop/C/swiftify-import/bridging-header.swift new file mode 100644 index 0000000000000..e9aa1f7042828 --- /dev/null +++ b/test/Interop/C/swiftify-import/bridging-header.swift @@ -0,0 +1,43 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -typecheck -plugin-path %swift-plugin-dir -o %t/test.swiftmodule -I %t -import-objc-header %t/bridging.h -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -warnings-as-errors -Xcc -Werror -Xcc -Wno-nullability-completeness -Xcc -Wno-div-by-zero -Xcc -Wno-pointer-to-int-cast %t/test.swift -verify +// RUN: %target-swift-frontend -typecheck -plugin-path %swift-plugin-dir -o %t/test.swiftmodule -I %t -import-objc-header %t/bridging.h -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -warnings-as-errors -Xcc -Werror -Xcc -Wno-nullability-completeness -Xcc -Wno-div-by-zero -Xcc -Wno-pointer-to-int-cast %t/test.swift -dump-macro-expansions 2>&1 | %FileCheck --dry-run > %t/macro-expansions.out +// RUN: %diff %t/macro-expansions.out %t/macro-expansions.expected +// RUN: %target-swift-frontend -typecheck -plugin-path %swift-plugin-dir -o %t/test.swiftmodule -I %t -import-objc-header %t/bridging.h -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -warnings-as-errors -Xcc -Werror -Xcc -Wno-nullability-completeness -Xcc -Wno-div-by-zero -Xcc -Wno-pointer-to-int-cast %t/test.swift -dump-source-file-imports 2>&1 | %FileCheck --dry-run > %t/imports.out +// RUN: %diff %t/imports.out %t/imports.expected + +//--- imports.expected +imports for TMP_DIR/test.swift: + Swift + __ObjC + _StringProcessing + _SwiftConcurrencyShims + _Concurrency +imports for __ObjC.foo: +imports for @__swiftmacro_So3foo15_SwiftifyImportfMp_.swift: + __ObjC + Swift + +//--- macro-expansions.expected +@__swiftmacro_So3foo15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_disfavoredOverload public func foo(_ p: Span) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeBufferPointer { _pPtr in + return unsafe foo(len, _pPtr.baseAddress!) + } +} +------------------------------ + +//--- test.swift +func test(s: Span) { + foo(s) +} + +//--- bridging.h +#include +#include + +void foo(int len, const int * __counted_by(len) p __noescape); From 507846cb384ad4750efeabe309089f89bc8c22f9 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Tue, 21 Oct 2025 13:48:31 -0700 Subject: [PATCH 2/3] don't try to load stdlib when it's known to fail This prevents it from being loaded correctly later. --- lib/ClangImporter/ClangImporter.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 3eb1d783e70fd..bf89d341f80ac 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1565,21 +1565,16 @@ std::unique_ptr ClangImporter::create( importer->Impl.setObjectForKeyedSubscript = clangContext.Selectors.getSelector(2, setObjectForKeyedSubscriptIdents); - ImplicitImportInfo implicitImportInfo; // Can't inherit implicit modules from main module, because it isn't loaded yet. // Add the Swift module, because it is important for safe interop wrappers. - if (auto stdlib = importer->Impl.getStdlibModule()) - implicitImportInfo.AdditionalImports.emplace_back(ImportedModule(stdlib)); - else { - Identifier stdlibName = importer->Impl.SwiftContext.getIdentifier(STDLIB_NAME); - ImportPath::Raw path = - importer->Impl.SwiftContext.AllocateCopy>( - Located(stdlibName, SourceLoc())); - implicitImportInfo.AdditionalUnloadedImports.emplace_back( - UnloadedImportedModule( - ImportPath(path), - ImportKind::Module)); - } + Identifier stdlibName = + importer->Impl.SwiftContext.getIdentifier(STDLIB_NAME); + ImportPath::Raw path = + importer->Impl.SwiftContext.AllocateCopy>( + Located(stdlibName, SourceLoc())); + ImplicitImportInfo implicitImportInfo; + implicitImportInfo.AdditionalUnloadedImports.emplace_back( + UnloadedImportedModule(ImportPath(path), ImportKind::Module)); // Set up the imported header module. auto *importedHeaderModule = ModuleDecl::create( From 314d3d520bc239e31cef5cbf6ef621f6964fcb2b Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Tue, 21 Oct 2025 13:50:06 -0700 Subject: [PATCH 3/3] add required feature --- test/Interop/C/swiftify-import/bridging-header.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Interop/C/swiftify-import/bridging-header.swift b/test/Interop/C/swiftify-import/bridging-header.swift index e9aa1f7042828..4124fbb12b52c 100644 --- a/test/Interop/C/swiftify-import/bridging-header.swift +++ b/test/Interop/C/swiftify-import/bridging-header.swift @@ -1,3 +1,5 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + // RUN: %empty-directory(%t) // RUN: split-file %s %t