1afd1b1c9SEugene Zelenko //===- HeaderSearch.cpp - Resolve Header File Locations -------------------===//
27a51313dSChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67a51313dSChris Lattner //
77a51313dSChris Lattner //===----------------------------------------------------------------------===//
87a51313dSChris Lattner //
97a51313dSChris Lattner //  This file implements the DirectoryLookup and HeaderSearch interfaces.
107a51313dSChris Lattner //
117a51313dSChris Lattner //===----------------------------------------------------------------------===//
127a51313dSChris Lattner 
137a51313dSChris Lattner #include "clang/Lex/HeaderSearch.h"
14afd1b1c9SEugene Zelenko #include "clang/Basic/Diagnostic.h"
157a51313dSChris Lattner #include "clang/Basic/FileManager.h"
167a51313dSChris Lattner #include "clang/Basic/IdentifierTable.h"
17afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h"
18afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h"
19afd1b1c9SEugene Zelenko #include "clang/Lex/DirectoryLookup.h"
202aedca34SRichard Smith #include "clang/Lex/ExternalPreprocessorSource.h"
213a02247dSChandler Carruth #include "clang/Lex/HeaderMap.h"
223a02247dSChandler Carruth #include "clang/Lex/HeaderSearchOptions.h"
230fafd34aSWill Wilson #include "clang/Lex/LexDiagnostic.h"
24afd1b1c9SEugene Zelenko #include "clang/Lex/ModuleMap.h"
2520e883e5SRichard Smith #include "clang/Lex/Preprocessor.h"
26beee15e7SBen Langmuir #include "llvm/ADT/APInt.h"
27beee15e7SBen Langmuir #include "llvm/ADT/Hashing.h"
287a51313dSChris Lattner #include "llvm/ADT/SmallString.h"
29afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
30e8752a9dSVolodymyr Sapsai #include "llvm/ADT/Statistic.h"
31afd1b1c9SEugene Zelenko #include "llvm/ADT/StringRef.h"
3232c2ea5cSJan Svoboda #include "llvm/ADT/STLExtras.h"
33afd1b1c9SEugene Zelenko #include "llvm/Support/Allocator.h"
34ae63d101STed Kremenek #include "llvm/Support/Capacity.h"
354a0328c9SAlexey Bataev #include "llvm/Support/Errc.h"
36afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
373a02247dSChandler Carruth #include "llvm/Support/FileSystem.h"
383a02247dSChandler Carruth #include "llvm/Support/Path.h"
39fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h"
40afd1b1c9SEugene Zelenko #include <algorithm>
41afd1b1c9SEugene Zelenko #include <cassert>
42afd1b1c9SEugene Zelenko #include <cstddef>
43c25d8a7eSChris Lattner #include <cstdio>
44afd1b1c9SEugene Zelenko #include <cstring>
45afd1b1c9SEugene Zelenko #include <string>
46afd1b1c9SEugene Zelenko #include <system_error>
47cfeacf56SBenjamin Kramer #include <utility>
48afd1b1c9SEugene Zelenko 
497a51313dSChris Lattner using namespace clang;
507a51313dSChris Lattner 
51e8752a9dSVolodymyr Sapsai #define DEBUG_TYPE "file-search"
52e8752a9dSVolodymyr Sapsai 
53e8752a9dSVolodymyr Sapsai ALWAYS_ENABLED_STATISTIC(NumIncluded, "Number of attempted #includes.");
54e8752a9dSVolodymyr Sapsai ALWAYS_ENABLED_STATISTIC(
55e8752a9dSVolodymyr Sapsai     NumMultiIncludeFileOptzn,
56e8752a9dSVolodymyr Sapsai     "Number of #includes skipped due to the multi-include optimization.");
57e8752a9dSVolodymyr Sapsai ALWAYS_ENABLED_STATISTIC(NumFrameworkLookups, "Number of framework lookups.");
58e8752a9dSVolodymyr Sapsai ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups,
59e8752a9dSVolodymyr Sapsai                          "Number of subframework lookups.");
60e8752a9dSVolodymyr Sapsai 
6199734e76SDouglas Gregor const IdentifierInfo *
getControllingMacro(ExternalPreprocessorSource * External)622aedca34SRichard Smith HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
632aedca34SRichard Smith   if (ControllingMacro) {
6459666777SChandler Carruth     if (ControllingMacro->isOutOfDate()) {
6559666777SChandler Carruth       assert(External && "We must have an external source if we have a "
6659666777SChandler Carruth                          "controlling macro that is out of date.");
672aedca34SRichard Smith       External->updateOutOfDateIdentifier(
682aedca34SRichard Smith           *const_cast<IdentifierInfo *>(ControllingMacro));
6959666777SChandler Carruth     }
7099734e76SDouglas Gregor     return ControllingMacro;
712aedca34SRichard Smith   }
7299734e76SDouglas Gregor 
7399734e76SDouglas Gregor   if (!ControllingMacroID || !External)
74d2d442caSCraig Topper     return nullptr;
7599734e76SDouglas Gregor 
7699734e76SDouglas Gregor   ControllingMacro = External->GetIdentifier(ControllingMacroID);
7799734e76SDouglas Gregor   return ControllingMacro;
7899734e76SDouglas Gregor }
7999734e76SDouglas Gregor 
80afd1b1c9SEugene Zelenko ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default;
8109b6989eSDouglas Gregor 
HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target)829c28cb3fSDavid Blaikie HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
831f76c4e8SManuel Klimek                            SourceManager &SourceMgr, DiagnosticsEngine &Diags,
8489929282SDouglas Gregor                            const LangOptions &LangOpts,
8589929282SDouglas Gregor                            const TargetInfo *Target)
86cfeacf56SBenjamin Kramer     : HSOpts(std::move(HSOpts)), Diags(Diags),
87cfeacf56SBenjamin Kramer       FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
88afd1b1c9SEugene Zelenko       ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}
897a51313dSChris Lattner 
PrintStats()907a51313dSChris Lattner void HeaderSearch::PrintStats() {
91e8752a9dSVolodymyr Sapsai   llvm::errs() << "\n*** HeaderSearch Stats:\n"
92e8752a9dSVolodymyr Sapsai                << FileInfo.size() << " files tracked.\n";
93f7202723SJan Svoboda   unsigned NumOnceOnlyFiles = 0;
94f7202723SJan Svoboda   for (unsigned i = 0, e = FileInfo.size(); i != e; ++i)
9564ebf313SVolodymyr Sapsai     NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);
96f7202723SJan Svoboda   llvm::errs() << "  " << NumOnceOnlyFiles << " #import/#pragma once files.\n";
977a51313dSChris Lattner 
98e8752a9dSVolodymyr Sapsai   llvm::errs() << "  " << NumIncluded << " #include/#include_next/#import.\n"
99e8752a9dSVolodymyr Sapsai                << "    " << NumMultiIncludeFileOptzn
100e8752a9dSVolodymyr Sapsai                << " #includes skipped due to the multi-include optimization.\n";
1017a51313dSChris Lattner 
102e8752a9dSVolodymyr Sapsai   llvm::errs() << NumFrameworkLookups << " framework lookups.\n"
103e8752a9dSVolodymyr Sapsai                << NumSubFrameworkLookups << " subframework lookups.\n";
1047a51313dSChris Lattner }
1057a51313dSChris Lattner 
SetSearchPaths(std::vector<DirectoryLookup> dirs,unsigned int angledDirIdx,unsigned int systemDirIdx,bool noCurDirSearch,llvm::DenseMap<unsigned int,unsigned int> searchDirToHSEntry)106d5ba066cSJan Svoboda void HeaderSearch::SetSearchPaths(
107d5ba066cSJan Svoboda     std::vector<DirectoryLookup> dirs, unsigned int angledDirIdx,
108d5ba066cSJan Svoboda     unsigned int systemDirIdx, bool noCurDirSearch,
109d5ba066cSJan Svoboda     llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
110d5ba066cSJan Svoboda   assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
111d5ba066cSJan Svoboda          "Directory indices are unordered");
112ccd7e783SJan Svoboda   SearchDirs = std::move(dirs);
113ccd7e783SJan Svoboda   SearchDirsUsage.assign(SearchDirs.size(), false);
114d5ba066cSJan Svoboda   AngledDirIdx = angledDirIdx;
115d5ba066cSJan Svoboda   SystemDirIdx = systemDirIdx;
116d5ba066cSJan Svoboda   NoCurDirSearch = noCurDirSearch;
117ccd7e783SJan Svoboda   SearchDirToHSEntry = std::move(searchDirToHSEntry);
118d5ba066cSJan Svoboda   //LookupFileCache.clear();
119d5ba066cSJan Svoboda }
120d5ba066cSJan Svoboda 
AddSearchPath(const DirectoryLookup & dir,bool isAngled)121d5ba066cSJan Svoboda void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
122d5ba066cSJan Svoboda   unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
123ccd7e783SJan Svoboda   SearchDirs.insert(SearchDirs.begin() + idx, dir);
124ccd7e783SJan Svoboda   SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);
125d5ba066cSJan Svoboda   if (!isAngled)
126d5ba066cSJan Svoboda     AngledDirIdx++;
127d5ba066cSJan Svoboda   SystemDirIdx++;
128d5ba066cSJan Svoboda }
129d5ba066cSJan Svoboda 
computeUserEntryUsage() const13044451351SJan Svoboda std::vector<bool> HeaderSearch::computeUserEntryUsage() const {
13144451351SJan Svoboda   std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size());
132ccd7e783SJan Svoboda   for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
133ccd7e783SJan Svoboda     // Check whether this DirectoryLookup has been successfully used.
134ccd7e783SJan Svoboda     if (SearchDirsUsage[I]) {
135ccd7e783SJan Svoboda       auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
13644451351SJan Svoboda       // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
13744451351SJan Svoboda       if (UserEntryIdxIt != SearchDirToHSEntry.end())
13844451351SJan Svoboda         UserEntryUsage[UserEntryIdxIt->second] = true;
13944451351SJan Svoboda     }
14044451351SJan Svoboda   }
14144451351SJan Svoboda   return UserEntryUsage;
14244451351SJan Svoboda }
14344451351SJan Svoboda 
1447a51313dSChris Lattner /// CreateHeaderMap - This method returns a HeaderMap for the specified
145830885caSSylvestre Ledru /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
CreateHeaderMap(const FileEntry * FE)1467a51313dSChris Lattner const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
1477a51313dSChris Lattner   // We expect the number of headermaps to be small, and almost always empty.
1487a51313dSChris Lattner   // If it ever grows, use of a linear search should be re-evaluated.
1497a51313dSChris Lattner   if (!HeaderMaps.empty()) {
1507a51313dSChris Lattner     for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
1517a51313dSChris Lattner       // Pointer equality comparison of FileEntries works because they are
1527a51313dSChris Lattner       // already uniqued by inode.
1537a51313dSChris Lattner       if (HeaderMaps[i].first == FE)
15448769770SFangrui Song         return HeaderMaps[i].second.get();
1557a51313dSChris Lattner   }
1567a51313dSChris Lattner 
15748769770SFangrui Song   if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) {
15848769770SFangrui Song     HeaderMaps.emplace_back(FE, std::move(HM));
15948769770SFangrui Song     return HeaderMaps.back().second.get();
1607a51313dSChris Lattner   }
1617a51313dSChris Lattner 
162d2d442caSCraig Topper   return nullptr;
1637a51313dSChris Lattner }
1647a51313dSChris Lattner 
1659fc8faf9SAdrian Prantl /// Get filenames for all registered header maps.
getHeaderMapFileNames(SmallVectorImpl<std::string> & Names) const166181225b8SBruno Cardoso Lopes void HeaderSearch::getHeaderMapFileNames(
167181225b8SBruno Cardoso Lopes     SmallVectorImpl<std::string> &Names) const {
168181225b8SBruno Cardoso Lopes   for (auto &HM : HeaderMaps)
169adcd0268SBenjamin Kramer     Names.push_back(std::string(HM.first->getName()));
170181225b8SBruno Cardoso Lopes }
171181225b8SBruno Cardoso Lopes 
getCachedModuleFileName(Module * Module)172d30446fdSBoris Kolpackov std::string HeaderSearch::getCachedModuleFileName(Module *Module) {
1739d6448b1SBen Langmuir   const FileEntry *ModuleMap =
1749d6448b1SBen Langmuir       getModuleMap().getModuleMapFileForUniquing(Module);
175d7969012SZezhengLi   // The ModuleMap maybe a nullptr, when we load a cached C++ module without
176d7969012SZezhengLi   // *.modulemap file. In this case, just return an empty string.
177d7969012SZezhengLi   if (ModuleMap == nullptr)
178d7969012SZezhengLi     return {};
179d30446fdSBoris Kolpackov   return getCachedModuleFileName(Module->Name, ModuleMap->getName());
1801735f4e7SDouglas Gregor }
1811e44e022SDouglas Gregor 
getPrebuiltModuleFileName(StringRef ModuleName,bool FileMapOnly)182d30446fdSBoris Kolpackov std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,
183d30446fdSBoris Kolpackov                                                     bool FileMapOnly) {
184d30446fdSBoris Kolpackov   // First check the module name to pcm file map.
185ef83d46bSBenjamin Kramer   auto i(HSOpts->PrebuiltModuleFiles.find(ModuleName));
186d30446fdSBoris Kolpackov   if (i != HSOpts->PrebuiltModuleFiles.end())
187d30446fdSBoris Kolpackov     return i->second;
188d30446fdSBoris Kolpackov 
189d30446fdSBoris Kolpackov   if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty())
190afd1b1c9SEugene Zelenko     return {};
19111f2a477SManman Ren 
192d30446fdSBoris Kolpackov   // Then go through each prebuilt module directory and try to find the pcm
193d30446fdSBoris Kolpackov   // file.
19411f2a477SManman Ren   for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {
19511f2a477SManman Ren     SmallString<256> Result(Dir);
19611f2a477SManman Ren     llvm::sys::fs::make_absolute(Result);
197ee572129SChuanqi Xu     if (ModuleName.contains(':'))
198ee572129SChuanqi Xu       // The separator of C++20 modules partitions (':') is not good for file
199ee572129SChuanqi Xu       // systems, here clang and gcc choose '-' by default since it is not a
200ee572129SChuanqi Xu       // valid character of C++ indentifiers. So we could avoid conflicts.
201ee572129SChuanqi Xu       llvm::sys::path::append(Result, ModuleName.split(':').first + "-" +
202ee572129SChuanqi Xu                                           ModuleName.split(':').second +
203ee572129SChuanqi Xu                                           ".pcm");
204ee572129SChuanqi Xu     else
20511f2a477SManman Ren       llvm::sys::path::append(Result, ModuleName + ".pcm");
20611f2a477SManman Ren     if (getFileMgr().getFile(Result.str()))
207509e21a1SJonas Devlieghere       return std::string(Result);
20811f2a477SManman Ren   }
209ee572129SChuanqi Xu 
210afd1b1c9SEugene Zelenko   return {};
21111f2a477SManman Ren }
21211f2a477SManman Ren 
getPrebuiltImplicitModuleFileName(Module * Module)21358c586e7SAlexandre Rames std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) {
21458c586e7SAlexandre Rames   const FileEntry *ModuleMap =
21558c586e7SAlexandre Rames       getModuleMap().getModuleMapFileForUniquing(Module);
21658c586e7SAlexandre Rames   StringRef ModuleName = Module->Name;
21758c586e7SAlexandre Rames   StringRef ModuleMapPath = ModuleMap->getName();
21858c586e7SAlexandre Rames   StringRef ModuleCacheHash = HSOpts->DisableModuleHash ? "" : getModuleHash();
21958c586e7SAlexandre Rames   for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {
22058c586e7SAlexandre Rames     SmallString<256> CachePath(Dir);
22158c586e7SAlexandre Rames     llvm::sys::fs::make_absolute(CachePath);
22258c586e7SAlexandre Rames     llvm::sys::path::append(CachePath, ModuleCacheHash);
22358c586e7SAlexandre Rames     std::string FileName =
22458c586e7SAlexandre Rames         getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
22558c586e7SAlexandre Rames     if (!FileName.empty() && getFileMgr().getFile(FileName))
22658c586e7SAlexandre Rames       return FileName;
22758c586e7SAlexandre Rames   }
22858c586e7SAlexandre Rames   return {};
22958c586e7SAlexandre Rames }
23058c586e7SAlexandre Rames 
getCachedModuleFileName(StringRef ModuleName,StringRef ModuleMapPath)231d30446fdSBoris Kolpackov std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName,
232d30446fdSBoris Kolpackov                                                   StringRef ModuleMapPath) {
23358c586e7SAlexandre Rames   return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
23458c586e7SAlexandre Rames                                      getModuleCachePath());
23558c586e7SAlexandre Rames }
23658c586e7SAlexandre Rames 
getCachedModuleFileNameImpl(StringRef ModuleName,StringRef ModuleMapPath,StringRef CachePath)23758c586e7SAlexandre Rames std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
23858c586e7SAlexandre Rames                                                       StringRef ModuleMapPath,
23958c586e7SAlexandre Rames                                                       StringRef CachePath) {
240d520a250SRichard Smith   // If we don't have a module cache path or aren't supposed to use one, we
241d520a250SRichard Smith   // can't do anything.
24258c586e7SAlexandre Rames   if (CachePath.empty())
243afd1b1c9SEugene Zelenko     return {};
2441735f4e7SDouglas Gregor 
24558c586e7SAlexandre Rames   SmallString<256> Result(CachePath);
246beee15e7SBen Langmuir   llvm::sys::fs::make_absolute(Result);
247beee15e7SBen Langmuir 
248beee15e7SBen Langmuir   if (HSOpts->DisableModuleHash) {
249279a6c37SDouglas Gregor     llvm::sys::path::append(Result, ModuleName + ".pcm");
250beee15e7SBen Langmuir   } else {
251beee15e7SBen Langmuir     // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
25254cc3c2fSRichard Smith     // ideally be globally unique to this particular module. Name collisions
25354cc3c2fSRichard Smith     // in the hash are safe (because any translation unit can only import one
25454cc3c2fSRichard Smith     // module with each name), but result in a loss of caching.
25554cc3c2fSRichard Smith     //
25654cc3c2fSRichard Smith     // To avoid false-negatives, we form as canonical a path as we can, and map
25754cc3c2fSRichard Smith     // to lower-case in case we're on a case-insensitive file system.
258adcd0268SBenjamin Kramer     std::string Parent =
259adcd0268SBenjamin Kramer         std::string(llvm::sys::path::parent_path(ModuleMapPath));
2603f57cff1SRichard Smith     if (Parent.empty())
2613f57cff1SRichard Smith       Parent = ".";
2628d323d15SHarlan Haskins     auto Dir = FileMgr.getDirectory(Parent);
26354cc3c2fSRichard Smith     if (!Dir)
264afd1b1c9SEugene Zelenko       return {};
2658d323d15SHarlan Haskins     auto DirName = FileMgr.getCanonicalName(*Dir);
26654cc3c2fSRichard Smith     auto FileName = llvm::sys::path::filename(ModuleMapPath);
26754cc3c2fSRichard Smith 
26854cc3c2fSRichard Smith     llvm::hash_code Hash =
269793038d3SAdrian Prantl       llvm::hash_combine(DirName.lower(), FileName.lower());
27054cc3c2fSRichard Smith 
271beee15e7SBen Langmuir     SmallString<128> HashStr;
27254cc3c2fSRichard Smith     llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36);
27392e1b62dSYaron Keren     llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");
274beee15e7SBen Langmuir   }
275279a6c37SDouglas Gregor   return Result.str().str();
276279a6c37SDouglas Gregor }
277279a6c37SDouglas Gregor 
lookupModule(StringRef ModuleName,SourceLocation ImportLoc,bool AllowSearch,bool AllowExtraModuleMapSearch)278638c673aSJan Svoboda Module *HeaderSearch::lookupModule(StringRef ModuleName,
279638c673aSJan Svoboda                                    SourceLocation ImportLoc, bool AllowSearch,
28052431f39SBruno Cardoso Lopes                                    bool AllowExtraModuleMapSearch) {
281af28ec80SDouglas Gregor   // Look in the module map to determine if there is a module by this name.
282279a6c37SDouglas Gregor   Module *Module = ModMap.findModule(ModuleName);
28347972afdSRichard Smith   if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
284279a6c37SDouglas Gregor     return Module;
285279a6c37SDouglas Gregor 
2864d867640SGraydon Hoare   StringRef SearchName = ModuleName;
287638c673aSJan Svoboda   Module = lookupModule(ModuleName, SearchName, ImportLoc,
288638c673aSJan Svoboda                         AllowExtraModuleMapSearch);
2894d867640SGraydon Hoare 
2904d867640SGraydon Hoare   // The facility for "private modules" -- adjacent, optional module maps named
2914d867640SGraydon Hoare   // module.private.modulemap that are supposed to define private submodules --
29229729919SBruno Cardoso Lopes   // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.
29329729919SBruno Cardoso Lopes   //
2942a8c18d9SAlexander Kornienko   // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate
29529729919SBruno Cardoso Lopes   // should also rename to Foo_Private. Representing private as submodules
29629729919SBruno Cardoso Lopes   // could force building unwanted dependencies into the parent module and cause
29729729919SBruno Cardoso Lopes   // dependency cycles.
29829729919SBruno Cardoso Lopes   if (!Module && SearchName.consume_back("_Private"))
299638c673aSJan Svoboda     Module = lookupModule(ModuleName, SearchName, ImportLoc,
300638c673aSJan Svoboda                           AllowExtraModuleMapSearch);
3014d867640SGraydon Hoare   if (!Module && SearchName.consume_back("Private"))
302638c673aSJan Svoboda     Module = lookupModule(ModuleName, SearchName, ImportLoc,
303638c673aSJan Svoboda                           AllowExtraModuleMapSearch);
3044d867640SGraydon Hoare   return Module;
3054d867640SGraydon Hoare }
3064d867640SGraydon Hoare 
lookupModule(StringRef ModuleName,StringRef SearchName,SourceLocation ImportLoc,bool AllowExtraModuleMapSearch)30752431f39SBruno Cardoso Lopes Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
308638c673aSJan Svoboda                                    SourceLocation ImportLoc,
30952431f39SBruno Cardoso Lopes                                    bool AllowExtraModuleMapSearch) {
3104d867640SGraydon Hoare   Module *Module = nullptr;
3114d867640SGraydon Hoare 
3124ddf2221SDouglas Gregor   // Look through the various header search paths to load any available module
313af28ec80SDouglas Gregor   // maps, searching for a module map that describes this module.
3146007b0b6SJan Svoboda   for (DirectoryLookup Dir : search_dir_range()) {
3156007b0b6SJan Svoboda     if (Dir.isFramework()) {
3164d867640SGraydon Hoare       // Search for or infer a module map for a framework. Here we use
3174d867640SGraydon Hoare       // SearchName rather than ModuleName, to permit finding private modules
3184d867640SGraydon Hoare       // named FooPrivate in buggy frameworks named Foo.
3192c1dd271SDylan Noblesmith       SmallString<128> FrameworkDirName;
3206007b0b6SJan Svoboda       FrameworkDirName += Dir.getFrameworkDir()->getName();
3214d867640SGraydon Hoare       llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
322d9390b6aSJan Svoboda       if (auto FrameworkDir =
323d9390b6aSJan Svoboda               FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
3246007b0b6SJan Svoboda         bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;
3258d323d15SHarlan Haskins         Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
326ca295457SDouglas Gregor         if (Module)
327ca295457SDouglas Gregor           break;
328ca295457SDouglas Gregor       }
329ca295457SDouglas Gregor     }
330ca295457SDouglas Gregor 
331ca295457SDouglas Gregor     // FIXME: Figure out how header maps and module maps will work together.
332ca295457SDouglas Gregor 
333ca295457SDouglas Gregor     // Only deal with normal search directories.
3346007b0b6SJan Svoboda     if (!Dir.isNormalDir())
335af28ec80SDouglas Gregor       continue;
336af28ec80SDouglas Gregor 
3376007b0b6SJan Svoboda     bool IsSystem = Dir.isSystemHeaderDirectory();
338d9390b6aSJan Svoboda     // Only returns None if not a normal directory, which we just checked
339d9390b6aSJan Svoboda     DirectoryEntryRef NormalDir = *Dir.getDirRef();
34080b6904bSDouglas Gregor     // Search for a module map file in this directory.
341d9390b6aSJan Svoboda     if (loadModuleMapFile(NormalDir, IsSystem,
342984e1df7SBen Langmuir                           /*IsFramework*/false) == LMM_NewlyLoaded) {
34380b6904bSDouglas Gregor       // We just loaded a module map file; check whether the module is
34480b6904bSDouglas Gregor       // available now.
345af28ec80SDouglas Gregor       Module = ModMap.findModule(ModuleName);
346af28ec80SDouglas Gregor       if (Module)
347af28ec80SDouglas Gregor         break;
348af28ec80SDouglas Gregor     }
349af28ec80SDouglas Gregor 
350af28ec80SDouglas Gregor     // Search for a module map in a subdirectory with the same name as the
351af28ec80SDouglas Gregor     // module.
3522c1dd271SDylan Noblesmith     SmallString<128> NestedModuleMapDirName;
3536007b0b6SJan Svoboda     NestedModuleMapDirName = Dir.getDir()->getName();
354af28ec80SDouglas Gregor     llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
355984e1df7SBen Langmuir     if (loadModuleMapFile(NestedModuleMapDirName, IsSystem,
356984e1df7SBen Langmuir                           /*IsFramework*/false) == LMM_NewlyLoaded){
35780b6904bSDouglas Gregor       // If we just loaded a module map file, look for the module again.
358af28ec80SDouglas Gregor       Module = ModMap.findModule(ModuleName);
359af28ec80SDouglas Gregor       if (Module)
360af28ec80SDouglas Gregor         break;
361af28ec80SDouglas Gregor     }
3620339a64aSDouglas Gregor 
3630339a64aSDouglas Gregor     // If we've already performed the exhaustive search for module maps in this
3640339a64aSDouglas Gregor     // search directory, don't do it again.
3656007b0b6SJan Svoboda     if (Dir.haveSearchedAllModuleMaps())
3660339a64aSDouglas Gregor       continue;
3670339a64aSDouglas Gregor 
3680339a64aSDouglas Gregor     // Load all module maps in the immediate subdirectories of this search
36952431f39SBruno Cardoso Lopes     // directory if ModuleName was from @import.
37052431f39SBruno Cardoso Lopes     if (AllowExtraModuleMapSearch)
3716007b0b6SJan Svoboda       loadSubdirectoryModuleMaps(Dir);
3720339a64aSDouglas Gregor 
3730339a64aSDouglas Gregor     // Look again for the module.
3740339a64aSDouglas Gregor     Module = ModMap.findModule(ModuleName);
3750339a64aSDouglas Gregor     if (Module)
3760339a64aSDouglas Gregor       break;
377af28ec80SDouglas Gregor   }
378af28ec80SDouglas Gregor 
379279a6c37SDouglas Gregor   return Module;
3801e44e022SDouglas Gregor }
3811e44e022SDouglas Gregor 
3827a51313dSChris Lattner //===----------------------------------------------------------------------===//
3837a51313dSChris Lattner // File lookup within a DirectoryLookup scope
3847a51313dSChris Lattner //===----------------------------------------------------------------------===//
3857a51313dSChris Lattner 
3867a51313dSChris Lattner /// getName - Return the directory or filename corresponding to this lookup
3877a51313dSChris Lattner /// object.
getName() const38899d1b295SMehdi Amini StringRef DirectoryLookup::getName() const {
3890377ca64SAlex Lorenz   // FIXME: Use the name from \c DirectoryEntryRef.
3907a51313dSChris Lattner   if (isNormalDir())
3917a51313dSChris Lattner     return getDir()->getName();
3927a51313dSChris Lattner   if (isFramework())
3937a51313dSChris Lattner     return getFrameworkDir()->getName();
3947a51313dSChris Lattner   assert(isHeaderMap() && "Unknown DirectoryLookup");
3957a51313dSChris Lattner   return getHeaderMap()->getFileName();
3967a51313dSChris Lattner }
3977a51313dSChris Lattner 
getFileAndSuggestModule(StringRef FileName,SourceLocation IncludeLoc,const DirectoryEntry * Dir,bool IsSystemHeaderDir,Module * RequestingModule,ModuleMap::KnownHeader * SuggestedModule)3984dc5573aSAlex Lorenz Optional<FileEntryRef> HeaderSearch::getFileAndSuggestModule(
399f42103ceSTaewook Oh     StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,
400f42103ceSTaewook Oh     bool IsSystemHeaderDir, Module *RequestingModule,
401f42103ceSTaewook Oh     ModuleMap::KnownHeader *SuggestedModule) {
4028c71eba1SRichard Smith   // If we have a module map that might map this header, load it and
4038c71eba1SRichard Smith   // check whether we'll have a suggestion for a module.
4044dc5573aSAlex Lorenz   auto File = getFileMgr().getFileRef(FileName, /*OpenFile=*/true);
405babdfdecSNico Weber   if (!File) {
406babdfdecSNico Weber     // For rare, surprising errors (e.g. "out of file handles"), diag the EC
407babdfdecSNico Weber     // message.
4089ef6c49bSDuncan P. N. Exon Smith     std::error_code EC = llvm::errorToErrorCode(File.takeError());
4094a0328c9SAlexey Bataev     if (EC != llvm::errc::no_such_file_or_directory &&
4104a0328c9SAlexey Bataev         EC != llvm::errc::invalid_argument &&
4114a0328c9SAlexey Bataev         EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
4121d63b02fSReid Kleckner       Diags.Report(IncludeLoc, diag::err_cannot_open_file)
4131d63b02fSReid Kleckner           << FileName << EC.message();
414babdfdecSNico Weber     }
4154dc5573aSAlex Lorenz     return None;
416babdfdecSNico Weber   }
4178c71eba1SRichard Smith 
4183d5b48c4SRichard Smith   // If there is a module that corresponds to this header, suggest it.
4194dc5573aSAlex Lorenz   if (!findUsableModuleForHeader(
4204dc5573aSAlex Lorenz           &File->getFileEntry(), Dir ? Dir : File->getFileEntry().getDir(),
4214dc5573aSAlex Lorenz           RequestingModule, SuggestedModule, IsSystemHeaderDir))
4224dc5573aSAlex Lorenz     return None;
4238c71eba1SRichard Smith 
4248d323d15SHarlan Haskins   return *File;
4258c71eba1SRichard Smith }
4268c71eba1SRichard Smith 
4277a51313dSChris Lattner /// LookupFile - Lookup the specified file in this search path, returning it
4287a51313dSChris Lattner /// 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) const4294dc5573aSAlex Lorenz Optional<FileEntryRef> DirectoryLookup::LookupFile(
4304dc5573aSAlex Lorenz     StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,
4314dc5573aSAlex Lorenz     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
4324dc5573aSAlex Lorenz     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
4334dc5573aSAlex Lorenz     bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
4342f843616SVolodymyr Sapsai     bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName) const {
4353c9bc4dbSDaniel Dunbar   InUserSpecifiedSystemFramework = false;
4362f843616SVolodymyr Sapsai   IsInHeaderMap = false;
4372f843616SVolodymyr Sapsai   MappedName.clear();
4383c9bc4dbSDaniel Dunbar 
4392c1dd271SDylan Noblesmith   SmallString<1024> TmpDir;
4407a51313dSChris Lattner   if (isNormalDir()) {
4417a51313dSChris Lattner     // Concatenate the requested file onto the directory.
442b672638dSJan Svoboda     TmpDir = getDirRef()->getName();
443f7ca26a0SEli Friedman     llvm::sys::path::append(TmpDir, Filename);
444d2d442caSCraig Topper     if (SearchPath) {
445b672638dSJan Svoboda       StringRef SearchPathRef(getDirRef()->getName());
4460c69fd27SManuel Klimek       SearchPath->clear();
4470c69fd27SManuel Klimek       SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
4480c69fd27SManuel Klimek     }
449d2d442caSCraig Topper     if (RelativePath) {
4500c69fd27SManuel Klimek       RelativePath->clear();
4510c69fd27SManuel Klimek       RelativePath->append(Filename.begin(), Filename.end());
4520c69fd27SManuel Klimek     }
453718292f2SDouglas Gregor 
454f42103ceSTaewook Oh     return HS.getFileAndSuggestModule(TmpDir, IncludeLoc, getDir(),
4558c71eba1SRichard Smith                                       isSystemHeaderDirectory(),
4563d5b48c4SRichard Smith                                       RequestingModule, SuggestedModule);
4577a51313dSChris Lattner   }
4587a51313dSChris Lattner 
4597a51313dSChris Lattner   if (isFramework())
46097eec24bSDouglas Gregor     return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
4613d5b48c4SRichard Smith                              RequestingModule, SuggestedModule,
462421380a1SVolodymyr Sapsai                              InUserSpecifiedSystemFramework, IsFrameworkFound);
4637a51313dSChris Lattner 
4647a51313dSChris Lattner   assert(isHeaderMap() && "Unknown directory lookup");
46575fa9eddSArgyrios Kyrtzidis   const HeaderMap *HM = getHeaderMap();
46675fa9eddSArgyrios Kyrtzidis   SmallString<1024> Path;
46775fa9eddSArgyrios Kyrtzidis   StringRef Dest = HM->lookupFilename(Filename, Path);
46875fa9eddSArgyrios Kyrtzidis   if (Dest.empty())
4694dc5573aSAlex Lorenz     return None;
47075fa9eddSArgyrios Kyrtzidis 
4712f843616SVolodymyr Sapsai   IsInHeaderMap = true;
4722f843616SVolodymyr Sapsai 
4734dc5573aSAlex Lorenz   auto FixupSearchPath = [&]() {
474d2d442caSCraig Topper     if (SearchPath) {
4750e62c1ccSChris Lattner       StringRef SearchPathRef(getName());
4760c69fd27SManuel Klimek       SearchPath->clear();
4770c69fd27SManuel Klimek       SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
4780c69fd27SManuel Klimek     }
479d2d442caSCraig Topper     if (RelativePath) {
4800c69fd27SManuel Klimek       RelativePath->clear();
4810c69fd27SManuel Klimek       RelativePath->append(Filename.begin(), Filename.end());
4820c69fd27SManuel Klimek     }
4834dc5573aSAlex Lorenz   };
4844dc5573aSAlex Lorenz 
4854dc5573aSAlex Lorenz   // Check if the headermap maps the filename to a framework include
4864dc5573aSAlex Lorenz   // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
4874dc5573aSAlex Lorenz   // framework include.
4884dc5573aSAlex Lorenz   if (llvm::sys::path::is_relative(Dest)) {
4894dc5573aSAlex Lorenz     MappedName.append(Dest.begin(), Dest.end());
4904dc5573aSAlex Lorenz     Filename = StringRef(MappedName.begin(), MappedName.size());
49144451351SJan Svoboda     Dest = HM->lookupFilename(Filename, Path);
4920c69fd27SManuel Klimek   }
49344451351SJan Svoboda 
49444451351SJan Svoboda   if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest)) {
4954dc5573aSAlex Lorenz     FixupSearchPath();
4964dc5573aSAlex Lorenz     return *Res;
4974dc5573aSAlex Lorenz   }
4984dc5573aSAlex Lorenz 
49944451351SJan Svoboda   // Header maps need to be marked as used whenever the filename matches.
50044451351SJan Svoboda   // The case where the target file **exists** is handled by callee of this
50144451351SJan Svoboda   // function as part of the regular logic that applies to include search paths.
50244451351SJan Svoboda   // The case where the target file **does not exist** is handled here:
503e7dcf09fSJan Svoboda   HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);
5044dc5573aSAlex Lorenz   return None;
5057a51313dSChris Lattner }
5067a51313dSChris Lattner 
5079fc8faf9SAdrian Prantl /// Given a framework directory, find the top-most framework directory.
5084ddf2221SDouglas Gregor ///
5094ddf2221SDouglas Gregor /// \param FileMgr The file manager to use for directory lookups.
5104ddf2221SDouglas Gregor /// \param DirName The name of the framework directory.
5114ddf2221SDouglas Gregor /// \param SubmodulePath Will be populated with the submodule path from the
5124ddf2221SDouglas Gregor /// returned top-level module to the originally named framework.
513d9390b6aSJan Svoboda static Optional<DirectoryEntryRef>
getTopFrameworkDir(FileManager & FileMgr,StringRef DirName,SmallVectorImpl<std::string> & SubmodulePath)5144ddf2221SDouglas Gregor getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
5154ddf2221SDouglas Gregor                    SmallVectorImpl<std::string> &SubmodulePath) {
5164ddf2221SDouglas Gregor   assert(llvm::sys::path::extension(DirName) == ".framework" &&
5174ddf2221SDouglas Gregor          "Not a framework directory");
5184ddf2221SDouglas Gregor 
5194ddf2221SDouglas Gregor   // Note: as an egregious but useful hack we use the real path here, because
5204ddf2221SDouglas Gregor   // frameworks moving between top-level frameworks to embedded frameworks tend
5214ddf2221SDouglas Gregor   // to be symlinked, and we base the logical structure of modules on the
5224ddf2221SDouglas Gregor   // physical layout. In particular, we need to deal with crazy includes like
5234ddf2221SDouglas Gregor   //
5244ddf2221SDouglas Gregor   //   #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h>
5254ddf2221SDouglas Gregor   //
5264ddf2221SDouglas Gregor   // where 'Bar' used to be embedded in 'Foo', is now a top-level framework
5274ddf2221SDouglas Gregor   // which one should access with, e.g.,
5284ddf2221SDouglas Gregor   //
5294ddf2221SDouglas Gregor   //   #include <Bar/Wibble.h>
5304ddf2221SDouglas Gregor   //
5314ddf2221SDouglas Gregor   // Similar issues occur when a top-level framework has moved into an
5324ddf2221SDouglas Gregor   // embedded framework.
533d9390b6aSJan Svoboda   auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName);
5348d323d15SHarlan Haskins 
5358d323d15SHarlan Haskins   if (TopFrameworkDir)
536d9390b6aSJan Svoboda     DirName = FileMgr.getCanonicalName(*TopFrameworkDir);
5374ddf2221SDouglas Gregor   do {
5384ddf2221SDouglas Gregor     // Get the parent directory name.
5394ddf2221SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
5404ddf2221SDouglas Gregor     if (DirName.empty())
5414ddf2221SDouglas Gregor       break;
5424ddf2221SDouglas Gregor 
5434ddf2221SDouglas Gregor     // Determine whether this directory exists.
544d9390b6aSJan Svoboda     auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
5454ddf2221SDouglas Gregor     if (!Dir)
5464ddf2221SDouglas Gregor       break;
5474ddf2221SDouglas Gregor 
5484ddf2221SDouglas Gregor     // If this is a framework directory, then we're a subframework of this
5494ddf2221SDouglas Gregor     // framework.
5504ddf2221SDouglas Gregor     if (llvm::sys::path::extension(DirName) == ".framework") {
551adcd0268SBenjamin Kramer       SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
5528d323d15SHarlan Haskins       TopFrameworkDir = *Dir;
5534ddf2221SDouglas Gregor     }
5544ddf2221SDouglas Gregor   } while (true);
5554ddf2221SDouglas Gregor 
5564ddf2221SDouglas Gregor   return TopFrameworkDir;
5574ddf2221SDouglas Gregor }
5587a51313dSChris Lattner 
needModuleLookup(Module * RequestingModule,bool HasSuggestedModule)559ed84df00SBruno Cardoso Lopes static bool needModuleLookup(Module *RequestingModule,
560ed84df00SBruno Cardoso Lopes                              bool HasSuggestedModule) {
561ed84df00SBruno Cardoso Lopes   return HasSuggestedModule ||
562ed84df00SBruno Cardoso Lopes          (RequestingModule && RequestingModule->NoUndeclaredIncludes);
563ed84df00SBruno Cardoso Lopes }
564ed84df00SBruno Cardoso Lopes 
5657a51313dSChris Lattner /// DoFrameworkLookup - Do a lookup of the specified file in the current
5667a51313dSChris Lattner /// 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) const5674dc5573aSAlex Lorenz Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup(
5683d5b48c4SRichard Smith     StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
5693d5b48c4SRichard Smith     SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
570b53e5483SLawrence Crowl     ModuleMap::KnownHeader *SuggestedModule,
571421380a1SVolodymyr Sapsai     bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {
5727a51313dSChris Lattner   FileManager &FileMgr = HS.getFileMgr();
5737a51313dSChris Lattner 
5747a51313dSChris Lattner   // Framework names must have a '/' in the filename.
575d081f8c8SChris Lattner   size_t SlashPos = Filename.find('/');
5764dc5573aSAlex Lorenz   if (SlashPos == StringRef::npos)
5774dc5573aSAlex Lorenz     return None;
5787a51313dSChris Lattner 
5797a51313dSChris Lattner   // Find out if this is the home for the specified framework, by checking
58017138613SDaniel Dunbar   // HeaderSearch.  Possible answers are yes/no and unknown.
581421380a1SVolodymyr Sapsai   FrameworkCacheEntry &CacheEntry =
582d081f8c8SChris Lattner     HS.LookupFrameworkCache(Filename.substr(0, SlashPos));
5837a51313dSChris Lattner 
5847a51313dSChris Lattner   // If it is known and in some other directory, fail.
585f43ce519SJan Svoboda   if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef())
5864dc5573aSAlex Lorenz     return None;
5877a51313dSChris Lattner 
5887a51313dSChris Lattner   // Otherwise, construct the path to this framework dir.
5897a51313dSChris Lattner 
5907a51313dSChris Lattner   // FrameworkName = "/System/Library/Frameworks/"
5912c1dd271SDylan Noblesmith   SmallString<1024> FrameworkName;
5920377ca64SAlex Lorenz   FrameworkName += getFrameworkDirRef()->getName();
5937a51313dSChris Lattner   if (FrameworkName.empty() || FrameworkName.back() != '/')
5947a51313dSChris Lattner     FrameworkName.push_back('/');
5957a51313dSChris Lattner 
5967a51313dSChris Lattner   // FrameworkName = "/System/Library/Frameworks/Cocoa"
59756c64013SDouglas Gregor   StringRef ModuleName(Filename.begin(), SlashPos);
59856c64013SDouglas Gregor   FrameworkName += ModuleName;
5997a51313dSChris Lattner 
6007a51313dSChris Lattner   // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
6017a51313dSChris Lattner   FrameworkName += ".framework/";
6027a51313dSChris Lattner 
60317138613SDaniel Dunbar   // If the cache entry was unresolved, populate it now.
604d2d442caSCraig Topper   if (!CacheEntry.Directory) {
605e8752a9dSVolodymyr Sapsai     ++NumFrameworkLookups;
6067a51313dSChris Lattner 
6077a51313dSChris Lattner     // If the framework dir doesn't exist, we fail.
6088d323d15SHarlan Haskins     auto Dir = FileMgr.getDirectory(FrameworkName);
6094dc5573aSAlex Lorenz     if (!Dir)
6104dc5573aSAlex Lorenz       return None;
6117a51313dSChris Lattner 
6127a51313dSChris Lattner     // Otherwise, if it does, remember that this is the right direntry for this
6137a51313dSChris Lattner     // framework.
614f43ce519SJan Svoboda     CacheEntry.Directory = getFrameworkDirRef();
6153c9bc4dbSDaniel Dunbar 
6163c9bc4dbSDaniel Dunbar     // If this is a user search directory, check if the framework has been
6173c9bc4dbSDaniel Dunbar     // user-specified as a system framework.
6183c9bc4dbSDaniel Dunbar     if (getDirCharacteristic() == SrcMgr::C_User) {
6193c9bc4dbSDaniel Dunbar       SmallString<1024> SystemFrameworkMarker(FrameworkName);
6203c9bc4dbSDaniel Dunbar       SystemFrameworkMarker += ".system_framework";
62192e1b62dSYaron Keren       if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
6223c9bc4dbSDaniel Dunbar         CacheEntry.IsUserSpecifiedSystemFramework = true;
6237a51313dSChris Lattner       }
6243c9bc4dbSDaniel Dunbar     }
6253c9bc4dbSDaniel Dunbar   }
6263c9bc4dbSDaniel Dunbar 
627421380a1SVolodymyr Sapsai   // Set out flags.
6283c9bc4dbSDaniel Dunbar   InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
629*0916d96dSKazu Hirata   IsFrameworkFound = CacheEntry.Directory.has_value();
6307a51313dSChris Lattner 
631d2d442caSCraig Topper   if (RelativePath) {
6320c69fd27SManuel Klimek     RelativePath->clear();
6330c69fd27SManuel Klimek     RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
6340c69fd27SManuel Klimek   }
6350c69fd27SManuel Klimek 
6367a51313dSChris Lattner   // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
6377a51313dSChris Lattner   unsigned OrigSize = FrameworkName.size();
6387a51313dSChris Lattner 
6397a51313dSChris Lattner   FrameworkName += "Headers/";
6400c69fd27SManuel Klimek 
641d2d442caSCraig Topper   if (SearchPath) {
6420c69fd27SManuel Klimek     SearchPath->clear();
6430c69fd27SManuel Klimek     // Without trailing '/'.
6440c69fd27SManuel Klimek     SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
6450c69fd27SManuel Klimek   }
6460c69fd27SManuel Klimek 
647d081f8c8SChris Lattner   FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
6488d323d15SHarlan Haskins 
6499ef6c49bSDuncan P. N. Exon Smith   auto File =
6509ef6c49bSDuncan P. N. Exon Smith       FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);
6514dc5573aSAlex Lorenz   if (!File) {
6527a51313dSChris Lattner     // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
6537a51313dSChris Lattner     const char *Private = "Private";
6547a51313dSChris Lattner     FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
6557a51313dSChris Lattner                          Private+strlen(Private));
656d2d442caSCraig Topper     if (SearchPath)
6570c69fd27SManuel Klimek       SearchPath->insert(SearchPath->begin()+OrigSize, Private,
6580c69fd27SManuel Klimek                          Private+strlen(Private));
6590c69fd27SManuel Klimek 
6609ef6c49bSDuncan P. N. Exon Smith     File = FileMgr.getOptionalFileRef(FrameworkName,
6619ef6c49bSDuncan P. N. Exon Smith                                       /*OpenFile=*/!SuggestedModule);
6624ddf2221SDouglas Gregor   }
6634ddf2221SDouglas Gregor 
6644ddf2221SDouglas Gregor   // If we found the header and are allowed to suggest a module, do so now.
6654dc5573aSAlex Lorenz   if (File && needModuleLookup(RequestingModule, SuggestedModule)) {
6664ddf2221SDouglas Gregor     // Find the framework in which this header occurs.
6674dc5573aSAlex Lorenz     StringRef FrameworkPath = File->getFileEntry().getDir()->getName();
6684ddf2221SDouglas Gregor     bool FoundFramework = false;
6694ddf2221SDouglas Gregor     do {
6704ddf2221SDouglas Gregor       // Determine whether this directory exists.
6718d323d15SHarlan Haskins       auto Dir = FileMgr.getDirectory(FrameworkPath);
6724ddf2221SDouglas Gregor       if (!Dir)
6734ddf2221SDouglas Gregor         break;
6744ddf2221SDouglas Gregor 
6754ddf2221SDouglas Gregor       // If this is a framework directory, then we're a subframework of this
6764ddf2221SDouglas Gregor       // framework.
6774ddf2221SDouglas Gregor       if (llvm::sys::path::extension(FrameworkPath) == ".framework") {
6784ddf2221SDouglas Gregor         FoundFramework = true;
6794ddf2221SDouglas Gregor         break;
6804ddf2221SDouglas Gregor       }
681ef914b89SBen Langmuir 
682ef914b89SBen Langmuir       // Get the parent directory name.
683ef914b89SBen Langmuir       FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
684ef914b89SBen Langmuir       if (FrameworkPath.empty())
685ef914b89SBen Langmuir         break;
6864ddf2221SDouglas Gregor     } while (true);
6874ddf2221SDouglas Gregor 
6884ddf2221SDouglas Gregor     bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
6893d5b48c4SRichard Smith     if (FoundFramework) {
6903d5b48c4SRichard Smith       if (!HS.findUsableModuleForFrameworkHeader(
6914dc5573aSAlex Lorenz               &File->getFileEntry(), FrameworkPath, RequestingModule,
6923d5b48c4SRichard Smith               SuggestedModule, IsSystem))
6934dc5573aSAlex Lorenz         return None;
6944dc5573aSAlex Lorenz     } else {
6954dc5573aSAlex Lorenz       if (!HS.findUsableModuleForHeader(&File->getFileEntry(), getDir(),
6964dc5573aSAlex Lorenz                                         RequestingModule, SuggestedModule,
6974dc5573aSAlex Lorenz                                         IsSystem))
6984dc5573aSAlex Lorenz         return None;
6994ddf2221SDouglas Gregor     }
7004ddf2221SDouglas Gregor   }
7014dc5573aSAlex Lorenz   if (File)
7024dc5573aSAlex Lorenz     return *File;
7034dc5573aSAlex Lorenz   return None;
7047a51313dSChris Lattner }
7057a51313dSChris Lattner 
cacheLookupSuccess(LookupFileCacheInfo & CacheLookup,ConstSearchDirIterator HitIt,SourceLocation Loc)70644451351SJan Svoboda void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
70717c9fcd6SJan Svoboda                                       ConstSearchDirIterator HitIt,
70817c9fcd6SJan Svoboda                                       SourceLocation Loc) {
70917c9fcd6SJan Svoboda   CacheLookup.HitIt = HitIt;
71017c9fcd6SJan Svoboda   noteLookupUsage(HitIt.Idx, Loc);
71144451351SJan Svoboda }
71244451351SJan Svoboda 
noteLookupUsage(unsigned HitIdx,SourceLocation Loc)713ccd7e783SJan Svoboda void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {
714ccd7e783SJan Svoboda   SearchDirsUsage[HitIdx] = true;
71544451351SJan Svoboda 
716ccd7e783SJan Svoboda   auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
71744451351SJan Svoboda   if (UserEntryIdxIt != SearchDirToHSEntry.end())
71844451351SJan Svoboda     Diags.Report(Loc, diag::remark_pp_search_path_usage)
71944451351SJan Svoboda         << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
72044451351SJan Svoboda }
72144451351SJan Svoboda 
setTarget(const TargetInfo & Target)72289929282SDouglas Gregor void HeaderSearch::setTarget(const TargetInfo &Target) {
72389929282SDouglas Gregor   ModMap.setTarget(Target);
72489929282SDouglas Gregor }
72589929282SDouglas Gregor 
7267a51313dSChris Lattner //===----------------------------------------------------------------------===//
7277a51313dSChris Lattner // Header File Location.
7287a51313dSChris Lattner //===----------------------------------------------------------------------===//
7297a51313dSChris Lattner 
7309fc8faf9SAdrian Prantl /// Return true with a diagnostic if the file that MSVC would have found
731a97d4c06SReid Kleckner /// fails to match the one that Clang would have found with MSVC header search
732a97d4c06SReid Kleckner /// disabled.
checkMSVCHeaderSearch(DiagnosticsEngine & Diags,const FileEntry * MSFE,const FileEntry * FE,SourceLocation IncludeLoc)733a97d4c06SReid Kleckner static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,
734a97d4c06SReid Kleckner                                   const FileEntry *MSFE, const FileEntry *FE,
735a97d4c06SReid Kleckner                                   SourceLocation IncludeLoc) {
736a97d4c06SReid Kleckner   if (MSFE && FE != MSFE) {
737a97d4c06SReid Kleckner     Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();
738a97d4c06SReid Kleckner     return true;
739a97d4c06SReid Kleckner   }
740a97d4c06SReid Kleckner   return false;
741a97d4c06SReid Kleckner }
7427a51313dSChris Lattner 
copyString(StringRef Str,llvm::BumpPtrAllocator & Alloc)74334fad420SArgyrios Kyrtzidis static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
74434fad420SArgyrios Kyrtzidis   assert(!Str.empty());
74534fad420SArgyrios Kyrtzidis   char *CopyStr = Alloc.Allocate<char>(Str.size()+1);
74634fad420SArgyrios Kyrtzidis   std::copy(Str.begin(), Str.end(), CopyStr);
74734fad420SArgyrios Kyrtzidis   CopyStr[Str.size()] = '\0';
74834fad420SArgyrios Kyrtzidis   return CopyStr;
74934fad420SArgyrios Kyrtzidis }
75034fad420SArgyrios Kyrtzidis 
isFrameworkStylePath(StringRef Path,bool & IsPrivateHeader,SmallVectorImpl<char> & FrameworkName,SmallVectorImpl<char> & IncludeSpelling)7511b3b69fbSBruno Cardoso Lopes static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,
7520cf7e61aSDavid Goldman                                  SmallVectorImpl<char> &FrameworkName,
7530cf7e61aSDavid Goldman                                  SmallVectorImpl<char> &IncludeSpelling) {
754a9c51fe0SBruno Cardoso Lopes   using namespace llvm::sys;
755a9c51fe0SBruno Cardoso Lopes   path::const_iterator I = path::begin(Path);
756a9c51fe0SBruno Cardoso Lopes   path::const_iterator E = path::end(Path);
7571b3b69fbSBruno Cardoso Lopes   IsPrivateHeader = false;
758a9c51fe0SBruno Cardoso Lopes 
759a9c51fe0SBruno Cardoso Lopes   // Detect different types of framework style paths:
760a9c51fe0SBruno Cardoso Lopes   //
761a9c51fe0SBruno Cardoso Lopes   //   ...Foo.framework/{Headers,PrivateHeaders}
762a9c51fe0SBruno Cardoso Lopes   //   ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders}
763a9c51fe0SBruno Cardoso Lopes   //   ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders}
764a9c51fe0SBruno Cardoso Lopes   //   ...<other variations with 'Versions' like in the above path>
765a9c51fe0SBruno Cardoso Lopes   //
766a9c51fe0SBruno Cardoso Lopes   // and some other variations among these lines.
767a9c51fe0SBruno Cardoso Lopes   int FoundComp = 0;
768a9c51fe0SBruno Cardoso Lopes   while (I != E) {
7690cf7e61aSDavid Goldman     if (*I == "Headers") {
7701b3b69fbSBruno Cardoso Lopes       ++FoundComp;
7710cf7e61aSDavid Goldman     } else if (*I == "PrivateHeaders") {
772a9c51fe0SBruno Cardoso Lopes       ++FoundComp;
7731b3b69fbSBruno Cardoso Lopes       IsPrivateHeader = true;
7740cf7e61aSDavid Goldman     } else if (I->endswith(".framework")) {
7750cf7e61aSDavid Goldman       StringRef Name = I->drop_back(10); // Drop .framework
7760cf7e61aSDavid Goldman       // Need to reset the strings and counter to support nested frameworks.
7770cf7e61aSDavid Goldman       FrameworkName.clear();
7780cf7e61aSDavid Goldman       FrameworkName.append(Name.begin(), Name.end());
7790cf7e61aSDavid Goldman       IncludeSpelling.clear();
7800cf7e61aSDavid Goldman       IncludeSpelling.append(Name.begin(), Name.end());
7810cf7e61aSDavid Goldman       FoundComp = 1;
7820cf7e61aSDavid Goldman     } else if (FoundComp >= 2) {
7830cf7e61aSDavid Goldman       IncludeSpelling.push_back('/');
7840cf7e61aSDavid Goldman       IncludeSpelling.append(I->begin(), I->end());
7851b3b69fbSBruno Cardoso Lopes     }
786a9c51fe0SBruno Cardoso Lopes     ++I;
787a9c51fe0SBruno Cardoso Lopes   }
788a9c51fe0SBruno Cardoso Lopes 
789abacc253SErik Pilkington   return !FrameworkName.empty() && FoundComp >= 2;
790a9c51fe0SBruno Cardoso Lopes }
791a9c51fe0SBruno Cardoso Lopes 
792a9c51fe0SBruno Cardoso Lopes static void
diagnoseFrameworkInclude(DiagnosticsEngine & Diags,SourceLocation IncludeLoc,StringRef Includer,StringRef IncludeFilename,const FileEntry * IncludeFE,bool isAngled=false,bool FoundByHeaderMap=false)793a9c51fe0SBruno Cardoso Lopes diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
794a9c51fe0SBruno Cardoso Lopes                          StringRef Includer, StringRef IncludeFilename,
795a9c51fe0SBruno Cardoso Lopes                          const FileEntry *IncludeFE, bool isAngled = false,
796a9c51fe0SBruno Cardoso Lopes                          bool FoundByHeaderMap = false) {
7971b3b69fbSBruno Cardoso Lopes   bool IsIncluderPrivateHeader = false;
798a9c51fe0SBruno Cardoso Lopes   SmallString<128> FromFramework, ToFramework;
7990cf7e61aSDavid Goldman   SmallString<128> FromIncludeSpelling, ToIncludeSpelling;
8000cf7e61aSDavid Goldman   if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework,
8010cf7e61aSDavid Goldman                             FromIncludeSpelling))
802a9c51fe0SBruno Cardoso Lopes     return;
8031b3b69fbSBruno Cardoso Lopes   bool IsIncludeePrivateHeader = false;
8040cf7e61aSDavid Goldman   bool IsIncludeeInFramework =
8050cf7e61aSDavid Goldman       isFrameworkStylePath(IncludeFE->getName(), IsIncludeePrivateHeader,
8060cf7e61aSDavid Goldman                            ToFramework, ToIncludeSpelling);
807a9c51fe0SBruno Cardoso Lopes 
808a9c51fe0SBruno Cardoso Lopes   if (!isAngled && !FoundByHeaderMap) {
809a9c51fe0SBruno Cardoso Lopes     SmallString<128> NewInclude("<");
810a9c51fe0SBruno Cardoso Lopes     if (IsIncludeeInFramework) {
8110cf7e61aSDavid Goldman       NewInclude += ToIncludeSpelling;
8120cf7e61aSDavid Goldman       NewInclude += ">";
8130cf7e61aSDavid Goldman     } else {
814a9c51fe0SBruno Cardoso Lopes       NewInclude += IncludeFilename;
815a9c51fe0SBruno Cardoso Lopes       NewInclude += ">";
8160cf7e61aSDavid Goldman     }
817a9c51fe0SBruno Cardoso Lopes     Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
818a9c51fe0SBruno Cardoso Lopes         << IncludeFilename
819a9c51fe0SBruno Cardoso Lopes         << FixItHint::CreateReplacement(IncludeLoc, NewInclude);
820a9c51fe0SBruno Cardoso Lopes   }
8211b3b69fbSBruno Cardoso Lopes 
8221b3b69fbSBruno Cardoso Lopes   // Headers in Foo.framework/Headers should not include headers
8231b3b69fbSBruno Cardoso Lopes   // from Foo.framework/PrivateHeaders, since this violates public/private
8241b3b69fbSBruno Cardoso Lopes   // API boundaries and can cause modular dependency cycles.
8251b3b69fbSBruno Cardoso Lopes   if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
8261b3b69fbSBruno Cardoso Lopes       IsIncludeePrivateHeader && FromFramework == ToFramework)
8271b3b69fbSBruno Cardoso Lopes     Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)
8281b3b69fbSBruno Cardoso Lopes         << IncludeFilename;
829a9c51fe0SBruno Cardoso Lopes }
830a9c51fe0SBruno Cardoso Lopes 
831c07ab2c9SJames Dennett /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
8327a51313dSChris Lattner /// return null on failure.  isAngled indicates whether the file reference is
8330fafd34aSWill Wilson /// for system \#include's or not (i.e. using <> instead of ""). Includers, if
8340fafd34aSWill Wilson /// non-empty, indicates where the \#including file(s) are, in case a relative
8350fafd34aSWill Wilson /// search is needed. Microsoft mode will pass all \#including files.
LookupFile(StringRef Filename,SourceLocation IncludeLoc,bool isAngled,ConstSearchDirIterator FromDir,ConstSearchDirIterator * CurDirArg,ArrayRef<std::pair<const FileEntry *,const DirectoryEntry * >> Includers,SmallVectorImpl<char> * SearchPath,SmallVectorImpl<char> * RelativePath,Module * RequestingModule,ModuleMap::KnownHeader * SuggestedModule,bool * IsMapped,bool * IsFrameworkFound,bool SkipCache,bool BuildSystemModule)8364dc5573aSAlex Lorenz Optional<FileEntryRef> HeaderSearch::LookupFile(
8370fafd34aSWill Wilson     StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
8387631c366SJan Svoboda     ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
8399af34aeaSManuel Klimek     ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
8409af34aeaSManuel Klimek     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
8413d5b48c4SRichard Smith     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
842421380a1SVolodymyr Sapsai     bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
843421380a1SVolodymyr Sapsai     bool BuildSystemModule) {
8447631c366SJan Svoboda   ConstSearchDirIterator CurDirLocal = nullptr;
8457631c366SJan Svoboda   ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
846105c9131SJan Svoboda 
847cfc1f6a6SDuncan P. N. Exon Smith   if (IsMapped)
848cfc1f6a6SDuncan P. N. Exon Smith     *IsMapped = false;
849cfc1f6a6SDuncan P. N. Exon Smith 
850421380a1SVolodymyr Sapsai   if (IsFrameworkFound)
851421380a1SVolodymyr Sapsai     *IsFrameworkFound = false;
852421380a1SVolodymyr Sapsai 
85397eec24bSDouglas Gregor   if (SuggestedModule)
854b53e5483SLawrence Crowl     *SuggestedModule = ModuleMap::KnownHeader();
85597eec24bSDouglas Gregor 
8567a51313dSChris Lattner   // If 'Filename' is absolute, check to see if it exists and no searching.
857f28df4cdSMichael J. Spencer   if (llvm::sys::path::is_absolute(Filename)) {
858d2d442caSCraig Topper     CurDir = nullptr;
8597a51313dSChris Lattner 
8607a51313dSChris Lattner     // If this was an #include_next "/absolute/file", fail.
8614dc5573aSAlex Lorenz     if (FromDir)
8624dc5573aSAlex Lorenz       return None;
8637a51313dSChris Lattner 
864d2d442caSCraig Topper     if (SearchPath)
8650c69fd27SManuel Klimek       SearchPath->clear();
866d2d442caSCraig Topper     if (RelativePath) {
8670c69fd27SManuel Klimek       RelativePath->clear();
8680c69fd27SManuel Klimek       RelativePath->append(Filename.begin(), Filename.end());
8690c69fd27SManuel Klimek     }
8707a51313dSChris Lattner     // Otherwise, just return the file.
871f42103ceSTaewook Oh     return getFileAndSuggestModule(Filename, IncludeLoc, nullptr,
8723d5b48c4SRichard Smith                                    /*IsSystemHeaderDir*/false,
8733d5b48c4SRichard Smith                                    RequestingModule, SuggestedModule);
8747a51313dSChris Lattner   }
8757a51313dSChris Lattner 
876a97d4c06SReid Kleckner   // This is the header that MSVC's header search would have found.
8778c71eba1SRichard Smith   ModuleMap::KnownHeader MSSuggestedModule;
87874910cbbSDuncan P. N. Exon Smith   Optional<FileEntryRef> MSFE;
879a97d4c06SReid Kleckner 
8809f93e38aSDouglas Gregor   // Unless disabled, check to see if the file is in the #includer's
8810fafd34aSWill Wilson   // directory.  This cannot be based on CurDir, because each includer could be
8820fafd34aSWill Wilson   // a #include of a subdirectory (#include "foo/bar.h") and a subsequent
8830fafd34aSWill Wilson   // include of "baz.h" should resolve to "whatever/foo/baz.h".
8847a51313dSChris Lattner   // This search is not done for <> headers.
8850fafd34aSWill Wilson   if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
8869cb62649SNAKAMURA Takumi     SmallString<1024> TmpDir;
8879af34aeaSManuel Klimek     bool First = true;
8889af34aeaSManuel Klimek     for (const auto &IncluderAndDir : Includers) {
8899af34aeaSManuel Klimek       const FileEntry *Includer = IncluderAndDir.first;
8909af34aeaSManuel Klimek 
891618e64a2SDouglas Gregor       // Concatenate the requested file onto the directory.
892cf385dc8SNikola Smiljanic       // FIXME: Portability.  Filename concatenation should be in sys::Path.
8939af34aeaSManuel Klimek       TmpDir = IncluderAndDir.second->getName();
894cf385dc8SNikola Smiljanic       TmpDir.push_back('/');
895cf385dc8SNikola Smiljanic       TmpDir.append(Filename.begin(), Filename.end());
8968c71eba1SRichard Smith 
8976f548ec3SRichard Smith       // FIXME: We don't cache the result of getFileInfo across the call to
8986f548ec3SRichard Smith       // getFileAndSuggestModule, because it's a reference to an element of
8996f548ec3SRichard Smith       // a container that could be reallocated across this call.
9003c1a41adSRichard Smith       //
901e4a5d37dSManman Ren       // If we have no includer, that means we're processing a #include
9023c1a41adSRichard Smith       // from a module build. We should treat this as a system header if we're
9033c1a41adSRichard Smith       // building a [system] module.
9046f548ec3SRichard Smith       bool IncluderIsSystemHeader =
905e39c8143SManman Ren           Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User :
906e39c8143SManman Ren           BuildSystemModule;
9074dc5573aSAlex Lorenz       if (Optional<FileEntryRef> FE = getFileAndSuggestModule(
908f42103ceSTaewook Oh               TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
9093d5b48c4SRichard Smith               RequestingModule, SuggestedModule)) {
9103c1a41adSRichard Smith         if (!Includer) {
9113c1a41adSRichard Smith           assert(First && "only first includer can have no file");
9123c1a41adSRichard Smith           return FE;
9133c1a41adSRichard Smith         }
9143c1a41adSRichard Smith 
9157a51313dSChris Lattner         // Leave CurDir unset.
916618e64a2SDouglas Gregor         // This file is a system header or C++ unfriendly if the old file is.
917618e64a2SDouglas Gregor         //
91803b5ebe4SDouglas Gregor         // Note that we only use one of FromHFI/ToHFI at once, due to potential
91903b5ebe4SDouglas Gregor         // reallocation of the underlying vector potentially making the first
92003b5ebe4SDouglas Gregor         // reference binding dangling.
9216f548ec3SRichard Smith         HeaderFileInfo &FromHFI = getFileInfo(Includer);
92203b5ebe4SDouglas Gregor         unsigned DirInfo = FromHFI.DirInfo;
92303b5ebe4SDouglas Gregor         bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
92403b5ebe4SDouglas Gregor         StringRef Framework = FromHFI.Framework;
92503b5ebe4SDouglas Gregor 
9264dc5573aSAlex Lorenz         HeaderFileInfo &ToHFI = getFileInfo(&FE->getFileEntry());
92703b5ebe4SDouglas Gregor         ToHFI.DirInfo = DirInfo;
92803b5ebe4SDouglas Gregor         ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
92903b5ebe4SDouglas Gregor         ToHFI.Framework = Framework;
93003b5ebe4SDouglas Gregor 
931d2d442caSCraig Topper         if (SearchPath) {
9329af34aeaSManuel Klimek           StringRef SearchPathRef(IncluderAndDir.second->getName());
9330c69fd27SManuel Klimek           SearchPath->clear();
9340c69fd27SManuel Klimek           SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
9350c69fd27SManuel Klimek         }
936d2d442caSCraig Topper         if (RelativePath) {
9370c69fd27SManuel Klimek           RelativePath->clear();
9380c69fd27SManuel Klimek           RelativePath->append(Filename.begin(), Filename.end());
9390c69fd27SManuel Klimek         }
940a9c51fe0SBruno Cardoso Lopes         if (First) {
941a9c51fe0SBruno Cardoso Lopes           diagnoseFrameworkInclude(Diags, IncludeLoc,
942a9c51fe0SBruno Cardoso Lopes                                    IncluderAndDir.second->getName(), Filename,
9434dc5573aSAlex Lorenz                                    &FE->getFileEntry());
9447a51313dSChris Lattner           return FE;
945a9c51fe0SBruno Cardoso Lopes         }
946a97d4c06SReid Kleckner 
947a97d4c06SReid Kleckner         // Otherwise, we found the path via MSVC header search rules.  If
948a97d4c06SReid Kleckner         // -Wmsvc-include is enabled, we have to keep searching to see if we
949a97d4c06SReid Kleckner         // would've found this header in -I or -isystem directories.
950d4a3f0e8SAlp Toker         if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
951a97d4c06SReid Kleckner           return FE;
952a97d4c06SReid Kleckner         } else {
95374910cbbSDuncan P. N. Exon Smith           MSFE = FE;
9548c71eba1SRichard Smith           if (SuggestedModule) {
9558c71eba1SRichard Smith             MSSuggestedModule = *SuggestedModule;
9568c71eba1SRichard Smith             *SuggestedModule = ModuleMap::KnownHeader();
9578c71eba1SRichard Smith           }
958a97d4c06SReid Kleckner           break;
959a97d4c06SReid Kleckner         }
9607a51313dSChris Lattner       }
9619af34aeaSManuel Klimek       First = false;
9627a51313dSChris Lattner     }
9630fafd34aSWill Wilson   }
9647a51313dSChris Lattner 
965d2d442caSCraig Topper   CurDir = nullptr;
9667a51313dSChris Lattner 
9677a51313dSChris Lattner   // If this is a system #include, ignore the user #include locs.
96817c9fcd6SJan Svoboda   ConstSearchDirIterator It =
96917c9fcd6SJan Svoboda       isAngled ? angled_dir_begin() : search_dir_begin();
9707a51313dSChris Lattner 
9717a51313dSChris Lattner   // If this is a #include_next request, start searching after the directory the
9727a51313dSChris Lattner   // file was found in.
9737a51313dSChris Lattner   if (FromDir)
97417c9fcd6SJan Svoboda     It = FromDir;
9757a51313dSChris Lattner 
9767a51313dSChris Lattner   // Cache all of the lookups performed by this method.  Many headers are
9777a51313dSChris Lattner   // multiply included, and the "pragma once" optimization prevents them from
9787a51313dSChris Lattner   // being relex/pp'd, but they would still have to search through a
9797a51313dSChris Lattner   // (potentially huge) series of SearchDirs to find it.
98013156b68SDavid Blaikie   LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
9817a51313dSChris Lattner 
98217c9fcd6SJan Svoboda   ConstSearchDirIterator NextIt = std::next(It);
98317c9fcd6SJan Svoboda 
9847a51313dSChris Lattner   // If the entry has been previously looked up, the first value will be
9857a51313dSChris Lattner   // non-zero.  If the value is equal to i (the start point of our search), then
9867a51313dSChris Lattner   // this is a matching hit.
98717c9fcd6SJan Svoboda   if (!SkipCache && CacheLookup.StartIt == NextIt) {
9887a51313dSChris Lattner     // Skip querying potentially lots of directories for this lookup.
98959dadd17SJan Svoboda     if (CacheLookup.HitIt)
99017c9fcd6SJan Svoboda       It = CacheLookup.HitIt;
991cfc1f6a6SDuncan P. N. Exon Smith     if (CacheLookup.MappedName) {
99234fad420SArgyrios Kyrtzidis       Filename = CacheLookup.MappedName;
993cfc1f6a6SDuncan P. N. Exon Smith       if (IsMapped)
994cfc1f6a6SDuncan P. N. Exon Smith         *IsMapped = true;
995cfc1f6a6SDuncan P. N. Exon Smith     }
9967a51313dSChris Lattner   } else {
9977a51313dSChris Lattner     // Otherwise, this is the first query, or the previous query didn't match
9987a51313dSChris Lattner     // our search start.  We will fill in our found location below, so prime the
9997a51313dSChris Lattner     // start point value.
100017c9fcd6SJan Svoboda     CacheLookup.reset(/*NewStartIt=*/NextIt);
10017a51313dSChris Lattner   }
10027a51313dSChris Lattner 
100375fa9eddSArgyrios Kyrtzidis   SmallString<64> MappedName;
100475fa9eddSArgyrios Kyrtzidis 
10057a51313dSChris Lattner   // Check each directory in sequence to see if it contains this file.
100617c9fcd6SJan Svoboda   for (; It != search_dir_end(); ++It) {
10073c9bc4dbSDaniel Dunbar     bool InUserSpecifiedSystemFramework = false;
10082f843616SVolodymyr Sapsai     bool IsInHeaderMap = false;
1009421380a1SVolodymyr Sapsai     bool IsFrameworkFoundInDir = false;
101017c9fcd6SJan Svoboda     Optional<FileEntryRef> File = It->LookupFile(
1011f42103ceSTaewook Oh         Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1012421380a1SVolodymyr Sapsai         SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
10132f843616SVolodymyr Sapsai         IsInHeaderMap, MappedName);
10142f843616SVolodymyr Sapsai     if (!MappedName.empty()) {
10152f843616SVolodymyr Sapsai       assert(IsInHeaderMap && "MappedName should come from a header map");
101634fad420SArgyrios Kyrtzidis       CacheLookup.MappedName =
10172f843616SVolodymyr Sapsai           copyString(MappedName, LookupFileCache.getAllocator());
101834fad420SArgyrios Kyrtzidis     }
10192f843616SVolodymyr Sapsai     if (IsMapped)
10202f843616SVolodymyr Sapsai       // A filename is mapped when a header map remapped it to a relative path
10212f843616SVolodymyr Sapsai       // used in subsequent header search or to an absolute path pointing to an
10222f843616SVolodymyr Sapsai       // existing file.
10232f843616SVolodymyr Sapsai       *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));
1024421380a1SVolodymyr Sapsai     if (IsFrameworkFound)
1025e32ff096SVolodymyr Sapsai       // Because we keep a filename remapped for subsequent search directory
1026e32ff096SVolodymyr Sapsai       // lookups, ignore IsFrameworkFoundInDir after the first remapping and not
1027e32ff096SVolodymyr Sapsai       // just for remapping in a current search directory.
1028e32ff096SVolodymyr Sapsai       *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
10294dc5573aSAlex Lorenz     if (!File)
10304dc5573aSAlex Lorenz       continue;
10317a51313dSChris Lattner 
103217c9fcd6SJan Svoboda     CurDir = It;
10337a51313dSChris Lattner 
1034b6c67c3cSCyndy Ishida     const auto FE = &File->getFileEntry();
1035b6c67c3cSCyndy Ishida     IncludeNames[FE] = Filename;
1036b6c67c3cSCyndy Ishida 
10377a51313dSChris Lattner     // This file is a system header or C++ unfriendly if the dir is.
1038b6c67c3cSCyndy Ishida     HeaderFileInfo &HFI = getFileInfo(FE);
10399f93e38aSDouglas Gregor     HFI.DirInfo = CurDir->getDirCharacteristic();
10409f93e38aSDouglas Gregor 
10413c9bc4dbSDaniel Dunbar     // If the directory characteristic is User but this framework was
10423c9bc4dbSDaniel Dunbar     // user-specified to be treated as a system framework, promote the
10433c9bc4dbSDaniel Dunbar     // characteristic.
10443c9bc4dbSDaniel Dunbar     if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
10453c9bc4dbSDaniel Dunbar       HFI.DirInfo = SrcMgr::C_System;
10463c9bc4dbSDaniel Dunbar 
10478acadcb8SRichard Smith     // If the filename matches a known system header prefix, override
10488acadcb8SRichard Smith     // whether the file is a system header.
1049871f5f32SRichard Trieu     for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1050871f5f32SRichard Trieu       if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
1051871f5f32SRichard Trieu         HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
10528acadcb8SRichard Smith                                                        : SrcMgr::C_User;
10538acadcb8SRichard Smith         break;
10548acadcb8SRichard Smith       }
10558acadcb8SRichard Smith     }
10568acadcb8SRichard Smith 
10579385ece9SDavid Goldman     // Set the `Framework` info if this file is in a header map with framework
10589385ece9SDavid Goldman     // style include spelling or found in a framework dir. The header map case
10599385ece9SDavid Goldman     // is possible when building frameworks which use header maps.
1060395e1fe3SCyndy Ishida     if (CurDir->isHeaderMap() && isAngled) {
10619f93e38aSDouglas Gregor       size_t SlashPos = Filename.find('/');
1062395e1fe3SCyndy Ishida       if (SlashPos != StringRef::npos)
1063395e1fe3SCyndy Ishida         HFI.Framework =
1064395e1fe3SCyndy Ishida             getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos));
1065395e1fe3SCyndy Ishida       if (CurDir->isIndexHeaderMap())
10669f93e38aSDouglas Gregor         HFI.IndexHeaderMapHeader = 1;
10679385ece9SDavid Goldman     } else if (CurDir->isFramework()) {
10689385ece9SDavid Goldman       size_t SlashPos = Filename.find('/');
10699385ece9SDavid Goldman       if (SlashPos != StringRef::npos)
10709385ece9SDavid Goldman         HFI.Framework =
10719385ece9SDavid Goldman             getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos));
10729f93e38aSDouglas Gregor     }
10737a51313dSChris Lattner 
10744dc5573aSAlex Lorenz     if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr,
10754dc5573aSAlex Lorenz                               &File->getFileEntry(), IncludeLoc)) {
10768c71eba1SRichard Smith       if (SuggestedModule)
10778c71eba1SRichard Smith         *SuggestedModule = MSSuggestedModule;
1078a97d4c06SReid Kleckner       return MSFE;
10798c71eba1SRichard Smith     }
1080a97d4c06SReid Kleckner 
1081a9c51fe0SBruno Cardoso Lopes     bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
1082a9c51fe0SBruno Cardoso Lopes     if (!Includers.empty())
10834dc5573aSAlex Lorenz       diagnoseFrameworkInclude(
10844dc5573aSAlex Lorenz           Diags, IncludeLoc, Includers.front().second->getName(), Filename,
10854dc5573aSAlex Lorenz           &File->getFileEntry(), isAngled, FoundByHeaderMap);
1086a9c51fe0SBruno Cardoso Lopes 
10877a51313dSChris Lattner     // Remember this location for the next lookup we do.
108817c9fcd6SJan Svoboda     cacheLookupSuccess(CacheLookup, It, IncludeLoc);
10894dc5573aSAlex Lorenz     return File;
10907a51313dSChris Lattner   }
10917a51313dSChris Lattner 
1092d8575e1eSDouglas Gregor   // If we are including a file with a quoted include "foo.h" from inside
1093d8575e1eSDouglas Gregor   // a header in a framework that is currently being built, and we couldn't
1094d8575e1eSDouglas Gregor   // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
1095d8575e1eSDouglas Gregor   // "Foo" is the name of the framework in which the including header was found.
10963c1a41adSRichard Smith   if (!Includers.empty() && Includers.front().first && !isAngled &&
1097dccfaddcSKazu Hirata       !Filename.contains('/')) {
10989af34aeaSManuel Klimek     HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first);
1099d8575e1eSDouglas Gregor     if (IncludingHFI.IndexHeaderMapHeader) {
11002c1dd271SDylan Noblesmith       SmallString<128> ScratchFilename;
1101d8575e1eSDouglas Gregor       ScratchFilename += IncludingHFI.Framework;
1102d8575e1eSDouglas Gregor       ScratchFilename += '/';
1103d8575e1eSDouglas Gregor       ScratchFilename += Filename;
1104d8575e1eSDouglas Gregor 
11054dc5573aSAlex Lorenz       Optional<FileEntryRef> File = LookupFile(
1106105c9131SJan Svoboda           ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, &CurDir,
1107421380a1SVolodymyr Sapsai           Includers.front(), SearchPath, RelativePath, RequestingModule,
1108421380a1SVolodymyr Sapsai           SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr);
1109a97d4c06SReid Kleckner 
11104dc5573aSAlex Lorenz       if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr,
11114dc5573aSAlex Lorenz                                 File ? &File->getFileEntry() : nullptr,
11124dc5573aSAlex Lorenz                                 IncludeLoc)) {
11138c71eba1SRichard Smith         if (SuggestedModule)
11148c71eba1SRichard Smith           *SuggestedModule = MSSuggestedModule;
1115a97d4c06SReid Kleckner         return MSFE;
11168c71eba1SRichard Smith       }
1117a97d4c06SReid Kleckner 
111844451351SJan Svoboda       cacheLookupSuccess(LookupFileCache[Filename],
111917c9fcd6SJan Svoboda                          LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
11208c71eba1SRichard Smith       // FIXME: SuggestedModule.
11214dc5573aSAlex Lorenz       return File;
1122d8575e1eSDouglas Gregor     }
1123d8575e1eSDouglas Gregor   }
1124d8575e1eSDouglas Gregor 
11254dc5573aSAlex Lorenz   if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr,
11264dc5573aSAlex Lorenz                             nullptr, IncludeLoc)) {
11278c71eba1SRichard Smith     if (SuggestedModule)
11288c71eba1SRichard Smith       *SuggestedModule = MSSuggestedModule;
1129a97d4c06SReid Kleckner     return MSFE;
11308c71eba1SRichard Smith   }
1131a97d4c06SReid Kleckner 
11327a51313dSChris Lattner   // Otherwise, didn't find it. Remember we didn't find this.
113317c9fcd6SJan Svoboda   CacheLookup.HitIt = search_dir_end();
11344dc5573aSAlex Lorenz   return None;
11357a51313dSChris Lattner }
11367a51313dSChris Lattner 
11377a51313dSChris Lattner /// LookupSubframeworkHeader - Look up a subframework for the specified
1138c07ab2c9SJames Dennett /// \#include file.  For example, if \#include'ing <HIToolbox/HIToolbox.h> from
11397a51313dSChris Lattner /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
11407a51313dSChris Lattner /// is a subframework within Carbon.framework.  If so, return the FileEntry
11417a51313dSChris Lattner /// for the designated file, otherwise return null.
LookupSubframeworkHeader(StringRef Filename,const FileEntry * ContextFileEnt,SmallVectorImpl<char> * SearchPath,SmallVectorImpl<char> * RelativePath,Module * RequestingModule,ModuleMap::KnownHeader * SuggestedModule)11424dc5573aSAlex Lorenz Optional<FileEntryRef> HeaderSearch::LookupSubframeworkHeader(
11434dc5573aSAlex Lorenz     StringRef Filename, const FileEntry *ContextFileEnt,
11444dc5573aSAlex Lorenz     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
11454dc5573aSAlex Lorenz     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {
11467a51313dSChris Lattner   assert(ContextFileEnt && "No context file?");
11477a51313dSChris Lattner 
11487a51313dSChris Lattner   // Framework names must have a '/' in the filename.  Find it.
11495ca04bd4SDouglas Gregor   // FIXME: Should we permit '\' on Windows?
1150d081f8c8SChris Lattner   size_t SlashPos = Filename.find('/');
11514dc5573aSAlex Lorenz   if (SlashPos == StringRef::npos)
11524dc5573aSAlex Lorenz     return None;
11537a51313dSChris Lattner 
11547a51313dSChris Lattner   // Look up the base framework name of the ContextFileEnt.
1155004b9c7aSMehdi Amini   StringRef ContextName = ContextFileEnt->getName();
11567a51313dSChris Lattner 
11577a51313dSChris Lattner   // If the context info wasn't a framework, couldn't be a subframework.
11585ca04bd4SDouglas Gregor   const unsigned DotFrameworkLen = 10;
1159004b9c7aSMehdi Amini   auto FrameworkPos = ContextName.find(".framework");
1160004b9c7aSMehdi Amini   if (FrameworkPos == StringRef::npos ||
1161004b9c7aSMehdi Amini       (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&
1162004b9c7aSMehdi Amini        ContextName[FrameworkPos + DotFrameworkLen] != '\\'))
11634dc5573aSAlex Lorenz     return None;
11647a51313dSChris Lattner 
1165004b9c7aSMehdi Amini   SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +
1166004b9c7aSMehdi Amini                                                           FrameworkPos +
1167004b9c7aSMehdi Amini                                                           DotFrameworkLen + 1);
11687a51313dSChris Lattner 
11697a51313dSChris Lattner   // Append Frameworks/HIToolbox.framework/
11707a51313dSChris Lattner   FrameworkName += "Frameworks/";
1171d081f8c8SChris Lattner   FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
11727a51313dSChris Lattner   FrameworkName += ".framework/";
11737a51313dSChris Lattner 
117413156b68SDavid Blaikie   auto &CacheLookup =
117513156b68SDavid Blaikie       *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
117613156b68SDavid Blaikie                                           FrameworkCacheEntry())).first;
11777a51313dSChris Lattner 
11787a51313dSChris Lattner   // Some other location?
117913156b68SDavid Blaikie   if (CacheLookup.second.Directory &&
118013156b68SDavid Blaikie       CacheLookup.first().size() == FrameworkName.size() &&
118113156b68SDavid Blaikie       memcmp(CacheLookup.first().data(), &FrameworkName[0],
118213156b68SDavid Blaikie              CacheLookup.first().size()) != 0)
11834dc5573aSAlex Lorenz     return None;
11847a51313dSChris Lattner 
11857a51313dSChris Lattner   // Cache subframework.
118613156b68SDavid Blaikie   if (!CacheLookup.second.Directory) {
11877a51313dSChris Lattner     ++NumSubFrameworkLookups;
11887a51313dSChris Lattner 
11897a51313dSChris Lattner     // If the framework dir doesn't exist, we fail.
1190f43ce519SJan Svoboda     auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
11914dc5573aSAlex Lorenz     if (!Dir)
11924dc5573aSAlex Lorenz       return None;
11937a51313dSChris Lattner 
11947a51313dSChris Lattner     // Otherwise, if it does, remember that this is the right direntry for this
11957a51313dSChris Lattner     // framework.
1196f43ce519SJan Svoboda     CacheLookup.second.Directory = Dir;
11977a51313dSChris Lattner   }
11987a51313dSChris Lattner 
11997a51313dSChris Lattner 
1200d2d442caSCraig Topper   if (RelativePath) {
12010c69fd27SManuel Klimek     RelativePath->clear();
12020c69fd27SManuel Klimek     RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
12030c69fd27SManuel Klimek   }
12040c69fd27SManuel Klimek 
12057a51313dSChris Lattner   // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
12062c1dd271SDylan Noblesmith   SmallString<1024> HeadersFilename(FrameworkName);
12077a51313dSChris Lattner   HeadersFilename += "Headers/";
1208d2d442caSCraig Topper   if (SearchPath) {
12090c69fd27SManuel Klimek     SearchPath->clear();
12100c69fd27SManuel Klimek     // Without trailing '/'.
12110c69fd27SManuel Klimek     SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
12120c69fd27SManuel Klimek   }
12130c69fd27SManuel Klimek 
1214d081f8c8SChris Lattner   HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
12159ef6c49bSDuncan P. N. Exon Smith   auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);
12164dc5573aSAlex Lorenz   if (!File) {
12177a51313dSChris Lattner     // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
12187a51313dSChris Lattner     HeadersFilename = FrameworkName;
12197a51313dSChris Lattner     HeadersFilename += "PrivateHeaders/";
1220d2d442caSCraig Topper     if (SearchPath) {
12210c69fd27SManuel Klimek       SearchPath->clear();
12220c69fd27SManuel Klimek       // Without trailing '/'.
12230c69fd27SManuel Klimek       SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
12240c69fd27SManuel Klimek     }
12250c69fd27SManuel Klimek 
1226d081f8c8SChris Lattner     HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
12279ef6c49bSDuncan P. N. Exon Smith     File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);
12288d323d15SHarlan Haskins 
12294dc5573aSAlex Lorenz     if (!File)
12304dc5573aSAlex Lorenz       return None;
12317a51313dSChris Lattner   }
12327a51313dSChris Lattner 
12337a51313dSChris Lattner   // This file is a system header or C++ unfriendly if the old file is.
12347a51313dSChris Lattner   //
12357a51313dSChris Lattner   // Note that the temporary 'DirInfo' is required here, as either call to
12367a51313dSChris Lattner   // getFileInfo could resize the vector and we don't want to rely on order
12377a51313dSChris Lattner   // of evaluation.
12387a51313dSChris Lattner   unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo;
12394dc5573aSAlex Lorenz   getFileInfo(&File->getFileEntry()).DirInfo = DirInfo;
1240f5f94528SDouglas Gregor 
1241f5f94528SDouglas Gregor   FrameworkName.pop_back(); // remove the trailing '/'
12424dc5573aSAlex Lorenz   if (!findUsableModuleForFrameworkHeader(&File->getFileEntry(), FrameworkName,
12434dc5573aSAlex Lorenz                                           RequestingModule, SuggestedModule,
12444dc5573aSAlex Lorenz                                           /*IsSystem*/ false))
12454dc5573aSAlex Lorenz     return None;
1246f5f94528SDouglas Gregor 
12474dc5573aSAlex Lorenz   return *File;
12487a51313dSChris Lattner }
12497a51313dSChris Lattner 
12507a51313dSChris Lattner //===----------------------------------------------------------------------===//
12517a51313dSChris Lattner // File Info Management.
12527a51313dSChris Lattner //===----------------------------------------------------------------------===//
12537a51313dSChris Lattner 
12549fc8faf9SAdrian Prantl /// Merge the header file info provided by \p OtherHFI into the current
12555d1bee25SDouglas Gregor /// header file info (\p HFI)
mergeHeaderFileInfo(HeaderFileInfo & HFI,const HeaderFileInfo & OtherHFI)12565d1bee25SDouglas Gregor static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
12575d1bee25SDouglas Gregor                                 const HeaderFileInfo &OtherHFI) {
1258d8879c85SRichard Smith   assert(OtherHFI.External && "expected to merge external HFI");
1259d8879c85SRichard Smith 
12605d1bee25SDouglas Gregor   HFI.isImport |= OtherHFI.isImport;
12615d1bee25SDouglas Gregor   HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
1262b146baabSArgyrios Kyrtzidis   HFI.isModuleHeader |= OtherHFI.isModuleHeader;
12635d1bee25SDouglas Gregor 
12645d1bee25SDouglas Gregor   if (!HFI.ControllingMacro && !HFI.ControllingMacroID) {
12655d1bee25SDouglas Gregor     HFI.ControllingMacro = OtherHFI.ControllingMacro;
12665d1bee25SDouglas Gregor     HFI.ControllingMacroID = OtherHFI.ControllingMacroID;
12675d1bee25SDouglas Gregor   }
12685d1bee25SDouglas Gregor 
12695d1bee25SDouglas Gregor   HFI.DirInfo = OtherHFI.DirInfo;
1270d8879c85SRichard Smith   HFI.External = (!HFI.IsValid || HFI.External);
1271d8879c85SRichard Smith   HFI.IsValid = true;
12725d1bee25SDouglas Gregor   HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader;
12735d1bee25SDouglas Gregor 
12745d1bee25SDouglas Gregor   if (HFI.Framework.empty())
12755d1bee25SDouglas Gregor     HFI.Framework = OtherHFI.Framework;
12765d1bee25SDouglas Gregor }
12777a51313dSChris Lattner 
12783fa455a1SSteve Naroff /// getFileInfo - Return the HeaderFileInfo structure for the specified
12797a51313dSChris Lattner /// FileEntry.
getFileInfo(const FileEntry * FE)12803fa455a1SSteve Naroff HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
12817a51313dSChris Lattner   if (FE->getUID() >= FileInfo.size())
12827a51313dSChris Lattner     FileInfo.resize(FE->getUID() + 1);
128309b6989eSDouglas Gregor 
1284d8879c85SRichard Smith   HeaderFileInfo *HFI = &FileInfo[FE->getUID()];
1285386bb073SRichard Smith   // FIXME: Use a generation count to check whether this is really up to date.
1286d8879c85SRichard Smith   if (ExternalSource && !HFI->Resolved) {
1287d8879c85SRichard Smith     auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
12887ac737e5SVolodymyr Sapsai     if (ExternalHFI.IsValid) {
12897ac737e5SVolodymyr Sapsai       HFI->Resolved = true;
1290d8879c85SRichard Smith       if (ExternalHFI.External)
1291d8879c85SRichard Smith         mergeHeaderFileInfo(*HFI, ExternalHFI);
1292386bb073SRichard Smith     }
12937ac737e5SVolodymyr Sapsai   }
1294386bb073SRichard Smith 
1295d8879c85SRichard Smith   HFI->IsValid = true;
1296386bb073SRichard Smith   // We have local information about this header file, so it's no longer
1297386bb073SRichard Smith   // strictly external.
1298d8879c85SRichard Smith   HFI->External = false;
1299d8879c85SRichard Smith   return *HFI;
13007a51313dSChris Lattner }
13017a51313dSChris Lattner 
1302386bb073SRichard Smith const HeaderFileInfo *
getExistingFileInfo(const FileEntry * FE,bool WantExternal) const1303d8879c85SRichard Smith HeaderSearch::getExistingFileInfo(const FileEntry *FE,
1304d8879c85SRichard Smith                                   bool WantExternal) const {
1305386bb073SRichard Smith   // If we have an external source, ensure we have the latest information.
1306386bb073SRichard Smith   // FIXME: Use a generation count to check whether this is really up to date.
1307d8879c85SRichard Smith   HeaderFileInfo *HFI;
1308d8879c85SRichard Smith   if (ExternalSource) {
1309d8879c85SRichard Smith     if (FE->getUID() >= FileInfo.size()) {
1310d8879c85SRichard Smith       if (!WantExternal)
1311d8879c85SRichard Smith         return nullptr;
1312386bb073SRichard Smith       FileInfo.resize(FE->getUID() + 1);
1313386bb073SRichard Smith     }
1314386bb073SRichard Smith 
1315d8879c85SRichard Smith     HFI = &FileInfo[FE->getUID()];
1316d8879c85SRichard Smith     if (!WantExternal && (!HFI->IsValid || HFI->External))
1317d8879c85SRichard Smith       return nullptr;
1318d8879c85SRichard Smith     if (!HFI->Resolved) {
1319d8879c85SRichard Smith       auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
13207ac737e5SVolodymyr Sapsai       if (ExternalHFI.IsValid) {
13217ac737e5SVolodymyr Sapsai         HFI->Resolved = true;
1322d8879c85SRichard Smith         if (ExternalHFI.External)
1323d8879c85SRichard Smith           mergeHeaderFileInfo(*HFI, ExternalHFI);
1324d8879c85SRichard Smith       }
13257ac737e5SVolodymyr Sapsai     }
1326d8879c85SRichard Smith   } else if (FE->getUID() >= FileInfo.size()) {
1327d8879c85SRichard Smith     return nullptr;
1328d8879c85SRichard Smith   } else {
1329d8879c85SRichard Smith     HFI = &FileInfo[FE->getUID()];
1330d8879c85SRichard Smith   }
1331d8879c85SRichard Smith 
1332d8879c85SRichard Smith   if (!HFI->IsValid || (HFI->External && !WantExternal))
1333386bb073SRichard Smith     return nullptr;
1334386bb073SRichard Smith 
1335d8879c85SRichard Smith   return HFI;
1336d285c503SBen Langmuir }
1337d285c503SBen Langmuir 
isFileMultipleIncludeGuarded(const FileEntry * File)133837aa4938SDouglas Gregor bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
13390a088eadSRichard Smith   // Check if we've entered this file and found an include guard or #pragma
13400a088eadSRichard Smith   // once. Note that we dor't check for #import, because that's not a property
13410a088eadSRichard Smith   // of the file itself.
1342386bb073SRichard Smith   if (auto *HFI = getExistingFileInfo(File))
13430a088eadSRichard Smith     return HFI->isPragmaOnce || HFI->ControllingMacro ||
1344386bb073SRichard Smith            HFI->ControllingMacroID;
134537aa4938SDouglas Gregor   return false;
134637aa4938SDouglas Gregor }
134737aa4938SDouglas Gregor 
MarkFileModuleHeader(const FileEntry * FE,ModuleMap::ModuleHeaderRole Role,bool isCompilingModuleHeader)13486f722b4eSArgyrios Kyrtzidis void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
1349b53e5483SLawrence Crowl                                         ModuleMap::ModuleHeaderRole Role,
13506f722b4eSArgyrios Kyrtzidis                                         bool isCompilingModuleHeader) {
1351d8879c85SRichard Smith   bool isModularHeader = !(Role & ModuleMap::TextualHeader);
1352d8879c85SRichard Smith 
1353d8879c85SRichard Smith   // Don't mark the file info as non-external if there's nothing to change.
1354d8879c85SRichard Smith   if (!isCompilingModuleHeader) {
1355d8879c85SRichard Smith     if (!isModularHeader)
1356d8879c85SRichard Smith       return;
1357d8879c85SRichard Smith     auto *HFI = getExistingFileInfo(FE);
1358d8879c85SRichard Smith     if (HFI && HFI->isModuleHeader)
1359d8879c85SRichard Smith       return;
1360d8879c85SRichard Smith   }
1361d8879c85SRichard Smith 
1362386bb073SRichard Smith   auto &HFI = getFileInfo(FE);
1363d8879c85SRichard Smith   HFI.isModuleHeader |= isModularHeader;
1364e70dadd6SRichard Smith   HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1365b146baabSArgyrios Kyrtzidis }
1366b146baabSArgyrios Kyrtzidis 
ShouldEnterIncludeFile(Preprocessor & PP,const FileEntry * File,bool isImport,bool ModulesEnabled,Module * M,bool & IsFirstIncludeOfFile)136720e883e5SRichard Smith bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
1368ba1b5c98SBruno Cardoso Lopes                                           const FileEntry *File, bool isImport,
1369197576c4SJan Svoboda                                           bool ModulesEnabled, Module *M,
1370197576c4SJan Svoboda                                           bool &IsFirstIncludeOfFile) {
13717a51313dSChris Lattner   ++NumIncluded; // Count # of attempted #includes.
13727a51313dSChris Lattner 
1373197576c4SJan Svoboda   IsFirstIncludeOfFile = false;
1374197576c4SJan Svoboda 
13757a51313dSChris Lattner   // Get information about this file.
13763fa455a1SSteve Naroff   HeaderFileInfo &FileInfo = getFileInfo(File);
13777a51313dSChris Lattner 
1378ba1b5c98SBruno Cardoso Lopes   // FIXME: this is a workaround for the lack of proper modules-aware support
1379ba1b5c98SBruno Cardoso Lopes   // for #import / #pragma once
1380afd1b1c9SEugene Zelenko   auto TryEnterImported = [&]() -> bool {
1381ba1b5c98SBruno Cardoso Lopes     if (!ModulesEnabled)
1382ba1b5c98SBruno Cardoso Lopes       return false;
1383040e1266SRichard Smith     // Ensure FileInfo bits are up to date.
1384040e1266SRichard Smith     ModMap.resolveHeaderDirectives(File);
1385ba1b5c98SBruno Cardoso Lopes     // Modules with builtins are special; multiple modules use builtins as
1386ba1b5c98SBruno Cardoso Lopes     // modular headers, example:
1387ba1b5c98SBruno Cardoso Lopes     //
1388ba1b5c98SBruno Cardoso Lopes     //    module stddef { header "stddef.h" export * }
1389ba1b5c98SBruno Cardoso Lopes     //
1390ba1b5c98SBruno Cardoso Lopes     // After module map parsing, this expands to:
1391ba1b5c98SBruno Cardoso Lopes     //
1392ba1b5c98SBruno Cardoso Lopes     //    module stddef {
1393ba1b5c98SBruno Cardoso Lopes     //      header "/path_to_builtin_dirs/stddef.h"
1394ba1b5c98SBruno Cardoso Lopes     //      textual "stddef.h"
1395ba1b5c98SBruno Cardoso Lopes     //    }
1396ba1b5c98SBruno Cardoso Lopes     //
1397ba1b5c98SBruno Cardoso Lopes     // It's common that libc++ and system modules will both define such
1398ba1b5c98SBruno Cardoso Lopes     // submodules. Make sure cached results for a builtin header won't
13998d74de9dSMartin Boehme     // prevent other builtin modules from potentially entering the builtin
14008d74de9dSMartin Boehme     // header. Note that builtins are header guarded and the decision to
14018d74de9dSMartin Boehme     // actually enter them is postponed to the controlling macros logic below.
1402ba1b5c98SBruno Cardoso Lopes     bool TryEnterHdr = false;
1403ba1b5c98SBruno Cardoso Lopes     if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader)
14048d74de9dSMartin Boehme       TryEnterHdr = ModMap.isBuiltinHeader(File);
1405ba1b5c98SBruno Cardoso Lopes 
1406ba1b5c98SBruno Cardoso Lopes     // Textual headers can be #imported from different modules. Since ObjC
1407ba1b5c98SBruno Cardoso Lopes     // headers find in the wild might rely only on #import and do not contain
1408ba1b5c98SBruno Cardoso Lopes     // controlling macros, be conservative and only try to enter textual headers
1409ba1b5c98SBruno Cardoso Lopes     // if such macro is present.
14104164dd91SBruno Cardoso Lopes     if (!FileInfo.isModuleHeader &&
1411ba1b5c98SBruno Cardoso Lopes         FileInfo.getControllingMacro(ExternalLookup))
1412ba1b5c98SBruno Cardoso Lopes       TryEnterHdr = true;
1413ba1b5c98SBruno Cardoso Lopes     return TryEnterHdr;
1414ba1b5c98SBruno Cardoso Lopes   };
1415ba1b5c98SBruno Cardoso Lopes 
14167a51313dSChris Lattner   // If this is a #import directive, check that we have not already imported
14177a51313dSChris Lattner   // this header.
14187a51313dSChris Lattner   if (isImport) {
14197a51313dSChris Lattner     // If this has already been imported, don't import it again.
14207a51313dSChris Lattner     FileInfo.isImport = true;
14217a51313dSChris Lattner 
14227a51313dSChris Lattner     // Has this already been #import'ed or #include'd?
1423f7202723SJan Svoboda     if (PP.alreadyIncluded(File) && !TryEnterImported())
1424ba1b5c98SBruno Cardoso Lopes       return false;
14257a51313dSChris Lattner   } else {
14267a51313dSChris Lattner     // Otherwise, if this is a #include of a file that was previously #import'd
14277a51313dSChris Lattner     // or if this is the second #include of a #pragma once file, ignore it.
142864ebf313SVolodymyr Sapsai     if ((FileInfo.isPragmaOnce || FileInfo.isImport) && !TryEnterImported())
14297a51313dSChris Lattner       return false;
14307a51313dSChris Lattner   }
14317a51313dSChris Lattner 
14327a51313dSChris Lattner   // Next, check to see if the file is wrapped with #ifndef guards.  If so, and
14337a51313dSChris Lattner   // if the macro that guards it is defined, we know the #include has no effect.
143499734e76SDouglas Gregor   if (const IdentifierInfo *ControllingMacro
1435e70dadd6SRichard Smith       = FileInfo.getControllingMacro(ExternalLookup)) {
1436e70dadd6SRichard Smith     // If the header corresponds to a module, check whether the macro is already
1437e70dadd6SRichard Smith     // defined in that module rather than checking in the current set of visible
1438e70dadd6SRichard Smith     // modules.
1439e70dadd6SRichard Smith     if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)
1440e70dadd6SRichard Smith           : PP.isMacroDefined(ControllingMacro)) {
14417a51313dSChris Lattner       ++NumMultiIncludeFileOptzn;
14427a51313dSChris Lattner       return false;
14437a51313dSChris Lattner     }
1444e70dadd6SRichard Smith   }
14457a51313dSChris Lattner 
1446f7202723SJan Svoboda   IsFirstIncludeOfFile = PP.markIncluded(File);
1447197576c4SJan Svoboda 
14487a51313dSChris Lattner   return true;
14497a51313dSChris Lattner }
14507a51313dSChris Lattner 
getTotalMemory() const1451fbcce6fbSTed Kremenek size_t HeaderSearch::getTotalMemory() const {
1452fbcce6fbSTed Kremenek   return SearchDirs.capacity()
1453ae63d101STed Kremenek     + llvm::capacity_in_bytes(FileInfo)
1454ae63d101STed Kremenek     + llvm::capacity_in_bytes(HeaderMaps)
1455fbcce6fbSTed Kremenek     + LookupFileCache.getAllocator().getTotalMemory()
1456fbcce6fbSTed Kremenek     + FrameworkMap.getAllocator().getTotalMemory();
1457fbcce6fbSTed Kremenek }
14589f93e38aSDouglas Gregor 
searchDirIdx(const DirectoryLookup & DL) const1459e7dcf09fSJan Svoboda unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
1460e7dcf09fSJan Svoboda   return &DL - &*SearchDirs.begin();
1461ccd7e783SJan Svoboda }
1462ccd7e783SJan Svoboda 
getUniqueFrameworkName(StringRef Framework)14639f93e38aSDouglas Gregor StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
146413156b68SDavid Blaikie   return FrameworkNames.insert(Framework).first->first();
14659f93e38aSDouglas Gregor }
1466718292f2SDouglas Gregor 
getIncludeNameForHeader(const FileEntry * File) const1467b6c67c3cSCyndy Ishida StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const {
1468b6c67c3cSCyndy Ishida   auto It = IncludeNames.find(File);
1469b6c67c3cSCyndy Ishida   if (It == IncludeNames.end())
1470b6c67c3cSCyndy Ishida     return {};
1471b6c67c3cSCyndy Ishida   return It->second;
1472b6c67c3cSCyndy Ishida }
1473b6c67c3cSCyndy Ishida 
hasModuleMap(StringRef FileName,const DirectoryEntry * Root,bool IsSystem)1474718292f2SDouglas Gregor bool HeaderSearch::hasModuleMap(StringRef FileName,
1475963c5535SDouglas Gregor                                 const DirectoryEntry *Root,
1476963c5535SDouglas Gregor                                 bool IsSystem) {
147747972afdSRichard Smith   if (!HSOpts->ImplicitModuleMaps)
14789955dbcaSArgyrios Kyrtzidis     return false;
14799955dbcaSArgyrios Kyrtzidis 
1480f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> FixUpDirectories;
1481718292f2SDouglas Gregor 
1482718292f2SDouglas Gregor   StringRef DirName = FileName;
1483718292f2SDouglas Gregor   do {
1484718292f2SDouglas Gregor     // Get the parent directory name.
1485718292f2SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
1486718292f2SDouglas Gregor     if (DirName.empty())
1487718292f2SDouglas Gregor       return false;
1488718292f2SDouglas Gregor 
1489718292f2SDouglas Gregor     // Determine whether this directory exists.
1490d9390b6aSJan Svoboda     auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1491718292f2SDouglas Gregor     if (!Dir)
1492718292f2SDouglas Gregor       return false;
1493718292f2SDouglas Gregor 
1494984e1df7SBen Langmuir     // Try to load the module map file in this directory.
14958d323d15SHarlan Haskins     switch (loadModuleMapFile(*Dir, IsSystem,
1496d9390b6aSJan Svoboda                               llvm::sys::path::extension(Dir->getName()) ==
14973c1a41adSRichard Smith                                   ".framework")) {
149880b6904bSDouglas Gregor     case LMM_NewlyLoaded:
149980b6904bSDouglas Gregor     case LMM_AlreadyLoaded:
1500ca9f7381SDaniel Jasper       // Success. All of the directories we stepped through inherit this module
1501ca9f7381SDaniel Jasper       // map file.
1502ca9f7381SDaniel Jasper       for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1503ca9f7381SDaniel Jasper         DirectoryHasModuleMap[FixUpDirectories[I]] = true;
1504ca9f7381SDaniel Jasper       return true;
150597da9178SDaniel Jasper 
150697da9178SDaniel Jasper     case LMM_NoDirectory:
150797da9178SDaniel Jasper     case LMM_InvalidModuleMap:
150897da9178SDaniel Jasper       break;
1509ca9f7381SDaniel Jasper     }
1510ca9f7381SDaniel Jasper 
1511af28ec80SDouglas Gregor     // If we hit the top of our search, we're done.
15128d323d15SHarlan Haskins     if (*Dir == Root)
1513718292f2SDouglas Gregor       return false;
1514718292f2SDouglas Gregor 
1515718292f2SDouglas Gregor     // Keep track of all of the directories we checked, so we can mark them as
1516718292f2SDouglas Gregor     // having module maps if we eventually do find a module map.
15178d323d15SHarlan Haskins     FixUpDirectories.push_back(*Dir);
1518718292f2SDouglas Gregor   } while (true);
1519718292f2SDouglas Gregor }
1520718292f2SDouglas Gregor 
1521b53e5483SLawrence Crowl ModuleMap::KnownHeader
findModuleForHeader(const FileEntry * File,bool AllowTextual) const1522ed84df00SBruno Cardoso Lopes HeaderSearch::findModuleForHeader(const FileEntry *File,
1523ed84df00SBruno Cardoso Lopes                                   bool AllowTextual) const {
1524b146baabSArgyrios Kyrtzidis   if (ExternalSource) {
1525b146baabSArgyrios Kyrtzidis     // Make sure the external source has handled header info about this file,
1526b146baabSArgyrios Kyrtzidis     // which includes whether the file is part of a module.
1527386bb073SRichard Smith     (void)getExistingFileInfo(File);
1528b146baabSArgyrios Kyrtzidis   }
1529ed84df00SBruno Cardoso Lopes   return ModMap.findModuleForHeader(File, AllowTextual);
1530ed84df00SBruno Cardoso Lopes }
1531ed84df00SBruno Cardoso Lopes 
15320a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File) const15330a088eadSRichard Smith HeaderSearch::findAllModulesForHeader(const FileEntry *File) const {
15340a088eadSRichard Smith   if (ExternalSource) {
15350a088eadSRichard Smith     // Make sure the external source has handled header info about this file,
15360a088eadSRichard Smith     // which includes whether the file is part of a module.
15370a088eadSRichard Smith     (void)getExistingFileInfo(File);
15380a088eadSRichard Smith   }
15390a088eadSRichard Smith   return ModMap.findAllModulesForHeader(File);
15400a088eadSRichard Smith }
15410a088eadSRichard Smith 
suggestModule(HeaderSearch & HS,const FileEntry * File,Module * RequestingModule,ModuleMap::KnownHeader * SuggestedModule)1542ed84df00SBruno Cardoso Lopes static bool suggestModule(HeaderSearch &HS, const FileEntry *File,
1543ed84df00SBruno Cardoso Lopes                           Module *RequestingModule,
1544ed84df00SBruno Cardoso Lopes                           ModuleMap::KnownHeader *SuggestedModule) {
1545ed84df00SBruno Cardoso Lopes   ModuleMap::KnownHeader Module =
1546ed84df00SBruno Cardoso Lopes       HS.findModuleForHeader(File, /*AllowTextual*/true);
1547ed84df00SBruno Cardoso Lopes 
1548ed84df00SBruno Cardoso Lopes   // If this module specifies [no_undeclared_includes], we cannot find any
1549ed84df00SBruno Cardoso Lopes   // file that's in a non-dependency module.
1550ed84df00SBruno Cardoso Lopes   if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {
1551ed84df00SBruno Cardoso Lopes     HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/ false);
1552ed84df00SBruno Cardoso Lopes     if (!RequestingModule->directlyUses(Module.getModule())) {
15538d74de9dSMartin Boehme       // Builtin headers are a special case. Multiple modules can use the same
15548d74de9dSMartin Boehme       // builtin as a modular header (see also comment in
15558d74de9dSMartin Boehme       // ShouldEnterIncludeFile()), so the builtin header may have been
15568d74de9dSMartin Boehme       // "claimed" by an unrelated module. This shouldn't prevent us from
15578d74de9dSMartin Boehme       // including the builtin header textually in this module.
15588d74de9dSMartin Boehme       if (HS.getModuleMap().isBuiltinHeader(File)) {
15598d74de9dSMartin Boehme         if (SuggestedModule)
15608d74de9dSMartin Boehme           *SuggestedModule = ModuleMap::KnownHeader();
15618d74de9dSMartin Boehme         return true;
15628d74de9dSMartin Boehme       }
1563ed84df00SBruno Cardoso Lopes       return false;
1564ed84df00SBruno Cardoso Lopes     }
1565ed84df00SBruno Cardoso Lopes   }
1566ed84df00SBruno Cardoso Lopes 
15678d74de9dSMartin Boehme   if (SuggestedModule)
15688d74de9dSMartin Boehme     *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)
15698d74de9dSMartin Boehme                            ? ModuleMap::KnownHeader()
15708d74de9dSMartin Boehme                            : Module;
15718d74de9dSMartin Boehme 
1572ed84df00SBruno Cardoso Lopes   return true;
1573718292f2SDouglas Gregor }
1574718292f2SDouglas Gregor 
findUsableModuleForHeader(const FileEntry * File,const DirectoryEntry * Root,Module * RequestingModule,ModuleMap::KnownHeader * SuggestedModule,bool IsSystemHeaderDir)15753d5b48c4SRichard Smith bool HeaderSearch::findUsableModuleForHeader(
15763d5b48c4SRichard Smith     const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule,
15773d5b48c4SRichard Smith     ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
1578ed84df00SBruno Cardoso Lopes   if (File && needModuleLookup(RequestingModule, SuggestedModule)) {
15793d5b48c4SRichard Smith     // If there is a module that corresponds to this header, suggest it.
15803d5b48c4SRichard Smith     hasModuleMap(File->getName(), Root, IsSystemHeaderDir);
1581ed84df00SBruno Cardoso Lopes     return suggestModule(*this, File, RequestingModule, SuggestedModule);
15823d5b48c4SRichard Smith   }
15833d5b48c4SRichard Smith   return true;
15843d5b48c4SRichard Smith }
15853d5b48c4SRichard Smith 
findUsableModuleForFrameworkHeader(const FileEntry * File,StringRef FrameworkName,Module * RequestingModule,ModuleMap::KnownHeader * SuggestedModule,bool IsSystemFramework)15863d5b48c4SRichard Smith bool HeaderSearch::findUsableModuleForFrameworkHeader(
15873d5b48c4SRichard Smith     const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
15883d5b48c4SRichard Smith     ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
15893d5b48c4SRichard Smith   // If we're supposed to suggest a module, look for one now.
1590ed84df00SBruno Cardoso Lopes   if (needModuleLookup(RequestingModule, SuggestedModule)) {
15913d5b48c4SRichard Smith     // Find the top-level framework based on this framework.
15923d5b48c4SRichard Smith     SmallVector<std::string, 4> SubmodulePath;
1593d9390b6aSJan Svoboda     Optional<DirectoryEntryRef> TopFrameworkDir =
1594d9390b6aSJan Svoboda         ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
1595d9390b6aSJan Svoboda     assert(TopFrameworkDir && "Could not find the top-most framework dir");
15963d5b48c4SRichard Smith 
15973d5b48c4SRichard Smith     // Determine the name of the top-level framework.
15983d5b48c4SRichard Smith     StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
15993d5b48c4SRichard Smith 
16003d5b48c4SRichard Smith     // Load this framework module. If that succeeds, find the suggested module
16013d5b48c4SRichard Smith     // for this header, if any.
1602d9390b6aSJan Svoboda     loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
16033d5b48c4SRichard Smith 
16043d5b48c4SRichard Smith     // FIXME: This can find a module not part of ModuleName, which is
16053d5b48c4SRichard Smith     // important so that we're consistent about whether this header
16063d5b48c4SRichard Smith     // corresponds to a module. Possibly we should lock down framework modules
16073d5b48c4SRichard Smith     // so that this is not possible.
1608ed84df00SBruno Cardoso Lopes     return suggestModule(*this, File, RequestingModule, SuggestedModule);
16093d5b48c4SRichard Smith   }
16103d5b48c4SRichard Smith   return true;
16113d5b48c4SRichard Smith }
16123d5b48c4SRichard Smith 
getPrivateModuleMap(const FileEntry * File,FileManager & FileMgr)16137799ef71SNico Weber static const FileEntry *getPrivateModuleMap(const FileEntry *File,
1614984e1df7SBen Langmuir                                             FileManager &FileMgr) {
16157799ef71SNico Weber   StringRef Filename = llvm::sys::path::filename(File->getName());
16167799ef71SNico Weber   SmallString<128>  PrivateFilename(File->getDir()->getName());
1617984e1df7SBen Langmuir   if (Filename == "module.map")
16188030677bSDouglas Gregor     llvm::sys::path::append(PrivateFilename, "module_private.map");
1619984e1df7SBen Langmuir   else if (Filename == "module.modulemap")
1620984e1df7SBen Langmuir     llvm::sys::path::append(PrivateFilename, "module.private.modulemap");
1621984e1df7SBen Langmuir   else
16227799ef71SNico Weber     return nullptr;
16237799ef71SNico Weber   if (auto File = FileMgr.getFile(PrivateFilename))
16247799ef71SNico Weber     return *File;
16257799ef71SNico Weber   return nullptr;
16268030677bSDouglas Gregor }
16278030677bSDouglas Gregor 
loadModuleMapFile(const FileEntry * File,bool IsSystem,FileID ID,unsigned * Offset,StringRef OriginalModuleMapFile)16287799ef71SNico Weber bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem,
16298b706104SRichard Smith                                      FileID ID, unsigned *Offset,
16308b706104SRichard Smith                                      StringRef OriginalModuleMapFile) {
16319acb99e3SRichard Smith   // Find the directory for the module. For frameworks, that may require going
16329acb99e3SRichard Smith   // up from the 'Modules' directory.
1633d9390b6aSJan Svoboda   Optional<DirectoryEntryRef> Dir;
16348d323d15SHarlan Haskins   if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) {
1635d9390b6aSJan Svoboda     Dir = FileMgr.getOptionalDirectoryRef(".");
16368d323d15SHarlan Haskins   } else {
16378b706104SRichard Smith     if (!OriginalModuleMapFile.empty()) {
16388b706104SRichard Smith       // We're building a preprocessed module map. Find or invent the directory
16398b706104SRichard Smith       // that it originally occupied.
1640d9390b6aSJan Svoboda       Dir = FileMgr.getOptionalDirectoryRef(
16418b706104SRichard Smith           llvm::sys::path::parent_path(OriginalModuleMapFile));
1642d9390b6aSJan Svoboda       if (!Dir) {
1643d9390b6aSJan Svoboda         auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
1644d9390b6aSJan Svoboda         Dir = FakeFile.getDir();
16458b706104SRichard Smith       }
16468b706104SRichard Smith     } else {
1647d9390b6aSJan Svoboda       // TODO: Replace with `Dir = File.getDir()` when `File` is switched to
1648d9390b6aSJan Svoboda       // `FileEntryRef`.
1649d9390b6aSJan Svoboda       Dir = FileMgr.getOptionalDirectoryRef(File->getDir()->getName());
16508b706104SRichard Smith     }
16518b706104SRichard Smith 
1652d9390b6aSJan Svoboda     assert(Dir && "parent must exist");
16539acb99e3SRichard Smith     StringRef DirName(Dir->getName());
16549acb99e3SRichard Smith     if (llvm::sys::path::filename(DirName) == "Modules") {
16559acb99e3SRichard Smith       DirName = llvm::sys::path::parent_path(DirName);
16569acb99e3SRichard Smith       if (DirName.endswith(".framework"))
1657d9390b6aSJan Svoboda         if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
1658d9390b6aSJan Svoboda           Dir = *MaybeDir;
16599acb99e3SRichard Smith       // FIXME: This assert can fail if there's a race between the above check
16609acb99e3SRichard Smith       // and the removal of the directory.
16619acb99e3SRichard Smith       assert(Dir && "parent must exist");
16629acb99e3SRichard Smith     }
16639acb99e3SRichard Smith   }
16649acb99e3SRichard Smith 
1665d9390b6aSJan Svoboda   assert(Dir && "module map home directory must exist");
1666d9390b6aSJan Svoboda   switch (loadModuleMapFileImpl(File, IsSystem, *Dir, ID, Offset)) {
1667984e1df7SBen Langmuir   case LMM_AlreadyLoaded:
1668984e1df7SBen Langmuir   case LMM_NewlyLoaded:
1669984e1df7SBen Langmuir     return false;
1670984e1df7SBen Langmuir   case LMM_NoDirectory:
1671984e1df7SBen Langmuir   case LMM_InvalidModuleMap:
1672984e1df7SBen Langmuir     return true;
1673984e1df7SBen Langmuir   }
1674d8de5b68SAaron Ballman   llvm_unreachable("Unknown load module map result");
1675984e1df7SBen Langmuir }
1676984e1df7SBen Langmuir 
1677c192d194SBruno Cardoso Lopes HeaderSearch::LoadModuleMapResult
loadModuleMapFileImpl(const FileEntry * File,bool IsSystem,DirectoryEntryRef Dir,FileID ID,unsigned * Offset)16787799ef71SNico Weber HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem,
1679d9390b6aSJan Svoboda                                     DirectoryEntryRef Dir, FileID ID,
1680c192d194SBruno Cardoso Lopes                                     unsigned *Offset) {
16817799ef71SNico Weber   assert(File && "expected FileEntry");
16827799ef71SNico Weber 
16839887d79aSRichard Smith   // Check whether we've already loaded this module map, and mark it as being
16849887d79aSRichard Smith   // loaded in case we recursively try to load it from itself.
16859887d79aSRichard Smith   auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));
16869887d79aSRichard Smith   if (!AddResult.second)
16879887d79aSRichard Smith     return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1688984e1df7SBen Langmuir 
1689c192d194SBruno Cardoso Lopes   if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) {
16909887d79aSRichard Smith     LoadedModuleMaps[File] = false;
1691984e1df7SBen Langmuir     return LMM_InvalidModuleMap;
1692984e1df7SBen Langmuir   }
1693984e1df7SBen Langmuir 
1694984e1df7SBen Langmuir   // Try to load a corresponding private module map.
16957799ef71SNico Weber   if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) {
16967799ef71SNico Weber     if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) {
16979887d79aSRichard Smith       LoadedModuleMaps[File] = false;
1698984e1df7SBen Langmuir       return LMM_InvalidModuleMap;
1699984e1df7SBen Langmuir     }
1700984e1df7SBen Langmuir   }
1701984e1df7SBen Langmuir 
1702984e1df7SBen Langmuir   // This directory has a module map.
1703984e1df7SBen Langmuir   return LMM_NewlyLoaded;
1704984e1df7SBen Langmuir }
1705984e1df7SBen Langmuir 
17067799ef71SNico Weber const FileEntry *
lookupModuleMapFile(const DirectoryEntry * Dir,bool IsFramework)1707984e1df7SBen Langmuir HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) {
170847972afdSRichard Smith   if (!HSOpts->ImplicitModuleMaps)
17097799ef71SNico Weber     return nullptr;
1710984e1df7SBen Langmuir   // For frameworks, the preferred spelling is Modules/module.modulemap, but
1711984e1df7SBen Langmuir   // module.map at the framework root is also accepted.
1712984e1df7SBen Langmuir   SmallString<128> ModuleMapFileName(Dir->getName());
1713984e1df7SBen Langmuir   if (IsFramework)
1714984e1df7SBen Langmuir     llvm::sys::path::append(ModuleMapFileName, "Modules");
1715984e1df7SBen Langmuir   llvm::sys::path::append(ModuleMapFileName, "module.modulemap");
17167799ef71SNico Weber   if (auto F = FileMgr.getFile(ModuleMapFileName))
17177799ef71SNico Weber     return *F;
1718984e1df7SBen Langmuir 
1719984e1df7SBen Langmuir   // Continue to allow module.map
1720984e1df7SBen Langmuir   ModuleMapFileName = Dir->getName();
1721984e1df7SBen Langmuir   llvm::sys::path::append(ModuleMapFileName, "module.map");
17227799ef71SNico Weber   if (auto F = FileMgr.getFile(ModuleMapFileName))
17237799ef71SNico Weber     return *F;
17244069dd14SVolodymyr Sapsai 
17254069dd14SVolodymyr Sapsai   // For frameworks, allow to have a private module map with a preferred
17264069dd14SVolodymyr Sapsai   // spelling when a public module map is absent.
17274069dd14SVolodymyr Sapsai   if (IsFramework) {
17284069dd14SVolodymyr Sapsai     ModuleMapFileName = Dir->getName();
17294069dd14SVolodymyr Sapsai     llvm::sys::path::append(ModuleMapFileName, "Modules",
17304069dd14SVolodymyr Sapsai                             "module.private.modulemap");
17317799ef71SNico Weber     if (auto F = FileMgr.getFile(ModuleMapFileName))
17327799ef71SNico Weber       return *F;
17334069dd14SVolodymyr Sapsai   }
17347799ef71SNico Weber   return nullptr;
17352b20cb87SDouglas Gregor }
17362b20cb87SDouglas Gregor 
loadFrameworkModule(StringRef Name,DirectoryEntryRef Dir,bool IsSystem)1737d9390b6aSJan Svoboda Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,
1738a686e1b0SDouglas Gregor                                           bool IsSystem) {
1739de3ef502SDouglas Gregor   if (Module *Module = ModMap.findModule(Name))
174056c64013SDouglas Gregor     return Module;
174156c64013SDouglas Gregor 
174256c64013SDouglas Gregor   // Try to load a module map file.
1743984e1df7SBen Langmuir   switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
174456c64013SDouglas Gregor   case LMM_InvalidModuleMap:
1745a525400dSBen Langmuir     // Try to infer a module map from the framework directory.
1746a525400dSBen Langmuir     if (HSOpts->ImplicitModuleMaps)
1747a525400dSBen Langmuir       ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr);
174856c64013SDouglas Gregor     break;
174956c64013SDouglas Gregor 
175056c64013SDouglas Gregor   case LMM_AlreadyLoaded:
175156c64013SDouglas Gregor   case LMM_NoDirectory:
1752d2d442caSCraig Topper     return nullptr;
175356c64013SDouglas Gregor 
175456c64013SDouglas Gregor   case LMM_NewlyLoaded:
1755a525400dSBen Langmuir     break;
175656c64013SDouglas Gregor   }
175756c64013SDouglas Gregor 
1758a525400dSBen Langmuir   return ModMap.findModule(Name);
175956c64013SDouglas Gregor }
176056c64013SDouglas Gregor 
176180b6904bSDouglas Gregor HeaderSearch::LoadModuleMapResult
loadModuleMapFile(StringRef DirName,bool IsSystem,bool IsFramework)1762984e1df7SBen Langmuir HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem,
1763984e1df7SBen Langmuir                                 bool IsFramework) {
1764d9390b6aSJan Svoboda   if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
17658d323d15SHarlan Haskins     return loadModuleMapFile(*Dir, IsSystem, IsFramework);
1766af28ec80SDouglas Gregor 
176780b6904bSDouglas Gregor   return LMM_NoDirectory;
1768af28ec80SDouglas Gregor }
1769af28ec80SDouglas Gregor 
177080b6904bSDouglas Gregor HeaderSearch::LoadModuleMapResult
loadModuleMapFile(DirectoryEntryRef Dir,bool IsSystem,bool IsFramework)1771d9390b6aSJan Svoboda HeaderSearch::loadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
1772984e1df7SBen Langmuir                                 bool IsFramework) {
1773984e1df7SBen Langmuir   auto KnownDir = DirectoryHasModuleMap.find(Dir);
1774af28ec80SDouglas Gregor   if (KnownDir != DirectoryHasModuleMap.end())
177580b6904bSDouglas Gregor     return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1776af28ec80SDouglas Gregor 
17777799ef71SNico Weber   if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) {
1778c192d194SBruno Cardoso Lopes     LoadModuleMapResult Result =
17797799ef71SNico Weber         loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir);
1780984e1df7SBen Langmuir     // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
1781984e1df7SBen Langmuir     // E.g. Foo.framework/Modules/module.modulemap
1782984e1df7SBen Langmuir     //      ^Dir                  ^ModuleMapFile
1783984e1df7SBen Langmuir     if (Result == LMM_NewlyLoaded)
1784af28ec80SDouglas Gregor       DirectoryHasModuleMap[Dir] = true;
17859887d79aSRichard Smith     else if (Result == LMM_InvalidModuleMap)
17869887d79aSRichard Smith       DirectoryHasModuleMap[Dir] = false;
1787984e1df7SBen Langmuir     return Result;
1788af28ec80SDouglas Gregor   }
178980b6904bSDouglas Gregor   return LMM_InvalidModuleMap;
1790af28ec80SDouglas Gregor }
1791718292f2SDouglas Gregor 
collectAllModules(SmallVectorImpl<Module * > & Modules)1792f857950dSDmitri Gribenko void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
179307f4357bSDouglas Gregor   Modules.clear();
179407f4357bSDouglas Gregor 
179547972afdSRichard Smith   if (HSOpts->ImplicitModuleMaps) {
179607f4357bSDouglas Gregor     // Load module maps for each of the header search directories.
1797e7dcf09fSJan Svoboda     for (DirectoryLookup &DL : search_dir_range()) {
1798e7dcf09fSJan Svoboda       bool IsSystem = DL.isSystemHeaderDirectory();
1799e7dcf09fSJan Svoboda       if (DL.isFramework()) {
1800c080917eSRafael Espindola         std::error_code EC;
18012c1dd271SDylan Noblesmith         SmallString<128> DirNative;
1802e7dcf09fSJan Svoboda         llvm::sys::path::native(DL.getFrameworkDir()->getName(), DirNative);
180307f4357bSDouglas Gregor 
180407f4357bSDouglas Gregor         // Search each of the ".framework" directories to load them as modules.
1805db8a7422SDuncan P. N. Exon Smith         llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1806fc51490bSJonas Devlieghere         for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1807fc51490bSJonas Devlieghere                                            DirEnd;
180807f4357bSDouglas Gregor              Dir != DirEnd && !EC; Dir.increment(EC)) {
18090ae00567SSam McCall           if (llvm::sys::path::extension(Dir->path()) != ".framework")
181007f4357bSDouglas Gregor             continue;
181107f4357bSDouglas Gregor 
1812d9390b6aSJan Svoboda           auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
181307f4357bSDouglas Gregor           if (!FrameworkDir)
181407f4357bSDouglas Gregor             continue;
181507f4357bSDouglas Gregor 
181607f4357bSDouglas Gregor           // Load this framework module.
18178d323d15SHarlan Haskins           loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
18180ae00567SSam McCall                               IsSystem);
181907f4357bSDouglas Gregor         }
182007f4357bSDouglas Gregor         continue;
182107f4357bSDouglas Gregor       }
182207f4357bSDouglas Gregor 
182307f4357bSDouglas Gregor       // FIXME: Deal with header maps.
1824e7dcf09fSJan Svoboda       if (DL.isHeaderMap())
182507f4357bSDouglas Gregor         continue;
182607f4357bSDouglas Gregor 
182707f4357bSDouglas Gregor       // Try to load a module map file for the search directory.
1828d9390b6aSJan Svoboda       loadModuleMapFile(*DL.getDirRef(), IsSystem, /*IsFramework*/ false);
182907f4357bSDouglas Gregor 
183021a0f557SDaniel Jasper       // Try to load module map files for immediate subdirectories of this
183121a0f557SDaniel Jasper       // search directory.
1832e7dcf09fSJan Svoboda       loadSubdirectoryModuleMaps(DL);
183307f4357bSDouglas Gregor     }
183421a0f557SDaniel Jasper   }
183507f4357bSDouglas Gregor 
183607f4357bSDouglas Gregor   // Populate the list of modules.
183732c2ea5cSJan Svoboda   llvm::transform(ModMap.modules(), std::back_inserter(Modules),
183832c2ea5cSJan Svoboda                   [](const auto &NameAndMod) { return NameAndMod.second; });
183907f4357bSDouglas Gregor }
18400339a64aSDouglas Gregor 
loadTopLevelSystemModules()184164a1fa5cSDouglas Gregor void HeaderSearch::loadTopLevelSystemModules() {
184247972afdSRichard Smith   if (!HSOpts->ImplicitModuleMaps)
184321a0f557SDaniel Jasper     return;
184421a0f557SDaniel Jasper 
184564a1fa5cSDouglas Gregor   // Load module maps for each of the header search directories.
1846e7dcf09fSJan Svoboda   for (const DirectoryLookup &DL : search_dir_range()) {
1847299787f7SDouglas Gregor     // We only care about normal header directories.
1848e7dcf09fSJan Svoboda     if (!DL.isNormalDir())
184964a1fa5cSDouglas Gregor       continue;
185064a1fa5cSDouglas Gregor 
185164a1fa5cSDouglas Gregor     // Try to load a module map file for the search directory.
1852d9390b6aSJan Svoboda     loadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(),
1853e7dcf09fSJan Svoboda                       DL.isFramework());
185464a1fa5cSDouglas Gregor   }
185564a1fa5cSDouglas Gregor }
185664a1fa5cSDouglas Gregor 
loadSubdirectoryModuleMaps(DirectoryLookup & SearchDir)18570339a64aSDouglas Gregor void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
185847972afdSRichard Smith   assert(HSOpts->ImplicitModuleMaps &&
185921a0f557SDaniel Jasper          "Should not be loading subdirectory module maps");
186021a0f557SDaniel Jasper 
18610339a64aSDouglas Gregor   if (SearchDir.haveSearchedAllModuleMaps())
18620339a64aSDouglas Gregor     return;
18630339a64aSDouglas Gregor 
1864c080917eSRafael Espindola   std::error_code EC;
18657d76ef9bSAlex Lorenz   SmallString<128> Dir = SearchDir.getDir()->getName();
18667d76ef9bSAlex Lorenz   FileMgr.makeAbsolutePath(Dir);
18670339a64aSDouglas Gregor   SmallString<128> DirNative;
18687d76ef9bSAlex Lorenz   llvm::sys::path::native(Dir, DirNative);
1869db8a7422SDuncan P. N. Exon Smith   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1870fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
18710339a64aSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
18720ae00567SSam McCall     bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
18731f6a32b3SBen Langmuir     if (IsFramework == SearchDir.isFramework())
18740ae00567SSam McCall       loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
1875984e1df7SBen Langmuir                         SearchDir.isFramework());
18760339a64aSDouglas Gregor   }
18770339a64aSDouglas Gregor 
18780339a64aSDouglas Gregor   SearchDir.setSearchedAllModuleMaps(true);
18790339a64aSDouglas Gregor }
18804eb8393cSRichard Smith 
suggestPathToFileForDiagnostics(const FileEntry * File,llvm::StringRef MainFile,bool * IsSystem)18811f6d9845SKadir Cetinkaya std::string HeaderSearch::suggestPathToFileForDiagnostics(
18821f6d9845SKadir Cetinkaya     const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) {
18834eb8393cSRichard Smith   // FIXME: We assume that the path name currently cached in the FileEntry is
1884dffb1a80SEric Liu   // the most appropriate one for this analysis (and that it's spelled the
1885dffb1a80SEric Liu   // same way as the corresponding header search path).
18861f6d9845SKadir Cetinkaya   return suggestPathToFileForDiagnostics(File->getName(), /*WorkingDir=*/"",
18871f6d9845SKadir Cetinkaya                                          MainFile, IsSystem);
1888dffb1a80SEric Liu }
1889dffb1a80SEric Liu 
suggestPathToFileForDiagnostics(llvm::StringRef File,llvm::StringRef WorkingDir,llvm::StringRef MainFile,bool * IsSystem)1890dffb1a80SEric Liu std::string HeaderSearch::suggestPathToFileForDiagnostics(
18911f6d9845SKadir Cetinkaya     llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
18921f6d9845SKadir Cetinkaya     bool *IsSystem) {
1893dffb1a80SEric Liu   using namespace llvm::sys;
18944eb8393cSRichard Smith 
18954eb8393cSRichard Smith   unsigned BestPrefixLength = 0;
18960cf7e61aSDavid Goldman   // Checks whether `Dir` is a strict path prefix of `File`. If so and that's
18970cf7e61aSDavid Goldman   // the longest prefix we've seen so for it, returns true and updates the
18980cf7e61aSDavid Goldman   // `BestPrefixLength` accordingly.
18991f6d9845SKadir Cetinkaya   auto CheckDir = [&](llvm::StringRef Dir) -> bool {
1900dffb1a80SEric Liu     llvm::SmallString<32> DirPath(Dir.begin(), Dir.end());
1901936c67d3SKadir Cetinkaya     if (!WorkingDir.empty() && !path::is_absolute(Dir))
19021ad53ca2SPavel Labath       fs::make_absolute(WorkingDir, DirPath);
1903dffb1a80SEric Liu     path::remove_dots(DirPath, /*remove_dot_dot=*/true);
1904dffb1a80SEric Liu     Dir = DirPath;
1905dffb1a80SEric Liu     for (auto NI = path::begin(File), NE = path::end(File),
1906dffb1a80SEric Liu               DI = path::begin(Dir), DE = path::end(Dir);
19074eb8393cSRichard Smith          /*termination condition in loop*/; ++NI, ++DI) {
1908dffb1a80SEric Liu       // '.' components in File are ignored.
19094eb8393cSRichard Smith       while (NI != NE && *NI == ".")
19104eb8393cSRichard Smith         ++NI;
19114eb8393cSRichard Smith       if (NI == NE)
19124eb8393cSRichard Smith         break;
19134eb8393cSRichard Smith 
19144eb8393cSRichard Smith       // '.' components in Dir are ignored.
19154eb8393cSRichard Smith       while (DI != DE && *DI == ".")
19164eb8393cSRichard Smith         ++DI;
19174eb8393cSRichard Smith       if (DI == DE) {
1918dffb1a80SEric Liu         // Dir is a prefix of File, up to '.' components and choice of path
19194eb8393cSRichard Smith         // separators.
1920dffb1a80SEric Liu         unsigned PrefixLength = NI - path::begin(File);
19214eb8393cSRichard Smith         if (PrefixLength > BestPrefixLength) {
19224eb8393cSRichard Smith           BestPrefixLength = PrefixLength;
19231f6d9845SKadir Cetinkaya           return true;
19244eb8393cSRichard Smith         }
19254eb8393cSRichard Smith         break;
19264eb8393cSRichard Smith       }
19274eb8393cSRichard Smith 
192851f85b40SKadir Cetinkaya       // Consider all path separators equal.
192951f85b40SKadir Cetinkaya       if (NI->size() == 1 && DI->size() == 1 &&
193051f85b40SKadir Cetinkaya           path::is_separator(NI->front()) && path::is_separator(DI->front()))
193151f85b40SKadir Cetinkaya         continue;
193251f85b40SKadir Cetinkaya 
19330cf7e61aSDavid Goldman       // Special case Apple .sdk folders since the search path is typically a
19340cf7e61aSDavid Goldman       // symlink like `iPhoneSimulator14.5.sdk` while the file is instead
19350cf7e61aSDavid Goldman       // located in `iPhoneSimulator.sdk` (the real folder).
19360cf7e61aSDavid Goldman       if (NI->endswith(".sdk") && DI->endswith(".sdk")) {
19370cf7e61aSDavid Goldman         StringRef NBasename = path::stem(*NI);
19380cf7e61aSDavid Goldman         StringRef DBasename = path::stem(*DI);
19390cf7e61aSDavid Goldman         if (DBasename.startswith(NBasename))
19400cf7e61aSDavid Goldman           continue;
19410cf7e61aSDavid Goldman       }
19420cf7e61aSDavid Goldman 
19434eb8393cSRichard Smith       if (*NI != *DI)
19444eb8393cSRichard Smith         break;
19454eb8393cSRichard Smith     }
19461f6d9845SKadir Cetinkaya     return false;
19471f6d9845SKadir Cetinkaya   };
19481f6d9845SKadir Cetinkaya 
19490cf7e61aSDavid Goldman   bool BestPrefixIsFramework = false;
1950e7dcf09fSJan Svoboda   for (const DirectoryLookup &DL : search_dir_range()) {
1951e7dcf09fSJan Svoboda     if (DL.isNormalDir()) {
1952e7dcf09fSJan Svoboda       StringRef Dir = DL.getDir()->getName();
19530cf7e61aSDavid Goldman       if (CheckDir(Dir)) {
19540cf7e61aSDavid Goldman         if (IsSystem)
1955e7dcf09fSJan Svoboda           *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
19560cf7e61aSDavid Goldman         BestPrefixIsFramework = false;
19570cf7e61aSDavid Goldman       }
1958e7dcf09fSJan Svoboda     } else if (DL.isFramework()) {
1959e7dcf09fSJan Svoboda       StringRef Dir = DL.getFrameworkDir()->getName();
19600cf7e61aSDavid Goldman       if (CheckDir(Dir)) {
19610cf7e61aSDavid Goldman         if (IsSystem)
1962e7dcf09fSJan Svoboda           *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
19630cf7e61aSDavid Goldman         BestPrefixIsFramework = true;
19640cf7e61aSDavid Goldman       }
19650cf7e61aSDavid Goldman     }
19664eb8393cSRichard Smith   }
19674eb8393cSRichard Smith 
19681f6d9845SKadir Cetinkaya   // Try to shorten include path using TUs directory, if we couldn't find any
19691f6d9845SKadir Cetinkaya   // suitable prefix in include search paths.
19700cf7e61aSDavid Goldman   if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
19710cf7e61aSDavid Goldman     if (IsSystem)
19721f6d9845SKadir Cetinkaya       *IsSystem = false;
19730cf7e61aSDavid Goldman     BestPrefixIsFramework = false;
19740cf7e61aSDavid Goldman   }
19751f6d9845SKadir Cetinkaya 
1976178ad93eSDmitry Polukhin   // Try resolving resulting filename via reverse search in header maps,
19775f57ca20SNico Weber   // key from header name is user preferred name for the include file.
1978178ad93eSDmitry Polukhin   StringRef Filename = File.drop_front(BestPrefixLength);
1979e7dcf09fSJan Svoboda   for (const DirectoryLookup &DL : search_dir_range()) {
1980e7dcf09fSJan Svoboda     if (!DL.isHeaderMap())
1981178ad93eSDmitry Polukhin       continue;
19821f6d9845SKadir Cetinkaya 
1983178ad93eSDmitry Polukhin     StringRef SpelledFilename =
1984e7dcf09fSJan Svoboda         DL.getHeaderMap()->reverseLookupFilename(Filename);
1985178ad93eSDmitry Polukhin     if (!SpelledFilename.empty()) {
1986178ad93eSDmitry Polukhin       Filename = SpelledFilename;
19870cf7e61aSDavid Goldman       BestPrefixIsFramework = false;
1988178ad93eSDmitry Polukhin       break;
1989178ad93eSDmitry Polukhin     }
1990178ad93eSDmitry Polukhin   }
19910cf7e61aSDavid Goldman 
19920cf7e61aSDavid Goldman   // If the best prefix is a framework path, we need to compute the proper
19930cf7e61aSDavid Goldman   // include spelling for the framework header.
19940cf7e61aSDavid Goldman   bool IsPrivateHeader;
19950cf7e61aSDavid Goldman   SmallString<128> FrameworkName, IncludeSpelling;
19960cf7e61aSDavid Goldman   if (BestPrefixIsFramework &&
19970cf7e61aSDavid Goldman       isFrameworkStylePath(Filename, IsPrivateHeader, FrameworkName,
19980cf7e61aSDavid Goldman                            IncludeSpelling)) {
19990cf7e61aSDavid Goldman     Filename = IncludeSpelling;
20000cf7e61aSDavid Goldman   }
2001178ad93eSDmitry Polukhin   return path::convert_to_slash(Filename);
20024eb8393cSRichard Smith }
2003