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