]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===--- HeaderSearch.cpp - Resolve Header File Locations ---===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file implements the DirectoryLookup and HeaderSearch interfaces. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "clang/Lex/HeaderSearch.h" | |
15 | #include "clang/Lex/HeaderMap.h" | |
16 | #include "clang/Lex/Lexer.h" | |
17 | #include "clang/Basic/Diagnostic.h" | |
18 | #include "clang/Basic/FileManager.h" | |
19 | #include "clang/Basic/IdentifierTable.h" | |
20 | #include "llvm/Support/FileSystem.h" | |
21 | #include "llvm/Support/Path.h" | |
22 | #include "llvm/ADT/SmallString.h" | |
23 | #include "llvm/Support/Capacity.h" | |
24 | #include <cstdio> | |
25 | using namespace clang; | |
26 | ||
27 | const IdentifierInfo * | |
28 | HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { | |
29 | if (ControllingMacro) | |
30 | return ControllingMacro; | |
31 | ||
32 | if (!ControllingMacroID || !External) | |
33 | return 0; | |
34 | ||
35 | ControllingMacro = External->GetIdentifier(ControllingMacroID); | |
36 | return ControllingMacro; | |
37 | } | |
38 | ||
39 | ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} | |
40 | ||
41 | HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, | |
42 | const LangOptions &LangOpts, | |
43 | const TargetInfo *Target) | |
44 | : FileMgr(FM), FrameworkMap(64), | |
45 | ModMap(FileMgr, *Diags.getClient(), LangOpts, Target) | |
46 | { | |
47 | AngledDirIdx = 0; | |
48 | SystemDirIdx = 0; | |
49 | NoCurDirSearch = false; | |
50 | ||
51 | ExternalLookup = 0; | |
52 | ExternalSource = 0; | |
53 | NumIncluded = 0; | |
54 | NumMultiIncludeFileOptzn = 0; | |
55 | NumFrameworkLookups = NumSubFrameworkLookups = 0; | |
56 | } | |
57 | ||
58 | HeaderSearch::~HeaderSearch() { | |
59 | // Delete headermaps. | |
60 | for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) | |
61 | delete HeaderMaps[i].second; | |
62 | } | |
63 | ||
64 | void HeaderSearch::PrintStats() { | |
65 | fprintf(stderr, "\n*** HeaderSearch Stats:\n"); | |
66 | fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); | |
67 | unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; | |
68 | for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { | |
69 | NumOnceOnlyFiles += FileInfo[i].isImport; | |
70 | if (MaxNumIncludes < FileInfo[i].NumIncludes) | |
71 | MaxNumIncludes = FileInfo[i].NumIncludes; | |
72 | NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; | |
73 | } | |
74 | fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); | |
75 | fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); | |
76 | fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); | |
77 | ||
78 | fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); | |
79 | fprintf(stderr, " %d #includes skipped due to" | |
80 | " the multi-include optimization.\n", NumMultiIncludeFileOptzn); | |
81 | ||
82 | fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); | |
83 | fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); | |
84 | } | |
85 | ||
86 | /// CreateHeaderMap - This method returns a HeaderMap for the specified | |
87 | /// FileEntry, uniquing them through the 'HeaderMaps' datastructure. | |
88 | const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { | |
89 | // We expect the number of headermaps to be small, and almost always empty. | |
90 | // If it ever grows, use of a linear search should be re-evaluated. | |
91 | if (!HeaderMaps.empty()) { | |
92 | for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) | |
93 | // Pointer equality comparison of FileEntries works because they are | |
94 | // already uniqued by inode. | |
95 | if (HeaderMaps[i].first == FE) | |
96 | return HeaderMaps[i].second; | |
97 | } | |
98 | ||
99 | if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) { | |
100 | HeaderMaps.push_back(std::make_pair(FE, HM)); | |
101 | return HM; | |
102 | } | |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
107 | std::string HeaderSearch::getModuleFileName(Module *Module) { | |
108 | // If we don't have a module cache path, we can't do anything. | |
109 | if (ModuleCachePath.empty()) | |
110 | return std::string(); | |
111 | ||
112 | ||
113 | SmallString<256> Result(ModuleCachePath); | |
114 | llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm"); | |
115 | return Result.str().str(); | |
116 | } | |
117 | ||
118 | std::string HeaderSearch::getModuleFileName(StringRef ModuleName) { | |
119 | // If we don't have a module cache path, we can't do anything. | |
120 | if (ModuleCachePath.empty()) | |
121 | return std::string(); | |
122 | ||
123 | ||
124 | SmallString<256> Result(ModuleCachePath); | |
125 | llvm::sys::path::append(Result, ModuleName + ".pcm"); | |
126 | return Result.str().str(); | |
127 | } | |
128 | ||
129 | Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { | |
130 | // Look in the module map to determine if there is a module by this name. | |
131 | Module *Module = ModMap.findModule(ModuleName); | |
132 | if (Module || !AllowSearch) | |
133 | return Module; | |
134 | ||
135 | // Look through the various header search paths to load any avai;able module | |
136 | // maps, searching for a module map that describes this module. | |
137 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { | |
138 | if (SearchDirs[Idx].isFramework()) { | |
139 | // Search for or infer a module map for a framework. | |
140 | SmallString<128> FrameworkDirName; | |
141 | FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName(); | |
142 | llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework"); | |
143 | if (const DirectoryEntry *FrameworkDir | |
144 | = FileMgr.getDirectory(FrameworkDirName)) { | |
145 | bool IsSystem | |
146 | = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; | |
147 | Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); | |
148 | if (Module) | |
149 | break; | |
150 | } | |
151 | } | |
152 | ||
153 | // FIXME: Figure out how header maps and module maps will work together. | |
154 | ||
155 | // Only deal with normal search directories. | |
156 | if (!SearchDirs[Idx].isNormalDir()) | |
157 | continue; | |
158 | ||
159 | // Search for a module map file in this directory. | |
160 | if (loadModuleMapFile(SearchDirs[Idx].getDir()) == LMM_NewlyLoaded) { | |
161 | // We just loaded a module map file; check whether the module is | |
162 | // available now. | |
163 | Module = ModMap.findModule(ModuleName); | |
164 | if (Module) | |
165 | break; | |
166 | } | |
167 | ||
168 | // Search for a module map in a subdirectory with the same name as the | |
169 | // module. | |
170 | SmallString<128> NestedModuleMapDirName; | |
171 | NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName(); | |
172 | llvm::sys::path::append(NestedModuleMapDirName, ModuleName); | |
173 | if (loadModuleMapFile(NestedModuleMapDirName) == LMM_NewlyLoaded) { | |
174 | // If we just loaded a module map file, look for the module again. | |
175 | Module = ModMap.findModule(ModuleName); | |
176 | if (Module) | |
177 | break; | |
178 | } | |
179 | } | |
180 | ||
181 | return Module; | |
182 | } | |
183 | ||
184 | //===----------------------------------------------------------------------===// | |
185 | // File lookup within a DirectoryLookup scope | |
186 | //===----------------------------------------------------------------------===// | |
187 | ||
188 | /// getName - Return the directory or filename corresponding to this lookup | |
189 | /// object. | |
190 | const char *DirectoryLookup::getName() const { | |
191 | if (isNormalDir()) | |
192 | return getDir()->getName(); | |
193 | if (isFramework()) | |
194 | return getFrameworkDir()->getName(); | |
195 | assert(isHeaderMap() && "Unknown DirectoryLookup"); | |
196 | return getHeaderMap()->getFileName(); | |
197 | } | |
198 | ||
199 | ||
200 | /// LookupFile - Lookup the specified file in this search path, returning it | |
201 | /// if it exists or returning null if not. | |
202 | const FileEntry *DirectoryLookup::LookupFile( | |
203 | StringRef Filename, | |
204 | HeaderSearch &HS, | |
205 | SmallVectorImpl<char> *SearchPath, | |
206 | SmallVectorImpl<char> *RelativePath, | |
207 | Module **SuggestedModule, | |
208 | bool &InUserSpecifiedSystemFramework) const { | |
209 | InUserSpecifiedSystemFramework = false; | |
210 | ||
211 | SmallString<1024> TmpDir; | |
212 | if (isNormalDir()) { | |
213 | // Concatenate the requested file onto the directory. | |
214 | TmpDir = getDir()->getName(); | |
215 | llvm::sys::path::append(TmpDir, Filename); | |
216 | if (SearchPath != NULL) { | |
217 | StringRef SearchPathRef(getDir()->getName()); | |
218 | SearchPath->clear(); | |
219 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); | |
220 | } | |
221 | if (RelativePath != NULL) { | |
222 | RelativePath->clear(); | |
223 | RelativePath->append(Filename.begin(), Filename.end()); | |
224 | } | |
225 | ||
226 | // If we have a module map that might map this header, load it and | |
227 | // check whether we'll have a suggestion for a module. | |
228 | if (SuggestedModule && HS.hasModuleMap(TmpDir, getDir())) { | |
229 | const FileEntry *File = HS.getFileMgr().getFile(TmpDir.str(), | |
230 | /*openFile=*/false); | |
231 | if (!File) | |
232 | return File; | |
233 | ||
234 | // If there is a module that corresponds to this header, | |
235 | // suggest it. | |
236 | *SuggestedModule = HS.findModuleForHeader(File); | |
237 | return File; | |
238 | } | |
239 | ||
240 | return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); | |
241 | } | |
242 | ||
243 | if (isFramework()) | |
244 | return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, | |
245 | SuggestedModule, InUserSpecifiedSystemFramework); | |
246 | ||
247 | assert(isHeaderMap() && "Unknown directory lookup"); | |
248 | const FileEntry * const Result = getHeaderMap()->LookupFile( | |
249 | Filename, HS.getFileMgr()); | |
250 | if (Result) { | |
251 | if (SearchPath != NULL) { | |
252 | StringRef SearchPathRef(getName()); | |
253 | SearchPath->clear(); | |
254 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); | |
255 | } | |
256 | if (RelativePath != NULL) { | |
257 | RelativePath->clear(); | |
258 | RelativePath->append(Filename.begin(), Filename.end()); | |
259 | } | |
260 | } | |
261 | return Result; | |
262 | } | |
263 | ||
264 | ||
265 | /// DoFrameworkLookup - Do a lookup of the specified file in the current | |
266 | /// DirectoryLookup, which is a framework directory. | |
267 | const FileEntry *DirectoryLookup::DoFrameworkLookup( | |
268 | StringRef Filename, | |
269 | HeaderSearch &HS, | |
270 | SmallVectorImpl<char> *SearchPath, | |
271 | SmallVectorImpl<char> *RelativePath, | |
272 | Module **SuggestedModule, | |
273 | bool &InUserSpecifiedSystemFramework) const | |
274 | { | |
275 | FileManager &FileMgr = HS.getFileMgr(); | |
276 | ||
277 | // Framework names must have a '/' in the filename. | |
278 | size_t SlashPos = Filename.find('/'); | |
279 | if (SlashPos == StringRef::npos) return 0; | |
280 | ||
281 | // Find out if this is the home for the specified framework, by checking | |
282 | // HeaderSearch. Possible answers are yes/no and unknown. | |
283 | HeaderSearch::FrameworkCacheEntry &CacheEntry = | |
284 | HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); | |
285 | ||
286 | // If it is known and in some other directory, fail. | |
287 | if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) | |
288 | return 0; | |
289 | ||
290 | // Otherwise, construct the path to this framework dir. | |
291 | ||
292 | // FrameworkName = "/System/Library/Frameworks/" | |
293 | SmallString<1024> FrameworkName; | |
294 | FrameworkName += getFrameworkDir()->getName(); | |
295 | if (FrameworkName.empty() || FrameworkName.back() != '/') | |
296 | FrameworkName.push_back('/'); | |
297 | ||
298 | // FrameworkName = "/System/Library/Frameworks/Cocoa" | |
299 | StringRef ModuleName(Filename.begin(), SlashPos); | |
300 | FrameworkName += ModuleName; | |
301 | ||
302 | // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" | |
303 | FrameworkName += ".framework/"; | |
304 | ||
305 | // If the cache entry was unresolved, populate it now. | |
306 | if (CacheEntry.Directory == 0) { | |
307 | HS.IncrementFrameworkLookupCount(); | |
308 | ||
309 | // If the framework dir doesn't exist, we fail. | |
310 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); | |
311 | if (Dir == 0) return 0; | |
312 | ||
313 | // Otherwise, if it does, remember that this is the right direntry for this | |
314 | // framework. | |
315 | CacheEntry.Directory = getFrameworkDir(); | |
316 | ||
317 | // If this is a user search directory, check if the framework has been | |
318 | // user-specified as a system framework. | |
319 | if (getDirCharacteristic() == SrcMgr::C_User) { | |
320 | SmallString<1024> SystemFrameworkMarker(FrameworkName); | |
321 | SystemFrameworkMarker += ".system_framework"; | |
322 | if (llvm::sys::fs::exists(SystemFrameworkMarker.str())) { | |
323 | CacheEntry.IsUserSpecifiedSystemFramework = true; | |
324 | } | |
325 | } | |
326 | } | |
327 | ||
328 | // Set the 'user-specified system framework' flag. | |
329 | InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; | |
330 | ||
331 | if (RelativePath != NULL) { | |
332 | RelativePath->clear(); | |
333 | RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); | |
334 | } | |
335 | ||
336 | // If we're allowed to look for modules, try to load or create the module | |
337 | // corresponding to this framework. | |
338 | Module *Module = 0; | |
339 | if (SuggestedModule) { | |
340 | if (const DirectoryEntry *FrameworkDir | |
341 | = FileMgr.getDirectory(FrameworkName)) { | |
342 | bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; | |
343 | Module = HS.loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); | |
344 | } | |
345 | } | |
346 | ||
347 | // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" | |
348 | unsigned OrigSize = FrameworkName.size(); | |
349 | ||
350 | FrameworkName += "Headers/"; | |
351 | ||
352 | if (SearchPath != NULL) { | |
353 | SearchPath->clear(); | |
354 | // Without trailing '/'. | |
355 | SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); | |
356 | } | |
357 | ||
358 | // Determine whether this is the module we're building or not. | |
359 | bool AutomaticImport = Module; | |
360 | FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); | |
361 | if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), | |
362 | /*openFile=*/!AutomaticImport)) { | |
363 | if (AutomaticImport) | |
364 | *SuggestedModule = HS.findModuleForHeader(FE); | |
365 | return FE; | |
366 | } | |
367 | ||
368 | // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" | |
369 | const char *Private = "Private"; | |
370 | FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, | |
371 | Private+strlen(Private)); | |
372 | if (SearchPath != NULL) | |
373 | SearchPath->insert(SearchPath->begin()+OrigSize, Private, | |
374 | Private+strlen(Private)); | |
375 | ||
376 | const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), | |
377 | /*openFile=*/!AutomaticImport); | |
378 | if (FE && AutomaticImport) | |
379 | *SuggestedModule = HS.findModuleForHeader(FE); | |
380 | return FE; | |
381 | } | |
382 | ||
383 | void HeaderSearch::setTarget(const TargetInfo &Target) { | |
384 | ModMap.setTarget(Target); | |
385 | } | |
386 | ||
387 | ||
388 | //===----------------------------------------------------------------------===// | |
389 | // Header File Location. | |
390 | //===----------------------------------------------------------------------===// | |
391 | ||
392 | ||
393 | /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, | |
394 | /// return null on failure. isAngled indicates whether the file reference is | |
395 | /// for system \#include's or not (i.e. using <> instead of ""). CurFileEnt, if | |
396 | /// non-null, indicates where the \#including file is, in case a relative search | |
397 | /// is needed. | |
398 | const FileEntry *HeaderSearch::LookupFile( | |
399 | StringRef Filename, | |
400 | bool isAngled, | |
401 | const DirectoryLookup *FromDir, | |
402 | const DirectoryLookup *&CurDir, | |
403 | const FileEntry *CurFileEnt, | |
404 | SmallVectorImpl<char> *SearchPath, | |
405 | SmallVectorImpl<char> *RelativePath, | |
406 | Module **SuggestedModule, | |
407 | bool SkipCache) | |
408 | { | |
409 | if (SuggestedModule) | |
410 | *SuggestedModule = 0; | |
411 | ||
412 | // If 'Filename' is absolute, check to see if it exists and no searching. | |
413 | if (llvm::sys::path::is_absolute(Filename)) { | |
414 | CurDir = 0; | |
415 | ||
416 | // If this was an #include_next "/absolute/file", fail. | |
417 | if (FromDir) return 0; | |
418 | ||
419 | if (SearchPath != NULL) | |
420 | SearchPath->clear(); | |
421 | if (RelativePath != NULL) { | |
422 | RelativePath->clear(); | |
423 | RelativePath->append(Filename.begin(), Filename.end()); | |
424 | } | |
425 | // Otherwise, just return the file. | |
426 | return FileMgr.getFile(Filename, /*openFile=*/true); | |
427 | } | |
428 | ||
429 | // Unless disabled, check to see if the file is in the #includer's | |
430 | // directory. This has to be based on CurFileEnt, not CurDir, because | |
431 | // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and | |
432 | // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". | |
433 | // This search is not done for <> headers. | |
434 | if (CurFileEnt && !isAngled && !NoCurDirSearch) { | |
435 | SmallString<1024> TmpDir; | |
436 | // Concatenate the requested file onto the directory. | |
437 | // FIXME: Portability. Filename concatenation should be in sys::Path. | |
438 | TmpDir += CurFileEnt->getDir()->getName(); | |
439 | TmpDir.push_back('/'); | |
440 | TmpDir.append(Filename.begin(), Filename.end()); | |
441 | if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) { | |
442 | // Leave CurDir unset. | |
443 | // This file is a system header or C++ unfriendly if the old file is. | |
444 | // | |
445 | // Note that we only use one of FromHFI/ToHFI at once, due to potential | |
446 | // reallocation of the underlying vector potentially making the first | |
447 | // reference binding dangling. | |
448 | HeaderFileInfo &FromHFI = getFileInfo(CurFileEnt); | |
449 | unsigned DirInfo = FromHFI.DirInfo; | |
450 | bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; | |
451 | StringRef Framework = FromHFI.Framework; | |
452 | ||
453 | HeaderFileInfo &ToHFI = getFileInfo(FE); | |
454 | ToHFI.DirInfo = DirInfo; | |
455 | ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; | |
456 | ToHFI.Framework = Framework; | |
457 | ||
458 | if (SearchPath != NULL) { | |
459 | StringRef SearchPathRef(CurFileEnt->getDir()->getName()); | |
460 | SearchPath->clear(); | |
461 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); | |
462 | } | |
463 | if (RelativePath != NULL) { | |
464 | RelativePath->clear(); | |
465 | RelativePath->append(Filename.begin(), Filename.end()); | |
466 | } | |
467 | return FE; | |
468 | } | |
469 | } | |
470 | ||
471 | CurDir = 0; | |
472 | ||
473 | // If this is a system #include, ignore the user #include locs. | |
474 | unsigned i = isAngled ? AngledDirIdx : 0; | |
475 | ||
476 | // If this is a #include_next request, start searching after the directory the | |
477 | // file was found in. | |
478 | if (FromDir) | |
479 | i = FromDir-&SearchDirs[0]; | |
480 | ||
481 | // Cache all of the lookups performed by this method. Many headers are | |
482 | // multiply included, and the "pragma once" optimization prevents them from | |
483 | // being relex/pp'd, but they would still have to search through a | |
484 | // (potentially huge) series of SearchDirs to find it. | |
485 | std::pair<unsigned, unsigned> &CacheLookup = | |
486 | LookupFileCache.GetOrCreateValue(Filename).getValue(); | |
487 | ||
488 | // If the entry has been previously looked up, the first value will be | |
489 | // non-zero. If the value is equal to i (the start point of our search), then | |
490 | // this is a matching hit. | |
491 | if (!SkipCache && CacheLookup.first == i+1) { | |
492 | // Skip querying potentially lots of directories for this lookup. | |
493 | i = CacheLookup.second; | |
494 | } else { | |
495 | // Otherwise, this is the first query, or the previous query didn't match | |
496 | // our search start. We will fill in our found location below, so prime the | |
497 | // start point value. | |
498 | CacheLookup.first = i+1; | |
499 | } | |
500 | ||
501 | // Check each directory in sequence to see if it contains this file. | |
502 | for (; i != SearchDirs.size(); ++i) { | |
503 | bool InUserSpecifiedSystemFramework = false; | |
504 | const FileEntry *FE = | |
505 | SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, | |
506 | SuggestedModule, InUserSpecifiedSystemFramework); | |
507 | if (!FE) continue; | |
508 | ||
509 | CurDir = &SearchDirs[i]; | |
510 | ||
511 | // This file is a system header or C++ unfriendly if the dir is. | |
512 | HeaderFileInfo &HFI = getFileInfo(FE); | |
513 | HFI.DirInfo = CurDir->getDirCharacteristic(); | |
514 | ||
515 | // If the directory characteristic is User but this framework was | |
516 | // user-specified to be treated as a system framework, promote the | |
517 | // characteristic. | |
518 | if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework) | |
519 | HFI.DirInfo = SrcMgr::C_System; | |
520 | ||
521 | // If the filename matches a known system header prefix, override | |
522 | // whether the file is a system header. | |
523 | for (unsigned j = SystemHeaderPrefixes.size(); j; --j) { | |
524 | if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) { | |
525 | HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System | |
526 | : SrcMgr::C_User; | |
527 | break; | |
528 | } | |
529 | } | |
530 | ||
531 | // If this file is found in a header map and uses the framework style of | |
532 | // includes, then this header is part of a framework we're building. | |
533 | if (CurDir->isIndexHeaderMap()) { | |
534 | size_t SlashPos = Filename.find('/'); | |
535 | if (SlashPos != StringRef::npos) { | |
536 | HFI.IndexHeaderMapHeader = 1; | |
537 | HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), | |
538 | SlashPos)); | |
539 | } | |
540 | } | |
541 | ||
542 | // Remember this location for the next lookup we do. | |
543 | CacheLookup.second = i; | |
544 | return FE; | |
545 | } | |
546 | ||
547 | // If we are including a file with a quoted include "foo.h" from inside | |
548 | // a header in a framework that is currently being built, and we couldn't | |
549 | // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where | |
550 | // "Foo" is the name of the framework in which the including header was found. | |
551 | if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { | |
552 | HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); | |
553 | if (IncludingHFI.IndexHeaderMapHeader) { | |
554 | SmallString<128> ScratchFilename; | |
555 | ScratchFilename += IncludingHFI.Framework; | |
556 | ScratchFilename += '/'; | |
557 | ScratchFilename += Filename; | |
558 | ||
559 | const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true, | |
560 | FromDir, CurDir, CurFileEnt, | |
561 | SearchPath, RelativePath, | |
562 | SuggestedModule); | |
563 | std::pair<unsigned, unsigned> &CacheLookup | |
564 | = LookupFileCache.GetOrCreateValue(Filename).getValue(); | |
565 | CacheLookup.second | |
566 | = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second; | |
567 | return Result; | |
568 | } | |
569 | } | |
570 | ||
571 | // Otherwise, didn't find it. Remember we didn't find this. | |
572 | CacheLookup.second = SearchDirs.size(); | |
573 | return 0; | |
574 | } | |
575 | ||
576 | /// LookupSubframeworkHeader - Look up a subframework for the specified | |
577 | /// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from | |
578 | /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox | |
579 | /// is a subframework within Carbon.framework. If so, return the FileEntry | |
580 | /// for the designated file, otherwise return null. | |
581 | const FileEntry *HeaderSearch:: | |
582 | LookupSubframeworkHeader(StringRef Filename, | |
583 | const FileEntry *ContextFileEnt, | |
584 | SmallVectorImpl<char> *SearchPath, | |
585 | SmallVectorImpl<char> *RelativePath) { | |
586 | assert(ContextFileEnt && "No context file?"); | |
587 | ||
588 | // Framework names must have a '/' in the filename. Find it. | |
589 | // FIXME: Should we permit '\' on Windows? | |
590 | size_t SlashPos = Filename.find('/'); | |
591 | if (SlashPos == StringRef::npos) return 0; | |
592 | ||
593 | // Look up the base framework name of the ContextFileEnt. | |
594 | const char *ContextName = ContextFileEnt->getName(); | |
595 | ||
596 | // If the context info wasn't a framework, couldn't be a subframework. | |
597 | const unsigned DotFrameworkLen = 10; | |
598 | const char *FrameworkPos = strstr(ContextName, ".framework"); | |
599 | if (FrameworkPos == 0 || | |
600 | (FrameworkPos[DotFrameworkLen] != '/' && | |
601 | FrameworkPos[DotFrameworkLen] != '\\')) | |
602 | return 0; | |
603 | ||
604 | SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1); | |
605 | ||
606 | // Append Frameworks/HIToolbox.framework/ | |
607 | FrameworkName += "Frameworks/"; | |
608 | FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); | |
609 | FrameworkName += ".framework/"; | |
610 | ||
611 | llvm::StringMapEntry<FrameworkCacheEntry> &CacheLookup = | |
612 | FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); | |
613 | ||
614 | // Some other location? | |
615 | if (CacheLookup.getValue().Directory && | |
616 | CacheLookup.getKeyLength() == FrameworkName.size() && | |
617 | memcmp(CacheLookup.getKeyData(), &FrameworkName[0], | |
618 | CacheLookup.getKeyLength()) != 0) | |
619 | return 0; | |
620 | ||
621 | // Cache subframework. | |
622 | if (CacheLookup.getValue().Directory == 0) { | |
623 | ++NumSubFrameworkLookups; | |
624 | ||
625 | // If the framework dir doesn't exist, we fail. | |
626 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); | |
627 | if (Dir == 0) return 0; | |
628 | ||
629 | // Otherwise, if it does, remember that this is the right direntry for this | |
630 | // framework. | |
631 | CacheLookup.getValue().Directory = Dir; | |
632 | } | |
633 | ||
634 | const FileEntry *FE = 0; | |
635 | ||
636 | if (RelativePath != NULL) { | |
637 | RelativePath->clear(); | |
638 | RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); | |
639 | } | |
640 | ||
641 | // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" | |
642 | SmallString<1024> HeadersFilename(FrameworkName); | |
643 | HeadersFilename += "Headers/"; | |
644 | if (SearchPath != NULL) { | |
645 | SearchPath->clear(); | |
646 | // Without trailing '/'. | |
647 | SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); | |
648 | } | |
649 | ||
650 | HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); | |
651 | if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { | |
652 | ||
653 | // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" | |
654 | HeadersFilename = FrameworkName; | |
655 | HeadersFilename += "PrivateHeaders/"; | |
656 | if (SearchPath != NULL) { | |
657 | SearchPath->clear(); | |
658 | // Without trailing '/'. | |
659 | SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); | |
660 | } | |
661 | ||
662 | HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); | |
663 | if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) | |
664 | return 0; | |
665 | } | |
666 | ||
667 | // This file is a system header or C++ unfriendly if the old file is. | |
668 | // | |
669 | // Note that the temporary 'DirInfo' is required here, as either call to | |
670 | // getFileInfo could resize the vector and we don't want to rely on order | |
671 | // of evaluation. | |
672 | unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; | |
673 | getFileInfo(FE).DirInfo = DirInfo; | |
674 | return FE; | |
675 | } | |
676 | ||
677 | /// \brief Helper static function to normalize a path for injection into | |
678 | /// a synthetic header. | |
679 | /*static*/ std::string | |
680 | HeaderSearch::NormalizeDashIncludePath(StringRef File, FileManager &FileMgr) { | |
681 | // Implicit include paths should be resolved relative to the current | |
682 | // working directory first, and then use the regular header search | |
683 | // mechanism. The proper way to handle this is to have the | |
684 | // predefines buffer located at the current working directory, but | |
685 | // it has no file entry. For now, workaround this by using an | |
686 | // absolute path if we find the file here, and otherwise letting | |
687 | // header search handle it. | |
688 | SmallString<128> Path(File); | |
689 | llvm::sys::fs::make_absolute(Path); | |
690 | bool exists; | |
691 | if (llvm::sys::fs::exists(Path.str(), exists) || !exists) | |
692 | Path = File; | |
693 | else if (exists) | |
694 | FileMgr.getFile(File); | |
695 | ||
696 | return Lexer::Stringify(Path.str()); | |
697 | } | |
698 | ||
699 | //===----------------------------------------------------------------------===// | |
700 | // File Info Management. | |
701 | //===----------------------------------------------------------------------===// | |
702 | ||
703 | /// \brief Merge the header file info provided by \p OtherHFI into the current | |
704 | /// header file info (\p HFI) | |
705 | static void mergeHeaderFileInfo(HeaderFileInfo &HFI, | |
706 | const HeaderFileInfo &OtherHFI) { | |
707 | HFI.isImport |= OtherHFI.isImport; | |
708 | HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; | |
709 | HFI.NumIncludes += OtherHFI.NumIncludes; | |
710 | ||
711 | if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { | |
712 | HFI.ControllingMacro = OtherHFI.ControllingMacro; | |
713 | HFI.ControllingMacroID = OtherHFI.ControllingMacroID; | |
714 | } | |
715 | ||
716 | if (OtherHFI.External) { | |
717 | HFI.DirInfo = OtherHFI.DirInfo; | |
718 | HFI.External = OtherHFI.External; | |
719 | HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; | |
720 | } | |
721 | ||
722 | if (HFI.Framework.empty()) | |
723 | HFI.Framework = OtherHFI.Framework; | |
724 | ||
725 | HFI.Resolved = true; | |
726 | } | |
727 | ||
728 | /// getFileInfo - Return the HeaderFileInfo structure for the specified | |
729 | /// FileEntry. | |
730 | HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { | |
731 | if (FE->getUID() >= FileInfo.size()) | |
732 | FileInfo.resize(FE->getUID()+1); | |
733 | ||
734 | HeaderFileInfo &HFI = FileInfo[FE->getUID()]; | |
735 | if (ExternalSource && !HFI.Resolved) | |
736 | mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE)); | |
737 | return HFI; | |
738 | } | |
739 | ||
740 | bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { | |
741 | // Check if we've ever seen this file as a header. | |
742 | if (File->getUID() >= FileInfo.size()) | |
743 | return false; | |
744 | ||
745 | // Resolve header file info from the external source, if needed. | |
746 | HeaderFileInfo &HFI = FileInfo[File->getUID()]; | |
747 | if (ExternalSource && !HFI.Resolved) | |
748 | mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File)); | |
749 | ||
750 | return HFI.isPragmaOnce || HFI.ControllingMacro || HFI.ControllingMacroID; | |
751 | } | |
752 | ||
753 | void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { | |
754 | if (UID >= FileInfo.size()) | |
755 | FileInfo.resize(UID+1); | |
756 | HFI.Resolved = true; | |
757 | FileInfo[UID] = HFI; | |
758 | } | |
759 | ||
760 | bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ | |
761 | ++NumIncluded; // Count # of attempted #includes. | |
762 | ||
763 | // Get information about this file. | |
764 | HeaderFileInfo &FileInfo = getFileInfo(File); | |
765 | ||
766 | // If this is a #import directive, check that we have not already imported | |
767 | // this header. | |
768 | if (isImport) { | |
769 | // If this has already been imported, don't import it again. | |
770 | FileInfo.isImport = true; | |
771 | ||
772 | // Has this already been #import'ed or #include'd? | |
773 | if (FileInfo.NumIncludes) return false; | |
774 | } else { | |
775 | // Otherwise, if this is a #include of a file that was previously #import'd | |
776 | // or if this is the second #include of a #pragma once file, ignore it. | |
777 | if (FileInfo.isImport) | |
778 | return false; | |
779 | } | |
780 | ||
781 | // Next, check to see if the file is wrapped with #ifndef guards. If so, and | |
782 | // if the macro that guards it is defined, we know the #include has no effect. | |
783 | if (const IdentifierInfo *ControllingMacro | |
784 | = FileInfo.getControllingMacro(ExternalLookup)) | |
785 | if (ControllingMacro->hasMacroDefinition()) { | |
786 | ++NumMultiIncludeFileOptzn; | |
787 | return false; | |
788 | } | |
789 | ||
790 | // Increment the number of times this file has been included. | |
791 | ++FileInfo.NumIncludes; | |
792 | ||
793 | return true; | |
794 | } | |
795 | ||
796 | size_t HeaderSearch::getTotalMemory() const { | |
797 | return SearchDirs.capacity() | |
798 | + llvm::capacity_in_bytes(FileInfo) | |
799 | + llvm::capacity_in_bytes(HeaderMaps) | |
800 | + LookupFileCache.getAllocator().getTotalMemory() | |
801 | + FrameworkMap.getAllocator().getTotalMemory(); | |
802 | } | |
803 | ||
804 | StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { | |
805 | return FrameworkNames.GetOrCreateValue(Framework).getKey(); | |
806 | } | |
807 | ||
808 | bool HeaderSearch::hasModuleMap(StringRef FileName, | |
809 | const DirectoryEntry *Root) { | |
810 | llvm::SmallVector<const DirectoryEntry *, 2> FixUpDirectories; | |
811 | ||
812 | StringRef DirName = FileName; | |
813 | do { | |
814 | // Get the parent directory name. | |
815 | DirName = llvm::sys::path::parent_path(DirName); | |
816 | if (DirName.empty()) | |
817 | return false; | |
818 | ||
819 | // Determine whether this directory exists. | |
820 | const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); | |
821 | if (!Dir) | |
822 | return false; | |
823 | ||
824 | // Try to load the module map file in this directory. | |
825 | switch (loadModuleMapFile(Dir)) { | |
826 | case LMM_NewlyLoaded: | |
827 | case LMM_AlreadyLoaded: | |
828 | // Success. All of the directories we stepped through inherit this module | |
829 | // map file. | |
830 | for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I) | |
831 | DirectoryHasModuleMap[FixUpDirectories[I]] = true; | |
832 | ||
833 | return true; | |
834 | ||
835 | case LMM_NoDirectory: | |
836 | case LMM_InvalidModuleMap: | |
837 | break; | |
838 | } | |
839 | ||
840 | // If we hit the top of our search, we're done. | |
841 | if (Dir == Root) | |
842 | return false; | |
843 | ||
844 | // Keep track of all of the directories we checked, so we can mark them as | |
845 | // having module maps if we eventually do find a module map. | |
846 | FixUpDirectories.push_back(Dir); | |
847 | } while (true); | |
848 | } | |
849 | ||
850 | Module *HeaderSearch::findModuleForHeader(const FileEntry *File) { | |
851 | if (Module *Mod = ModMap.findModuleForHeader(File)) | |
852 | return Mod; | |
853 | ||
854 | return 0; | |
855 | } | |
856 | ||
857 | bool HeaderSearch::loadModuleMapFile(const FileEntry *File) { | |
858 | const DirectoryEntry *Dir = File->getDir(); | |
859 | ||
860 | llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir | |
861 | = DirectoryHasModuleMap.find(Dir); | |
862 | if (KnownDir != DirectoryHasModuleMap.end()) | |
863 | return !KnownDir->second; | |
864 | ||
865 | bool Result = ModMap.parseModuleMapFile(File); | |
866 | if (!Result && llvm::sys::path::filename(File->getName()) == "module.map") { | |
867 | // If the file we loaded was a module.map, look for the corresponding | |
868 | // module_private.map. | |
869 | SmallString<128> PrivateFilename(Dir->getName()); | |
870 | llvm::sys::path::append(PrivateFilename, "module_private.map"); | |
871 | if (const FileEntry *PrivateFile = FileMgr.getFile(PrivateFilename)) | |
872 | Result = ModMap.parseModuleMapFile(PrivateFile); | |
873 | } | |
874 | ||
875 | DirectoryHasModuleMap[Dir] = !Result; | |
876 | return Result; | |
877 | } | |
878 | ||
879 | Module *HeaderSearch::loadFrameworkModule(StringRef Name, | |
880 | const DirectoryEntry *Dir, | |
881 | bool IsSystem) { | |
882 | if (Module *Module = ModMap.findModule(Name)) | |
883 | return Module; | |
884 | ||
885 | // Try to load a module map file. | |
886 | switch (loadModuleMapFile(Dir)) { | |
887 | case LMM_InvalidModuleMap: | |
888 | break; | |
889 | ||
890 | case LMM_AlreadyLoaded: | |
891 | case LMM_NoDirectory: | |
892 | return 0; | |
893 | ||
894 | case LMM_NewlyLoaded: | |
895 | return ModMap.findModule(Name); | |
896 | } | |
897 | ||
898 | // The top-level framework directory, from which we'll infer a framework | |
899 | // module. | |
900 | const DirectoryEntry *TopFrameworkDir = Dir; | |
901 | ||
902 | // The path from the module we're actually looking for back to the top-level | |
903 | // framework name. | |
904 | llvm::SmallVector<StringRef, 2> SubmodulePath; | |
905 | SubmodulePath.push_back(Name); | |
906 | ||
907 | // Walk the directory structure to find any enclosing frameworks. | |
908 | #ifdef LLVM_ON_UNIX | |
909 | // Note: as an egregious but useful hack we use the real path here, because | |
910 | // frameworks moving from top-level frameworks to embedded frameworks tend | |
911 | // to be symlinked from the top-level location to the embedded location, | |
912 | // and we need to resolve lookups as if we had found the embedded location. | |
913 | char RealDirName[PATH_MAX]; | |
914 | StringRef DirName; | |
915 | if (realpath(Dir->getName(), RealDirName)) | |
916 | DirName = RealDirName; | |
917 | else | |
918 | DirName = Dir->getName(); | |
919 | #else | |
920 | StringRef DirName = Dir->getName(); | |
921 | #endif | |
922 | do { | |
923 | // Get the parent directory name. | |
924 | DirName = llvm::sys::path::parent_path(DirName); | |
925 | if (DirName.empty()) | |
926 | break; | |
927 | ||
928 | // Determine whether this directory exists. | |
929 | Dir = FileMgr.getDirectory(DirName); | |
930 | if (!Dir) | |
931 | break; | |
932 | ||
933 | // If this is a framework directory, then we're a subframework of this | |
934 | // framework. | |
935 | if (llvm::sys::path::extension(DirName) == ".framework") { | |
936 | SubmodulePath.push_back(llvm::sys::path::stem(DirName)); | |
937 | TopFrameworkDir = Dir; | |
938 | } | |
939 | } while (true); | |
940 | ||
941 | // Try to infer a module map from the top-level framework directory. | |
942 | Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(), | |
943 | TopFrameworkDir, | |
944 | IsSystem, | |
945 | /*Parent=*/0); | |
946 | ||
947 | // Follow the submodule path to find the requested (sub)framework module | |
948 | // within the top-level framework module. | |
949 | SubmodulePath.pop_back(); | |
950 | while (!SubmodulePath.empty() && Result) { | |
951 | Result = ModMap.lookupModuleQualified(SubmodulePath.back(), Result); | |
952 | SubmodulePath.pop_back(); | |
953 | } | |
954 | return Result; | |
955 | } | |
956 | ||
957 | ||
958 | HeaderSearch::LoadModuleMapResult | |
959 | HeaderSearch::loadModuleMapFile(StringRef DirName) { | |
960 | if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) | |
961 | return loadModuleMapFile(Dir); | |
962 | ||
963 | return LMM_NoDirectory; | |
964 | } | |
965 | ||
966 | HeaderSearch::LoadModuleMapResult | |
967 | HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir) { | |
968 | llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir | |
969 | = DirectoryHasModuleMap.find(Dir); | |
970 | if (KnownDir != DirectoryHasModuleMap.end()) | |
971 | return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap; | |
972 | ||
973 | SmallString<128> ModuleMapFileName; | |
974 | ModuleMapFileName += Dir->getName(); | |
975 | unsigned ModuleMapDirNameLen = ModuleMapFileName.size(); | |
976 | llvm::sys::path::append(ModuleMapFileName, "module.map"); | |
977 | if (const FileEntry *ModuleMapFile = FileMgr.getFile(ModuleMapFileName)) { | |
978 | // We have found a module map file. Try to parse it. | |
979 | if (ModMap.parseModuleMapFile(ModuleMapFile)) { | |
980 | // No suitable module map. | |
981 | DirectoryHasModuleMap[Dir] = false; | |
982 | return LMM_InvalidModuleMap; | |
983 | } | |
984 | ||
985 | // This directory has a module map. | |
986 | DirectoryHasModuleMap[Dir] = true; | |
987 | ||
988 | // Check whether there is a private module map that we need to load as well. | |
989 | ModuleMapFileName.erase(ModuleMapFileName.begin() + ModuleMapDirNameLen, | |
990 | ModuleMapFileName.end()); | |
991 | llvm::sys::path::append(ModuleMapFileName, "module_private.map"); | |
992 | if (const FileEntry *PrivateModuleMapFile | |
993 | = FileMgr.getFile(ModuleMapFileName)) { | |
994 | if (ModMap.parseModuleMapFile(PrivateModuleMapFile)) { | |
995 | // No suitable module map. | |
996 | DirectoryHasModuleMap[Dir] = false; | |
997 | return LMM_InvalidModuleMap; | |
998 | } | |
999 | } | |
1000 | ||
1001 | return LMM_NewlyLoaded; | |
1002 | } | |
1003 | ||
1004 | // No suitable module map. | |
1005 | DirectoryHasModuleMap[Dir] = false; | |
1006 | return LMM_InvalidModuleMap; | |
1007 | } | |
1008 | ||
1009 | void HeaderSearch::collectAllModules(llvm::SmallVectorImpl<Module *> &Modules) { | |
1010 | Modules.clear(); | |
1011 | ||
1012 | // Load module maps for each of the header search directories. | |
1013 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { | |
1014 | if (SearchDirs[Idx].isFramework()) { | |
1015 | llvm::error_code EC; | |
1016 | SmallString<128> DirNative; | |
1017 | llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(), | |
1018 | DirNative); | |
1019 | ||
1020 | // Search each of the ".framework" directories to load them as modules. | |
1021 | bool IsSystem = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; | |
1022 | for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; | |
1023 | Dir != DirEnd && !EC; Dir.increment(EC)) { | |
1024 | if (llvm::sys::path::extension(Dir->path()) != ".framework") | |
1025 | continue; | |
1026 | ||
1027 | const DirectoryEntry *FrameworkDir = FileMgr.getDirectory(Dir->path()); | |
1028 | if (!FrameworkDir) | |
1029 | continue; | |
1030 | ||
1031 | // Load this framework module. | |
1032 | loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, | |
1033 | IsSystem); | |
1034 | } | |
1035 | continue; | |
1036 | } | |
1037 | ||
1038 | // FIXME: Deal with header maps. | |
1039 | if (SearchDirs[Idx].isHeaderMap()) | |
1040 | continue; | |
1041 | ||
1042 | // Try to load a module map file for the search directory. | |
1043 | loadModuleMapFile(SearchDirs[Idx].getDir()); | |
1044 | ||
1045 | // Try to load module map files for immediate subdirectories of this search | |
1046 | // directory. | |
1047 | llvm::error_code EC; | |
1048 | SmallString<128> DirNative; | |
1049 | llvm::sys::path::native(SearchDirs[Idx].getDir()->getName(), DirNative); | |
1050 | for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; | |
1051 | Dir != DirEnd && !EC; Dir.increment(EC)) { | |
1052 | loadModuleMapFile(Dir->path()); | |
1053 | } | |
1054 | } | |
1055 | ||
1056 | // Populate the list of modules. | |
1057 | for (ModuleMap::module_iterator M = ModMap.module_begin(), | |
1058 | MEnd = ModMap.module_end(); | |
1059 | M != MEnd; ++M) { | |
1060 | Modules.push_back(M->getValue()); | |
1061 | } | |
1062 | } |