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