From ec0ab18d70156882fcb4eb96e82c7ea8facb6dd1 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Wed, 2 Jul 2025 15:50:27 -0700 Subject: [PATCH] [Dependency Scanning][C++ Interop] Do not skip lookup of 'CxxStdlib' overlay for the source module A prior change ensured that we forego this query when looking up Swift overlays for a textual interface which was built without C++ interop. This change introduced a bug where it also caused us to skip this lookup for the main source module. This commit resolves that by preserving the fix above but also ensuring we perform the lookup for the main source module under scan. --- .../ModuleDependencyScanner.cpp | 60 +++++++++---------- .../cxx-overlay-source-lookup.swift | 41 +++++++++++++ 2 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 test/ScanDependencies/cxx-overlay-source-lookup.swift diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 5f773c58eaca6..f926119c19141 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -1541,41 +1541,41 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule( recordResult(clangDep); // C++ Interop requires additional handling - if (ScanCompilerInvocation.getLangOptions().EnableCXXInterop && - moduleID.Kind == ModuleDependencyKind::SwiftInterface) { + bool lookupCxxStdLibOverlay = ScanCompilerInvocation.getLangOptions().EnableCXXInterop; + if (lookupCxxStdLibOverlay && moduleID.Kind == ModuleDependencyKind::SwiftInterface) { const auto &moduleInfo = cache.findKnownDependency(moduleID); const auto commandLine = moduleInfo.getCommandline(); - // If the textual interface was built without C++ interop, do not query // the C++ Standard Library Swift overlay for its compilation. // - // FIXME: We always declare the 'Darwin' module as formally having been - // built without C++Interop, for compatibility with prior versions. Once we - // are certain that we are only building against modules built with support - // of - // '-formal-cxx-interoperability-mode', this hard-coded check should be - // removed. - if (moduleID.ModuleName != "Darwin" && - llvm::find(commandLine, "-formal-cxx-interoperability-mode=off") == - commandLine.end()) { - for (const auto &clangDepName : allClangDependencies) { - // If this Clang module is a part of the C++ stdlib, and we haven't - // loaded the overlay for it so far, it is a split libc++ module (e.g. - // std_vector). Load the CxxStdlib overlay explicitly. - const auto &clangDepInfo = - cache.findDependency(clangDepName, ModuleDependencyKind::Clang) - .value() - ->getAsClangModule(); - if (importer::isCxxStdModule(clangDepName, clangDepInfo->IsSystem) && - !swiftOverlayDependencies.contains( - {clangDepName, ModuleDependencyKind::SwiftInterface}) && - !swiftOverlayDependencies.contains( - {clangDepName, ModuleDependencyKind::SwiftBinary})) { - scanForSwiftDependency( - getModuleImportIdentifier(ScanASTContext.Id_CxxStdlib.str())); - recordResult(ScanASTContext.Id_CxxStdlib.str().str()); - break; - } + // FIXME: We always declare the 'Darwin' module as formally having been built + // without C++Interop, for compatibility with prior versions. Once we are certain + // that we are only building against modules built with support of + // '-formal-cxx-interoperability-mode', this hard-coded check should be removed. + if (moduleID.ModuleName == "Darwin" || + llvm::find(commandLine, "-formal-cxx-interoperability-mode=off") != + commandLine.end()) + lookupCxxStdLibOverlay = false; + } + + if (lookupCxxStdLibOverlay) { + for (const auto &clangDepName : allClangDependencies) { + // If this Clang module is a part of the C++ stdlib, and we haven't + // loaded the overlay for it so far, it is a split libc++ module (e.g. + // std_vector). Load the CxxStdlib overlay explicitly. + const auto &clangDepInfo = + cache.findDependency(clangDepName, ModuleDependencyKind::Clang) + .value() + ->getAsClangModule(); + if (importer::isCxxStdModule(clangDepName, clangDepInfo->IsSystem) && + !swiftOverlayDependencies.contains( + {clangDepName, ModuleDependencyKind::SwiftInterface}) && + !swiftOverlayDependencies.contains( + {clangDepName, ModuleDependencyKind::SwiftBinary})) { + scanForSwiftDependency( + getModuleImportIdentifier(ScanASTContext.Id_CxxStdlib.str())); + recordResult(ScanASTContext.Id_CxxStdlib.str().str()); + break; } } } diff --git a/test/ScanDependencies/cxx-overlay-source-lookup.swift b/test/ScanDependencies/cxx-overlay-source-lookup.swift new file mode 100644 index 0000000000000..bcc978d3931e3 --- /dev/null +++ b/test/ScanDependencies/cxx-overlay-source-lookup.swift @@ -0,0 +1,41 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/deps) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -scan-dependencies -o %t/deps.json %t/client.swift -I %t/deps -cxx-interoperability-mode=default -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import +// RUN: cat %t/deps.json | %FileCheck %s + +/// --------Main module +// CHECK-LABEL: "modulePath": "deps.swiftmodule", +// CHECK-NEXT: "sourceFiles": [ +// CHECK-NEXT: cxx-overlay-source-lookup.swift +// CHECK-NEXT: ], +// CHECK: "directDependencies": [ +// CHECK-DAG: "swift": "Swift" +// CHECK-DAG: "swift": "SwiftOnoneSupport" +// CHECK-DAG: "swift": "Cxx" +// CHECK-DAG: "swift": "CxxStdlib" +// CHECK-DAG: "clang": "CxxShim" +// CHECK-DAG: "clang": "Foo" +// CHECK: ], + +//--- deps/bar.h +void bar(void); + +//--- deps/foo.h +#include "bar.h" +void foo(void); + +//--- deps/module.modulemap +module std_Bar [system] { + header "bar.h" + export * +} + +module Foo { + header "foo.h" + export * +} + +//--- client.swift +import Foo