10b57cec5SDimitry Andric //===- HeaderSearch.cpp - Resolve Header File Locations -------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the DirectoryLookup and HeaderSearch interfaces. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h" 140b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 150b57cec5SDimitry Andric #include "clang/Basic/FileManager.h" 160b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 170b57cec5SDimitry Andric #include "clang/Basic/Module.h" 180b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 190b57cec5SDimitry Andric #include "clang/Lex/DirectoryLookup.h" 200b57cec5SDimitry Andric #include "clang/Lex/ExternalPreprocessorSource.h" 210b57cec5SDimitry Andric #include "clang/Lex/HeaderMap.h" 220b57cec5SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h" 230b57cec5SDimitry Andric #include "clang/Lex/LexDiagnostic.h" 240b57cec5SDimitry Andric #include "clang/Lex/ModuleMap.h" 250b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 260b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 270b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h" 28*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 290b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 300b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 31a7dea167SDimitry Andric #include "llvm/ADT/Statistic.h" 320b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 330b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 340b57cec5SDimitry Andric #include "llvm/Support/Capacity.h" 35a7dea167SDimitry Andric #include "llvm/Support/Errc.h" 360b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 370b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 380b57cec5SDimitry Andric #include "llvm/Support/Path.h" 390b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 40*0fca6ea1SDimitry Andric #include "llvm/Support/xxhash.h" 410b57cec5SDimitry Andric #include <algorithm> 420b57cec5SDimitry Andric #include <cassert> 430b57cec5SDimitry Andric #include <cstddef> 440b57cec5SDimitry Andric #include <cstdio> 450b57cec5SDimitry Andric #include <cstring> 460b57cec5SDimitry Andric #include <string> 470b57cec5SDimitry Andric #include <system_error> 480b57cec5SDimitry Andric #include <utility> 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric using namespace clang; 510b57cec5SDimitry Andric 52a7dea167SDimitry Andric #define DEBUG_TYPE "file-search" 53a7dea167SDimitry Andric 54a7dea167SDimitry Andric ALWAYS_ENABLED_STATISTIC(NumIncluded, "Number of attempted #includes."); 55a7dea167SDimitry Andric ALWAYS_ENABLED_STATISTIC( 56a7dea167SDimitry Andric NumMultiIncludeFileOptzn, 57a7dea167SDimitry Andric "Number of #includes skipped due to the multi-include optimization."); 58a7dea167SDimitry Andric ALWAYS_ENABLED_STATISTIC(NumFrameworkLookups, "Number of framework lookups."); 59a7dea167SDimitry Andric ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups, 60a7dea167SDimitry Andric "Number of subframework lookups."); 61a7dea167SDimitry Andric 620b57cec5SDimitry Andric const IdentifierInfo * 630b57cec5SDimitry Andric HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) { 64*0fca6ea1SDimitry Andric if (LazyControllingMacro.isID()) { 65*0fca6ea1SDimitry Andric if (!External) 660b57cec5SDimitry Andric return nullptr; 670b57cec5SDimitry Andric 68*0fca6ea1SDimitry Andric LazyControllingMacro = 69*0fca6ea1SDimitry Andric External->GetIdentifier(LazyControllingMacro.getID()); 70*0fca6ea1SDimitry Andric return LazyControllingMacro.getPtr(); 71*0fca6ea1SDimitry Andric } 72*0fca6ea1SDimitry Andric 73*0fca6ea1SDimitry Andric IdentifierInfo *ControllingMacro = LazyControllingMacro.getPtr(); 74*0fca6ea1SDimitry Andric if (ControllingMacro && ControllingMacro->isOutOfDate()) { 75*0fca6ea1SDimitry Andric assert(External && "We must have an external source if we have a " 76*0fca6ea1SDimitry Andric "controlling macro that is out of date."); 77*0fca6ea1SDimitry Andric External->updateOutOfDateIdentifier(*ControllingMacro); 78*0fca6ea1SDimitry Andric } 790b57cec5SDimitry Andric return ControllingMacro; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, 850b57cec5SDimitry Andric SourceManager &SourceMgr, DiagnosticsEngine &Diags, 860b57cec5SDimitry Andric const LangOptions &LangOpts, 870b57cec5SDimitry Andric const TargetInfo *Target) 880b57cec5SDimitry Andric : HSOpts(std::move(HSOpts)), Diags(Diags), 890b57cec5SDimitry Andric FileMgr(SourceMgr.getFileManager()), FrameworkMap(64), 900b57cec5SDimitry Andric ModMap(SourceMgr, Diags, LangOpts, Target, *this) {} 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric void HeaderSearch::PrintStats() { 93a7dea167SDimitry Andric llvm::errs() << "\n*** HeaderSearch Stats:\n" 94a7dea167SDimitry Andric << FileInfo.size() << " files tracked.\n"; 9504eeddc0SDimitry Andric unsigned NumOnceOnlyFiles = 0; 9604eeddc0SDimitry Andric for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) 97349cc55cSDimitry Andric NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport); 9804eeddc0SDimitry Andric llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n"; 990b57cec5SDimitry Andric 100a7dea167SDimitry Andric llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n" 101a7dea167SDimitry Andric << " " << NumMultiIncludeFileOptzn 102a7dea167SDimitry Andric << " #includes skipped due to the multi-include optimization.\n"; 1030b57cec5SDimitry Andric 104a7dea167SDimitry Andric llvm::errs() << NumFrameworkLookups << " framework lookups.\n" 105a7dea167SDimitry Andric << NumSubFrameworkLookups << " subframework lookups.\n"; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 10804eeddc0SDimitry Andric void HeaderSearch::SetSearchPaths( 10904eeddc0SDimitry Andric std::vector<DirectoryLookup> dirs, unsigned int angledDirIdx, 1105f757f3fSDimitry Andric unsigned int systemDirIdx, 11104eeddc0SDimitry Andric llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) { 11204eeddc0SDimitry Andric assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() && 11304eeddc0SDimitry Andric "Directory indices are unordered"); 11404eeddc0SDimitry Andric SearchDirs = std::move(dirs); 11504eeddc0SDimitry Andric SearchDirsUsage.assign(SearchDirs.size(), false); 11604eeddc0SDimitry Andric AngledDirIdx = angledDirIdx; 11704eeddc0SDimitry Andric SystemDirIdx = systemDirIdx; 11804eeddc0SDimitry Andric SearchDirToHSEntry = std::move(searchDirToHSEntry); 11904eeddc0SDimitry Andric //LookupFileCache.clear(); 120bdd1243dSDimitry Andric indexInitialHeaderMaps(); 12104eeddc0SDimitry Andric } 12204eeddc0SDimitry Andric 12304eeddc0SDimitry Andric void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) { 12404eeddc0SDimitry Andric unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx; 12504eeddc0SDimitry Andric SearchDirs.insert(SearchDirs.begin() + idx, dir); 12604eeddc0SDimitry Andric SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false); 12704eeddc0SDimitry Andric if (!isAngled) 12804eeddc0SDimitry Andric AngledDirIdx++; 12904eeddc0SDimitry Andric SystemDirIdx++; 13004eeddc0SDimitry Andric } 13104eeddc0SDimitry Andric 132349cc55cSDimitry Andric std::vector<bool> HeaderSearch::computeUserEntryUsage() const { 133349cc55cSDimitry Andric std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size()); 134349cc55cSDimitry Andric for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) { 135349cc55cSDimitry Andric // Check whether this DirectoryLookup has been successfully used. 136349cc55cSDimitry Andric if (SearchDirsUsage[I]) { 137349cc55cSDimitry Andric auto UserEntryIdxIt = SearchDirToHSEntry.find(I); 138349cc55cSDimitry Andric // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry. 139349cc55cSDimitry Andric if (UserEntryIdxIt != SearchDirToHSEntry.end()) 140349cc55cSDimitry Andric UserEntryUsage[UserEntryIdxIt->second] = true; 141349cc55cSDimitry Andric } 142349cc55cSDimitry Andric } 143349cc55cSDimitry Andric return UserEntryUsage; 144349cc55cSDimitry Andric } 145349cc55cSDimitry Andric 146*0fca6ea1SDimitry Andric std::vector<bool> HeaderSearch::collectVFSUsageAndClear() const { 147*0fca6ea1SDimitry Andric std::vector<bool> VFSUsage; 148*0fca6ea1SDimitry Andric if (!getHeaderSearchOpts().ModulesIncludeVFSUsage) 149*0fca6ea1SDimitry Andric return VFSUsage; 150*0fca6ea1SDimitry Andric 151*0fca6ea1SDimitry Andric llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem(); 152*0fca6ea1SDimitry Andric // TODO: This only works if the `RedirectingFileSystem`s were all created by 153*0fca6ea1SDimitry Andric // `createVFSFromOverlayFiles`. 154*0fca6ea1SDimitry Andric RootFS.visit([&](llvm::vfs::FileSystem &FS) { 155*0fca6ea1SDimitry Andric if (auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) { 156*0fca6ea1SDimitry Andric VFSUsage.push_back(RFS->hasBeenUsed()); 157*0fca6ea1SDimitry Andric RFS->clearHasBeenUsed(); 158*0fca6ea1SDimitry Andric } 159*0fca6ea1SDimitry Andric }); 160*0fca6ea1SDimitry Andric assert(VFSUsage.size() == getHeaderSearchOpts().VFSOverlayFiles.size() && 161*0fca6ea1SDimitry Andric "A different number of RedirectingFileSystem's were present than " 162*0fca6ea1SDimitry Andric "-ivfsoverlay options passed to Clang!"); 163*0fca6ea1SDimitry Andric // VFS visit order is the opposite of VFSOverlayFiles order. 164*0fca6ea1SDimitry Andric std::reverse(VFSUsage.begin(), VFSUsage.end()); 165*0fca6ea1SDimitry Andric return VFSUsage; 166*0fca6ea1SDimitry Andric } 167*0fca6ea1SDimitry Andric 1680b57cec5SDimitry Andric /// CreateHeaderMap - This method returns a HeaderMap for the specified 1690b57cec5SDimitry Andric /// FileEntry, uniquing them through the 'HeaderMaps' datastructure. 1705f757f3fSDimitry Andric const HeaderMap *HeaderSearch::CreateHeaderMap(FileEntryRef FE) { 1710b57cec5SDimitry Andric // We expect the number of headermaps to be small, and almost always empty. 1720b57cec5SDimitry Andric // If it ever grows, use of a linear search should be re-evaluated. 1730b57cec5SDimitry Andric if (!HeaderMaps.empty()) { 1740b57cec5SDimitry Andric for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 1750b57cec5SDimitry Andric // Pointer equality comparison of FileEntries works because they are 1760b57cec5SDimitry Andric // already uniqued by inode. 1770b57cec5SDimitry Andric if (HeaderMaps[i].first == FE) 1780b57cec5SDimitry Andric return HeaderMaps[i].second.get(); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) { 1820b57cec5SDimitry Andric HeaderMaps.emplace_back(FE, std::move(HM)); 1830b57cec5SDimitry Andric return HeaderMaps.back().second.get(); 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric return nullptr; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric /// Get filenames for all registered header maps. 1900b57cec5SDimitry Andric void HeaderSearch::getHeaderMapFileNames( 1910b57cec5SDimitry Andric SmallVectorImpl<std::string> &Names) const { 1920b57cec5SDimitry Andric for (auto &HM : HeaderMaps) 1935f757f3fSDimitry Andric Names.push_back(std::string(HM.first.getName())); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric std::string HeaderSearch::getCachedModuleFileName(Module *Module) { 197bdd1243dSDimitry Andric OptionalFileEntryRef ModuleMap = 1980b57cec5SDimitry Andric getModuleMap().getModuleMapFileForUniquing(Module); 19981ad6265SDimitry Andric // The ModuleMap maybe a nullptr, when we load a cached C++ module without 20081ad6265SDimitry Andric // *.modulemap file. In this case, just return an empty string. 201bdd1243dSDimitry Andric if (!ModuleMap) 20281ad6265SDimitry Andric return {}; 2035f757f3fSDimitry Andric return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested()); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, 2070b57cec5SDimitry Andric bool FileMapOnly) { 2080b57cec5SDimitry Andric // First check the module name to pcm file map. 2090b57cec5SDimitry Andric auto i(HSOpts->PrebuiltModuleFiles.find(ModuleName)); 2100b57cec5SDimitry Andric if (i != HSOpts->PrebuiltModuleFiles.end()) 2110b57cec5SDimitry Andric return i->second; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty()) 2140b57cec5SDimitry Andric return {}; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Then go through each prebuilt module directory and try to find the pcm 2170b57cec5SDimitry Andric // file. 2180b57cec5SDimitry Andric for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { 2190b57cec5SDimitry Andric SmallString<256> Result(Dir); 2200b57cec5SDimitry Andric llvm::sys::fs::make_absolute(Result); 22181ad6265SDimitry Andric if (ModuleName.contains(':')) 22281ad6265SDimitry Andric // The separator of C++20 modules partitions (':') is not good for file 22381ad6265SDimitry Andric // systems, here clang and gcc choose '-' by default since it is not a 22481ad6265SDimitry Andric // valid character of C++ indentifiers. So we could avoid conflicts. 22581ad6265SDimitry Andric llvm::sys::path::append(Result, ModuleName.split(':').first + "-" + 22681ad6265SDimitry Andric ModuleName.split(':').second + 22781ad6265SDimitry Andric ".pcm"); 22881ad6265SDimitry Andric else 2290b57cec5SDimitry Andric llvm::sys::path::append(Result, ModuleName + ".pcm"); 2300b57cec5SDimitry Andric if (getFileMgr().getFile(Result.str())) 2315ffd83dbSDimitry Andric return std::string(Result); 2320b57cec5SDimitry Andric } 23381ad6265SDimitry Andric 2340b57cec5SDimitry Andric return {}; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 237e8d8bef9SDimitry Andric std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) { 238bdd1243dSDimitry Andric OptionalFileEntryRef ModuleMap = 239e8d8bef9SDimitry Andric getModuleMap().getModuleMapFileForUniquing(Module); 240e8d8bef9SDimitry Andric StringRef ModuleName = Module->Name; 241e8d8bef9SDimitry Andric StringRef ModuleMapPath = ModuleMap->getName(); 242e8d8bef9SDimitry Andric StringRef ModuleCacheHash = HSOpts->DisableModuleHash ? "" : getModuleHash(); 243e8d8bef9SDimitry Andric for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { 244e8d8bef9SDimitry Andric SmallString<256> CachePath(Dir); 245e8d8bef9SDimitry Andric llvm::sys::fs::make_absolute(CachePath); 246e8d8bef9SDimitry Andric llvm::sys::path::append(CachePath, ModuleCacheHash); 247e8d8bef9SDimitry Andric std::string FileName = 248e8d8bef9SDimitry Andric getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath); 249e8d8bef9SDimitry Andric if (!FileName.empty() && getFileMgr().getFile(FileName)) 250e8d8bef9SDimitry Andric return FileName; 251e8d8bef9SDimitry Andric } 252e8d8bef9SDimitry Andric return {}; 253e8d8bef9SDimitry Andric } 254e8d8bef9SDimitry Andric 2550b57cec5SDimitry Andric std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, 2560b57cec5SDimitry Andric StringRef ModuleMapPath) { 257e8d8bef9SDimitry Andric return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, 258e8d8bef9SDimitry Andric getModuleCachePath()); 259e8d8bef9SDimitry Andric } 260e8d8bef9SDimitry Andric 261e8d8bef9SDimitry Andric std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName, 262e8d8bef9SDimitry Andric StringRef ModuleMapPath, 263e8d8bef9SDimitry Andric StringRef CachePath) { 2640b57cec5SDimitry Andric // If we don't have a module cache path or aren't supposed to use one, we 2650b57cec5SDimitry Andric // can't do anything. 266e8d8bef9SDimitry Andric if (CachePath.empty()) 2670b57cec5SDimitry Andric return {}; 2680b57cec5SDimitry Andric 269e8d8bef9SDimitry Andric SmallString<256> Result(CachePath); 2700b57cec5SDimitry Andric llvm::sys::fs::make_absolute(Result); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric if (HSOpts->DisableModuleHash) { 2730b57cec5SDimitry Andric llvm::sys::path::append(Result, ModuleName + ".pcm"); 2740b57cec5SDimitry Andric } else { 2750b57cec5SDimitry Andric // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should 2760b57cec5SDimitry Andric // ideally be globally unique to this particular module. Name collisions 2770b57cec5SDimitry Andric // in the hash are safe (because any translation unit can only import one 2780b57cec5SDimitry Andric // module with each name), but result in a loss of caching. 2790b57cec5SDimitry Andric // 2800b57cec5SDimitry Andric // To avoid false-negatives, we form as canonical a path as we can, and map 2810b57cec5SDimitry Andric // to lower-case in case we're on a case-insensitive file system. 282bdd1243dSDimitry Andric SmallString<128> CanonicalPath(ModuleMapPath); 283bdd1243dSDimitry Andric if (getModuleMap().canonicalizeModuleMapPath(CanonicalPath)) 2840b57cec5SDimitry Andric return {}; 2850b57cec5SDimitry Andric 286*0fca6ea1SDimitry Andric auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower()); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric SmallString<128> HashStr; 289*0fca6ea1SDimitry Andric llvm::APInt(64, Hash).toStringUnsigned(HashStr, /*Radix*/36); 2900b57cec5SDimitry Andric llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm"); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric return Result.str().str(); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 295349cc55cSDimitry Andric Module *HeaderSearch::lookupModule(StringRef ModuleName, 296349cc55cSDimitry Andric SourceLocation ImportLoc, bool AllowSearch, 2970b57cec5SDimitry Andric bool AllowExtraModuleMapSearch) { 2980b57cec5SDimitry Andric // Look in the module map to determine if there is a module by this name. 2990b57cec5SDimitry Andric Module *Module = ModMap.findModule(ModuleName); 3000b57cec5SDimitry Andric if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) 3010b57cec5SDimitry Andric return Module; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric StringRef SearchName = ModuleName; 304349cc55cSDimitry Andric Module = lookupModule(ModuleName, SearchName, ImportLoc, 305349cc55cSDimitry Andric AllowExtraModuleMapSearch); 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric // The facility for "private modules" -- adjacent, optional module maps named 3080b57cec5SDimitry Andric // module.private.modulemap that are supposed to define private submodules -- 3090b57cec5SDimitry Andric // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private. 3100b57cec5SDimitry Andric // 3110b57cec5SDimitry Andric // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate 3120b57cec5SDimitry Andric // should also rename to Foo_Private. Representing private as submodules 3130b57cec5SDimitry Andric // could force building unwanted dependencies into the parent module and cause 3140b57cec5SDimitry Andric // dependency cycles. 3150b57cec5SDimitry Andric if (!Module && SearchName.consume_back("_Private")) 316349cc55cSDimitry Andric Module = lookupModule(ModuleName, SearchName, ImportLoc, 317349cc55cSDimitry Andric AllowExtraModuleMapSearch); 3180b57cec5SDimitry Andric if (!Module && SearchName.consume_back("Private")) 319349cc55cSDimitry Andric Module = lookupModule(ModuleName, SearchName, ImportLoc, 320349cc55cSDimitry Andric AllowExtraModuleMapSearch); 3210b57cec5SDimitry Andric return Module; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, 325349cc55cSDimitry Andric SourceLocation ImportLoc, 3260b57cec5SDimitry Andric bool AllowExtraModuleMapSearch) { 3270b57cec5SDimitry Andric Module *Module = nullptr; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // Look through the various header search paths to load any available module 3300b57cec5SDimitry Andric // maps, searching for a module map that describes this module. 331bdd1243dSDimitry Andric for (DirectoryLookup &Dir : search_dir_range()) { 33281ad6265SDimitry Andric if (Dir.isFramework()) { 3330b57cec5SDimitry Andric // Search for or infer a module map for a framework. Here we use 3340b57cec5SDimitry Andric // SearchName rather than ModuleName, to permit finding private modules 3350b57cec5SDimitry Andric // named FooPrivate in buggy frameworks named Foo. 3360b57cec5SDimitry Andric SmallString<128> FrameworkDirName; 33706c3fb27SDimitry Andric FrameworkDirName += Dir.getFrameworkDirRef()->getName(); 3380b57cec5SDimitry Andric llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); 33981ad6265SDimitry Andric if (auto FrameworkDir = 34081ad6265SDimitry Andric FileMgr.getOptionalDirectoryRef(FrameworkDirName)) { 34181ad6265SDimitry Andric bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User; 342a7dea167SDimitry Andric Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem); 3430b57cec5SDimitry Andric if (Module) 3440b57cec5SDimitry Andric break; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric // FIXME: Figure out how header maps and module maps will work together. 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric // Only deal with normal search directories. 35181ad6265SDimitry Andric if (!Dir.isNormalDir()) 3520b57cec5SDimitry Andric continue; 3530b57cec5SDimitry Andric 35481ad6265SDimitry Andric bool IsSystem = Dir.isSystemHeaderDirectory(); 355bdd1243dSDimitry Andric // Only returns std::nullopt if not a normal directory, which we just 356bdd1243dSDimitry Andric // checked 35781ad6265SDimitry Andric DirectoryEntryRef NormalDir = *Dir.getDirRef(); 3580b57cec5SDimitry Andric // Search for a module map file in this directory. 35981ad6265SDimitry Andric if (loadModuleMapFile(NormalDir, IsSystem, 3600b57cec5SDimitry Andric /*IsFramework*/false) == LMM_NewlyLoaded) { 3610b57cec5SDimitry Andric // We just loaded a module map file; check whether the module is 3620b57cec5SDimitry Andric // available now. 3630b57cec5SDimitry Andric Module = ModMap.findModule(ModuleName); 3640b57cec5SDimitry Andric if (Module) 3650b57cec5SDimitry Andric break; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric // Search for a module map in a subdirectory with the same name as the 3690b57cec5SDimitry Andric // module. 3700b57cec5SDimitry Andric SmallString<128> NestedModuleMapDirName; 37106c3fb27SDimitry Andric NestedModuleMapDirName = Dir.getDirRef()->getName(); 3720b57cec5SDimitry Andric llvm::sys::path::append(NestedModuleMapDirName, ModuleName); 3730b57cec5SDimitry Andric if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, 3740b57cec5SDimitry Andric /*IsFramework*/false) == LMM_NewlyLoaded){ 3750b57cec5SDimitry Andric // If we just loaded a module map file, look for the module again. 3760b57cec5SDimitry Andric Module = ModMap.findModule(ModuleName); 3770b57cec5SDimitry Andric if (Module) 3780b57cec5SDimitry Andric break; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric // If we've already performed the exhaustive search for module maps in this 3820b57cec5SDimitry Andric // search directory, don't do it again. 38381ad6265SDimitry Andric if (Dir.haveSearchedAllModuleMaps()) 3840b57cec5SDimitry Andric continue; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric // Load all module maps in the immediate subdirectories of this search 3870b57cec5SDimitry Andric // directory if ModuleName was from @import. 3880b57cec5SDimitry Andric if (AllowExtraModuleMapSearch) 38981ad6265SDimitry Andric loadSubdirectoryModuleMaps(Dir); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric // Look again for the module. 3920b57cec5SDimitry Andric Module = ModMap.findModule(ModuleName); 3930b57cec5SDimitry Andric if (Module) 3940b57cec5SDimitry Andric break; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric return Module; 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 400bdd1243dSDimitry Andric void HeaderSearch::indexInitialHeaderMaps() { 401bdd1243dSDimitry Andric llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size()); 402bdd1243dSDimitry Andric 403bdd1243dSDimitry Andric // Iterate over all filename keys and associate them with the index i. 40406c3fb27SDimitry Andric for (unsigned i = 0; i != SearchDirs.size(); ++i) { 405bdd1243dSDimitry Andric auto &Dir = SearchDirs[i]; 406bdd1243dSDimitry Andric 407bdd1243dSDimitry Andric // We're concerned with only the initial contiguous run of header 408bdd1243dSDimitry Andric // maps within SearchDirs, which can be 99% of SearchDirs when 409bdd1243dSDimitry Andric // SearchDirs.size() is ~10000. 41006c3fb27SDimitry Andric if (!Dir.isHeaderMap()) { 41106c3fb27SDimitry Andric SearchDirHeaderMapIndex = std::move(Index); 41206c3fb27SDimitry Andric FirstNonHeaderMapSearchDirIdx = i; 413bdd1243dSDimitry Andric break; 41406c3fb27SDimitry Andric } 415bdd1243dSDimitry Andric 416bdd1243dSDimitry Andric // Give earlier keys precedence over identical later keys. 417bdd1243dSDimitry Andric auto Callback = [&](StringRef Filename) { 418bdd1243dSDimitry Andric Index.try_emplace(Filename.lower(), i); 419bdd1243dSDimitry Andric }; 420bdd1243dSDimitry Andric Dir.getHeaderMap()->forEachKey(Callback); 421bdd1243dSDimitry Andric } 422bdd1243dSDimitry Andric } 423bdd1243dSDimitry Andric 4240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4250b57cec5SDimitry Andric // File lookup within a DirectoryLookup scope 4260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric /// getName - Return the directory or filename corresponding to this lookup 4290b57cec5SDimitry Andric /// object. 4300b57cec5SDimitry Andric StringRef DirectoryLookup::getName() const { 4310b57cec5SDimitry Andric if (isNormalDir()) 43206c3fb27SDimitry Andric return getDirRef()->getName(); 4330b57cec5SDimitry Andric if (isFramework()) 43406c3fb27SDimitry Andric return getFrameworkDirRef()->getName(); 4350b57cec5SDimitry Andric assert(isHeaderMap() && "Unknown DirectoryLookup"); 4360b57cec5SDimitry Andric return getHeaderMap()->getFileName(); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 439bdd1243dSDimitry Andric OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule( 4400b57cec5SDimitry Andric StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir, 4410b57cec5SDimitry Andric bool IsSystemHeaderDir, Module *RequestingModule, 442bdd1243dSDimitry Andric ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/, 443bdd1243dSDimitry Andric bool CacheFailures /*=true*/) { 4440b57cec5SDimitry Andric // If we have a module map that might map this header, load it and 4450b57cec5SDimitry Andric // check whether we'll have a suggestion for a module. 446bdd1243dSDimitry Andric auto File = getFileMgr().getFileRef(FileName, OpenFile, CacheFailures); 447a7dea167SDimitry Andric if (!File) { 448a7dea167SDimitry Andric // For rare, surprising errors (e.g. "out of file handles"), diag the EC 449a7dea167SDimitry Andric // message. 450a7dea167SDimitry Andric std::error_code EC = llvm::errorToErrorCode(File.takeError()); 451a7dea167SDimitry Andric if (EC != llvm::errc::no_such_file_or_directory && 452a7dea167SDimitry Andric EC != llvm::errc::invalid_argument && 453a7dea167SDimitry Andric EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) { 454a7dea167SDimitry Andric Diags.Report(IncludeLoc, diag::err_cannot_open_file) 455a7dea167SDimitry Andric << FileName << EC.message(); 456a7dea167SDimitry Andric } 457bdd1243dSDimitry Andric return std::nullopt; 458a7dea167SDimitry Andric } 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric // If there is a module that corresponds to this header, suggest it. 461a7dea167SDimitry Andric if (!findUsableModuleForHeader( 46206c3fb27SDimitry Andric *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule, 46306c3fb27SDimitry Andric SuggestedModule, IsSystemHeaderDir)) 464bdd1243dSDimitry Andric return std::nullopt; 4650b57cec5SDimitry Andric 466a7dea167SDimitry Andric return *File; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric /// LookupFile - Lookup the specified file in this search path, returning it 4700b57cec5SDimitry Andric /// if it exists or returning null if not. 471bdd1243dSDimitry Andric OptionalFileEntryRef DirectoryLookup::LookupFile( 472a7dea167SDimitry Andric StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, 473a7dea167SDimitry Andric SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, 474a7dea167SDimitry Andric Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, 475a7dea167SDimitry Andric bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, 476bdd1243dSDimitry Andric bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName, 477bdd1243dSDimitry Andric bool OpenFile) const { 4780b57cec5SDimitry Andric InUserSpecifiedSystemFramework = false; 479a7dea167SDimitry Andric IsInHeaderMap = false; 480a7dea167SDimitry Andric MappedName.clear(); 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric SmallString<1024> TmpDir; 4830b57cec5SDimitry Andric if (isNormalDir()) { 4840b57cec5SDimitry Andric // Concatenate the requested file onto the directory. 48581ad6265SDimitry Andric TmpDir = getDirRef()->getName(); 4860b57cec5SDimitry Andric llvm::sys::path::append(TmpDir, Filename); 4870b57cec5SDimitry Andric if (SearchPath) { 48881ad6265SDimitry Andric StringRef SearchPathRef(getDirRef()->getName()); 4890b57cec5SDimitry Andric SearchPath->clear(); 4900b57cec5SDimitry Andric SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric if (RelativePath) { 4930b57cec5SDimitry Andric RelativePath->clear(); 4940b57cec5SDimitry Andric RelativePath->append(Filename.begin(), Filename.end()); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 497bdd1243dSDimitry Andric return HS.getFileAndSuggestModule( 498bdd1243dSDimitry Andric TmpDir, IncludeLoc, getDir(), isSystemHeaderDirectory(), 499bdd1243dSDimitry Andric RequestingModule, SuggestedModule, OpenFile); 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric if (isFramework()) 5030b57cec5SDimitry Andric return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, 5040b57cec5SDimitry Andric RequestingModule, SuggestedModule, 5050b57cec5SDimitry Andric InUserSpecifiedSystemFramework, IsFrameworkFound); 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric assert(isHeaderMap() && "Unknown directory lookup"); 5080b57cec5SDimitry Andric const HeaderMap *HM = getHeaderMap(); 5090b57cec5SDimitry Andric SmallString<1024> Path; 5100b57cec5SDimitry Andric StringRef Dest = HM->lookupFilename(Filename, Path); 5110b57cec5SDimitry Andric if (Dest.empty()) 512bdd1243dSDimitry Andric return std::nullopt; 5130b57cec5SDimitry Andric 514a7dea167SDimitry Andric IsInHeaderMap = true; 5150b57cec5SDimitry Andric 51606c3fb27SDimitry Andric auto FixupSearchPathAndFindUsableModule = 51706c3fb27SDimitry Andric [&](FileEntryRef File) -> OptionalFileEntryRef { 5180b57cec5SDimitry Andric if (SearchPath) { 5190b57cec5SDimitry Andric StringRef SearchPathRef(getName()); 5200b57cec5SDimitry Andric SearchPath->clear(); 5210b57cec5SDimitry Andric SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric if (RelativePath) { 5240b57cec5SDimitry Andric RelativePath->clear(); 5250b57cec5SDimitry Andric RelativePath->append(Filename.begin(), Filename.end()); 5260b57cec5SDimitry Andric } 52706c3fb27SDimitry Andric if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(), 52806c3fb27SDimitry Andric RequestingModule, SuggestedModule, 52906c3fb27SDimitry Andric isSystemHeaderDirectory())) { 53006c3fb27SDimitry Andric return std::nullopt; 53106c3fb27SDimitry Andric } 53206c3fb27SDimitry Andric return File; 533a7dea167SDimitry Andric }; 534a7dea167SDimitry Andric 535a7dea167SDimitry Andric // Check if the headermap maps the filename to a framework include 536a7dea167SDimitry Andric // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the 537a7dea167SDimitry Andric // framework include. 538a7dea167SDimitry Andric if (llvm::sys::path::is_relative(Dest)) { 539a7dea167SDimitry Andric MappedName.append(Dest.begin(), Dest.end()); 540a7dea167SDimitry Andric Filename = StringRef(MappedName.begin(), MappedName.size()); 541349cc55cSDimitry Andric Dest = HM->lookupFilename(Filename, Path); 5420b57cec5SDimitry Andric } 543349cc55cSDimitry Andric 544bdd1243dSDimitry Andric if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest, OpenFile)) { 54506c3fb27SDimitry Andric return FixupSearchPathAndFindUsableModule(*Res); 546a7dea167SDimitry Andric } 547a7dea167SDimitry Andric 548349cc55cSDimitry Andric // Header maps need to be marked as used whenever the filename matches. 549349cc55cSDimitry Andric // The case where the target file **exists** is handled by callee of this 550349cc55cSDimitry Andric // function as part of the regular logic that applies to include search paths. 551349cc55cSDimitry Andric // The case where the target file **does not exist** is handled here: 55281ad6265SDimitry Andric HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc); 553bdd1243dSDimitry Andric return std::nullopt; 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric /// Given a framework directory, find the top-most framework directory. 5570b57cec5SDimitry Andric /// 5580b57cec5SDimitry Andric /// \param FileMgr The file manager to use for directory lookups. 5590b57cec5SDimitry Andric /// \param DirName The name of the framework directory. 5600b57cec5SDimitry Andric /// \param SubmodulePath Will be populated with the submodule path from the 5610b57cec5SDimitry Andric /// returned top-level module to the originally named framework. 562bdd1243dSDimitry Andric static OptionalDirectoryEntryRef 5630b57cec5SDimitry Andric getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, 5640b57cec5SDimitry Andric SmallVectorImpl<std::string> &SubmodulePath) { 5650b57cec5SDimitry Andric assert(llvm::sys::path::extension(DirName) == ".framework" && 5660b57cec5SDimitry Andric "Not a framework directory"); 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric // Note: as an egregious but useful hack we use the real path here, because 5690b57cec5SDimitry Andric // frameworks moving between top-level frameworks to embedded frameworks tend 5700b57cec5SDimitry Andric // to be symlinked, and we base the logical structure of modules on the 5710b57cec5SDimitry Andric // physical layout. In particular, we need to deal with crazy includes like 5720b57cec5SDimitry Andric // 5730b57cec5SDimitry Andric // #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h> 5740b57cec5SDimitry Andric // 5750b57cec5SDimitry Andric // where 'Bar' used to be embedded in 'Foo', is now a top-level framework 5760b57cec5SDimitry Andric // which one should access with, e.g., 5770b57cec5SDimitry Andric // 5780b57cec5SDimitry Andric // #include <Bar/Wibble.h> 5790b57cec5SDimitry Andric // 5800b57cec5SDimitry Andric // Similar issues occur when a top-level framework has moved into an 5810b57cec5SDimitry Andric // embedded framework. 58281ad6265SDimitry Andric auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName); 583a7dea167SDimitry Andric 584a7dea167SDimitry Andric if (TopFrameworkDir) 58581ad6265SDimitry Andric DirName = FileMgr.getCanonicalName(*TopFrameworkDir); 5860b57cec5SDimitry Andric do { 5870b57cec5SDimitry Andric // Get the parent directory name. 5880b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName); 5890b57cec5SDimitry Andric if (DirName.empty()) 5900b57cec5SDimitry Andric break; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric // Determine whether this directory exists. 59381ad6265SDimitry Andric auto Dir = FileMgr.getOptionalDirectoryRef(DirName); 5940b57cec5SDimitry Andric if (!Dir) 5950b57cec5SDimitry Andric break; 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric // If this is a framework directory, then we're a subframework of this 5980b57cec5SDimitry Andric // framework. 5990b57cec5SDimitry Andric if (llvm::sys::path::extension(DirName) == ".framework") { 6005ffd83dbSDimitry Andric SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName))); 601a7dea167SDimitry Andric TopFrameworkDir = *Dir; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric } while (true); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric return TopFrameworkDir; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric static bool needModuleLookup(Module *RequestingModule, 6090b57cec5SDimitry Andric bool HasSuggestedModule) { 6100b57cec5SDimitry Andric return HasSuggestedModule || 6110b57cec5SDimitry Andric (RequestingModule && RequestingModule->NoUndeclaredIncludes); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric /// DoFrameworkLookup - Do a lookup of the specified file in the current 6150b57cec5SDimitry Andric /// DirectoryLookup, which is a framework directory. 616bdd1243dSDimitry Andric OptionalFileEntryRef DirectoryLookup::DoFrameworkLookup( 6170b57cec5SDimitry Andric StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, 6180b57cec5SDimitry Andric SmallVectorImpl<char> *RelativePath, Module *RequestingModule, 6190b57cec5SDimitry Andric ModuleMap::KnownHeader *SuggestedModule, 6200b57cec5SDimitry Andric bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const { 6210b57cec5SDimitry Andric FileManager &FileMgr = HS.getFileMgr(); 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric // Framework names must have a '/' in the filename. 6240b57cec5SDimitry Andric size_t SlashPos = Filename.find('/'); 625a7dea167SDimitry Andric if (SlashPos == StringRef::npos) 626bdd1243dSDimitry Andric return std::nullopt; 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric // Find out if this is the home for the specified framework, by checking 6290b57cec5SDimitry Andric // HeaderSearch. Possible answers are yes/no and unknown. 6300b57cec5SDimitry Andric FrameworkCacheEntry &CacheEntry = 6310b57cec5SDimitry Andric HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric // If it is known and in some other directory, fail. 63481ad6265SDimitry Andric if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef()) 635bdd1243dSDimitry Andric return std::nullopt; 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric // Otherwise, construct the path to this framework dir. 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric // FrameworkName = "/System/Library/Frameworks/" 6400b57cec5SDimitry Andric SmallString<1024> FrameworkName; 641a7dea167SDimitry Andric FrameworkName += getFrameworkDirRef()->getName(); 6420b57cec5SDimitry Andric if (FrameworkName.empty() || FrameworkName.back() != '/') 6430b57cec5SDimitry Andric FrameworkName.push_back('/'); 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric // FrameworkName = "/System/Library/Frameworks/Cocoa" 6460b57cec5SDimitry Andric StringRef ModuleName(Filename.begin(), SlashPos); 6470b57cec5SDimitry Andric FrameworkName += ModuleName; 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" 6500b57cec5SDimitry Andric FrameworkName += ".framework/"; 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric // If the cache entry was unresolved, populate it now. 6530b57cec5SDimitry Andric if (!CacheEntry.Directory) { 654a7dea167SDimitry Andric ++NumFrameworkLookups; 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric // If the framework dir doesn't exist, we fail. 657a7dea167SDimitry Andric auto Dir = FileMgr.getDirectory(FrameworkName); 658a7dea167SDimitry Andric if (!Dir) 659bdd1243dSDimitry Andric return std::nullopt; 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric // Otherwise, if it does, remember that this is the right direntry for this 6620b57cec5SDimitry Andric // framework. 66381ad6265SDimitry Andric CacheEntry.Directory = getFrameworkDirRef(); 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric // If this is a user search directory, check if the framework has been 6660b57cec5SDimitry Andric // user-specified as a system framework. 6670b57cec5SDimitry Andric if (getDirCharacteristic() == SrcMgr::C_User) { 6680b57cec5SDimitry Andric SmallString<1024> SystemFrameworkMarker(FrameworkName); 6690b57cec5SDimitry Andric SystemFrameworkMarker += ".system_framework"; 6700b57cec5SDimitry Andric if (llvm::sys::fs::exists(SystemFrameworkMarker)) { 6710b57cec5SDimitry Andric CacheEntry.IsUserSpecifiedSystemFramework = true; 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric // Set out flags. 6770b57cec5SDimitry Andric InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; 67881ad6265SDimitry Andric IsFrameworkFound = CacheEntry.Directory.has_value(); 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric if (RelativePath) { 6810b57cec5SDimitry Andric RelativePath->clear(); 6820b57cec5SDimitry Andric RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" 6860b57cec5SDimitry Andric unsigned OrigSize = FrameworkName.size(); 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric FrameworkName += "Headers/"; 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric if (SearchPath) { 6910b57cec5SDimitry Andric SearchPath->clear(); 6920b57cec5SDimitry Andric // Without trailing '/'. 6930b57cec5SDimitry Andric SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); 697a7dea167SDimitry Andric 698a7dea167SDimitry Andric auto File = 699a7dea167SDimitry Andric FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule); 700a7dea167SDimitry Andric if (!File) { 7010b57cec5SDimitry Andric // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 7020b57cec5SDimitry Andric const char *Private = "Private"; 7030b57cec5SDimitry Andric FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 7040b57cec5SDimitry Andric Private+strlen(Private)); 7050b57cec5SDimitry Andric if (SearchPath) 7060b57cec5SDimitry Andric SearchPath->insert(SearchPath->begin()+OrigSize, Private, 7070b57cec5SDimitry Andric Private+strlen(Private)); 7080b57cec5SDimitry Andric 709a7dea167SDimitry Andric File = FileMgr.getOptionalFileRef(FrameworkName, 710a7dea167SDimitry Andric /*OpenFile=*/!SuggestedModule); 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric // If we found the header and are allowed to suggest a module, do so now. 714a7dea167SDimitry Andric if (File && needModuleLookup(RequestingModule, SuggestedModule)) { 7150b57cec5SDimitry Andric // Find the framework in which this header occurs. 71606c3fb27SDimitry Andric StringRef FrameworkPath = File->getDir().getName(); 7170b57cec5SDimitry Andric bool FoundFramework = false; 7180b57cec5SDimitry Andric do { 7190b57cec5SDimitry Andric // Determine whether this directory exists. 720a7dea167SDimitry Andric auto Dir = FileMgr.getDirectory(FrameworkPath); 7210b57cec5SDimitry Andric if (!Dir) 7220b57cec5SDimitry Andric break; 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric // If this is a framework directory, then we're a subframework of this 7250b57cec5SDimitry Andric // framework. 7260b57cec5SDimitry Andric if (llvm::sys::path::extension(FrameworkPath) == ".framework") { 7270b57cec5SDimitry Andric FoundFramework = true; 7280b57cec5SDimitry Andric break; 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // Get the parent directory name. 7320b57cec5SDimitry Andric FrameworkPath = llvm::sys::path::parent_path(FrameworkPath); 7330b57cec5SDimitry Andric if (FrameworkPath.empty()) 7340b57cec5SDimitry Andric break; 7350b57cec5SDimitry Andric } while (true); 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; 7380b57cec5SDimitry Andric if (FoundFramework) { 73906c3fb27SDimitry Andric if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath, 74006c3fb27SDimitry Andric RequestingModule, 7410b57cec5SDimitry Andric SuggestedModule, IsSystem)) 742bdd1243dSDimitry Andric return std::nullopt; 743a7dea167SDimitry Andric } else { 74406c3fb27SDimitry Andric if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule, 74506c3fb27SDimitry Andric SuggestedModule, IsSystem)) 746bdd1243dSDimitry Andric return std::nullopt; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric } 749a7dea167SDimitry Andric if (File) 750a7dea167SDimitry Andric return *File; 751bdd1243dSDimitry Andric return std::nullopt; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 754349cc55cSDimitry Andric void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup, 75581ad6265SDimitry Andric ConstSearchDirIterator HitIt, 75681ad6265SDimitry Andric SourceLocation Loc) { 75781ad6265SDimitry Andric CacheLookup.HitIt = HitIt; 75881ad6265SDimitry Andric noteLookupUsage(HitIt.Idx, Loc); 759349cc55cSDimitry Andric } 760349cc55cSDimitry Andric 761349cc55cSDimitry Andric void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) { 762349cc55cSDimitry Andric SearchDirsUsage[HitIdx] = true; 763349cc55cSDimitry Andric 764349cc55cSDimitry Andric auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx); 765349cc55cSDimitry Andric if (UserEntryIdxIt != SearchDirToHSEntry.end()) 766349cc55cSDimitry Andric Diags.Report(Loc, diag::remark_pp_search_path_usage) 767349cc55cSDimitry Andric << HSOpts->UserEntries[UserEntryIdxIt->second].Path; 768349cc55cSDimitry Andric } 769349cc55cSDimitry Andric 7700b57cec5SDimitry Andric void HeaderSearch::setTarget(const TargetInfo &Target) { 7710b57cec5SDimitry Andric ModMap.setTarget(Target); 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7750b57cec5SDimitry Andric // Header File Location. 7760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric /// Return true with a diagnostic if the file that MSVC would have found 7790b57cec5SDimitry Andric /// fails to match the one that Clang would have found with MSVC header search 7800b57cec5SDimitry Andric /// disabled. 7810b57cec5SDimitry Andric static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags, 7825f757f3fSDimitry Andric OptionalFileEntryRef MSFE, 7835f757f3fSDimitry Andric const FileEntry *FE, 7840b57cec5SDimitry Andric SourceLocation IncludeLoc) { 7855f757f3fSDimitry Andric if (MSFE && FE != *MSFE) { 7860b57cec5SDimitry Andric Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName(); 7870b57cec5SDimitry Andric return true; 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric return false; 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { 7930b57cec5SDimitry Andric assert(!Str.empty()); 7940b57cec5SDimitry Andric char *CopyStr = Alloc.Allocate<char>(Str.size()+1); 7950b57cec5SDimitry Andric std::copy(Str.begin(), Str.end(), CopyStr); 7960b57cec5SDimitry Andric CopyStr[Str.size()] = '\0'; 7970b57cec5SDimitry Andric return CopyStr; 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader, 80104eeddc0SDimitry Andric SmallVectorImpl<char> &FrameworkName, 80204eeddc0SDimitry Andric SmallVectorImpl<char> &IncludeSpelling) { 8030b57cec5SDimitry Andric using namespace llvm::sys; 8040b57cec5SDimitry Andric path::const_iterator I = path::begin(Path); 8050b57cec5SDimitry Andric path::const_iterator E = path::end(Path); 8060b57cec5SDimitry Andric IsPrivateHeader = false; 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric // Detect different types of framework style paths: 8090b57cec5SDimitry Andric // 8100b57cec5SDimitry Andric // ...Foo.framework/{Headers,PrivateHeaders} 8110b57cec5SDimitry Andric // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} 8120b57cec5SDimitry Andric // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} 8130b57cec5SDimitry Andric // ...<other variations with 'Versions' like in the above path> 8140b57cec5SDimitry Andric // 8150b57cec5SDimitry Andric // and some other variations among these lines. 8160b57cec5SDimitry Andric int FoundComp = 0; 8170b57cec5SDimitry Andric while (I != E) { 81804eeddc0SDimitry Andric if (*I == "Headers") { 8190b57cec5SDimitry Andric ++FoundComp; 82004eeddc0SDimitry Andric } else if (*I == "PrivateHeaders") { 8210b57cec5SDimitry Andric ++FoundComp; 8220b57cec5SDimitry Andric IsPrivateHeader = true; 8235f757f3fSDimitry Andric } else if (I->ends_with(".framework")) { 82404eeddc0SDimitry Andric StringRef Name = I->drop_back(10); // Drop .framework 82504eeddc0SDimitry Andric // Need to reset the strings and counter to support nested frameworks. 82604eeddc0SDimitry Andric FrameworkName.clear(); 82704eeddc0SDimitry Andric FrameworkName.append(Name.begin(), Name.end()); 82804eeddc0SDimitry Andric IncludeSpelling.clear(); 82904eeddc0SDimitry Andric IncludeSpelling.append(Name.begin(), Name.end()); 83004eeddc0SDimitry Andric FoundComp = 1; 83104eeddc0SDimitry Andric } else if (FoundComp >= 2) { 83204eeddc0SDimitry Andric IncludeSpelling.push_back('/'); 83304eeddc0SDimitry Andric IncludeSpelling.append(I->begin(), I->end()); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric ++I; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric return !FrameworkName.empty() && FoundComp >= 2; 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric static void 8420b57cec5SDimitry Andric diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, 8430b57cec5SDimitry Andric StringRef Includer, StringRef IncludeFilename, 8445f757f3fSDimitry Andric FileEntryRef IncludeFE, bool isAngled = false, 8450b57cec5SDimitry Andric bool FoundByHeaderMap = false) { 8460b57cec5SDimitry Andric bool IsIncluderPrivateHeader = false; 8470b57cec5SDimitry Andric SmallString<128> FromFramework, ToFramework; 84804eeddc0SDimitry Andric SmallString<128> FromIncludeSpelling, ToIncludeSpelling; 84904eeddc0SDimitry Andric if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework, 85004eeddc0SDimitry Andric FromIncludeSpelling)) 8510b57cec5SDimitry Andric return; 8520b57cec5SDimitry Andric bool IsIncludeePrivateHeader = false; 85304eeddc0SDimitry Andric bool IsIncludeeInFramework = 8545f757f3fSDimitry Andric isFrameworkStylePath(IncludeFE.getName(), IsIncludeePrivateHeader, 85504eeddc0SDimitry Andric ToFramework, ToIncludeSpelling); 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric if (!isAngled && !FoundByHeaderMap) { 8580b57cec5SDimitry Andric SmallString<128> NewInclude("<"); 8590b57cec5SDimitry Andric if (IsIncludeeInFramework) { 86004eeddc0SDimitry Andric NewInclude += ToIncludeSpelling; 86104eeddc0SDimitry Andric NewInclude += ">"; 86204eeddc0SDimitry Andric } else { 8630b57cec5SDimitry Andric NewInclude += IncludeFilename; 8640b57cec5SDimitry Andric NewInclude += ">"; 86504eeddc0SDimitry Andric } 8660b57cec5SDimitry Andric Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) 8670b57cec5SDimitry Andric << IncludeFilename 8680b57cec5SDimitry Andric << FixItHint::CreateReplacement(IncludeLoc, NewInclude); 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric // Headers in Foo.framework/Headers should not include headers 8720b57cec5SDimitry Andric // from Foo.framework/PrivateHeaders, since this violates public/private 8730b57cec5SDimitry Andric // API boundaries and can cause modular dependency cycles. 8740b57cec5SDimitry Andric if (!IsIncluderPrivateHeader && IsIncludeeInFramework && 8750b57cec5SDimitry Andric IsIncludeePrivateHeader && FromFramework == ToFramework) 8760b57cec5SDimitry Andric Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public) 8770b57cec5SDimitry Andric << IncludeFilename; 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, 8810b57cec5SDimitry Andric /// return null on failure. isAngled indicates whether the file reference is 8820b57cec5SDimitry Andric /// for system \#include's or not (i.e. using <> instead of ""). Includers, if 8830b57cec5SDimitry Andric /// non-empty, indicates where the \#including file(s) are, in case a relative 8840b57cec5SDimitry Andric /// search is needed. Microsoft mode will pass all \#including files. 885bdd1243dSDimitry Andric OptionalFileEntryRef HeaderSearch::LookupFile( 8860b57cec5SDimitry Andric StringRef Filename, SourceLocation IncludeLoc, bool isAngled, 88781ad6265SDimitry Andric ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg, 8885f757f3fSDimitry Andric ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers, 8890b57cec5SDimitry Andric SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, 8900b57cec5SDimitry Andric Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, 8910b57cec5SDimitry Andric bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, 892bdd1243dSDimitry Andric bool BuildSystemModule, bool OpenFile, bool CacheFailures) { 89381ad6265SDimitry Andric ConstSearchDirIterator CurDirLocal = nullptr; 89481ad6265SDimitry Andric ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal; 89504eeddc0SDimitry Andric 8960b57cec5SDimitry Andric if (IsMapped) 8970b57cec5SDimitry Andric *IsMapped = false; 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric if (IsFrameworkFound) 9000b57cec5SDimitry Andric *IsFrameworkFound = false; 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric if (SuggestedModule) 9030b57cec5SDimitry Andric *SuggestedModule = ModuleMap::KnownHeader(); 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric // If 'Filename' is absolute, check to see if it exists and no searching. 9060b57cec5SDimitry Andric if (llvm::sys::path::is_absolute(Filename)) { 9070b57cec5SDimitry Andric CurDir = nullptr; 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric // If this was an #include_next "/absolute/file", fail. 910a7dea167SDimitry Andric if (FromDir) 911bdd1243dSDimitry Andric return std::nullopt; 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric if (SearchPath) 9140b57cec5SDimitry Andric SearchPath->clear(); 9150b57cec5SDimitry Andric if (RelativePath) { 9160b57cec5SDimitry Andric RelativePath->clear(); 9170b57cec5SDimitry Andric RelativePath->append(Filename.begin(), Filename.end()); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric // Otherwise, just return the file. 9200b57cec5SDimitry Andric return getFileAndSuggestModule(Filename, IncludeLoc, nullptr, 9210b57cec5SDimitry Andric /*IsSystemHeaderDir*/ false, 922bdd1243dSDimitry Andric RequestingModule, SuggestedModule, OpenFile, 923bdd1243dSDimitry Andric CacheFailures); 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric // This is the header that MSVC's header search would have found. 9270b57cec5SDimitry Andric ModuleMap::KnownHeader MSSuggestedModule; 928bdd1243dSDimitry Andric OptionalFileEntryRef MSFE; 9290b57cec5SDimitry Andric 9305f757f3fSDimitry Andric // Check to see if the file is in the #includer's directory. This cannot be 9315f757f3fSDimitry Andric // based on CurDir, because each includer could be a #include of a 9325f757f3fSDimitry Andric // subdirectory (#include "foo/bar.h") and a subsequent include of "baz.h" 9335f757f3fSDimitry Andric // should resolve to "whatever/foo/baz.h". This search is not done for <> 9345f757f3fSDimitry Andric // headers. 9355f757f3fSDimitry Andric if (!Includers.empty() && !isAngled) { 9360b57cec5SDimitry Andric SmallString<1024> TmpDir; 9370b57cec5SDimitry Andric bool First = true; 9380b57cec5SDimitry Andric for (const auto &IncluderAndDir : Includers) { 9395f757f3fSDimitry Andric OptionalFileEntryRef Includer = IncluderAndDir.first; 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric // Concatenate the requested file onto the directory. 94206c3fb27SDimitry Andric TmpDir = IncluderAndDir.second.getName(); 9435f757f3fSDimitry Andric llvm::sys::path::append(TmpDir, Filename); 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric // FIXME: We don't cache the result of getFileInfo across the call to 9460b57cec5SDimitry Andric // getFileAndSuggestModule, because it's a reference to an element of 9470b57cec5SDimitry Andric // a container that could be reallocated across this call. 9480b57cec5SDimitry Andric // 9490b57cec5SDimitry Andric // If we have no includer, that means we're processing a #include 9500b57cec5SDimitry Andric // from a module build. We should treat this as a system header if we're 9510b57cec5SDimitry Andric // building a [system] module. 952*0fca6ea1SDimitry Andric bool IncluderIsSystemHeader = [&]() { 953*0fca6ea1SDimitry Andric if (!Includer) 954*0fca6ea1SDimitry Andric return BuildSystemModule; 955*0fca6ea1SDimitry Andric const HeaderFileInfo *HFI = getExistingFileInfo(*Includer); 956*0fca6ea1SDimitry Andric assert(HFI && "includer without file info"); 957*0fca6ea1SDimitry Andric return HFI->DirInfo != SrcMgr::C_User; 958*0fca6ea1SDimitry Andric }(); 959bdd1243dSDimitry Andric if (OptionalFileEntryRef FE = getFileAndSuggestModule( 9600b57cec5SDimitry Andric TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, 9610b57cec5SDimitry Andric RequestingModule, SuggestedModule)) { 9620b57cec5SDimitry Andric if (!Includer) { 9630b57cec5SDimitry Andric assert(First && "only first includer can have no file"); 9640b57cec5SDimitry Andric return FE; 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric // Leave CurDir unset. 9680b57cec5SDimitry Andric // This file is a system header or C++ unfriendly if the old file is. 9690b57cec5SDimitry Andric // 9700b57cec5SDimitry Andric // Note that we only use one of FromHFI/ToHFI at once, due to potential 9710b57cec5SDimitry Andric // reallocation of the underlying vector potentially making the first 9720b57cec5SDimitry Andric // reference binding dangling. 973*0fca6ea1SDimitry Andric const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer); 974*0fca6ea1SDimitry Andric assert(FromHFI && "includer without file info"); 975*0fca6ea1SDimitry Andric unsigned DirInfo = FromHFI->DirInfo; 976*0fca6ea1SDimitry Andric bool IndexHeaderMapHeader = FromHFI->IndexHeaderMapHeader; 977*0fca6ea1SDimitry Andric StringRef Framework = FromHFI->Framework; 9780b57cec5SDimitry Andric 9795f757f3fSDimitry Andric HeaderFileInfo &ToHFI = getFileInfo(*FE); 9800b57cec5SDimitry Andric ToHFI.DirInfo = DirInfo; 9810b57cec5SDimitry Andric ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; 9820b57cec5SDimitry Andric ToHFI.Framework = Framework; 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric if (SearchPath) { 98506c3fb27SDimitry Andric StringRef SearchPathRef(IncluderAndDir.second.getName()); 9860b57cec5SDimitry Andric SearchPath->clear(); 9870b57cec5SDimitry Andric SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric if (RelativePath) { 9900b57cec5SDimitry Andric RelativePath->clear(); 9910b57cec5SDimitry Andric RelativePath->append(Filename.begin(), Filename.end()); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric if (First) { 9940b57cec5SDimitry Andric diagnoseFrameworkInclude(Diags, IncludeLoc, 99506c3fb27SDimitry Andric IncluderAndDir.second.getName(), Filename, 9965f757f3fSDimitry Andric *FE); 9970b57cec5SDimitry Andric return FE; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric // Otherwise, we found the path via MSVC header search rules. If 10010b57cec5SDimitry Andric // -Wmsvc-include is enabled, we have to keep searching to see if we 10020b57cec5SDimitry Andric // would've found this header in -I or -isystem directories. 10030b57cec5SDimitry Andric if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) { 10040b57cec5SDimitry Andric return FE; 10050b57cec5SDimitry Andric } else { 1006e8d8bef9SDimitry Andric MSFE = FE; 10070b57cec5SDimitry Andric if (SuggestedModule) { 10080b57cec5SDimitry Andric MSSuggestedModule = *SuggestedModule; 10090b57cec5SDimitry Andric *SuggestedModule = ModuleMap::KnownHeader(); 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric break; 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric First = false; 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric CurDir = nullptr; 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric // If this is a system #include, ignore the user #include locs. 102181ad6265SDimitry Andric ConstSearchDirIterator It = 102281ad6265SDimitry Andric isAngled ? angled_dir_begin() : search_dir_begin(); 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric // If this is a #include_next request, start searching after the directory the 10250b57cec5SDimitry Andric // file was found in. 10260b57cec5SDimitry Andric if (FromDir) 102781ad6265SDimitry Andric It = FromDir; 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric // Cache all of the lookups performed by this method. Many headers are 10300b57cec5SDimitry Andric // multiply included, and the "pragma once" optimization prevents them from 10310b57cec5SDimitry Andric // being relex/pp'd, but they would still have to search through a 10320b57cec5SDimitry Andric // (potentially huge) series of SearchDirs to find it. 10330b57cec5SDimitry Andric LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; 10340b57cec5SDimitry Andric 103581ad6265SDimitry Andric ConstSearchDirIterator NextIt = std::next(It); 103681ad6265SDimitry Andric 1037bdd1243dSDimitry Andric if (!SkipCache) { 103806c3fb27SDimitry Andric if (CacheLookup.StartIt == NextIt && 103906c3fb27SDimitry Andric CacheLookup.RequestingModule == RequestingModule) { 1040bdd1243dSDimitry Andric // HIT: Skip querying potentially lots of directories for this lookup. 104181ad6265SDimitry Andric if (CacheLookup.HitIt) 104281ad6265SDimitry Andric It = CacheLookup.HitIt; 10430b57cec5SDimitry Andric if (CacheLookup.MappedName) { 10440b57cec5SDimitry Andric Filename = CacheLookup.MappedName; 10450b57cec5SDimitry Andric if (IsMapped) 10460b57cec5SDimitry Andric *IsMapped = true; 10470b57cec5SDimitry Andric } 10480b57cec5SDimitry Andric } else { 1049bdd1243dSDimitry Andric // MISS: This is the first query, or the previous query didn't match 1050bdd1243dSDimitry Andric // our search start. We will fill in our found location below, so prime 1051bdd1243dSDimitry Andric // the start point value. 105206c3fb27SDimitry Andric CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt); 1053bdd1243dSDimitry Andric 1054bdd1243dSDimitry Andric if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) { 1055bdd1243dSDimitry Andric // Handle cold misses of user includes in the presence of many header 1056bdd1243dSDimitry Andric // maps. We avoid searching perhaps thousands of header maps by 1057bdd1243dSDimitry Andric // jumping directly to the correct one or jumping beyond all of them. 1058bdd1243dSDimitry Andric auto Iter = SearchDirHeaderMapIndex.find(Filename.lower()); 1059bdd1243dSDimitry Andric if (Iter == SearchDirHeaderMapIndex.end()) 1060bdd1243dSDimitry Andric // Not in index => Skip to first SearchDir after initial header maps 1061bdd1243dSDimitry Andric It = search_dir_nth(FirstNonHeaderMapSearchDirIdx); 1062bdd1243dSDimitry Andric else 1063bdd1243dSDimitry Andric // In index => Start with a specific header map 1064bdd1243dSDimitry Andric It = search_dir_nth(Iter->second); 10650b57cec5SDimitry Andric } 1066bdd1243dSDimitry Andric } 106706c3fb27SDimitry Andric } else { 106806c3fb27SDimitry Andric CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt); 106906c3fb27SDimitry Andric } 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric SmallString<64> MappedName; 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric // Check each directory in sequence to see if it contains this file. 107481ad6265SDimitry Andric for (; It != search_dir_end(); ++It) { 10750b57cec5SDimitry Andric bool InUserSpecifiedSystemFramework = false; 1076a7dea167SDimitry Andric bool IsInHeaderMap = false; 10770b57cec5SDimitry Andric bool IsFrameworkFoundInDir = false; 1078bdd1243dSDimitry Andric OptionalFileEntryRef File = It->LookupFile( 10790b57cec5SDimitry Andric Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, 10800b57cec5SDimitry Andric SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, 1081bdd1243dSDimitry Andric IsInHeaderMap, MappedName, OpenFile); 1082a7dea167SDimitry Andric if (!MappedName.empty()) { 1083a7dea167SDimitry Andric assert(IsInHeaderMap && "MappedName should come from a header map"); 10840b57cec5SDimitry Andric CacheLookup.MappedName = 1085a7dea167SDimitry Andric copyString(MappedName, LookupFileCache.getAllocator()); 10860b57cec5SDimitry Andric } 1087a7dea167SDimitry Andric if (IsMapped) 1088a7dea167SDimitry Andric // A filename is mapped when a header map remapped it to a relative path 1089a7dea167SDimitry Andric // used in subsequent header search or to an absolute path pointing to an 1090a7dea167SDimitry Andric // existing file. 1091a7dea167SDimitry Andric *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File)); 10920b57cec5SDimitry Andric if (IsFrameworkFound) 10930b57cec5SDimitry Andric // Because we keep a filename remapped for subsequent search directory 10940b57cec5SDimitry Andric // lookups, ignore IsFrameworkFoundInDir after the first remapping and not 10950b57cec5SDimitry Andric // just for remapping in a current search directory. 10960b57cec5SDimitry Andric *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName); 1097a7dea167SDimitry Andric if (!File) 1098a7dea167SDimitry Andric continue; 10990b57cec5SDimitry Andric 110081ad6265SDimitry Andric CurDir = It; 110181ad6265SDimitry Andric 11025f757f3fSDimitry Andric IncludeNames[*File] = Filename; 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric // This file is a system header or C++ unfriendly if the dir is. 11055f757f3fSDimitry Andric HeaderFileInfo &HFI = getFileInfo(*File); 11060b57cec5SDimitry Andric HFI.DirInfo = CurDir->getDirCharacteristic(); 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric // If the directory characteristic is User but this framework was 11090b57cec5SDimitry Andric // user-specified to be treated as a system framework, promote the 11100b57cec5SDimitry Andric // characteristic. 11110b57cec5SDimitry Andric if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework) 11120b57cec5SDimitry Andric HFI.DirInfo = SrcMgr::C_System; 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric // If the filename matches a known system header prefix, override 11150b57cec5SDimitry Andric // whether the file is a system header. 11160b57cec5SDimitry Andric for (unsigned j = SystemHeaderPrefixes.size(); j; --j) { 11175f757f3fSDimitry Andric if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) { 11180b57cec5SDimitry Andric HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System 11190b57cec5SDimitry Andric : SrcMgr::C_User; 11200b57cec5SDimitry Andric break; 11210b57cec5SDimitry Andric } 11220b57cec5SDimitry Andric } 11230b57cec5SDimitry Andric 112481ad6265SDimitry Andric // Set the `Framework` info if this file is in a header map with framework 112581ad6265SDimitry Andric // style include spelling or found in a framework dir. The header map case 112681ad6265SDimitry Andric // is possible when building frameworks which use header maps. 1127349cc55cSDimitry Andric if (CurDir->isHeaderMap() && isAngled) { 11280b57cec5SDimitry Andric size_t SlashPos = Filename.find('/'); 1129349cc55cSDimitry Andric if (SlashPos != StringRef::npos) 1130349cc55cSDimitry Andric HFI.Framework = 1131349cc55cSDimitry Andric getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos)); 1132349cc55cSDimitry Andric if (CurDir->isIndexHeaderMap()) 11330b57cec5SDimitry Andric HFI.IndexHeaderMapHeader = 1; 113481ad6265SDimitry Andric } else if (CurDir->isFramework()) { 113581ad6265SDimitry Andric size_t SlashPos = Filename.find('/'); 113681ad6265SDimitry Andric if (SlashPos != StringRef::npos) 113781ad6265SDimitry Andric HFI.Framework = 113881ad6265SDimitry Andric getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos)); 11390b57cec5SDimitry Andric } 11400b57cec5SDimitry Andric 11415f757f3fSDimitry Andric if (checkMSVCHeaderSearch(Diags, MSFE, &File->getFileEntry(), IncludeLoc)) { 11420b57cec5SDimitry Andric if (SuggestedModule) 11430b57cec5SDimitry Andric *SuggestedModule = MSSuggestedModule; 11440b57cec5SDimitry Andric return MSFE; 11450b57cec5SDimitry Andric } 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; 11480b57cec5SDimitry Andric if (!Includers.empty()) 11495f757f3fSDimitry Andric diagnoseFrameworkInclude(Diags, IncludeLoc, 11505f757f3fSDimitry Andric Includers.front().second.getName(), Filename, 11515f757f3fSDimitry Andric *File, isAngled, FoundByHeaderMap); 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric // Remember this location for the next lookup we do. 115481ad6265SDimitry Andric cacheLookupSuccess(CacheLookup, It, IncludeLoc); 1155a7dea167SDimitry Andric return File; 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric // If we are including a file with a quoted include "foo.h" from inside 11590b57cec5SDimitry Andric // a header in a framework that is currently being built, and we couldn't 11600b57cec5SDimitry Andric // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where 11610b57cec5SDimitry Andric // "Foo" is the name of the framework in which the including header was found. 11620b57cec5SDimitry Andric if (!Includers.empty() && Includers.front().first && !isAngled && 1163349cc55cSDimitry Andric !Filename.contains('/')) { 1164*0fca6ea1SDimitry Andric const HeaderFileInfo *IncludingHFI = 1165*0fca6ea1SDimitry Andric getExistingFileInfo(*Includers.front().first); 1166*0fca6ea1SDimitry Andric assert(IncludingHFI && "includer without file info"); 1167*0fca6ea1SDimitry Andric if (IncludingHFI->IndexHeaderMapHeader) { 11680b57cec5SDimitry Andric SmallString<128> ScratchFilename; 1169*0fca6ea1SDimitry Andric ScratchFilename += IncludingHFI->Framework; 11700b57cec5SDimitry Andric ScratchFilename += '/'; 11710b57cec5SDimitry Andric ScratchFilename += Filename; 11720b57cec5SDimitry Andric 1173bdd1243dSDimitry Andric OptionalFileEntryRef File = LookupFile( 117404eeddc0SDimitry Andric ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, &CurDir, 11750b57cec5SDimitry Andric Includers.front(), SearchPath, RelativePath, RequestingModule, 11760b57cec5SDimitry Andric SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); 11770b57cec5SDimitry Andric 11785f757f3fSDimitry Andric if (checkMSVCHeaderSearch(Diags, MSFE, 1179a7dea167SDimitry Andric File ? &File->getFileEntry() : nullptr, 1180a7dea167SDimitry Andric IncludeLoc)) { 11810b57cec5SDimitry Andric if (SuggestedModule) 11820b57cec5SDimitry Andric *SuggestedModule = MSSuggestedModule; 11830b57cec5SDimitry Andric return MSFE; 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 1186349cc55cSDimitry Andric cacheLookupSuccess(LookupFileCache[Filename], 118781ad6265SDimitry Andric LookupFileCache[ScratchFilename].HitIt, IncludeLoc); 11880b57cec5SDimitry Andric // FIXME: SuggestedModule. 1189a7dea167SDimitry Andric return File; 11900b57cec5SDimitry Andric } 11910b57cec5SDimitry Andric } 11920b57cec5SDimitry Andric 11935f757f3fSDimitry Andric if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) { 11940b57cec5SDimitry Andric if (SuggestedModule) 11950b57cec5SDimitry Andric *SuggestedModule = MSSuggestedModule; 11960b57cec5SDimitry Andric return MSFE; 11970b57cec5SDimitry Andric } 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric // Otherwise, didn't find it. Remember we didn't find this. 120081ad6265SDimitry Andric CacheLookup.HitIt = search_dir_end(); 1201bdd1243dSDimitry Andric return std::nullopt; 12020b57cec5SDimitry Andric } 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric /// LookupSubframeworkHeader - Look up a subframework for the specified 12050b57cec5SDimitry Andric /// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from 12060b57cec5SDimitry Andric /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 12070b57cec5SDimitry Andric /// is a subframework within Carbon.framework. If so, return the FileEntry 12080b57cec5SDimitry Andric /// for the designated file, otherwise return null. 1209bdd1243dSDimitry Andric OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader( 12105f757f3fSDimitry Andric StringRef Filename, FileEntryRef ContextFileEnt, 1211a7dea167SDimitry Andric SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, 1212a7dea167SDimitry Andric Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { 12130b57cec5SDimitry Andric // Framework names must have a '/' in the filename. Find it. 12140b57cec5SDimitry Andric // FIXME: Should we permit '\' on Windows? 12150b57cec5SDimitry Andric size_t SlashPos = Filename.find('/'); 1216a7dea167SDimitry Andric if (SlashPos == StringRef::npos) 1217bdd1243dSDimitry Andric return std::nullopt; 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric // Look up the base framework name of the ContextFileEnt. 12205f757f3fSDimitry Andric StringRef ContextName = ContextFileEnt.getName(); 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric // If the context info wasn't a framework, couldn't be a subframework. 12230b57cec5SDimitry Andric const unsigned DotFrameworkLen = 10; 12240b57cec5SDimitry Andric auto FrameworkPos = ContextName.find(".framework"); 12250b57cec5SDimitry Andric if (FrameworkPos == StringRef::npos || 12260b57cec5SDimitry Andric (ContextName[FrameworkPos + DotFrameworkLen] != '/' && 12270b57cec5SDimitry Andric ContextName[FrameworkPos + DotFrameworkLen] != '\\')) 1228bdd1243dSDimitry Andric return std::nullopt; 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + 12310b57cec5SDimitry Andric FrameworkPos + 12320b57cec5SDimitry Andric DotFrameworkLen + 1); 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric // Append Frameworks/HIToolbox.framework/ 12350b57cec5SDimitry Andric FrameworkName += "Frameworks/"; 12360b57cec5SDimitry Andric FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 12370b57cec5SDimitry Andric FrameworkName += ".framework/"; 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric auto &CacheLookup = 12400b57cec5SDimitry Andric *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos), 12410b57cec5SDimitry Andric FrameworkCacheEntry())).first; 12420b57cec5SDimitry Andric 12430b57cec5SDimitry Andric // Some other location? 12440b57cec5SDimitry Andric if (CacheLookup.second.Directory && 12450b57cec5SDimitry Andric CacheLookup.first().size() == FrameworkName.size() && 12460b57cec5SDimitry Andric memcmp(CacheLookup.first().data(), &FrameworkName[0], 12470b57cec5SDimitry Andric CacheLookup.first().size()) != 0) 1248bdd1243dSDimitry Andric return std::nullopt; 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric // Cache subframework. 12510b57cec5SDimitry Andric if (!CacheLookup.second.Directory) { 12520b57cec5SDimitry Andric ++NumSubFrameworkLookups; 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric // If the framework dir doesn't exist, we fail. 125581ad6265SDimitry Andric auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName); 1256a7dea167SDimitry Andric if (!Dir) 1257bdd1243dSDimitry Andric return std::nullopt; 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric // Otherwise, if it does, remember that this is the right direntry for this 12600b57cec5SDimitry Andric // framework. 126181ad6265SDimitry Andric CacheLookup.second.Directory = Dir; 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andric if (RelativePath) { 12660b57cec5SDimitry Andric RelativePath->clear(); 12670b57cec5SDimitry Andric RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 12710b57cec5SDimitry Andric SmallString<1024> HeadersFilename(FrameworkName); 12720b57cec5SDimitry Andric HeadersFilename += "Headers/"; 12730b57cec5SDimitry Andric if (SearchPath) { 12740b57cec5SDimitry Andric SearchPath->clear(); 12750b57cec5SDimitry Andric // Without trailing '/'. 12760b57cec5SDimitry Andric SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 12770b57cec5SDimitry Andric } 12780b57cec5SDimitry Andric 12790b57cec5SDimitry Andric HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 1280a7dea167SDimitry Andric auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); 1281a7dea167SDimitry Andric if (!File) { 12820b57cec5SDimitry Andric // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 12830b57cec5SDimitry Andric HeadersFilename = FrameworkName; 12840b57cec5SDimitry Andric HeadersFilename += "PrivateHeaders/"; 12850b57cec5SDimitry Andric if (SearchPath) { 12860b57cec5SDimitry Andric SearchPath->clear(); 12870b57cec5SDimitry Andric // Without trailing '/'. 12880b57cec5SDimitry Andric SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 12890b57cec5SDimitry Andric } 12900b57cec5SDimitry Andric 12910b57cec5SDimitry Andric HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 1292a7dea167SDimitry Andric File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); 1293a7dea167SDimitry Andric 1294a7dea167SDimitry Andric if (!File) 1295bdd1243dSDimitry Andric return std::nullopt; 12960b57cec5SDimitry Andric } 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric // This file is a system header or C++ unfriendly if the old file is. 1299*0fca6ea1SDimitry Andric const HeaderFileInfo *ContextHFI = getExistingFileInfo(ContextFileEnt); 1300*0fca6ea1SDimitry Andric assert(ContextHFI && "context file without file info"); 1301*0fca6ea1SDimitry Andric // Note that the temporary 'DirInfo' is required here, as the call to 1302*0fca6ea1SDimitry Andric // getFileInfo could resize the vector and might invalidate 'ContextHFI'. 1303*0fca6ea1SDimitry Andric unsigned DirInfo = ContextHFI->DirInfo; 13045f757f3fSDimitry Andric getFileInfo(*File).DirInfo = DirInfo; 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andric FrameworkName.pop_back(); // remove the trailing '/' 130706c3fb27SDimitry Andric if (!findUsableModuleForFrameworkHeader(*File, FrameworkName, 1308a7dea167SDimitry Andric RequestingModule, SuggestedModule, 1309a7dea167SDimitry Andric /*IsSystem*/ false)) 1310bdd1243dSDimitry Andric return std::nullopt; 13110b57cec5SDimitry Andric 1312a7dea167SDimitry Andric return *File; 13130b57cec5SDimitry Andric } 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13160b57cec5SDimitry Andric // File Info Management. 13170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13180b57cec5SDimitry Andric 1319*0fca6ea1SDimitry Andric static bool moduleMembershipNeedsMerge(const HeaderFileInfo *HFI, 1320*0fca6ea1SDimitry Andric ModuleMap::ModuleHeaderRole Role) { 1321*0fca6ea1SDimitry Andric if (ModuleMap::isModular(Role)) 1322*0fca6ea1SDimitry Andric return !HFI->isModuleHeader || HFI->isTextualModuleHeader; 1323*0fca6ea1SDimitry Andric if (!HFI->isModuleHeader && (Role & ModuleMap::TextualHeader)) 1324*0fca6ea1SDimitry Andric return !HFI->isTextualModuleHeader; 1325*0fca6ea1SDimitry Andric return false; 1326*0fca6ea1SDimitry Andric } 1327*0fca6ea1SDimitry Andric 1328*0fca6ea1SDimitry Andric static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI, 1329*0fca6ea1SDimitry Andric bool isModuleHeader, 1330*0fca6ea1SDimitry Andric bool isTextualModuleHeader) { 1331*0fca6ea1SDimitry Andric HFI.isModuleHeader |= isModuleHeader; 1332*0fca6ea1SDimitry Andric if (HFI.isModuleHeader) 1333*0fca6ea1SDimitry Andric HFI.isTextualModuleHeader = false; 1334*0fca6ea1SDimitry Andric else 1335*0fca6ea1SDimitry Andric HFI.isTextualModuleHeader |= isTextualModuleHeader; 1336*0fca6ea1SDimitry Andric } 1337*0fca6ea1SDimitry Andric 1338*0fca6ea1SDimitry Andric void HeaderFileInfo::mergeModuleMembership(ModuleMap::ModuleHeaderRole Role) { 1339*0fca6ea1SDimitry Andric mergeHeaderFileInfoModuleBits(*this, ModuleMap::isModular(Role), 1340*0fca6ea1SDimitry Andric (Role & ModuleMap::TextualHeader)); 1341*0fca6ea1SDimitry Andric } 1342*0fca6ea1SDimitry Andric 13430b57cec5SDimitry Andric /// Merge the header file info provided by \p OtherHFI into the current 13440b57cec5SDimitry Andric /// header file info (\p HFI) 13450b57cec5SDimitry Andric static void mergeHeaderFileInfo(HeaderFileInfo &HFI, 13460b57cec5SDimitry Andric const HeaderFileInfo &OtherHFI) { 13470b57cec5SDimitry Andric assert(OtherHFI.External && "expected to merge external HFI"); 13480b57cec5SDimitry Andric 13490b57cec5SDimitry Andric HFI.isImport |= OtherHFI.isImport; 13500b57cec5SDimitry Andric HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; 1351*0fca6ea1SDimitry Andric mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader, 1352*0fca6ea1SDimitry Andric OtherHFI.isTextualModuleHeader); 13530b57cec5SDimitry Andric 1354*0fca6ea1SDimitry Andric if (!HFI.LazyControllingMacro.isValid()) 1355*0fca6ea1SDimitry Andric HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro; 13560b57cec5SDimitry Andric 13570b57cec5SDimitry Andric HFI.DirInfo = OtherHFI.DirInfo; 13580b57cec5SDimitry Andric HFI.External = (!HFI.IsValid || HFI.External); 13590b57cec5SDimitry Andric HFI.IsValid = true; 13600b57cec5SDimitry Andric HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; 13610b57cec5SDimitry Andric 13620b57cec5SDimitry Andric if (HFI.Framework.empty()) 13630b57cec5SDimitry Andric HFI.Framework = OtherHFI.Framework; 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric 13665f757f3fSDimitry Andric HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) { 13675f757f3fSDimitry Andric if (FE.getUID() >= FileInfo.size()) 13685f757f3fSDimitry Andric FileInfo.resize(FE.getUID() + 1); 13690b57cec5SDimitry Andric 13705f757f3fSDimitry Andric HeaderFileInfo *HFI = &FileInfo[FE.getUID()]; 13710b57cec5SDimitry Andric // FIXME: Use a generation count to check whether this is really up to date. 13720b57cec5SDimitry Andric if (ExternalSource && !HFI->Resolved) { 13730b57cec5SDimitry Andric auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); 1374e8d8bef9SDimitry Andric if (ExternalHFI.IsValid) { 1375e8d8bef9SDimitry Andric HFI->Resolved = true; 13760b57cec5SDimitry Andric if (ExternalHFI.External) 13770b57cec5SDimitry Andric mergeHeaderFileInfo(*HFI, ExternalHFI); 13780b57cec5SDimitry Andric } 1379e8d8bef9SDimitry Andric } 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric HFI->IsValid = true; 1382*0fca6ea1SDimitry Andric // We assume the caller has local information about this header file, so it's 1383*0fca6ea1SDimitry Andric // no longer strictly external. 13840b57cec5SDimitry Andric HFI->External = false; 13850b57cec5SDimitry Andric return *HFI; 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric 1388*0fca6ea1SDimitry Andric const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const { 13890b57cec5SDimitry Andric HeaderFileInfo *HFI; 13900b57cec5SDimitry Andric if (ExternalSource) { 1391*0fca6ea1SDimitry Andric if (FE.getUID() >= FileInfo.size()) 13925f757f3fSDimitry Andric FileInfo.resize(FE.getUID() + 1); 13930b57cec5SDimitry Andric 13945f757f3fSDimitry Andric HFI = &FileInfo[FE.getUID()]; 1395*0fca6ea1SDimitry Andric // FIXME: Use a generation count to check whether this is really up to date. 13960b57cec5SDimitry Andric if (!HFI->Resolved) { 13970b57cec5SDimitry Andric auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); 1398e8d8bef9SDimitry Andric if (ExternalHFI.IsValid) { 1399e8d8bef9SDimitry Andric HFI->Resolved = true; 14000b57cec5SDimitry Andric if (ExternalHFI.External) 14010b57cec5SDimitry Andric mergeHeaderFileInfo(*HFI, ExternalHFI); 14020b57cec5SDimitry Andric } 1403e8d8bef9SDimitry Andric } 1404*0fca6ea1SDimitry Andric } else if (FE.getUID() < FileInfo.size()) { 14055f757f3fSDimitry Andric HFI = &FileInfo[FE.getUID()]; 1406*0fca6ea1SDimitry Andric } else { 1407*0fca6ea1SDimitry Andric HFI = nullptr; 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric 1410*0fca6ea1SDimitry Andric return (HFI && HFI->IsValid) ? HFI : nullptr; 1411*0fca6ea1SDimitry Andric } 14120b57cec5SDimitry Andric 1413*0fca6ea1SDimitry Andric const HeaderFileInfo * 1414*0fca6ea1SDimitry Andric HeaderSearch::getExistingLocalFileInfo(FileEntryRef FE) const { 1415*0fca6ea1SDimitry Andric HeaderFileInfo *HFI; 1416*0fca6ea1SDimitry Andric if (FE.getUID() < FileInfo.size()) { 1417*0fca6ea1SDimitry Andric HFI = &FileInfo[FE.getUID()]; 1418*0fca6ea1SDimitry Andric } else { 1419*0fca6ea1SDimitry Andric HFI = nullptr; 1420*0fca6ea1SDimitry Andric } 1421*0fca6ea1SDimitry Andric 1422*0fca6ea1SDimitry Andric return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr; 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric 14255f757f3fSDimitry Andric bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const { 14265ffd83dbSDimitry Andric // Check if we've entered this file and found an include guard or #pragma 14275ffd83dbSDimitry Andric // once. Note that we dor't check for #import, because that's not a property 14285ffd83dbSDimitry Andric // of the file itself. 14290b57cec5SDimitry Andric if (auto *HFI = getExistingFileInfo(File)) 1430*0fca6ea1SDimitry Andric return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid(); 14310b57cec5SDimitry Andric return false; 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric 14345f757f3fSDimitry Andric void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE, 14350b57cec5SDimitry Andric ModuleMap::ModuleHeaderRole Role, 14360b57cec5SDimitry Andric bool isCompilingModuleHeader) { 14370b57cec5SDimitry Andric // Don't mark the file info as non-external if there's nothing to change. 14380b57cec5SDimitry Andric if (!isCompilingModuleHeader) { 1439*0fca6ea1SDimitry Andric if ((Role & ModuleMap::ExcludedHeader)) 14400b57cec5SDimitry Andric return; 14410b57cec5SDimitry Andric auto *HFI = getExistingFileInfo(FE); 1442*0fca6ea1SDimitry Andric if (HFI && !moduleMembershipNeedsMerge(HFI, Role)) 14430b57cec5SDimitry Andric return; 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric 14460b57cec5SDimitry Andric auto &HFI = getFileInfo(FE); 1447*0fca6ea1SDimitry Andric HFI.mergeModuleMembership(Role); 14480b57cec5SDimitry Andric HFI.isCompilingModuleHeader |= isCompilingModuleHeader; 14490b57cec5SDimitry Andric } 14500b57cec5SDimitry Andric 14510b57cec5SDimitry Andric bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, 14525f757f3fSDimitry Andric FileEntryRef File, bool isImport, 1453349cc55cSDimitry Andric bool ModulesEnabled, Module *M, 1454349cc55cSDimitry Andric bool &IsFirstIncludeOfFile) { 1455*0fca6ea1SDimitry Andric // An include file should be entered if either: 1456*0fca6ea1SDimitry Andric // 1. This is the first include of the file. 1457*0fca6ea1SDimitry Andric // 2. This file can be included multiple times, that is it's not an 1458*0fca6ea1SDimitry Andric // "include-once" file. 1459*0fca6ea1SDimitry Andric // 1460*0fca6ea1SDimitry Andric // Include-once is controlled by these preprocessor directives. 1461*0fca6ea1SDimitry Andric // 1462*0fca6ea1SDimitry Andric // #pragma once 1463*0fca6ea1SDimitry Andric // This directive is in the include file, and marks it as an include-once 1464*0fca6ea1SDimitry Andric // file. 1465*0fca6ea1SDimitry Andric // 1466*0fca6ea1SDimitry Andric // #import <file> 1467*0fca6ea1SDimitry Andric // This directive is in the includer, and indicates that the include file 1468*0fca6ea1SDimitry Andric // should only be entered if this is the first include. 1469*0fca6ea1SDimitry Andric ++NumIncluded; 1470349cc55cSDimitry Andric IsFirstIncludeOfFile = false; 14710b57cec5SDimitry Andric HeaderFileInfo &FileInfo = getFileInfo(File); 14720b57cec5SDimitry Andric 1473*0fca6ea1SDimitry Andric auto MaybeReenterImportedFile = [&]() -> bool { 1474*0fca6ea1SDimitry Andric // Modules add a wrinkle though: what's included isn't necessarily visible. 1475*0fca6ea1SDimitry Andric // Consider this module. 1476*0fca6ea1SDimitry Andric // module Example { 1477*0fca6ea1SDimitry Andric // module A { header "a.h" export * } 1478*0fca6ea1SDimitry Andric // module B { header "b.h" export * } 1479*0fca6ea1SDimitry Andric // } 1480*0fca6ea1SDimitry Andric // b.h includes c.h. The main file includes a.h, which will trigger a module 1481*0fca6ea1SDimitry Andric // build of Example, and c.h will be included. However, c.h isn't visible to 1482*0fca6ea1SDimitry Andric // the main file. Normally this is fine, the main file can just include c.h 1483*0fca6ea1SDimitry Andric // if it needs it. If c.h is in a module, the include will translate into a 1484*0fca6ea1SDimitry Andric // module import, this function will be skipped, and everything will work as 1485*0fca6ea1SDimitry Andric // expected. However, if c.h is not in a module (or is `textual`), then this 1486*0fca6ea1SDimitry Andric // function will run. If c.h is include-once, it will not be entered from 1487*0fca6ea1SDimitry Andric // the main file and it will still not be visible. 14887a6dacacSDimitry Andric 1489*0fca6ea1SDimitry Andric // If modules aren't enabled then there's no visibility issue. Always 1490*0fca6ea1SDimitry Andric // respect `#pragma once`. 1491*0fca6ea1SDimitry Andric if (!ModulesEnabled || FileInfo.isPragmaOnce) 14920b57cec5SDimitry Andric return false; 1493*0fca6ea1SDimitry Andric 14940b57cec5SDimitry Andric // Ensure FileInfo bits are up to date. 14950b57cec5SDimitry Andric ModMap.resolveHeaderDirectives(File); 14960b57cec5SDimitry Andric 1497*0fca6ea1SDimitry Andric // This brings up a subtlety of #import - it's not a very good indicator of 1498*0fca6ea1SDimitry Andric // include-once. Developers are often unaware of the difference between 1499*0fca6ea1SDimitry Andric // #include and #import, and tend to use one or the other indiscrimiately. 1500*0fca6ea1SDimitry Andric // In order to support #include on include-once headers that lack macro 1501*0fca6ea1SDimitry Andric // guards and `#pragma once` (which is the vast majority of Objective-C 1502*0fca6ea1SDimitry Andric // headers), if a file is ever included with #import, it's marked as 1503*0fca6ea1SDimitry Andric // isImport in the HeaderFileInfo and treated as include-once. This allows 1504*0fca6ea1SDimitry Andric // #include to work in Objective-C. 1505*0fca6ea1SDimitry Andric // #include <Foundation/Foundation.h> 1506*0fca6ea1SDimitry Andric // #include <Foundation/NSString.h> 1507*0fca6ea1SDimitry Andric // Foundation.h has an #import of NSString.h, and so the second #include is 1508*0fca6ea1SDimitry Andric // skipped even though NSString.h has no `#pragma once` and no macro guard. 1509*0fca6ea1SDimitry Andric // 1510*0fca6ea1SDimitry Andric // However, this helpfulness causes problems with modules. If c.h is not an 1511*0fca6ea1SDimitry Andric // include-once file, but something included it with #import anyway (as is 1512*0fca6ea1SDimitry Andric // typical in Objective-C code), this include will be skipped and c.h will 1513*0fca6ea1SDimitry Andric // not be visible. Consider it not include-once if it is a `textual` header 1514*0fca6ea1SDimitry Andric // in a module. 1515*0fca6ea1SDimitry Andric if (FileInfo.isTextualModuleHeader) 1516*0fca6ea1SDimitry Andric return true; 1517*0fca6ea1SDimitry Andric 1518*0fca6ea1SDimitry Andric if (FileInfo.isCompilingModuleHeader) { 1519*0fca6ea1SDimitry Andric // It's safer to re-enter a file whose module is being built because its 1520*0fca6ea1SDimitry Andric // declarations will still be scoped to a single module. 1521*0fca6ea1SDimitry Andric if (FileInfo.isModuleHeader) { 1522*0fca6ea1SDimitry Andric // Headers marked as "builtin" are covered by the system module maps 1523*0fca6ea1SDimitry Andric // rather than the builtin ones. Some versions of the Darwin module fail 1524*0fca6ea1SDimitry Andric // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these 1525*0fca6ea1SDimitry Andric // files while building their module to allow them to function properly. 1526*0fca6ea1SDimitry Andric if (ModMap.isBuiltinHeader(File)) 1527*0fca6ea1SDimitry Andric return true; 1528*0fca6ea1SDimitry Andric } else { 1529*0fca6ea1SDimitry Andric // Files that are excluded from their module can potentially be 1530*0fca6ea1SDimitry Andric // re-entered from their own module. This might cause redeclaration 1531*0fca6ea1SDimitry Andric // errors if another module saw this file first, but there's a 1532*0fca6ea1SDimitry Andric // reasonable chance that its module will build first. However if 1533*0fca6ea1SDimitry Andric // there's no controlling macro, then trust the #import and assume this 1534*0fca6ea1SDimitry Andric // really is an include-once file. 1535*0fca6ea1SDimitry Andric if (FileInfo.getControllingMacro(ExternalLookup)) 1536*0fca6ea1SDimitry Andric return true; 1537*0fca6ea1SDimitry Andric } 1538*0fca6ea1SDimitry Andric } 1539*0fca6ea1SDimitry Andric // If the include file has a macro guard, then it might still not be 1540*0fca6ea1SDimitry Andric // re-entered if the controlling macro is visibly defined. e.g. another 1541*0fca6ea1SDimitry Andric // header in the module being built included this file and local submodule 1542*0fca6ea1SDimitry Andric // visibility is not enabled. 1543*0fca6ea1SDimitry Andric 1544*0fca6ea1SDimitry Andric // It might be tempting to re-enter the include-once file if it's not 1545*0fca6ea1SDimitry Andric // visible in an attempt to make it visible. However this will still cause 1546*0fca6ea1SDimitry Andric // redeclaration errors against the known-but-not-visible declarations. The 1547*0fca6ea1SDimitry Andric // include file not being visible will most likely cause "undefined x" 1548*0fca6ea1SDimitry Andric // errors, but at least there's a slim chance of compilation succeeding. 1549*0fca6ea1SDimitry Andric return false; 15500b57cec5SDimitry Andric }; 15510b57cec5SDimitry Andric 1552*0fca6ea1SDimitry Andric if (isImport) { 1553*0fca6ea1SDimitry Andric // As discussed above, record that this file was ever `#import`ed, and treat 1554*0fca6ea1SDimitry Andric // it as an include-once file from here out. 1555*0fca6ea1SDimitry Andric FileInfo.isImport = true; 1556*0fca6ea1SDimitry Andric if (PP.alreadyIncluded(File) && !MaybeReenterImportedFile()) 15570b57cec5SDimitry Andric return false; 15580b57cec5SDimitry Andric } else { 1559*0fca6ea1SDimitry Andric // isPragmaOnce and isImport are only set after the file has been included 1560*0fca6ea1SDimitry Andric // at least once. If either are set then this is a repeat #include of an 1561*0fca6ea1SDimitry Andric // include-once file. 1562*0fca6ea1SDimitry Andric if (FileInfo.isPragmaOnce || 1563*0fca6ea1SDimitry Andric (FileInfo.isImport && !MaybeReenterImportedFile())) 15640b57cec5SDimitry Andric return false; 15650b57cec5SDimitry Andric } 15660b57cec5SDimitry Andric 1567*0fca6ea1SDimitry Andric // As a final optimization, check for a macro guard and skip entering the file 1568*0fca6ea1SDimitry Andric // if the controlling macro is defined. The macro guard will effectively erase 1569*0fca6ea1SDimitry Andric // the file's contents, and the include would have no effect other than to 1570*0fca6ea1SDimitry Andric // waste time opening and reading a file. 1571*0fca6ea1SDimitry Andric if (const IdentifierInfo *ControllingMacro = 1572*0fca6ea1SDimitry Andric FileInfo.getControllingMacro(ExternalLookup)) { 15730b57cec5SDimitry Andric // If the header corresponds to a module, check whether the macro is already 1574*0fca6ea1SDimitry Andric // defined in that module rather than checking all visible modules. This is 1575*0fca6ea1SDimitry Andric // mainly to cover corner cases where the same controlling macro is used in 1576*0fca6ea1SDimitry Andric // different files in multiple modules. 15770b57cec5SDimitry Andric if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M) 15780b57cec5SDimitry Andric : PP.isMacroDefined(ControllingMacro)) { 15790b57cec5SDimitry Andric ++NumMultiIncludeFileOptzn; 15800b57cec5SDimitry Andric return false; 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric 1584*0fca6ea1SDimitry Andric FileInfo.IsLocallyIncluded = true; 158504eeddc0SDimitry Andric IsFirstIncludeOfFile = PP.markIncluded(File); 15860b57cec5SDimitry Andric return true; 15870b57cec5SDimitry Andric } 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric size_t HeaderSearch::getTotalMemory() const { 15900b57cec5SDimitry Andric return SearchDirs.capacity() 15910b57cec5SDimitry Andric + llvm::capacity_in_bytes(FileInfo) 15920b57cec5SDimitry Andric + llvm::capacity_in_bytes(HeaderMaps) 15930b57cec5SDimitry Andric + LookupFileCache.getAllocator().getTotalMemory() 15940b57cec5SDimitry Andric + FrameworkMap.getAllocator().getTotalMemory(); 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 159781ad6265SDimitry Andric unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const { 159881ad6265SDimitry Andric return &DL - &*SearchDirs.begin(); 1599349cc55cSDimitry Andric } 1600349cc55cSDimitry Andric 16010b57cec5SDimitry Andric StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { 16020b57cec5SDimitry Andric return FrameworkNames.insert(Framework).first->first(); 16030b57cec5SDimitry Andric } 16040b57cec5SDimitry Andric 160581ad6265SDimitry Andric StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const { 160681ad6265SDimitry Andric auto It = IncludeNames.find(File); 160781ad6265SDimitry Andric if (It == IncludeNames.end()) 160881ad6265SDimitry Andric return {}; 160981ad6265SDimitry Andric return It->second; 161081ad6265SDimitry Andric } 161181ad6265SDimitry Andric 16120b57cec5SDimitry Andric bool HeaderSearch::hasModuleMap(StringRef FileName, 16130b57cec5SDimitry Andric const DirectoryEntry *Root, 16140b57cec5SDimitry Andric bool IsSystem) { 16150b57cec5SDimitry Andric if (!HSOpts->ImplicitModuleMaps) 16160b57cec5SDimitry Andric return false; 16170b57cec5SDimitry Andric 16180b57cec5SDimitry Andric SmallVector<const DirectoryEntry *, 2> FixUpDirectories; 16190b57cec5SDimitry Andric 16200b57cec5SDimitry Andric StringRef DirName = FileName; 16210b57cec5SDimitry Andric do { 16220b57cec5SDimitry Andric // Get the parent directory name. 16230b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName); 16240b57cec5SDimitry Andric if (DirName.empty()) 16250b57cec5SDimitry Andric return false; 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric // Determine whether this directory exists. 162881ad6265SDimitry Andric auto Dir = FileMgr.getOptionalDirectoryRef(DirName); 16290b57cec5SDimitry Andric if (!Dir) 16300b57cec5SDimitry Andric return false; 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric // Try to load the module map file in this directory. 1633a7dea167SDimitry Andric switch (loadModuleMapFile(*Dir, IsSystem, 163481ad6265SDimitry Andric llvm::sys::path::extension(Dir->getName()) == 16350b57cec5SDimitry Andric ".framework")) { 16360b57cec5SDimitry Andric case LMM_NewlyLoaded: 16370b57cec5SDimitry Andric case LMM_AlreadyLoaded: 16380b57cec5SDimitry Andric // Success. All of the directories we stepped through inherit this module 16390b57cec5SDimitry Andric // map file. 16400b57cec5SDimitry Andric for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I) 16410b57cec5SDimitry Andric DirectoryHasModuleMap[FixUpDirectories[I]] = true; 16420b57cec5SDimitry Andric return true; 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric case LMM_NoDirectory: 16450b57cec5SDimitry Andric case LMM_InvalidModuleMap: 16460b57cec5SDimitry Andric break; 16470b57cec5SDimitry Andric } 16480b57cec5SDimitry Andric 16490b57cec5SDimitry Andric // If we hit the top of our search, we're done. 1650a7dea167SDimitry Andric if (*Dir == Root) 16510b57cec5SDimitry Andric return false; 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric // Keep track of all of the directories we checked, so we can mark them as 16540b57cec5SDimitry Andric // having module maps if we eventually do find a module map. 1655a7dea167SDimitry Andric FixUpDirectories.push_back(*Dir); 16560b57cec5SDimitry Andric } while (true); 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric 16590b57cec5SDimitry Andric ModuleMap::KnownHeader 166006c3fb27SDimitry Andric HeaderSearch::findModuleForHeader(FileEntryRef File, bool AllowTextual, 1661bdd1243dSDimitry Andric bool AllowExcluded) const { 16620b57cec5SDimitry Andric if (ExternalSource) { 16630b57cec5SDimitry Andric // Make sure the external source has handled header info about this file, 16640b57cec5SDimitry Andric // which includes whether the file is part of a module. 16650b57cec5SDimitry Andric (void)getExistingFileInfo(File); 16660b57cec5SDimitry Andric } 1667bdd1243dSDimitry Andric return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded); 16680b57cec5SDimitry Andric } 16690b57cec5SDimitry Andric 16705ffd83dbSDimitry Andric ArrayRef<ModuleMap::KnownHeader> 167106c3fb27SDimitry Andric HeaderSearch::findAllModulesForHeader(FileEntryRef File) const { 16725ffd83dbSDimitry Andric if (ExternalSource) { 16735ffd83dbSDimitry Andric // Make sure the external source has handled header info about this file, 16745ffd83dbSDimitry Andric // which includes whether the file is part of a module. 16755ffd83dbSDimitry Andric (void)getExistingFileInfo(File); 16765ffd83dbSDimitry Andric } 16775ffd83dbSDimitry Andric return ModMap.findAllModulesForHeader(File); 16785ffd83dbSDimitry Andric } 16795ffd83dbSDimitry Andric 168006c3fb27SDimitry Andric ArrayRef<ModuleMap::KnownHeader> 16815f757f3fSDimitry Andric HeaderSearch::findResolvedModulesForHeader(FileEntryRef File) const { 168206c3fb27SDimitry Andric if (ExternalSource) { 168306c3fb27SDimitry Andric // Make sure the external source has handled header info about this file, 168406c3fb27SDimitry Andric // which includes whether the file is part of a module. 168506c3fb27SDimitry Andric (void)getExistingFileInfo(File); 168606c3fb27SDimitry Andric } 168706c3fb27SDimitry Andric return ModMap.findResolvedModulesForHeader(File); 168806c3fb27SDimitry Andric } 168906c3fb27SDimitry Andric 169006c3fb27SDimitry Andric static bool suggestModule(HeaderSearch &HS, FileEntryRef File, 16910b57cec5SDimitry Andric Module *RequestingModule, 16920b57cec5SDimitry Andric ModuleMap::KnownHeader *SuggestedModule) { 16930b57cec5SDimitry Andric ModuleMap::KnownHeader Module = 16940b57cec5SDimitry Andric HS.findModuleForHeader(File, /*AllowTextual*/true); 16950b57cec5SDimitry Andric 16960b57cec5SDimitry Andric // If this module specifies [no_undeclared_includes], we cannot find any 16970b57cec5SDimitry Andric // file that's in a non-dependency module. 16980b57cec5SDimitry Andric if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) { 16990b57cec5SDimitry Andric HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/ false); 17000b57cec5SDimitry Andric if (!RequestingModule->directlyUses(Module.getModule())) { 17015ffd83dbSDimitry Andric // Builtin headers are a special case. Multiple modules can use the same 17025ffd83dbSDimitry Andric // builtin as a modular header (see also comment in 17035ffd83dbSDimitry Andric // ShouldEnterIncludeFile()), so the builtin header may have been 17045ffd83dbSDimitry Andric // "claimed" by an unrelated module. This shouldn't prevent us from 17055ffd83dbSDimitry Andric // including the builtin header textually in this module. 17065ffd83dbSDimitry Andric if (HS.getModuleMap().isBuiltinHeader(File)) { 17075ffd83dbSDimitry Andric if (SuggestedModule) 17085ffd83dbSDimitry Andric *SuggestedModule = ModuleMap::KnownHeader(); 17095ffd83dbSDimitry Andric return true; 17105ffd83dbSDimitry Andric } 1711bdd1243dSDimitry Andric // TODO: Add this module (or just its module map file) into something like 1712bdd1243dSDimitry Andric // `RequestingModule->AffectingClangModules`. 17130b57cec5SDimitry Andric return false; 17140b57cec5SDimitry Andric } 17150b57cec5SDimitry Andric } 17160b57cec5SDimitry Andric 17175ffd83dbSDimitry Andric if (SuggestedModule) 17185ffd83dbSDimitry Andric *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader) 17195ffd83dbSDimitry Andric ? ModuleMap::KnownHeader() 17205ffd83dbSDimitry Andric : Module; 17215ffd83dbSDimitry Andric 17220b57cec5SDimitry Andric return true; 17230b57cec5SDimitry Andric } 17240b57cec5SDimitry Andric 17250b57cec5SDimitry Andric bool HeaderSearch::findUsableModuleForHeader( 172606c3fb27SDimitry Andric FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule, 17270b57cec5SDimitry Andric ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { 172806c3fb27SDimitry Andric if (needModuleLookup(RequestingModule, SuggestedModule)) { 17290b57cec5SDimitry Andric // If there is a module that corresponds to this header, suggest it. 17305f757f3fSDimitry Andric hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir); 17310b57cec5SDimitry Andric return suggestModule(*this, File, RequestingModule, SuggestedModule); 17320b57cec5SDimitry Andric } 17330b57cec5SDimitry Andric return true; 17340b57cec5SDimitry Andric } 17350b57cec5SDimitry Andric 17360b57cec5SDimitry Andric bool HeaderSearch::findUsableModuleForFrameworkHeader( 173706c3fb27SDimitry Andric FileEntryRef File, StringRef FrameworkName, Module *RequestingModule, 17380b57cec5SDimitry Andric ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { 17390b57cec5SDimitry Andric // If we're supposed to suggest a module, look for one now. 17400b57cec5SDimitry Andric if (needModuleLookup(RequestingModule, SuggestedModule)) { 17410b57cec5SDimitry Andric // Find the top-level framework based on this framework. 17420b57cec5SDimitry Andric SmallVector<std::string, 4> SubmodulePath; 1743bdd1243dSDimitry Andric OptionalDirectoryEntryRef TopFrameworkDir = 174481ad6265SDimitry Andric ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); 174581ad6265SDimitry Andric assert(TopFrameworkDir && "Could not find the top-most framework dir"); 17460b57cec5SDimitry Andric 17470b57cec5SDimitry Andric // Determine the name of the top-level framework. 17480b57cec5SDimitry Andric StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); 17490b57cec5SDimitry Andric 17500b57cec5SDimitry Andric // Load this framework module. If that succeeds, find the suggested module 17510b57cec5SDimitry Andric // for this header, if any. 175281ad6265SDimitry Andric loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework); 17530b57cec5SDimitry Andric 17540b57cec5SDimitry Andric // FIXME: This can find a module not part of ModuleName, which is 17550b57cec5SDimitry Andric // important so that we're consistent about whether this header 17560b57cec5SDimitry Andric // corresponds to a module. Possibly we should lock down framework modules 17570b57cec5SDimitry Andric // so that this is not possible. 17580b57cec5SDimitry Andric return suggestModule(*this, File, RequestingModule, SuggestedModule); 17590b57cec5SDimitry Andric } 17600b57cec5SDimitry Andric return true; 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric 17635f757f3fSDimitry Andric static OptionalFileEntryRef getPrivateModuleMap(FileEntryRef File, 17645f757f3fSDimitry Andric FileManager &FileMgr, 17655f757f3fSDimitry Andric DiagnosticsEngine &Diags) { 176606c3fb27SDimitry Andric StringRef Filename = llvm::sys::path::filename(File.getName()); 176706c3fb27SDimitry Andric SmallString<128> PrivateFilename(File.getDir().getName()); 17680b57cec5SDimitry Andric if (Filename == "module.map") 17690b57cec5SDimitry Andric llvm::sys::path::append(PrivateFilename, "module_private.map"); 17700b57cec5SDimitry Andric else if (Filename == "module.modulemap") 17710b57cec5SDimitry Andric llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); 17720b57cec5SDimitry Andric else 17735f757f3fSDimitry Andric return std::nullopt; 17745f757f3fSDimitry Andric auto PMMFile = FileMgr.getOptionalFileRef(PrivateFilename); 17755f757f3fSDimitry Andric if (PMMFile) { 17765f757f3fSDimitry Andric if (Filename == "module.map") 17775f757f3fSDimitry Andric Diags.Report(diag::warn_deprecated_module_dot_map) 17785f757f3fSDimitry Andric << PrivateFilename << 1 17795f757f3fSDimitry Andric << File.getDir().getName().ends_with(".framework"); 17805f757f3fSDimitry Andric } 17815f757f3fSDimitry Andric return PMMFile; 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric 178406c3fb27SDimitry Andric bool HeaderSearch::loadModuleMapFile(FileEntryRef File, bool IsSystem, 17850b57cec5SDimitry Andric FileID ID, unsigned *Offset, 17860b57cec5SDimitry Andric StringRef OriginalModuleMapFile) { 17870b57cec5SDimitry Andric // Find the directory for the module. For frameworks, that may require going 17880b57cec5SDimitry Andric // up from the 'Modules' directory. 1789bdd1243dSDimitry Andric OptionalDirectoryEntryRef Dir; 1790a7dea167SDimitry Andric if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) { 179181ad6265SDimitry Andric Dir = FileMgr.getOptionalDirectoryRef("."); 1792a7dea167SDimitry Andric } else { 17930b57cec5SDimitry Andric if (!OriginalModuleMapFile.empty()) { 17940b57cec5SDimitry Andric // We're building a preprocessed module map. Find or invent the directory 17950b57cec5SDimitry Andric // that it originally occupied. 179681ad6265SDimitry Andric Dir = FileMgr.getOptionalDirectoryRef( 17970b57cec5SDimitry Andric llvm::sys::path::parent_path(OriginalModuleMapFile)); 179881ad6265SDimitry Andric if (!Dir) { 179981ad6265SDimitry Andric auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0); 180081ad6265SDimitry Andric Dir = FakeFile.getDir(); 18010b57cec5SDimitry Andric } 18020b57cec5SDimitry Andric } else { 180306c3fb27SDimitry Andric Dir = File.getDir(); 18040b57cec5SDimitry Andric } 18050b57cec5SDimitry Andric 180681ad6265SDimitry Andric assert(Dir && "parent must exist"); 18070b57cec5SDimitry Andric StringRef DirName(Dir->getName()); 18080b57cec5SDimitry Andric if (llvm::sys::path::filename(DirName) == "Modules") { 18090b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName); 18105f757f3fSDimitry Andric if (DirName.ends_with(".framework")) 181181ad6265SDimitry Andric if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName)) 181281ad6265SDimitry Andric Dir = *MaybeDir; 18130b57cec5SDimitry Andric // FIXME: This assert can fail if there's a race between the above check 18140b57cec5SDimitry Andric // and the removal of the directory. 18150b57cec5SDimitry Andric assert(Dir && "parent must exist"); 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric } 18180b57cec5SDimitry Andric 181981ad6265SDimitry Andric assert(Dir && "module map home directory must exist"); 182081ad6265SDimitry Andric switch (loadModuleMapFileImpl(File, IsSystem, *Dir, ID, Offset)) { 18210b57cec5SDimitry Andric case LMM_AlreadyLoaded: 18220b57cec5SDimitry Andric case LMM_NewlyLoaded: 18230b57cec5SDimitry Andric return false; 18240b57cec5SDimitry Andric case LMM_NoDirectory: 18250b57cec5SDimitry Andric case LMM_InvalidModuleMap: 18260b57cec5SDimitry Andric return true; 18270b57cec5SDimitry Andric } 18280b57cec5SDimitry Andric llvm_unreachable("Unknown load module map result"); 18290b57cec5SDimitry Andric } 18300b57cec5SDimitry Andric 18310b57cec5SDimitry Andric HeaderSearch::LoadModuleMapResult 183206c3fb27SDimitry Andric HeaderSearch::loadModuleMapFileImpl(FileEntryRef File, bool IsSystem, 183381ad6265SDimitry Andric DirectoryEntryRef Dir, FileID ID, 18340b57cec5SDimitry Andric unsigned *Offset) { 18350b57cec5SDimitry Andric // Check whether we've already loaded this module map, and mark it as being 18360b57cec5SDimitry Andric // loaded in case we recursively try to load it from itself. 18370b57cec5SDimitry Andric auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true)); 18380b57cec5SDimitry Andric if (!AddResult.second) 18390b57cec5SDimitry Andric return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; 18400b57cec5SDimitry Andric 18410b57cec5SDimitry Andric if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) { 18420b57cec5SDimitry Andric LoadedModuleMaps[File] = false; 18430b57cec5SDimitry Andric return LMM_InvalidModuleMap; 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric 18460b57cec5SDimitry Andric // Try to load a corresponding private module map. 18475f757f3fSDimitry Andric if (OptionalFileEntryRef PMMFile = 18485f757f3fSDimitry Andric getPrivateModuleMap(File, FileMgr, Diags)) { 18495f757f3fSDimitry Andric if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) { 18500b57cec5SDimitry Andric LoadedModuleMaps[File] = false; 18510b57cec5SDimitry Andric return LMM_InvalidModuleMap; 18520b57cec5SDimitry Andric } 18530b57cec5SDimitry Andric } 18540b57cec5SDimitry Andric 18550b57cec5SDimitry Andric // This directory has a module map. 18560b57cec5SDimitry Andric return LMM_NewlyLoaded; 18570b57cec5SDimitry Andric } 18580b57cec5SDimitry Andric 185906c3fb27SDimitry Andric OptionalFileEntryRef 186006c3fb27SDimitry Andric HeaderSearch::lookupModuleMapFile(DirectoryEntryRef Dir, bool IsFramework) { 18610b57cec5SDimitry Andric if (!HSOpts->ImplicitModuleMaps) 186206c3fb27SDimitry Andric return std::nullopt; 18630b57cec5SDimitry Andric // For frameworks, the preferred spelling is Modules/module.modulemap, but 18640b57cec5SDimitry Andric // module.map at the framework root is also accepted. 186506c3fb27SDimitry Andric SmallString<128> ModuleMapFileName(Dir.getName()); 18660b57cec5SDimitry Andric if (IsFramework) 18670b57cec5SDimitry Andric llvm::sys::path::append(ModuleMapFileName, "Modules"); 18680b57cec5SDimitry Andric llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); 186906c3fb27SDimitry Andric if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) 1870a7dea167SDimitry Andric return *F; 18710b57cec5SDimitry Andric 18725f757f3fSDimitry Andric // Continue to allow module.map, but warn it's deprecated. 187306c3fb27SDimitry Andric ModuleMapFileName = Dir.getName(); 18740b57cec5SDimitry Andric llvm::sys::path::append(ModuleMapFileName, "module.map"); 18755f757f3fSDimitry Andric if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) { 18765f757f3fSDimitry Andric Diags.Report(diag::warn_deprecated_module_dot_map) 18775f757f3fSDimitry Andric << ModuleMapFileName << 0 << IsFramework; 1878a7dea167SDimitry Andric return *F; 18795f757f3fSDimitry Andric } 18805ffd83dbSDimitry Andric 18815ffd83dbSDimitry Andric // For frameworks, allow to have a private module map with a preferred 18825ffd83dbSDimitry Andric // spelling when a public module map is absent. 18835ffd83dbSDimitry Andric if (IsFramework) { 188406c3fb27SDimitry Andric ModuleMapFileName = Dir.getName(); 18855ffd83dbSDimitry Andric llvm::sys::path::append(ModuleMapFileName, "Modules", 18865ffd83dbSDimitry Andric "module.private.modulemap"); 188706c3fb27SDimitry Andric if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) 18885ffd83dbSDimitry Andric return *F; 18895ffd83dbSDimitry Andric } 189006c3fb27SDimitry Andric return std::nullopt; 18910b57cec5SDimitry Andric } 18920b57cec5SDimitry Andric 189381ad6265SDimitry Andric Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir, 18940b57cec5SDimitry Andric bool IsSystem) { 18950b57cec5SDimitry Andric // Try to load a module map file. 18960b57cec5SDimitry Andric switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) { 18970b57cec5SDimitry Andric case LMM_InvalidModuleMap: 18980b57cec5SDimitry Andric // Try to infer a module map from the framework directory. 18990b57cec5SDimitry Andric if (HSOpts->ImplicitModuleMaps) 19000b57cec5SDimitry Andric ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr); 19010b57cec5SDimitry Andric break; 19020b57cec5SDimitry Andric 19030b57cec5SDimitry Andric case LMM_NoDirectory: 19040b57cec5SDimitry Andric return nullptr; 19050b57cec5SDimitry Andric 190606c3fb27SDimitry Andric case LMM_AlreadyLoaded: 19070b57cec5SDimitry Andric case LMM_NewlyLoaded: 19080b57cec5SDimitry Andric break; 19090b57cec5SDimitry Andric } 19100b57cec5SDimitry Andric 19110b57cec5SDimitry Andric return ModMap.findModule(Name); 19120b57cec5SDimitry Andric } 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric HeaderSearch::LoadModuleMapResult 19150b57cec5SDimitry Andric HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem, 19160b57cec5SDimitry Andric bool IsFramework) { 191781ad6265SDimitry Andric if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName)) 1918a7dea167SDimitry Andric return loadModuleMapFile(*Dir, IsSystem, IsFramework); 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric return LMM_NoDirectory; 19210b57cec5SDimitry Andric } 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric HeaderSearch::LoadModuleMapResult 192481ad6265SDimitry Andric HeaderSearch::loadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem, 19250b57cec5SDimitry Andric bool IsFramework) { 19260b57cec5SDimitry Andric auto KnownDir = DirectoryHasModuleMap.find(Dir); 19270b57cec5SDimitry Andric if (KnownDir != DirectoryHasModuleMap.end()) 19280b57cec5SDimitry Andric return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; 19290b57cec5SDimitry Andric 193006c3fb27SDimitry Andric if (OptionalFileEntryRef ModuleMapFile = 193106c3fb27SDimitry Andric lookupModuleMapFile(Dir, IsFramework)) { 19320b57cec5SDimitry Andric LoadModuleMapResult Result = 193306c3fb27SDimitry Andric loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir); 19340b57cec5SDimitry Andric // Add Dir explicitly in case ModuleMapFile is in a subdirectory. 19350b57cec5SDimitry Andric // E.g. Foo.framework/Modules/module.modulemap 19360b57cec5SDimitry Andric // ^Dir ^ModuleMapFile 19370b57cec5SDimitry Andric if (Result == LMM_NewlyLoaded) 19380b57cec5SDimitry Andric DirectoryHasModuleMap[Dir] = true; 19390b57cec5SDimitry Andric else if (Result == LMM_InvalidModuleMap) 19400b57cec5SDimitry Andric DirectoryHasModuleMap[Dir] = false; 19410b57cec5SDimitry Andric return Result; 19420b57cec5SDimitry Andric } 19430b57cec5SDimitry Andric return LMM_InvalidModuleMap; 19440b57cec5SDimitry Andric } 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { 19470b57cec5SDimitry Andric Modules.clear(); 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric if (HSOpts->ImplicitModuleMaps) { 19500b57cec5SDimitry Andric // Load module maps for each of the header search directories. 195181ad6265SDimitry Andric for (DirectoryLookup &DL : search_dir_range()) { 195281ad6265SDimitry Andric bool IsSystem = DL.isSystemHeaderDirectory(); 195381ad6265SDimitry Andric if (DL.isFramework()) { 19540b57cec5SDimitry Andric std::error_code EC; 19550b57cec5SDimitry Andric SmallString<128> DirNative; 195606c3fb27SDimitry Andric llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative); 19570b57cec5SDimitry Andric 19580b57cec5SDimitry Andric // Search each of the ".framework" directories to load them as modules. 19590b57cec5SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 19600b57cec5SDimitry Andric for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), 19610b57cec5SDimitry Andric DirEnd; 19620b57cec5SDimitry Andric Dir != DirEnd && !EC; Dir.increment(EC)) { 19630b57cec5SDimitry Andric if (llvm::sys::path::extension(Dir->path()) != ".framework") 19640b57cec5SDimitry Andric continue; 19650b57cec5SDimitry Andric 196681ad6265SDimitry Andric auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path()); 19670b57cec5SDimitry Andric if (!FrameworkDir) 19680b57cec5SDimitry Andric continue; 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric // Load this framework module. 1971a7dea167SDimitry Andric loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir, 19720b57cec5SDimitry Andric IsSystem); 19730b57cec5SDimitry Andric } 19740b57cec5SDimitry Andric continue; 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 19770b57cec5SDimitry Andric // FIXME: Deal with header maps. 197881ad6265SDimitry Andric if (DL.isHeaderMap()) 19790b57cec5SDimitry Andric continue; 19800b57cec5SDimitry Andric 19810b57cec5SDimitry Andric // Try to load a module map file for the search directory. 198281ad6265SDimitry Andric loadModuleMapFile(*DL.getDirRef(), IsSystem, /*IsFramework*/ false); 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric // Try to load module map files for immediate subdirectories of this 19850b57cec5SDimitry Andric // search directory. 198681ad6265SDimitry Andric loadSubdirectoryModuleMaps(DL); 19870b57cec5SDimitry Andric } 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric // Populate the list of modules. 199104eeddc0SDimitry Andric llvm::transform(ModMap.modules(), std::back_inserter(Modules), 199204eeddc0SDimitry Andric [](const auto &NameAndMod) { return NameAndMod.second; }); 19930b57cec5SDimitry Andric } 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric void HeaderSearch::loadTopLevelSystemModules() { 19960b57cec5SDimitry Andric if (!HSOpts->ImplicitModuleMaps) 19970b57cec5SDimitry Andric return; 19980b57cec5SDimitry Andric 19990b57cec5SDimitry Andric // Load module maps for each of the header search directories. 200081ad6265SDimitry Andric for (const DirectoryLookup &DL : search_dir_range()) { 20010b57cec5SDimitry Andric // We only care about normal header directories. 200281ad6265SDimitry Andric if (!DL.isNormalDir()) 20030b57cec5SDimitry Andric continue; 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric // Try to load a module map file for the search directory. 200681ad6265SDimitry Andric loadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(), 200781ad6265SDimitry Andric DL.isFramework()); 20080b57cec5SDimitry Andric } 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric 20110b57cec5SDimitry Andric void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { 20120b57cec5SDimitry Andric assert(HSOpts->ImplicitModuleMaps && 20130b57cec5SDimitry Andric "Should not be loading subdirectory module maps"); 20140b57cec5SDimitry Andric 20150b57cec5SDimitry Andric if (SearchDir.haveSearchedAllModuleMaps()) 20160b57cec5SDimitry Andric return; 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric std::error_code EC; 201906c3fb27SDimitry Andric SmallString<128> Dir = SearchDir.getDirRef()->getName(); 20200b57cec5SDimitry Andric FileMgr.makeAbsolutePath(Dir); 20210b57cec5SDimitry Andric SmallString<128> DirNative; 20220b57cec5SDimitry Andric llvm::sys::path::native(Dir, DirNative); 20230b57cec5SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 20240b57cec5SDimitry Andric for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; 20250b57cec5SDimitry Andric Dir != DirEnd && !EC; Dir.increment(EC)) { 202606c3fb27SDimitry Andric if (Dir->type() == llvm::sys::fs::file_type::regular_file) 202706c3fb27SDimitry Andric continue; 20280b57cec5SDimitry Andric bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework"; 20290b57cec5SDimitry Andric if (IsFramework == SearchDir.isFramework()) 20300b57cec5SDimitry Andric loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), 20310b57cec5SDimitry Andric SearchDir.isFramework()); 20320b57cec5SDimitry Andric } 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric SearchDir.setSearchedAllModuleMaps(true); 20350b57cec5SDimitry Andric } 20360b57cec5SDimitry Andric 20370b57cec5SDimitry Andric std::string HeaderSearch::suggestPathToFileForDiagnostics( 20385f757f3fSDimitry Andric FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const { 20395f757f3fSDimitry Andric return suggestPathToFileForDiagnostics(File.getName(), /*WorkingDir=*/"", 20405f757f3fSDimitry Andric MainFile, IsAngled); 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric std::string HeaderSearch::suggestPathToFileForDiagnostics( 20440b57cec5SDimitry Andric llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile, 20455f757f3fSDimitry Andric bool *IsAngled) const { 20460b57cec5SDimitry Andric using namespace llvm::sys; 20470b57cec5SDimitry Andric 2048bdd1243dSDimitry Andric llvm::SmallString<32> FilePath = File; 2049*0fca6ea1SDimitry Andric if (!WorkingDir.empty() && !path::is_absolute(FilePath)) 2050*0fca6ea1SDimitry Andric fs::make_absolute(WorkingDir, FilePath); 2051bdd1243dSDimitry Andric // remove_dots switches to backslashes on windows as a side-effect! 2052bdd1243dSDimitry Andric // We always want to suggest forward slashes for includes. 2053bdd1243dSDimitry Andric // (not remove_dots(..., posix) as that misparses windows paths). 2054bdd1243dSDimitry Andric path::remove_dots(FilePath, /*remove_dot_dot=*/true); 2055bdd1243dSDimitry Andric path::native(FilePath, path::Style::posix); 2056bdd1243dSDimitry Andric File = FilePath; 2057bdd1243dSDimitry Andric 20580b57cec5SDimitry Andric unsigned BestPrefixLength = 0; 205904eeddc0SDimitry Andric // Checks whether `Dir` is a strict path prefix of `File`. If so and that's 206004eeddc0SDimitry Andric // the longest prefix we've seen so for it, returns true and updates the 206104eeddc0SDimitry Andric // `BestPrefixLength` accordingly. 2062bdd1243dSDimitry Andric auto CheckDir = [&](llvm::SmallString<32> Dir) -> bool { 20630b57cec5SDimitry Andric if (!WorkingDir.empty() && !path::is_absolute(Dir)) 2064bdd1243dSDimitry Andric fs::make_absolute(WorkingDir, Dir); 2065bdd1243dSDimitry Andric path::remove_dots(Dir, /*remove_dot_dot=*/true); 20660b57cec5SDimitry Andric for (auto NI = path::begin(File), NE = path::end(File), 20670b57cec5SDimitry Andric DI = path::begin(Dir), DE = path::end(Dir); 2068bdd1243dSDimitry Andric NI != NE; ++NI, ++DI) { 20690b57cec5SDimitry Andric if (DI == DE) { 2070bdd1243dSDimitry Andric // Dir is a prefix of File, up to choice of path separators. 20710b57cec5SDimitry Andric unsigned PrefixLength = NI - path::begin(File); 20720b57cec5SDimitry Andric if (PrefixLength > BestPrefixLength) { 20730b57cec5SDimitry Andric BestPrefixLength = PrefixLength; 20740b57cec5SDimitry Andric return true; 20750b57cec5SDimitry Andric } 20760b57cec5SDimitry Andric break; 20770b57cec5SDimitry Andric } 20780b57cec5SDimitry Andric 20790b57cec5SDimitry Andric // Consider all path separators equal. 20800b57cec5SDimitry Andric if (NI->size() == 1 && DI->size() == 1 && 20810b57cec5SDimitry Andric path::is_separator(NI->front()) && path::is_separator(DI->front())) 20820b57cec5SDimitry Andric continue; 20830b57cec5SDimitry Andric 208404eeddc0SDimitry Andric // Special case Apple .sdk folders since the search path is typically a 208504eeddc0SDimitry Andric // symlink like `iPhoneSimulator14.5.sdk` while the file is instead 208604eeddc0SDimitry Andric // located in `iPhoneSimulator.sdk` (the real folder). 20875f757f3fSDimitry Andric if (NI->ends_with(".sdk") && DI->ends_with(".sdk")) { 208804eeddc0SDimitry Andric StringRef NBasename = path::stem(*NI); 208904eeddc0SDimitry Andric StringRef DBasename = path::stem(*DI); 20905f757f3fSDimitry Andric if (DBasename.starts_with(NBasename)) 209104eeddc0SDimitry Andric continue; 209204eeddc0SDimitry Andric } 209304eeddc0SDimitry Andric 20940b57cec5SDimitry Andric if (*NI != *DI) 20950b57cec5SDimitry Andric break; 20960b57cec5SDimitry Andric } 20970b57cec5SDimitry Andric return false; 20980b57cec5SDimitry Andric }; 20990b57cec5SDimitry Andric 210004eeddc0SDimitry Andric bool BestPrefixIsFramework = false; 210181ad6265SDimitry Andric for (const DirectoryLookup &DL : search_dir_range()) { 210281ad6265SDimitry Andric if (DL.isNormalDir()) { 210306c3fb27SDimitry Andric StringRef Dir = DL.getDirRef()->getName(); 210404eeddc0SDimitry Andric if (CheckDir(Dir)) { 21055f757f3fSDimitry Andric if (IsAngled) 21065f757f3fSDimitry Andric *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic()); 210704eeddc0SDimitry Andric BestPrefixIsFramework = false; 210804eeddc0SDimitry Andric } 210981ad6265SDimitry Andric } else if (DL.isFramework()) { 211006c3fb27SDimitry Andric StringRef Dir = DL.getFrameworkDirRef()->getName(); 211104eeddc0SDimitry Andric if (CheckDir(Dir)) { 21125f757f3fSDimitry Andric // Framework includes by convention use <>. 21135f757f3fSDimitry Andric if (IsAngled) 21145f757f3fSDimitry Andric *IsAngled = BestPrefixLength; 211504eeddc0SDimitry Andric BestPrefixIsFramework = true; 211604eeddc0SDimitry Andric } 211704eeddc0SDimitry Andric } 21180b57cec5SDimitry Andric } 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric // Try to shorten include path using TUs directory, if we couldn't find any 21210b57cec5SDimitry Andric // suitable prefix in include search paths. 212204eeddc0SDimitry Andric if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) { 21235f757f3fSDimitry Andric if (IsAngled) 21245f757f3fSDimitry Andric *IsAngled = false; 212504eeddc0SDimitry Andric BestPrefixIsFramework = false; 212604eeddc0SDimitry Andric } 21270b57cec5SDimitry Andric 2128fe6060f1SDimitry Andric // Try resolving resulting filename via reverse search in header maps, 212981ad6265SDimitry Andric // key from header name is user preferred name for the include file. 2130fe6060f1SDimitry Andric StringRef Filename = File.drop_front(BestPrefixLength); 213181ad6265SDimitry Andric for (const DirectoryLookup &DL : search_dir_range()) { 213281ad6265SDimitry Andric if (!DL.isHeaderMap()) 2133fe6060f1SDimitry Andric continue; 21340b57cec5SDimitry Andric 2135fe6060f1SDimitry Andric StringRef SpelledFilename = 213681ad6265SDimitry Andric DL.getHeaderMap()->reverseLookupFilename(Filename); 2137fe6060f1SDimitry Andric if (!SpelledFilename.empty()) { 2138fe6060f1SDimitry Andric Filename = SpelledFilename; 213904eeddc0SDimitry Andric BestPrefixIsFramework = false; 2140fe6060f1SDimitry Andric break; 2141fe6060f1SDimitry Andric } 2142fe6060f1SDimitry Andric } 214304eeddc0SDimitry Andric 214404eeddc0SDimitry Andric // If the best prefix is a framework path, we need to compute the proper 214504eeddc0SDimitry Andric // include spelling for the framework header. 214604eeddc0SDimitry Andric bool IsPrivateHeader; 214704eeddc0SDimitry Andric SmallString<128> FrameworkName, IncludeSpelling; 214804eeddc0SDimitry Andric if (BestPrefixIsFramework && 214904eeddc0SDimitry Andric isFrameworkStylePath(Filename, IsPrivateHeader, FrameworkName, 215004eeddc0SDimitry Andric IncludeSpelling)) { 215104eeddc0SDimitry Andric Filename = IncludeSpelling; 215204eeddc0SDimitry Andric } 2153fe6060f1SDimitry Andric return path::convert_to_slash(Filename); 21540b57cec5SDimitry Andric } 2155