From fe632e530f5d1ba39280f0e58d3f44711bca615b Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 25 Apr 2025 16:51:42 -0700 Subject: [PATCH] Modify clang declaration weakly-imported query to use Swift's code-gen target triple Similarly to how https://github.com/swiftlang/swift/pull/70564 configures 'ClangImporter's 'CodeGenerator' using Swift's compilation target triple, we must use the versioned version of the 'isWeakImported' query to determine linkage for imported Clang symbols. --- lib/AST/Decl.cpp | 7 ++- lib/ClangImporter/ClangImporter.cpp | 11 +++- lib/SIL/IR/SILFunction.cpp | 3 +- test/SILGen/clang-target-weak-import.swift | 70 ++++++++++++++++++++++ 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 test/SILGen/clang-target-weak-import.swift diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index db0e2e516478f..62832eccd1f7d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -75,6 +75,7 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/Module.h" +#include "clang/Basic/TargetInfo.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" @@ -1468,9 +1469,9 @@ AvailabilityRange Decl::getAvailabilityForLinkage() const { bool Decl::isAlwaysWeakImported() const { // For a Clang declaration, trust Clang. - if (auto clangDecl = getClangDecl()) { - return clangDecl->isWeakImported(); - } + if (auto clangDecl = getClangDecl()) + return clangDecl->isWeakImported( + getASTContext().LangOpts.getMinPlatformVersion()); if (getAttrs().hasAttribute()) return true; diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 564dfbbdbf1fb..3d339ecde7c20 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -66,6 +66,7 @@ #include "clang/Basic/FileEntry.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangStandard.h" +#include "clang/Basic/MacroBuilder.h" #include "clang/Basic/Module.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" @@ -1464,8 +1465,14 @@ ClangImporter::create(ASTContext &ctx, importer.get(), importerOpts, VFS, *swiftTargetClangArgs); if (!swiftTargetClangInvocation) return nullptr; - importer->Impl.setSwiftTargetInfo(clang::TargetInfo::CreateTargetInfo( - clangDiags, swiftTargetClangInvocation->TargetOpts)); + auto targetInfo = clang::TargetInfo::CreateTargetInfo( + clangDiags, swiftTargetClangInvocation->TargetOpts); + // Ensure the target info has configured target-specific defines + std::string defineBuffer; + llvm::raw_string_ostream predefines(defineBuffer); + clang::MacroBuilder builder(predefines); + targetInfo->getTargetDefines(instance.getLangOpts(), builder); + importer->Impl.setSwiftTargetInfo(targetInfo); importer->Impl.setSwiftCodeGenOptions(new clang::CodeGenOptions( swiftTargetClangInvocation->getCodeGenOpts())); } else { diff --git a/lib/SIL/IR/SILFunction.cpp b/lib/SIL/IR/SILFunction.cpp index 57cb2f36a118c..958dad4efeba3 100644 --- a/lib/SIL/IR/SILFunction.cpp +++ b/lib/SIL/IR/SILFunction.cpp @@ -618,7 +618,8 @@ bool SILFunction::isWeakImported(ModuleDecl *module) const { // For imported functions check the Clang declaration. if (ClangNodeOwner) - return ClangNodeOwner->getClangDecl()->isWeakImported(); + return ClangNodeOwner->getClangDecl()->isWeakImported( + getASTContext().LangOpts.getMinPlatformVersion()); // For native functions check a flag on the SILFunction // itself. diff --git a/test/SILGen/clang-target-weak-import.swift b/test/SILGen/clang-target-weak-import.swift new file mode 100644 index 0000000000000..c50ef9cf770d0 --- /dev/null +++ b/test/SILGen/clang-target-weak-import.swift @@ -0,0 +1,70 @@ +// REQUIRES: objc_interop +// REQUIRES: OS=macosx +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/module-cache) +// RUN: %empty-directory(%t/inputs) +// RUN: %empty-directory(%t/cheaders) + +// RUN: split-file %s %t +// RUN: sed -e "s|INPUTSDIR|%/t/inputs|g" %t/map.json.template > %t/map.json.template1 +// RUN: sed -e "s|STDLIBMOD|%/stdlib_module|g" %t/map.json.template1 > %t/map.json.template2 +// RUN: sed -e "s|ONONEMOD|%/ononesupport_module|g" %t/map.json.template2 > %t/map.json.template3 +// RUN: sed -e "s|CHEADERSDIR|%t/cheaders|g" %t/map.json.template3 > %t/map.json.template4 +// RUN: sed -e "s|SWIFTLIBDIR|%swift-lib-dir|g" %t/map.json.template4 > %t/map.json + +// RUN: %target-swift-emit-pcm -module-name Bar -o %t/inputs/Bar.pcm %t/cheaders/module.modulemap -target %target-cpu-apple-macosx15.0 +// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift-lib-dir/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm -target %target-cpu-apple-macosx15.0 + +// RUN: %target-swift-frontend -c -disable-implicit-swift-modules -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -module-cache-path %t/module-cache -explicit-swift-module-map-file %t/map.json -primary-file %t/test.swift -o %t/test.o -target %target-cpu-apple-macosx14.0 -clang-target %target-cpu-apple-macosx15.0 + +// RUN: %llvm-nm -m %t/test.o | %FileCheck %s +// CHECK: (undefined) weak external _funcBar +// CHECK: (undefined) external _funcBarButOlder + +//--- map.json.template +[ + { + "moduleName": "Bar", + "clangModulePath": "INPUTSDIR/Bar.pcm", + "clangModuleMapPath": "CHEADERSDIR/module.modulemap" + }, + { + "moduleName": "Swift", + "modulePath": "STDLIBMOD", + "isFramework": false + }, + { + "moduleName": "SwiftOnoneSupport", + "modulePath": "ONONEMOD", + "isFramework": false + }, + { + "moduleName": "SwiftShims", + "isFramework": false, + "clangModuleMapPath": "SWIFTLIBDIR/swift/shims/module.modulemap", + "clangModulePath": "INPUTSDIR/SwiftShims.pcm" +}] + +//--- cheaders/module.modulemap +module Bar { + header "Bar.h" + export * +} + +//--- cheaders/Bar.h +#pragma clang attribute push (__attribute__((availability(macOS, introduced=15.0))), apply_to=function) +extern int funcBar(void); +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((availability(macOS, introduced=14.0))), apply_to=function) +extern int funcBarButOlder(void); +#pragma clang attribute pop + +//--- test.swift +import Bar +public func foo() { + let _ = funcBarButOlder() + if #available(macOS 15.0, *), funcBar() != 0 { + print("Hello, World!") + } +}