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-exception
6//
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(ID: 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(II: *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 (const auto &[FE, HFI] : FileInfo)
95 NumOnceOnlyFiles += (HFI.isPragmaOnce || HFI.isImport);
96 llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n";
97
98 llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n"
99 << " " << NumMultiIncludeFileOptzn
100 << " #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(n: SearchDirs.size(), x: 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(position: SearchDirs.begin() + idx, x: dir);
124 SearchDirsUsage.insert(position: SearchDirsUsage.begin() + idx, x: 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(Val: 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 by
151 // `createVFSFromOverlayFiles`. But at least exclude the ones with null
152 // OverlayFileDir.
153 RootFS.visit(Callback: [&](llvm::vfs::FileSystem &FS) {
154 if (auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(Val: &FS)) {
155 // Skip a `RedirectingFileSystem` with null OverlayFileDir which indicates
156 // that they aren't created by createVFSFromOverlayFiles from the overlays
157 // in HeaderSearchOption::VFSOverlayFiles.
158 if (!RFS->getOverlayFileDir().empty()) {
159 VFSUsage.push_back(x: 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(first: VFSUsage.begin(), last: VFSUsage.end());
169 return VFSUsage;
170}
171
172/// CreateHeaderMap - This method returns a HeaderMap for the specified
173/// 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 are
180 // 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, FM&: FileMgr)) {
186 HeaderMaps.emplace_back(args&: FE, args: 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(Elt: std::string(HM.first.getName()));
198}
199
200ModuleFileName HeaderSearch::getCachedModuleFileName(Module *Module) {
201 OptionalFileEntryRef ModuleMap =
202 getModuleMap().getModuleMapFileForUniquing(M: Module);
203 // The ModuleMap maybe a nullptr, when we load a cached C++ module without
204 // *.modulemap file. In this case, just return an empty string.
205 if (!ModuleMap)
206 return {};
207 return getCachedModuleFileName(ModuleName: Module->Name, ModuleMapPath: ModuleMap->getNameAsRequested());
208}
209
210ModuleFileName HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,
211 bool FileMapOnly) {
212 // First check the module name to pcm file map.
213 auto i(HSOpts.PrebuiltModuleFiles.find(x: ModuleName));
214 if (i != HSOpts.PrebuiltModuleFiles.end())
215 return ModuleFileName::makeExplicit(Name: 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 pcm
221 // file.
222 for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {
223 SmallString<256> Result(Dir);
224 FileMgr.makeAbsolutePath(Path&: Result);
225 if (ModuleName.contains(C: ':'))
226 // The separator of C++20 modules partitions (':') is not good for file
227 // systems, here clang and gcc choose '-' by default since it is not a
228 // valid character of C++ indentifiers. So we could avoid conflicts.
229 llvm::sys::path::append(path&: Result, a: ModuleName.split(Separator: ':').first + "-" +
230 ModuleName.split(Separator: ':').second +
231 ".pcm");
232 else
233 llvm::sys::path::append(path&: Result, a: ModuleName + ".pcm");
234 if (getFileMgr().getOptionalFileRef(Filename: Result))
235 return ModuleFileName::makeExplicit(Name: Result);
236 }
237
238 return {};
239}
240
241ModuleFileName HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) {
242 OptionalFileEntryRef ModuleMap =
243 getModuleMap().getModuleMapFileForUniquing(M: Module);
244 StringRef ModuleName = Module->Name;
245 StringRef ModuleMapPath = ModuleMap->getName();
246 for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {
247 SmallString<256> CachePath(Dir);
248 FileMgr.makeAbsolutePath(Path&: CachePath);
249 ModuleFileName FileName =
250 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, NormalizedCachePath: CachePath);
251 if (!FileName.empty() && getFileMgr().getOptionalFileRef(Filename: FileName))
252 return ModuleFileName::makeExplicit(Name: FileName);
253 }
254 return {};
255}
256
257ModuleFileName HeaderSearch::getCachedModuleFileName(StringRef ModuleName,
258 StringRef ModuleMapPath) {
259 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
260 NormalizedCachePath: getNormalizedModuleCachePath());
261}
262
263ModuleFileName HeaderSearch::getCachedModuleFileNameImpl(
264 StringRef ModuleName, StringRef ModuleMapPath, StringRef CachePath) {
265 // If we don't have a module cache path or aren't supposed to use one, we
266 // can't do anything.
267 if (CachePath.empty())
268 return {};
269
270 // Note: This re-implements part of createSpecificModuleCachePathImpl() in
271 // order to be able to correctly construct ModuleFileName.
272
273 SmallString<256> Result(CachePath);
274 unsigned SuffixBegin = Result.size();
275
276 if (HSOpts.DisableModuleHash) {
277 llvm::sys::path::append(path&: Result, a: ModuleName + ".pcm");
278 } else {
279 llvm::sys::path::append(path&: Result, a: ContextHash);
280
281 // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
282 // ideally be globally unique to this particular module. Name collisions
283 // in the hash are safe (because any translation unit can only import one
284 // module with each name), but result in a loss of caching.
285 //
286 // To avoid false-negatives, we form as canonical a path as we can.
287 SmallString<128> CanonicalPath(ModuleMapPath);
288 if (getModuleMap().canonicalizeModuleMapPath(Path&: CanonicalPath))
289 return {};
290
291 auto Hash = llvm::xxh3_64bits(data: CanonicalPath);
292
293 SmallString<128> HashStr;
294 llvm::APInt(64, Hash).toStringUnsigned(Str&: HashStr, /*Radix*/36);
295 llvm::sys::path::append(path&: Result, a: ModuleName + "-" + HashStr + ".pcm");
296 }
297 return ModuleFileName::makeImplicit(Name: Result, SuffixLength: Result.size() - SuffixBegin);
298}
299
300Module *HeaderSearch::lookupModule(StringRef ModuleName,
301 SourceLocation ImportLoc, bool AllowSearch,
302 bool AllowExtraModuleMapSearch) {
303 // Look in the module map to determine if there is a module by this name.
304 Module *Module = ModMap.findOrLoadModule(Name: ModuleName);
305 if (Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
306 return Module;
307
308 StringRef SearchName = ModuleName;
309 Module = lookupModule(ModuleName, SearchName, ImportLoc,
310 AllowExtraModuleMapSearch);
311
312 // The facility for "private modules" -- adjacent, optional module maps named
313 // module.private.modulemap that are supposed to define private submodules --
314 // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.
315 //
316 // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate
317 // should also rename to Foo_Private. Representing private as submodules
318 // could force building unwanted dependencies into the parent module and cause
319 // dependency cycles.
320 if (!Module && SearchName.consume_back(Suffix: "_Private"))
321 Module = lookupModule(ModuleName, SearchName, ImportLoc,
322 AllowExtraModuleMapSearch);
323 if (!Module && SearchName.consume_back(Suffix: "Private"))
324 Module = lookupModule(ModuleName, SearchName, ImportLoc,
325 AllowExtraModuleMapSearch);
326 return Module;
327}
328
329Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
330 SourceLocation ImportLoc,
331 bool AllowExtraModuleMapSearch) {
332 Module *Module = nullptr;
333
334 // Look through the various header search paths to load any available module
335 // maps, searching for a module map that describes this module.
336 for (DirectoryLookup &Dir : search_dir_range()) {
337 if (Dir.isFramework()) {
338 // Search for or infer a module map for a framework. Here we use
339 // SearchName rather than ModuleName, to permit finding private modules
340 // named FooPrivate in buggy frameworks named Foo.
341 SmallString<128> FrameworkDirName;
342 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
343 llvm::sys::path::append(path&: FrameworkDirName, a: SearchName + ".framework");
344 if (auto FrameworkDir =
345 FileMgr.getOptionalDirectoryRef(DirName: FrameworkDirName)) {
346 bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;
347 Module = loadFrameworkModule(Name: ModuleName, Dir: *FrameworkDir, IsSystem,
348 /*ImplicitlyDiscovered=*/true);
349 if (Module)
350 break;
351 }
352 }
353
354 // FIXME: Figure out how header maps and module maps will work together.
355
356 // Only deal with normal search directories.
357 if (!Dir.isNormalDir())
358 continue;
359
360 bool IsSystem = Dir.isSystemHeaderDirectory();
361 // Only returns std::nullopt if not a normal directory, which we just
362 // checked
363 DirectoryEntryRef NormalDir = *Dir.getDirRef();
364 // Search for a module map file in this directory.
365 if (parseModuleMapFile(Dir: NormalDir, IsSystem, /*ImplicitlyDiscovered=*/true,
366 /*IsFramework*/ false) == MMR_NewlyProcessed) {
367 // We just parsed a module map file; check whether the module can be
368 // loaded now.
369 Module = ModMap.findOrLoadModule(Name: ModuleName);
370 if (Module)
371 break;
372 }
373
374 // Search for a module map in a subdirectory with the same name as the
375 // module.
376 SmallString<128> NestedModuleMapDirName;
377 NestedModuleMapDirName = Dir.getDirRef()->getName();
378 llvm::sys::path::append(path&: NestedModuleMapDirName, a: ModuleName);
379 if (parseModuleMapFile(DirName: NestedModuleMapDirName, IsSystem,
380 /*ImplicitlyDiscovered=*/true,
381 /*IsFramework*/ false) == MMR_NewlyProcessed) {
382 // If we just parsed a module map file, look for the module again.
383 Module = ModMap.findOrLoadModule(Name: ModuleName);
384 if (Module)
385 break;
386 }
387
388 if (HSOpts.AllowModuleMapSubdirectorySearch) {
389 // If we've already performed the exhaustive search for module maps in
390 // this search directory, don't do it again.
391 if (Dir.haveSearchedAllModuleMaps())
392 continue;
393
394 // Load all module maps in the immediate subdirectories of this search
395 // directory if ModuleName was from @import.
396 if (AllowExtraModuleMapSearch)
397 loadSubdirectoryModuleMaps(SearchDir&: Dir);
398
399 // Look again for the module.
400 Module = ModMap.findOrLoadModule(Name: ModuleName);
401 if (Module)
402 break;
403 }
404 }
405
406 return Module;
407}
408
409void HeaderSearch::indexInitialHeaderMaps() {
410 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
411
412 // Iterate over all filename keys and associate them with the index i.
413 for (unsigned i = 0; i != SearchDirs.size(); ++i) {
414 auto &Dir = SearchDirs[i];
415
416 // We're concerned with only the initial contiguous run of header
417 // maps within SearchDirs, which can be 99% of SearchDirs when
418 // SearchDirs.size() is ~10000.
419 if (!Dir.isHeaderMap()) {
420 SearchDirHeaderMapIndex = std::move(Index);
421 FirstNonHeaderMapSearchDirIdx = i;
422 break;
423 }
424
425 // Give earlier keys precedence over identical later keys.
426 auto Callback = [&](StringRef Filename) {
427 Index.try_emplace(Key: Filename.lower(), Args&: i);
428 };
429 Dir.getHeaderMap()->forEachKey(Callback);
430 }
431}
432
433//===----------------------------------------------------------------------===//
434// File lookup within a DirectoryLookup scope
435//===----------------------------------------------------------------------===//
436
437/// getName - Return the directory or filename corresponding to this lookup
438/// object.
439StringRef DirectoryLookup::getName() const {
440 if (isNormalDir())
441 return getDirRef()->getName();
442 if (isFramework())
443 return getFrameworkDirRef()->getName();
444 assert(isHeaderMap() && "Unknown DirectoryLookup");
445 return getHeaderMap()->getFileName();
446}
447
448OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule(
449 StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,
450 bool IsSystemHeaderDir, Module *RequestingModule,
451 ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/,
452 bool CacheFailures /*=true*/) {
453 // If we have a module map that might map this header, load it and
454 // check whether we'll have a suggestion for a module.
455 auto File = getFileMgr().getFileRef(Filename: FileName, OpenFile, CacheFailure: CacheFailures);
456 if (!File) {
457 // For rare, surprising errors (e.g. "out of file handles"), diag the EC
458 // message.
459 std::error_code EC = llvm::errorToErrorCode(Err: File.takeError());
460 if (EC != llvm::errc::no_such_file_or_directory &&
461 EC != llvm::errc::invalid_argument &&
462 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
463 Diags.Report(Loc: IncludeLoc, DiagID: diag::err_cannot_open_file)
464 << FileName << EC.message();
465 }
466 return std::nullopt;
467 }
468
469 // If there is a module that corresponds to this header, suggest it.
470 if (!findUsableModuleForHeader(
471 File: *File, Root: Dir ? Dir : File->getFileEntry().getDir(), RequestingModule,
472 SuggestedModule, IsSystemHeaderDir))
473 return std::nullopt;
474
475 return *File;
476}
477
478/// LookupFile - Lookup the specified file in this search path, returning it
479/// if it exists or returning null if not.
480OptionalFileEntryRef DirectoryLookup::LookupFile(
481 StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,
482 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
483 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
484 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
485 bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName,
486 bool OpenFile) const {
487 InUserSpecifiedSystemFramework = false;
488 IsInHeaderMap = false;
489 MappedName.clear();
490
491 SmallString<1024> TmpDir;
492 if (isNormalDir()) {
493 // Concatenate the requested file onto the directory.
494 TmpDir = getDirRef()->getName();
495 llvm::sys::path::append(path&: TmpDir, a: Filename);
496 if (SearchPath) {
497 StringRef SearchPathRef(getDirRef()->getName());
498 SearchPath->clear();
499 SearchPath->append(in_start: SearchPathRef.begin(), in_end: SearchPathRef.end());
500 }
501 if (RelativePath) {
502 RelativePath->clear();
503 RelativePath->append(in_start: Filename.begin(), in_end: Filename.end());
504 }
505
506 return HS.getFileAndSuggestModule(
507 FileName: TmpDir, IncludeLoc, Dir: getDir(), IsSystemHeaderDir: isSystemHeaderDirectory(),
508 RequestingModule, SuggestedModule, OpenFile);
509 }
510
511 if (isFramework())
512 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
513 RequestingModule, SuggestedModule,
514 InUserSpecifiedSystemFramework, IsFrameworkFound);
515
516 assert(isHeaderMap() && "Unknown directory lookup");
517 const HeaderMap *HM = getHeaderMap();
518 SmallString<1024> Path;
519 StringRef Dest = HM->lookupFilename(Filename, DestPath&: Path);
520 if (Dest.empty())
521 return std::nullopt;
522
523 IsInHeaderMap = true;
524
525 auto FixupSearchPathAndFindUsableModule =
526 [&](FileEntryRef File) -> OptionalFileEntryRef {
527 if (SearchPath) {
528 StringRef SearchPathRef(getName());
529 SearchPath->clear();
530 SearchPath->append(in_start: SearchPathRef.begin(), in_end: SearchPathRef.end());
531 }
532 if (RelativePath) {
533 RelativePath->clear();
534 RelativePath->append(in_start: Filename.begin(), in_end: Filename.end());
535 }
536 if (!HS.findUsableModuleForHeader(File, Root: File.getFileEntry().getDir(),
537 RequestingModule, SuggestedModule,
538 IsSystemHeaderDir: isSystemHeaderDirectory())) {
539 return std::nullopt;
540 }
541 return File;
542 };
543
544 // Check if the headermap maps the filename to a framework include
545 // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
546 // framework include.
547 if (llvm::sys::path::is_relative(path: Dest)) {
548 MappedName.append(in_start: Dest.begin(), in_end: Dest.end());
549 Filename = StringRef(MappedName.begin(), MappedName.size());
550 Dest = HM->lookupFilename(Filename, DestPath&: Path);
551 }
552
553 if (auto Res = HS.getFileMgr().getOptionalFileRef(Filename: Dest, OpenFile)) {
554 return FixupSearchPathAndFindUsableModule(*Res);
555 }
556
557 // Header maps need to be marked as used whenever the filename matches.
558 // The case where the target file **exists** is handled by callee of this
559 // function as part of the regular logic that applies to include search paths.
560 // The case where the target file **does not exist** is handled here:
561 HS.noteLookupUsage(HitIdx: HS.searchDirIdx(DL: *this), IncludeLoc);
562 return std::nullopt;
563}
564
565/// Given a framework directory, find the top-most framework directory.
566///
567/// \param FileMgr The file manager to use for directory lookups.
568/// \param DirName The name of the framework directory.
569/// \param SubmodulePath Will be populated with the submodule path from the
570/// returned top-level module to the originally named framework.
571static OptionalDirectoryEntryRef
572getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
573 SmallVectorImpl<std::string> &SubmodulePath) {
574 assert(llvm::sys::path::extension(DirName) == ".framework" &&
575 "Not a framework directory");
576
577 // Note: as an egregious but useful hack we use the real path here, because
578 // frameworks moving between top-level frameworks to embedded frameworks tend
579 // to be symlinked, and we base the logical structure of modules on the
580 // physical layout. In particular, we need to deal with crazy includes like
581 //
582 // #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h>
583 //
584 // where 'Bar' used to be embedded in 'Foo', is now a top-level framework
585 // which one should access with, e.g.,
586 //
587 // #include <Bar/Wibble.h>
588 //
589 // Similar issues occur when a top-level framework has moved into an
590 // embedded framework.
591 auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName);
592
593 if (TopFrameworkDir)
594 DirName = FileMgr.getCanonicalName(Dir: *TopFrameworkDir);
595 do {
596 // Get the parent directory name.
597 DirName = llvm::sys::path::parent_path(path: DirName);
598 if (DirName.empty())
599 break;
600
601 // Determine whether this directory exists.
602 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
603 if (!Dir)
604 break;
605
606 // If this is a framework directory, then we're a subframework of this
607 // framework.
608 if (llvm::sys::path::extension(path: DirName) == ".framework") {
609 SubmodulePath.push_back(Elt: std::string(llvm::sys::path::stem(path: DirName)));
610 TopFrameworkDir = *Dir;
611 }
612 } while (true);
613
614 return TopFrameworkDir;
615}
616
617static bool needModuleLookup(Module *RequestingModule,
618 bool HasSuggestedModule) {
619 return HasSuggestedModule ||
620 (RequestingModule && RequestingModule->NoUndeclaredIncludes);
621}
622
623/// DoFrameworkLookup - Do a lookup of the specified file in the current
624/// DirectoryLookup, which is a framework directory.
625OptionalFileEntryRef DirectoryLookup::DoFrameworkLookup(
626 StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
627 SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
628 ModuleMap::KnownHeader *SuggestedModule,
629 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {
630 FileManager &FileMgr = HS.getFileMgr();
631
632 // Framework names must have a '/' in the filename.
633 size_t SlashPos = Filename.find(C: '/');
634 if (SlashPos == StringRef::npos)
635 return std::nullopt;
636
637 // Find out if this is the home for the specified framework, by checking
638 // HeaderSearch. Possible answers are yes/no and unknown.
639 FrameworkCacheEntry &CacheEntry =
640 HS.LookupFrameworkCache(FWName: Filename.substr(Start: 0, N: SlashPos));
641
642 // If it is known and in some other directory, fail.
643 if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef())
644 return std::nullopt;
645
646 // Otherwise, construct the path to this framework dir.
647
648 // FrameworkName = "/System/Library/Frameworks/"
649 SmallString<1024> FrameworkName;
650 FrameworkName += getFrameworkDirRef()->getName();
651 if (FrameworkName.empty() || FrameworkName.back() != '/')
652 FrameworkName.push_back(Elt: '/');
653
654 // FrameworkName = "/System/Library/Frameworks/Cocoa"
655 StringRef ModuleName(Filename.begin(), SlashPos);
656 FrameworkName += ModuleName;
657
658 // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
659 FrameworkName += ".framework/";
660
661 // If the cache entry was unresolved, populate it now.
662 if (!CacheEntry.Directory) {
663 ++NumFrameworkLookups;
664
665 // If the framework dir doesn't exist, we fail.
666 auto Dir = FileMgr.getOptionalDirectoryRef(DirName: FrameworkName);
667 if (!Dir)
668 return std::nullopt;
669
670 // Otherwise, if it does, remember that this is the right direntry for this
671 // framework.
672 CacheEntry.Directory = getFrameworkDirRef();
673
674 // If this is a user search directory, check if the framework has been
675 // user-specified as a system framework.
676 if (getDirCharacteristic() == SrcMgr::C_User) {
677 SmallString<1024> SystemFrameworkMarker(FrameworkName);
678 SystemFrameworkMarker += ".system_framework";
679 if (FileMgr.getOptionalFileRef(Filename: SystemFrameworkMarker))
680 CacheEntry.IsUserSpecifiedSystemFramework = true;
681 }
682 }
683
684 // Set out flags.
685 InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
686 IsFrameworkFound = CacheEntry.Directory.has_value();
687
688 if (RelativePath) {
689 RelativePath->clear();
690 RelativePath->append(in_start: Filename.begin()+SlashPos+1, in_end: Filename.end());
691 }
692
693 // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
694 unsigned OrigSize = FrameworkName.size();
695
696 FrameworkName += "Headers/";
697
698 if (SearchPath) {
699 SearchPath->clear();
700 // Without trailing '/'.
701 SearchPath->append(in_start: FrameworkName.begin(), in_end: FrameworkName.end()-1);
702 }
703
704 FrameworkName.append(in_start: Filename.begin()+SlashPos+1, in_end: Filename.end());
705
706 auto File =
707 FileMgr.getOptionalFileRef(Filename: FrameworkName, /*OpenFile=*/!SuggestedModule);
708 if (!File) {
709 // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
710 const char *Private = "Private";
711 FrameworkName.insert(I: FrameworkName.begin()+OrigSize, From: Private,
712 To: Private+strlen(s: Private));
713 if (SearchPath)
714 SearchPath->insert(I: SearchPath->begin()+OrigSize, From: Private,
715 To: Private+strlen(s: Private));
716
717 File = FileMgr.getOptionalFileRef(Filename: FrameworkName,
718 /*OpenFile=*/!SuggestedModule);
719 }
720
721 // If we found the header and are allowed to suggest a module, do so now.
722 if (File && needModuleLookup(RequestingModule, HasSuggestedModule: SuggestedModule)) {
723 // Find the framework in which this header occurs.
724 StringRef FrameworkPath = File->getDir().getName();
725 bool FoundFramework = false;
726 do {
727 // Determine whether this directory exists.
728 auto Dir = FileMgr.getOptionalDirectoryRef(DirName: FrameworkPath);
729 if (!Dir)
730 break;
731
732 // If this is a framework directory, then we're a subframework of this
733 // framework.
734 if (llvm::sys::path::extension(path: FrameworkPath) == ".framework") {
735 FoundFramework = true;
736 break;
737 }
738
739 // Get the parent directory name.
740 FrameworkPath = llvm::sys::path::parent_path(path: FrameworkPath);
741 if (FrameworkPath.empty())
742 break;
743 } while (true);
744
745 bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
746 if (FoundFramework) {
747 if (!HS.findUsableModuleForFrameworkHeader(File: *File, FrameworkName: FrameworkPath,
748 RequestingModule,
749 SuggestedModule, IsSystemFramework: IsSystem))
750 return std::nullopt;
751 } else {
752 if (!HS.findUsableModuleForHeader(File: *File, Root: getDir(), RequestingModule,
753 SuggestedModule, IsSystemHeaderDir: IsSystem))
754 return std::nullopt;
755 }
756 }
757 if (File)
758 return *File;
759 return std::nullopt;
760}
761
762void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
763 ConstSearchDirIterator HitIt,
764 SourceLocation Loc) {
765 CacheLookup.HitIt = HitIt;
766 noteLookupUsage(HitIdx: HitIt.Idx, IncludeLoc: Loc);
767}
768
769void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {
770 SearchDirsUsage[HitIdx] = true;
771
772 auto UserEntryIdxIt = SearchDirToHSEntry.find(Val: HitIdx);
773 if (UserEntryIdxIt != SearchDirToHSEntry.end())
774 Diags.Report(Loc, DiagID: diag::remark_pp_search_path_usage)
775 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
776}
777
778void HeaderSearch::setTarget(const TargetInfo &Target) {
779 ModMap.setTarget(Target);
780}
781
782//===----------------------------------------------------------------------===//
783// Header File Location.
784//===----------------------------------------------------------------------===//
785
786/// Return true with a diagnostic if the file that MSVC would have found
787/// fails to match the one that Clang would have found with MSVC header search
788/// disabled.
789static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,
790 OptionalFileEntryRef MSFE,
791 const FileEntry *FE,
792 SourceLocation IncludeLoc) {
793 if (MSFE && FE != *MSFE) {
794 Diags.Report(Loc: IncludeLoc, DiagID: diag::ext_pp_include_search_ms) << MSFE->getName();
795 return true;
796 }
797 return false;
798}
799
800static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
801 assert(!Str.empty());
802 char *CopyStr = Alloc.Allocate<char>(Num: Str.size()+1);
803 std::copy(first: Str.begin(), last: Str.end(), result: CopyStr);
804 CopyStr[Str.size()] = '\0';
805 return CopyStr;
806}
807
808static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,
809 SmallVectorImpl<char> &FrameworkName,
810 SmallVectorImpl<char> &IncludeSpelling) {
811 using namespace llvm::sys;
812 path::const_iterator I = path::begin(path: Path);
813 path::const_iterator E = path::end(path: Path);
814 IsPrivateHeader = false;
815
816 // Detect different types of framework style paths:
817 //
818 // ...Foo.framework/{Headers,PrivateHeaders}
819 // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders}
820 // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders}
821 // ...<other variations with 'Versions' like in the above path>
822 //
823 // and some other variations among these lines.
824 int FoundComp = 0;
825 while (I != E) {
826 if (*I == "Headers") {
827 ++FoundComp;
828 } else if (*I == "PrivateHeaders") {
829 ++FoundComp;
830 IsPrivateHeader = true;
831 } else if (I->ends_with(Suffix: ".framework")) {
832 StringRef Name = I->drop_back(N: 10); // Drop .framework
833 // Need to reset the strings and counter to support nested frameworks.
834 FrameworkName.clear();
835 FrameworkName.append(in_start: Name.begin(), in_end: Name.end());
836 IncludeSpelling.clear();
837 IncludeSpelling.append(in_start: Name.begin(), in_end: Name.end());
838 FoundComp = 1;
839 } else if (FoundComp >= 2) {
840 IncludeSpelling.push_back(Elt: '/');
841 IncludeSpelling.append(in_start: I->begin(), in_end: I->end());
842 }
843 ++I;
844 }
845
846 return !FrameworkName.empty() && FoundComp >= 2;
847}
848
849static void
850diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
851 StringRef Includer, StringRef IncludeFilename,
852 FileEntryRef IncludeFE, bool isAngled = false,
853 bool FoundByHeaderMap = false) {
854 bool IsIncluderPrivateHeader = false;
855 SmallString<128> FromFramework, ToFramework;
856 SmallString<128> FromIncludeSpelling, ToIncludeSpelling;
857 if (!isFrameworkStylePath(Path: Includer, IsPrivateHeader&: IsIncluderPrivateHeader, FrameworkName&: FromFramework,
858 IncludeSpelling&: FromIncludeSpelling))
859 return;
860 bool IsIncludeePrivateHeader = false;
861 bool IsIncludeeInFramework =
862 isFrameworkStylePath(Path: IncludeFE.getName(), IsPrivateHeader&: IsIncludeePrivateHeader,
863 FrameworkName&: ToFramework, IncludeSpelling&: ToIncludeSpelling);
864
865 if (!isAngled && !FoundByHeaderMap) {
866 SmallString<128> NewInclude("<");
867 if (IsIncludeeInFramework) {
868 NewInclude += ToIncludeSpelling;
869 NewInclude += ">";
870 } else {
871 NewInclude += IncludeFilename;
872 NewInclude += ">";
873 }
874 Diags.Report(Loc: IncludeLoc, DiagID: diag::warn_quoted_include_in_framework_header)
875 << IncludeFilename
876 << FixItHint::CreateReplacement(RemoveRange: IncludeLoc, Code: NewInclude);
877 }
878
879 // Headers in Foo.framework/Headers should not include headers
880 // from Foo.framework/PrivateHeaders, since this violates public/private
881 // API boundaries and can cause modular dependency cycles.
882 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
883 IsIncludeePrivateHeader && FromFramework == ToFramework)
884 Diags.Report(Loc: IncludeLoc, DiagID: diag::warn_framework_include_private_from_public)
885 << IncludeFilename;
886}
887
888void HeaderSearch::diagnoseHeaderShadowing(
889 StringRef Filename, FileEntryRef FE, SourceLocation IncludeLoc,
890 ConstSearchDirIterator FromDir,
891 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
892 bool isAngled, int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {
893
894 if (Diags.isIgnored(DiagID: diag::warn_header_shadowing, Loc: IncludeLoc))
895 return;
896 // Ignore diagnostics from system headers.
897 if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
898 return;
899
900 // Only consider each file once per spelling it was found under. Note that
901 // this also suppresses the search below for files that turn out not to be
902 // shadowed at all.
903 if (!ShadowCheckedHeaders[Filename].insert(Ptr: FE).second)
904 return;
905
906 // Indicates that file is first found in the includer's directory
907 if (!MainLoopIt) {
908 for (size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
909 const auto &IncluderAndDir = Includers[i];
910 SmallString<1024> TmpDir = IncluderAndDir.second.getName();
911 llvm::sys::path::append(path&: TmpDir, a: Filename);
912 if (auto File = getFileMgr().getOptionalFileRef(Filename: TmpDir)) {
913 if (*File == FE)
914 continue;
915 Diags.Report(Loc: IncludeLoc, DiagID: diag::warn_header_shadowing)
916 << Filename << FE.getDir().getName()
917 << IncluderAndDir.second.getName();
918 return;
919 }
920 }
921 }
922
923 // Continue searching in the regular search paths
924 ConstSearchDirIterator It =
925 isAngled ? angled_dir_begin() : search_dir_begin();
926 if (MainLoopIt) {
927 It = std::next(x: MainLoopIt);
928 } else if (FromDir) {
929 It = FromDir;
930 }
931 for (; It != search_dir_end(); ++It) {
932 // Suppress check for system headers, as duplicates are often intentional.
933 if (It->getDirCharacteristic() != SrcMgr::C_User)
934 continue;
935 SmallString<1024> TmpPath = It->getName();
936 llvm::sys::path::append(path&: TmpPath, a: Filename);
937 if (auto File = getFileMgr().getOptionalFileRef(Filename: TmpPath)) {
938 if (*File == FE)
939 continue;
940 Diags.Report(Loc: IncludeLoc, DiagID: diag::warn_header_shadowing)
941 << Filename << FE.getDir().getName() << It->getName();
942 return;
943 }
944 }
945}
946
947/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
948/// return null on failure. isAngled indicates whether the file reference is
949/// for system \#include's or not (i.e. using <> instead of ""). Includers, if
950/// non-empty, indicates where the \#including file(s) are, in case a relative
951/// search is needed. Microsoft mode will pass all \#including files.
952OptionalFileEntryRef HeaderSearch::LookupFile(
953 StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
954 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
955 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
956 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
957 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
958 bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
959 bool BuildSystemModule, bool OpenFile, bool CacheFailures) {
960 ConstSearchDirIterator CurDirLocal = nullptr;
961 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
962
963 if (IsMapped)
964 *IsMapped = false;
965
966 if (IsFrameworkFound)
967 *IsFrameworkFound = false;
968
969 if (SuggestedModule)
970 *SuggestedModule = ModuleMap::KnownHeader();
971
972 // If 'Filename' is absolute, check to see if it exists and no searching.
973 if (llvm::sys::path::is_absolute(path: Filename)) {
974 CurDir = nullptr;
975
976 // If this was an #include_next "/absolute/file", fail.
977 if (FromDir)
978 return std::nullopt;
979
980 if (SearchPath)
981 SearchPath->clear();
982 if (RelativePath) {
983 RelativePath->clear();
984 RelativePath->append(in_start: Filename.begin(), in_end: Filename.end());
985 }
986 // Otherwise, just return the file.
987 return getFileAndSuggestModule(FileName: Filename, IncludeLoc, Dir: nullptr,
988 /*IsSystemHeaderDir*/ false,
989 RequestingModule, SuggestedModule, OpenFile,
990 CacheFailures);
991 }
992
993 // This is the header that MSVC's header search would have found.
994 ModuleMap::KnownHeader MSSuggestedModule;
995 OptionalFileEntryRef MSFE;
996
997 // Check to see if the file is in the #includer's directory. This cannot be
998 // based on CurDir, because each includer could be a #include of a
999 // subdirectory (#include "foo/bar.h") and a subsequent include of "baz.h"
1000 // should resolve to "whatever/foo/baz.h". This search is not done for <>
1001 // headers.
1002 if (!Includers.empty() && !isAngled) {
1003 SmallString<1024> TmpDir;
1004 bool First = true;
1005 for (const auto &IncluderAndDir : Includers) {
1006 OptionalFileEntryRef Includer = IncluderAndDir.first;
1007
1008 // Concatenate the requested file onto the directory.
1009 TmpDir = IncluderAndDir.second.getName();
1010 llvm::sys::path::append(path&: TmpDir, a: Filename);
1011
1012 // FIXME: We don't cache the result of getFileInfo across the call to
1013 // getFileAndSuggestModule, because it's a reference to an element of
1014 // a container that could be reallocated across this call.
1015 //
1016 // If we have no includer, that means we're processing a #include
1017 // from a module build. We should treat this as a system header if we're
1018 // building a [system] module.
1019 bool IncluderIsSystemHeader = [&]() {
1020 if (!Includer)
1021 return BuildSystemModule;
1022 const HeaderFileInfo *HFI = getExistingFileInfo(FE: *Includer);
1023 assert(HFI && "includer without file info");
1024 return HFI->DirInfo != SrcMgr::C_User;
1025 }();
1026 if (OptionalFileEntryRef FE = getFileAndSuggestModule(
1027 FileName: TmpDir, IncludeLoc, Dir: IncluderAndDir.second, IsSystemHeaderDir: IncluderIsSystemHeader,
1028 RequestingModule, SuggestedModule)) {
1029 diagnoseHeaderShadowing(Filename, FE: *FE, IncludeLoc, FromDir, Includers,
1030 isAngled, IncluderLoopIndex: &IncluderAndDir - Includers.begin(),
1031 MainLoopIt: nullptr);
1032 if (!Includer) {
1033 assert(First && "only first includer can have no file");
1034 return FE;
1035 }
1036
1037 // Leave CurDir unset.
1038 // This file is a system header or C++ unfriendly if the old file is.
1039 //
1040 // Note that we only use one of FromHFI/ToHFI at once, due to potential
1041 // reallocation of the underlying vector potentially making the first
1042 // reference binding dangling.
1043 const HeaderFileInfo *FromHFI = getExistingFileInfo(FE: *Includer);
1044 assert(FromHFI && "includer without file info");
1045 unsigned DirInfo = FromHFI->DirInfo;
1046
1047 HeaderFileInfo &ToHFI = getFileInfo(FE: *FE);
1048 ToHFI.DirInfo = DirInfo;
1049
1050 if (SearchPath) {
1051 StringRef SearchPathRef(IncluderAndDir.second.getName());
1052 SearchPath->clear();
1053 SearchPath->append(in_start: SearchPathRef.begin(), in_end: SearchPathRef.end());
1054 }
1055 if (RelativePath) {
1056 RelativePath->clear();
1057 RelativePath->append(in_start: Filename.begin(), in_end: Filename.end());
1058 }
1059 if (First) {
1060 diagnoseFrameworkInclude(Diags, IncludeLoc,
1061 Includer: IncluderAndDir.second.getName(), IncludeFilename: Filename,
1062 IncludeFE: *FE);
1063 return FE;
1064 }
1065
1066 // Otherwise, we found the path via MSVC header search rules. If
1067 // -Wmsvc-include is enabled, we have to keep searching to see if we
1068 // would've found this header in -I or -isystem directories.
1069 if (Diags.isIgnored(DiagID: diag::ext_pp_include_search_ms, Loc: IncludeLoc)) {
1070 return FE;
1071 } else {
1072 MSFE = FE;
1073 if (SuggestedModule) {
1074 MSSuggestedModule = *SuggestedModule;
1075 *SuggestedModule = ModuleMap::KnownHeader();
1076 }
1077 break;
1078 }
1079 }
1080 First = false;
1081 }
1082 }
1083
1084 CurDir = nullptr;
1085
1086 // If this is a system #include, ignore the user #include locs.
1087 ConstSearchDirIterator It =
1088 isAngled ? angled_dir_begin() : search_dir_begin();
1089
1090 // If this is a #include_next request, start searching after the directory the
1091 // file was found in.
1092 if (FromDir)
1093 It = FromDir;
1094
1095 // Cache all of the lookups performed by this method. Many headers are
1096 // multiply included, and the "pragma once" optimization prevents them from
1097 // being relex/pp'd, but they would still have to search through a
1098 // (potentially huge) series of SearchDirs to find it.
1099 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1100
1101 ConstSearchDirIterator NextIt = std::next(x: It);
1102
1103 if (!SkipCache) {
1104 if (CacheLookup.StartIt == NextIt &&
1105 CacheLookup.RequestingModule == RequestingModule) {
1106 // HIT: Skip querying potentially lots of directories for this lookup.
1107 if (CacheLookup.HitIt)
1108 It = CacheLookup.HitIt;
1109 if (CacheLookup.MappedName) {
1110 Filename = CacheLookup.MappedName;
1111 if (IsMapped)
1112 *IsMapped = true;
1113 }
1114 } else {
1115 // MISS: This is the first query, or the previous query didn't match
1116 // our search start. We will fill in our found location below, so prime
1117 // the start point value.
1118 CacheLookup.reset(NewRequestingModule: RequestingModule, /*NewStartIt=*/NextIt);
1119
1120 if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) {
1121 // Handle cold misses of user includes in the presence of many header
1122 // maps. We avoid searching perhaps thousands of header maps by
1123 // jumping directly to the correct one or jumping beyond all of them.
1124 auto Iter = SearchDirHeaderMapIndex.find(Key: Filename.lower());
1125 if (Iter == SearchDirHeaderMapIndex.end())
1126 // Not in index => Skip to first SearchDir after initial header maps
1127 It = search_dir_nth(n: FirstNonHeaderMapSearchDirIdx);
1128 else
1129 // In index => Start with a specific header map
1130 It = search_dir_nth(n: Iter->second);
1131 }
1132 }
1133 } else {
1134 CacheLookup.reset(NewRequestingModule: RequestingModule, /*NewStartIt=*/NextIt);
1135 }
1136
1137 SmallString<64> MappedName;
1138
1139 // Check each directory in sequence to see if it contains this file.
1140 for (; It != search_dir_end(); ++It) {
1141 bool InUserSpecifiedSystemFramework = false;
1142 bool IsInHeaderMap = false;
1143 bool IsFrameworkFoundInDir = false;
1144 OptionalFileEntryRef File = It->LookupFile(
1145 Filename, HS&: *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1146 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFound&: IsFrameworkFoundInDir,
1147 IsInHeaderMap, MappedName, OpenFile);
1148 if (!MappedName.empty()) {
1149 assert(IsInHeaderMap && "MappedName should come from a header map");
1150 CacheLookup.MappedName =
1151 copyString(Str: MappedName, Alloc&: LookupFileCache.getAllocator());
1152 }
1153 if (IsMapped)
1154 // A filename is mapped when a header map remapped it to a relative path
1155 // used in subsequent header search or to an absolute path pointing to an
1156 // existing file.
1157 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));
1158 if (IsFrameworkFound)
1159 // Because we keep a filename remapped for subsequent search directory
1160 // lookups, ignore IsFrameworkFoundInDir after the first remapping and not
1161 // just for remapping in a current search directory.
1162 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1163 if (!File)
1164 continue;
1165
1166 // In MSVC compatibility mode we may have already found the file in one of
1167 // the includers' directories. That file is the one that ends up being used
1168 // (see checkMSVCHeaderSearch() below), so reporting this one as the chosen
1169 // candidate would be wrong.
1170 if (!MSFE)
1171 diagnoseHeaderShadowing(Filename, FE: *File, IncludeLoc, FromDir, Includers,
1172 isAngled, IncluderLoopIndex: -1, MainLoopIt: It);
1173
1174 CurDir = It;
1175
1176 IncludeNames[*File] = Filename;
1177
1178 // This file is a system header or C++ unfriendly if the dir is.
1179 HeaderFileInfo &HFI = getFileInfo(FE: *File);
1180 HFI.DirInfo = CurDir->getDirCharacteristic();
1181
1182 // If the directory characteristic is User but this framework was
1183 // user-specified to be treated as a system framework, promote the
1184 // characteristic.
1185 if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
1186 HFI.DirInfo = SrcMgr::C_System;
1187
1188 // If the filename matches a known system header prefix, override
1189 // whether the file is a system header.
1190 for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1191 if (Filename.starts_with(Prefix: SystemHeaderPrefixes[j - 1].first)) {
1192 HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
1193 : SrcMgr::C_User;
1194 break;
1195 }
1196 }
1197
1198 if (checkMSVCHeaderSearch(Diags, MSFE, FE: &File->getFileEntry(), IncludeLoc)) {
1199 if (SuggestedModule)
1200 *SuggestedModule = MSSuggestedModule;
1201 return MSFE;
1202 }
1203
1204 bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
1205 if (!Includers.empty())
1206 diagnoseFrameworkInclude(Diags, IncludeLoc,
1207 Includer: Includers.front().second.getName(), IncludeFilename: Filename,
1208 IncludeFE: *File, isAngled, FoundByHeaderMap);
1209
1210 // Remember this location for the next lookup we do.
1211 cacheLookupSuccess(CacheLookup, HitIt: It, Loc: IncludeLoc);
1212 return File;
1213 }
1214
1215 if (checkMSVCHeaderSearch(Diags, MSFE, FE: nullptr, IncludeLoc)) {
1216 if (SuggestedModule)
1217 *SuggestedModule = MSSuggestedModule;
1218 return MSFE;
1219 }
1220
1221 // Otherwise, didn't find it. Remember we didn't find this.
1222 CacheLookup.HitIt = search_dir_end();
1223 return std::nullopt;
1224}
1225
1226/// LookupSubframeworkHeader - Look up a subframework for the specified
1227/// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from
1228/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
1229/// is a subframework within Carbon.framework. If so, return the FileEntry
1230/// for the designated file, otherwise return null.
1231OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
1232 StringRef Filename, FileEntryRef ContextFileEnt,
1233 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
1234 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {
1235 // Framework names must have a '/' in the filename. Find it.
1236 // FIXME: Should we permit '\' on Windows?
1237 size_t SlashPos = Filename.find(C: '/');
1238 if (SlashPos == StringRef::npos)
1239 return std::nullopt;
1240
1241 // Look up the base framework name of the ContextFileEnt.
1242 StringRef ContextName = ContextFileEnt.getName();
1243
1244 // If the context info wasn't a framework, couldn't be a subframework.
1245 const unsigned DotFrameworkLen = 10;
1246 auto FrameworkPos = ContextName.find(Str: ".framework");
1247 if (FrameworkPos == StringRef::npos ||
1248 (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&
1249 ContextName[FrameworkPos + DotFrameworkLen] != '\\'))
1250 return std::nullopt;
1251
1252 SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +
1253 FrameworkPos +
1254 DotFrameworkLen + 1);
1255
1256 // Append Frameworks/HIToolbox.framework/
1257 FrameworkName += "Frameworks/";
1258 FrameworkName.append(in_start: Filename.begin(), in_end: Filename.begin()+SlashPos);
1259 FrameworkName += ".framework/";
1260
1261 auto &CacheLookup =
1262 *FrameworkMap.insert(KV: std::make_pair(x: Filename.substr(Start: 0, N: SlashPos),
1263 y: FrameworkCacheEntry())).first;
1264
1265 // Some other location?
1266 if (CacheLookup.second.Directory &&
1267 CacheLookup.first().size() == FrameworkName.size() &&
1268 memcmp(s1: CacheLookup.first().data(), s2: &FrameworkName[0],
1269 n: CacheLookup.first().size()) != 0)
1270 return std::nullopt;
1271
1272 // Cache subframework.
1273 if (!CacheLookup.second.Directory) {
1274 ++NumSubFrameworkLookups;
1275
1276 // If the framework dir doesn't exist, we fail.
1277 auto Dir = FileMgr.getOptionalDirectoryRef(DirName: FrameworkName);
1278 if (!Dir)
1279 return std::nullopt;
1280
1281 // Otherwise, if it does, remember that this is the right direntry for this
1282 // framework.
1283 CacheLookup.second.Directory = Dir;
1284 }
1285
1286
1287 if (RelativePath) {
1288 RelativePath->clear();
1289 RelativePath->append(in_start: Filename.begin()+SlashPos+1, in_end: Filename.end());
1290 }
1291
1292 // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
1293 SmallString<1024> HeadersFilename(FrameworkName);
1294 HeadersFilename += "Headers/";
1295 if (SearchPath) {
1296 SearchPath->clear();
1297 // Without trailing '/'.
1298 SearchPath->append(in_start: HeadersFilename.begin(), in_end: HeadersFilename.end()-1);
1299 }
1300
1301 HeadersFilename.append(in_start: Filename.begin()+SlashPos+1, in_end: Filename.end());
1302 auto File = FileMgr.getOptionalFileRef(Filename: HeadersFilename, /*OpenFile=*/true);
1303 if (!File) {
1304 // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
1305 HeadersFilename = FrameworkName;
1306 HeadersFilename += "PrivateHeaders/";
1307 if (SearchPath) {
1308 SearchPath->clear();
1309 // Without trailing '/'.
1310 SearchPath->append(in_start: HeadersFilename.begin(), in_end: HeadersFilename.end()-1);
1311 }
1312
1313 HeadersFilename.append(in_start: Filename.begin()+SlashPos+1, in_end: Filename.end());
1314 File = FileMgr.getOptionalFileRef(Filename: HeadersFilename, /*OpenFile=*/true);
1315
1316 if (!File)
1317 return std::nullopt;
1318 }
1319
1320 // This file is a system header or C++ unfriendly if the old file is.
1321 const HeaderFileInfo *ContextHFI = getExistingFileInfo(FE: ContextFileEnt);
1322 assert(ContextHFI && "context file without file info");
1323 // Note that the temporary 'DirInfo' is required here, as the call to
1324 // getFileInfo could resize the vector and might invalidate 'ContextHFI'.
1325 unsigned DirInfo = ContextHFI->DirInfo;
1326 getFileInfo(FE: *File).DirInfo = DirInfo;
1327
1328 FrameworkName.pop_back(); // remove the trailing '/'
1329 if (!findUsableModuleForFrameworkHeader(File: *File, FrameworkName,
1330 RequestingModule, SuggestedModule,
1331 /*IsSystem*/ IsSystemFramework: false))
1332 return std::nullopt;
1333
1334 return *File;
1335}
1336
1337//===----------------------------------------------------------------------===//
1338// File Info Management.
1339//===----------------------------------------------------------------------===//
1340
1341static bool moduleMembershipNeedsMerge(const HeaderFileInfo *HFI,
1342 ModuleMap::ModuleHeaderRole Role) {
1343 if (ModuleMap::isModular(Role))
1344 return !HFI->isModuleHeader || HFI->isTextualModuleHeader;
1345 if (!HFI->isModuleHeader && (Role & ModuleMap::TextualHeader))
1346 return !HFI->isTextualModuleHeader;
1347 return false;
1348}
1349
1350static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI,
1351 bool isModuleHeader,
1352 bool isTextualModuleHeader) {
1353 HFI.isModuleHeader |= isModuleHeader;
1354 if (HFI.isModuleHeader)
1355 HFI.isTextualModuleHeader = false;
1356 else
1357 HFI.isTextualModuleHeader |= isTextualModuleHeader;
1358}
1359
1360void HeaderFileInfo::mergeModuleMembership(ModuleMap::ModuleHeaderRole Role) {
1361 mergeHeaderFileInfoModuleBits(HFI&: *this, isModuleHeader: ModuleMap::isModular(Role),
1362 isTextualModuleHeader: (Role & ModuleMap::TextualHeader));
1363}
1364
1365/// Merge the header file info provided by \p OtherHFI into the current
1366/// header file info (\p HFI)
1367static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
1368 const HeaderFileInfo &OtherHFI) {
1369 assert(OtherHFI.External && "expected to merge external HFI");
1370
1371 HFI.isImport |= OtherHFI.isImport;
1372 HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
1373 mergeHeaderFileInfoModuleBits(HFI, isModuleHeader: OtherHFI.isModuleHeader,
1374 isTextualModuleHeader: OtherHFI.isTextualModuleHeader);
1375
1376 if (!HFI.LazyControllingMacro.isValid())
1377 HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro;
1378
1379 HFI.DirInfo = OtherHFI.DirInfo;
1380 HFI.External = (!HFI.IsValid || HFI.External);
1381 HFI.IsValid = true;
1382}
1383
1384HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) {
1385 HeaderFileInfo *HFI = &FileInfo[FE];
1386 // FIXME: Use a generation count to check whether this is really up to date.
1387 if (ExternalSource && !HFI->Resolved) {
1388 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1389 if (ExternalHFI.IsValid) {
1390 HFI->Resolved = true;
1391 if (ExternalHFI.External)
1392 mergeHeaderFileInfo(HFI&: *HFI, OtherHFI: ExternalHFI);
1393 }
1394 }
1395
1396 HFI->IsValid = true;
1397 // We assume the caller has local information about this header file, so it's
1398 // no longer strictly external.
1399 HFI->External = false;
1400 return *HFI;
1401}
1402
1403const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const {
1404 HeaderFileInfo *HFI;
1405 if (ExternalSource) {
1406 HFI = &FileInfo[FE];
1407 // FIXME: Use a generation count to check whether this is really up to date.
1408 if (!HFI->Resolved) {
1409 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1410 if (ExternalHFI.IsValid) {
1411 HFI->Resolved = true;
1412 if (ExternalHFI.External)
1413 mergeHeaderFileInfo(HFI&: *HFI, OtherHFI: ExternalHFI);
1414 }
1415 }
1416 } else if (auto It = FileInfo.find(Key: FE); It != FileInfo.end()) {
1417 HFI = &It->second;
1418 } else {
1419 HFI = nullptr;
1420 }
1421
1422 return (HFI && HFI->IsValid) ? HFI : nullptr;
1423}
1424
1425void HeaderSearch::forEachExistingLocalFileInfo(
1426 llvm::function_ref<void(FileEntryRef, const HeaderFileInfo &)> Fn) const {
1427 for (const auto &[FE, HFI] : FileInfo)
1428 if (HFI.IsValid && !HFI.External)
1429 Fn(FE, HFI);
1430}
1431
1432bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {
1433 // Check if we've entered this file and found an include guard or #pragma
1434 // once. Note that we dor't check for #import, because that's not a property
1435 // of the file itself.
1436 if (auto *HFI = getExistingFileInfo(FE: File))
1437 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1438 return false;
1439}
1440
1441void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE,
1442 ModuleMap::ModuleHeaderRole Role,
1443 bool isCompilingModuleHeader) {
1444 // Don't mark the file info as non-external if there's nothing to change.
1445 if (!isCompilingModuleHeader) {
1446 if ((Role & ModuleMap::ExcludedHeader))
1447 return;
1448 auto *HFI = getExistingFileInfo(FE);
1449 if (HFI && !moduleMembershipNeedsMerge(HFI, Role))
1450 return;
1451 }
1452
1453 auto &HFI = getFileInfo(FE);
1454 HFI.mergeModuleMembership(Role);
1455 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1456}
1457
1458bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
1459 FileEntryRef File, bool isImport,
1460 bool ModulesEnabled, Module *M,
1461 bool &IsFirstIncludeOfFile) {
1462 // An include file should be entered if either:
1463 // 1. This is the first include of the file.
1464 // 2. This file can be included multiple times, that is it's not an
1465 // "include-once" file.
1466 //
1467 // Include-once is controlled by these preprocessor directives.
1468 //
1469 // #pragma once
1470 // This directive is in the include file, and marks it as an include-once
1471 // file.
1472 //
1473 // #import <file>
1474 // This directive is in the includer, and indicates that the include file
1475 // should only be entered if this is the first include.
1476 ++NumIncluded;
1477 IsFirstIncludeOfFile = false;
1478 HeaderFileInfo &FileInfo = getFileInfo(FE: File);
1479
1480 auto MaybeReenterImportedFile = [&]() -> bool {
1481 // Modules add a wrinkle though: what's included isn't necessarily visible.
1482 // Consider this module.
1483 // module Example {
1484 // module A { header "a.h" export * }
1485 // module B { header "b.h" export * }
1486 // }
1487 // b.h includes c.h. The main file includes a.h, which will trigger a module
1488 // build of Example, and c.h will be included. However, c.h isn't visible to
1489 // the main file. Normally this is fine, the main file can just include c.h
1490 // if it needs it. If c.h is in a module, the include will translate into a
1491 // module import, this function will be skipped, and everything will work as
1492 // expected. However, if c.h is not in a module (or is `textual`), then this
1493 // function will run. If c.h is include-once, it will not be entered from
1494 // the main file and it will still not be visible.
1495
1496 // If modules aren't enabled then there's no visibility issue. Always
1497 // respect `#pragma once`.
1498 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1499 return false;
1500
1501 // Ensure FileInfo bits are up to date.
1502 ModMap.resolveHeaderDirectives(File);
1503
1504 // This brings up a subtlety of #import - it's not a very good indicator of
1505 // include-once. Developers are often unaware of the difference between
1506 // #include and #import, and tend to use one or the other indiscrimiately.
1507 // In order to support #include on include-once headers that lack macro
1508 // guards and `#pragma once` (which is the vast majority of Objective-C
1509 // headers), if a file is ever included with #import, it's marked as
1510 // isImport in the HeaderFileInfo and treated as include-once. This allows
1511 // #include to work in Objective-C.
1512 // #include <Foundation/Foundation.h>
1513 // #include <Foundation/NSString.h>
1514 // Foundation.h has an #import of NSString.h, and so the second #include is
1515 // skipped even though NSString.h has no `#pragma once` and no macro guard.
1516 //
1517 // However, this helpfulness causes problems with modules. If c.h is not an
1518 // include-once file, but something included it with #import anyway (as is
1519 // typical in Objective-C code), this include will be skipped and c.h will
1520 // not be visible. Consider it not include-once if it is a `textual` header
1521 // in a module.
1522 if (FileInfo.isTextualModuleHeader)
1523 return true;
1524
1525 if (FileInfo.isCompilingModuleHeader) {
1526 // It's safer to re-enter a file whose module is being built because its
1527 // declarations will still be scoped to a single module.
1528 if (FileInfo.isModuleHeader) {
1529 // Headers marked as "builtin" are covered by the system module maps
1530 // rather than the builtin ones. Some versions of the Darwin module fail
1531 // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these
1532 // files while building their module to allow them to function properly.
1533 if (ModMap.isBuiltinHeader(File))
1534 return true;
1535 } else {
1536 // Files that are excluded from their module can potentially be
1537 // re-entered from their own module. This might cause redeclaration
1538 // errors if another module saw this file first, but there's a
1539 // reasonable chance that its module will build first. However if
1540 // there's no controlling macro, then trust the #import and assume this
1541 // really is an include-once file.
1542 if (FileInfo.getControllingMacro(External: ExternalLookup))
1543 return true;
1544 }
1545 }
1546 // If the include file has a macro guard, then it might still not be
1547 // re-entered if the controlling macro is visibly defined. e.g. another
1548 // header in the module being built included this file and local submodule
1549 // visibility is not enabled.
1550
1551 // It might be tempting to re-enter the include-once file if it's not
1552 // visible in an attempt to make it visible. However this will still cause
1553 // redeclaration errors against the known-but-not-visible declarations. The
1554 // include file not being visible will most likely cause "undefined x"
1555 // errors, but at least there's a slim chance of compilation succeeding.
1556 return false;
1557 };
1558
1559 if (isImport) {
1560 // As discussed above, record that this file was ever `#import`ed, and treat
1561 // it as an include-once file from here out.
1562 FileInfo.isImport = true;
1563 if (PP.alreadyIncluded(File) && !MaybeReenterImportedFile())
1564 return false;
1565 } else {
1566 // isPragmaOnce and isImport are only set after the file has been included
1567 // at least once. If either are set then this is a repeat #include of an
1568 // include-once file.
1569 if (FileInfo.isPragmaOnce ||
1570 (FileInfo.isImport && !MaybeReenterImportedFile()))
1571 return false;
1572 }
1573
1574 // As a final optimization, check for a macro guard and skip entering the file
1575 // if the controlling macro is defined. The macro guard will effectively erase
1576 // the file's contents, and the include would have no effect other than to
1577 // waste time opening and reading a file.
1578 if (const IdentifierInfo *ControllingMacro =
1579 FileInfo.getControllingMacro(External: ExternalLookup)) {
1580 // If the header corresponds to a module, check whether the macro is already
1581 // defined in that module rather than checking all visible modules. This is
1582 // mainly to cover corner cases where the same controlling macro is used in
1583 // different files in multiple modules.
1584 if (M ? PP.isMacroDefinedInLocalModule(II: ControllingMacro, M)
1585 : PP.isMacroDefined(II: ControllingMacro)) {
1586 ++NumMultiIncludeFileOptzn;
1587 return false;
1588 }
1589 }
1590
1591 IsFirstIncludeOfFile = PP.markIncluded(File);
1592 return true;
1593}
1594
1595size_t HeaderSearch::getTotalMemory() const {
1596 return SearchDirs.capacity()
1597 + llvm::capacity_in_bytes(X: FileInfo)
1598 + llvm::capacity_in_bytes(x: HeaderMaps)
1599 + LookupFileCache.getAllocator().getTotalMemory()
1600 + FrameworkMap.getAllocator().getTotalMemory();
1601}
1602
1603unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
1604 return &DL - &*SearchDirs.begin();
1605}
1606
1607StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
1608 return FrameworkNames.insert(key: Framework).first->first();
1609}
1610
1611StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const {
1612 auto It = IncludeNames.find(Val: File);
1613 if (It == IncludeNames.end())
1614 return {};
1615 return It->second;
1616}
1617
1618void HeaderSearch::buildModuleMapIndex(DirectoryEntryRef Dir,
1619 ModuleMapDirectoryState &MMState) {
1620 if (!MMState.ModuleMapFile)
1621 return;
1622 const modulemap::ModuleMapFile *ParsedMM =
1623 ModMap.getParsedModuleMap(File: *MMState.ModuleMapFile);
1624 if (!ParsedMM)
1625 return;
1626 const modulemap::ModuleMapFile *ParsedPrivateMM = nullptr;
1627 if (MMState.PrivateModuleMapFile)
1628 ParsedPrivateMM = ModMap.getParsedModuleMap(File: *MMState.PrivateModuleMapFile);
1629
1630 processModuleMapForIndex(MMF: *ParsedMM, MMDir: Dir, PathPrefix: "", MMState);
1631 if (ParsedPrivateMM)
1632 processModuleMapForIndex(MMF: *ParsedPrivateMM, MMDir: Dir, PathPrefix: "", MMState);
1633}
1634
1635void HeaderSearch::addToModuleMapIndex(StringRef RelPath, StringRef ModuleName,
1636 StringRef PathPrefix,
1637 ModuleMapDirectoryState &MMState) {
1638 SmallString<128> RelFromRootPath(PathPrefix);
1639 llvm::sys::path::append(path&: RelFromRootPath, a: RelPath);
1640 llvm::sys::path::native(path&: RelFromRootPath);
1641 MMState.HeaderToModules[RelFromRootPath].push_back(Elt: ModuleName);
1642}
1643
1644void HeaderSearch::processExternModuleDeclForIndex(
1645 const modulemap::ExternModuleDecl &EMD, DirectoryEntryRef MMDir,
1646 StringRef PathPrefix, ModuleMapDirectoryState &MMState) {
1647 StringRef FileNameRef = EMD.Path;
1648 SmallString<128> ModuleMapFileName;
1649 if (llvm::sys::path::is_relative(path: FileNameRef)) {
1650 ModuleMapFileName = MMDir.getName();
1651 llvm::sys::path::append(path&: ModuleMapFileName, a: EMD.Path);
1652 FileNameRef = ModuleMapFileName;
1653 }
1654 if (auto EFile = FileMgr.getOptionalFileRef(Filename: FileNameRef)) {
1655 if (auto *ExtMMF = ModMap.getParsedModuleMap(File: *EFile)) {
1656 // Compute the new prefix by appending the extern module's directory
1657 // (from the extern declaration path) to the current prefix.
1658 SmallString<128> NewPrefix(PathPrefix);
1659 StringRef ExternDir = llvm::sys::path::parent_path(path: EMD.Path);
1660 if (!ExternDir.empty()) {
1661 llvm::sys::path::append(path&: NewPrefix, a: ExternDir);
1662 llvm::sys::path::native(path&: NewPrefix);
1663 }
1664 processModuleMapForIndex(MMF: *ExtMMF, MMDir: EFile->getDir(), PathPrefix: NewPrefix, MMState);
1665 }
1666 }
1667}
1668
1669void HeaderSearch::processModuleDeclForIndex(const modulemap::ModuleDecl &MD,
1670 StringRef ModuleName,
1671 DirectoryEntryRef MMDir,
1672 StringRef PathPrefix,
1673 ModuleMapDirectoryState &MMState) {
1674 // Skip inferred submodules (module *)
1675 if (MD.Id.front().first == "*")
1676 return;
1677
1678 auto ProcessDecl = llvm::makeVisitor(
1679 Callables: [&](const modulemap::HeaderDecl &HD) {
1680 if (HD.Umbrella) {
1681 MMState.UmbrellaHeaderModules.push_back(Elt: ModuleName);
1682 } else {
1683 addToModuleMapIndex(RelPath: HD.Path, ModuleName, PathPrefix, MMState);
1684 }
1685 },
1686 Callables: [&](const modulemap::UmbrellaDirDecl &UDD) {
1687 SmallString<128> FullPath(PathPrefix);
1688 llvm::sys::path::append(path&: FullPath, a: UDD.Path);
1689 llvm::sys::path::native(path&: FullPath);
1690 MMState.UmbrellaDirModules.push_back(
1691 Elt: std::make_pair(x: std::string(FullPath), y&: ModuleName));
1692 },
1693 Callables: [&](const modulemap::ModuleDecl &SubMD) {
1694 processModuleDeclForIndex(MD: SubMD, ModuleName, MMDir, PathPrefix,
1695 MMState);
1696 },
1697 Callables: [&](const modulemap::ExternModuleDecl &EMD) {
1698 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix, MMState);
1699 },
1700 Callables: [](const auto &) {
1701 // Ignore other decls.
1702 });
1703
1704 for (const auto &Decl : MD.Decls) {
1705 std::visit(visitor&: ProcessDecl, variants: Decl);
1706 }
1707}
1708
1709void HeaderSearch::processModuleMapForIndex(const modulemap::ModuleMapFile &MMF,
1710 DirectoryEntryRef MMDir,
1711 StringRef PathPrefix,
1712 ModuleMapDirectoryState &MMState) {
1713 for (const auto &Decl : MMF.Decls) {
1714 std::visit(visitor: llvm::makeVisitor(
1715 Callables: [&](const modulemap::ModuleDecl &MD) {
1716 processModuleDeclForIndex(MD, ModuleName: MD.Id.front().first, MMDir,
1717 PathPrefix, MMState);
1718 },
1719 Callables: [&](const modulemap::ExternModuleDecl &EMD) {
1720 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix,
1721 MMState);
1722 }),
1723 variants: Decl);
1724 }
1725}
1726
1727/// Compute relative path from DirPath to FileName by stripping the DirPath
1728/// prefix. DirPath should be derived from FileName (e.g. via parent_path) to
1729/// ensure consistent path separators. Returns empty if FileName doesn't start
1730/// with DirPath.
1731static StringRef computeRelativePath(StringRef FileName, StringRef DirPath) {
1732 if (!FileName.starts_with(Prefix: DirPath))
1733 return {};
1734 StringRef RelativePath = FileName.substr(Start: DirPath.size());
1735 while (!RelativePath.empty() &&
1736 llvm::sys::path::is_separator(value: RelativePath.front()))
1737 RelativePath = RelativePath.substr(Start: 1);
1738 return RelativePath;
1739}
1740
1741SmallVector<StringRef, 1> HeaderSearch::findMatchingModulesInIndex(
1742 StringRef RelativePath, const ModuleMapDirectoryState &MMState) const {
1743 SmallVector<StringRef, 1> Modules;
1744
1745 // Check for exact matches in cache.
1746 auto CachedMods = MMState.HeaderToModules.find(Key: RelativePath);
1747 if (CachedMods != MMState.HeaderToModules.end())
1748 Modules.append(in_start: CachedMods->second.begin(), in_end: CachedMods->second.end());
1749
1750 // Check umbrella directories.
1751 for (const auto &UmbrellaDir : MMState.UmbrellaDirModules) {
1752 if (RelativePath.starts_with(Prefix: UmbrellaDir.first) || UmbrellaDir.first == ".")
1753 Modules.push_back(Elt: UmbrellaDir.second);
1754 }
1755
1756 // Add all modules corresponding to an umbrella header. We don't know which
1757 // other headers these umbrella headers include, so it's possible any one of
1758 // them includes the file. `ModuleMap::findModuleForHeader` will select the
1759 // correct module, accounting for any already known headers from other module
1760 // maps or loaded PCMs.
1761 //
1762 // TODO: Clang should strictly enforce that umbrella headers include the
1763 // other headers in their directory, or that they are referenced in
1764 // the module map. The current behavior can be order of include/import
1765 // dependent. This would allow treating umbrella headers the same as
1766 // umbrella directories here.
1767 Modules.append(in_start: MMState.UmbrellaHeaderModules.begin(),
1768 in_end: MMState.UmbrellaHeaderModules.end());
1769
1770 return Modules;
1771}
1772
1773bool HeaderSearch::hasModuleMap(StringRef FileName,
1774 const DirectoryEntry *Root,
1775 bool IsSystem) {
1776 if (!HSOpts.ImplicitModuleMaps)
1777 return false;
1778
1779 StringRef DirName = FileName;
1780 const DirectoryEntry *CurDir = nullptr;
1781 do {
1782 // Get the parent directory name.
1783 DirName = llvm::sys::path::parent_path(path: DirName);
1784 if (DirName.empty())
1785 return false;
1786
1787 // Determine whether this directory exists.
1788 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1789 if (!Dir)
1790 return false;
1791 CurDir = *Dir;
1792
1793 bool IsFramework =
1794 llvm::sys::path::extension(path: Dir->getName()) == ".framework";
1795
1796 // Check if it's possible that the module map for this directory can resolve
1797 // this header.
1798 parseModuleMapFile(Dir: *Dir, IsSystem, /*ImplicitlyDiscovered=*/true,
1799 IsFramework);
1800 auto DirState = DirectoryModuleMap.find(Val: *Dir);
1801 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1802 continue;
1803
1804 if (!HSOpts.LazyLoadModuleMaps &&
1805 Diags.isIgnored(DiagID: diag::warn_mmap_deprecated_symlink_to_modular_header,
1806 Loc: SourceLocation()))
1807 return true;
1808
1809 auto &MMState = DirState->second;
1810
1811 // Build index if not already built
1812 if (MMState.HeaderToModules.empty() && MMState.UmbrellaDirModules.empty() &&
1813 MMState.UmbrellaHeaderModules.empty()) {
1814 buildModuleMapIndex(Dir: *Dir, MMState);
1815 }
1816
1817 // The header cache is needed for the symlink diagnostic.
1818 if (!HSOpts.LazyLoadModuleMaps)
1819 return true;
1820
1821 // Compute relative path from directory to the file. Use DirName (which
1822 // we computed via parent_path) rather than Dir->getName() to ensure
1823 // consistent path separators.
1824 StringRef RelativePath = computeRelativePath(FileName, DirPath: DirName);
1825 SmallString<128> RelativePathNative(RelativePath);
1826 llvm::sys::path::native(path&: RelativePathNative);
1827
1828 auto ModulesToLoad =
1829 findMatchingModulesInIndex(RelativePath: RelativePathNative, MMState);
1830
1831 // Load all matching modules.
1832 bool LoadedAny = false;
1833 for (StringRef ModName : ModulesToLoad) {
1834 if (ModMap.findOrLoadModule(Name: ModName)) {
1835 LoadedAny = true;
1836 }
1837 }
1838
1839 if (LoadedAny)
1840 return true;
1841
1842 // If we hit the top of our search, we're done.
1843 } while (CurDir != Root);
1844 return false;
1845}
1846
1847ModuleMap::KnownHeader
1848HeaderSearch::findModuleForHeader(FileEntryRef File, bool AllowTextual,
1849 bool AllowExcluded) const {
1850 if (ExternalSource) {
1851 // Make sure the external source has handled header info about this file,
1852 // which includes whether the file is part of a module.
1853 (void)getExistingFileInfo(FE: File);
1854 }
1855 return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded);
1856}
1857
1858ArrayRef<ModuleMap::KnownHeader>
1859HeaderSearch::findAllModulesForHeader(FileEntryRef File) const {
1860 if (ExternalSource) {
1861 // Make sure the external source has handled header info about this file,
1862 // which includes whether the file is part of a module.
1863 (void)getExistingFileInfo(FE: File);
1864 }
1865 return ModMap.findAllModulesForHeader(File);
1866}
1867
1868ArrayRef<ModuleMap::KnownHeader>
1869HeaderSearch::findResolvedModulesForHeader(FileEntryRef File) const {
1870 if (ExternalSource) {
1871 // Make sure the external source has handled header info about this file,
1872 // which includes whether the file is part of a module.
1873 (void)getExistingFileInfo(FE: File);
1874 }
1875 return ModMap.findResolvedModulesForHeader(File);
1876}
1877
1878static bool suggestModule(HeaderSearch &HS, ModuleMap::KnownHeader Module,
1879 FileEntryRef File, clang::Module *RequestingModule,
1880 ModuleMap::KnownHeader *SuggestedModule) {
1881 // If this module specifies [no_undeclared_includes], we cannot find any
1882 // file that's in a non-dependency module.
1883 if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {
1884 HS.getModuleMap().resolveUses(Mod: RequestingModule, /*Complain*/ false);
1885 if (!RequestingModule->directlyUses(Requested: Module.getModule())) {
1886 // Builtin headers are a special case. Multiple modules can use the same
1887 // builtin as a modular header (see also comment in
1888 // ShouldEnterIncludeFile()), so the builtin header may have been
1889 // "claimed" by an unrelated module. This shouldn't prevent us from
1890 // including the builtin header textually in this module.
1891 if (HS.getModuleMap().isBuiltinHeader(File)) {
1892 if (SuggestedModule)
1893 *SuggestedModule = ModuleMap::KnownHeader();
1894 return true;
1895 }
1896 // TODO: Add this module (or just its module map file) into something like
1897 // `RequestingModule->AffectingClangModules`.
1898 return false;
1899 }
1900 }
1901
1902 if (SuggestedModule)
1903 *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)
1904 ? ModuleMap::KnownHeader()
1905 : Module;
1906
1907 return true;
1908}
1909
1910void HeaderSearch::diagnoseUncoveredSymlink(FileEntryRef File,
1911 ModuleMap::KnownHeader &Module,
1912 const DirectoryEntry *Root) {
1913 if (!Module)
1914 return;
1915
1916 if (!HSOpts.ImplicitModuleMaps || Module.getModule()->isPartOfFramework() ||
1917 !Module.getModule()->isModuleMapModule())
1918 return;
1919
1920 if (Diags.isIgnored(DiagID: diag::warn_mmap_deprecated_symlink_to_modular_header,
1921 Loc: Module.getModule()->DefinitionLoc))
1922 return;
1923
1924 if (File.isDeviceFile() || File.isNamedPipe())
1925 return;
1926
1927 llvm::SmallString<128> AbsPath(File.getName());
1928 FileMgr.makeAbsolutePath(Path&: AbsPath);
1929 llvm::sys::path::remove_dots(path&: AbsPath, /*remove_dot_dot=*/true);
1930
1931 // NOTE: This path may be redirected, LLVM's VFS does not model symlinks, so
1932 // it's possible this fails. The diagnostic is worded as such.
1933 llvm::SmallString<128> LinkTarget;
1934 if (llvm::sys::fs::readlink(path: AbsPath, output&: LinkTarget))
1935 return;
1936
1937 // We know this file is a symlink and resolved to a module. Check that there's
1938 // a module map that would be discoverable that covers this header. This uses
1939 // VFS paths as that's how module map search works.
1940 StringRef FileName = File.getNameAsRequested();
1941 StringRef DirName = FileName;
1942 const DirectoryEntry *CurDir = nullptr;
1943
1944 // Walk up the directory tree looking for a module map that covers this path.
1945 do {
1946 DirName = llvm::sys::path::parent_path(path: DirName);
1947 if (DirName.empty())
1948 break;
1949
1950 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1951 if (!Dir)
1952 break;
1953 CurDir = *Dir;
1954
1955 auto DirState = DirectoryModuleMap.find(Val: *Dir);
1956 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1957 continue;
1958
1959 // Use DirName (from parent_path) rather than Dir->getName() to ensure
1960 // consistent path separators.
1961 StringRef RelativePath = computeRelativePath(FileName, DirPath: DirName);
1962 if (RelativePath.empty())
1963 continue;
1964 SmallString<128> RelativePathNative(RelativePath);
1965 llvm::sys::path::native(path&: RelativePathNative);
1966
1967 auto MatchingModules =
1968 findMatchingModulesInIndex(RelativePath: RelativePathNative, MMState: DirState->second);
1969 if (!MatchingModules.empty())
1970 return; // Symlink path is covered, no diagnostic needed.
1971 } while (CurDir != Root);
1972
1973 // The symlink path is not covered by any module map.
1974 Diags.Report(DiagID: diag::warn_mmap_deprecated_symlink_to_modular_header)
1975 << File.getName() << LinkTarget
1976 << Module.getModule()->getFullModuleName();
1977 Diags.Report(Loc: Module.getModule()->DefinitionLoc,
1978 DiagID: diag::note_mmap_module_defined_here);
1979}
1980
1981bool HeaderSearch::findUsableModuleForHeader(
1982 FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule,
1983 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
1984 if (needModuleLookup(RequestingModule, HasSuggestedModule: SuggestedModule)) {
1985 if (!HSOpts.LazyLoadModuleMaps) {
1986 // NOTE: This is required for `shadowed-submodule.m` to pass as it relies
1987 // on A1/module.modulemap being loaded even though we already know
1988 // which module the header belongs to. We will remove this behavior
1989 // as part of lazy module map loading.
1990 hasModuleMap(FileName: File.getNameAsRequested(), Root, IsSystem: IsSystemHeaderDir);
1991 ModuleMap::KnownHeader Module =
1992 findModuleForHeader(File, /*AllowTextual=*/true);
1993 diagnoseUncoveredSymlink(File, Module, Root);
1994 return suggestModule(HS&: *this, Module, File, RequestingModule,
1995 SuggestedModule);
1996 }
1997
1998 // First check if we already know about this header
1999 ModuleMap::KnownHeader Module =
2000 findModuleForHeader(File, /*AllowTextual=*/true);
2001
2002 // If we don't have a module yet, try to find/load module maps
2003 if (!Module) {
2004 hasModuleMap(FileName: File.getNameAsRequested(), Root, IsSystem: IsSystemHeaderDir);
2005 // Try again after loading module maps, this time bypassing loading module
2006 // map data from PCMs.
2007 Module = ModMap.findModuleForHeader(File, /*AllowTextual=*/true);
2008 }
2009 diagnoseUncoveredSymlink(File, Module, Root);
2010 return suggestModule(HS&: *this, Module, File, RequestingModule,
2011 SuggestedModule);
2012 }
2013 return true;
2014}
2015
2016bool HeaderSearch::findUsableModuleForFrameworkHeader(
2017 FileEntryRef File, StringRef FrameworkName, Module *RequestingModule,
2018 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
2019 // If we're supposed to suggest a module, look for one now.
2020 if (needModuleLookup(RequestingModule, HasSuggestedModule: SuggestedModule)) {
2021 // Find the top-level framework based on this framework.
2022 SmallVector<std::string, 4> SubmodulePath;
2023 OptionalDirectoryEntryRef TopFrameworkDir =
2024 ::getTopFrameworkDir(FileMgr, DirName: FrameworkName, SubmodulePath);
2025 assert(TopFrameworkDir && "Could not find the top-most framework dir");
2026
2027 // Determine the name of the top-level framework.
2028 StringRef ModuleName = llvm::sys::path::stem(path: TopFrameworkDir->getName());
2029
2030 // Load this framework module. If that succeeds, find the suggested module
2031 // for this header, if any.
2032 loadFrameworkModule(Name: ModuleName, Dir: *TopFrameworkDir, IsSystem: IsSystemFramework,
2033 /*ImplicitlyDiscovered=*/true);
2034
2035 // FIXME: This can find a module not part of ModuleName, which is
2036 // important so that we're consistent about whether this header
2037 // corresponds to a module. Possibly we should lock down framework modules
2038 // so that this is not possible.
2039 ModuleMap::KnownHeader Module =
2040 findModuleForHeader(File, /*AllowTextual=*/true);
2041 return suggestModule(HS&: *this, Module, File, RequestingModule,
2042 SuggestedModule);
2043 }
2044 return true;
2045}
2046
2047static OptionalFileEntryRef getPrivateModuleMap(FileEntryRef File,
2048 FileManager &FileMgr,
2049 DiagnosticsEngine &Diags,
2050 bool Diagnose = true) {
2051 StringRef Filename = llvm::sys::path::filename(path: File.getName());
2052 SmallString<128> PrivateFilename(File.getDir().getName());
2053 if (Filename == "module.map")
2054 llvm::sys::path::append(path&: PrivateFilename, a: "module_private.map");
2055 else if (Filename == "module.modulemap")
2056 llvm::sys::path::append(path&: PrivateFilename, a: "module.private.modulemap");
2057 else
2058 return std::nullopt;
2059 auto PMMFile = FileMgr.getOptionalFileRef(Filename: PrivateFilename);
2060 if (PMMFile) {
2061 if (Diagnose && Filename == "module.map")
2062 Diags.Report(DiagID: diag::warn_deprecated_module_dot_map)
2063 << PrivateFilename << 1
2064 << File.getDir().getName().ends_with(Suffix: ".framework");
2065 }
2066 return PMMFile;
2067}
2068
2069bool HeaderSearch::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,
2070 bool ImplicitlyDiscovered,
2071 FileID ID, unsigned *Offset,
2072 StringRef OriginalModuleMapFile) {
2073 // Find the directory for the module. For frameworks, that may require going
2074 // up from the 'Modules' directory.
2075 OptionalDirectoryEntryRef Dir;
2076 if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) {
2077 Dir = FileMgr.getOptionalDirectoryRef(DirName: ".");
2078 } else {
2079 if (!OriginalModuleMapFile.empty()) {
2080 // We're building a preprocessed module map. Find or invent the directory
2081 // that it originally occupied.
2082 Dir = FileMgr.getOptionalDirectoryRef(
2083 DirName: llvm::sys::path::parent_path(path: OriginalModuleMapFile));
2084 if (!Dir) {
2085 auto FakeFile = FileMgr.getVirtualFileRef(Filename: OriginalModuleMapFile, Size: 0, ModificationTime: 0);
2086 Dir = FakeFile.getDir();
2087 }
2088 } else {
2089 Dir = File.getDir();
2090 }
2091
2092 assert(Dir && "parent must exist");
2093 StringRef DirName(Dir->getName());
2094 if (llvm::sys::path::filename(path: DirName) == "Modules") {
2095 DirName = llvm::sys::path::parent_path(path: DirName);
2096 if (DirName.ends_with(Suffix: ".framework"))
2097 if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
2098 Dir = *MaybeDir;
2099 // FIXME: This assert can fail if there's a race between the above check
2100 // and the removal of the directory.
2101 assert(Dir && "parent must exist");
2102 }
2103 }
2104
2105 assert(Dir && "module map home directory must exist");
2106 switch (parseAndLoadModuleMapFileImpl(File, IsSystem, ImplicitlyDiscovered,
2107 Dir: *Dir, ID, Offset,
2108 /*DiagnosePrivMMap=*/true)) {
2109 case MMR_AlreadyProcessed:
2110 case MMR_NewlyProcessed:
2111 return false;
2112 case MMR_NoDirectory:
2113 case MMR_InvalidModuleMap:
2114 return true;
2115 }
2116 llvm_unreachable("Unknown load module map result");
2117}
2118
2119HeaderSearch::ModuleMapResult HeaderSearch::parseAndLoadModuleMapFileImpl(
2120 FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered,
2121 DirectoryEntryRef Dir, FileID ID, unsigned *Offset, bool DiagnosePrivMMap) {
2122 // Check whether we've already loaded this module map, and mark it as being
2123 // loaded in case we recursively try to load it from itself.
2124 auto AddResult = LoadedModuleMaps.insert(KV: std::make_pair(x&: File, y: true));
2125 if (!AddResult.second)
2126 return AddResult.first->second ? MMR_AlreadyProcessed
2127 : MMR_InvalidModuleMap;
2128
2129 if (ModMap.parseAndLoadModuleMapFile(File, IsSystem, ImplicitlyDiscovered,
2130 HomeDir: Dir, ID, Offset)) {
2131 LoadedModuleMaps[File] = false;
2132 return MMR_InvalidModuleMap;
2133 }
2134
2135 // Try to load a corresponding private module map.
2136 if (OptionalFileEntryRef PMMFile =
2137 getPrivateModuleMap(File, FileMgr, Diags, Diagnose: DiagnosePrivMMap)) {
2138 if (ModMap.parseAndLoadModuleMapFile(File: *PMMFile, IsSystem,
2139 ImplicitlyDiscovered, HomeDir: Dir)) {
2140 LoadedModuleMaps[File] = false;
2141 return MMR_InvalidModuleMap;
2142 }
2143 }
2144
2145 // This directory has a module map.
2146 return MMR_NewlyProcessed;
2147}
2148
2149HeaderSearch::ModuleMapResult
2150HeaderSearch::parseModuleMapFileImpl(FileEntryRef File, bool IsSystem,
2151 bool ImplicitlyDiscovered,
2152 DirectoryEntryRef Dir, FileID ID) {
2153 // Check whether we've already parsed this module map, and mark it as being
2154 // parsed in case we recursively try to parse it from itself.
2155 auto AddResult = ParsedModuleMaps.insert(KV: std::make_pair(x&: File, y: true));
2156 if (!AddResult.second)
2157 return AddResult.first->second ? MMR_AlreadyProcessed
2158 : MMR_InvalidModuleMap;
2159
2160 if (ModMap.parseModuleMapFile(File, IsSystem, ImplicitlyDiscovered, Dir,
2161 ID)) {
2162 ParsedModuleMaps[File] = false;
2163 return MMR_InvalidModuleMap;
2164 }
2165
2166 // Try to parse a corresponding private module map.
2167 if (OptionalFileEntryRef PMMFile =
2168 getPrivateModuleMap(File, FileMgr, Diags, /*Diagnose=*/false)) {
2169 if (ModMap.parseModuleMapFile(File: *PMMFile, IsSystem, ImplicitlyDiscovered,
2170 Dir)) {
2171 ParsedModuleMaps[File] = false;
2172 return MMR_InvalidModuleMap;
2173 }
2174 }
2175
2176 // This directory has a module map.
2177 return MMR_NewlyProcessed;
2178}
2179
2180OptionalFileEntryRef
2181HeaderSearch::lookupModuleMapFile(DirectoryEntryRef Dir, bool IsFramework) {
2182 if (!HSOpts.ImplicitModuleMaps)
2183 return std::nullopt;
2184 // For frameworks, the preferred spelling is Modules/module.modulemap, but
2185 // module.map at the framework root is also accepted.
2186 SmallString<128> ModuleMapFileName(Dir.getName());
2187 if (IsFramework)
2188 llvm::sys::path::append(path&: ModuleMapFileName, a: "Modules");
2189 llvm::sys::path::append(path&: ModuleMapFileName, a: "module.modulemap");
2190 if (auto F = FileMgr.getOptionalFileRef(Filename: ModuleMapFileName))
2191 return *F;
2192
2193 // Continue to allow module.map, but warn it's deprecated.
2194 ModuleMapFileName = Dir.getName();
2195 llvm::sys::path::append(path&: ModuleMapFileName, a: "module.map");
2196 if (auto F = FileMgr.getOptionalFileRef(Filename: ModuleMapFileName)) {
2197 Diags.Report(DiagID: diag::warn_deprecated_module_dot_map)
2198 << ModuleMapFileName << 0 << IsFramework;
2199 return *F;
2200 }
2201
2202 // For frameworks, allow to have a private module map with a preferred
2203 // spelling when a public module map is absent.
2204 if (IsFramework) {
2205 ModuleMapFileName = Dir.getName();
2206 llvm::sys::path::append(path&: ModuleMapFileName, a: "Modules",
2207 b: "module.private.modulemap");
2208 if (auto F = FileMgr.getOptionalFileRef(Filename: ModuleMapFileName))
2209 return *F;
2210 }
2211 return std::nullopt;
2212}
2213
2214Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,
2215 bool IsSystem,
2216 bool ImplicitlyDiscovered) {
2217 // Try to load a module map file.
2218 switch (parseAndLoadModuleMapFile(Dir, IsSystem, ImplicitlyDiscovered,
2219 /*IsFramework*/ true)) {
2220 case MMR_InvalidModuleMap:
2221 // Try to infer a module map from the framework directory.
2222 if (HSOpts.ImplicitModuleMaps)
2223 ModMap.inferFrameworkModule(FrameworkDir: Dir, IsSystem, /*Parent=*/nullptr);
2224 break;
2225
2226 case MMR_NoDirectory:
2227 return nullptr;
2228
2229 case MMR_AlreadyProcessed:
2230 case MMR_NewlyProcessed:
2231 break;
2232 }
2233
2234 return ModMap.findOrLoadModule(Name);
2235}
2236
2237HeaderSearch::ModuleMapResult
2238HeaderSearch::parseAndLoadModuleMapFile(StringRef DirName, bool IsSystem,
2239 bool ImplicitlyDiscovered,
2240 bool IsFramework) {
2241 if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2242 return parseAndLoadModuleMapFile(Dir: *Dir, IsSystem, ImplicitlyDiscovered,
2243 IsFramework);
2244
2245 return MMR_NoDirectory;
2246}
2247
2248HeaderSearch::ModuleMapResult
2249HeaderSearch::parseAndLoadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
2250 bool ImplicitlyDiscovered,
2251 bool IsFramework) {
2252 auto InsertRes = DirectoryModuleMap.insert(KV: std::pair{
2253 Dir, ModuleMapDirectoryState{.ModuleMapFile: {}, .PrivateModuleMapFile: {}, .Status: ModuleMapDirectoryState::Invalid}});
2254 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2255 if (!InsertRes.second) {
2256 switch (MMState.Status) {
2257 case ModuleMapDirectoryState::Parsed:
2258 break;
2259 case ModuleMapDirectoryState::Loaded:
2260 return MMR_AlreadyProcessed;
2261 case ModuleMapDirectoryState::Invalid:
2262 return MMR_InvalidModuleMap;
2263 };
2264 }
2265
2266 if (!MMState.ModuleMapFile) {
2267 MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);
2268 if (MMState.ModuleMapFile)
2269 MMState.PrivateModuleMapFile =
2270 getPrivateModuleMap(File: *MMState.ModuleMapFile, FileMgr, Diags);
2271 }
2272
2273 if (MMState.ModuleMapFile) {
2274 ModuleMapResult Result = parseAndLoadModuleMapFileImpl(
2275 File: *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2276 // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
2277 // E.g. Foo.framework/Modules/module.modulemap
2278 // ^Dir ^ModuleMapFile
2279 if (Result == MMR_NewlyProcessed)
2280 MMState.Status = ModuleMapDirectoryState::Loaded;
2281 else if (Result == MMR_InvalidModuleMap)
2282 MMState.Status = ModuleMapDirectoryState::Invalid;
2283 return Result;
2284 }
2285 return MMR_InvalidModuleMap;
2286}
2287
2288HeaderSearch::ModuleMapResult
2289HeaderSearch::parseModuleMapFile(StringRef DirName, bool IsSystem,
2290 bool ImplicitlyDiscovered, bool IsFramework) {
2291 if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2292 return parseModuleMapFile(Dir: *Dir, IsSystem, ImplicitlyDiscovered,
2293 IsFramework);
2294
2295 return MMR_NoDirectory;
2296}
2297
2298HeaderSearch::ModuleMapResult
2299HeaderSearch::parseModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
2300 bool ImplicitlyDiscovered, bool IsFramework) {
2301 if (!HSOpts.LazyLoadModuleMaps)
2302 return parseAndLoadModuleMapFile(Dir, IsSystem, ImplicitlyDiscovered,
2303 IsFramework);
2304
2305 auto InsertRes = DirectoryModuleMap.insert(KV: std::pair{
2306 Dir, ModuleMapDirectoryState{.ModuleMapFile: {}, .PrivateModuleMapFile: {}, .Status: ModuleMapDirectoryState::Invalid}});
2307 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2308 if (!InsertRes.second) {
2309 switch (MMState.Status) {
2310 case ModuleMapDirectoryState::Parsed:
2311 case ModuleMapDirectoryState::Loaded:
2312 return MMR_AlreadyProcessed;
2313 case ModuleMapDirectoryState::Invalid:
2314 return MMR_InvalidModuleMap;
2315 };
2316 }
2317
2318 if (!MMState.ModuleMapFile) {
2319 MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);
2320 if (MMState.ModuleMapFile)
2321 MMState.PrivateModuleMapFile =
2322 getPrivateModuleMap(File: *MMState.ModuleMapFile, FileMgr, Diags);
2323 }
2324
2325 if (MMState.ModuleMapFile) {
2326 ModuleMapResult Result = parseModuleMapFileImpl(
2327 File: *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2328 // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
2329 // E.g. Foo.framework/Modules/module.modulemap
2330 // ^Dir ^ModuleMapFile
2331 if (Result == MMR_NewlyProcessed)
2332 MMState.Status = ModuleMapDirectoryState::Parsed;
2333 else if (Result == MMR_InvalidModuleMap)
2334 MMState.Status = ModuleMapDirectoryState::Invalid;
2335 return Result;
2336 }
2337 return MMR_InvalidModuleMap;
2338}
2339
2340void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
2341 Modules.clear();
2342
2343 if (HSOpts.ImplicitModuleMaps) {
2344 // Load module maps for each of the header search directories.
2345 for (DirectoryLookup &DL : search_dir_range()) {
2346 bool IsSystem = DL.isSystemHeaderDirectory();
2347 if (DL.isFramework()) {
2348 std::error_code EC;
2349 SmallString<128> DirNative;
2350 llvm::sys::path::native(path: DL.getFrameworkDirRef()->getName(), result&: DirNative);
2351
2352 // Search each of the ".framework" directories to load them as modules.
2353 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2354 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(Dir: DirNative, EC),
2355 DirEnd;
2356 Dir != DirEnd && !EC; Dir.increment(EC)) {
2357 if (llvm::sys::path::extension(path: Dir->path()) != ".framework")
2358 continue;
2359
2360 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(DirName: Dir->path());
2361 if (!FrameworkDir)
2362 continue;
2363
2364 // Load this framework module.
2365 loadFrameworkModule(Name: llvm::sys::path::stem(path: Dir->path()), Dir: *FrameworkDir,
2366 IsSystem, /*ImplicitlyDiscovered=*/true);
2367 }
2368 continue;
2369 }
2370
2371 // FIXME: Deal with header maps.
2372 if (DL.isHeaderMap())
2373 continue;
2374
2375 // Try to load a module map file for the search directory.
2376 parseAndLoadModuleMapFile(Dir: *DL.getDirRef(), IsSystem,
2377 /*ImplicitlyDiscovered=*/true,
2378 /*IsFramework*/ false);
2379
2380 // Try to load module map files for immediate subdirectories of this
2381 // search directory.
2382 loadSubdirectoryModuleMaps(SearchDir&: DL);
2383 }
2384 }
2385
2386 // Populate the list of modules.
2387 llvm::append_range(C&: Modules, R: llvm::make_second_range(c: ModMap.modules()));
2388}
2389
2390void HeaderSearch::loadTopLevelSystemModules() {
2391 if (!HSOpts.ImplicitModuleMaps)
2392 return;
2393
2394 // Load module maps for each of the header search directories.
2395 for (const DirectoryLookup &DL : search_dir_range()) {
2396 // We only care about normal header directories.
2397 if (!DL.isNormalDir())
2398 continue;
2399
2400 // Try to load a module map file for the search directory.
2401 parseAndLoadModuleMapFile(Dir: *DL.getDirRef(), IsSystem: DL.isSystemHeaderDirectory(),
2402 /*ImplicitlyDiscovered=*/true, IsFramework: DL.isFramework());
2403 }
2404}
2405
2406void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
2407 assert(HSOpts.ImplicitModuleMaps &&
2408 "Should not be loading subdirectory module maps");
2409
2410 if (SearchDir.haveSearchedAllModuleMaps())
2411 return;
2412
2413 std::error_code EC;
2414 SmallString<128> Dir = SearchDir.getDirRef()->getName();
2415 FileMgr.makeAbsolutePath(Path&: Dir);
2416 SmallString<128> DirNative;
2417 llvm::sys::path::native(path: Dir, result&: DirNative);
2418 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2419 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(Dir: DirNative, EC), DirEnd;
2420 Dir != DirEnd && !EC; Dir.increment(EC)) {
2421 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2422 continue;
2423 bool IsFramework = llvm::sys::path::extension(path: Dir->path()) == ".framework";
2424 if (IsFramework == SearchDir.isFramework())
2425 parseAndLoadModuleMapFile(
2426 DirName: Dir->path(), IsSystem: SearchDir.isSystemHeaderDirectory(),
2427 /*ImplicitlyDiscovered=*/true, IsFramework: SearchDir.isFramework());
2428 }
2429
2430 SearchDir.setSearchedAllModuleMaps(true);
2431}
2432
2433std::string HeaderSearch::suggestPathToFileForDiagnostics(
2434 FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {
2435 return suggestPathToFileForDiagnostics(File: File.getName(), /*WorkingDir=*/"",
2436 MainFile, IsAngled);
2437}
2438
2439std::string HeaderSearch::suggestPathToFileForDiagnostics(
2440 llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2441 bool *IsAngled) const {
2442 using namespace llvm::sys;
2443
2444 llvm::SmallString<32> FilePath = File;
2445 if (!WorkingDir.empty() && !path::is_absolute(path: FilePath))
2446 path::make_absolute(current_directory: WorkingDir, path&: FilePath);
2447 // remove_dots switches to backslashes on windows as a side-effect!
2448 // We always want to suggest forward slashes for includes.
2449 // (not remove_dots(..., posix) as that misparses windows paths).
2450 path::remove_dots(path&: FilePath, /*remove_dot_dot=*/true);
2451 path::native(path&: FilePath, style: path::Style::posix);
2452 File = FilePath;
2453
2454 unsigned BestPrefixLength = 0;
2455 // Checks whether `Dir` is a strict path prefix of `File`. If so and that's
2456 // the longest prefix we've seen so for it, returns true and updates the
2457 // `BestPrefixLength` accordingly.
2458 auto CheckDir = [&](llvm::SmallString<32> Dir) -> bool {
2459 if (!WorkingDir.empty() && !path::is_absolute(path: Dir))
2460 path::make_absolute(current_directory: WorkingDir, path&: Dir);
2461 path::remove_dots(path&: Dir, /*remove_dot_dot=*/true);
2462 for (auto NI = path::begin(path: File), NE = path::end(path: File),
2463 DI = path::begin(path: Dir), DE = path::end(path: Dir);
2464 NI != NE; ++NI, ++DI) {
2465 if (DI == DE) {
2466 // Dir is a prefix of File, up to choice of path separators.
2467 unsigned PrefixLength = NI - path::begin(path: File);
2468 if (PrefixLength > BestPrefixLength) {
2469 BestPrefixLength = PrefixLength;
2470 return true;
2471 }
2472 break;
2473 }
2474
2475 // Consider all path separators equal.
2476 if (NI->size() == 1 && DI->size() == 1 &&
2477 path::is_separator(value: NI->front()) && path::is_separator(value: DI->front()))
2478 continue;
2479
2480 // Special case Apple .sdk folders since the search path is typically a
2481 // symlink like `iPhoneSimulator14.5.sdk` while the file is instead
2482 // located in `iPhoneSimulator.sdk` (the real folder).
2483 if (NI->ends_with(Suffix: ".sdk") && DI->ends_with(Suffix: ".sdk")) {
2484 StringRef NBasename = path::stem(path: *NI);
2485 StringRef DBasename = path::stem(path: *DI);
2486 if (DBasename.starts_with(Prefix: NBasename))
2487 continue;
2488 }
2489
2490 if (*NI != *DI)
2491 break;
2492 }
2493 return false;
2494 };
2495
2496 bool BestPrefixIsFramework = false;
2497 for (const DirectoryLookup &DL : search_dir_range()) {
2498 if (DL.isNormalDir()) {
2499 StringRef Dir = DL.getDirRef()->getName();
2500 if (CheckDir(Dir)) {
2501 if (IsAngled)
2502 *IsAngled = BestPrefixLength && isSystem(CK: DL.getDirCharacteristic());
2503 BestPrefixIsFramework = false;
2504 }
2505 } else if (DL.isFramework()) {
2506 StringRef Dir = DL.getFrameworkDirRef()->getName();
2507 if (CheckDir(Dir)) {
2508 // Framework includes by convention use <>.
2509 if (IsAngled)
2510 *IsAngled = BestPrefixLength;
2511 BestPrefixIsFramework = true;
2512 }
2513 }
2514 }
2515
2516 // Try to shorten include path using TUs directory, if we couldn't find any
2517 // suitable prefix in include search paths.
2518 if (!BestPrefixLength && CheckDir(path::parent_path(path: MainFile))) {
2519 if (IsAngled)
2520 *IsAngled = false;
2521 BestPrefixIsFramework = false;
2522 }
2523
2524 // Try resolving resulting filename via reverse search in header maps,
2525 // key from header name is user preferred name for the include file.
2526 StringRef Filename = File.drop_front(N: BestPrefixLength);
2527 for (const DirectoryLookup &DL : search_dir_range()) {
2528 if (!DL.isHeaderMap())
2529 continue;
2530
2531 StringRef SpelledFilename =
2532 DL.getHeaderMap()->reverseLookupFilename(DestPath: Filename);
2533 if (!SpelledFilename.empty()) {
2534 Filename = SpelledFilename;
2535 BestPrefixIsFramework = false;
2536 break;
2537 }
2538 }
2539
2540 // If the best prefix is a framework path, we need to compute the proper
2541 // include spelling for the framework header.
2542 bool IsPrivateHeader;
2543 SmallString<128> FrameworkName, IncludeSpelling;
2544 if (BestPrefixIsFramework &&
2545 isFrameworkStylePath(Path: Filename, IsPrivateHeader, FrameworkName,
2546 IncludeSpelling)) {
2547 Filename = IncludeSpelling;
2548 }
2549 return path::convert_to_slash(path: Filename);
2550}
2551
2552void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path,
2553 SmallVectorImpl<char> &NormalizedPath) {
2554 NormalizedPath.assign(in_start: Path.begin(), in_end: Path.end());
2555 if (!NormalizedPath.empty()) {
2556 FileMgr.makeAbsolutePath(Path&: NormalizedPath);
2557 llvm::sys::path::remove_dots(path&: NormalizedPath);
2558 }
2559}
2560
2561static std::string createSpecificModuleCachePathImpl(
2562 FileManager &FileMgr, StringRef ModuleCachePath, bool DisableModuleHash,
2563 std::string ContextHash, size_t &NormalizedModuleCachePathLen) {
2564 SmallString<256> SpecificModuleCachePath;
2565 normalizeModuleCachePath(FileMgr, Path: ModuleCachePath, NormalizedPath&: SpecificModuleCachePath);
2566 NormalizedModuleCachePathLen = SpecificModuleCachePath.size();
2567 if (!SpecificModuleCachePath.empty() && !DisableModuleHash)
2568 llvm::sys::path::append(path&: SpecificModuleCachePath, a: ContextHash);
2569 return std::string(SpecificModuleCachePath);
2570}
2571
2572void HeaderSearch::initializeModuleCachePath(std::string NewContextHash) {
2573 ContextHash = std::move(NewContextHash);
2574 SpecificModuleCachePath = createSpecificModuleCachePathImpl(
2575 FileMgr, ModuleCachePath: HSOpts.ModuleCachePath, DisableModuleHash: HSOpts.DisableModuleHash, ContextHash,
2576 NormalizedModuleCachePathLen);
2577}
2578
2579std::string clang::createSpecificModuleCachePath(FileManager &FileMgr,
2580 StringRef ModuleCachePath,
2581 bool DisableModuleHash,
2582 std::string ContextHash) {
2583 size_t NormalizedModuleCachePathLen;
2584 return createSpecificModuleCachePathImpl(
2585 FileMgr, ModuleCachePath, DisableModuleHash, ContextHash: std::move(ContextHash),
2586 NormalizedModuleCachePathLen);
2587}
2588