1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/Lex/HeaderSearch.h" |
14 | #include "clang/Basic/Diagnostic.h" |
15 | #include "clang/Basic/FileManager.h" |
16 | #include "clang/Basic/IdentifierTable.h" |
17 | #include "clang/Basic/Module.h" |
18 | #include "clang/Basic/SourceManager.h" |
19 | #include "clang/Lex/DirectoryLookup.h" |
20 | #include "clang/Lex/ExternalPreprocessorSource.h" |
21 | #include "clang/Lex/HeaderMap.h" |
22 | #include "clang/Lex/HeaderSearchOptions.h" |
23 | #include "clang/Lex/LexDiagnostic.h" |
24 | #include "clang/Lex/ModuleMap.h" |
25 | #include "clang/Lex/Preprocessor.h" |
26 | #include "llvm/ADT/APInt.h" |
27 | #include "llvm/ADT/Hashing.h" |
28 | #include "llvm/ADT/SmallString.h" |
29 | #include "llvm/ADT/SmallVector.h" |
30 | #include "llvm/ADT/StringRef.h" |
31 | #include "llvm/Support/Allocator.h" |
32 | #include "llvm/Support/Capacity.h" |
33 | #include "llvm/Support/ErrorHandling.h" |
34 | #include "llvm/Support/FileSystem.h" |
35 | #include "llvm/Support/Path.h" |
36 | #include "llvm/Support/VirtualFileSystem.h" |
37 | #include <algorithm> |
38 | #include <cassert> |
39 | #include <cstddef> |
40 | #include <cstdio> |
41 | #include <cstring> |
42 | #include <string> |
43 | #include <system_error> |
44 | #include <utility> |
45 | |
46 | using namespace clang; |
47 | |
48 | const IdentifierInfo * |
49 | HeaderFileInfo::(ExternalPreprocessorSource *External) { |
50 | if (ControllingMacro) { |
51 | if (ControllingMacro->isOutOfDate()) { |
52 | (0) . __assert_fail ("External && \"We must have an external source if we have a \" \"controlling macro that is out of date.\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 53, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(External && "We must have an external source if we have a " |
53 | (0) . __assert_fail ("External && \"We must have an external source if we have a \" \"controlling macro that is out of date.\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 53, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "controlling macro that is out of date."); |
54 | External->updateOutOfDateIdentifier( |
55 | *const_cast<IdentifierInfo *>(ControllingMacro)); |
56 | } |
57 | return ControllingMacro; |
58 | } |
59 | |
60 | if (!ControllingMacroID || !External) |
61 | return nullptr; |
62 | |
63 | ControllingMacro = External->GetIdentifier(ControllingMacroID); |
64 | return ControllingMacro; |
65 | } |
66 | |
67 | ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default; |
68 | |
69 | HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, |
70 | SourceManager &SourceMgr, DiagnosticsEngine &Diags, |
71 | const LangOptions &LangOpts, |
72 | const TargetInfo *Target) |
73 | : HSOpts(std::move(HSOpts)), Diags(Diags), |
74 | FileMgr(SourceMgr.getFileManager()), FrameworkMap(64), |
75 | ModMap(SourceMgr, Diags, LangOpts, Target, *this) {} |
76 | |
77 | void HeaderSearch::() { |
78 | fprintf(stderr, "\n*** HeaderSearch Stats:\n"); |
79 | fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); |
80 | unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; |
81 | for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { |
82 | NumOnceOnlyFiles += FileInfo[i].isImport; |
83 | if (MaxNumIncludes < FileInfo[i].NumIncludes) |
84 | MaxNumIncludes = FileInfo[i].NumIncludes; |
85 | NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; |
86 | } |
87 | fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); |
88 | fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); |
89 | fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); |
90 | |
91 | fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); |
92 | fprintf(stderr, " %d #includes skipped due to" |
93 | " the multi-include optimization.\n", NumMultiIncludeFileOptzn); |
94 | |
95 | fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); |
96 | fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); |
97 | } |
98 | |
99 | |
100 | |
101 | const HeaderMap *HeaderSearch::(const FileEntry *FE) { |
102 | |
103 | |
104 | if (!HeaderMaps.empty()) { |
105 | for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) |
106 | |
107 | |
108 | if (HeaderMaps[i].first == FE) |
109 | return HeaderMaps[i].second.get(); |
110 | } |
111 | |
112 | if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) { |
113 | HeaderMaps.emplace_back(FE, std::move(HM)); |
114 | return HeaderMaps.back().second.get(); |
115 | } |
116 | |
117 | return nullptr; |
118 | } |
119 | |
120 | |
121 | void HeaderSearch::( |
122 | SmallVectorImpl<std::string> &Names) const { |
123 | for (auto &HM : HeaderMaps) |
124 | Names.push_back(HM.first->getName()); |
125 | } |
126 | |
127 | std::string HeaderSearch::(Module *Module) { |
128 | const FileEntry *ModuleMap = |
129 | getModuleMap().getModuleMapFileForUniquing(Module); |
130 | return getCachedModuleFileName(Module->Name, ModuleMap->getName()); |
131 | } |
132 | |
133 | std::string HeaderSearch::(StringRef ModuleName, |
134 | bool FileMapOnly) { |
135 | |
136 | auto i (HSOpts->PrebuiltModuleFiles.find(ModuleName)); |
137 | if (i != HSOpts->PrebuiltModuleFiles.end()) |
138 | return i->second; |
139 | |
140 | if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty()) |
141 | return {}; |
142 | |
143 | |
144 | |
145 | for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { |
146 | SmallString<256> Result(Dir); |
147 | llvm::sys::fs::make_absolute(Result); |
148 | llvm::sys::path::append(Result, ModuleName + ".pcm"); |
149 | if (getFileMgr().getFile(Result.str())) |
150 | return Result.str().str(); |
151 | } |
152 | return {}; |
153 | } |
154 | |
155 | std::string HeaderSearch::(StringRef ModuleName, |
156 | StringRef ModuleMapPath) { |
157 | |
158 | |
159 | if (getModuleCachePath().empty()) |
160 | return {}; |
161 | |
162 | SmallString<256> Result(getModuleCachePath()); |
163 | llvm::sys::fs::make_absolute(Result); |
164 | |
165 | if (HSOpts->DisableModuleHash) { |
166 | llvm::sys::path::append(Result, ModuleName + ".pcm"); |
167 | } else { |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | std::string Parent = llvm::sys::path::parent_path(ModuleMapPath); |
176 | if (Parent.empty()) |
177 | Parent = "."; |
178 | auto *Dir = FileMgr.getDirectory(Parent); |
179 | if (!Dir) |
180 | return {}; |
181 | auto DirName = FileMgr.getCanonicalName(Dir); |
182 | auto FileName = llvm::sys::path::filename(ModuleMapPath); |
183 | |
184 | llvm::hash_code Hash = |
185 | llvm::hash_combine(DirName.lower(), FileName.lower()); |
186 | |
187 | SmallString<128> HashStr; |
188 | llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, ); |
189 | llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm"); |
190 | } |
191 | return Result.str().str(); |
192 | } |
193 | |
194 | Module *HeaderSearch::(StringRef ModuleName, bool AllowSearch, |
195 | bool ) { |
196 | |
197 | Module *Module = ModMap.findModule(ModuleName); |
198 | if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) |
199 | return Module; |
200 | |
201 | StringRef SearchName = ModuleName; |
202 | Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | if (!Module && SearchName.consume_back("_Private")) |
213 | Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); |
214 | if (!Module && SearchName.consume_back("Private")) |
215 | Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); |
216 | return Module; |
217 | } |
218 | |
219 | Module *HeaderSearch::(StringRef ModuleName, StringRef SearchName, |
220 | bool ) { |
221 | Module *Module = nullptr; |
222 | |
223 | |
224 | |
225 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { |
226 | if (SearchDirs[Idx].isFramework()) { |
227 | |
228 | |
229 | |
230 | SmallString<128> FrameworkDirName; |
231 | FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName(); |
232 | llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); |
233 | if (const DirectoryEntry *FrameworkDir |
234 | = FileMgr.getDirectory(FrameworkDirName)) { |
235 | bool IsSystem |
236 | = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; |
237 | Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); |
238 | if (Module) |
239 | break; |
240 | } |
241 | } |
242 | |
243 | |
244 | |
245 | |
246 | if (!SearchDirs[Idx].isNormalDir()) |
247 | continue; |
248 | |
249 | bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory(); |
250 | |
251 | if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, |
252 | ) == LMM_NewlyLoaded) { |
253 | |
254 | |
255 | Module = ModMap.findModule(ModuleName); |
256 | if (Module) |
257 | break; |
258 | } |
259 | |
260 | |
261 | |
262 | SmallString<128> NestedModuleMapDirName; |
263 | NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName(); |
264 | llvm::sys::path::append(NestedModuleMapDirName, ModuleName); |
265 | if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, |
266 | ) == LMM_NewlyLoaded){ |
267 | |
268 | Module = ModMap.findModule(ModuleName); |
269 | if (Module) |
270 | break; |
271 | } |
272 | |
273 | |
274 | |
275 | if (SearchDirs[Idx].haveSearchedAllModuleMaps()) |
276 | continue; |
277 | |
278 | |
279 | |
280 | if (AllowExtraModuleMapSearch) |
281 | loadSubdirectoryModuleMaps(SearchDirs[Idx]); |
282 | |
283 | |
284 | Module = ModMap.findModule(ModuleName); |
285 | if (Module) |
286 | break; |
287 | } |
288 | |
289 | return Module; |
290 | } |
291 | |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | |
298 | StringRef DirectoryLookup::getName() const { |
299 | if (isNormalDir()) |
300 | return getDir()->getName(); |
301 | if (isFramework()) |
302 | return getFrameworkDir()->getName(); |
303 | (0) . __assert_fail ("isHeaderMap() && \"Unknown DirectoryLookup\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 303, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isHeaderMap() && "Unknown DirectoryLookup"); |
304 | return getHeaderMap()->getFileName(); |
305 | } |
306 | |
307 | const FileEntry *HeaderSearch::getFileAndSuggestModule( |
308 | StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir, |
309 | bool , Module *RequestingModule, |
310 | ModuleMap::KnownHeader *SuggestedModule) { |
311 | |
312 | |
313 | const FileEntry *File = getFileMgr().getFile(FileName, ); |
314 | if (!File) |
315 | return nullptr; |
316 | |
317 | |
318 | if (!findUsableModuleForHeader(File, Dir ? Dir : File->getDir(), |
319 | RequestingModule, SuggestedModule, |
320 | IsSystemHeaderDir)) |
321 | return nullptr; |
322 | |
323 | return File; |
324 | } |
325 | |
326 | |
327 | |
328 | const FileEntry *DirectoryLookup::( |
329 | StringRef &Filename, |
330 | HeaderSearch &HS, |
331 | SourceLocation IncludeLoc, |
332 | SmallVectorImpl<char> *SearchPath, |
333 | SmallVectorImpl<char> *RelativePath, |
334 | Module *RequestingModule, |
335 | ModuleMap::KnownHeader *SuggestedModule, |
336 | bool &InUserSpecifiedSystemFramework, |
337 | bool &IsFrameworkFound, |
338 | bool &HasBeenMapped, |
339 | SmallVectorImpl<char> &MappedName) const { |
340 | InUserSpecifiedSystemFramework = false; |
341 | HasBeenMapped = false; |
342 | |
343 | SmallString<1024> TmpDir; |
344 | if (isNormalDir()) { |
345 | |
346 | TmpDir = getDir()->getName(); |
347 | llvm::sys::path::append(TmpDir, Filename); |
348 | if (SearchPath) { |
349 | StringRef SearchPathRef(getDir()->getName()); |
350 | SearchPath->clear(); |
351 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
352 | } |
353 | if (RelativePath) { |
354 | RelativePath->clear(); |
355 | RelativePath->append(Filename.begin(), Filename.end()); |
356 | } |
357 | |
358 | return HS.getFileAndSuggestModule(TmpDir, IncludeLoc, getDir(), |
359 | isSystemHeaderDirectory(), |
360 | RequestingModule, SuggestedModule); |
361 | } |
362 | |
363 | if (isFramework()) |
364 | return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, |
365 | RequestingModule, SuggestedModule, |
366 | InUserSpecifiedSystemFramework, IsFrameworkFound); |
367 | |
368 | (0) . __assert_fail ("isHeaderMap() && \"Unknown directory lookup\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 368, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isHeaderMap() && "Unknown directory lookup"); |
369 | const HeaderMap *HM = getHeaderMap(); |
370 | SmallString<1024> Path; |
371 | StringRef Dest = HM->lookupFilename(Filename, Path); |
372 | if (Dest.empty()) |
373 | return nullptr; |
374 | |
375 | const FileEntry *Result; |
376 | |
377 | |
378 | |
379 | |
380 | if (llvm::sys::path::is_relative(Dest)) { |
381 | MappedName.clear(); |
382 | MappedName.append(Dest.begin(), Dest.end()); |
383 | Filename = StringRef(MappedName.begin(), MappedName.size()); |
384 | HasBeenMapped = true; |
385 | Result = HM->LookupFile(Filename, HS.getFileMgr()); |
386 | } else { |
387 | Result = HS.getFileMgr().getFile(Dest); |
388 | } |
389 | |
390 | if (Result) { |
391 | if (SearchPath) { |
392 | StringRef SearchPathRef(getName()); |
393 | SearchPath->clear(); |
394 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
395 | } |
396 | if (RelativePath) { |
397 | RelativePath->clear(); |
398 | RelativePath->append(Filename.begin(), Filename.end()); |
399 | } |
400 | } |
401 | return Result; |
402 | } |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | |
410 | static const DirectoryEntry * |
411 | getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, |
412 | SmallVectorImpl<std::string> &SubmodulePath) { |
413 | (0) . __assert_fail ("llvm..sys..path..extension(DirName) == \".framework\" && \"Not a framework directory\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 414, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(llvm::sys::path::extension(DirName) == ".framework" && |
414 | (0) . __assert_fail ("llvm..sys..path..extension(DirName) == \".framework\" && \"Not a framework directory\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 414, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Not a framework directory"); |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | const DirectoryEntry *TopFrameworkDir = FileMgr.getDirectory(DirName); |
431 | DirName = FileMgr.getCanonicalName(TopFrameworkDir); |
432 | do { |
433 | |
434 | DirName = llvm::sys::path::parent_path(DirName); |
435 | if (DirName.empty()) |
436 | break; |
437 | |
438 | |
439 | const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); |
440 | if (!Dir) |
441 | break; |
442 | |
443 | |
444 | |
445 | if (llvm::sys::path::extension(DirName) == ".framework") { |
446 | SubmodulePath.push_back(llvm::sys::path::stem(DirName)); |
447 | TopFrameworkDir = Dir; |
448 | } |
449 | } while (true); |
450 | |
451 | return TopFrameworkDir; |
452 | } |
453 | |
454 | static bool needModuleLookup(Module *RequestingModule, |
455 | bool HasSuggestedModule) { |
456 | return HasSuggestedModule || |
457 | (RequestingModule && RequestingModule->NoUndeclaredIncludes); |
458 | } |
459 | |
460 | |
461 | |
462 | const FileEntry *DirectoryLookup::( |
463 | StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, |
464 | SmallVectorImpl<char> *RelativePath, Module *RequestingModule, |
465 | ModuleMap::KnownHeader *SuggestedModule, |
466 | bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const { |
467 | FileManager &FileMgr = HS.getFileMgr(); |
468 | |
469 | |
470 | size_t SlashPos = Filename.find('/'); |
471 | if (SlashPos == StringRef::npos) return nullptr; |
472 | |
473 | |
474 | |
475 | FrameworkCacheEntry &CacheEntry = |
476 | HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); |
477 | |
478 | |
479 | if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) |
480 | return nullptr; |
481 | |
482 | |
483 | |
484 | |
485 | SmallString<1024> FrameworkName; |
486 | FrameworkName += getFrameworkDir()->getName(); |
487 | if (FrameworkName.empty() || FrameworkName.back() != '/') |
488 | FrameworkName.push_back('/'); |
489 | |
490 | |
491 | StringRef ModuleName(Filename.begin(), SlashPos); |
492 | FrameworkName += ModuleName; |
493 | |
494 | |
495 | FrameworkName += ".framework/"; |
496 | |
497 | |
498 | if (!CacheEntry.Directory) { |
499 | HS.IncrementFrameworkLookupCount(); |
500 | |
501 | |
502 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); |
503 | if (!Dir) return nullptr; |
504 | |
505 | |
506 | |
507 | CacheEntry.Directory = getFrameworkDir(); |
508 | |
509 | |
510 | |
511 | if (getDirCharacteristic() == SrcMgr::C_User) { |
512 | SmallString<1024> SystemFrameworkMarker(FrameworkName); |
513 | SystemFrameworkMarker += ".system_framework"; |
514 | if (llvm::sys::fs::exists(SystemFrameworkMarker)) { |
515 | CacheEntry.IsUserSpecifiedSystemFramework = true; |
516 | } |
517 | } |
518 | } |
519 | |
520 | |
521 | InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; |
522 | IsFrameworkFound = CacheEntry.Directory; |
523 | |
524 | if (RelativePath) { |
525 | RelativePath->clear(); |
526 | RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); |
527 | } |
528 | |
529 | |
530 | unsigned OrigSize = FrameworkName.size(); |
531 | |
532 | FrameworkName += "Headers/"; |
533 | |
534 | if (SearchPath) { |
535 | SearchPath->clear(); |
536 | |
537 | SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); |
538 | } |
539 | |
540 | FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); |
541 | const FileEntry *FE = FileMgr.getFile(FrameworkName, |
542 | !SuggestedModule); |
543 | if (!FE) { |
544 | |
545 | const char *Private = "Private"; |
546 | FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, |
547 | Private+strlen(Private)); |
548 | if (SearchPath) |
549 | SearchPath->insert(SearchPath->begin()+OrigSize, Private, |
550 | Private+strlen(Private)); |
551 | |
552 | FE = FileMgr.getFile(FrameworkName, !SuggestedModule); |
553 | } |
554 | |
555 | |
556 | if (FE && needModuleLookup(RequestingModule, SuggestedModule)) { |
557 | |
558 | StringRef FrameworkPath = FE->getDir()->getName(); |
559 | bool FoundFramework = false; |
560 | do { |
561 | |
562 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath); |
563 | if (!Dir) |
564 | break; |
565 | |
566 | |
567 | |
568 | if (llvm::sys::path::extension(FrameworkPath) == ".framework") { |
569 | FoundFramework = true; |
570 | break; |
571 | } |
572 | |
573 | |
574 | FrameworkPath = llvm::sys::path::parent_path(FrameworkPath); |
575 | if (FrameworkPath.empty()) |
576 | break; |
577 | } while (true); |
578 | |
579 | bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; |
580 | if (FoundFramework) { |
581 | if (!HS.findUsableModuleForFrameworkHeader( |
582 | FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem)) |
583 | return nullptr; |
584 | } else { |
585 | if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule, |
586 | SuggestedModule, IsSystem)) |
587 | return nullptr; |
588 | } |
589 | } |
590 | return FE; |
591 | } |
592 | |
593 | void HeaderSearch::(const TargetInfo &Target) { |
594 | ModMap.setTarget(Target); |
595 | } |
596 | |
597 | |
598 | |
599 | |
600 | |
601 | |
602 | |
603 | |
604 | static bool (DiagnosticsEngine &Diags, |
605 | const FileEntry *MSFE, const FileEntry *FE, |
606 | SourceLocation IncludeLoc) { |
607 | if (MSFE && FE != MSFE) { |
608 | Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName(); |
609 | return true; |
610 | } |
611 | return false; |
612 | } |
613 | |
614 | static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { |
615 | assert(!Str.empty()); |
616 | char *CopyStr = Alloc.Allocate<char>(Str.size()+1); |
617 | std::copy(Str.begin(), Str.end(), CopyStr); |
618 | CopyStr[Str.size()] = '\0'; |
619 | return CopyStr; |
620 | } |
621 | |
622 | static bool isFrameworkStylePath(StringRef Path, bool &, |
623 | SmallVectorImpl<char> &FrameworkName) { |
624 | using namespace llvm::sys; |
625 | path::const_iterator I = path::begin(Path); |
626 | path::const_iterator E = path::end(Path); |
627 | IsPrivateHeader = false; |
628 | |
629 | |
630 | |
631 | |
632 | |
633 | |
634 | |
635 | |
636 | |
637 | int FoundComp = 0; |
638 | while (I != E) { |
639 | if (*I == "Headers") |
640 | ++FoundComp; |
641 | if (I->endswith(".framework")) { |
642 | FrameworkName.append(I->begin(), I->end()); |
643 | ++FoundComp; |
644 | } |
645 | if (*I == "PrivateHeaders") { |
646 | ++FoundComp; |
647 | IsPrivateHeader = true; |
648 | } |
649 | ++I; |
650 | } |
651 | |
652 | return !FrameworkName.empty() && FoundComp >= 2; |
653 | } |
654 | |
655 | static void |
656 | diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, |
657 | StringRef Includer, StringRef IncludeFilename, |
658 | const FileEntry *IncludeFE, bool isAngled = false, |
659 | bool = false) { |
660 | bool = false; |
661 | SmallString<128> FromFramework, ToFramework; |
662 | if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework)) |
663 | return; |
664 | bool = false; |
665 | bool IsIncludeeInFramework = isFrameworkStylePath( |
666 | IncludeFE->getName(), IsIncludeePrivateHeader, ToFramework); |
667 | |
668 | if (!isAngled && !FoundByHeaderMap) { |
669 | SmallString<128> NewInclude("<"); |
670 | if (IsIncludeeInFramework) { |
671 | NewInclude += StringRef(ToFramework).drop_back(10); |
672 | NewInclude += "/"; |
673 | } |
674 | NewInclude += IncludeFilename; |
675 | NewInclude += ">"; |
676 | Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) |
677 | << IncludeFilename |
678 | << FixItHint::CreateReplacement(IncludeLoc, NewInclude); |
679 | } |
680 | |
681 | |
682 | |
683 | |
684 | if (!IsIncluderPrivateHeader && IsIncludeeInFramework && |
685 | IsIncludeePrivateHeader && FromFramework == ToFramework) |
686 | Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public) |
687 | << IncludeFilename; |
688 | } |
689 | |
690 | |
691 | |
692 | |
693 | |
694 | |
695 | const FileEntry *HeaderSearch::( |
696 | StringRef Filename, SourceLocation IncludeLoc, bool isAngled, |
697 | const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, |
698 | ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, |
699 | SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, |
700 | Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, |
701 | bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, |
702 | bool BuildSystemModule) { |
703 | if (IsMapped) |
704 | *IsMapped = false; |
705 | |
706 | if (IsFrameworkFound) |
707 | *IsFrameworkFound = false; |
708 | |
709 | if (SuggestedModule) |
710 | *SuggestedModule = ModuleMap::KnownHeader(); |
711 | |
712 | |
713 | if (llvm::sys::path::is_absolute(Filename)) { |
714 | CurDir = nullptr; |
715 | |
716 | |
717 | if (FromDir) return nullptr; |
718 | |
719 | if (SearchPath) |
720 | SearchPath->clear(); |
721 | if (RelativePath) { |
722 | RelativePath->clear(); |
723 | RelativePath->append(Filename.begin(), Filename.end()); |
724 | } |
725 | |
726 | return getFileAndSuggestModule(Filename, IncludeLoc, nullptr, |
727 | , |
728 | RequestingModule, SuggestedModule); |
729 | } |
730 | |
731 | |
732 | const FileEntry *MSFE = nullptr; |
733 | ModuleMap::KnownHeader MSSuggestedModule; |
734 | |
735 | |
736 | |
737 | |
738 | |
739 | |
740 | if (!Includers.empty() && !isAngled && !NoCurDirSearch) { |
741 | SmallString<1024> TmpDir; |
742 | bool First = true; |
743 | for (const auto &IncluderAndDir : Includers) { |
744 | const FileEntry *Includer = IncluderAndDir.first; |
745 | |
746 | |
747 | |
748 | TmpDir = IncluderAndDir.second->getName(); |
749 | TmpDir.push_back('/'); |
750 | TmpDir.append(Filename.begin(), Filename.end()); |
751 | |
752 | |
753 | |
754 | |
755 | |
756 | |
757 | |
758 | |
759 | bool IncluderIsSystemHeader = |
760 | Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User : |
761 | BuildSystemModule; |
762 | if (const FileEntry *FE = getFileAndSuggestModule( |
763 | TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, |
764 | RequestingModule, SuggestedModule)) { |
765 | if (!Includer) { |
766 | (0) . __assert_fail ("First && \"only first includer can have no file\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 766, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(First && "only first includer can have no file"); |
767 | return FE; |
768 | } |
769 | |
770 | |
771 | |
772 | |
773 | |
774 | |
775 | |
776 | HeaderFileInfo &FromHFI = getFileInfo(Includer); |
777 | unsigned DirInfo = FromHFI.DirInfo; |
778 | bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; |
779 | StringRef Framework = FromHFI.Framework; |
780 | |
781 | HeaderFileInfo &ToHFI = getFileInfo(FE); |
782 | ToHFI.DirInfo = DirInfo; |
783 | ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; |
784 | ToHFI.Framework = Framework; |
785 | |
786 | if (SearchPath) { |
787 | StringRef SearchPathRef(IncluderAndDir.second->getName()); |
788 | SearchPath->clear(); |
789 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
790 | } |
791 | if (RelativePath) { |
792 | RelativePath->clear(); |
793 | RelativePath->append(Filename.begin(), Filename.end()); |
794 | } |
795 | if (First) { |
796 | diagnoseFrameworkInclude(Diags, IncludeLoc, |
797 | IncluderAndDir.second->getName(), Filename, |
798 | FE); |
799 | return FE; |
800 | } |
801 | |
802 | |
803 | |
804 | |
805 | if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) { |
806 | return FE; |
807 | } else { |
808 | MSFE = FE; |
809 | if (SuggestedModule) { |
810 | MSSuggestedModule = *SuggestedModule; |
811 | *SuggestedModule = ModuleMap::KnownHeader(); |
812 | } |
813 | break; |
814 | } |
815 | } |
816 | First = false; |
817 | } |
818 | } |
819 | |
820 | CurDir = nullptr; |
821 | |
822 | |
823 | unsigned i = isAngled ? AngledDirIdx : 0; |
824 | |
825 | |
826 | |
827 | if (FromDir) |
828 | i = FromDir-&SearchDirs[0]; |
829 | |
830 | |
831 | |
832 | |
833 | |
834 | LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; |
835 | |
836 | |
837 | |
838 | |
839 | if (!SkipCache && CacheLookup.StartIdx == i+1) { |
840 | |
841 | i = CacheLookup.HitIdx; |
842 | if (CacheLookup.MappedName) { |
843 | Filename = CacheLookup.MappedName; |
844 | if (IsMapped) |
845 | *IsMapped = true; |
846 | } |
847 | } else { |
848 | |
849 | |
850 | |
851 | CacheLookup.reset(+1); |
852 | } |
853 | |
854 | SmallString<64> MappedName; |
855 | |
856 | |
857 | for (; i != SearchDirs.size(); ++i) { |
858 | bool InUserSpecifiedSystemFramework = false; |
859 | bool HasBeenMapped = false; |
860 | bool IsFrameworkFoundInDir = false; |
861 | const FileEntry *FE = SearchDirs[i].LookupFile( |
862 | Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, |
863 | SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, |
864 | HasBeenMapped, MappedName); |
865 | if (HasBeenMapped) { |
866 | CacheLookup.MappedName = |
867 | copyString(Filename, LookupFileCache.getAllocator()); |
868 | if (IsMapped) |
869 | *IsMapped = true; |
870 | } |
871 | if (IsFrameworkFound) |
872 | *IsFrameworkFound |= IsFrameworkFoundInDir; |
873 | if (!FE) continue; |
874 | |
875 | CurDir = &SearchDirs[i]; |
876 | |
877 | |
878 | HeaderFileInfo &HFI = getFileInfo(FE); |
879 | HFI.DirInfo = CurDir->getDirCharacteristic(); |
880 | |
881 | |
882 | |
883 | |
884 | if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework) |
885 | HFI.DirInfo = SrcMgr::C_System; |
886 | |
887 | |
888 | |
889 | for (unsigned j = SystemHeaderPrefixes.size(); j; --j) { |
890 | if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) { |
891 | HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System |
892 | : SrcMgr::C_User; |
893 | break; |
894 | } |
895 | } |
896 | |
897 | |
898 | |
899 | if (CurDir->isIndexHeaderMap()) { |
900 | size_t SlashPos = Filename.find('/'); |
901 | if (SlashPos != StringRef::npos) { |
902 | HFI.IndexHeaderMapHeader = 1; |
903 | HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), |
904 | SlashPos)); |
905 | } |
906 | } |
907 | |
908 | if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { |
909 | if (SuggestedModule) |
910 | *SuggestedModule = MSSuggestedModule; |
911 | return MSFE; |
912 | } |
913 | |
914 | bool = !IsMapped ? false : *IsMapped; |
915 | if (!Includers.empty()) |
916 | diagnoseFrameworkInclude(Diags, IncludeLoc, |
917 | Includers.front().second->getName(), Filename, |
918 | FE, isAngled, FoundByHeaderMap); |
919 | |
920 | |
921 | CacheLookup.HitIdx = i; |
922 | return FE; |
923 | } |
924 | |
925 | |
926 | |
927 | |
928 | |
929 | if (!Includers.empty() && Includers.front().first && !isAngled && |
930 | Filename.find('/') == StringRef::npos) { |
931 | HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first); |
932 | if (IncludingHFI.IndexHeaderMapHeader) { |
933 | SmallString<128> ScratchFilename; |
934 | ScratchFilename += IncludingHFI.Framework; |
935 | ScratchFilename += '/'; |
936 | ScratchFilename += Filename; |
937 | |
938 | const FileEntry *FE = LookupFile( |
939 | ScratchFilename, IncludeLoc, , FromDir, CurDir, |
940 | Includers.front(), SearchPath, RelativePath, RequestingModule, |
941 | SuggestedModule, IsMapped, ); |
942 | |
943 | if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { |
944 | if (SuggestedModule) |
945 | *SuggestedModule = MSSuggestedModule; |
946 | return MSFE; |
947 | } |
948 | |
949 | LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; |
950 | CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx; |
951 | |
952 | return FE; |
953 | } |
954 | } |
955 | |
956 | if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) { |
957 | if (SuggestedModule) |
958 | *SuggestedModule = MSSuggestedModule; |
959 | return MSFE; |
960 | } |
961 | |
962 | |
963 | CacheLookup.HitIdx = SearchDirs.size(); |
964 | return nullptr; |
965 | } |
966 | |
967 | |
968 | |
969 | |
970 | |
971 | |
972 | const FileEntry *HeaderSearch:: |
973 | (StringRef Filename, |
974 | const FileEntry *ContextFileEnt, |
975 | SmallVectorImpl<char> *SearchPath, |
976 | SmallVectorImpl<char> *RelativePath, |
977 | Module *RequestingModule, |
978 | ModuleMap::KnownHeader *SuggestedModule) { |
979 | (0) . __assert_fail ("ContextFileEnt && \"No context file?\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 979, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(ContextFileEnt && "No context file?"); |
980 | |
981 | |
982 | |
983 | size_t SlashPos = Filename.find('/'); |
984 | if (SlashPos == StringRef::npos) return nullptr; |
985 | |
986 | |
987 | StringRef ContextName = ContextFileEnt->getName(); |
988 | |
989 | |
990 | const unsigned DotFrameworkLen = 10; |
991 | auto FrameworkPos = ContextName.find(".framework"); |
992 | if (FrameworkPos == StringRef::npos || |
993 | (ContextName[FrameworkPos + DotFrameworkLen] != '/' && |
994 | ContextName[FrameworkPos + DotFrameworkLen] != '\\')) |
995 | return nullptr; |
996 | |
997 | SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + |
998 | FrameworkPos + |
999 | DotFrameworkLen + 1); |
1000 | |
1001 | |
1002 | FrameworkName += "Frameworks/"; |
1003 | FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); |
1004 | FrameworkName += ".framework/"; |
1005 | |
1006 | auto &CacheLookup = |
1007 | *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos), |
1008 | FrameworkCacheEntry())).first; |
1009 | |
1010 | |
1011 | if (CacheLookup.second.Directory && |
1012 | CacheLookup.first().size() == FrameworkName.size() && |
1013 | memcmp(CacheLookup.first().data(), &FrameworkName[0], |
1014 | CacheLookup.first().size()) != 0) |
1015 | return nullptr; |
1016 | |
1017 | |
1018 | if (!CacheLookup.second.Directory) { |
1019 | ++NumSubFrameworkLookups; |
1020 | |
1021 | |
1022 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); |
1023 | if (!Dir) return nullptr; |
1024 | |
1025 | |
1026 | |
1027 | CacheLookup.second.Directory = Dir; |
1028 | } |
1029 | |
1030 | const FileEntry *FE = nullptr; |
1031 | |
1032 | if (RelativePath) { |
1033 | RelativePath->clear(); |
1034 | RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); |
1035 | } |
1036 | |
1037 | |
1038 | SmallString<1024> (FrameworkName); |
1039 | HeadersFilename += "Headers/"; |
1040 | if (SearchPath) { |
1041 | SearchPath->clear(); |
1042 | |
1043 | SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); |
1044 | } |
1045 | |
1046 | HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); |
1047 | if (!(FE = FileMgr.getFile(HeadersFilename, ))) { |
1048 | |
1049 | HeadersFilename = FrameworkName; |
1050 | HeadersFilename += "PrivateHeaders/"; |
1051 | if (SearchPath) { |
1052 | SearchPath->clear(); |
1053 | |
1054 | SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); |
1055 | } |
1056 | |
1057 | HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); |
1058 | if (!(FE = FileMgr.getFile(HeadersFilename, ))) |
1059 | return nullptr; |
1060 | } |
1061 | |
1062 | |
1063 | |
1064 | |
1065 | |
1066 | |
1067 | unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; |
1068 | getFileInfo(FE).DirInfo = DirInfo; |
1069 | |
1070 | FrameworkName.pop_back(); |
1071 | if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule, |
1072 | SuggestedModule, false)) |
1073 | return nullptr; |
1074 | |
1075 | return FE; |
1076 | } |
1077 | |
1078 | |
1079 | |
1080 | |
1081 | |
1082 | |
1083 | |
1084 | static void (HeaderFileInfo &HFI, |
1085 | const HeaderFileInfo &OtherHFI) { |
1086 | (0) . __assert_fail ("OtherHFI.External && \"expected to merge external HFI\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 1086, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(OtherHFI.External && "expected to merge external HFI"); |
1087 | |
1088 | HFI.isImport |= OtherHFI.isImport; |
1089 | HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; |
1090 | HFI.isModuleHeader |= OtherHFI.isModuleHeader; |
1091 | HFI.NumIncludes += OtherHFI.NumIncludes; |
1092 | |
1093 | if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { |
1094 | HFI.ControllingMacro = OtherHFI.ControllingMacro; |
1095 | HFI.ControllingMacroID = OtherHFI.ControllingMacroID; |
1096 | } |
1097 | |
1098 | HFI.DirInfo = OtherHFI.DirInfo; |
1099 | HFI.External = (!HFI.IsValid || HFI.External); |
1100 | HFI.IsValid = true; |
1101 | HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; |
1102 | |
1103 | if (HFI.Framework.empty()) |
1104 | HFI.Framework = OtherHFI.Framework; |
1105 | } |
1106 | |
1107 | |
1108 | |
1109 | HeaderFileInfo &HeaderSearch::(const FileEntry *FE) { |
1110 | if (FE->getUID() >= FileInfo.size()) |
1111 | FileInfo.resize(FE->getUID() + 1); |
1112 | |
1113 | HeaderFileInfo *HFI = &FileInfo[FE->getUID()]; |
1114 | |
1115 | if (ExternalSource && !HFI->Resolved) { |
1116 | HFI->Resolved = true; |
1117 | auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); |
1118 | |
1119 | HFI = &FileInfo[FE->getUID()]; |
1120 | if (ExternalHFI.External) |
1121 | mergeHeaderFileInfo(*HFI, ExternalHFI); |
1122 | } |
1123 | |
1124 | HFI->IsValid = true; |
1125 | |
1126 | |
1127 | HFI->External = false; |
1128 | return *HFI; |
1129 | } |
1130 | |
1131 | const HeaderFileInfo * |
1132 | HeaderSearch::(const FileEntry *FE, |
1133 | bool WantExternal) const { |
1134 | |
1135 | |
1136 | HeaderFileInfo *HFI; |
1137 | if (ExternalSource) { |
1138 | if (FE->getUID() >= FileInfo.size()) { |
1139 | if (!WantExternal) |
1140 | return nullptr; |
1141 | FileInfo.resize(FE->getUID() + 1); |
1142 | } |
1143 | |
1144 | HFI = &FileInfo[FE->getUID()]; |
1145 | if (!WantExternal && (!HFI->IsValid || HFI->External)) |
1146 | return nullptr; |
1147 | if (!HFI->Resolved) { |
1148 | HFI->Resolved = true; |
1149 | auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); |
1150 | |
1151 | HFI = &FileInfo[FE->getUID()]; |
1152 | if (ExternalHFI.External) |
1153 | mergeHeaderFileInfo(*HFI, ExternalHFI); |
1154 | } |
1155 | } else if (FE->getUID() >= FileInfo.size()) { |
1156 | return nullptr; |
1157 | } else { |
1158 | HFI = &FileInfo[FE->getUID()]; |
1159 | } |
1160 | |
1161 | if (!HFI->IsValid || (HFI->External && !WantExternal)) |
1162 | return nullptr; |
1163 | |
1164 | return HFI; |
1165 | } |
1166 | |
1167 | bool HeaderSearch::(const FileEntry *File) { |
1168 | |
1169 | if (auto *HFI = getExistingFileInfo(File)) |
1170 | return HFI->isPragmaOnce || HFI->isImport || HFI->ControllingMacro || |
1171 | HFI->ControllingMacroID; |
1172 | return false; |
1173 | } |
1174 | |
1175 | void HeaderSearch::(const FileEntry *FE, |
1176 | ModuleMap::ModuleHeaderRole Role, |
1177 | bool ) { |
1178 | bool = !(Role & ModuleMap::TextualHeader); |
1179 | |
1180 | |
1181 | if (!isCompilingModuleHeader) { |
1182 | if (!isModularHeader) |
1183 | return; |
1184 | auto *HFI = getExistingFileInfo(FE); |
1185 | if (HFI && HFI->isModuleHeader) |
1186 | return; |
1187 | } |
1188 | |
1189 | auto &HFI = getFileInfo(FE); |
1190 | HFI.isModuleHeader |= isModularHeader; |
1191 | HFI.isCompilingModuleHeader |= isCompilingModuleHeader; |
1192 | } |
1193 | |
1194 | bool HeaderSearch::(Preprocessor &PP, |
1195 | const FileEntry *File, bool isImport, |
1196 | bool ModulesEnabled, Module *M) { |
1197 | ++NumIncluded; |
1198 | |
1199 | |
1200 | HeaderFileInfo &FileInfo = getFileInfo(File); |
1201 | |
1202 | |
1203 | |
1204 | auto TryEnterImported = [&]() -> bool { |
1205 | if (!ModulesEnabled) |
1206 | return false; |
1207 | |
1208 | ModMap.resolveHeaderDirectives(File); |
1209 | |
1210 | |
1211 | |
1212 | |
1213 | |
1214 | |
1215 | |
1216 | |
1217 | |
1218 | |
1219 | |
1220 | |
1221 | |
1222 | |
1223 | |
1224 | |
1225 | |
1226 | bool TryEnterHdr = false; |
1227 | if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader) |
1228 | TryEnterHdr = File->getDir() == ModMap.getBuiltinDir() && |
1229 | ModuleMap::isBuiltinHeader( |
1230 | llvm::sys::path::filename(File->getName())); |
1231 | |
1232 | |
1233 | |
1234 | |
1235 | |
1236 | if (!FileInfo.isModuleHeader && |
1237 | FileInfo.getControllingMacro(ExternalLookup)) |
1238 | TryEnterHdr = true; |
1239 | return TryEnterHdr; |
1240 | }; |
1241 | |
1242 | |
1243 | |
1244 | if (isImport) { |
1245 | |
1246 | FileInfo.isImport = true; |
1247 | |
1248 | |
1249 | if (FileInfo.NumIncludes && !TryEnterImported()) |
1250 | return false; |
1251 | } else { |
1252 | |
1253 | |
1254 | if (FileInfo.isImport && !TryEnterImported()) |
1255 | return false; |
1256 | } |
1257 | |
1258 | |
1259 | |
1260 | if (const IdentifierInfo *ControllingMacro |
1261 | = FileInfo.getControllingMacro(ExternalLookup)) { |
1262 | |
1263 | |
1264 | |
1265 | if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M) |
1266 | : PP.isMacroDefined(ControllingMacro)) { |
1267 | ++NumMultiIncludeFileOptzn; |
1268 | return false; |
1269 | } |
1270 | } |
1271 | |
1272 | |
1273 | ++FileInfo.NumIncludes; |
1274 | |
1275 | return true; |
1276 | } |
1277 | |
1278 | size_t HeaderSearch::() const { |
1279 | return SearchDirs.capacity() |
1280 | + llvm::capacity_in_bytes(FileInfo) |
1281 | + llvm::capacity_in_bytes(HeaderMaps) |
1282 | + LookupFileCache.getAllocator().getTotalMemory() |
1283 | + FrameworkMap.getAllocator().getTotalMemory(); |
1284 | } |
1285 | |
1286 | StringRef HeaderSearch::(StringRef Framework) { |
1287 | return FrameworkNames.insert(Framework).first->first(); |
1288 | } |
1289 | |
1290 | bool HeaderSearch::(StringRef FileName, |
1291 | const DirectoryEntry *Root, |
1292 | bool IsSystem) { |
1293 | if (!HSOpts->ImplicitModuleMaps) |
1294 | return false; |
1295 | |
1296 | SmallVector<const DirectoryEntry *, 2> FixUpDirectories; |
1297 | |
1298 | StringRef DirName = FileName; |
1299 | do { |
1300 | |
1301 | DirName = llvm::sys::path::parent_path(DirName); |
1302 | if (DirName.empty()) |
1303 | return false; |
1304 | |
1305 | |
1306 | const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); |
1307 | if (!Dir) |
1308 | return false; |
1309 | |
1310 | |
1311 | switch (loadModuleMapFile(Dir, IsSystem, |
1312 | llvm::sys::path::extension(Dir->getName()) == |
1313 | ".framework")) { |
1314 | case LMM_NewlyLoaded: |
1315 | case LMM_AlreadyLoaded: |
1316 | |
1317 | |
1318 | for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I) |
1319 | DirectoryHasModuleMap[FixUpDirectories[I]] = true; |
1320 | return true; |
1321 | |
1322 | case LMM_NoDirectory: |
1323 | case LMM_InvalidModuleMap: |
1324 | break; |
1325 | } |
1326 | |
1327 | |
1328 | if (Dir == Root) |
1329 | return false; |
1330 | |
1331 | |
1332 | |
1333 | FixUpDirectories.push_back(Dir); |
1334 | } while (true); |
1335 | } |
1336 | |
1337 | ModuleMap::KnownHeader |
1338 | HeaderSearch::(const FileEntry *File, |
1339 | bool AllowTextual) const { |
1340 | if (ExternalSource) { |
1341 | |
1342 | |
1343 | (void)getExistingFileInfo(File); |
1344 | } |
1345 | return ModMap.findModuleForHeader(File, AllowTextual); |
1346 | } |
1347 | |
1348 | static bool (HeaderSearch &HS, const FileEntry *File, |
1349 | Module *RequestingModule, |
1350 | ModuleMap::KnownHeader *SuggestedModule) { |
1351 | ModuleMap::KnownHeader Module = |
1352 | HS.findModuleForHeader(File, ); |
1353 | if (SuggestedModule) |
1354 | *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader) |
1355 | ? ModuleMap::KnownHeader() |
1356 | : Module; |
1357 | |
1358 | |
1359 | |
1360 | if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) { |
1361 | HS.getModuleMap().resolveUses(RequestingModule, ); |
1362 | if (!RequestingModule->directlyUses(Module.getModule())) { |
1363 | return false; |
1364 | } |
1365 | } |
1366 | |
1367 | return true; |
1368 | } |
1369 | |
1370 | bool HeaderSearch::( |
1371 | const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, |
1372 | ModuleMap::KnownHeader *SuggestedModule, bool ) { |
1373 | if (File && needModuleLookup(RequestingModule, SuggestedModule)) { |
1374 | |
1375 | hasModuleMap(File->getName(), Root, IsSystemHeaderDir); |
1376 | return suggestModule(*this, File, RequestingModule, SuggestedModule); |
1377 | } |
1378 | return true; |
1379 | } |
1380 | |
1381 | bool HeaderSearch::( |
1382 | const FileEntry *File, StringRef FrameworkName, Module *RequestingModule, |
1383 | ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { |
1384 | |
1385 | if (needModuleLookup(RequestingModule, SuggestedModule)) { |
1386 | |
1387 | SmallVector<std::string, 4> SubmodulePath; |
1388 | const DirectoryEntry *TopFrameworkDir |
1389 | = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); |
1390 | |
1391 | |
1392 | StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); |
1393 | |
1394 | |
1395 | |
1396 | loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystemFramework); |
1397 | |
1398 | |
1399 | |
1400 | |
1401 | |
1402 | return suggestModule(*this, File, RequestingModule, SuggestedModule); |
1403 | } |
1404 | return true; |
1405 | } |
1406 | |
1407 | static const FileEntry *getPrivateModuleMap(const FileEntry *File, |
1408 | FileManager &FileMgr) { |
1409 | StringRef Filename = llvm::sys::path::filename(File->getName()); |
1410 | SmallString<128> PrivateFilename(File->getDir()->getName()); |
1411 | if (Filename == "module.map") |
1412 | llvm::sys::path::append(PrivateFilename, "module_private.map"); |
1413 | else if (Filename == "module.modulemap") |
1414 | llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); |
1415 | else |
1416 | return nullptr; |
1417 | return FileMgr.getFile(PrivateFilename); |
1418 | } |
1419 | |
1420 | bool HeaderSearch::(const FileEntry *File, bool IsSystem, |
1421 | FileID ID, unsigned *Offset, |
1422 | StringRef OriginalModuleMapFile) { |
1423 | |
1424 | |
1425 | const DirectoryEntry *Dir = nullptr; |
1426 | if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) |
1427 | Dir = FileMgr.getDirectory("."); |
1428 | else { |
1429 | if (!OriginalModuleMapFile.empty()) { |
1430 | |
1431 | |
1432 | Dir = FileMgr.getDirectory( |
1433 | llvm::sys::path::parent_path(OriginalModuleMapFile)); |
1434 | if (!Dir) { |
1435 | auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0); |
1436 | Dir = FakeFile->getDir(); |
1437 | } |
1438 | } else { |
1439 | Dir = File->getDir(); |
1440 | } |
1441 | |
1442 | StringRef DirName(Dir->getName()); |
1443 | if (llvm::sys::path::filename(DirName) == "Modules") { |
1444 | DirName = llvm::sys::path::parent_path(DirName); |
1445 | if (DirName.endswith(".framework")) |
1446 | Dir = FileMgr.getDirectory(DirName); |
1447 | |
1448 | |
1449 | (0) . __assert_fail ("Dir && \"parent must exist\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 1449, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Dir && "parent must exist"); |
1450 | } |
1451 | } |
1452 | |
1453 | switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) { |
1454 | case LMM_AlreadyLoaded: |
1455 | case LMM_NewlyLoaded: |
1456 | return false; |
1457 | case LMM_NoDirectory: |
1458 | case LMM_InvalidModuleMap: |
1459 | return true; |
1460 | } |
1461 | llvm_unreachable("Unknown load module map result"); |
1462 | } |
1463 | |
1464 | HeaderSearch::LoadModuleMapResult |
1465 | HeaderSearch::(const FileEntry *File, bool IsSystem, |
1466 | const DirectoryEntry *Dir, FileID ID, |
1467 | unsigned *Offset) { |
1468 | (0) . __assert_fail ("File && \"expected FileEntry\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 1468, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(File && "expected FileEntry"); |
1469 | |
1470 | |
1471 | |
1472 | auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true)); |
1473 | if (!AddResult.second) |
1474 | return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; |
1475 | |
1476 | if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) { |
1477 | LoadedModuleMaps[File] = false; |
1478 | return LMM_InvalidModuleMap; |
1479 | } |
1480 | |
1481 | |
1482 | if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) { |
1483 | if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) { |
1484 | LoadedModuleMaps[File] = false; |
1485 | return LMM_InvalidModuleMap; |
1486 | } |
1487 | } |
1488 | |
1489 | |
1490 | return LMM_NewlyLoaded; |
1491 | } |
1492 | |
1493 | const FileEntry * |
1494 | HeaderSearch::(const DirectoryEntry *Dir, bool IsFramework) { |
1495 | if (!HSOpts->ImplicitModuleMaps) |
1496 | return nullptr; |
1497 | |
1498 | |
1499 | SmallString<128> ModuleMapFileName(Dir->getName()); |
1500 | if (IsFramework) |
1501 | llvm::sys::path::append(ModuleMapFileName, "Modules"); |
1502 | llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); |
1503 | if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName)) |
1504 | return F; |
1505 | |
1506 | |
1507 | ModuleMapFileName = Dir->getName(); |
1508 | llvm::sys::path::append(ModuleMapFileName, "module.map"); |
1509 | return FileMgr.getFile(ModuleMapFileName); |
1510 | } |
1511 | |
1512 | Module *HeaderSearch::(StringRef Name, |
1513 | const DirectoryEntry *Dir, |
1514 | bool IsSystem) { |
1515 | if (Module *Module = ModMap.findModule(Name)) |
1516 | return Module; |
1517 | |
1518 | |
1519 | switch (loadModuleMapFile(Dir, IsSystem, )) { |
1520 | case LMM_InvalidModuleMap: |
1521 | |
1522 | if (HSOpts->ImplicitModuleMaps) |
1523 | ModMap.inferFrameworkModule(Dir, IsSystem, ); |
1524 | break; |
1525 | |
1526 | case LMM_AlreadyLoaded: |
1527 | case LMM_NoDirectory: |
1528 | return nullptr; |
1529 | |
1530 | case LMM_NewlyLoaded: |
1531 | break; |
1532 | } |
1533 | |
1534 | return ModMap.findModule(Name); |
1535 | } |
1536 | |
1537 | HeaderSearch::LoadModuleMapResult |
1538 | HeaderSearch::(StringRef DirName, bool IsSystem, |
1539 | bool IsFramework) { |
1540 | if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) |
1541 | return loadModuleMapFile(Dir, IsSystem, IsFramework); |
1542 | |
1543 | return LMM_NoDirectory; |
1544 | } |
1545 | |
1546 | HeaderSearch::LoadModuleMapResult |
1547 | HeaderSearch::(const DirectoryEntry *Dir, bool IsSystem, |
1548 | bool IsFramework) { |
1549 | auto KnownDir = DirectoryHasModuleMap.find(Dir); |
1550 | if (KnownDir != DirectoryHasModuleMap.end()) |
1551 | return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; |
1552 | |
1553 | if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { |
1554 | LoadModuleMapResult Result = |
1555 | loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir); |
1556 | |
1557 | |
1558 | |
1559 | if (Result == LMM_NewlyLoaded) |
1560 | DirectoryHasModuleMap[Dir] = true; |
1561 | else if (Result == LMM_InvalidModuleMap) |
1562 | DirectoryHasModuleMap[Dir] = false; |
1563 | return Result; |
1564 | } |
1565 | return LMM_InvalidModuleMap; |
1566 | } |
1567 | |
1568 | void HeaderSearch::(SmallVectorImpl<Module *> &Modules) { |
1569 | Modules.clear(); |
1570 | |
1571 | if (HSOpts->ImplicitModuleMaps) { |
1572 | |
1573 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { |
1574 | bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory(); |
1575 | if (SearchDirs[Idx].isFramework()) { |
1576 | std::error_code EC; |
1577 | SmallString<128> DirNative; |
1578 | llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(), |
1579 | DirNative); |
1580 | |
1581 | |
1582 | llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); |
1583 | for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), |
1584 | DirEnd; |
1585 | Dir != DirEnd && !EC; Dir.increment(EC)) { |
1586 | if (llvm::sys::path::extension(Dir->path()) != ".framework") |
1587 | continue; |
1588 | |
1589 | const DirectoryEntry *FrameworkDir = |
1590 | FileMgr.getDirectory(Dir->path()); |
1591 | if (!FrameworkDir) |
1592 | continue; |
1593 | |
1594 | |
1595 | loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, |
1596 | IsSystem); |
1597 | } |
1598 | continue; |
1599 | } |
1600 | |
1601 | |
1602 | if (SearchDirs[Idx].isHeaderMap()) |
1603 | continue; |
1604 | |
1605 | |
1606 | loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, |
1607 | false); |
1608 | |
1609 | |
1610 | |
1611 | loadSubdirectoryModuleMaps(SearchDirs[Idx]); |
1612 | } |
1613 | } |
1614 | |
1615 | |
1616 | for (ModuleMap::module_iterator M = ModMap.module_begin(), |
1617 | MEnd = ModMap.module_end(); |
1618 | M != MEnd; ++M) { |
1619 | Modules.push_back(M->getValue()); |
1620 | } |
1621 | } |
1622 | |
1623 | void HeaderSearch::() { |
1624 | if (!HSOpts->ImplicitModuleMaps) |
1625 | return; |
1626 | |
1627 | |
1628 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { |
1629 | |
1630 | if (!SearchDirs[Idx].isNormalDir()) { |
1631 | continue; |
1632 | } |
1633 | |
1634 | |
1635 | loadModuleMapFile(SearchDirs[Idx].getDir(), |
1636 | SearchDirs[Idx].isSystemHeaderDirectory(), |
1637 | SearchDirs[Idx].isFramework()); |
1638 | } |
1639 | } |
1640 | |
1641 | void HeaderSearch::(DirectoryLookup &SearchDir) { |
1642 | (0) . __assert_fail ("HSOpts->ImplicitModuleMaps && \"Should not be loading subdirectory module maps\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 1643, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(HSOpts->ImplicitModuleMaps && |
1643 | (0) . __assert_fail ("HSOpts->ImplicitModuleMaps && \"Should not be loading subdirectory module maps\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/HeaderSearch.cpp", 1643, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Should not be loading subdirectory module maps"); |
1644 | |
1645 | if (SearchDir.haveSearchedAllModuleMaps()) |
1646 | return; |
1647 | |
1648 | std::error_code EC; |
1649 | SmallString<128> Dir = SearchDir.getDir()->getName(); |
1650 | FileMgr.makeAbsolutePath(Dir); |
1651 | SmallString<128> DirNative; |
1652 | llvm::sys::path::native(Dir, DirNative); |
1653 | llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); |
1654 | for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; |
1655 | Dir != DirEnd && !EC; Dir.increment(EC)) { |
1656 | bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework"; |
1657 | if (IsFramework == SearchDir.isFramework()) |
1658 | loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), |
1659 | SearchDir.isFramework()); |
1660 | } |
1661 | |
1662 | SearchDir.setSearchedAllModuleMaps(true); |
1663 | } |
1664 | |
1665 | std::string HeaderSearch::(const FileEntry *File, |
1666 | bool *IsSystem) { |
1667 | |
1668 | |
1669 | |
1670 | return suggestPathToFileForDiagnostics(File->getName(), , |
1671 | IsSystem); |
1672 | } |
1673 | |
1674 | std::string HeaderSearch::( |
1675 | llvm::StringRef File, llvm::StringRef WorkingDir, bool *IsSystem) { |
1676 | using namespace llvm::sys; |
1677 | |
1678 | unsigned BestPrefixLength = 0; |
1679 | unsigned BestSearchDir; |
1680 | |
1681 | for (unsigned I = 0; I != SearchDirs.size(); ++I) { |
1682 | |
1683 | if (!SearchDirs[I].isNormalDir()) |
1684 | continue; |
1685 | |
1686 | StringRef Dir = SearchDirs[I].getDir()->getName(); |
1687 | llvm::SmallString<32> DirPath(Dir.begin(), Dir.end()); |
1688 | if (!WorkingDir.empty() && !path::is_absolute(Dir)) { |
1689 | fs::make_absolute(WorkingDir, DirPath); |
1690 | path::remove_dots(DirPath, ); |
1691 | Dir = DirPath; |
1692 | } |
1693 | for (auto NI = path::begin(File), NE = path::end(File), |
1694 | DI = path::begin(Dir), DE = path::end(Dir); |
1695 | ; ++NI, ++DI) { |
1696 | |
1697 | while (NI != NE && *NI == ".") |
1698 | ++NI; |
1699 | if (NI == NE) |
1700 | break; |
1701 | |
1702 | |
1703 | while (DI != DE && *DI == ".") |
1704 | ++DI; |
1705 | if (DI == DE) { |
1706 | |
1707 | |
1708 | unsigned PrefixLength = NI - path::begin(File); |
1709 | if (PrefixLength > BestPrefixLength) { |
1710 | BestPrefixLength = PrefixLength; |
1711 | BestSearchDir = I; |
1712 | } |
1713 | break; |
1714 | } |
1715 | |
1716 | if (*NI != *DI) |
1717 | break; |
1718 | } |
1719 | } |
1720 | |
1721 | if (IsSystem) |
1722 | *IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false; |
1723 | return File.drop_front(BestPrefixLength); |
1724 | } |
1725 | |