xref: /minix3/external/bsd/llvm/dist/clang/lib/Lex/HeaderSearch.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- HeaderSearch.cpp - Resolve Header File Locations ---===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  This file implements the DirectoryLookup and HeaderSearch interfaces.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "clang/Lex/HeaderSearch.h"
15f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/IdentifierTable.h"
17f4a2713aSLionel Sambuc #include "clang/Lex/HeaderMap.h"
18f4a2713aSLionel Sambuc #include "clang/Lex/HeaderSearchOptions.h"
19*0a6a1f1dSLionel Sambuc #include "clang/Lex/LexDiagnostic.h"
20f4a2713aSLionel Sambuc #include "clang/Lex/Lexer.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/ADT/APInt.h"
22*0a6a1f1dSLionel Sambuc #include "llvm/ADT/Hashing.h"
23f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
24f4a2713aSLionel Sambuc #include "llvm/Support/Capacity.h"
25f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
28f4a2713aSLionel Sambuc #include <cstdio>
29f4a2713aSLionel Sambuc #if defined(LLVM_ON_UNIX)
30f4a2713aSLionel Sambuc #include <limits.h>
31f4a2713aSLionel Sambuc #endif
32f4a2713aSLionel Sambuc using namespace clang;
33f4a2713aSLionel Sambuc 
34f4a2713aSLionel Sambuc const IdentifierInfo *
getControllingMacro(ExternalIdentifierLookup * External)35f4a2713aSLionel Sambuc HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
36f4a2713aSLionel Sambuc   if (ControllingMacro)
37f4a2713aSLionel Sambuc     return ControllingMacro;
38f4a2713aSLionel Sambuc 
39f4a2713aSLionel Sambuc   if (!ControllingMacroID || !External)
40*0a6a1f1dSLionel Sambuc     return nullptr;
41f4a2713aSLionel Sambuc 
42f4a2713aSLionel Sambuc   ControllingMacro = External->GetIdentifier(ControllingMacroID);
43f4a2713aSLionel Sambuc   return ControllingMacro;
44f4a2713aSLionel Sambuc }
45f4a2713aSLionel Sambuc 
~ExternalHeaderFileInfoSource()46f4a2713aSLionel Sambuc ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {}
47f4a2713aSLionel Sambuc 
HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target)48f4a2713aSLionel Sambuc HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,
49f4a2713aSLionel Sambuc                            SourceManager &SourceMgr, DiagnosticsEngine &Diags,
50f4a2713aSLionel Sambuc                            const LangOptions &LangOpts,
51f4a2713aSLionel Sambuc                            const TargetInfo *Target)
52*0a6a1f1dSLionel Sambuc     : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
53*0a6a1f1dSLionel Sambuc       FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this),
54*0a6a1f1dSLionel Sambuc       LangOpts(LangOpts) {
55f4a2713aSLionel Sambuc   AngledDirIdx = 0;
56f4a2713aSLionel Sambuc   SystemDirIdx = 0;
57f4a2713aSLionel Sambuc   NoCurDirSearch = false;
58f4a2713aSLionel Sambuc 
59*0a6a1f1dSLionel Sambuc   ExternalLookup = nullptr;
60*0a6a1f1dSLionel Sambuc   ExternalSource = nullptr;
61f4a2713aSLionel Sambuc   NumIncluded = 0;
62f4a2713aSLionel Sambuc   NumMultiIncludeFileOptzn = 0;
63f4a2713aSLionel Sambuc   NumFrameworkLookups = NumSubFrameworkLookups = 0;
64f4a2713aSLionel Sambuc }
65f4a2713aSLionel Sambuc 
~HeaderSearch()66f4a2713aSLionel Sambuc HeaderSearch::~HeaderSearch() {
67f4a2713aSLionel Sambuc   // Delete headermaps.
68f4a2713aSLionel Sambuc   for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
69f4a2713aSLionel Sambuc     delete HeaderMaps[i].second;
70f4a2713aSLionel Sambuc }
71f4a2713aSLionel Sambuc 
PrintStats()72f4a2713aSLionel Sambuc void HeaderSearch::PrintStats() {
73f4a2713aSLionel Sambuc   fprintf(stderr, "\n*** HeaderSearch Stats:\n");
74f4a2713aSLionel Sambuc   fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size());
75f4a2713aSLionel Sambuc   unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0;
76f4a2713aSLionel Sambuc   for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) {
77f4a2713aSLionel Sambuc     NumOnceOnlyFiles += FileInfo[i].isImport;
78f4a2713aSLionel Sambuc     if (MaxNumIncludes < FileInfo[i].NumIncludes)
79f4a2713aSLionel Sambuc       MaxNumIncludes = FileInfo[i].NumIncludes;
80f4a2713aSLionel Sambuc     NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1;
81f4a2713aSLionel Sambuc   }
82f4a2713aSLionel Sambuc   fprintf(stderr, "  %d #import/#pragma once files.\n", NumOnceOnlyFiles);
83f4a2713aSLionel Sambuc   fprintf(stderr, "  %d included exactly once.\n", NumSingleIncludedFiles);
84f4a2713aSLionel Sambuc   fprintf(stderr, "  %d max times a file is included.\n", MaxNumIncludes);
85f4a2713aSLionel Sambuc 
86f4a2713aSLionel Sambuc   fprintf(stderr, "  %d #include/#include_next/#import.\n", NumIncluded);
87f4a2713aSLionel Sambuc   fprintf(stderr, "    %d #includes skipped due to"
88f4a2713aSLionel Sambuc           " the multi-include optimization.\n", NumMultiIncludeFileOptzn);
89f4a2713aSLionel Sambuc 
90f4a2713aSLionel Sambuc   fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups);
91f4a2713aSLionel Sambuc   fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups);
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc 
94f4a2713aSLionel Sambuc /// CreateHeaderMap - This method returns a HeaderMap for the specified
95f4a2713aSLionel Sambuc /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
CreateHeaderMap(const FileEntry * FE)96f4a2713aSLionel Sambuc const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
97f4a2713aSLionel Sambuc   // We expect the number of headermaps to be small, and almost always empty.
98f4a2713aSLionel Sambuc   // If it ever grows, use of a linear search should be re-evaluated.
99f4a2713aSLionel Sambuc   if (!HeaderMaps.empty()) {
100f4a2713aSLionel Sambuc     for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
101f4a2713aSLionel Sambuc       // Pointer equality comparison of FileEntries works because they are
102f4a2713aSLionel Sambuc       // already uniqued by inode.
103f4a2713aSLionel Sambuc       if (HeaderMaps[i].first == FE)
104f4a2713aSLionel Sambuc         return HeaderMaps[i].second;
105f4a2713aSLionel Sambuc   }
106f4a2713aSLionel Sambuc 
107f4a2713aSLionel Sambuc   if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) {
108f4a2713aSLionel Sambuc     HeaderMaps.push_back(std::make_pair(FE, HM));
109f4a2713aSLionel Sambuc     return HM;
110f4a2713aSLionel Sambuc   }
111f4a2713aSLionel Sambuc 
112*0a6a1f1dSLionel Sambuc   return nullptr;
113f4a2713aSLionel Sambuc }
114f4a2713aSLionel Sambuc 
getModuleFileName(Module * Module)115f4a2713aSLionel Sambuc std::string HeaderSearch::getModuleFileName(Module *Module) {
116*0a6a1f1dSLionel Sambuc   const FileEntry *ModuleMap =
117*0a6a1f1dSLionel Sambuc       getModuleMap().getModuleMapFileForUniquing(Module);
118*0a6a1f1dSLionel Sambuc   return getModuleFileName(Module->Name, ModuleMap->getName());
119f4a2713aSLionel Sambuc }
120f4a2713aSLionel Sambuc 
getModuleFileName(StringRef ModuleName,StringRef ModuleMapPath)121*0a6a1f1dSLionel Sambuc std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
122*0a6a1f1dSLionel Sambuc                                             StringRef ModuleMapPath) {
123f4a2713aSLionel Sambuc   // If we don't have a module cache path, we can't do anything.
124f4a2713aSLionel Sambuc   if (ModuleCachePath.empty())
125f4a2713aSLionel Sambuc     return std::string();
126f4a2713aSLionel Sambuc 
127f4a2713aSLionel Sambuc   SmallString<256> Result(ModuleCachePath);
128*0a6a1f1dSLionel Sambuc   llvm::sys::fs::make_absolute(Result);
129*0a6a1f1dSLionel Sambuc 
130*0a6a1f1dSLionel Sambuc   if (HSOpts->DisableModuleHash) {
131f4a2713aSLionel Sambuc     llvm::sys::path::append(Result, ModuleName + ".pcm");
132*0a6a1f1dSLionel Sambuc   } else {
133*0a6a1f1dSLionel Sambuc     // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
134*0a6a1f1dSLionel Sambuc     // ideally be globally unique to this particular module. Name collisions
135*0a6a1f1dSLionel Sambuc     // in the hash are safe (because any translation unit can only import one
136*0a6a1f1dSLionel Sambuc     // module with each name), but result in a loss of caching.
137*0a6a1f1dSLionel Sambuc     //
138*0a6a1f1dSLionel Sambuc     // To avoid false-negatives, we form as canonical a path as we can, and map
139*0a6a1f1dSLionel Sambuc     // to lower-case in case we're on a case-insensitive file system.
140*0a6a1f1dSLionel Sambuc    auto *Dir =
141*0a6a1f1dSLionel Sambuc         FileMgr.getDirectory(llvm::sys::path::parent_path(ModuleMapPath));
142*0a6a1f1dSLionel Sambuc     if (!Dir)
143*0a6a1f1dSLionel Sambuc       return std::string();
144*0a6a1f1dSLionel Sambuc     auto DirName = FileMgr.getCanonicalName(Dir);
145*0a6a1f1dSLionel Sambuc     auto FileName = llvm::sys::path::filename(ModuleMapPath);
146*0a6a1f1dSLionel Sambuc 
147*0a6a1f1dSLionel Sambuc     llvm::hash_code Hash =
148*0a6a1f1dSLionel Sambuc         llvm::hash_combine(DirName.lower(), FileName.lower());
149*0a6a1f1dSLionel Sambuc 
150*0a6a1f1dSLionel Sambuc     SmallString<128> HashStr;
151*0a6a1f1dSLionel Sambuc     llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36);
152*0a6a1f1dSLionel Sambuc     llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
153*0a6a1f1dSLionel Sambuc   }
154f4a2713aSLionel Sambuc   return Result.str().str();
155f4a2713aSLionel Sambuc }
156f4a2713aSLionel Sambuc 
lookupModule(StringRef ModuleName,bool AllowSearch)157f4a2713aSLionel Sambuc Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
158f4a2713aSLionel Sambuc   // Look in the module map to determine if there is a module by this name.
159f4a2713aSLionel Sambuc   Module *Module = ModMap.findModule(ModuleName);
160*0a6a1f1dSLionel Sambuc   if (Module || !AllowSearch || !LangOpts.ModulesImplicitMaps)
161f4a2713aSLionel Sambuc     return Module;
162f4a2713aSLionel Sambuc 
163f4a2713aSLionel Sambuc   // Look through the various header search paths to load any available module
164f4a2713aSLionel Sambuc   // maps, searching for a module map that describes this module.
165f4a2713aSLionel Sambuc   for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
166f4a2713aSLionel Sambuc     if (SearchDirs[Idx].isFramework()) {
167f4a2713aSLionel Sambuc       // Search for or infer a module map for a framework.
168f4a2713aSLionel Sambuc       SmallString<128> FrameworkDirName;
169f4a2713aSLionel Sambuc       FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();
170f4a2713aSLionel Sambuc       llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework");
171f4a2713aSLionel Sambuc       if (const DirectoryEntry *FrameworkDir
172f4a2713aSLionel Sambuc             = FileMgr.getDirectory(FrameworkDirName)) {
173f4a2713aSLionel Sambuc         bool IsSystem
174f4a2713aSLionel Sambuc           = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
175f4a2713aSLionel Sambuc         Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem);
176f4a2713aSLionel Sambuc         if (Module)
177f4a2713aSLionel Sambuc           break;
178f4a2713aSLionel Sambuc       }
179f4a2713aSLionel Sambuc     }
180f4a2713aSLionel Sambuc 
181f4a2713aSLionel Sambuc     // FIXME: Figure out how header maps and module maps will work together.
182f4a2713aSLionel Sambuc 
183f4a2713aSLionel Sambuc     // Only deal with normal search directories.
184f4a2713aSLionel Sambuc     if (!SearchDirs[Idx].isNormalDir())
185f4a2713aSLionel Sambuc       continue;
186f4a2713aSLionel Sambuc 
187f4a2713aSLionel Sambuc     bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
188f4a2713aSLionel Sambuc     // Search for a module map file in this directory.
189*0a6a1f1dSLionel Sambuc     if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
190*0a6a1f1dSLionel Sambuc                           /*IsFramework*/false) == LMM_NewlyLoaded) {
191f4a2713aSLionel Sambuc       // We just loaded a module map file; check whether the module is
192f4a2713aSLionel Sambuc       // available now.
193f4a2713aSLionel Sambuc       Module = ModMap.findModule(ModuleName);
194f4a2713aSLionel Sambuc       if (Module)
195f4a2713aSLionel Sambuc         break;
196f4a2713aSLionel Sambuc     }
197f4a2713aSLionel Sambuc 
198f4a2713aSLionel Sambuc     // Search for a module map in a subdirectory with the same name as the
199f4a2713aSLionel Sambuc     // module.
200f4a2713aSLionel Sambuc     SmallString<128> NestedModuleMapDirName;
201f4a2713aSLionel Sambuc     NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName();
202f4a2713aSLionel Sambuc     llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
203*0a6a1f1dSLionel Sambuc     if (loadModuleMapFile(NestedModuleMapDirName, IsSystem,
204*0a6a1f1dSLionel Sambuc                           /*IsFramework*/false) == LMM_NewlyLoaded){
205f4a2713aSLionel Sambuc       // If we just loaded a module map file, look for the module again.
206f4a2713aSLionel Sambuc       Module = ModMap.findModule(ModuleName);
207f4a2713aSLionel Sambuc       if (Module)
208f4a2713aSLionel Sambuc         break;
209f4a2713aSLionel Sambuc     }
210f4a2713aSLionel Sambuc 
211f4a2713aSLionel Sambuc     // If we've already performed the exhaustive search for module maps in this
212f4a2713aSLionel Sambuc     // search directory, don't do it again.
213f4a2713aSLionel Sambuc     if (SearchDirs[Idx].haveSearchedAllModuleMaps())
214f4a2713aSLionel Sambuc       continue;
215f4a2713aSLionel Sambuc 
216f4a2713aSLionel Sambuc     // Load all module maps in the immediate subdirectories of this search
217f4a2713aSLionel Sambuc     // directory.
218f4a2713aSLionel Sambuc     loadSubdirectoryModuleMaps(SearchDirs[Idx]);
219f4a2713aSLionel Sambuc 
220f4a2713aSLionel Sambuc     // Look again for the module.
221f4a2713aSLionel Sambuc     Module = ModMap.findModule(ModuleName);
222f4a2713aSLionel Sambuc     if (Module)
223f4a2713aSLionel Sambuc       break;
224f4a2713aSLionel Sambuc   }
225f4a2713aSLionel Sambuc 
226f4a2713aSLionel Sambuc   return Module;
227f4a2713aSLionel Sambuc }
228f4a2713aSLionel Sambuc 
229f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
230f4a2713aSLionel Sambuc // File lookup within a DirectoryLookup scope
231f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
232f4a2713aSLionel Sambuc 
233f4a2713aSLionel Sambuc /// getName - Return the directory or filename corresponding to this lookup
234f4a2713aSLionel Sambuc /// object.
getName() const235f4a2713aSLionel Sambuc const char *DirectoryLookup::getName() const {
236f4a2713aSLionel Sambuc   if (isNormalDir())
237f4a2713aSLionel Sambuc     return getDir()->getName();
238f4a2713aSLionel Sambuc   if (isFramework())
239f4a2713aSLionel Sambuc     return getFrameworkDir()->getName();
240f4a2713aSLionel Sambuc   assert(isHeaderMap() && "Unknown DirectoryLookup");
241f4a2713aSLionel Sambuc   return getHeaderMap()->getFileName();
242f4a2713aSLionel Sambuc }
243f4a2713aSLionel Sambuc 
244*0a6a1f1dSLionel Sambuc static const FileEntry *
getFileAndSuggestModule(HeaderSearch & HS,StringRef FileName,const DirectoryEntry * Dir,bool IsSystemHeaderDir,ModuleMap::KnownHeader * SuggestedModule)245*0a6a1f1dSLionel Sambuc getFileAndSuggestModule(HeaderSearch &HS, StringRef FileName,
246*0a6a1f1dSLionel Sambuc                         const DirectoryEntry *Dir, bool IsSystemHeaderDir,
247*0a6a1f1dSLionel Sambuc                         ModuleMap::KnownHeader *SuggestedModule) {
248*0a6a1f1dSLionel Sambuc   // If we have a module map that might map this header, load it and
249*0a6a1f1dSLionel Sambuc   // check whether we'll have a suggestion for a module.
250*0a6a1f1dSLionel Sambuc   HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir);
251*0a6a1f1dSLionel Sambuc   if (SuggestedModule) {
252*0a6a1f1dSLionel Sambuc     const FileEntry *File = HS.getFileMgr().getFile(FileName,
253*0a6a1f1dSLionel Sambuc                                                     /*OpenFile=*/false);
254*0a6a1f1dSLionel Sambuc     if (File) {
255*0a6a1f1dSLionel Sambuc       // If there is a module that corresponds to this header, suggest it.
256*0a6a1f1dSLionel Sambuc       *SuggestedModule = HS.findModuleForHeader(File);
257*0a6a1f1dSLionel Sambuc 
258*0a6a1f1dSLionel Sambuc       // FIXME: This appears to be a no-op. We loaded the module map for this
259*0a6a1f1dSLionel Sambuc       // directory at the start of this function.
260*0a6a1f1dSLionel Sambuc       if (!SuggestedModule->getModule() &&
261*0a6a1f1dSLionel Sambuc           HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir))
262*0a6a1f1dSLionel Sambuc         *SuggestedModule = HS.findModuleForHeader(File);
263*0a6a1f1dSLionel Sambuc     }
264*0a6a1f1dSLionel Sambuc 
265*0a6a1f1dSLionel Sambuc     return File;
266*0a6a1f1dSLionel Sambuc   }
267*0a6a1f1dSLionel Sambuc 
268*0a6a1f1dSLionel Sambuc   return HS.getFileMgr().getFile(FileName, /*openFile=*/true);
269*0a6a1f1dSLionel Sambuc }
270f4a2713aSLionel Sambuc 
271f4a2713aSLionel Sambuc /// LookupFile - Lookup the specified file in this search path, returning it
272f4a2713aSLionel Sambuc /// if it exists or returning null if not.
LookupFile(StringRef & Filename,HeaderSearch & HS,SmallVectorImpl<char> * SearchPath,SmallVectorImpl<char> * RelativePath,ModuleMap::KnownHeader * SuggestedModule,bool & InUserSpecifiedSystemFramework,bool & HasBeenMapped,SmallVectorImpl<char> & MappedName) const273f4a2713aSLionel Sambuc const FileEntry *DirectoryLookup::LookupFile(
274*0a6a1f1dSLionel Sambuc     StringRef &Filename,
275f4a2713aSLionel Sambuc     HeaderSearch &HS,
276f4a2713aSLionel Sambuc     SmallVectorImpl<char> *SearchPath,
277f4a2713aSLionel Sambuc     SmallVectorImpl<char> *RelativePath,
278f4a2713aSLionel Sambuc     ModuleMap::KnownHeader *SuggestedModule,
279*0a6a1f1dSLionel Sambuc     bool &InUserSpecifiedSystemFramework,
280*0a6a1f1dSLionel Sambuc     bool &HasBeenMapped,
281*0a6a1f1dSLionel Sambuc     SmallVectorImpl<char> &MappedName) const {
282f4a2713aSLionel Sambuc   InUserSpecifiedSystemFramework = false;
283*0a6a1f1dSLionel Sambuc   HasBeenMapped = false;
284f4a2713aSLionel Sambuc 
285f4a2713aSLionel Sambuc   SmallString<1024> TmpDir;
286f4a2713aSLionel Sambuc   if (isNormalDir()) {
287f4a2713aSLionel Sambuc     // Concatenate the requested file onto the directory.
288f4a2713aSLionel Sambuc     TmpDir = getDir()->getName();
289f4a2713aSLionel Sambuc     llvm::sys::path::append(TmpDir, Filename);
290*0a6a1f1dSLionel Sambuc     if (SearchPath) {
291f4a2713aSLionel Sambuc       StringRef SearchPathRef(getDir()->getName());
292f4a2713aSLionel Sambuc       SearchPath->clear();
293f4a2713aSLionel Sambuc       SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
294f4a2713aSLionel Sambuc     }
295*0a6a1f1dSLionel Sambuc     if (RelativePath) {
296f4a2713aSLionel Sambuc       RelativePath->clear();
297f4a2713aSLionel Sambuc       RelativePath->append(Filename.begin(), Filename.end());
298f4a2713aSLionel Sambuc     }
299f4a2713aSLionel Sambuc 
300*0a6a1f1dSLionel Sambuc     return getFileAndSuggestModule(HS, TmpDir.str(), getDir(),
301*0a6a1f1dSLionel Sambuc                                    isSystemHeaderDirectory(),
302*0a6a1f1dSLionel Sambuc                                    SuggestedModule);
303f4a2713aSLionel Sambuc   }
304f4a2713aSLionel Sambuc 
305f4a2713aSLionel Sambuc   if (isFramework())
306f4a2713aSLionel Sambuc     return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
307f4a2713aSLionel Sambuc                              SuggestedModule, InUserSpecifiedSystemFramework);
308f4a2713aSLionel Sambuc 
309f4a2713aSLionel Sambuc   assert(isHeaderMap() && "Unknown directory lookup");
310*0a6a1f1dSLionel Sambuc   const HeaderMap *HM = getHeaderMap();
311*0a6a1f1dSLionel Sambuc   SmallString<1024> Path;
312*0a6a1f1dSLionel Sambuc   StringRef Dest = HM->lookupFilename(Filename, Path);
313*0a6a1f1dSLionel Sambuc   if (Dest.empty())
314*0a6a1f1dSLionel Sambuc     return nullptr;
315*0a6a1f1dSLionel Sambuc 
316*0a6a1f1dSLionel Sambuc   const FileEntry *Result;
317*0a6a1f1dSLionel Sambuc 
318*0a6a1f1dSLionel Sambuc   // Check if the headermap maps the filename to a framework include
319*0a6a1f1dSLionel Sambuc   // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
320*0a6a1f1dSLionel Sambuc   // framework include.
321*0a6a1f1dSLionel Sambuc   if (llvm::sys::path::is_relative(Dest)) {
322*0a6a1f1dSLionel Sambuc     MappedName.clear();
323*0a6a1f1dSLionel Sambuc     MappedName.append(Dest.begin(), Dest.end());
324*0a6a1f1dSLionel Sambuc     Filename = StringRef(MappedName.begin(), MappedName.size());
325*0a6a1f1dSLionel Sambuc     HasBeenMapped = true;
326*0a6a1f1dSLionel Sambuc     Result = HM->LookupFile(Filename, HS.getFileMgr());
327*0a6a1f1dSLionel Sambuc 
328*0a6a1f1dSLionel Sambuc   } else {
329*0a6a1f1dSLionel Sambuc     Result = HS.getFileMgr().getFile(Dest);
330*0a6a1f1dSLionel Sambuc   }
331*0a6a1f1dSLionel Sambuc 
332f4a2713aSLionel Sambuc   if (Result) {
333*0a6a1f1dSLionel Sambuc     if (SearchPath) {
334f4a2713aSLionel Sambuc       StringRef SearchPathRef(getName());
335f4a2713aSLionel Sambuc       SearchPath->clear();
336f4a2713aSLionel Sambuc       SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
337f4a2713aSLionel Sambuc     }
338*0a6a1f1dSLionel Sambuc     if (RelativePath) {
339f4a2713aSLionel Sambuc       RelativePath->clear();
340f4a2713aSLionel Sambuc       RelativePath->append(Filename.begin(), Filename.end());
341f4a2713aSLionel Sambuc     }
342f4a2713aSLionel Sambuc   }
343f4a2713aSLionel Sambuc   return Result;
344f4a2713aSLionel Sambuc }
345f4a2713aSLionel Sambuc 
346f4a2713aSLionel Sambuc /// \brief Given a framework directory, find the top-most framework directory.
347f4a2713aSLionel Sambuc ///
348f4a2713aSLionel Sambuc /// \param FileMgr The file manager to use for directory lookups.
349f4a2713aSLionel Sambuc /// \param DirName The name of the framework directory.
350f4a2713aSLionel Sambuc /// \param SubmodulePath Will be populated with the submodule path from the
351f4a2713aSLionel Sambuc /// returned top-level module to the originally named framework.
352f4a2713aSLionel Sambuc static const DirectoryEntry *
getTopFrameworkDir(FileManager & FileMgr,StringRef DirName,SmallVectorImpl<std::string> & SubmodulePath)353f4a2713aSLionel Sambuc getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
354f4a2713aSLionel Sambuc                    SmallVectorImpl<std::string> &SubmodulePath) {
355f4a2713aSLionel Sambuc   assert(llvm::sys::path::extension(DirName) == ".framework" &&
356f4a2713aSLionel Sambuc          "Not a framework directory");
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc   // Note: as an egregious but useful hack we use the real path here, because
359f4a2713aSLionel Sambuc   // frameworks moving between top-level frameworks to embedded frameworks tend
360f4a2713aSLionel Sambuc   // to be symlinked, and we base the logical structure of modules on the
361f4a2713aSLionel Sambuc   // physical layout. In particular, we need to deal with crazy includes like
362f4a2713aSLionel Sambuc   //
363f4a2713aSLionel Sambuc   //   #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h>
364f4a2713aSLionel Sambuc   //
365f4a2713aSLionel Sambuc   // where 'Bar' used to be embedded in 'Foo', is now a top-level framework
366f4a2713aSLionel Sambuc   // which one should access with, e.g.,
367f4a2713aSLionel Sambuc   //
368f4a2713aSLionel Sambuc   //   #include <Bar/Wibble.h>
369f4a2713aSLionel Sambuc   //
370f4a2713aSLionel Sambuc   // Similar issues occur when a top-level framework has moved into an
371f4a2713aSLionel Sambuc   // embedded framework.
372f4a2713aSLionel Sambuc   const DirectoryEntry *TopFrameworkDir = FileMgr.getDirectory(DirName);
373f4a2713aSLionel Sambuc   DirName = FileMgr.getCanonicalName(TopFrameworkDir);
374f4a2713aSLionel Sambuc   do {
375f4a2713aSLionel Sambuc     // Get the parent directory name.
376f4a2713aSLionel Sambuc     DirName = llvm::sys::path::parent_path(DirName);
377f4a2713aSLionel Sambuc     if (DirName.empty())
378f4a2713aSLionel Sambuc       break;
379f4a2713aSLionel Sambuc 
380f4a2713aSLionel Sambuc     // Determine whether this directory exists.
381f4a2713aSLionel Sambuc     const DirectoryEntry *Dir = FileMgr.getDirectory(DirName);
382f4a2713aSLionel Sambuc     if (!Dir)
383f4a2713aSLionel Sambuc       break;
384f4a2713aSLionel Sambuc 
385f4a2713aSLionel Sambuc     // If this is a framework directory, then we're a subframework of this
386f4a2713aSLionel Sambuc     // framework.
387f4a2713aSLionel Sambuc     if (llvm::sys::path::extension(DirName) == ".framework") {
388f4a2713aSLionel Sambuc       SubmodulePath.push_back(llvm::sys::path::stem(DirName));
389f4a2713aSLionel Sambuc       TopFrameworkDir = Dir;
390f4a2713aSLionel Sambuc     }
391f4a2713aSLionel Sambuc   } while (true);
392f4a2713aSLionel Sambuc 
393f4a2713aSLionel Sambuc   return TopFrameworkDir;
394f4a2713aSLionel Sambuc }
395f4a2713aSLionel Sambuc 
396f4a2713aSLionel Sambuc /// DoFrameworkLookup - Do a lookup of the specified file in the current
397f4a2713aSLionel Sambuc /// DirectoryLookup, which is a framework directory.
DoFrameworkLookup(StringRef Filename,HeaderSearch & HS,SmallVectorImpl<char> * SearchPath,SmallVectorImpl<char> * RelativePath,ModuleMap::KnownHeader * SuggestedModule,bool & InUserSpecifiedSystemFramework) const398f4a2713aSLionel Sambuc const FileEntry *DirectoryLookup::DoFrameworkLookup(
399f4a2713aSLionel Sambuc     StringRef Filename,
400f4a2713aSLionel Sambuc     HeaderSearch &HS,
401f4a2713aSLionel Sambuc     SmallVectorImpl<char> *SearchPath,
402f4a2713aSLionel Sambuc     SmallVectorImpl<char> *RelativePath,
403f4a2713aSLionel Sambuc     ModuleMap::KnownHeader *SuggestedModule,
404f4a2713aSLionel Sambuc     bool &InUserSpecifiedSystemFramework) const
405f4a2713aSLionel Sambuc {
406f4a2713aSLionel Sambuc   FileManager &FileMgr = HS.getFileMgr();
407f4a2713aSLionel Sambuc 
408f4a2713aSLionel Sambuc   // Framework names must have a '/' in the filename.
409f4a2713aSLionel Sambuc   size_t SlashPos = Filename.find('/');
410*0a6a1f1dSLionel Sambuc   if (SlashPos == StringRef::npos) return nullptr;
411f4a2713aSLionel Sambuc 
412f4a2713aSLionel Sambuc   // Find out if this is the home for the specified framework, by checking
413f4a2713aSLionel Sambuc   // HeaderSearch.  Possible answers are yes/no and unknown.
414f4a2713aSLionel Sambuc   HeaderSearch::FrameworkCacheEntry &CacheEntry =
415f4a2713aSLionel Sambuc     HS.LookupFrameworkCache(Filename.substr(0, SlashPos));
416f4a2713aSLionel Sambuc 
417f4a2713aSLionel Sambuc   // If it is known and in some other directory, fail.
418f4a2713aSLionel Sambuc   if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
419*0a6a1f1dSLionel Sambuc     return nullptr;
420f4a2713aSLionel Sambuc 
421f4a2713aSLionel Sambuc   // Otherwise, construct the path to this framework dir.
422f4a2713aSLionel Sambuc 
423f4a2713aSLionel Sambuc   // FrameworkName = "/System/Library/Frameworks/"
424f4a2713aSLionel Sambuc   SmallString<1024> FrameworkName;
425f4a2713aSLionel Sambuc   FrameworkName += getFrameworkDir()->getName();
426f4a2713aSLionel Sambuc   if (FrameworkName.empty() || FrameworkName.back() != '/')
427f4a2713aSLionel Sambuc     FrameworkName.push_back('/');
428f4a2713aSLionel Sambuc 
429f4a2713aSLionel Sambuc   // FrameworkName = "/System/Library/Frameworks/Cocoa"
430f4a2713aSLionel Sambuc   StringRef ModuleName(Filename.begin(), SlashPos);
431f4a2713aSLionel Sambuc   FrameworkName += ModuleName;
432f4a2713aSLionel Sambuc 
433f4a2713aSLionel Sambuc   // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
434f4a2713aSLionel Sambuc   FrameworkName += ".framework/";
435f4a2713aSLionel Sambuc 
436f4a2713aSLionel Sambuc   // If the cache entry was unresolved, populate it now.
437*0a6a1f1dSLionel Sambuc   if (!CacheEntry.Directory) {
438f4a2713aSLionel Sambuc     HS.IncrementFrameworkLookupCount();
439f4a2713aSLionel Sambuc 
440f4a2713aSLionel Sambuc     // If the framework dir doesn't exist, we fail.
441f4a2713aSLionel Sambuc     const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
442*0a6a1f1dSLionel Sambuc     if (!Dir) return nullptr;
443f4a2713aSLionel Sambuc 
444f4a2713aSLionel Sambuc     // Otherwise, if it does, remember that this is the right direntry for this
445f4a2713aSLionel Sambuc     // framework.
446f4a2713aSLionel Sambuc     CacheEntry.Directory = getFrameworkDir();
447f4a2713aSLionel Sambuc 
448f4a2713aSLionel Sambuc     // If this is a user search directory, check if the framework has been
449f4a2713aSLionel Sambuc     // user-specified as a system framework.
450f4a2713aSLionel Sambuc     if (getDirCharacteristic() == SrcMgr::C_User) {
451f4a2713aSLionel Sambuc       SmallString<1024> SystemFrameworkMarker(FrameworkName);
452f4a2713aSLionel Sambuc       SystemFrameworkMarker += ".system_framework";
453f4a2713aSLionel Sambuc       if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) {
454f4a2713aSLionel Sambuc         CacheEntry.IsUserSpecifiedSystemFramework = true;
455f4a2713aSLionel Sambuc       }
456f4a2713aSLionel Sambuc     }
457f4a2713aSLionel Sambuc   }
458f4a2713aSLionel Sambuc 
459f4a2713aSLionel Sambuc   // Set the 'user-specified system framework' flag.
460f4a2713aSLionel Sambuc   InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
461f4a2713aSLionel Sambuc 
462*0a6a1f1dSLionel Sambuc   if (RelativePath) {
463f4a2713aSLionel Sambuc     RelativePath->clear();
464f4a2713aSLionel Sambuc     RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
465f4a2713aSLionel Sambuc   }
466f4a2713aSLionel Sambuc 
467f4a2713aSLionel Sambuc   // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
468f4a2713aSLionel Sambuc   unsigned OrigSize = FrameworkName.size();
469f4a2713aSLionel Sambuc 
470f4a2713aSLionel Sambuc   FrameworkName += "Headers/";
471f4a2713aSLionel Sambuc 
472*0a6a1f1dSLionel Sambuc   if (SearchPath) {
473f4a2713aSLionel Sambuc     SearchPath->clear();
474f4a2713aSLionel Sambuc     // Without trailing '/'.
475f4a2713aSLionel Sambuc     SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
476f4a2713aSLionel Sambuc   }
477f4a2713aSLionel Sambuc 
478f4a2713aSLionel Sambuc   FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
479f4a2713aSLionel Sambuc   const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
480f4a2713aSLionel Sambuc                                         /*openFile=*/!SuggestedModule);
481f4a2713aSLionel Sambuc   if (!FE) {
482f4a2713aSLionel Sambuc     // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
483f4a2713aSLionel Sambuc     const char *Private = "Private";
484f4a2713aSLionel Sambuc     FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
485f4a2713aSLionel Sambuc                          Private+strlen(Private));
486*0a6a1f1dSLionel Sambuc     if (SearchPath)
487f4a2713aSLionel Sambuc       SearchPath->insert(SearchPath->begin()+OrigSize, Private,
488f4a2713aSLionel Sambuc                          Private+strlen(Private));
489f4a2713aSLionel Sambuc 
490f4a2713aSLionel Sambuc     FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/!SuggestedModule);
491f4a2713aSLionel Sambuc   }
492f4a2713aSLionel Sambuc 
493f4a2713aSLionel Sambuc   // If we found the header and are allowed to suggest a module, do so now.
494f4a2713aSLionel Sambuc   if (FE && SuggestedModule) {
495f4a2713aSLionel Sambuc     // Find the framework in which this header occurs.
496*0a6a1f1dSLionel Sambuc     StringRef FrameworkPath = FE->getDir()->getName();
497f4a2713aSLionel Sambuc     bool FoundFramework = false;
498f4a2713aSLionel Sambuc     do {
499f4a2713aSLionel Sambuc       // Determine whether this directory exists.
500f4a2713aSLionel Sambuc       const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath);
501f4a2713aSLionel Sambuc       if (!Dir)
502f4a2713aSLionel Sambuc         break;
503f4a2713aSLionel Sambuc 
504f4a2713aSLionel Sambuc       // If this is a framework directory, then we're a subframework of this
505f4a2713aSLionel Sambuc       // framework.
506f4a2713aSLionel Sambuc       if (llvm::sys::path::extension(FrameworkPath) == ".framework") {
507f4a2713aSLionel Sambuc         FoundFramework = true;
508f4a2713aSLionel Sambuc         break;
509f4a2713aSLionel Sambuc       }
510*0a6a1f1dSLionel Sambuc 
511*0a6a1f1dSLionel Sambuc       // Get the parent directory name.
512*0a6a1f1dSLionel Sambuc       FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
513*0a6a1f1dSLionel Sambuc       if (FrameworkPath.empty())
514*0a6a1f1dSLionel Sambuc         break;
515f4a2713aSLionel Sambuc     } while (true);
516f4a2713aSLionel Sambuc 
517f4a2713aSLionel Sambuc     if (FoundFramework) {
518f4a2713aSLionel Sambuc       // Find the top-level framework based on this framework.
519f4a2713aSLionel Sambuc       SmallVector<std::string, 4> SubmodulePath;
520f4a2713aSLionel Sambuc       const DirectoryEntry *TopFrameworkDir
521f4a2713aSLionel Sambuc         = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath);
522f4a2713aSLionel Sambuc 
523f4a2713aSLionel Sambuc       // Determine the name of the top-level framework.
524f4a2713aSLionel Sambuc       StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
525f4a2713aSLionel Sambuc 
526f4a2713aSLionel Sambuc       // Load this framework module. If that succeeds, find the suggested module
527f4a2713aSLionel Sambuc       // for this header, if any.
528f4a2713aSLionel Sambuc       bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
529f4a2713aSLionel Sambuc       if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
530f4a2713aSLionel Sambuc         *SuggestedModule = HS.findModuleForHeader(FE);
531f4a2713aSLionel Sambuc       }
532f4a2713aSLionel Sambuc     } else {
533f4a2713aSLionel Sambuc       *SuggestedModule = HS.findModuleForHeader(FE);
534f4a2713aSLionel Sambuc     }
535f4a2713aSLionel Sambuc   }
536f4a2713aSLionel Sambuc   return FE;
537f4a2713aSLionel Sambuc }
538f4a2713aSLionel Sambuc 
setTarget(const TargetInfo & Target)539f4a2713aSLionel Sambuc void HeaderSearch::setTarget(const TargetInfo &Target) {
540f4a2713aSLionel Sambuc   ModMap.setTarget(Target);
541f4a2713aSLionel Sambuc }
542f4a2713aSLionel Sambuc 
543f4a2713aSLionel Sambuc 
544f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
545f4a2713aSLionel Sambuc // Header File Location.
546f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
547f4a2713aSLionel Sambuc 
548*0a6a1f1dSLionel Sambuc /// \brief Return true with a diagnostic if the file that MSVC would have found
549*0a6a1f1dSLionel Sambuc /// fails to match the one that Clang would have found with MSVC header search
550*0a6a1f1dSLionel Sambuc /// disabled.
checkMSVCHeaderSearch(DiagnosticsEngine & Diags,const FileEntry * MSFE,const FileEntry * FE,SourceLocation IncludeLoc)551*0a6a1f1dSLionel Sambuc static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,
552*0a6a1f1dSLionel Sambuc                                   const FileEntry *MSFE, const FileEntry *FE,
553*0a6a1f1dSLionel Sambuc                                   SourceLocation IncludeLoc) {
554*0a6a1f1dSLionel Sambuc   if (MSFE && FE != MSFE) {
555*0a6a1f1dSLionel Sambuc     Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();
556*0a6a1f1dSLionel Sambuc     return true;
557*0a6a1f1dSLionel Sambuc   }
558*0a6a1f1dSLionel Sambuc   return false;
559*0a6a1f1dSLionel Sambuc }
560*0a6a1f1dSLionel Sambuc 
copyString(StringRef Str,llvm::BumpPtrAllocator & Alloc)561*0a6a1f1dSLionel Sambuc static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
562*0a6a1f1dSLionel Sambuc   assert(!Str.empty());
563*0a6a1f1dSLionel Sambuc   char *CopyStr = Alloc.Allocate<char>(Str.size()+1);
564*0a6a1f1dSLionel Sambuc   std::copy(Str.begin(), Str.end(), CopyStr);
565*0a6a1f1dSLionel Sambuc   CopyStr[Str.size()] = '\0';
566*0a6a1f1dSLionel Sambuc   return CopyStr;
567*0a6a1f1dSLionel Sambuc }
568f4a2713aSLionel Sambuc 
569f4a2713aSLionel Sambuc /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
570f4a2713aSLionel Sambuc /// return null on failure.  isAngled indicates whether the file reference is
571*0a6a1f1dSLionel Sambuc /// for system \#include's or not (i.e. using <> instead of ""). Includers, if
572*0a6a1f1dSLionel Sambuc /// non-empty, indicates where the \#including file(s) are, in case a relative
573*0a6a1f1dSLionel Sambuc /// search is needed. Microsoft mode will pass all \#including files.
LookupFile(StringRef Filename,SourceLocation IncludeLoc,bool isAngled,const DirectoryLookup * FromDir,const DirectoryLookup * & CurDir,ArrayRef<std::pair<const FileEntry *,const DirectoryEntry * >> Includers,SmallVectorImpl<char> * SearchPath,SmallVectorImpl<char> * RelativePath,ModuleMap::KnownHeader * SuggestedModule,bool SkipCache)574f4a2713aSLionel Sambuc const FileEntry *HeaderSearch::LookupFile(
575*0a6a1f1dSLionel Sambuc     StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
576*0a6a1f1dSLionel Sambuc     const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
577*0a6a1f1dSLionel Sambuc     ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
578*0a6a1f1dSLionel Sambuc     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
579*0a6a1f1dSLionel Sambuc     ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
580f4a2713aSLionel Sambuc   if (SuggestedModule)
581f4a2713aSLionel Sambuc     *SuggestedModule = ModuleMap::KnownHeader();
582f4a2713aSLionel Sambuc 
583f4a2713aSLionel Sambuc   // If 'Filename' is absolute, check to see if it exists and no searching.
584f4a2713aSLionel Sambuc   if (llvm::sys::path::is_absolute(Filename)) {
585*0a6a1f1dSLionel Sambuc     CurDir = nullptr;
586f4a2713aSLionel Sambuc 
587f4a2713aSLionel Sambuc     // If this was an #include_next "/absolute/file", fail.
588*0a6a1f1dSLionel Sambuc     if (FromDir) return nullptr;
589f4a2713aSLionel Sambuc 
590*0a6a1f1dSLionel Sambuc     if (SearchPath)
591f4a2713aSLionel Sambuc       SearchPath->clear();
592*0a6a1f1dSLionel Sambuc     if (RelativePath) {
593f4a2713aSLionel Sambuc       RelativePath->clear();
594f4a2713aSLionel Sambuc       RelativePath->append(Filename.begin(), Filename.end());
595f4a2713aSLionel Sambuc     }
596f4a2713aSLionel Sambuc     // Otherwise, just return the file.
597f4a2713aSLionel Sambuc     return FileMgr.getFile(Filename, /*openFile=*/true);
598f4a2713aSLionel Sambuc   }
599f4a2713aSLionel Sambuc 
600*0a6a1f1dSLionel Sambuc   // This is the header that MSVC's header search would have found.
601*0a6a1f1dSLionel Sambuc   const FileEntry *MSFE = nullptr;
602*0a6a1f1dSLionel Sambuc   ModuleMap::KnownHeader MSSuggestedModule;
603*0a6a1f1dSLionel Sambuc 
604f4a2713aSLionel Sambuc   // Unless disabled, check to see if the file is in the #includer's
605*0a6a1f1dSLionel Sambuc   // directory.  This cannot be based on CurDir, because each includer could be
606*0a6a1f1dSLionel Sambuc   // a #include of a subdirectory (#include "foo/bar.h") and a subsequent
607*0a6a1f1dSLionel Sambuc   // include of "baz.h" should resolve to "whatever/foo/baz.h".
608f4a2713aSLionel Sambuc   // This search is not done for <> headers.
609*0a6a1f1dSLionel Sambuc   if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
610f4a2713aSLionel Sambuc     SmallString<1024> TmpDir;
611*0a6a1f1dSLionel Sambuc     bool First = true;
612*0a6a1f1dSLionel Sambuc     for (const auto &IncluderAndDir : Includers) {
613*0a6a1f1dSLionel Sambuc       const FileEntry *Includer = IncluderAndDir.first;
614*0a6a1f1dSLionel Sambuc 
615f4a2713aSLionel Sambuc       // Concatenate the requested file onto the directory.
616f4a2713aSLionel Sambuc       // FIXME: Portability.  Filename concatenation should be in sys::Path.
617*0a6a1f1dSLionel Sambuc       TmpDir = IncluderAndDir.second->getName();
618f4a2713aSLionel Sambuc       TmpDir.push_back('/');
619f4a2713aSLionel Sambuc       TmpDir.append(Filename.begin(), Filename.end());
620*0a6a1f1dSLionel Sambuc 
621*0a6a1f1dSLionel Sambuc       // FIXME: We don't cache the result of getFileInfo across the call to
622*0a6a1f1dSLionel Sambuc       // getFileAndSuggestModule, because it's a reference to an element of
623*0a6a1f1dSLionel Sambuc       // a container that could be reallocated across this call.
624*0a6a1f1dSLionel Sambuc       //
625*0a6a1f1dSLionel Sambuc       // FIXME: If we have no includer, that means we're processing a #include
626*0a6a1f1dSLionel Sambuc       // from a module build. We should treat this as a system header if we're
627*0a6a1f1dSLionel Sambuc       // building a [system] module.
628*0a6a1f1dSLionel Sambuc       bool IncluderIsSystemHeader =
629*0a6a1f1dSLionel Sambuc           Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User;
630*0a6a1f1dSLionel Sambuc       if (const FileEntry *FE = getFileAndSuggestModule(
631*0a6a1f1dSLionel Sambuc               *this, TmpDir.str(), IncluderAndDir.second,
632*0a6a1f1dSLionel Sambuc               IncluderIsSystemHeader, SuggestedModule)) {
633*0a6a1f1dSLionel Sambuc         if (!Includer) {
634*0a6a1f1dSLionel Sambuc           assert(First && "only first includer can have no file");
635*0a6a1f1dSLionel Sambuc           return FE;
636*0a6a1f1dSLionel Sambuc         }
637*0a6a1f1dSLionel Sambuc 
638f4a2713aSLionel Sambuc         // Leave CurDir unset.
639f4a2713aSLionel Sambuc         // This file is a system header or C++ unfriendly if the old file is.
640f4a2713aSLionel Sambuc         //
641f4a2713aSLionel Sambuc         // Note that we only use one of FromHFI/ToHFI at once, due to potential
642f4a2713aSLionel Sambuc         // reallocation of the underlying vector potentially making the first
643f4a2713aSLionel Sambuc         // reference binding dangling.
644*0a6a1f1dSLionel Sambuc         HeaderFileInfo &FromHFI = getFileInfo(Includer);
645f4a2713aSLionel Sambuc         unsigned DirInfo = FromHFI.DirInfo;
646f4a2713aSLionel Sambuc         bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
647f4a2713aSLionel Sambuc         StringRef Framework = FromHFI.Framework;
648f4a2713aSLionel Sambuc 
649f4a2713aSLionel Sambuc         HeaderFileInfo &ToHFI = getFileInfo(FE);
650f4a2713aSLionel Sambuc         ToHFI.DirInfo = DirInfo;
651f4a2713aSLionel Sambuc         ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
652f4a2713aSLionel Sambuc         ToHFI.Framework = Framework;
653f4a2713aSLionel Sambuc 
654*0a6a1f1dSLionel Sambuc         if (SearchPath) {
655*0a6a1f1dSLionel Sambuc           StringRef SearchPathRef(IncluderAndDir.second->getName());
656f4a2713aSLionel Sambuc           SearchPath->clear();
657f4a2713aSLionel Sambuc           SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
658f4a2713aSLionel Sambuc         }
659*0a6a1f1dSLionel Sambuc         if (RelativePath) {
660f4a2713aSLionel Sambuc           RelativePath->clear();
661f4a2713aSLionel Sambuc           RelativePath->append(Filename.begin(), Filename.end());
662f4a2713aSLionel Sambuc         }
663*0a6a1f1dSLionel Sambuc         if (First)
664f4a2713aSLionel Sambuc           return FE;
665*0a6a1f1dSLionel Sambuc 
666*0a6a1f1dSLionel Sambuc         // Otherwise, we found the path via MSVC header search rules.  If
667*0a6a1f1dSLionel Sambuc         // -Wmsvc-include is enabled, we have to keep searching to see if we
668*0a6a1f1dSLionel Sambuc         // would've found this header in -I or -isystem directories.
669*0a6a1f1dSLionel Sambuc         if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
670*0a6a1f1dSLionel Sambuc           return FE;
671*0a6a1f1dSLionel Sambuc         } else {
672*0a6a1f1dSLionel Sambuc           MSFE = FE;
673*0a6a1f1dSLionel Sambuc           if (SuggestedModule) {
674*0a6a1f1dSLionel Sambuc             MSSuggestedModule = *SuggestedModule;
675*0a6a1f1dSLionel Sambuc             *SuggestedModule = ModuleMap::KnownHeader();
676*0a6a1f1dSLionel Sambuc           }
677*0a6a1f1dSLionel Sambuc           break;
678*0a6a1f1dSLionel Sambuc         }
679*0a6a1f1dSLionel Sambuc       }
680*0a6a1f1dSLionel Sambuc       First = false;
681f4a2713aSLionel Sambuc     }
682f4a2713aSLionel Sambuc   }
683f4a2713aSLionel Sambuc 
684*0a6a1f1dSLionel Sambuc   CurDir = nullptr;
685f4a2713aSLionel Sambuc 
686f4a2713aSLionel Sambuc   // If this is a system #include, ignore the user #include locs.
687f4a2713aSLionel Sambuc   unsigned i = isAngled ? AngledDirIdx : 0;
688f4a2713aSLionel Sambuc 
689f4a2713aSLionel Sambuc   // If this is a #include_next request, start searching after the directory the
690f4a2713aSLionel Sambuc   // file was found in.
691f4a2713aSLionel Sambuc   if (FromDir)
692f4a2713aSLionel Sambuc     i = FromDir-&SearchDirs[0];
693f4a2713aSLionel Sambuc 
694f4a2713aSLionel Sambuc   // Cache all of the lookups performed by this method.  Many headers are
695f4a2713aSLionel Sambuc   // multiply included, and the "pragma once" optimization prevents them from
696f4a2713aSLionel Sambuc   // being relex/pp'd, but they would still have to search through a
697f4a2713aSLionel Sambuc   // (potentially huge) series of SearchDirs to find it.
698*0a6a1f1dSLionel Sambuc   LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
699f4a2713aSLionel Sambuc 
700f4a2713aSLionel Sambuc   // If the entry has been previously looked up, the first value will be
701f4a2713aSLionel Sambuc   // non-zero.  If the value is equal to i (the start point of our search), then
702f4a2713aSLionel Sambuc   // this is a matching hit.
703*0a6a1f1dSLionel Sambuc   if (!SkipCache && CacheLookup.StartIdx == i+1) {
704f4a2713aSLionel Sambuc     // Skip querying potentially lots of directories for this lookup.
705*0a6a1f1dSLionel Sambuc     i = CacheLookup.HitIdx;
706*0a6a1f1dSLionel Sambuc     if (CacheLookup.MappedName)
707*0a6a1f1dSLionel Sambuc       Filename = CacheLookup.MappedName;
708f4a2713aSLionel Sambuc   } else {
709f4a2713aSLionel Sambuc     // Otherwise, this is the first query, or the previous query didn't match
710f4a2713aSLionel Sambuc     // our search start.  We will fill in our found location below, so prime the
711f4a2713aSLionel Sambuc     // start point value.
712*0a6a1f1dSLionel Sambuc     CacheLookup.reset(/*StartIdx=*/i+1);
713f4a2713aSLionel Sambuc   }
714f4a2713aSLionel Sambuc 
715*0a6a1f1dSLionel Sambuc   SmallString<64> MappedName;
716*0a6a1f1dSLionel Sambuc 
717f4a2713aSLionel Sambuc   // Check each directory in sequence to see if it contains this file.
718f4a2713aSLionel Sambuc   for (; i != SearchDirs.size(); ++i) {
719f4a2713aSLionel Sambuc     bool InUserSpecifiedSystemFramework = false;
720*0a6a1f1dSLionel Sambuc     bool HasBeenMapped = false;
721f4a2713aSLionel Sambuc     const FileEntry *FE =
722f4a2713aSLionel Sambuc       SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
723*0a6a1f1dSLionel Sambuc                                SuggestedModule, InUserSpecifiedSystemFramework,
724*0a6a1f1dSLionel Sambuc                                HasBeenMapped, MappedName);
725*0a6a1f1dSLionel Sambuc     if (HasBeenMapped) {
726*0a6a1f1dSLionel Sambuc       CacheLookup.MappedName =
727*0a6a1f1dSLionel Sambuc           copyString(Filename, LookupFileCache.getAllocator());
728*0a6a1f1dSLionel Sambuc     }
729f4a2713aSLionel Sambuc     if (!FE) continue;
730f4a2713aSLionel Sambuc 
731f4a2713aSLionel Sambuc     CurDir = &SearchDirs[i];
732f4a2713aSLionel Sambuc 
733f4a2713aSLionel Sambuc     // This file is a system header or C++ unfriendly if the dir is.
734f4a2713aSLionel Sambuc     HeaderFileInfo &HFI = getFileInfo(FE);
735f4a2713aSLionel Sambuc     HFI.DirInfo = CurDir->getDirCharacteristic();
736f4a2713aSLionel Sambuc 
737f4a2713aSLionel Sambuc     // If the directory characteristic is User but this framework was
738f4a2713aSLionel Sambuc     // user-specified to be treated as a system framework, promote the
739f4a2713aSLionel Sambuc     // characteristic.
740f4a2713aSLionel Sambuc     if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
741f4a2713aSLionel Sambuc       HFI.DirInfo = SrcMgr::C_System;
742f4a2713aSLionel Sambuc 
743f4a2713aSLionel Sambuc     // If the filename matches a known system header prefix, override
744f4a2713aSLionel Sambuc     // whether the file is a system header.
745f4a2713aSLionel Sambuc     for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
746f4a2713aSLionel Sambuc       if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
747f4a2713aSLionel Sambuc         HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
748f4a2713aSLionel Sambuc                                                        : SrcMgr::C_User;
749f4a2713aSLionel Sambuc         break;
750f4a2713aSLionel Sambuc       }
751f4a2713aSLionel Sambuc     }
752f4a2713aSLionel Sambuc 
753f4a2713aSLionel Sambuc     // If this file is found in a header map and uses the framework style of
754f4a2713aSLionel Sambuc     // includes, then this header is part of a framework we're building.
755f4a2713aSLionel Sambuc     if (CurDir->isIndexHeaderMap()) {
756f4a2713aSLionel Sambuc       size_t SlashPos = Filename.find('/');
757f4a2713aSLionel Sambuc       if (SlashPos != StringRef::npos) {
758f4a2713aSLionel Sambuc         HFI.IndexHeaderMapHeader = 1;
759f4a2713aSLionel Sambuc         HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(),
760f4a2713aSLionel Sambuc                                                          SlashPos));
761f4a2713aSLionel Sambuc       }
762f4a2713aSLionel Sambuc     }
763f4a2713aSLionel Sambuc 
764*0a6a1f1dSLionel Sambuc     if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
765*0a6a1f1dSLionel Sambuc       if (SuggestedModule)
766*0a6a1f1dSLionel Sambuc         *SuggestedModule = MSSuggestedModule;
767*0a6a1f1dSLionel Sambuc       return MSFE;
768*0a6a1f1dSLionel Sambuc     }
769*0a6a1f1dSLionel Sambuc 
770f4a2713aSLionel Sambuc     // Remember this location for the next lookup we do.
771*0a6a1f1dSLionel Sambuc     CacheLookup.HitIdx = i;
772f4a2713aSLionel Sambuc     return FE;
773f4a2713aSLionel Sambuc   }
774f4a2713aSLionel Sambuc 
775f4a2713aSLionel Sambuc   // If we are including a file with a quoted include "foo.h" from inside
776f4a2713aSLionel Sambuc   // a header in a framework that is currently being built, and we couldn't
777f4a2713aSLionel Sambuc   // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
778f4a2713aSLionel Sambuc   // "Foo" is the name of the framework in which the including header was found.
779*0a6a1f1dSLionel Sambuc   if (!Includers.empty() && Includers.front().first && !isAngled &&
780*0a6a1f1dSLionel Sambuc       Filename.find('/') == StringRef::npos) {
781*0a6a1f1dSLionel Sambuc     HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first);
782f4a2713aSLionel Sambuc     if (IncludingHFI.IndexHeaderMapHeader) {
783f4a2713aSLionel Sambuc       SmallString<128> ScratchFilename;
784f4a2713aSLionel Sambuc       ScratchFilename += IncludingHFI.Framework;
785f4a2713aSLionel Sambuc       ScratchFilename += '/';
786f4a2713aSLionel Sambuc       ScratchFilename += Filename;
787f4a2713aSLionel Sambuc 
788*0a6a1f1dSLionel Sambuc       const FileEntry *FE = LookupFile(
789*0a6a1f1dSLionel Sambuc           ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
790*0a6a1f1dSLionel Sambuc           Includers.front(), SearchPath, RelativePath, SuggestedModule);
791*0a6a1f1dSLionel Sambuc 
792*0a6a1f1dSLionel Sambuc       if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
793*0a6a1f1dSLionel Sambuc         if (SuggestedModule)
794*0a6a1f1dSLionel Sambuc           *SuggestedModule = MSSuggestedModule;
795*0a6a1f1dSLionel Sambuc         return MSFE;
796*0a6a1f1dSLionel Sambuc       }
797*0a6a1f1dSLionel Sambuc 
798*0a6a1f1dSLionel Sambuc       LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
799*0a6a1f1dSLionel Sambuc       CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx;
800*0a6a1f1dSLionel Sambuc       // FIXME: SuggestedModule.
801*0a6a1f1dSLionel Sambuc       return FE;
802f4a2713aSLionel Sambuc     }
803f4a2713aSLionel Sambuc   }
804f4a2713aSLionel Sambuc 
805*0a6a1f1dSLionel Sambuc   if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {
806*0a6a1f1dSLionel Sambuc     if (SuggestedModule)
807*0a6a1f1dSLionel Sambuc       *SuggestedModule = MSSuggestedModule;
808*0a6a1f1dSLionel Sambuc     return MSFE;
809*0a6a1f1dSLionel Sambuc   }
810*0a6a1f1dSLionel Sambuc 
811f4a2713aSLionel Sambuc   // Otherwise, didn't find it. Remember we didn't find this.
812*0a6a1f1dSLionel Sambuc   CacheLookup.HitIdx = SearchDirs.size();
813*0a6a1f1dSLionel Sambuc   return nullptr;
814f4a2713aSLionel Sambuc }
815f4a2713aSLionel Sambuc 
816f4a2713aSLionel Sambuc /// LookupSubframeworkHeader - Look up a subframework for the specified
817f4a2713aSLionel Sambuc /// \#include file.  For example, if \#include'ing <HIToolbox/HIToolbox.h> from
818f4a2713aSLionel Sambuc /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
819f4a2713aSLionel Sambuc /// is a subframework within Carbon.framework.  If so, return the FileEntry
820f4a2713aSLionel Sambuc /// for the designated file, otherwise return null.
821f4a2713aSLionel Sambuc const FileEntry *HeaderSearch::
LookupSubframeworkHeader(StringRef Filename,const FileEntry * ContextFileEnt,SmallVectorImpl<char> * SearchPath,SmallVectorImpl<char> * RelativePath,ModuleMap::KnownHeader * SuggestedModule)822f4a2713aSLionel Sambuc LookupSubframeworkHeader(StringRef Filename,
823f4a2713aSLionel Sambuc                          const FileEntry *ContextFileEnt,
824f4a2713aSLionel Sambuc                          SmallVectorImpl<char> *SearchPath,
825f4a2713aSLionel Sambuc                          SmallVectorImpl<char> *RelativePath,
826f4a2713aSLionel Sambuc                          ModuleMap::KnownHeader *SuggestedModule) {
827f4a2713aSLionel Sambuc   assert(ContextFileEnt && "No context file?");
828f4a2713aSLionel Sambuc 
829f4a2713aSLionel Sambuc   // Framework names must have a '/' in the filename.  Find it.
830f4a2713aSLionel Sambuc   // FIXME: Should we permit '\' on Windows?
831f4a2713aSLionel Sambuc   size_t SlashPos = Filename.find('/');
832*0a6a1f1dSLionel Sambuc   if (SlashPos == StringRef::npos) return nullptr;
833f4a2713aSLionel Sambuc 
834f4a2713aSLionel Sambuc   // Look up the base framework name of the ContextFileEnt.
835f4a2713aSLionel Sambuc   const char *ContextName = ContextFileEnt->getName();
836f4a2713aSLionel Sambuc 
837f4a2713aSLionel Sambuc   // If the context info wasn't a framework, couldn't be a subframework.
838f4a2713aSLionel Sambuc   const unsigned DotFrameworkLen = 10;
839f4a2713aSLionel Sambuc   const char *FrameworkPos = strstr(ContextName, ".framework");
840*0a6a1f1dSLionel Sambuc   if (FrameworkPos == nullptr ||
841f4a2713aSLionel Sambuc       (FrameworkPos[DotFrameworkLen] != '/' &&
842f4a2713aSLionel Sambuc        FrameworkPos[DotFrameworkLen] != '\\'))
843*0a6a1f1dSLionel Sambuc     return nullptr;
844f4a2713aSLionel Sambuc 
845f4a2713aSLionel Sambuc   SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1);
846f4a2713aSLionel Sambuc 
847f4a2713aSLionel Sambuc   // Append Frameworks/HIToolbox.framework/
848f4a2713aSLionel Sambuc   FrameworkName += "Frameworks/";
849f4a2713aSLionel Sambuc   FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
850f4a2713aSLionel Sambuc   FrameworkName += ".framework/";
851f4a2713aSLionel Sambuc 
852*0a6a1f1dSLionel Sambuc   auto &CacheLookup =
853*0a6a1f1dSLionel Sambuc       *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
854*0a6a1f1dSLionel Sambuc                                           FrameworkCacheEntry())).first;
855f4a2713aSLionel Sambuc 
856f4a2713aSLionel Sambuc   // Some other location?
857*0a6a1f1dSLionel Sambuc   if (CacheLookup.second.Directory &&
858*0a6a1f1dSLionel Sambuc       CacheLookup.first().size() == FrameworkName.size() &&
859*0a6a1f1dSLionel Sambuc       memcmp(CacheLookup.first().data(), &FrameworkName[0],
860*0a6a1f1dSLionel Sambuc              CacheLookup.first().size()) != 0)
861*0a6a1f1dSLionel Sambuc     return nullptr;
862f4a2713aSLionel Sambuc 
863f4a2713aSLionel Sambuc   // Cache subframework.
864*0a6a1f1dSLionel Sambuc   if (!CacheLookup.second.Directory) {
865f4a2713aSLionel Sambuc     ++NumSubFrameworkLookups;
866f4a2713aSLionel Sambuc 
867f4a2713aSLionel Sambuc     // If the framework dir doesn't exist, we fail.
868f4a2713aSLionel Sambuc     const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
869*0a6a1f1dSLionel Sambuc     if (!Dir) return nullptr;
870f4a2713aSLionel Sambuc 
871f4a2713aSLionel Sambuc     // Otherwise, if it does, remember that this is the right direntry for this
872f4a2713aSLionel Sambuc     // framework.
873*0a6a1f1dSLionel Sambuc     CacheLookup.second.Directory = Dir;
874f4a2713aSLionel Sambuc   }
875f4a2713aSLionel Sambuc 
876*0a6a1f1dSLionel Sambuc   const FileEntry *FE = nullptr;
877f4a2713aSLionel Sambuc 
878*0a6a1f1dSLionel Sambuc   if (RelativePath) {
879f4a2713aSLionel Sambuc     RelativePath->clear();
880f4a2713aSLionel Sambuc     RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
881f4a2713aSLionel Sambuc   }
882f4a2713aSLionel Sambuc 
883f4a2713aSLionel Sambuc   // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
884f4a2713aSLionel Sambuc   SmallString<1024> HeadersFilename(FrameworkName);
885f4a2713aSLionel Sambuc   HeadersFilename += "Headers/";
886*0a6a1f1dSLionel Sambuc   if (SearchPath) {
887f4a2713aSLionel Sambuc     SearchPath->clear();
888f4a2713aSLionel Sambuc     // Without trailing '/'.
889f4a2713aSLionel Sambuc     SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
890f4a2713aSLionel Sambuc   }
891f4a2713aSLionel Sambuc 
892f4a2713aSLionel Sambuc   HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
893f4a2713aSLionel Sambuc   if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) {
894f4a2713aSLionel Sambuc 
895f4a2713aSLionel Sambuc     // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
896f4a2713aSLionel Sambuc     HeadersFilename = FrameworkName;
897f4a2713aSLionel Sambuc     HeadersFilename += "PrivateHeaders/";
898*0a6a1f1dSLionel Sambuc     if (SearchPath) {
899f4a2713aSLionel Sambuc       SearchPath->clear();
900f4a2713aSLionel Sambuc       // Without trailing '/'.
901f4a2713aSLionel Sambuc       SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
902f4a2713aSLionel Sambuc     }
903f4a2713aSLionel Sambuc 
904f4a2713aSLionel Sambuc     HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
905f4a2713aSLionel Sambuc     if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true)))
906*0a6a1f1dSLionel Sambuc       return nullptr;
907f4a2713aSLionel Sambuc   }
908f4a2713aSLionel Sambuc 
909f4a2713aSLionel Sambuc   // This file is a system header or C++ unfriendly if the old file is.
910f4a2713aSLionel Sambuc   //
911f4a2713aSLionel Sambuc   // Note that the temporary 'DirInfo' is required here, as either call to
912f4a2713aSLionel Sambuc   // getFileInfo could resize the vector and we don't want to rely on order
913f4a2713aSLionel Sambuc   // of evaluation.
914f4a2713aSLionel Sambuc   unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo;
915f4a2713aSLionel Sambuc   getFileInfo(FE).DirInfo = DirInfo;
916f4a2713aSLionel Sambuc 
917f4a2713aSLionel Sambuc   // If we're supposed to suggest a module, look for one now.
918f4a2713aSLionel Sambuc   if (SuggestedModule) {
919f4a2713aSLionel Sambuc     // Find the top-level framework based on this framework.
920f4a2713aSLionel Sambuc     FrameworkName.pop_back(); // remove the trailing '/'
921f4a2713aSLionel Sambuc     SmallVector<std::string, 4> SubmodulePath;
922f4a2713aSLionel Sambuc     const DirectoryEntry *TopFrameworkDir
923f4a2713aSLionel Sambuc       = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
924f4a2713aSLionel Sambuc 
925f4a2713aSLionel Sambuc     // Determine the name of the top-level framework.
926f4a2713aSLionel Sambuc     StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
927f4a2713aSLionel Sambuc 
928f4a2713aSLionel Sambuc     // Load this framework module. If that succeeds, find the suggested module
929f4a2713aSLionel Sambuc     // for this header, if any.
930f4a2713aSLionel Sambuc     bool IsSystem = false;
931f4a2713aSLionel Sambuc     if (loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
932f4a2713aSLionel Sambuc       *SuggestedModule = findModuleForHeader(FE);
933f4a2713aSLionel Sambuc     }
934f4a2713aSLionel Sambuc   }
935f4a2713aSLionel Sambuc 
936f4a2713aSLionel Sambuc   return FE;
937f4a2713aSLionel Sambuc }
938f4a2713aSLionel Sambuc 
939f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
940f4a2713aSLionel Sambuc // File Info Management.
941f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
942f4a2713aSLionel Sambuc 
943f4a2713aSLionel Sambuc /// \brief Merge the header file info provided by \p OtherHFI into the current
944f4a2713aSLionel Sambuc /// header file info (\p HFI)
mergeHeaderFileInfo(HeaderFileInfo & HFI,const HeaderFileInfo & OtherHFI)945f4a2713aSLionel Sambuc static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
946f4a2713aSLionel Sambuc                                 const HeaderFileInfo &OtherHFI) {
947f4a2713aSLionel Sambuc   HFI.isImport |= OtherHFI.isImport;
948f4a2713aSLionel Sambuc   HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
949f4a2713aSLionel Sambuc   HFI.isModuleHeader |= OtherHFI.isModuleHeader;
950f4a2713aSLionel Sambuc   HFI.NumIncludes += OtherHFI.NumIncludes;
951f4a2713aSLionel Sambuc 
952f4a2713aSLionel Sambuc   if (!HFI.ControllingMacro && !HFI.ControllingMacroID) {
953f4a2713aSLionel Sambuc     HFI.ControllingMacro = OtherHFI.ControllingMacro;
954f4a2713aSLionel Sambuc     HFI.ControllingMacroID = OtherHFI.ControllingMacroID;
955f4a2713aSLionel Sambuc   }
956f4a2713aSLionel Sambuc 
957f4a2713aSLionel Sambuc   if (OtherHFI.External) {
958f4a2713aSLionel Sambuc     HFI.DirInfo = OtherHFI.DirInfo;
959f4a2713aSLionel Sambuc     HFI.External = OtherHFI.External;
960f4a2713aSLionel Sambuc     HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader;
961f4a2713aSLionel Sambuc   }
962f4a2713aSLionel Sambuc 
963f4a2713aSLionel Sambuc   if (HFI.Framework.empty())
964f4a2713aSLionel Sambuc     HFI.Framework = OtherHFI.Framework;
965f4a2713aSLionel Sambuc 
966f4a2713aSLionel Sambuc   HFI.Resolved = true;
967f4a2713aSLionel Sambuc }
968f4a2713aSLionel Sambuc 
969f4a2713aSLionel Sambuc /// getFileInfo - Return the HeaderFileInfo structure for the specified
970f4a2713aSLionel Sambuc /// FileEntry.
getFileInfo(const FileEntry * FE)971f4a2713aSLionel Sambuc HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
972f4a2713aSLionel Sambuc   if (FE->getUID() >= FileInfo.size())
973f4a2713aSLionel Sambuc     FileInfo.resize(FE->getUID()+1);
974f4a2713aSLionel Sambuc 
975f4a2713aSLionel Sambuc   HeaderFileInfo &HFI = FileInfo[FE->getUID()];
976f4a2713aSLionel Sambuc   if (ExternalSource && !HFI.Resolved)
977f4a2713aSLionel Sambuc     mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE));
978*0a6a1f1dSLionel Sambuc   HFI.IsValid = 1;
979f4a2713aSLionel Sambuc   return HFI;
980f4a2713aSLionel Sambuc }
981f4a2713aSLionel Sambuc 
tryGetFileInfo(const FileEntry * FE,HeaderFileInfo & Result) const982*0a6a1f1dSLionel Sambuc bool HeaderSearch::tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const {
983*0a6a1f1dSLionel Sambuc   if (FE->getUID() >= FileInfo.size())
984*0a6a1f1dSLionel Sambuc     return false;
985*0a6a1f1dSLionel Sambuc   const HeaderFileInfo &HFI = FileInfo[FE->getUID()];
986*0a6a1f1dSLionel Sambuc   if (HFI.IsValid) {
987*0a6a1f1dSLionel Sambuc     Result = HFI;
988*0a6a1f1dSLionel Sambuc     return true;
989*0a6a1f1dSLionel Sambuc   }
990*0a6a1f1dSLionel Sambuc   return false;
991*0a6a1f1dSLionel Sambuc }
992*0a6a1f1dSLionel Sambuc 
isFileMultipleIncludeGuarded(const FileEntry * File)993f4a2713aSLionel Sambuc bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
994f4a2713aSLionel Sambuc   // Check if we've ever seen this file as a header.
995f4a2713aSLionel Sambuc   if (File->getUID() >= FileInfo.size())
996f4a2713aSLionel Sambuc     return false;
997f4a2713aSLionel Sambuc 
998f4a2713aSLionel Sambuc   // Resolve header file info from the external source, if needed.
999f4a2713aSLionel Sambuc   HeaderFileInfo &HFI = FileInfo[File->getUID()];
1000f4a2713aSLionel Sambuc   if (ExternalSource && !HFI.Resolved)
1001f4a2713aSLionel Sambuc     mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File));
1002f4a2713aSLionel Sambuc 
1003f4a2713aSLionel Sambuc   return HFI.isPragmaOnce || HFI.isImport ||
1004f4a2713aSLionel Sambuc       HFI.ControllingMacro || HFI.ControllingMacroID;
1005f4a2713aSLionel Sambuc }
1006f4a2713aSLionel Sambuc 
MarkFileModuleHeader(const FileEntry * FE,ModuleMap::ModuleHeaderRole Role,bool isCompilingModuleHeader)1007f4a2713aSLionel Sambuc void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
1008f4a2713aSLionel Sambuc                                         ModuleMap::ModuleHeaderRole Role,
1009f4a2713aSLionel Sambuc                                         bool isCompilingModuleHeader) {
1010f4a2713aSLionel Sambuc   if (FE->getUID() >= FileInfo.size())
1011f4a2713aSLionel Sambuc     FileInfo.resize(FE->getUID()+1);
1012f4a2713aSLionel Sambuc 
1013f4a2713aSLionel Sambuc   HeaderFileInfo &HFI = FileInfo[FE->getUID()];
1014f4a2713aSLionel Sambuc   HFI.isModuleHeader = true;
1015f4a2713aSLionel Sambuc   HFI.isCompilingModuleHeader = isCompilingModuleHeader;
1016f4a2713aSLionel Sambuc   HFI.setHeaderRole(Role);
1017f4a2713aSLionel Sambuc }
1018f4a2713aSLionel Sambuc 
ShouldEnterIncludeFile(const FileEntry * File,bool isImport)1019f4a2713aSLionel Sambuc bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
1020f4a2713aSLionel Sambuc   ++NumIncluded; // Count # of attempted #includes.
1021f4a2713aSLionel Sambuc 
1022f4a2713aSLionel Sambuc   // Get information about this file.
1023f4a2713aSLionel Sambuc   HeaderFileInfo &FileInfo = getFileInfo(File);
1024f4a2713aSLionel Sambuc 
1025f4a2713aSLionel Sambuc   // If this is a #import directive, check that we have not already imported
1026f4a2713aSLionel Sambuc   // this header.
1027f4a2713aSLionel Sambuc   if (isImport) {
1028f4a2713aSLionel Sambuc     // If this has already been imported, don't import it again.
1029f4a2713aSLionel Sambuc     FileInfo.isImport = true;
1030f4a2713aSLionel Sambuc 
1031f4a2713aSLionel Sambuc     // Has this already been #import'ed or #include'd?
1032f4a2713aSLionel Sambuc     if (FileInfo.NumIncludes) return false;
1033f4a2713aSLionel Sambuc   } else {
1034f4a2713aSLionel Sambuc     // Otherwise, if this is a #include of a file that was previously #import'd
1035f4a2713aSLionel Sambuc     // or if this is the second #include of a #pragma once file, ignore it.
1036f4a2713aSLionel Sambuc     if (FileInfo.isImport)
1037f4a2713aSLionel Sambuc       return false;
1038f4a2713aSLionel Sambuc   }
1039f4a2713aSLionel Sambuc 
1040f4a2713aSLionel Sambuc   // Next, check to see if the file is wrapped with #ifndef guards.  If so, and
1041f4a2713aSLionel Sambuc   // if the macro that guards it is defined, we know the #include has no effect.
1042f4a2713aSLionel Sambuc   if (const IdentifierInfo *ControllingMacro
1043f4a2713aSLionel Sambuc       = FileInfo.getControllingMacro(ExternalLookup))
1044f4a2713aSLionel Sambuc     if (ControllingMacro->hasMacroDefinition()) {
1045f4a2713aSLionel Sambuc       ++NumMultiIncludeFileOptzn;
1046f4a2713aSLionel Sambuc       return false;
1047f4a2713aSLionel Sambuc     }
1048f4a2713aSLionel Sambuc 
1049f4a2713aSLionel Sambuc   // Increment the number of times this file has been included.
1050f4a2713aSLionel Sambuc   ++FileInfo.NumIncludes;
1051f4a2713aSLionel Sambuc 
1052f4a2713aSLionel Sambuc   return true;
1053f4a2713aSLionel Sambuc }
1054f4a2713aSLionel Sambuc 
getTotalMemory() const1055f4a2713aSLionel Sambuc size_t HeaderSearch::getTotalMemory() const {
1056f4a2713aSLionel Sambuc   return SearchDirs.capacity()
1057f4a2713aSLionel Sambuc     + llvm::capacity_in_bytes(FileInfo)
1058f4a2713aSLionel Sambuc     + llvm::capacity_in_bytes(HeaderMaps)
1059f4a2713aSLionel Sambuc     + LookupFileCache.getAllocator().getTotalMemory()
1060f4a2713aSLionel Sambuc     + FrameworkMap.getAllocator().getTotalMemory();
1061f4a2713aSLionel Sambuc }
1062f4a2713aSLionel Sambuc 
getUniqueFrameworkName(StringRef Framework)1063f4a2713aSLionel Sambuc StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
1064*0a6a1f1dSLionel Sambuc   return FrameworkNames.insert(Framework).first->first();
1065f4a2713aSLionel Sambuc }
1066f4a2713aSLionel Sambuc 
hasModuleMap(StringRef FileName,const DirectoryEntry * Root,bool IsSystem)1067f4a2713aSLionel Sambuc bool HeaderSearch::hasModuleMap(StringRef FileName,
1068f4a2713aSLionel Sambuc                                 const DirectoryEntry *Root,
1069f4a2713aSLionel Sambuc                                 bool IsSystem) {
1070*0a6a1f1dSLionel Sambuc   if (!enabledModules() || !LangOpts.ModulesImplicitMaps)
1071*0a6a1f1dSLionel Sambuc     return false;
1072*0a6a1f1dSLionel Sambuc 
1073f4a2713aSLionel Sambuc   SmallVector<const DirectoryEntry *, 2> FixUpDirectories;
1074f4a2713aSLionel Sambuc 
1075f4a2713aSLionel Sambuc   StringRef DirName = FileName;
1076f4a2713aSLionel Sambuc   do {
1077f4a2713aSLionel Sambuc     // Get the parent directory name.
1078f4a2713aSLionel Sambuc     DirName = llvm::sys::path::parent_path(DirName);
1079f4a2713aSLionel Sambuc     if (DirName.empty())
1080f4a2713aSLionel Sambuc       return false;
1081f4a2713aSLionel Sambuc 
1082f4a2713aSLionel Sambuc     // Determine whether this directory exists.
1083f4a2713aSLionel Sambuc     const DirectoryEntry *Dir = FileMgr.getDirectory(DirName);
1084f4a2713aSLionel Sambuc     if (!Dir)
1085f4a2713aSLionel Sambuc       return false;
1086f4a2713aSLionel Sambuc 
1087*0a6a1f1dSLionel Sambuc     // Try to load the module map file in this directory.
1088*0a6a1f1dSLionel Sambuc     switch (loadModuleMapFile(Dir, IsSystem,
1089*0a6a1f1dSLionel Sambuc                               llvm::sys::path::extension(Dir->getName()) ==
1090*0a6a1f1dSLionel Sambuc                                   ".framework")) {
1091f4a2713aSLionel Sambuc     case LMM_NewlyLoaded:
1092f4a2713aSLionel Sambuc     case LMM_AlreadyLoaded:
1093f4a2713aSLionel Sambuc       // Success. All of the directories we stepped through inherit this module
1094f4a2713aSLionel Sambuc       // map file.
1095f4a2713aSLionel Sambuc       for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1096f4a2713aSLionel Sambuc         DirectoryHasModuleMap[FixUpDirectories[I]] = true;
1097f4a2713aSLionel Sambuc       return true;
1098f4a2713aSLionel Sambuc 
1099f4a2713aSLionel Sambuc     case LMM_NoDirectory:
1100f4a2713aSLionel Sambuc     case LMM_InvalidModuleMap:
1101f4a2713aSLionel Sambuc       break;
1102f4a2713aSLionel Sambuc     }
1103f4a2713aSLionel Sambuc 
1104f4a2713aSLionel Sambuc     // If we hit the top of our search, we're done.
1105f4a2713aSLionel Sambuc     if (Dir == Root)
1106f4a2713aSLionel Sambuc       return false;
1107f4a2713aSLionel Sambuc 
1108f4a2713aSLionel Sambuc     // Keep track of all of the directories we checked, so we can mark them as
1109f4a2713aSLionel Sambuc     // having module maps if we eventually do find a module map.
1110f4a2713aSLionel Sambuc     FixUpDirectories.push_back(Dir);
1111f4a2713aSLionel Sambuc   } while (true);
1112f4a2713aSLionel Sambuc }
1113f4a2713aSLionel Sambuc 
1114f4a2713aSLionel Sambuc ModuleMap::KnownHeader
findModuleForHeader(const FileEntry * File) const1115f4a2713aSLionel Sambuc HeaderSearch::findModuleForHeader(const FileEntry *File) const {
1116f4a2713aSLionel Sambuc   if (ExternalSource) {
1117f4a2713aSLionel Sambuc     // Make sure the external source has handled header info about this file,
1118f4a2713aSLionel Sambuc     // which includes whether the file is part of a module.
1119f4a2713aSLionel Sambuc     (void)getFileInfo(File);
1120f4a2713aSLionel Sambuc   }
1121f4a2713aSLionel Sambuc   return ModMap.findModuleForHeader(File);
1122f4a2713aSLionel Sambuc }
1123f4a2713aSLionel Sambuc 
getPrivateModuleMap(const FileEntry * File,FileManager & FileMgr)1124*0a6a1f1dSLionel Sambuc static const FileEntry *getPrivateModuleMap(const FileEntry *File,
1125*0a6a1f1dSLionel Sambuc                                             FileManager &FileMgr) {
1126*0a6a1f1dSLionel Sambuc   StringRef Filename = llvm::sys::path::filename(File->getName());
1127*0a6a1f1dSLionel Sambuc   SmallString<128>  PrivateFilename(File->getDir()->getName());
1128*0a6a1f1dSLionel Sambuc   if (Filename == "module.map")
1129f4a2713aSLionel Sambuc     llvm::sys::path::append(PrivateFilename, "module_private.map");
1130*0a6a1f1dSLionel Sambuc   else if (Filename == "module.modulemap")
1131*0a6a1f1dSLionel Sambuc     llvm::sys::path::append(PrivateFilename, "module.private.modulemap");
1132*0a6a1f1dSLionel Sambuc   else
1133*0a6a1f1dSLionel Sambuc     return nullptr;
1134*0a6a1f1dSLionel Sambuc   return FileMgr.getFile(PrivateFilename);
1135f4a2713aSLionel Sambuc }
1136f4a2713aSLionel Sambuc 
loadModuleMapFile(const FileEntry * File,bool IsSystem)1137*0a6a1f1dSLionel Sambuc bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) {
1138*0a6a1f1dSLionel Sambuc   // Find the directory for the module. For frameworks, that may require going
1139*0a6a1f1dSLionel Sambuc   // up from the 'Modules' directory.
1140*0a6a1f1dSLionel Sambuc   const DirectoryEntry *Dir = nullptr;
1141*0a6a1f1dSLionel Sambuc   if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd)
1142*0a6a1f1dSLionel Sambuc     Dir = FileMgr.getDirectory(".");
1143*0a6a1f1dSLionel Sambuc   else {
1144*0a6a1f1dSLionel Sambuc     Dir = File->getDir();
1145*0a6a1f1dSLionel Sambuc     StringRef DirName(Dir->getName());
1146*0a6a1f1dSLionel Sambuc     if (llvm::sys::path::filename(DirName) == "Modules") {
1147*0a6a1f1dSLionel Sambuc       DirName = llvm::sys::path::parent_path(DirName);
1148*0a6a1f1dSLionel Sambuc       if (DirName.endswith(".framework"))
1149*0a6a1f1dSLionel Sambuc         Dir = FileMgr.getDirectory(DirName);
1150*0a6a1f1dSLionel Sambuc       // FIXME: This assert can fail if there's a race between the above check
1151*0a6a1f1dSLionel Sambuc       // and the removal of the directory.
1152*0a6a1f1dSLionel Sambuc       assert(Dir && "parent must exist");
1153*0a6a1f1dSLionel Sambuc     }
1154*0a6a1f1dSLionel Sambuc   }
1155*0a6a1f1dSLionel Sambuc 
1156*0a6a1f1dSLionel Sambuc   switch (loadModuleMapFileImpl(File, IsSystem, Dir)) {
1157*0a6a1f1dSLionel Sambuc   case LMM_AlreadyLoaded:
1158*0a6a1f1dSLionel Sambuc   case LMM_NewlyLoaded:
1159*0a6a1f1dSLionel Sambuc     return false;
1160*0a6a1f1dSLionel Sambuc   case LMM_NoDirectory:
1161*0a6a1f1dSLionel Sambuc   case LMM_InvalidModuleMap:
1162*0a6a1f1dSLionel Sambuc     return true;
1163*0a6a1f1dSLionel Sambuc   }
1164*0a6a1f1dSLionel Sambuc   llvm_unreachable("Unknown load module map result");
1165*0a6a1f1dSLionel Sambuc }
1166*0a6a1f1dSLionel Sambuc 
1167*0a6a1f1dSLionel Sambuc HeaderSearch::LoadModuleMapResult
loadModuleMapFileImpl(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir)1168*0a6a1f1dSLionel Sambuc HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem,
1169*0a6a1f1dSLionel Sambuc                                     const DirectoryEntry *Dir) {
1170*0a6a1f1dSLionel Sambuc   assert(File && "expected FileEntry");
1171*0a6a1f1dSLionel Sambuc 
1172*0a6a1f1dSLionel Sambuc   // Check whether we've already loaded this module map, and mark it as being
1173*0a6a1f1dSLionel Sambuc   // loaded in case we recursively try to load it from itself.
1174*0a6a1f1dSLionel Sambuc   auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));
1175*0a6a1f1dSLionel Sambuc   if (!AddResult.second)
1176*0a6a1f1dSLionel Sambuc     return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1177*0a6a1f1dSLionel Sambuc 
1178*0a6a1f1dSLionel Sambuc   if (ModMap.parseModuleMapFile(File, IsSystem, Dir)) {
1179*0a6a1f1dSLionel Sambuc     LoadedModuleMaps[File] = false;
1180*0a6a1f1dSLionel Sambuc     return LMM_InvalidModuleMap;
1181*0a6a1f1dSLionel Sambuc   }
1182*0a6a1f1dSLionel Sambuc 
1183*0a6a1f1dSLionel Sambuc   // Try to load a corresponding private module map.
1184*0a6a1f1dSLionel Sambuc   if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) {
1185*0a6a1f1dSLionel Sambuc     if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) {
1186*0a6a1f1dSLionel Sambuc       LoadedModuleMaps[File] = false;
1187*0a6a1f1dSLionel Sambuc       return LMM_InvalidModuleMap;
1188*0a6a1f1dSLionel Sambuc     }
1189*0a6a1f1dSLionel Sambuc   }
1190*0a6a1f1dSLionel Sambuc 
1191*0a6a1f1dSLionel Sambuc   // This directory has a module map.
1192*0a6a1f1dSLionel Sambuc   return LMM_NewlyLoaded;
1193*0a6a1f1dSLionel Sambuc }
1194*0a6a1f1dSLionel Sambuc 
1195*0a6a1f1dSLionel Sambuc const FileEntry *
lookupModuleMapFile(const DirectoryEntry * Dir,bool IsFramework)1196*0a6a1f1dSLionel Sambuc HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) {
1197*0a6a1f1dSLionel Sambuc   if (!LangOpts.ModulesImplicitMaps)
1198*0a6a1f1dSLionel Sambuc     return nullptr;
1199*0a6a1f1dSLionel Sambuc   // For frameworks, the preferred spelling is Modules/module.modulemap, but
1200*0a6a1f1dSLionel Sambuc   // module.map at the framework root is also accepted.
1201*0a6a1f1dSLionel Sambuc   SmallString<128> ModuleMapFileName(Dir->getName());
1202*0a6a1f1dSLionel Sambuc   if (IsFramework)
1203*0a6a1f1dSLionel Sambuc     llvm::sys::path::append(ModuleMapFileName, "Modules");
1204*0a6a1f1dSLionel Sambuc   llvm::sys::path::append(ModuleMapFileName, "module.modulemap");
1205*0a6a1f1dSLionel Sambuc   if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName))
1206*0a6a1f1dSLionel Sambuc     return F;
1207*0a6a1f1dSLionel Sambuc 
1208*0a6a1f1dSLionel Sambuc   // Continue to allow module.map
1209*0a6a1f1dSLionel Sambuc   ModuleMapFileName = Dir->getName();
1210*0a6a1f1dSLionel Sambuc   llvm::sys::path::append(ModuleMapFileName, "module.map");
1211*0a6a1f1dSLionel Sambuc   return FileMgr.getFile(ModuleMapFileName);
1212f4a2713aSLionel Sambuc }
1213f4a2713aSLionel Sambuc 
loadFrameworkModule(StringRef Name,const DirectoryEntry * Dir,bool IsSystem)1214f4a2713aSLionel Sambuc Module *HeaderSearch::loadFrameworkModule(StringRef Name,
1215f4a2713aSLionel Sambuc                                           const DirectoryEntry *Dir,
1216f4a2713aSLionel Sambuc                                           bool IsSystem) {
1217f4a2713aSLionel Sambuc   if (Module *Module = ModMap.findModule(Name))
1218f4a2713aSLionel Sambuc     return Module;
1219f4a2713aSLionel Sambuc 
1220f4a2713aSLionel Sambuc   // Try to load a module map file.
1221*0a6a1f1dSLionel Sambuc   switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
1222f4a2713aSLionel Sambuc   case LMM_InvalidModuleMap:
1223f4a2713aSLionel Sambuc     break;
1224f4a2713aSLionel Sambuc 
1225f4a2713aSLionel Sambuc   case LMM_AlreadyLoaded:
1226f4a2713aSLionel Sambuc   case LMM_NoDirectory:
1227*0a6a1f1dSLionel Sambuc     return nullptr;
1228f4a2713aSLionel Sambuc 
1229f4a2713aSLionel Sambuc   case LMM_NewlyLoaded:
1230f4a2713aSLionel Sambuc     return ModMap.findModule(Name);
1231f4a2713aSLionel Sambuc   }
1232f4a2713aSLionel Sambuc 
1233f4a2713aSLionel Sambuc 
1234*0a6a1f1dSLionel Sambuc   // Try to infer a module map from the framework directory.
1235*0a6a1f1dSLionel Sambuc   if (LangOpts.ModulesImplicitMaps)
1236*0a6a1f1dSLionel Sambuc     return ModMap.inferFrameworkModule(Name, Dir, IsSystem, /*Parent=*/nullptr);
1237f4a2713aSLionel Sambuc 
1238*0a6a1f1dSLionel Sambuc   return nullptr;
1239f4a2713aSLionel Sambuc }
1240f4a2713aSLionel Sambuc 
1241f4a2713aSLionel Sambuc 
1242f4a2713aSLionel Sambuc HeaderSearch::LoadModuleMapResult
loadModuleMapFile(StringRef DirName,bool IsSystem,bool IsFramework)1243*0a6a1f1dSLionel Sambuc HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem,
1244*0a6a1f1dSLionel Sambuc                                 bool IsFramework) {
1245f4a2713aSLionel Sambuc   if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName))
1246*0a6a1f1dSLionel Sambuc     return loadModuleMapFile(Dir, IsSystem, IsFramework);
1247f4a2713aSLionel Sambuc 
1248f4a2713aSLionel Sambuc   return LMM_NoDirectory;
1249f4a2713aSLionel Sambuc }
1250f4a2713aSLionel Sambuc 
1251f4a2713aSLionel Sambuc HeaderSearch::LoadModuleMapResult
loadModuleMapFile(const DirectoryEntry * Dir,bool IsSystem,bool IsFramework)1252*0a6a1f1dSLionel Sambuc HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem,
1253*0a6a1f1dSLionel Sambuc                                 bool IsFramework) {
1254*0a6a1f1dSLionel Sambuc   auto KnownDir = DirectoryHasModuleMap.find(Dir);
1255f4a2713aSLionel Sambuc   if (KnownDir != DirectoryHasModuleMap.end())
1256f4a2713aSLionel Sambuc     return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1257f4a2713aSLionel Sambuc 
1258*0a6a1f1dSLionel Sambuc   if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) {
1259*0a6a1f1dSLionel Sambuc     LoadModuleMapResult Result =
1260*0a6a1f1dSLionel Sambuc         loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir);
1261*0a6a1f1dSLionel Sambuc     // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
1262*0a6a1f1dSLionel Sambuc     // E.g. Foo.framework/Modules/module.modulemap
1263*0a6a1f1dSLionel Sambuc     //      ^Dir                  ^ModuleMapFile
1264*0a6a1f1dSLionel Sambuc     if (Result == LMM_NewlyLoaded)
1265f4a2713aSLionel Sambuc       DirectoryHasModuleMap[Dir] = true;
1266*0a6a1f1dSLionel Sambuc     else if (Result == LMM_InvalidModuleMap)
1267f4a2713aSLionel Sambuc       DirectoryHasModuleMap[Dir] = false;
1268*0a6a1f1dSLionel Sambuc     return Result;
1269f4a2713aSLionel Sambuc   }
1270f4a2713aSLionel Sambuc   return LMM_InvalidModuleMap;
1271f4a2713aSLionel Sambuc }
1272f4a2713aSLionel Sambuc 
collectAllModules(SmallVectorImpl<Module * > & Modules)1273f4a2713aSLionel Sambuc void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
1274f4a2713aSLionel Sambuc   Modules.clear();
1275f4a2713aSLionel Sambuc 
1276*0a6a1f1dSLionel Sambuc   if (LangOpts.ModulesImplicitMaps) {
1277f4a2713aSLionel Sambuc     // Load module maps for each of the header search directories.
1278f4a2713aSLionel Sambuc     for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
1279f4a2713aSLionel Sambuc       bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
1280f4a2713aSLionel Sambuc       if (SearchDirs[Idx].isFramework()) {
1281*0a6a1f1dSLionel Sambuc         std::error_code EC;
1282f4a2713aSLionel Sambuc         SmallString<128> DirNative;
1283f4a2713aSLionel Sambuc         llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(),
1284f4a2713aSLionel Sambuc                                 DirNative);
1285f4a2713aSLionel Sambuc 
1286f4a2713aSLionel Sambuc         // Search each of the ".framework" directories to load them as modules.
1287f4a2713aSLionel Sambuc         for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
1288f4a2713aSLionel Sambuc              Dir != DirEnd && !EC; Dir.increment(EC)) {
1289f4a2713aSLionel Sambuc           if (llvm::sys::path::extension(Dir->path()) != ".framework")
1290f4a2713aSLionel Sambuc             continue;
1291f4a2713aSLionel Sambuc 
1292*0a6a1f1dSLionel Sambuc           const DirectoryEntry *FrameworkDir =
1293*0a6a1f1dSLionel Sambuc               FileMgr.getDirectory(Dir->path());
1294f4a2713aSLionel Sambuc           if (!FrameworkDir)
1295f4a2713aSLionel Sambuc             continue;
1296f4a2713aSLionel Sambuc 
1297f4a2713aSLionel Sambuc           // Load this framework module.
1298f4a2713aSLionel Sambuc           loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir,
1299f4a2713aSLionel Sambuc                               IsSystem);
1300f4a2713aSLionel Sambuc         }
1301f4a2713aSLionel Sambuc         continue;
1302f4a2713aSLionel Sambuc       }
1303f4a2713aSLionel Sambuc 
1304f4a2713aSLionel Sambuc       // FIXME: Deal with header maps.
1305f4a2713aSLionel Sambuc       if (SearchDirs[Idx].isHeaderMap())
1306f4a2713aSLionel Sambuc         continue;
1307f4a2713aSLionel Sambuc 
1308f4a2713aSLionel Sambuc       // Try to load a module map file for the search directory.
1309*0a6a1f1dSLionel Sambuc       loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
1310*0a6a1f1dSLionel Sambuc                         /*IsFramework*/ false);
1311f4a2713aSLionel Sambuc 
1312*0a6a1f1dSLionel Sambuc       // Try to load module map files for immediate subdirectories of this
1313*0a6a1f1dSLionel Sambuc       // search directory.
1314f4a2713aSLionel Sambuc       loadSubdirectoryModuleMaps(SearchDirs[Idx]);
1315f4a2713aSLionel Sambuc     }
1316*0a6a1f1dSLionel Sambuc   }
1317f4a2713aSLionel Sambuc 
1318f4a2713aSLionel Sambuc   // Populate the list of modules.
1319f4a2713aSLionel Sambuc   for (ModuleMap::module_iterator M = ModMap.module_begin(),
1320f4a2713aSLionel Sambuc                                MEnd = ModMap.module_end();
1321f4a2713aSLionel Sambuc        M != MEnd; ++M) {
1322f4a2713aSLionel Sambuc     Modules.push_back(M->getValue());
1323f4a2713aSLionel Sambuc   }
1324f4a2713aSLionel Sambuc }
1325f4a2713aSLionel Sambuc 
loadTopLevelSystemModules()1326f4a2713aSLionel Sambuc void HeaderSearch::loadTopLevelSystemModules() {
1327*0a6a1f1dSLionel Sambuc   if (!LangOpts.ModulesImplicitMaps)
1328*0a6a1f1dSLionel Sambuc     return;
1329*0a6a1f1dSLionel Sambuc 
1330f4a2713aSLionel Sambuc   // Load module maps for each of the header search directories.
1331f4a2713aSLionel Sambuc   for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
1332f4a2713aSLionel Sambuc     // We only care about normal header directories.
1333f4a2713aSLionel Sambuc     if (!SearchDirs[Idx].isNormalDir()) {
1334f4a2713aSLionel Sambuc       continue;
1335f4a2713aSLionel Sambuc     }
1336f4a2713aSLionel Sambuc 
1337f4a2713aSLionel Sambuc     // Try to load a module map file for the search directory.
1338f4a2713aSLionel Sambuc     loadModuleMapFile(SearchDirs[Idx].getDir(),
1339*0a6a1f1dSLionel Sambuc                       SearchDirs[Idx].isSystemHeaderDirectory(),
1340*0a6a1f1dSLionel Sambuc                       SearchDirs[Idx].isFramework());
1341f4a2713aSLionel Sambuc   }
1342f4a2713aSLionel Sambuc }
1343f4a2713aSLionel Sambuc 
loadSubdirectoryModuleMaps(DirectoryLookup & SearchDir)1344f4a2713aSLionel Sambuc void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
1345*0a6a1f1dSLionel Sambuc   assert(LangOpts.ModulesImplicitMaps &&
1346*0a6a1f1dSLionel Sambuc          "Should not be loading subdirectory module maps");
1347*0a6a1f1dSLionel Sambuc 
1348f4a2713aSLionel Sambuc   if (SearchDir.haveSearchedAllModuleMaps())
1349f4a2713aSLionel Sambuc     return;
1350f4a2713aSLionel Sambuc 
1351*0a6a1f1dSLionel Sambuc   std::error_code EC;
1352f4a2713aSLionel Sambuc   SmallString<128> DirNative;
1353f4a2713aSLionel Sambuc   llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative);
1354f4a2713aSLionel Sambuc   for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
1355f4a2713aSLionel Sambuc        Dir != DirEnd && !EC; Dir.increment(EC)) {
1356*0a6a1f1dSLionel Sambuc     loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
1357*0a6a1f1dSLionel Sambuc                       SearchDir.isFramework());
1358f4a2713aSLionel Sambuc   }
1359f4a2713aSLionel Sambuc 
1360f4a2713aSLionel Sambuc   SearchDir.setSearchedAllModuleMaps(true);
1361f4a2713aSLionel Sambuc }
1362