From 35d8d1a024512d27cf16e39878ed87e86c4203a4 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 16 Dec 2025 21:03:53 -0800 Subject: [PATCH] [DependencyScan] Correct setup clang VFS for dependency scanning Currently, dependency scanner is not reporting the redirecting files that are baked inside swift-frontend for platform support. This causes dependency scanner returns virtual path for those files, and swift-driver/build-system will not be able to correct validate the files on incremental build, causing incremental build to be almost clean builds. This behavior issue is caused by the dependency scanning file system layer inside clang dependency scanner that caches stats. If the redirecting files are created underneath the layer, the real path is lost. This fixes the issue by moving the redirecting files above the caching layer using `-ivfsoverlay` option. In addition to that, this commit also unifies how clang importer and clang dependency scanner initiate the VFS, making the logic much simpler. --- include/swift/ClangImporter/ClangImporter.h | 67 ++++------ lib/ClangImporter/ClangImporter.cpp | 122 +++++++++++++++--- lib/ClangImporter/ClangIncludePaths.cpp | 104 ++++----------- lib/ClangImporter/ImporterImpl.h | 12 +- .../ModuleDependencyScanner.cpp | 23 ++-- lib/Frontend/Frontend.cpp | 25 +--- .../print-module-map-paths.swift | 8 +- 7 files changed, 188 insertions(+), 173 deletions(-) diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 81da1291ff293..8eeaa0303e3a7 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -148,6 +148,17 @@ typedef llvm::PointerUnion ImportDiagnosticTarget; +/// Addition file mapping information for ClangImporter. +struct ClangInvocationFileMapping { + /// Mapping from a file name to an existing file path. + SmallVector, 2> redirectedFiles; + + /// MemoryBuffer that represents the file name and content to overload. + SmallVector, 2> overridenFiles; + + bool requiresBuiltinHeadersInSystemModules = false; +}; + /// Class that imports Clang modules into Swift, mapping directly /// from Clang ASTs over to Swift ASTs. class ClangImporter final : public ClangModuleLoader { @@ -166,7 +177,7 @@ class ClangImporter final : public ClangModuleLoader { private: Implementation &Impl; - bool requiresBuiltinHeadersInSystemModules = false; + ClangInvocationFileMapping clangFileMapping; ClangImporter(ASTContext &ctx, DependencyTracker *tracker, DWARFImporterDelegate *dwarfImporterDelegate); @@ -205,6 +216,14 @@ class ClangImporter final : public ClangModuleLoader { DWARFImporterDelegate *dwarfImporterDelegate = nullptr, bool ignoreFileMapping = false); + static std::string getClangSystemOverlayFile(const SearchPathOptions &Opts); + + static llvm::IntrusiveRefCntPtr + computeClangImporterFileSystem( + const ASTContext &ctx, const ClangInvocationFileMapping &fileMapping, + llvm::IntrusiveRefCntPtr baseFS, + bool suppressDiagnostics = false); + std::vector getClangDriverArguments(ASTContext &ctx, bool ignoreClangTarget = false); @@ -531,6 +550,11 @@ class ClangImporter final : public ClangModuleLoader { std::string getClangModuleHash() const; + /// Get clang file mapping. + const ClangInvocationFileMapping &getClangFileMapping() const { + return clangFileMapping; + } + /// Get clang import creation cc1 args for swift explicit module build. std::vector getSwiftExplicitModuleDirectCC1Args() const; @@ -883,36 +907,6 @@ std::optional getCxxRefConventionWithAttrs(const clang::Decl *decl); } // namespace importer -struct ClangInvocationFileMapping { - /// Mapping from a file name to an existing file path. - SmallVector, 2> redirectedFiles; - - /// Mapping from a file name to a string of characters that represents the - /// contents of the file. - SmallVector, 1> overridenFiles; - - bool requiresBuiltinHeadersInSystemModules; -}; - -class ClangInvocationFileMappingContext { -public: - const LangOptions &LangOpts; - SearchPathOptions &SearchPathOpts; - ClangImporterOptions &ClangImporterOpts; - const CASOptions &CASOpts; - DiagnosticEngine &Diags; - - ClangInvocationFileMappingContext( - const LangOptions &LangOpts, SearchPathOptions &SearchPathOpts, - ClangImporterOptions &ClangImporterOpts, const CASOptions &CASOpts, - DiagnosticEngine &Diags) - : LangOpts(LangOpts), SearchPathOpts(SearchPathOpts), - ClangImporterOpts(ClangImporterOpts), CASOpts(CASOpts), - Diags(Diags) {} - - ClangInvocationFileMappingContext(const swift::ASTContext &Ctx); -}; - /// On Linux, some platform libraries (glibc, libstdc++) are not modularized. /// We inject modulemaps for those libraries into their include directories /// to allow using them from Swift. @@ -920,19 +914,10 @@ class ClangInvocationFileMappingContext { /// `suppressDiagnostic` prevents us from emitting warning messages when we /// are unable to find headers. ClangInvocationFileMapping getClangInvocationFileMapping( - const ClangInvocationFileMappingContext &ctx, + const ASTContext &ctx, llvm::IntrusiveRefCntPtr vfs = nullptr, bool suppressDiagnostic = false); -/// Apply the given file mapping to the specified 'fileSystem', used -/// primarily to inject modulemaps on platforms with non-modularized -/// platform libraries. -ClangInvocationFileMapping applyClangInvocationMapping( - const ClangInvocationFileMappingContext &ctx, - llvm::IntrusiveRefCntPtr baseVFS, - llvm::IntrusiveRefCntPtr &fileSystem, - bool suppressDiagnostics = false); - /// Information used to compute the access level of inherited C++ members. class ClangInheritanceInfo { /// The cumulative inheritance access specifier, that is used to compute the diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index ba291e66c3db9..880e8590ad20c 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -828,10 +828,9 @@ getEmbedBitcodeInvocationArguments(std::vector &invocationArgStrs, }); } -void -importer::addCommonInvocationArguments( - std::vector &invocationArgStrs, - ASTContext &ctx, bool requiresBuiltinHeadersInSystemModules, +void importer::addCommonInvocationArguments( + std::vector &invocationArgStrs, ASTContext &ctx, + bool requiresBuiltinHeadersInSystemModules, bool needSystemVFSOverlay, bool ignoreClangTarget) { using ImporterImpl = ClangImporter::Implementation; llvm::Triple triple = ctx.LangOpts.Target; @@ -1003,6 +1002,12 @@ importer::addCommonInvocationArguments( invocationArgStrs.push_back("-Xclang"); invocationArgStrs.push_back("-fbuiltin-headers-in-system-modules"); } + + if (needSystemVFSOverlay) { + invocationArgStrs.push_back("-ivfsoverlay"); + invocationArgStrs.push_back( + ClangImporter::getClangSystemOverlayFile(ctx.SearchPathOpts)); + } } bool ClangImporter::canReadPCH(StringRef PCHFilename) { @@ -1151,6 +1156,85 @@ ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions, return PCHFilename.value(); } +std::string +ClangImporter::getClangSystemOverlayFile(const SearchPathOptions &Opts) { + llvm::SmallString<256> overlayPath(Opts.RuntimeResourcePath); + llvm::sys::path::append(overlayPath, + Implementation::clangSystemVFSOverlayName); + return overlayPath.str().str(); +} + +llvm::IntrusiveRefCntPtr +ClangImporter::computeClangImporterFileSystem( + const ASTContext &ctx, const ClangInvocationFileMapping &fileMapping, + llvm::IntrusiveRefCntPtr baseFS, + bool suppressDiagnostics) { + // Configure ClangImporter file system. There are two situations: + // * If caching is used, thus file system is immutable, the one immutable file + // system is shared between swift frontend and ClangImporter. + // * Otherwise, ClangImporter file system is configure from scratch from + // VFS in SourceMgr using ivfsoverlay options. + if (ctx.CASOpts.HasImmutableFileSystem) + return baseFS; + + auto importerOpts = ctx.ClangImporterOpts; + auto fileSystem = baseFS; + std::unique_ptr redirectYAMLFile; + if (!fileMapping.redirectedFiles.empty()) { + if (importerOpts.DumpClangDiagnostics) { + llvm::errs() << "clang importer redirected file mappings:\n"; + for (const auto &mapping : fileMapping.redirectedFiles) { + llvm::errs() << " mapping real file '" << mapping.second + << "' to virtual file '" << mapping.first << "'\n"; + } + llvm::errs() << "\n"; + } + // Create a vfs overlay map for all redirects. + llvm::vfs::YAMLVFSWriter vfsWriter; + vfsWriter.setUseExternalNames(true); + for (const auto &mapping : fileMapping.redirectedFiles) + vfsWriter.addFileMapping(mapping.first, mapping.second); + + std::string vfsYAML; + llvm::raw_string_ostream os(vfsYAML); + vfsWriter.write(os); + + redirectYAMLFile = llvm::MemoryBuffer::getMemBufferCopy( + vfsYAML, getClangSystemOverlayFile(ctx.SearchPathOpts)); + } + + if (!fileMapping.overridenFiles.empty() || redirectYAMLFile) { + auto overridenVFS = + llvm::makeIntrusiveRefCnt(); + for (auto &file : fileMapping.overridenFiles) { + if (importerOpts.DumpClangDiagnostics) { + llvm::errs() << "clang importer overriding file '" << file.first + << "' with the following contents:\n"; + llvm::errs() << file.second << "\n"; + } + // Note MemoryBuffer is guaranteeed to be null-terminated. + overridenVFS->addFile(file.first, 0, + llvm::MemoryBuffer::getMemBufferCopy(file.second)); + } + if (redirectYAMLFile) { + if (importerOpts.DumpClangDiagnostics) { + llvm::errs() << "clang importer overriding file for redirects'" + << redirectYAMLFile->getBufferIdentifier() + << "' with the following contents:\n"; + llvm::errs() << redirectYAMLFile->getBuffer() << "\n"; + } + std::string yamlFile = redirectYAMLFile->getBufferIdentifier().str(); + overridenVFS->addFile(yamlFile, 0, std::move(redirectYAMLFile)); + } + auto overlayVFS = + llvm::makeIntrusiveRefCnt(fileSystem); + overlayVFS->pushOverlay(std::move(overridenVFS)); + fileSystem = std::move(overlayVFS); + } + + return fileSystem; +} + std::vector ClangImporter::getClangDriverArguments(ASTContext &ctx, bool ignoreClangTarget) { assert(!ctx.ClangImporterOpts.DirectClangCC1ModuleBuild && @@ -1168,8 +1252,10 @@ ClangImporter::getClangDriverArguments(ASTContext &ctx, bool ignoreClangTarget) getEmbedBitcodeInvocationArguments(invocationArgStrs, ctx); break; } - addCommonInvocationArguments(invocationArgStrs, ctx, - requiresBuiltinHeadersInSystemModules, ignoreClangTarget); + addCommonInvocationArguments( + invocationArgStrs, ctx, + clangFileMapping.requiresBuiltinHeadersInSystemModules, + !clangFileMapping.redirectedFiles.empty(), ignoreClangTarget); return invocationArgStrs; } @@ -1235,6 +1321,10 @@ std::optional> ClangImporter::getClangCC1Arguments( CI->getTargetOpts().DarwinTargetVariantTriple = ctx.LangOpts.TargetVariant->str(); } + if (!clangFileMapping.redirectedFiles.empty()) + CI->getHeaderSearchOpts().AddVFSOverlayFile( + getClangSystemOverlayFile(ctx.SearchPathOpts)); + // Forward the index store path. That information is not passed to scanner // and it is cached invariant so we don't want to re-scan if that changed. CI->getFrontendOpts().IndexStorePath = ctx.ClangImporterOpts.IndexStorePath; @@ -1348,18 +1438,16 @@ std::unique_ptr ClangImporter::create( } } - llvm::IntrusiveRefCntPtr VFS = - ctx.SourceMgr.getFileSystem(); - - ClangInvocationFileMapping fileMapping = - applyClangInvocationMapping(ctx, nullptr, VFS, ignoreFileMapping); - - importer->requiresBuiltinHeadersInSystemModules = - fileMapping.requiresBuiltinHeadersInSystemModules; + importer->clangFileMapping = getClangInvocationFileMapping( + ctx, ctx.SourceMgr.getFileSystem(), ignoreFileMapping); + llvm::IntrusiveRefCntPtr vfs = + computeClangImporterFileSystem(ctx, importer->clangFileMapping, + ctx.SourceMgr.getFileSystem(), + ignoreFileMapping); // Create a new Clang compiler invocation. { - if (auto ClangArgs = importer->getClangCC1Arguments(ctx, VFS)) + if (auto ClangArgs = importer->getClangCC1Arguments(ctx, vfs)) importer->Impl.ClangArgs = *ClangArgs; else return nullptr; @@ -1373,7 +1461,7 @@ std::unique_ptr ClangImporter::create( llvm::errs() << "'\n"; } importer->Impl.Invocation = createClangInvocation( - importer.get(), importerOpts, VFS, importer->Impl.ClangArgs); + importer.get(), importerOpts, vfs, importer->Impl.ClangArgs); if (!importer->Impl.Invocation) return nullptr; } @@ -1424,7 +1512,7 @@ std::unique_ptr ClangImporter::create( auto actualDiagClient = std::make_unique( importer->Impl, instance.getDiagnosticOpts(), importerOpts.DumpClangDiagnostics); - instance.createVirtualFileSystem(std::move(VFS), actualDiagClient.get()); + instance.createVirtualFileSystem(std::move(vfs), actualDiagClient.get()); instance.createFileManager(); instance.createDiagnostics(actualDiagClient.release()); diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 1f25e1d2657a6..810cf76be0105 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -202,8 +202,7 @@ ClangImporter::createClangArgs(const ClangImporterOptions &ClangImporterOpts, } static SmallVector, 2> -getLibcFileMapping(const ClangInvocationFileMappingContext &ctx, - StringRef modulemapFileName, +getLibcFileMapping(const ASTContext &ctx, StringRef modulemapFileName, std::optional> maybeHeaderFileNames, const llvm::IntrusiveRefCntPtr &vfs, bool suppressDiagnostic) { @@ -270,8 +269,7 @@ getLibcFileMapping(const ClangInvocationFileMappingContext &ctx, } static void getLibStdCxxFileMapping( - ClangInvocationFileMapping &fileMapping, - const ClangInvocationFileMappingContext &ctx, + ClangInvocationFileMapping &fileMapping, const ASTContext &ctx, const llvm::IntrusiveRefCntPtr &vfs, bool suppressDiagnostic) { assert(ctx.LangOpts.EnableCXXInterop && @@ -450,26 +448,27 @@ static void getLibStdCxxFileMapping( includeHeaderInModuleMap(additionalFile); os << contents.substr(headerInjectionPoint); - fileMapping.overridenFiles.push_back( - {std::string(injectedModuleMapPath), std::move(os.str())}); + fileMapping.overridenFiles.emplace_back( + std::string(injectedModuleMapPath), + std::move(additionalHeaderDirectives)); } namespace { -std::string -GetPlatformAuxiliaryFile(StringRef Platform, StringRef File, - const SearchPathOptions &Options) { +std::string GetPlatformAuxiliaryFile(StringRef Platform, StringRef File, + llvm::vfs::FileSystem &VFS, + const SearchPathOptions &Options) { StringRef SDKPath = Options.getSDKPath(); if (!SDKPath.empty()) { llvm::SmallString<261> path{SDKPath}; llvm::sys::path::append(path, "usr", "share", File); - if (llvm::sys::fs::exists(path)) + if (VFS.exists(path)) return path.str().str(); } if (!Options.RuntimeResourcePath.empty()) { llvm::SmallString<261> path{Options.RuntimeResourcePath}; llvm::sys::path::append(path, Platform, File); - if (llvm::sys::fs::exists(path)) + if (VFS.exists(path)) return path.str().str(); } @@ -477,8 +476,7 @@ GetPlatformAuxiliaryFile(StringRef Platform, StringRef File, } void GetWindowsFileMappings( - ClangInvocationFileMapping &fileMapping, - const ClangInvocationFileMappingContext &Context, + ClangInvocationFileMapping &fileMapping, const ASTContext &Context, const llvm::IntrusiveRefCntPtr &driverVFS, bool &requiresBuiltinHeadersInSystemModules) { const llvm::Triple &Triple = Context.LangOpts.Target; @@ -514,7 +512,7 @@ void GetWindowsFileMappings( llvm::sys::path::append(WinSDKInjection, "module.modulemap"); AuxiliaryFile = GetPlatformAuxiliaryFile("windows", "winsdk_um.modulemap", - SearchPathOpts); + VFS, SearchPathOpts); if (!AuxiliaryFile.empty()) fileMapping.redirectedFiles.emplace_back(std::string(WinSDKInjection), AuxiliaryFile); @@ -523,7 +521,7 @@ void GetWindowsFileMappings( llvm::sys::path::remove_filename(WinSDKInjection); llvm::sys::path::append(WinSDKInjection, "shared", "module.modulemap"); AuxiliaryFile = GetPlatformAuxiliaryFile( - "windows", "winsdk_shared.modulemap", SearchPathOpts); + "windows", "winsdk_shared.modulemap", VFS, SearchPathOpts); if (!AuxiliaryFile.empty()) fileMapping.redirectedFiles.emplace_back(std::string(WinSDKInjection), AuxiliaryFile); @@ -540,8 +538,8 @@ void GetWindowsFileMappings( llvm::sys::path::append(UCRTInjection, "Include", UCRTSDK.Version, "ucrt"); llvm::sys::path::append(UCRTInjection, "module.modulemap"); - AuxiliaryFile = - GetPlatformAuxiliaryFile("windows", "ucrt.modulemap", SearchPathOpts); + AuxiliaryFile = GetPlatformAuxiliaryFile("windows", "ucrt.modulemap", VFS, + SearchPathOpts); if (!AuxiliaryFile.empty()) { // The ucrt module map has the C standard library headers all together. // That leads to module cycles with the clang _Builtin_ modules. e.g. @@ -578,18 +576,16 @@ void GetWindowsFileMappings( llvm::sys::path::append(VCToolsInjection, "include"); llvm::sys::path::append(VCToolsInjection, "module.modulemap"); - AuxiliaryFile = - GetPlatformAuxiliaryFile("windows", "vcruntime.modulemap", - SearchPathOpts); + AuxiliaryFile = GetPlatformAuxiliaryFile("windows", "vcruntime.modulemap", + VFS, SearchPathOpts); if (!AuxiliaryFile.empty()) fileMapping.redirectedFiles.emplace_back(std::string(VCToolsInjection), AuxiliaryFile); llvm::sys::path::remove_filename(VCToolsInjection); llvm::sys::path::append(VCToolsInjection, "vcruntime.apinotes"); - AuxiliaryFile = - GetPlatformAuxiliaryFile("windows", "vcruntime.apinotes", - SearchPathOpts); + AuxiliaryFile = GetPlatformAuxiliaryFile("windows", "vcruntime.apinotes", + VFS, SearchPathOpts); if (!AuxiliaryFile.empty()) fileMapping.redirectedFiles.emplace_back(std::string(VCToolsInjection), AuxiliaryFile); @@ -610,23 +606,16 @@ void GetWindowsFileMappings( for (const char * const header : kInjectedHeaders) { llvm::sys::path::remove_filename(VCToolsInjection); llvm::sys::path::append(VCToolsInjection, header); - if (!llvm::sys::fs::exists(VCToolsInjection)) - fileMapping.overridenFiles.emplace_back(std::string{VCToolsInjection}, - ""); + if (!VFS.exists(VCToolsInjection)) + fileMapping.overridenFiles.emplace_back(VCToolsInjection, ""); } } } } // namespace -ClangInvocationFileMappingContext::ClangInvocationFileMappingContext( - const swift::ASTContext &Ctx) - : ClangInvocationFileMappingContext(Ctx.LangOpts, Ctx.SearchPathOpts, - Ctx.ClangImporterOpts, Ctx.CASOpts, Ctx.Diags) {} - ClangInvocationFileMapping swift::getClangInvocationFileMapping( - const ClangInvocationFileMappingContext &ctx, - llvm::IntrusiveRefCntPtr vfs, - bool suppressDiagnostic) { + const ASTContext &ctx, llvm::IntrusiveRefCntPtr vfs, + bool suppressDiagnostic) { ClangInvocationFileMapping result; if (!vfs) vfs = llvm::vfs::getRealFileSystem(); @@ -693,51 +682,6 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping( GetWindowsFileMappings(result, ctx, vfs, result.requiresBuiltinHeadersInSystemModules); - return result; -} - -ClangInvocationFileMapping swift::applyClangInvocationMapping( - const ClangInvocationFileMappingContext &ctx, - llvm::IntrusiveRefCntPtr baseVFS, - llvm::IntrusiveRefCntPtr &fileSystem, - bool suppressDiagnostics) { - if (ctx.CASOpts.HasImmutableFileSystem) - return ClangInvocationFileMapping(); - - ClangInvocationFileMapping fileMapping = - getClangInvocationFileMapping(ctx, baseVFS, suppressDiagnostics); - - auto importerOpts = ctx.ClangImporterOpts; - // Wrap Swift's FS to allow Clang to override the working directory - fileSystem = llvm::vfs::RedirectingFileSystem::create( - fileMapping.redirectedFiles, true, *fileSystem); - if (importerOpts.DumpClangDiagnostics) { - llvm::errs() << "clang importer redirected file mappings:\n"; - for (const auto &mapping : fileMapping.redirectedFiles) { - llvm::errs() << " mapping real file '" << mapping.second - << "' to virtual file '" << mapping.first << "'\n"; - } - llvm::errs() << "\n"; - } - if (!fileMapping.overridenFiles.empty()) { - llvm::IntrusiveRefCntPtr overridenVFS = - new llvm::vfs::InMemoryFileSystem(); - for (const auto &file : fileMapping.overridenFiles) { - if (importerOpts.DumpClangDiagnostics) { - llvm::errs() << "clang importer overriding file '" << file.first - << "' with the following contents:\n"; - llvm::errs() << file.second << "\n"; - } - // Note MemoryBuffer is guaranteeed to be null-terminated. - overridenVFS->addFile(file.first, 0, - llvm::MemoryBuffer::getMemBufferCopy(file.second)); - } - llvm::IntrusiveRefCntPtr overlayVFS = - new llvm::vfs::OverlayFileSystem(fileSystem); - fileSystem = overlayVFS; - overlayVFS->pushOverlay(overridenVFS); - } - - return fileMapping; + return result; } diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index ab596c6359299..c1bc5a0b114d6 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -490,10 +490,13 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation const Version CurrentVersion; - constexpr static const char * const moduleImportBufferName = - ""; - constexpr static const char * const bridgingHeaderBufferName = - ""; + constexpr static const char *const moduleImportBufferName = + ""; + constexpr static const char *const bridgingHeaderBufferName = + ""; + /// The name of system vfsoverlay. + constexpr static const char *const clangSystemVFSOverlayName = + ""; private: DiagnosticWalker Walker; @@ -2012,6 +2015,7 @@ void getNormalInvocationArguments(std::vector &invocationArgStrs, void addCommonInvocationArguments(std::vector &invocationArgStrs, ASTContext &ctx, bool requiresBuiltinHeadersInSystemModules, + bool needSystemVFSOverlay, bool ignoreClangTarget); /// Finds a particular kind of nominal by looking through typealiases. diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 6d492ae752e89..f84e82d801535 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -196,14 +196,15 @@ static std::vector inputSpecificClangScannerCommand( static llvm::IntrusiveRefCntPtr getClangScanningFS(std::shared_ptr cas, ASTContext &ctx) { - llvm::IntrusiveRefCntPtr baseFileSystem = - llvm::vfs::createPhysicalFileSystem(); - ClangInvocationFileMapping fileMapping = - applyClangInvocationMapping(ctx, nullptr, baseFileSystem, false); + auto *importer = static_cast(ctx.getClangModuleLoader()); + // Dependency scanner needs to create its own file system per worker. + auto fs = ClangImporter::computeClangImporterFileSystem( + ctx, importer->getClangFileMapping(), + llvm::vfs::createPhysicalFileSystem(), true); if (cas) - return llvm::cas::createCASProvidingFileSystem(cas, baseFileSystem); - return baseFileSystem; + return llvm::cas::createCASProvidingFileSystem(cas, fs); + return fs; } ModuleDependencyScanningWorker::ModuleDependencyScanningWorker( @@ -2038,10 +2039,16 @@ ModuleDependencyInfo ModuleDependencyScanner::bridgeClangModuleDependency( invocation.getMutCASOpts() = clang::CASOptions(); invocation.getMutFrontendOpts().CASIncludeTreeID.clear(); - // FIXME: workaround for rdar://105684525: find the -ivfsoverlay option - // from clang scanner and pass to swift. if (!ScanASTContext.CASOpts.EnableCaching) { auto &overlayFiles = invocation.getMutHeaderSearchOpts().VFSOverlayFiles; + + // clang system overlay file is a virtual file that is not an actual file. + auto clangSystemOverlayFile = + ClangImporter::getClangSystemOverlayFile(ScanASTContext.SearchPathOpts); + llvm::erase(overlayFiles, clangSystemOverlayFile); + + // FIXME: workaround for rdar://105684525: find the -ivfsoverlay option + // from clang scanner and pass to swift. for (auto overlay : overlayFiles) { swiftArgs.push_back("-vfsoverlay"); swiftArgs.push_back(overlay); diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 4fb3c0e114ea0..178b3f1356808 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -711,25 +711,6 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() { new llvm::vfs::OverlayFileSystem(MemFS); OverlayVFS->pushOverlay(SourceMgr.getFileSystem()); SourceMgr.setFileSystem(std::move(OverlayVFS)); - } else { - // For non-caching -direct-clang-cc1-module-build emit-pcm build, - // setup the clang VFS so it can find system modulemap files - // (like vcruntime.modulemap) as an input file. - if (Invocation.getClangImporterOptions().DirectClangCC1ModuleBuild && - Invocation.getFrontendOptions().RequestedAction == - FrontendOptions::ActionType::EmitPCM) { - llvm::IntrusiveRefCntPtr VFS = - SourceMgr.getFileSystem(); - ClangInvocationFileMappingContext Context( - Invocation.getLangOptions(), Invocation.getSearchPathOptions(), - Invocation.getClangImporterOptions(), Invocation.getCASOptions(), - Diagnostics); - ClangInvocationFileMapping FileMapping = applyClangInvocationMapping( - Context, nullptr, VFS, /*suppressDiagnostic=*/false); - if (!FileMapping.redirectedFiles.empty()) { - SourceMgr.setFileSystem(std::move(VFS)); - } - } } auto ExpectedOverlay = @@ -991,10 +972,10 @@ std::string CompilerInstance::getBridgingHeaderPath() const { } bool CompilerInstance::setUpInputs() { - // There is no input file when building PCM using Caching. + // There is no need to setup input when emit PCM. Let ClangImporter and the + // underlying clang CompilerInstance to handle inputs. if (Invocation.getFrontendOptions().RequestedAction == - FrontendOptions::ActionType::EmitPCM && - Invocation.getCASOptions().EnableCaching) + FrontendOptions::ActionType::EmitPCM) return false; // Adds to InputSourceCodeBufferIDs, so may need to happen before the diff --git a/test/ClangImporter/print-module-map-paths.swift b/test/ClangImporter/print-module-map-paths.swift index d5fac537f2679..20966ce6e2b1e 100644 --- a/test/ClangImporter/print-module-map-paths.swift +++ b/test/ClangImporter/print-module-map-paths.swift @@ -28,11 +28,13 @@ // RUN: cp %S/../../stdlib/public/Cxx/cxxshim/libcxxshim.modulemap %t/sdk/usr/lib/swift/android // RUN: %swift %s -typecheck -parse-stdlib -dump-clang-diagnostics -target aarch64-unknown-linux-android -sdk %t/sdk -resource-dir %t/resources -cxx-interoperability-mode=default 2>&1 | %FileCheck -check-prefix=CHECK-ANDROID-CXX %s +// CHECK-macosx-CXX-NOT: clang importer redirected file mappings: + // CHECK-LINUX: clang importer redirected file mappings: // CHECK-LINUX-NEXT: mapping real file '{{.*}}{{/|\\}}resources{{/|\\}}linux{{/|\\}}armv7{{/|\\}}glibc.modulemap' to virtual file '{{.*}}{{/|\\}}sdk{{/|\\}}usr{{/|\\}}include{{/|\\}}module.modulemap' // CHECK-LINUX-NEXT: mapping real file '{{.*}}{{/|\\}}resources{{/|\\}}linux{{/|\\}}armv7{{/|\\}}SwiftGlibc.h' to virtual file '{{.*}}{{/|\\}}sdk{{/|\\}}usr{{/|\\}}include{{/|\\}}SwiftGlibc.h' -// CHECK-CXX: clang importer redirected file mappings: +// CHECK-linux-gnu-CXX: clang importer redirected file mappings: // CHECK-linux-gnu-CXX: mapping real file '{{.*}}/resources/linux/libstdcxx.h' to virtual file '{{.*}}/usr/include/c++/{{.*}}/libstdcxx.h' // CHECK-linux-gnu-CXX: clang importer overriding file '{{.*}}/usr/include/c++/{{.*}}/module.modulemap' with the following contents: // CHECK-linux-gnu-CXX-NEXT: --- libstdcxx.modulemap --- @@ -46,4 +48,8 @@ // CHECK-ANDROID-NEXT: mapping real file '{{.*}}{{/|\\}}resources{{/|\\}}android{{/|\\}}aarch64{{/|\\}}SwiftAndroidNDK.h' to virtual file '{{.*}}{{/|\\}}sdk{{/|\\}}usr{{/|\\}}include{{/|\\}}SwiftAndroidNDK.h' // CHECK-ANDROID-NEXT: mapping real file '{{.*}}{{/|\\}}resources{{/|\\}}android{{/|\\}}aarch64{{/|\\}}SwiftBionic.h' to virtual file '{{.*}}{{/|\\}}sdk{{/|\\}}usr{{/|\\}}include{{/|\\}}SwiftBionic.h' +// CHECK-windows-msvc-CXX: clang importer file mappings: + // CHECK-ANDROID-CXX: clang importer driver args: {{.*}}'-fmodule-map-file={{.*}}resources{{/|\\}}android{{/|\\}}libcxxshim.modulemap' + +// CHECK-CXX: clang importer cc1 args: