2194 lines · cpp
1//===- HeaderSearch.cpp - Resolve Header File Locations -------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the DirectoryLookup and HeaderSearch interfaces.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Lex/HeaderSearch.h"14#include "clang/Basic/Diagnostic.h"15#include "clang/Basic/FileManager.h"16#include "clang/Basic/IdentifierTable.h"17#include "clang/Basic/Module.h"18#include "clang/Basic/SourceManager.h"19#include "clang/Lex/DirectoryLookup.h"20#include "clang/Lex/ExternalPreprocessorSource.h"21#include "clang/Lex/HeaderMap.h"22#include "clang/Lex/HeaderSearchOptions.h"23#include "clang/Lex/LexDiagnostic.h"24#include "clang/Lex/ModuleMap.h"25#include "clang/Lex/Preprocessor.h"26#include "llvm/ADT/APInt.h"27#include "llvm/ADT/STLExtras.h"28#include "llvm/ADT/SmallString.h"29#include "llvm/ADT/SmallVector.h"30#include "llvm/ADT/Statistic.h"31#include "llvm/ADT/StringRef.h"32#include "llvm/Support/Allocator.h"33#include "llvm/Support/Capacity.h"34#include "llvm/Support/Errc.h"35#include "llvm/Support/ErrorHandling.h"36#include "llvm/Support/FileSystem.h"37#include "llvm/Support/Path.h"38#include "llvm/Support/VirtualFileSystem.h"39#include "llvm/Support/xxhash.h"40#include <algorithm>41#include <cassert>42#include <cstddef>43#include <cstdio>44#include <cstring>45#include <string>46#include <system_error>47#include <utility>48 49using namespace clang;50 51#define DEBUG_TYPE "file-search"52 53ALWAYS_ENABLED_STATISTIC(NumIncluded, "Number of attempted #includes.");54ALWAYS_ENABLED_STATISTIC(55 NumMultiIncludeFileOptzn,56 "Number of #includes skipped due to the multi-include optimization.");57ALWAYS_ENABLED_STATISTIC(NumFrameworkLookups, "Number of framework lookups.");58ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups,59 "Number of subframework lookups.");60 61const IdentifierInfo *62HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {63 if (LazyControllingMacro.isID()) {64 if (!External)65 return nullptr;66 67 LazyControllingMacro =68 External->GetIdentifier(LazyControllingMacro.getID());69 return LazyControllingMacro.getPtr();70 }71 72 IdentifierInfo *ControllingMacro = LazyControllingMacro.getPtr();73 if (ControllingMacro && ControllingMacro->isOutOfDate()) {74 assert(External && "We must have an external source if we have a "75 "controlling macro that is out of date.");76 External->updateOutOfDateIdentifier(*ControllingMacro);77 }78 return ControllingMacro;79}80 81ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default;82 83HeaderSearch::HeaderSearch(const HeaderSearchOptions &HSOpts,84 SourceManager &SourceMgr, DiagnosticsEngine &Diags,85 const LangOptions &LangOpts,86 const TargetInfo *Target)87 : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),88 FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}89 90void HeaderSearch::PrintStats() {91 llvm::errs() << "\n*** HeaderSearch Stats:\n"92 << FileInfo.size() << " files tracked.\n";93 unsigned NumOnceOnlyFiles = 0;94 for (unsigned i = 0, e = FileInfo.size(); i != e; ++i)95 NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);96 llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n";97 98 llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n"99 << " " << NumMultiIncludeFileOptzn100 << " #includes skipped due to the multi-include optimization.\n";101 102 llvm::errs() << NumFrameworkLookups << " framework lookups.\n"103 << NumSubFrameworkLookups << " subframework lookups.\n";104}105 106void HeaderSearch::SetSearchPaths(107 std::vector<DirectoryLookup> dirs, unsigned int angledDirIdx,108 unsigned int systemDirIdx,109 llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {110 assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&111 "Directory indices are unordered");112 SearchDirs = std::move(dirs);113 SearchDirsUsage.assign(SearchDirs.size(), false);114 AngledDirIdx = angledDirIdx;115 SystemDirIdx = systemDirIdx;116 SearchDirToHSEntry = std::move(searchDirToHSEntry);117 //LookupFileCache.clear();118 indexInitialHeaderMaps();119}120 121void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {122 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;123 SearchDirs.insert(SearchDirs.begin() + idx, dir);124 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);125 if (!isAngled)126 AngledDirIdx++;127 SystemDirIdx++;128}129 130std::vector<bool> HeaderSearch::computeUserEntryUsage() const {131 std::vector<bool> UserEntryUsage(HSOpts.UserEntries.size());132 for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {133 // Check whether this DirectoryLookup has been successfully used.134 if (SearchDirsUsage[I]) {135 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);136 // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.137 if (UserEntryIdxIt != SearchDirToHSEntry.end())138 UserEntryUsage[UserEntryIdxIt->second] = true;139 }140 }141 return UserEntryUsage;142}143 144std::vector<bool> HeaderSearch::collectVFSUsageAndClear() const {145 std::vector<bool> VFSUsage;146 if (!getHeaderSearchOpts().ModulesIncludeVFSUsage)147 return VFSUsage;148 149 llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();150 // TODO: This only works if the `RedirectingFileSystem`s were all created by151 // `createVFSFromOverlayFiles`. But at least exclude the ones with null152 // OverlayFileDir.153 RootFS.visit([&](llvm::vfs::FileSystem &FS) {154 if (auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {155 // Skip a `RedirectingFileSystem` with null OverlayFileDir which indicates156 // that they aren't created by createVFSFromOverlayFiles from the overlays157 // in HeaderSearchOption::VFSOverlayFiles.158 if (!RFS->getOverlayFileDir().empty()) {159 VFSUsage.push_back(RFS->hasBeenUsed());160 RFS->clearHasBeenUsed();161 }162 }163 });164 assert(VFSUsage.size() == getHeaderSearchOpts().VFSOverlayFiles.size() &&165 "A different number of RedirectingFileSystem's were present than "166 "-ivfsoverlay options passed to Clang!");167 // VFS visit order is the opposite of VFSOverlayFiles order.168 std::reverse(VFSUsage.begin(), VFSUsage.end());169 return VFSUsage;170}171 172/// CreateHeaderMap - This method returns a HeaderMap for the specified173/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.174const HeaderMap *HeaderSearch::CreateHeaderMap(FileEntryRef FE) {175 // We expect the number of headermaps to be small, and almost always empty.176 // If it ever grows, use of a linear search should be re-evaluated.177 if (!HeaderMaps.empty()) {178 for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)179 // Pointer equality comparison of FileEntries works because they are180 // already uniqued by inode.181 if (HeaderMaps[i].first == FE)182 return HeaderMaps[i].second.get();183 }184 185 if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) {186 HeaderMaps.emplace_back(FE, std::move(HM));187 return HeaderMaps.back().second.get();188 }189 190 return nullptr;191}192 193/// Get filenames for all registered header maps.194void HeaderSearch::getHeaderMapFileNames(195 SmallVectorImpl<std::string> &Names) const {196 for (auto &HM : HeaderMaps)197 Names.push_back(std::string(HM.first.getName()));198}199 200std::string HeaderSearch::getCachedModuleFileName(Module *Module) {201 OptionalFileEntryRef ModuleMap =202 getModuleMap().getModuleMapFileForUniquing(Module);203 // The ModuleMap maybe a nullptr, when we load a cached C++ module without204 // *.modulemap file. In this case, just return an empty string.205 if (!ModuleMap)206 return {};207 return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested());208}209 210std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,211 bool FileMapOnly) {212 // First check the module name to pcm file map.213 auto i(HSOpts.PrebuiltModuleFiles.find(ModuleName));214 if (i != HSOpts.PrebuiltModuleFiles.end())215 return i->second;216 217 if (FileMapOnly || HSOpts.PrebuiltModulePaths.empty())218 return {};219 220 // Then go through each prebuilt module directory and try to find the pcm221 // file.222 for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {223 SmallString<256> Result(Dir);224 FileMgr.makeAbsolutePath(Result);225 if (ModuleName.contains(':'))226 // The separator of C++20 modules partitions (':') is not good for file227 // systems, here clang and gcc choose '-' by default since it is not a228 // valid character of C++ indentifiers. So we could avoid conflicts.229 llvm::sys::path::append(Result, ModuleName.split(':').first + "-" +230 ModuleName.split(':').second +231 ".pcm");232 else233 llvm::sys::path::append(Result, ModuleName + ".pcm");234 if (getFileMgr().getOptionalFileRef(Result))235 return std::string(Result);236 }237 238 return {};239}240 241std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) {242 OptionalFileEntryRef ModuleMap =243 getModuleMap().getModuleMapFileForUniquing(Module);244 StringRef ModuleName = Module->Name;245 StringRef ModuleMapPath = ModuleMap->getName();246 StringRef ModuleCacheHash = HSOpts.DisableModuleHash ? "" : getModuleHash();247 for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {248 SmallString<256> CachePath(Dir);249 FileMgr.makeAbsolutePath(CachePath);250 llvm::sys::path::append(CachePath, ModuleCacheHash);251 std::string FileName =252 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);253 if (!FileName.empty() && getFileMgr().getOptionalFileRef(FileName))254 return FileName;255 }256 return {};257}258 259std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName,260 StringRef ModuleMapPath) {261 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,262 getModuleCachePath());263}264 265std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,266 StringRef ModuleMapPath,267 StringRef CachePath) {268 // If we don't have a module cache path or aren't supposed to use one, we269 // can't do anything.270 if (CachePath.empty())271 return {};272 273 SmallString<256> Result(CachePath);274 275 if (HSOpts.DisableModuleHash) {276 llvm::sys::path::append(Result, ModuleName + ".pcm");277 } else {278 // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should279 // ideally be globally unique to this particular module. Name collisions280 // in the hash are safe (because any translation unit can only import one281 // module with each name), but result in a loss of caching.282 //283 // To avoid false-negatives, we form as canonical a path as we can, and map284 // to lower-case in case we're on a case-insensitive file system.285 SmallString<128> CanonicalPath(ModuleMapPath);286 if (getModuleMap().canonicalizeModuleMapPath(CanonicalPath))287 return {};288 289 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());290 291 SmallString<128> HashStr;292 llvm::APInt(64, Hash).toStringUnsigned(HashStr, /*Radix*/36);293 llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");294 }295 return Result.str().str();296}297 298Module *HeaderSearch::lookupModule(StringRef ModuleName,299 SourceLocation ImportLoc, bool AllowSearch,300 bool AllowExtraModuleMapSearch) {301 // Look in the module map to determine if there is a module by this name.302 Module *Module = ModMap.findOrLoadModule(ModuleName);303 if (Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)304 return Module;305 306 StringRef SearchName = ModuleName;307 Module = lookupModule(ModuleName, SearchName, ImportLoc,308 AllowExtraModuleMapSearch);309 310 // The facility for "private modules" -- adjacent, optional module maps named311 // module.private.modulemap that are supposed to define private submodules --312 // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.313 //314 // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate315 // should also rename to Foo_Private. Representing private as submodules316 // could force building unwanted dependencies into the parent module and cause317 // dependency cycles.318 if (!Module && SearchName.consume_back("_Private"))319 Module = lookupModule(ModuleName, SearchName, ImportLoc,320 AllowExtraModuleMapSearch);321 if (!Module && SearchName.consume_back("Private"))322 Module = lookupModule(ModuleName, SearchName, ImportLoc,323 AllowExtraModuleMapSearch);324 return Module;325}326 327Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,328 SourceLocation ImportLoc,329 bool AllowExtraModuleMapSearch) {330 Module *Module = nullptr;331 332 // Look through the various header search paths to load any available module333 // maps, searching for a module map that describes this module.334 for (DirectoryLookup &Dir : search_dir_range()) {335 if (Dir.isFramework()) {336 // Search for or infer a module map for a framework. Here we use337 // SearchName rather than ModuleName, to permit finding private modules338 // named FooPrivate in buggy frameworks named Foo.339 SmallString<128> FrameworkDirName;340 FrameworkDirName += Dir.getFrameworkDirRef()->getName();341 llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");342 if (auto FrameworkDir =343 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {344 bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;345 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);346 if (Module)347 break;348 }349 }350 351 // FIXME: Figure out how header maps and module maps will work together.352 353 // Only deal with normal search directories.354 if (!Dir.isNormalDir())355 continue;356 357 bool IsSystem = Dir.isSystemHeaderDirectory();358 // Only returns std::nullopt if not a normal directory, which we just359 // checked360 DirectoryEntryRef NormalDir = *Dir.getDirRef();361 // Search for a module map file in this directory.362 if (parseModuleMapFile(NormalDir, IsSystem,363 /*IsFramework*/ false) == MMR_NewlyProcessed) {364 // We just parsed a module map file; check whether the module can be365 // loaded now.366 Module = ModMap.findOrLoadModule(ModuleName);367 if (Module)368 break;369 }370 371 // Search for a module map in a subdirectory with the same name as the372 // module.373 SmallString<128> NestedModuleMapDirName;374 NestedModuleMapDirName = Dir.getDirRef()->getName();375 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);376 if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,377 /*IsFramework*/ false) == MMR_NewlyProcessed) {378 // If we just parsed a module map file, look for the module again.379 Module = ModMap.findOrLoadModule(ModuleName);380 if (Module)381 break;382 }383 384 if (HSOpts.AllowModuleMapSubdirectorySearch) {385 // If we've already performed the exhaustive search for module maps in386 // this search directory, don't do it again.387 if (Dir.haveSearchedAllModuleMaps())388 continue;389 390 // Load all module maps in the immediate subdirectories of this search391 // directory if ModuleName was from @import.392 if (AllowExtraModuleMapSearch)393 loadSubdirectoryModuleMaps(Dir);394 395 // Look again for the module.396 Module = ModMap.findOrLoadModule(ModuleName);397 if (Module)398 break;399 }400 }401 402 return Module;403}404 405void HeaderSearch::indexInitialHeaderMaps() {406 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());407 408 // Iterate over all filename keys and associate them with the index i.409 for (unsigned i = 0; i != SearchDirs.size(); ++i) {410 auto &Dir = SearchDirs[i];411 412 // We're concerned with only the initial contiguous run of header413 // maps within SearchDirs, which can be 99% of SearchDirs when414 // SearchDirs.size() is ~10000.415 if (!Dir.isHeaderMap()) {416 SearchDirHeaderMapIndex = std::move(Index);417 FirstNonHeaderMapSearchDirIdx = i;418 break;419 }420 421 // Give earlier keys precedence over identical later keys.422 auto Callback = [&](StringRef Filename) {423 Index.try_emplace(Filename.lower(), i);424 };425 Dir.getHeaderMap()->forEachKey(Callback);426 }427}428 429//===----------------------------------------------------------------------===//430// File lookup within a DirectoryLookup scope431//===----------------------------------------------------------------------===//432 433/// getName - Return the directory or filename corresponding to this lookup434/// object.435StringRef DirectoryLookup::getName() const {436 if (isNormalDir())437 return getDirRef()->getName();438 if (isFramework())439 return getFrameworkDirRef()->getName();440 assert(isHeaderMap() && "Unknown DirectoryLookup");441 return getHeaderMap()->getFileName();442}443 444OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule(445 StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,446 bool IsSystemHeaderDir, Module *RequestingModule,447 ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/,448 bool CacheFailures /*=true*/) {449 // If we have a module map that might map this header, load it and450 // check whether we'll have a suggestion for a module.451 auto File = getFileMgr().getFileRef(FileName, OpenFile, CacheFailures);452 if (!File) {453 // For rare, surprising errors (e.g. "out of file handles"), diag the EC454 // message.455 std::error_code EC = llvm::errorToErrorCode(File.takeError());456 if (EC != llvm::errc::no_such_file_or_directory &&457 EC != llvm::errc::invalid_argument &&458 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {459 Diags.Report(IncludeLoc, diag::err_cannot_open_file)460 << FileName << EC.message();461 }462 return std::nullopt;463 }464 465 // If there is a module that corresponds to this header, suggest it.466 if (!findUsableModuleForHeader(467 *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule,468 SuggestedModule, IsSystemHeaderDir))469 return std::nullopt;470 471 return *File;472}473 474/// LookupFile - Lookup the specified file in this search path, returning it475/// if it exists or returning null if not.476OptionalFileEntryRef DirectoryLookup::LookupFile(477 StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,478 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,479 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,480 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,481 bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName,482 bool OpenFile) const {483 InUserSpecifiedSystemFramework = false;484 IsInHeaderMap = false;485 MappedName.clear();486 487 SmallString<1024> TmpDir;488 if (isNormalDir()) {489 // Concatenate the requested file onto the directory.490 TmpDir = getDirRef()->getName();491 llvm::sys::path::append(TmpDir, Filename);492 if (SearchPath) {493 StringRef SearchPathRef(getDirRef()->getName());494 SearchPath->clear();495 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());496 }497 if (RelativePath) {498 RelativePath->clear();499 RelativePath->append(Filename.begin(), Filename.end());500 }501 502 return HS.getFileAndSuggestModule(503 TmpDir, IncludeLoc, getDir(), isSystemHeaderDirectory(),504 RequestingModule, SuggestedModule, OpenFile);505 }506 507 if (isFramework())508 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,509 RequestingModule, SuggestedModule,510 InUserSpecifiedSystemFramework, IsFrameworkFound);511 512 assert(isHeaderMap() && "Unknown directory lookup");513 const HeaderMap *HM = getHeaderMap();514 SmallString<1024> Path;515 StringRef Dest = HM->lookupFilename(Filename, Path);516 if (Dest.empty())517 return std::nullopt;518 519 IsInHeaderMap = true;520 521 auto FixupSearchPathAndFindUsableModule =522 [&](FileEntryRef File) -> OptionalFileEntryRef {523 if (SearchPath) {524 StringRef SearchPathRef(getName());525 SearchPath->clear();526 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());527 }528 if (RelativePath) {529 RelativePath->clear();530 RelativePath->append(Filename.begin(), Filename.end());531 }532 if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(),533 RequestingModule, SuggestedModule,534 isSystemHeaderDirectory())) {535 return std::nullopt;536 }537 return File;538 };539 540 // Check if the headermap maps the filename to a framework include541 // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the542 // framework include.543 if (llvm::sys::path::is_relative(Dest)) {544 MappedName.append(Dest.begin(), Dest.end());545 Filename = StringRef(MappedName.begin(), MappedName.size());546 Dest = HM->lookupFilename(Filename, Path);547 }548 549 if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest, OpenFile)) {550 return FixupSearchPathAndFindUsableModule(*Res);551 }552 553 // Header maps need to be marked as used whenever the filename matches.554 // The case where the target file **exists** is handled by callee of this555 // function as part of the regular logic that applies to include search paths.556 // The case where the target file **does not exist** is handled here:557 HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);558 return std::nullopt;559}560 561/// Given a framework directory, find the top-most framework directory.562///563/// \param FileMgr The file manager to use for directory lookups.564/// \param DirName The name of the framework directory.565/// \param SubmodulePath Will be populated with the submodule path from the566/// returned top-level module to the originally named framework.567static OptionalDirectoryEntryRef568getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,569 SmallVectorImpl<std::string> &SubmodulePath) {570 assert(llvm::sys::path::extension(DirName) == ".framework" &&571 "Not a framework directory");572 573 // Note: as an egregious but useful hack we use the real path here, because574 // frameworks moving between top-level frameworks to embedded frameworks tend575 // to be symlinked, and we base the logical structure of modules on the576 // physical layout. In particular, we need to deal with crazy includes like577 //578 // #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h>579 //580 // where 'Bar' used to be embedded in 'Foo', is now a top-level framework581 // which one should access with, e.g.,582 //583 // #include <Bar/Wibble.h>584 //585 // Similar issues occur when a top-level framework has moved into an586 // embedded framework.587 auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName);588 589 if (TopFrameworkDir)590 DirName = FileMgr.getCanonicalName(*TopFrameworkDir);591 do {592 // Get the parent directory name.593 DirName = llvm::sys::path::parent_path(DirName);594 if (DirName.empty())595 break;596 597 // Determine whether this directory exists.598 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);599 if (!Dir)600 break;601 602 // If this is a framework directory, then we're a subframework of this603 // framework.604 if (llvm::sys::path::extension(DirName) == ".framework") {605 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));606 TopFrameworkDir = *Dir;607 }608 } while (true);609 610 return TopFrameworkDir;611}612 613static bool needModuleLookup(Module *RequestingModule,614 bool HasSuggestedModule) {615 return HasSuggestedModule ||616 (RequestingModule && RequestingModule->NoUndeclaredIncludes);617}618 619/// DoFrameworkLookup - Do a lookup of the specified file in the current620/// DirectoryLookup, which is a framework directory.621OptionalFileEntryRef DirectoryLookup::DoFrameworkLookup(622 StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,623 SmallVectorImpl<char> *RelativePath, Module *RequestingModule,624 ModuleMap::KnownHeader *SuggestedModule,625 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {626 FileManager &FileMgr = HS.getFileMgr();627 628 // Framework names must have a '/' in the filename.629 size_t SlashPos = Filename.find('/');630 if (SlashPos == StringRef::npos)631 return std::nullopt;632 633 // Find out if this is the home for the specified framework, by checking634 // HeaderSearch. Possible answers are yes/no and unknown.635 FrameworkCacheEntry &CacheEntry =636 HS.LookupFrameworkCache(Filename.substr(0, SlashPos));637 638 // If it is known and in some other directory, fail.639 if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef())640 return std::nullopt;641 642 // Otherwise, construct the path to this framework dir.643 644 // FrameworkName = "/System/Library/Frameworks/"645 SmallString<1024> FrameworkName;646 FrameworkName += getFrameworkDirRef()->getName();647 if (FrameworkName.empty() || FrameworkName.back() != '/')648 FrameworkName.push_back('/');649 650 // FrameworkName = "/System/Library/Frameworks/Cocoa"651 StringRef ModuleName(Filename.begin(), SlashPos);652 FrameworkName += ModuleName;653 654 // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"655 FrameworkName += ".framework/";656 657 // If the cache entry was unresolved, populate it now.658 if (!CacheEntry.Directory) {659 ++NumFrameworkLookups;660 661 // If the framework dir doesn't exist, we fail.662 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);663 if (!Dir)664 return std::nullopt;665 666 // Otherwise, if it does, remember that this is the right direntry for this667 // framework.668 CacheEntry.Directory = getFrameworkDirRef();669 670 // If this is a user search directory, check if the framework has been671 // user-specified as a system framework.672 if (getDirCharacteristic() == SrcMgr::C_User) {673 SmallString<1024> SystemFrameworkMarker(FrameworkName);674 SystemFrameworkMarker += ".system_framework";675 if (FileMgr.getOptionalFileRef(SystemFrameworkMarker))676 CacheEntry.IsUserSpecifiedSystemFramework = true;677 }678 }679 680 // Set out flags.681 InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;682 IsFrameworkFound = CacheEntry.Directory.has_value();683 684 if (RelativePath) {685 RelativePath->clear();686 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());687 }688 689 // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"690 unsigned OrigSize = FrameworkName.size();691 692 FrameworkName += "Headers/";693 694 if (SearchPath) {695 SearchPath->clear();696 // Without trailing '/'.697 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);698 }699 700 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());701 702 auto File =703 FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);704 if (!File) {705 // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"706 const char *Private = "Private";707 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,708 Private+strlen(Private));709 if (SearchPath)710 SearchPath->insert(SearchPath->begin()+OrigSize, Private,711 Private+strlen(Private));712 713 File = FileMgr.getOptionalFileRef(FrameworkName,714 /*OpenFile=*/!SuggestedModule);715 }716 717 // If we found the header and are allowed to suggest a module, do so now.718 if (File && needModuleLookup(RequestingModule, SuggestedModule)) {719 // Find the framework in which this header occurs.720 StringRef FrameworkPath = File->getDir().getName();721 bool FoundFramework = false;722 do {723 // Determine whether this directory exists.724 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkPath);725 if (!Dir)726 break;727 728 // If this is a framework directory, then we're a subframework of this729 // framework.730 if (llvm::sys::path::extension(FrameworkPath) == ".framework") {731 FoundFramework = true;732 break;733 }734 735 // Get the parent directory name.736 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);737 if (FrameworkPath.empty())738 break;739 } while (true);740 741 bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;742 if (FoundFramework) {743 if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath,744 RequestingModule,745 SuggestedModule, IsSystem))746 return std::nullopt;747 } else {748 if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule,749 SuggestedModule, IsSystem))750 return std::nullopt;751 }752 }753 if (File)754 return *File;755 return std::nullopt;756}757 758void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,759 ConstSearchDirIterator HitIt,760 SourceLocation Loc) {761 CacheLookup.HitIt = HitIt;762 noteLookupUsage(HitIt.Idx, Loc);763}764 765void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {766 SearchDirsUsage[HitIdx] = true;767 768 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);769 if (UserEntryIdxIt != SearchDirToHSEntry.end())770 Diags.Report(Loc, diag::remark_pp_search_path_usage)771 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;772}773 774void HeaderSearch::setTarget(const TargetInfo &Target) {775 ModMap.setTarget(Target);776}777 778//===----------------------------------------------------------------------===//779// Header File Location.780//===----------------------------------------------------------------------===//781 782/// Return true with a diagnostic if the file that MSVC would have found783/// fails to match the one that Clang would have found with MSVC header search784/// disabled.785static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,786 OptionalFileEntryRef MSFE,787 const FileEntry *FE,788 SourceLocation IncludeLoc) {789 if (MSFE && FE != *MSFE) {790 Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();791 return true;792 }793 return false;794}795 796static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {797 assert(!Str.empty());798 char *CopyStr = Alloc.Allocate<char>(Str.size()+1);799 std::copy(Str.begin(), Str.end(), CopyStr);800 CopyStr[Str.size()] = '\0';801 return CopyStr;802}803 804static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,805 SmallVectorImpl<char> &FrameworkName,806 SmallVectorImpl<char> &IncludeSpelling) {807 using namespace llvm::sys;808 path::const_iterator I = path::begin(Path);809 path::const_iterator E = path::end(Path);810 IsPrivateHeader = false;811 812 // Detect different types of framework style paths:813 //814 // ...Foo.framework/{Headers,PrivateHeaders}815 // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders}816 // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders}817 // ...<other variations with 'Versions' like in the above path>818 //819 // and some other variations among these lines.820 int FoundComp = 0;821 while (I != E) {822 if (*I == "Headers") {823 ++FoundComp;824 } else if (*I == "PrivateHeaders") {825 ++FoundComp;826 IsPrivateHeader = true;827 } else if (I->ends_with(".framework")) {828 StringRef Name = I->drop_back(10); // Drop .framework829 // Need to reset the strings and counter to support nested frameworks.830 FrameworkName.clear();831 FrameworkName.append(Name.begin(), Name.end());832 IncludeSpelling.clear();833 IncludeSpelling.append(Name.begin(), Name.end());834 FoundComp = 1;835 } else if (FoundComp >= 2) {836 IncludeSpelling.push_back('/');837 IncludeSpelling.append(I->begin(), I->end());838 }839 ++I;840 }841 842 return !FrameworkName.empty() && FoundComp >= 2;843}844 845static void846diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,847 StringRef Includer, StringRef IncludeFilename,848 FileEntryRef IncludeFE, bool isAngled = false,849 bool FoundByHeaderMap = false) {850 bool IsIncluderPrivateHeader = false;851 SmallString<128> FromFramework, ToFramework;852 SmallString<128> FromIncludeSpelling, ToIncludeSpelling;853 if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework,854 FromIncludeSpelling))855 return;856 bool IsIncludeePrivateHeader = false;857 bool IsIncludeeInFramework =858 isFrameworkStylePath(IncludeFE.getName(), IsIncludeePrivateHeader,859 ToFramework, ToIncludeSpelling);860 861 if (!isAngled && !FoundByHeaderMap) {862 SmallString<128> NewInclude("<");863 if (IsIncludeeInFramework) {864 NewInclude += ToIncludeSpelling;865 NewInclude += ">";866 } else {867 NewInclude += IncludeFilename;868 NewInclude += ">";869 }870 Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)871 << IncludeFilename872 << FixItHint::CreateReplacement(IncludeLoc, NewInclude);873 }874 875 // Headers in Foo.framework/Headers should not include headers876 // from Foo.framework/PrivateHeaders, since this violates public/private877 // API boundaries and can cause modular dependency cycles.878 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&879 IsIncludeePrivateHeader && FromFramework == ToFramework)880 Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)881 << IncludeFilename;882}883 884/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,885/// return null on failure. isAngled indicates whether the file reference is886/// for system \#include's or not (i.e. using <> instead of ""). Includers, if887/// non-empty, indicates where the \#including file(s) are, in case a relative888/// search is needed. Microsoft mode will pass all \#including files.889OptionalFileEntryRef HeaderSearch::LookupFile(890 StringRef Filename, SourceLocation IncludeLoc, bool isAngled,891 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,892 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,893 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,894 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,895 bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,896 bool BuildSystemModule, bool OpenFile, bool CacheFailures) {897 ConstSearchDirIterator CurDirLocal = nullptr;898 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;899 900 if (IsMapped)901 *IsMapped = false;902 903 if (IsFrameworkFound)904 *IsFrameworkFound = false;905 906 if (SuggestedModule)907 *SuggestedModule = ModuleMap::KnownHeader();908 909 // If 'Filename' is absolute, check to see if it exists and no searching.910 if (llvm::sys::path::is_absolute(Filename)) {911 CurDir = nullptr;912 913 // If this was an #include_next "/absolute/file", fail.914 if (FromDir)915 return std::nullopt;916 917 if (SearchPath)918 SearchPath->clear();919 if (RelativePath) {920 RelativePath->clear();921 RelativePath->append(Filename.begin(), Filename.end());922 }923 // Otherwise, just return the file.924 return getFileAndSuggestModule(Filename, IncludeLoc, nullptr,925 /*IsSystemHeaderDir*/ false,926 RequestingModule, SuggestedModule, OpenFile,927 CacheFailures);928 }929 930 // This is the header that MSVC's header search would have found.931 ModuleMap::KnownHeader MSSuggestedModule;932 OptionalFileEntryRef MSFE;933 934 // Check to see if the file is in the #includer's directory. This cannot be935 // based on CurDir, because each includer could be a #include of a936 // subdirectory (#include "foo/bar.h") and a subsequent include of "baz.h"937 // should resolve to "whatever/foo/baz.h". This search is not done for <>938 // headers.939 if (!Includers.empty() && !isAngled) {940 SmallString<1024> TmpDir;941 bool First = true;942 for (const auto &IncluderAndDir : Includers) {943 OptionalFileEntryRef Includer = IncluderAndDir.first;944 945 // Concatenate the requested file onto the directory.946 TmpDir = IncluderAndDir.second.getName();947 llvm::sys::path::append(TmpDir, Filename);948 949 // FIXME: We don't cache the result of getFileInfo across the call to950 // getFileAndSuggestModule, because it's a reference to an element of951 // a container that could be reallocated across this call.952 //953 // If we have no includer, that means we're processing a #include954 // from a module build. We should treat this as a system header if we're955 // building a [system] module.956 bool IncluderIsSystemHeader = [&]() {957 if (!Includer)958 return BuildSystemModule;959 const HeaderFileInfo *HFI = getExistingFileInfo(*Includer);960 assert(HFI && "includer without file info");961 return HFI->DirInfo != SrcMgr::C_User;962 }();963 if (OptionalFileEntryRef FE = getFileAndSuggestModule(964 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,965 RequestingModule, SuggestedModule)) {966 if (!Includer) {967 assert(First && "only first includer can have no file");968 return FE;969 }970 971 // Leave CurDir unset.972 // This file is a system header or C++ unfriendly if the old file is.973 //974 // Note that we only use one of FromHFI/ToHFI at once, due to potential975 // reallocation of the underlying vector potentially making the first976 // reference binding dangling.977 const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer);978 assert(FromHFI && "includer without file info");979 unsigned DirInfo = FromHFI->DirInfo;980 981 HeaderFileInfo &ToHFI = getFileInfo(*FE);982 ToHFI.DirInfo = DirInfo;983 984 if (SearchPath) {985 StringRef SearchPathRef(IncluderAndDir.second.getName());986 SearchPath->clear();987 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());988 }989 if (RelativePath) {990 RelativePath->clear();991 RelativePath->append(Filename.begin(), Filename.end());992 }993 if (First) {994 diagnoseFrameworkInclude(Diags, IncludeLoc,995 IncluderAndDir.second.getName(), Filename,996 *FE);997 return FE;998 }999 1000 // Otherwise, we found the path via MSVC header search rules. If1001 // -Wmsvc-include is enabled, we have to keep searching to see if we1002 // would've found this header in -I or -isystem directories.1003 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {1004 return FE;1005 } else {1006 MSFE = FE;1007 if (SuggestedModule) {1008 MSSuggestedModule = *SuggestedModule;1009 *SuggestedModule = ModuleMap::KnownHeader();1010 }1011 break;1012 }1013 }1014 First = false;1015 }1016 }1017 1018 CurDir = nullptr;1019 1020 // If this is a system #include, ignore the user #include locs.1021 ConstSearchDirIterator It =1022 isAngled ? angled_dir_begin() : search_dir_begin();1023 1024 // If this is a #include_next request, start searching after the directory the1025 // file was found in.1026 if (FromDir)1027 It = FromDir;1028 1029 // Cache all of the lookups performed by this method. Many headers are1030 // multiply included, and the "pragma once" optimization prevents them from1031 // being relex/pp'd, but they would still have to search through a1032 // (potentially huge) series of SearchDirs to find it.1033 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];1034 1035 ConstSearchDirIterator NextIt = std::next(It);1036 1037 if (!SkipCache) {1038 if (CacheLookup.StartIt == NextIt &&1039 CacheLookup.RequestingModule == RequestingModule) {1040 // HIT: Skip querying potentially lots of directories for this lookup.1041 if (CacheLookup.HitIt)1042 It = CacheLookup.HitIt;1043 if (CacheLookup.MappedName) {1044 Filename = CacheLookup.MappedName;1045 if (IsMapped)1046 *IsMapped = true;1047 }1048 } else {1049 // MISS: This is the first query, or the previous query didn't match1050 // our search start. We will fill in our found location below, so prime1051 // the start point value.1052 CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt);1053 1054 if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) {1055 // Handle cold misses of user includes in the presence of many header1056 // maps. We avoid searching perhaps thousands of header maps by1057 // jumping directly to the correct one or jumping beyond all of them.1058 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());1059 if (Iter == SearchDirHeaderMapIndex.end())1060 // Not in index => Skip to first SearchDir after initial header maps1061 It = search_dir_nth(FirstNonHeaderMapSearchDirIdx);1062 else1063 // In index => Start with a specific header map1064 It = search_dir_nth(Iter->second);1065 }1066 }1067 } else {1068 CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt);1069 }1070 1071 SmallString<64> MappedName;1072 1073 // Check each directory in sequence to see if it contains this file.1074 for (; It != search_dir_end(); ++It) {1075 bool InUserSpecifiedSystemFramework = false;1076 bool IsInHeaderMap = false;1077 bool IsFrameworkFoundInDir = false;1078 OptionalFileEntryRef File = It->LookupFile(1079 Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,1080 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,1081 IsInHeaderMap, MappedName, OpenFile);1082 if (!MappedName.empty()) {1083 assert(IsInHeaderMap && "MappedName should come from a header map");1084 CacheLookup.MappedName =1085 copyString(MappedName, LookupFileCache.getAllocator());1086 }1087 if (IsMapped)1088 // A filename is mapped when a header map remapped it to a relative path1089 // used in subsequent header search or to an absolute path pointing to an1090 // existing file.1091 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));1092 if (IsFrameworkFound)1093 // Because we keep a filename remapped for subsequent search directory1094 // lookups, ignore IsFrameworkFoundInDir after the first remapping and not1095 // just for remapping in a current search directory.1096 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);1097 if (!File)1098 continue;1099 1100 CurDir = It;1101 1102 IncludeNames[*File] = Filename;1103 1104 // This file is a system header or C++ unfriendly if the dir is.1105 HeaderFileInfo &HFI = getFileInfo(*File);1106 HFI.DirInfo = CurDir->getDirCharacteristic();1107 1108 // If the directory characteristic is User but this framework was1109 // user-specified to be treated as a system framework, promote the1110 // characteristic.1111 if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)1112 HFI.DirInfo = SrcMgr::C_System;1113 1114 // If the filename matches a known system header prefix, override1115 // whether the file is a system header.1116 for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {1117 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {1118 HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System1119 : SrcMgr::C_User;1120 break;1121 }1122 }1123 1124 if (checkMSVCHeaderSearch(Diags, MSFE, &File->getFileEntry(), IncludeLoc)) {1125 if (SuggestedModule)1126 *SuggestedModule = MSSuggestedModule;1127 return MSFE;1128 }1129 1130 bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;1131 if (!Includers.empty())1132 diagnoseFrameworkInclude(Diags, IncludeLoc,1133 Includers.front().second.getName(), Filename,1134 *File, isAngled, FoundByHeaderMap);1135 1136 // Remember this location for the next lookup we do.1137 cacheLookupSuccess(CacheLookup, It, IncludeLoc);1138 return File;1139 }1140 1141 if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {1142 if (SuggestedModule)1143 *SuggestedModule = MSSuggestedModule;1144 return MSFE;1145 }1146 1147 // Otherwise, didn't find it. Remember we didn't find this.1148 CacheLookup.HitIt = search_dir_end();1149 return std::nullopt;1150}1151 1152/// LookupSubframeworkHeader - Look up a subframework for the specified1153/// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from1154/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox1155/// is a subframework within Carbon.framework. If so, return the FileEntry1156/// for the designated file, otherwise return null.1157OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(1158 StringRef Filename, FileEntryRef ContextFileEnt,1159 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,1160 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {1161 // Framework names must have a '/' in the filename. Find it.1162 // FIXME: Should we permit '\' on Windows?1163 size_t SlashPos = Filename.find('/');1164 if (SlashPos == StringRef::npos)1165 return std::nullopt;1166 1167 // Look up the base framework name of the ContextFileEnt.1168 StringRef ContextName = ContextFileEnt.getName();1169 1170 // If the context info wasn't a framework, couldn't be a subframework.1171 const unsigned DotFrameworkLen = 10;1172 auto FrameworkPos = ContextName.find(".framework");1173 if (FrameworkPos == StringRef::npos ||1174 (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&1175 ContextName[FrameworkPos + DotFrameworkLen] != '\\'))1176 return std::nullopt;1177 1178 SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +1179 FrameworkPos +1180 DotFrameworkLen + 1);1181 1182 // Append Frameworks/HIToolbox.framework/1183 FrameworkName += "Frameworks/";1184 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);1185 FrameworkName += ".framework/";1186 1187 auto &CacheLookup =1188 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),1189 FrameworkCacheEntry())).first;1190 1191 // Some other location?1192 if (CacheLookup.second.Directory &&1193 CacheLookup.first().size() == FrameworkName.size() &&1194 memcmp(CacheLookup.first().data(), &FrameworkName[0],1195 CacheLookup.first().size()) != 0)1196 return std::nullopt;1197 1198 // Cache subframework.1199 if (!CacheLookup.second.Directory) {1200 ++NumSubFrameworkLookups;1201 1202 // If the framework dir doesn't exist, we fail.1203 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);1204 if (!Dir)1205 return std::nullopt;1206 1207 // Otherwise, if it does, remember that this is the right direntry for this1208 // framework.1209 CacheLookup.second.Directory = Dir;1210 }1211 1212 1213 if (RelativePath) {1214 RelativePath->clear();1215 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());1216 }1217 1218 // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"1219 SmallString<1024> HeadersFilename(FrameworkName);1220 HeadersFilename += "Headers/";1221 if (SearchPath) {1222 SearchPath->clear();1223 // Without trailing '/'.1224 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);1225 }1226 1227 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());1228 auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);1229 if (!File) {1230 // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"1231 HeadersFilename = FrameworkName;1232 HeadersFilename += "PrivateHeaders/";1233 if (SearchPath) {1234 SearchPath->clear();1235 // Without trailing '/'.1236 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);1237 }1238 1239 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());1240 File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);1241 1242 if (!File)1243 return std::nullopt;1244 }1245 1246 // This file is a system header or C++ unfriendly if the old file is.1247 const HeaderFileInfo *ContextHFI = getExistingFileInfo(ContextFileEnt);1248 assert(ContextHFI && "context file without file info");1249 // Note that the temporary 'DirInfo' is required here, as the call to1250 // getFileInfo could resize the vector and might invalidate 'ContextHFI'.1251 unsigned DirInfo = ContextHFI->DirInfo;1252 getFileInfo(*File).DirInfo = DirInfo;1253 1254 FrameworkName.pop_back(); // remove the trailing '/'1255 if (!findUsableModuleForFrameworkHeader(*File, FrameworkName,1256 RequestingModule, SuggestedModule,1257 /*IsSystem*/ false))1258 return std::nullopt;1259 1260 return *File;1261}1262 1263//===----------------------------------------------------------------------===//1264// File Info Management.1265//===----------------------------------------------------------------------===//1266 1267static bool moduleMembershipNeedsMerge(const HeaderFileInfo *HFI,1268 ModuleMap::ModuleHeaderRole Role) {1269 if (ModuleMap::isModular(Role))1270 return !HFI->isModuleHeader || HFI->isTextualModuleHeader;1271 if (!HFI->isModuleHeader && (Role & ModuleMap::TextualHeader))1272 return !HFI->isTextualModuleHeader;1273 return false;1274}1275 1276static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI,1277 bool isModuleHeader,1278 bool isTextualModuleHeader) {1279 HFI.isModuleHeader |= isModuleHeader;1280 if (HFI.isModuleHeader)1281 HFI.isTextualModuleHeader = false;1282 else1283 HFI.isTextualModuleHeader |= isTextualModuleHeader;1284}1285 1286void HeaderFileInfo::mergeModuleMembership(ModuleMap::ModuleHeaderRole Role) {1287 mergeHeaderFileInfoModuleBits(*this, ModuleMap::isModular(Role),1288 (Role & ModuleMap::TextualHeader));1289}1290 1291/// Merge the header file info provided by \p OtherHFI into the current1292/// header file info (\p HFI)1293static void mergeHeaderFileInfo(HeaderFileInfo &HFI,1294 const HeaderFileInfo &OtherHFI) {1295 assert(OtherHFI.External && "expected to merge external HFI");1296 1297 HFI.isImport |= OtherHFI.isImport;1298 HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;1299 mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader,1300 OtherHFI.isTextualModuleHeader);1301 1302 if (!HFI.LazyControllingMacro.isValid())1303 HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro;1304 1305 HFI.DirInfo = OtherHFI.DirInfo;1306 HFI.External = (!HFI.IsValid || HFI.External);1307 HFI.IsValid = true;1308}1309 1310HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) {1311 if (FE.getUID() >= FileInfo.size())1312 FileInfo.resize(FE.getUID() + 1);1313 1314 HeaderFileInfo *HFI = &FileInfo[FE.getUID()];1315 // FIXME: Use a generation count to check whether this is really up to date.1316 if (ExternalSource && !HFI->Resolved) {1317 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);1318 if (ExternalHFI.IsValid) {1319 HFI->Resolved = true;1320 if (ExternalHFI.External)1321 mergeHeaderFileInfo(*HFI, ExternalHFI);1322 }1323 }1324 1325 HFI->IsValid = true;1326 // We assume the caller has local information about this header file, so it's1327 // no longer strictly external.1328 HFI->External = false;1329 return *HFI;1330}1331 1332const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const {1333 HeaderFileInfo *HFI;1334 if (ExternalSource) {1335 if (FE.getUID() >= FileInfo.size())1336 FileInfo.resize(FE.getUID() + 1);1337 1338 HFI = &FileInfo[FE.getUID()];1339 // FIXME: Use a generation count to check whether this is really up to date.1340 if (!HFI->Resolved) {1341 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);1342 if (ExternalHFI.IsValid) {1343 HFI->Resolved = true;1344 if (ExternalHFI.External)1345 mergeHeaderFileInfo(*HFI, ExternalHFI);1346 }1347 }1348 } else if (FE.getUID() < FileInfo.size()) {1349 HFI = &FileInfo[FE.getUID()];1350 } else {1351 HFI = nullptr;1352 }1353 1354 return (HFI && HFI->IsValid) ? HFI : nullptr;1355}1356 1357const HeaderFileInfo *1358HeaderSearch::getExistingLocalFileInfo(FileEntryRef FE) const {1359 HeaderFileInfo *HFI;1360 if (FE.getUID() < FileInfo.size()) {1361 HFI = &FileInfo[FE.getUID()];1362 } else {1363 HFI = nullptr;1364 }1365 1366 return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr;1367}1368 1369bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {1370 // Check if we've entered this file and found an include guard or #pragma1371 // once. Note that we dor't check for #import, because that's not a property1372 // of the file itself.1373 if (auto *HFI = getExistingFileInfo(File))1374 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();1375 return false;1376}1377 1378void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE,1379 ModuleMap::ModuleHeaderRole Role,1380 bool isCompilingModuleHeader) {1381 // Don't mark the file info as non-external if there's nothing to change.1382 if (!isCompilingModuleHeader) {1383 if ((Role & ModuleMap::ExcludedHeader))1384 return;1385 auto *HFI = getExistingFileInfo(FE);1386 if (HFI && !moduleMembershipNeedsMerge(HFI, Role))1387 return;1388 }1389 1390 auto &HFI = getFileInfo(FE);1391 HFI.mergeModuleMembership(Role);1392 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;1393}1394 1395bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,1396 FileEntryRef File, bool isImport,1397 bool ModulesEnabled, Module *M,1398 bool &IsFirstIncludeOfFile) {1399 // An include file should be entered if either:1400 // 1. This is the first include of the file.1401 // 2. This file can be included multiple times, that is it's not an1402 // "include-once" file.1403 //1404 // Include-once is controlled by these preprocessor directives.1405 //1406 // #pragma once1407 // This directive is in the include file, and marks it as an include-once1408 // file.1409 //1410 // #import <file>1411 // This directive is in the includer, and indicates that the include file1412 // should only be entered if this is the first include.1413 ++NumIncluded;1414 IsFirstIncludeOfFile = false;1415 HeaderFileInfo &FileInfo = getFileInfo(File);1416 1417 auto MaybeReenterImportedFile = [&]() -> bool {1418 // Modules add a wrinkle though: what's included isn't necessarily visible.1419 // Consider this module.1420 // module Example {1421 // module A { header "a.h" export * }1422 // module B { header "b.h" export * }1423 // }1424 // b.h includes c.h. The main file includes a.h, which will trigger a module1425 // build of Example, and c.h will be included. However, c.h isn't visible to1426 // the main file. Normally this is fine, the main file can just include c.h1427 // if it needs it. If c.h is in a module, the include will translate into a1428 // module import, this function will be skipped, and everything will work as1429 // expected. However, if c.h is not in a module (or is `textual`), then this1430 // function will run. If c.h is include-once, it will not be entered from1431 // the main file and it will still not be visible.1432 1433 // If modules aren't enabled then there's no visibility issue. Always1434 // respect `#pragma once`.1435 if (!ModulesEnabled || FileInfo.isPragmaOnce)1436 return false;1437 1438 // Ensure FileInfo bits are up to date.1439 ModMap.resolveHeaderDirectives(File);1440 1441 // This brings up a subtlety of #import - it's not a very good indicator of1442 // include-once. Developers are often unaware of the difference between1443 // #include and #import, and tend to use one or the other indiscrimiately.1444 // In order to support #include on include-once headers that lack macro1445 // guards and `#pragma once` (which is the vast majority of Objective-C1446 // headers), if a file is ever included with #import, it's marked as1447 // isImport in the HeaderFileInfo and treated as include-once. This allows1448 // #include to work in Objective-C.1449 // #include <Foundation/Foundation.h>1450 // #include <Foundation/NSString.h>1451 // Foundation.h has an #import of NSString.h, and so the second #include is1452 // skipped even though NSString.h has no `#pragma once` and no macro guard.1453 //1454 // However, this helpfulness causes problems with modules. If c.h is not an1455 // include-once file, but something included it with #import anyway (as is1456 // typical in Objective-C code), this include will be skipped and c.h will1457 // not be visible. Consider it not include-once if it is a `textual` header1458 // in a module.1459 if (FileInfo.isTextualModuleHeader)1460 return true;1461 1462 if (FileInfo.isCompilingModuleHeader) {1463 // It's safer to re-enter a file whose module is being built because its1464 // declarations will still be scoped to a single module.1465 if (FileInfo.isModuleHeader) {1466 // Headers marked as "builtin" are covered by the system module maps1467 // rather than the builtin ones. Some versions of the Darwin module fail1468 // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these1469 // files while building their module to allow them to function properly.1470 if (ModMap.isBuiltinHeader(File))1471 return true;1472 } else {1473 // Files that are excluded from their module can potentially be1474 // re-entered from their own module. This might cause redeclaration1475 // errors if another module saw this file first, but there's a1476 // reasonable chance that its module will build first. However if1477 // there's no controlling macro, then trust the #import and assume this1478 // really is an include-once file.1479 if (FileInfo.getControllingMacro(ExternalLookup))1480 return true;1481 }1482 }1483 // If the include file has a macro guard, then it might still not be1484 // re-entered if the controlling macro is visibly defined. e.g. another1485 // header in the module being built included this file and local submodule1486 // visibility is not enabled.1487 1488 // It might be tempting to re-enter the include-once file if it's not1489 // visible in an attempt to make it visible. However this will still cause1490 // redeclaration errors against the known-but-not-visible declarations. The1491 // include file not being visible will most likely cause "undefined x"1492 // errors, but at least there's a slim chance of compilation succeeding.1493 return false;1494 };1495 1496 if (isImport) {1497 // As discussed above, record that this file was ever `#import`ed, and treat1498 // it as an include-once file from here out.1499 FileInfo.isImport = true;1500 if (PP.alreadyIncluded(File) && !MaybeReenterImportedFile())1501 return false;1502 } else {1503 // isPragmaOnce and isImport are only set after the file has been included1504 // at least once. If either are set then this is a repeat #include of an1505 // include-once file.1506 if (FileInfo.isPragmaOnce ||1507 (FileInfo.isImport && !MaybeReenterImportedFile()))1508 return false;1509 }1510 1511 // As a final optimization, check for a macro guard and skip entering the file1512 // if the controlling macro is defined. The macro guard will effectively erase1513 // the file's contents, and the include would have no effect other than to1514 // waste time opening and reading a file.1515 if (const IdentifierInfo *ControllingMacro =1516 FileInfo.getControllingMacro(ExternalLookup)) {1517 // If the header corresponds to a module, check whether the macro is already1518 // defined in that module rather than checking all visible modules. This is1519 // mainly to cover corner cases where the same controlling macro is used in1520 // different files in multiple modules.1521 if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)1522 : PP.isMacroDefined(ControllingMacro)) {1523 ++NumMultiIncludeFileOptzn;1524 return false;1525 }1526 }1527 1528 IsFirstIncludeOfFile = PP.markIncluded(File);1529 return true;1530}1531 1532size_t HeaderSearch::getTotalMemory() const {1533 return SearchDirs.capacity()1534 + llvm::capacity_in_bytes(FileInfo)1535 + llvm::capacity_in_bytes(HeaderMaps)1536 + LookupFileCache.getAllocator().getTotalMemory()1537 + FrameworkMap.getAllocator().getTotalMemory();1538}1539 1540unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {1541 return &DL - &*SearchDirs.begin();1542}1543 1544StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {1545 return FrameworkNames.insert(Framework).first->first();1546}1547 1548StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const {1549 auto It = IncludeNames.find(File);1550 if (It == IncludeNames.end())1551 return {};1552 return It->second;1553}1554 1555bool HeaderSearch::hasModuleMap(StringRef FileName,1556 const DirectoryEntry *Root,1557 bool IsSystem) {1558 if (!HSOpts.ImplicitModuleMaps)1559 return false;1560 1561 SmallVector<DirectoryEntryRef, 2> FixUpDirectories;1562 1563 StringRef DirName = FileName;1564 do {1565 // Get the parent directory name.1566 DirName = llvm::sys::path::parent_path(DirName);1567 if (DirName.empty())1568 return false;1569 1570 // Determine whether this directory exists.1571 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);1572 if (!Dir)1573 return false;1574 1575 // Try to load the module map file in this directory.1576 switch (parseAndLoadModuleMapFile(1577 *Dir, IsSystem,1578 llvm::sys::path::extension(Dir->getName()) == ".framework")) {1579 case MMR_NewlyProcessed:1580 case MMR_AlreadyProcessed: {1581 // Success. All of the directories we stepped through inherit this module1582 // map file.1583 const ModuleMapDirectoryState &MMDS = DirectoryModuleMap[*Dir];1584 for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)1585 DirectoryModuleMap[FixUpDirectories[I]] = MMDS;1586 return true;1587 }1588 case MMR_NoDirectory:1589 case MMR_InvalidModuleMap:1590 break;1591 }1592 1593 // If we hit the top of our search, we're done.1594 if (*Dir == Root)1595 return false;1596 1597 // Keep track of all of the directories we checked, so we can mark them as1598 // having module maps if we eventually do find a module map.1599 FixUpDirectories.push_back(*Dir);1600 } while (true);1601}1602 1603ModuleMap::KnownHeader1604HeaderSearch::findModuleForHeader(FileEntryRef File, bool AllowTextual,1605 bool AllowExcluded) const {1606 if (ExternalSource) {1607 // Make sure the external source has handled header info about this file,1608 // which includes whether the file is part of a module.1609 (void)getExistingFileInfo(File);1610 }1611 return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded);1612}1613 1614ArrayRef<ModuleMap::KnownHeader>1615HeaderSearch::findAllModulesForHeader(FileEntryRef File) const {1616 if (ExternalSource) {1617 // Make sure the external source has handled header info about this file,1618 // which includes whether the file is part of a module.1619 (void)getExistingFileInfo(File);1620 }1621 return ModMap.findAllModulesForHeader(File);1622}1623 1624ArrayRef<ModuleMap::KnownHeader>1625HeaderSearch::findResolvedModulesForHeader(FileEntryRef File) const {1626 if (ExternalSource) {1627 // Make sure the external source has handled header info about this file,1628 // which includes whether the file is part of a module.1629 (void)getExistingFileInfo(File);1630 }1631 return ModMap.findResolvedModulesForHeader(File);1632}1633 1634static bool suggestModule(HeaderSearch &HS, FileEntryRef File,1635 Module *RequestingModule,1636 ModuleMap::KnownHeader *SuggestedModule) {1637 ModuleMap::KnownHeader Module =1638 HS.findModuleForHeader(File, /*AllowTextual*/true);1639 1640 // If this module specifies [no_undeclared_includes], we cannot find any1641 // file that's in a non-dependency module.1642 if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {1643 HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/ false);1644 if (!RequestingModule->directlyUses(Module.getModule())) {1645 // Builtin headers are a special case. Multiple modules can use the same1646 // builtin as a modular header (see also comment in1647 // ShouldEnterIncludeFile()), so the builtin header may have been1648 // "claimed" by an unrelated module. This shouldn't prevent us from1649 // including the builtin header textually in this module.1650 if (HS.getModuleMap().isBuiltinHeader(File)) {1651 if (SuggestedModule)1652 *SuggestedModule = ModuleMap::KnownHeader();1653 return true;1654 }1655 // TODO: Add this module (or just its module map file) into something like1656 // `RequestingModule->AffectingClangModules`.1657 return false;1658 }1659 }1660 1661 if (SuggestedModule)1662 *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)1663 ? ModuleMap::KnownHeader()1664 : Module;1665 1666 return true;1667}1668 1669bool HeaderSearch::findUsableModuleForHeader(1670 FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule,1671 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {1672 if (needModuleLookup(RequestingModule, SuggestedModule)) {1673 // If there is a module that corresponds to this header, suggest it.1674 hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);1675 return suggestModule(*this, File, RequestingModule, SuggestedModule);1676 }1677 return true;1678}1679 1680bool HeaderSearch::findUsableModuleForFrameworkHeader(1681 FileEntryRef File, StringRef FrameworkName, Module *RequestingModule,1682 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {1683 // If we're supposed to suggest a module, look for one now.1684 if (needModuleLookup(RequestingModule, SuggestedModule)) {1685 // Find the top-level framework based on this framework.1686 SmallVector<std::string, 4> SubmodulePath;1687 OptionalDirectoryEntryRef TopFrameworkDir =1688 ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);1689 assert(TopFrameworkDir && "Could not find the top-most framework dir");1690 1691 // Determine the name of the top-level framework.1692 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());1693 1694 // Load this framework module. If that succeeds, find the suggested module1695 // for this header, if any.1696 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);1697 1698 // FIXME: This can find a module not part of ModuleName, which is1699 // important so that we're consistent about whether this header1700 // corresponds to a module. Possibly we should lock down framework modules1701 // so that this is not possible.1702 return suggestModule(*this, File, RequestingModule, SuggestedModule);1703 }1704 return true;1705}1706 1707static OptionalFileEntryRef getPrivateModuleMap(FileEntryRef File,1708 FileManager &FileMgr,1709 DiagnosticsEngine &Diags,1710 bool Diagnose = true) {1711 StringRef Filename = llvm::sys::path::filename(File.getName());1712 SmallString<128> PrivateFilename(File.getDir().getName());1713 if (Filename == "module.map")1714 llvm::sys::path::append(PrivateFilename, "module_private.map");1715 else if (Filename == "module.modulemap")1716 llvm::sys::path::append(PrivateFilename, "module.private.modulemap");1717 else1718 return std::nullopt;1719 auto PMMFile = FileMgr.getOptionalFileRef(PrivateFilename);1720 if (PMMFile) {1721 if (Diagnose && Filename == "module.map")1722 Diags.Report(diag::warn_deprecated_module_dot_map)1723 << PrivateFilename << 11724 << File.getDir().getName().ends_with(".framework");1725 }1726 return PMMFile;1727}1728 1729bool HeaderSearch::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,1730 FileID ID, unsigned *Offset,1731 StringRef OriginalModuleMapFile) {1732 // Find the directory for the module. For frameworks, that may require going1733 // up from the 'Modules' directory.1734 OptionalDirectoryEntryRef Dir;1735 if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) {1736 Dir = FileMgr.getOptionalDirectoryRef(".");1737 } else {1738 if (!OriginalModuleMapFile.empty()) {1739 // We're building a preprocessed module map. Find or invent the directory1740 // that it originally occupied.1741 Dir = FileMgr.getOptionalDirectoryRef(1742 llvm::sys::path::parent_path(OriginalModuleMapFile));1743 if (!Dir) {1744 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);1745 Dir = FakeFile.getDir();1746 }1747 } else {1748 Dir = File.getDir();1749 }1750 1751 assert(Dir && "parent must exist");1752 StringRef DirName(Dir->getName());1753 if (llvm::sys::path::filename(DirName) == "Modules") {1754 DirName = llvm::sys::path::parent_path(DirName);1755 if (DirName.ends_with(".framework"))1756 if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))1757 Dir = *MaybeDir;1758 // FIXME: This assert can fail if there's a race between the above check1759 // and the removal of the directory.1760 assert(Dir && "parent must exist");1761 }1762 }1763 1764 assert(Dir && "module map home directory must exist");1765 switch (parseAndLoadModuleMapFileImpl(File, IsSystem, *Dir, ID, Offset)) {1766 case MMR_AlreadyProcessed:1767 case MMR_NewlyProcessed:1768 return false;1769 case MMR_NoDirectory:1770 case MMR_InvalidModuleMap:1771 return true;1772 }1773 llvm_unreachable("Unknown load module map result");1774}1775 1776HeaderSearch::ModuleMapResult1777HeaderSearch::parseAndLoadModuleMapFileImpl(FileEntryRef File, bool IsSystem,1778 DirectoryEntryRef Dir, FileID ID,1779 unsigned *Offset) {1780 // Check whether we've already loaded this module map, and mark it as being1781 // loaded in case we recursively try to load it from itself.1782 auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));1783 if (!AddResult.second)1784 return AddResult.first->second ? MMR_AlreadyProcessed1785 : MMR_InvalidModuleMap;1786 1787 if (ModMap.parseAndLoadModuleMapFile(File, IsSystem, Dir, ID, Offset)) {1788 LoadedModuleMaps[File] = false;1789 return MMR_InvalidModuleMap;1790 }1791 1792 // Try to load a corresponding private module map.1793 if (OptionalFileEntryRef PMMFile =1794 getPrivateModuleMap(File, FileMgr, Diags, !ParsedModuleMaps[File])) {1795 if (ModMap.parseAndLoadModuleMapFile(*PMMFile, IsSystem, Dir)) {1796 LoadedModuleMaps[File] = false;1797 return MMR_InvalidModuleMap;1798 }1799 }1800 1801 // This directory has a module map.1802 return MMR_NewlyProcessed;1803}1804 1805HeaderSearch::ModuleMapResult1806HeaderSearch::parseModuleMapFileImpl(FileEntryRef File, bool IsSystem,1807 DirectoryEntryRef Dir, FileID ID) {1808 // Check whether we've already parsed this module map, and mark it as being1809 // parsed in case we recursively try to parse it from itself.1810 auto AddResult = ParsedModuleMaps.insert(std::make_pair(File, true));1811 if (!AddResult.second)1812 return AddResult.first->second ? MMR_AlreadyProcessed1813 : MMR_InvalidModuleMap;1814 1815 if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID)) {1816 ParsedModuleMaps[File] = false;1817 return MMR_InvalidModuleMap;1818 }1819 1820 // Try to parse a corresponding private module map.1821 if (OptionalFileEntryRef PMMFile =1822 getPrivateModuleMap(File, FileMgr, Diags)) {1823 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {1824 ParsedModuleMaps[File] = false;1825 return MMR_InvalidModuleMap;1826 }1827 }1828 1829 // This directory has a module map.1830 return MMR_NewlyProcessed;1831}1832 1833OptionalFileEntryRef1834HeaderSearch::lookupModuleMapFile(DirectoryEntryRef Dir, bool IsFramework) {1835 if (!HSOpts.ImplicitModuleMaps)1836 return std::nullopt;1837 // For frameworks, the preferred spelling is Modules/module.modulemap, but1838 // module.map at the framework root is also accepted.1839 SmallString<128> ModuleMapFileName(Dir.getName());1840 if (IsFramework)1841 llvm::sys::path::append(ModuleMapFileName, "Modules");1842 llvm::sys::path::append(ModuleMapFileName, "module.modulemap");1843 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))1844 return *F;1845 1846 // Continue to allow module.map, but warn it's deprecated.1847 ModuleMapFileName = Dir.getName();1848 llvm::sys::path::append(ModuleMapFileName, "module.map");1849 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {1850 Diags.Report(diag::warn_deprecated_module_dot_map)1851 << ModuleMapFileName << 0 << IsFramework;1852 return *F;1853 }1854 1855 // For frameworks, allow to have a private module map with a preferred1856 // spelling when a public module map is absent.1857 if (IsFramework) {1858 ModuleMapFileName = Dir.getName();1859 llvm::sys::path::append(ModuleMapFileName, "Modules",1860 "module.private.modulemap");1861 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))1862 return *F;1863 }1864 return std::nullopt;1865}1866 1867Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,1868 bool IsSystem) {1869 // Try to load a module map file.1870 switch (parseAndLoadModuleMapFile(Dir, IsSystem, /*IsFramework*/ true)) {1871 case MMR_InvalidModuleMap:1872 // Try to infer a module map from the framework directory.1873 if (HSOpts.ImplicitModuleMaps)1874 ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr);1875 break;1876 1877 case MMR_NoDirectory:1878 return nullptr;1879 1880 case MMR_AlreadyProcessed:1881 case MMR_NewlyProcessed:1882 break;1883 }1884 1885 return ModMap.findOrLoadModule(Name);1886}1887 1888HeaderSearch::ModuleMapResult1889HeaderSearch::parseAndLoadModuleMapFile(StringRef DirName, bool IsSystem,1890 bool IsFramework) {1891 if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))1892 return parseAndLoadModuleMapFile(*Dir, IsSystem, IsFramework);1893 1894 return MMR_NoDirectory;1895}1896 1897HeaderSearch::ModuleMapResult1898HeaderSearch::parseAndLoadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,1899 bool IsFramework) {1900 auto InsertRes = DirectoryModuleMap.insert(std::pair{1901 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});1902 ModuleMapDirectoryState &MMState = InsertRes.first->second;1903 if (!InsertRes.second) {1904 switch (MMState.Status) {1905 case ModuleMapDirectoryState::Parsed:1906 break;1907 case ModuleMapDirectoryState::Loaded:1908 return MMR_AlreadyProcessed;1909 case ModuleMapDirectoryState::Invalid:1910 return MMR_InvalidModuleMap;1911 };1912 }1913 1914 if (!MMState.ModuleMapFile)1915 MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);1916 1917 if (MMState.ModuleMapFile) {1918 ModuleMapResult Result =1919 parseAndLoadModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);1920 // Add Dir explicitly in case ModuleMapFile is in a subdirectory.1921 // E.g. Foo.framework/Modules/module.modulemap1922 // ^Dir ^ModuleMapFile1923 if (Result == MMR_NewlyProcessed)1924 MMState.Status = ModuleMapDirectoryState::Loaded;1925 else if (Result == MMR_InvalidModuleMap)1926 MMState.Status = ModuleMapDirectoryState::Invalid;1927 return Result;1928 }1929 return MMR_InvalidModuleMap;1930}1931 1932HeaderSearch::ModuleMapResult1933HeaderSearch::parseModuleMapFile(StringRef DirName, bool IsSystem,1934 bool IsFramework) {1935 if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))1936 return parseModuleMapFile(*Dir, IsSystem, IsFramework);1937 1938 return MMR_NoDirectory;1939}1940 1941HeaderSearch::ModuleMapResult1942HeaderSearch::parseModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,1943 bool IsFramework) {1944 auto InsertRes = DirectoryModuleMap.insert(std::pair{1945 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});1946 ModuleMapDirectoryState &MMState = InsertRes.first->second;1947 if (!InsertRes.second) {1948 switch (MMState.Status) {1949 case ModuleMapDirectoryState::Parsed:1950 case ModuleMapDirectoryState::Loaded:1951 return MMR_AlreadyProcessed;1952 case ModuleMapDirectoryState::Invalid:1953 return MMR_InvalidModuleMap;1954 };1955 }1956 1957 if (!MMState.ModuleMapFile)1958 MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);1959 1960 if (MMState.ModuleMapFile) {1961 ModuleMapResult Result =1962 parseModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);1963 // Add Dir explicitly in case ModuleMapFile is in a subdirectory.1964 // E.g. Foo.framework/Modules/module.modulemap1965 // ^Dir ^ModuleMapFile1966 if (Result == MMR_NewlyProcessed)1967 MMState.Status = ModuleMapDirectoryState::Parsed;1968 else if (Result == MMR_InvalidModuleMap)1969 MMState.Status = ModuleMapDirectoryState::Invalid;1970 return Result;1971 }1972 return MMR_InvalidModuleMap;1973}1974 1975void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {1976 Modules.clear();1977 1978 if (HSOpts.ImplicitModuleMaps) {1979 // Load module maps for each of the header search directories.1980 for (DirectoryLookup &DL : search_dir_range()) {1981 bool IsSystem = DL.isSystemHeaderDirectory();1982 if (DL.isFramework()) {1983 std::error_code EC;1984 SmallString<128> DirNative;1985 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);1986 1987 // Search each of the ".framework" directories to load them as modules.1988 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();1989 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),1990 DirEnd;1991 Dir != DirEnd && !EC; Dir.increment(EC)) {1992 if (llvm::sys::path::extension(Dir->path()) != ".framework")1993 continue;1994 1995 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());1996 if (!FrameworkDir)1997 continue;1998 1999 // Load this framework module.2000 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,2001 IsSystem);2002 }2003 continue;2004 }2005 2006 // FIXME: Deal with header maps.2007 if (DL.isHeaderMap())2008 continue;2009 2010 // Try to load a module map file for the search directory.2011 parseAndLoadModuleMapFile(*DL.getDirRef(), IsSystem,2012 /*IsFramework*/ false);2013 2014 // Try to load module map files for immediate subdirectories of this2015 // search directory.2016 loadSubdirectoryModuleMaps(DL);2017 }2018 }2019 2020 // Populate the list of modules.2021 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));2022}2023 2024void HeaderSearch::loadTopLevelSystemModules() {2025 if (!HSOpts.ImplicitModuleMaps)2026 return;2027 2028 // Load module maps for each of the header search directories.2029 for (const DirectoryLookup &DL : search_dir_range()) {2030 // We only care about normal header directories.2031 if (!DL.isNormalDir())2032 continue;2033 2034 // Try to load a module map file for the search directory.2035 parseAndLoadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(),2036 DL.isFramework());2037 }2038}2039 2040void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {2041 assert(HSOpts.ImplicitModuleMaps &&2042 "Should not be loading subdirectory module maps");2043 2044 if (SearchDir.haveSearchedAllModuleMaps())2045 return;2046 2047 std::error_code EC;2048 SmallString<128> Dir = SearchDir.getDirRef()->getName();2049 FileMgr.makeAbsolutePath(Dir);2050 SmallString<128> DirNative;2051 llvm::sys::path::native(Dir, DirNative);2052 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();2053 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;2054 Dir != DirEnd && !EC; Dir.increment(EC)) {2055 if (Dir->type() == llvm::sys::fs::file_type::regular_file)2056 continue;2057 bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";2058 if (IsFramework == SearchDir.isFramework())2059 parseAndLoadModuleMapFile(Dir->path(),2060 SearchDir.isSystemHeaderDirectory(),2061 SearchDir.isFramework());2062 }2063 2064 SearchDir.setSearchedAllModuleMaps(true);2065}2066 2067std::string HeaderSearch::suggestPathToFileForDiagnostics(2068 FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {2069 return suggestPathToFileForDiagnostics(File.getName(), /*WorkingDir=*/"",2070 MainFile, IsAngled);2071}2072 2073std::string HeaderSearch::suggestPathToFileForDiagnostics(2074 llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,2075 bool *IsAngled) const {2076 using namespace llvm::sys;2077 2078 llvm::SmallString<32> FilePath = File;2079 if (!WorkingDir.empty() && !path::is_absolute(FilePath))2080 path::make_absolute(WorkingDir, FilePath);2081 // remove_dots switches to backslashes on windows as a side-effect!2082 // We always want to suggest forward slashes for includes.2083 // (not remove_dots(..., posix) as that misparses windows paths).2084 path::remove_dots(FilePath, /*remove_dot_dot=*/true);2085 path::native(FilePath, path::Style::posix);2086 File = FilePath;2087 2088 unsigned BestPrefixLength = 0;2089 // Checks whether `Dir` is a strict path prefix of `File`. If so and that's2090 // the longest prefix we've seen so for it, returns true and updates the2091 // `BestPrefixLength` accordingly.2092 auto CheckDir = [&](llvm::SmallString<32> Dir) -> bool {2093 if (!WorkingDir.empty() && !path::is_absolute(Dir))2094 path::make_absolute(WorkingDir, Dir);2095 path::remove_dots(Dir, /*remove_dot_dot=*/true);2096 for (auto NI = path::begin(File), NE = path::end(File),2097 DI = path::begin(Dir), DE = path::end(Dir);2098 NI != NE; ++NI, ++DI) {2099 if (DI == DE) {2100 // Dir is a prefix of File, up to choice of path separators.2101 unsigned PrefixLength = NI - path::begin(File);2102 if (PrefixLength > BestPrefixLength) {2103 BestPrefixLength = PrefixLength;2104 return true;2105 }2106 break;2107 }2108 2109 // Consider all path separators equal.2110 if (NI->size() == 1 && DI->size() == 1 &&2111 path::is_separator(NI->front()) && path::is_separator(DI->front()))2112 continue;2113 2114 // Special case Apple .sdk folders since the search path is typically a2115 // symlink like `iPhoneSimulator14.5.sdk` while the file is instead2116 // located in `iPhoneSimulator.sdk` (the real folder).2117 if (NI->ends_with(".sdk") && DI->ends_with(".sdk")) {2118 StringRef NBasename = path::stem(*NI);2119 StringRef DBasename = path::stem(*DI);2120 if (DBasename.starts_with(NBasename))2121 continue;2122 }2123 2124 if (*NI != *DI)2125 break;2126 }2127 return false;2128 };2129 2130 bool BestPrefixIsFramework = false;2131 for (const DirectoryLookup &DL : search_dir_range()) {2132 if (DL.isNormalDir()) {2133 StringRef Dir = DL.getDirRef()->getName();2134 if (CheckDir(Dir)) {2135 if (IsAngled)2136 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());2137 BestPrefixIsFramework = false;2138 }2139 } else if (DL.isFramework()) {2140 StringRef Dir = DL.getFrameworkDirRef()->getName();2141 if (CheckDir(Dir)) {2142 // Framework includes by convention use <>.2143 if (IsAngled)2144 *IsAngled = BestPrefixLength;2145 BestPrefixIsFramework = true;2146 }2147 }2148 }2149 2150 // Try to shorten include path using TUs directory, if we couldn't find any2151 // suitable prefix in include search paths.2152 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {2153 if (IsAngled)2154 *IsAngled = false;2155 BestPrefixIsFramework = false;2156 }2157 2158 // Try resolving resulting filename via reverse search in header maps,2159 // key from header name is user preferred name for the include file.2160 StringRef Filename = File.drop_front(BestPrefixLength);2161 for (const DirectoryLookup &DL : search_dir_range()) {2162 if (!DL.isHeaderMap())2163 continue;2164 2165 StringRef SpelledFilename =2166 DL.getHeaderMap()->reverseLookupFilename(Filename);2167 if (!SpelledFilename.empty()) {2168 Filename = SpelledFilename;2169 BestPrefixIsFramework = false;2170 break;2171 }2172 }2173 2174 // If the best prefix is a framework path, we need to compute the proper2175 // include spelling for the framework header.2176 bool IsPrivateHeader;2177 SmallString<128> FrameworkName, IncludeSpelling;2178 if (BestPrefixIsFramework &&2179 isFrameworkStylePath(Filename, IsPrivateHeader, FrameworkName,2180 IncludeSpelling)) {2181 Filename = IncludeSpelling;2182 }2183 return path::convert_to_slash(Filename);2184}2185 2186void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path,2187 SmallVectorImpl<char> &NormalizedPath) {2188 NormalizedPath.assign(Path.begin(), Path.end());2189 if (!NormalizedPath.empty()) {2190 FileMgr.makeAbsolutePath(NormalizedPath);2191 llvm::sys::path::remove_dots(NormalizedPath);2192 }2193}2194