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