Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Lex/HeaderSearch.cpp @ 252:1f2b6ac9f198 llvm-original
LLVM16-1
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 18 Aug 2023 09:04:13 +0900 |
parents | c4bab56944e8 |
children |
comparison
equal
deleted
inserted
replaced
237:c80f45b162ad | 252:1f2b6ac9f198 |
---|---|
169 for (auto &HM : HeaderMaps) | 169 for (auto &HM : HeaderMaps) |
170 Names.push_back(std::string(HM.first->getName())); | 170 Names.push_back(std::string(HM.first->getName())); |
171 } | 171 } |
172 | 172 |
173 std::string HeaderSearch::getCachedModuleFileName(Module *Module) { | 173 std::string HeaderSearch::getCachedModuleFileName(Module *Module) { |
174 Optional<FileEntryRef> ModuleMap = | 174 OptionalFileEntryRef ModuleMap = |
175 getModuleMap().getModuleMapFileForUniquing(Module); | 175 getModuleMap().getModuleMapFileForUniquing(Module); |
176 // The ModuleMap maybe a nullptr, when we load a cached C++ module without | 176 // The ModuleMap maybe a nullptr, when we load a cached C++ module without |
177 // *.modulemap file. In this case, just return an empty string. | 177 // *.modulemap file. In this case, just return an empty string. |
178 if (!ModuleMap) | 178 if (!ModuleMap) |
179 return {}; | 179 return {}; |
210 | 210 |
211 return {}; | 211 return {}; |
212 } | 212 } |
213 | 213 |
214 std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) { | 214 std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) { |
215 Optional<FileEntryRef> ModuleMap = | 215 OptionalFileEntryRef ModuleMap = |
216 getModuleMap().getModuleMapFileForUniquing(Module); | 216 getModuleMap().getModuleMapFileForUniquing(Module); |
217 StringRef ModuleName = Module->Name; | 217 StringRef ModuleName = Module->Name; |
218 StringRef ModuleMapPath = ModuleMap->getName(); | 218 StringRef ModuleMapPath = ModuleMap->getName(); |
219 StringRef ModuleCacheHash = HSOpts->DisableModuleHash ? "" : getModuleHash(); | 219 StringRef ModuleCacheHash = HSOpts->DisableModuleHash ? "" : getModuleHash(); |
220 for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { | 220 for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { |
309 if (Dir.isFramework()) { | 309 if (Dir.isFramework()) { |
310 // Search for or infer a module map for a framework. Here we use | 310 // Search for or infer a module map for a framework. Here we use |
311 // SearchName rather than ModuleName, to permit finding private modules | 311 // SearchName rather than ModuleName, to permit finding private modules |
312 // named FooPrivate in buggy frameworks named Foo. | 312 // named FooPrivate in buggy frameworks named Foo. |
313 SmallString<128> FrameworkDirName; | 313 SmallString<128> FrameworkDirName; |
314 FrameworkDirName += Dir.getFrameworkDir()->getName(); | 314 FrameworkDirName += Dir.getFrameworkDirRef()->getName(); |
315 llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); | 315 llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); |
316 if (auto FrameworkDir = | 316 if (auto FrameworkDir = |
317 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) { | 317 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) { |
318 bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User; | 318 bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User; |
319 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem); | 319 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem); |
327 // Only deal with normal search directories. | 327 // Only deal with normal search directories. |
328 if (!Dir.isNormalDir()) | 328 if (!Dir.isNormalDir()) |
329 continue; | 329 continue; |
330 | 330 |
331 bool IsSystem = Dir.isSystemHeaderDirectory(); | 331 bool IsSystem = Dir.isSystemHeaderDirectory(); |
332 // Only returns None if not a normal directory, which we just checked | 332 // Only returns std::nullopt if not a normal directory, which we just |
333 // checked | |
333 DirectoryEntryRef NormalDir = *Dir.getDirRef(); | 334 DirectoryEntryRef NormalDir = *Dir.getDirRef(); |
334 // Search for a module map file in this directory. | 335 // Search for a module map file in this directory. |
335 if (loadModuleMapFile(NormalDir, IsSystem, | 336 if (loadModuleMapFile(NormalDir, IsSystem, |
336 /*IsFramework*/false) == LMM_NewlyLoaded) { | 337 /*IsFramework*/false) == LMM_NewlyLoaded) { |
337 // We just loaded a module map file; check whether the module is | 338 // We just loaded a module map file; check whether the module is |
342 } | 343 } |
343 | 344 |
344 // Search for a module map in a subdirectory with the same name as the | 345 // Search for a module map in a subdirectory with the same name as the |
345 // module. | 346 // module. |
346 SmallString<128> NestedModuleMapDirName; | 347 SmallString<128> NestedModuleMapDirName; |
347 NestedModuleMapDirName = Dir.getDir()->getName(); | 348 NestedModuleMapDirName = Dir.getDirRef()->getName(); |
348 llvm::sys::path::append(NestedModuleMapDirName, ModuleName); | 349 llvm::sys::path::append(NestedModuleMapDirName, ModuleName); |
349 if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, | 350 if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, |
350 /*IsFramework*/false) == LMM_NewlyLoaded){ | 351 /*IsFramework*/false) == LMM_NewlyLoaded){ |
351 // If we just loaded a module map file, look for the module again. | 352 // If we just loaded a module map file, look for the module again. |
352 Module = ModMap.findModule(ModuleName); | 353 Module = ModMap.findModule(ModuleName); |
375 | 376 |
376 void HeaderSearch::indexInitialHeaderMaps() { | 377 void HeaderSearch::indexInitialHeaderMaps() { |
377 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size()); | 378 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size()); |
378 | 379 |
379 // Iterate over all filename keys and associate them with the index i. | 380 // Iterate over all filename keys and associate them with the index i. |
380 unsigned i = 0; | 381 for (unsigned i = 0; i != SearchDirs.size(); ++i) { |
381 for (; i != SearchDirs.size(); ++i) { | |
382 auto &Dir = SearchDirs[i]; | 382 auto &Dir = SearchDirs[i]; |
383 | 383 |
384 // We're concerned with only the initial contiguous run of header | 384 // We're concerned with only the initial contiguous run of header |
385 // maps within SearchDirs, which can be 99% of SearchDirs when | 385 // maps within SearchDirs, which can be 99% of SearchDirs when |
386 // SearchDirs.size() is ~10000. | 386 // SearchDirs.size() is ~10000. |
387 if (!Dir.isHeaderMap()) | 387 if (!Dir.isHeaderMap()) { |
388 SearchDirHeaderMapIndex = std::move(Index); | |
389 FirstNonHeaderMapSearchDirIdx = i; | |
388 break; | 390 break; |
391 } | |
389 | 392 |
390 // Give earlier keys precedence over identical later keys. | 393 // Give earlier keys precedence over identical later keys. |
391 auto Callback = [&](StringRef Filename) { | 394 auto Callback = [&](StringRef Filename) { |
392 Index.try_emplace(Filename.lower(), i); | 395 Index.try_emplace(Filename.lower(), i); |
393 }; | 396 }; |
394 Dir.getHeaderMap()->forEachKey(Callback); | 397 Dir.getHeaderMap()->forEachKey(Callback); |
395 } | 398 } |
396 | |
397 SearchDirHeaderMapIndex = std::move(Index); | |
398 FirstNonHeaderMapSearchDirIdx = i; | |
399 } | 399 } |
400 | 400 |
401 //===----------------------------------------------------------------------===// | 401 //===----------------------------------------------------------------------===// |
402 // File lookup within a DirectoryLookup scope | 402 // File lookup within a DirectoryLookup scope |
403 //===----------------------------------------------------------------------===// | 403 //===----------------------------------------------------------------------===// |
404 | 404 |
405 /// getName - Return the directory or filename corresponding to this lookup | 405 /// getName - Return the directory or filename corresponding to this lookup |
406 /// object. | 406 /// object. |
407 StringRef DirectoryLookup::getName() const { | 407 StringRef DirectoryLookup::getName() const { |
408 // FIXME: Use the name from \c DirectoryEntryRef. | |
409 if (isNormalDir()) | 408 if (isNormalDir()) |
410 return getDir()->getName(); | 409 return getDirRef()->getName(); |
411 if (isFramework()) | 410 if (isFramework()) |
412 return getFrameworkDir()->getName(); | 411 return getFrameworkDirRef()->getName(); |
413 assert(isHeaderMap() && "Unknown DirectoryLookup"); | 412 assert(isHeaderMap() && "Unknown DirectoryLookup"); |
414 return getHeaderMap()->getFileName(); | 413 return getHeaderMap()->getFileName(); |
415 } | 414 } |
416 | 415 |
417 Optional<FileEntryRef> HeaderSearch::getFileAndSuggestModule( | 416 OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule( |
418 StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir, | 417 StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir, |
419 bool IsSystemHeaderDir, Module *RequestingModule, | 418 bool IsSystemHeaderDir, Module *RequestingModule, |
420 ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/, | 419 ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/, |
421 bool CacheFailures /*=true*/) { | 420 bool CacheFailures /*=true*/) { |
422 // If we have a module map that might map this header, load it and | 421 // If we have a module map that might map this header, load it and |
430 EC != llvm::errc::invalid_argument && | 429 EC != llvm::errc::invalid_argument && |
431 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) { | 430 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) { |
432 Diags.Report(IncludeLoc, diag::err_cannot_open_file) | 431 Diags.Report(IncludeLoc, diag::err_cannot_open_file) |
433 << FileName << EC.message(); | 432 << FileName << EC.message(); |
434 } | 433 } |
435 return None; | 434 return std::nullopt; |
436 } | 435 } |
437 | 436 |
438 // If there is a module that corresponds to this header, suggest it. | 437 // If there is a module that corresponds to this header, suggest it. |
439 if (!findUsableModuleForHeader( | 438 if (!findUsableModuleForHeader( |
440 &File->getFileEntry(), Dir ? Dir : File->getFileEntry().getDir(), | 439 *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule, |
441 RequestingModule, SuggestedModule, IsSystemHeaderDir)) | 440 SuggestedModule, IsSystemHeaderDir)) |
442 return None; | 441 return std::nullopt; |
443 | 442 |
444 return *File; | 443 return *File; |
445 } | 444 } |
446 | 445 |
447 /// LookupFile - Lookup the specified file in this search path, returning it | 446 /// LookupFile - Lookup the specified file in this search path, returning it |
448 /// if it exists or returning null if not. | 447 /// if it exists or returning null if not. |
449 Optional<FileEntryRef> DirectoryLookup::LookupFile( | 448 OptionalFileEntryRef DirectoryLookup::LookupFile( |
450 StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, | 449 StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, |
451 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, | 450 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, |
452 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, | 451 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, |
453 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, | 452 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, |
454 bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName, | 453 bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName, |
485 assert(isHeaderMap() && "Unknown directory lookup"); | 484 assert(isHeaderMap() && "Unknown directory lookup"); |
486 const HeaderMap *HM = getHeaderMap(); | 485 const HeaderMap *HM = getHeaderMap(); |
487 SmallString<1024> Path; | 486 SmallString<1024> Path; |
488 StringRef Dest = HM->lookupFilename(Filename, Path); | 487 StringRef Dest = HM->lookupFilename(Filename, Path); |
489 if (Dest.empty()) | 488 if (Dest.empty()) |
490 return None; | 489 return std::nullopt; |
491 | 490 |
492 IsInHeaderMap = true; | 491 IsInHeaderMap = true; |
493 | 492 |
494 auto FixupSearchPath = [&]() { | 493 auto FixupSearchPathAndFindUsableModule = |
494 [&](FileEntryRef File) -> OptionalFileEntryRef { | |
495 if (SearchPath) { | 495 if (SearchPath) { |
496 StringRef SearchPathRef(getName()); | 496 StringRef SearchPathRef(getName()); |
497 SearchPath->clear(); | 497 SearchPath->clear(); |
498 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); | 498 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
499 } | 499 } |
500 if (RelativePath) { | 500 if (RelativePath) { |
501 RelativePath->clear(); | 501 RelativePath->clear(); |
502 RelativePath->append(Filename.begin(), Filename.end()); | 502 RelativePath->append(Filename.begin(), Filename.end()); |
503 } | 503 } |
504 if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(), | |
505 RequestingModule, SuggestedModule, | |
506 isSystemHeaderDirectory())) { | |
507 return std::nullopt; | |
508 } | |
509 return File; | |
504 }; | 510 }; |
505 | 511 |
506 // Check if the headermap maps the filename to a framework include | 512 // Check if the headermap maps the filename to a framework include |
507 // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the | 513 // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the |
508 // framework include. | 514 // framework include. |
511 Filename = StringRef(MappedName.begin(), MappedName.size()); | 517 Filename = StringRef(MappedName.begin(), MappedName.size()); |
512 Dest = HM->lookupFilename(Filename, Path); | 518 Dest = HM->lookupFilename(Filename, Path); |
513 } | 519 } |
514 | 520 |
515 if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest, OpenFile)) { | 521 if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest, OpenFile)) { |
516 FixupSearchPath(); | 522 return FixupSearchPathAndFindUsableModule(*Res); |
517 return *Res; | |
518 } | 523 } |
519 | 524 |
520 // Header maps need to be marked as used whenever the filename matches. | 525 // Header maps need to be marked as used whenever the filename matches. |
521 // The case where the target file **exists** is handled by callee of this | 526 // The case where the target file **exists** is handled by callee of this |
522 // function as part of the regular logic that applies to include search paths. | 527 // function as part of the regular logic that applies to include search paths. |
523 // The case where the target file **does not exist** is handled here: | 528 // The case where the target file **does not exist** is handled here: |
524 HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc); | 529 HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc); |
525 return None; | 530 return std::nullopt; |
526 } | 531 } |
527 | 532 |
528 /// Given a framework directory, find the top-most framework directory. | 533 /// Given a framework directory, find the top-most framework directory. |
529 /// | 534 /// |
530 /// \param FileMgr The file manager to use for directory lookups. | 535 /// \param FileMgr The file manager to use for directory lookups. |
531 /// \param DirName The name of the framework directory. | 536 /// \param DirName The name of the framework directory. |
532 /// \param SubmodulePath Will be populated with the submodule path from the | 537 /// \param SubmodulePath Will be populated with the submodule path from the |
533 /// returned top-level module to the originally named framework. | 538 /// returned top-level module to the originally named framework. |
534 static Optional<DirectoryEntryRef> | 539 static OptionalDirectoryEntryRef |
535 getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, | 540 getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, |
536 SmallVectorImpl<std::string> &SubmodulePath) { | 541 SmallVectorImpl<std::string> &SubmodulePath) { |
537 assert(llvm::sys::path::extension(DirName) == ".framework" && | 542 assert(llvm::sys::path::extension(DirName) == ".framework" && |
538 "Not a framework directory"); | 543 "Not a framework directory"); |
539 | 544 |
583 (RequestingModule && RequestingModule->NoUndeclaredIncludes); | 588 (RequestingModule && RequestingModule->NoUndeclaredIncludes); |
584 } | 589 } |
585 | 590 |
586 /// DoFrameworkLookup - Do a lookup of the specified file in the current | 591 /// DoFrameworkLookup - Do a lookup of the specified file in the current |
587 /// DirectoryLookup, which is a framework directory. | 592 /// DirectoryLookup, which is a framework directory. |
588 Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup( | 593 OptionalFileEntryRef DirectoryLookup::DoFrameworkLookup( |
589 StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, | 594 StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, |
590 SmallVectorImpl<char> *RelativePath, Module *RequestingModule, | 595 SmallVectorImpl<char> *RelativePath, Module *RequestingModule, |
591 ModuleMap::KnownHeader *SuggestedModule, | 596 ModuleMap::KnownHeader *SuggestedModule, |
592 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const { | 597 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const { |
593 FileManager &FileMgr = HS.getFileMgr(); | 598 FileManager &FileMgr = HS.getFileMgr(); |
594 | 599 |
595 // Framework names must have a '/' in the filename. | 600 // Framework names must have a '/' in the filename. |
596 size_t SlashPos = Filename.find('/'); | 601 size_t SlashPos = Filename.find('/'); |
597 if (SlashPos == StringRef::npos) | 602 if (SlashPos == StringRef::npos) |
598 return None; | 603 return std::nullopt; |
599 | 604 |
600 // Find out if this is the home for the specified framework, by checking | 605 // Find out if this is the home for the specified framework, by checking |
601 // HeaderSearch. Possible answers are yes/no and unknown. | 606 // HeaderSearch. Possible answers are yes/no and unknown. |
602 FrameworkCacheEntry &CacheEntry = | 607 FrameworkCacheEntry &CacheEntry = |
603 HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); | 608 HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); |
604 | 609 |
605 // If it is known and in some other directory, fail. | 610 // If it is known and in some other directory, fail. |
606 if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef()) | 611 if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef()) |
607 return None; | 612 return std::nullopt; |
608 | 613 |
609 // Otherwise, construct the path to this framework dir. | 614 // Otherwise, construct the path to this framework dir. |
610 | 615 |
611 // FrameworkName = "/System/Library/Frameworks/" | 616 // FrameworkName = "/System/Library/Frameworks/" |
612 SmallString<1024> FrameworkName; | 617 SmallString<1024> FrameworkName; |
626 ++NumFrameworkLookups; | 631 ++NumFrameworkLookups; |
627 | 632 |
628 // If the framework dir doesn't exist, we fail. | 633 // If the framework dir doesn't exist, we fail. |
629 auto Dir = FileMgr.getDirectory(FrameworkName); | 634 auto Dir = FileMgr.getDirectory(FrameworkName); |
630 if (!Dir) | 635 if (!Dir) |
631 return None; | 636 return std::nullopt; |
632 | 637 |
633 // Otherwise, if it does, remember that this is the right direntry for this | 638 // Otherwise, if it does, remember that this is the right direntry for this |
634 // framework. | 639 // framework. |
635 CacheEntry.Directory = getFrameworkDirRef(); | 640 CacheEntry.Directory = getFrameworkDirRef(); |
636 | 641 |
683 } | 688 } |
684 | 689 |
685 // If we found the header and are allowed to suggest a module, do so now. | 690 // If we found the header and are allowed to suggest a module, do so now. |
686 if (File && needModuleLookup(RequestingModule, SuggestedModule)) { | 691 if (File && needModuleLookup(RequestingModule, SuggestedModule)) { |
687 // Find the framework in which this header occurs. | 692 // Find the framework in which this header occurs. |
688 StringRef FrameworkPath = File->getFileEntry().getDir()->getName(); | 693 StringRef FrameworkPath = File->getDir().getName(); |
689 bool FoundFramework = false; | 694 bool FoundFramework = false; |
690 do { | 695 do { |
691 // Determine whether this directory exists. | 696 // Determine whether this directory exists. |
692 auto Dir = FileMgr.getDirectory(FrameworkPath); | 697 auto Dir = FileMgr.getDirectory(FrameworkPath); |
693 if (!Dir) | 698 if (!Dir) |
706 break; | 711 break; |
707 } while (true); | 712 } while (true); |
708 | 713 |
709 bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; | 714 bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; |
710 if (FoundFramework) { | 715 if (FoundFramework) { |
711 if (!HS.findUsableModuleForFrameworkHeader( | 716 if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath, |
712 &File->getFileEntry(), FrameworkPath, RequestingModule, | 717 RequestingModule, |
713 SuggestedModule, IsSystem)) | 718 SuggestedModule, IsSystem)) |
714 return None; | 719 return std::nullopt; |
715 } else { | 720 } else { |
716 if (!HS.findUsableModuleForHeader(&File->getFileEntry(), getDir(), | 721 if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule, |
717 RequestingModule, SuggestedModule, | 722 SuggestedModule, IsSystem)) |
718 IsSystem)) | 723 return std::nullopt; |
719 return None; | |
720 } | 724 } |
721 } | 725 } |
722 if (File) | 726 if (File) |
723 return *File; | 727 return *File; |
724 return None; | 728 return std::nullopt; |
725 } | 729 } |
726 | 730 |
727 void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup, | 731 void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup, |
728 ConstSearchDirIterator HitIt, | 732 ConstSearchDirIterator HitIt, |
729 SourceLocation Loc) { | 733 SourceLocation Loc) { |
852 /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, | 856 /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, |
853 /// return null on failure. isAngled indicates whether the file reference is | 857 /// return null on failure. isAngled indicates whether the file reference is |
854 /// for system \#include's or not (i.e. using <> instead of ""). Includers, if | 858 /// for system \#include's or not (i.e. using <> instead of ""). Includers, if |
855 /// non-empty, indicates where the \#including file(s) are, in case a relative | 859 /// non-empty, indicates where the \#including file(s) are, in case a relative |
856 /// search is needed. Microsoft mode will pass all \#including files. | 860 /// search is needed. Microsoft mode will pass all \#including files. |
857 Optional<FileEntryRef> HeaderSearch::LookupFile( | 861 OptionalFileEntryRef HeaderSearch::LookupFile( |
858 StringRef Filename, SourceLocation IncludeLoc, bool isAngled, | 862 StringRef Filename, SourceLocation IncludeLoc, bool isAngled, |
859 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg, | 863 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg, |
860 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, | 864 ArrayRef<std::pair<const FileEntry *, DirectoryEntryRef>> Includers, |
861 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, | 865 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, |
862 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, | 866 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, |
863 bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, | 867 bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, |
864 bool BuildSystemModule, bool OpenFile, bool CacheFailures) { | 868 bool BuildSystemModule, bool OpenFile, bool CacheFailures) { |
865 ConstSearchDirIterator CurDirLocal = nullptr; | 869 ConstSearchDirIterator CurDirLocal = nullptr; |
878 if (llvm::sys::path::is_absolute(Filename)) { | 882 if (llvm::sys::path::is_absolute(Filename)) { |
879 CurDir = nullptr; | 883 CurDir = nullptr; |
880 | 884 |
881 // If this was an #include_next "/absolute/file", fail. | 885 // If this was an #include_next "/absolute/file", fail. |
882 if (FromDir) | 886 if (FromDir) |
883 return None; | 887 return std::nullopt; |
884 | 888 |
885 if (SearchPath) | 889 if (SearchPath) |
886 SearchPath->clear(); | 890 SearchPath->clear(); |
887 if (RelativePath) { | 891 if (RelativePath) { |
888 RelativePath->clear(); | 892 RelativePath->clear(); |
895 CacheFailures); | 899 CacheFailures); |
896 } | 900 } |
897 | 901 |
898 // This is the header that MSVC's header search would have found. | 902 // This is the header that MSVC's header search would have found. |
899 ModuleMap::KnownHeader MSSuggestedModule; | 903 ModuleMap::KnownHeader MSSuggestedModule; |
900 Optional<FileEntryRef> MSFE; | 904 OptionalFileEntryRef MSFE; |
901 | 905 |
902 // Unless disabled, check to see if the file is in the #includer's | 906 // Unless disabled, check to see if the file is in the #includer's |
903 // directory. This cannot be based on CurDir, because each includer could be | 907 // directory. This cannot be based on CurDir, because each includer could be |
904 // a #include of a subdirectory (#include "foo/bar.h") and a subsequent | 908 // a #include of a subdirectory (#include "foo/bar.h") and a subsequent |
905 // include of "baz.h" should resolve to "whatever/foo/baz.h". | 909 // include of "baz.h" should resolve to "whatever/foo/baz.h". |
910 for (const auto &IncluderAndDir : Includers) { | 914 for (const auto &IncluderAndDir : Includers) { |
911 const FileEntry *Includer = IncluderAndDir.first; | 915 const FileEntry *Includer = IncluderAndDir.first; |
912 | 916 |
913 // Concatenate the requested file onto the directory. | 917 // Concatenate the requested file onto the directory. |
914 // FIXME: Portability. Filename concatenation should be in sys::Path. | 918 // FIXME: Portability. Filename concatenation should be in sys::Path. |
915 TmpDir = IncluderAndDir.second->getName(); | 919 TmpDir = IncluderAndDir.second.getName(); |
916 TmpDir.push_back('/'); | 920 TmpDir.push_back('/'); |
917 TmpDir.append(Filename.begin(), Filename.end()); | 921 TmpDir.append(Filename.begin(), Filename.end()); |
918 | 922 |
919 // FIXME: We don't cache the result of getFileInfo across the call to | 923 // FIXME: We don't cache the result of getFileInfo across the call to |
920 // getFileAndSuggestModule, because it's a reference to an element of | 924 // getFileAndSuggestModule, because it's a reference to an element of |
924 // from a module build. We should treat this as a system header if we're | 928 // from a module build. We should treat this as a system header if we're |
925 // building a [system] module. | 929 // building a [system] module. |
926 bool IncluderIsSystemHeader = | 930 bool IncluderIsSystemHeader = |
927 Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User : | 931 Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User : |
928 BuildSystemModule; | 932 BuildSystemModule; |
929 if (Optional<FileEntryRef> FE = getFileAndSuggestModule( | 933 if (OptionalFileEntryRef FE = getFileAndSuggestModule( |
930 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, | 934 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, |
931 RequestingModule, SuggestedModule)) { | 935 RequestingModule, SuggestedModule)) { |
932 if (!Includer) { | 936 if (!Includer) { |
933 assert(First && "only first includer can have no file"); | 937 assert(First && "only first includer can have no file"); |
934 return FE; | 938 return FE; |
949 ToHFI.DirInfo = DirInfo; | 953 ToHFI.DirInfo = DirInfo; |
950 ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; | 954 ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; |
951 ToHFI.Framework = Framework; | 955 ToHFI.Framework = Framework; |
952 | 956 |
953 if (SearchPath) { | 957 if (SearchPath) { |
954 StringRef SearchPathRef(IncluderAndDir.second->getName()); | 958 StringRef SearchPathRef(IncluderAndDir.second.getName()); |
955 SearchPath->clear(); | 959 SearchPath->clear(); |
956 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); | 960 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
957 } | 961 } |
958 if (RelativePath) { | 962 if (RelativePath) { |
959 RelativePath->clear(); | 963 RelativePath->clear(); |
960 RelativePath->append(Filename.begin(), Filename.end()); | 964 RelativePath->append(Filename.begin(), Filename.end()); |
961 } | 965 } |
962 if (First) { | 966 if (First) { |
963 diagnoseFrameworkInclude(Diags, IncludeLoc, | 967 diagnoseFrameworkInclude(Diags, IncludeLoc, |
964 IncluderAndDir.second->getName(), Filename, | 968 IncluderAndDir.second.getName(), Filename, |
965 &FE->getFileEntry()); | 969 &FE->getFileEntry()); |
966 return FE; | 970 return FE; |
967 } | 971 } |
968 | 972 |
969 // Otherwise, we found the path via MSVC header search rules. If | 973 // Otherwise, we found the path via MSVC header search rules. If |
1002 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; | 1006 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; |
1003 | 1007 |
1004 ConstSearchDirIterator NextIt = std::next(It); | 1008 ConstSearchDirIterator NextIt = std::next(It); |
1005 | 1009 |
1006 if (!SkipCache) { | 1010 if (!SkipCache) { |
1007 if (CacheLookup.StartIt == NextIt) { | 1011 if (CacheLookup.StartIt == NextIt && |
1012 CacheLookup.RequestingModule == RequestingModule) { | |
1008 // HIT: Skip querying potentially lots of directories for this lookup. | 1013 // HIT: Skip querying potentially lots of directories for this lookup. |
1009 if (CacheLookup.HitIt) | 1014 if (CacheLookup.HitIt) |
1010 It = CacheLookup.HitIt; | 1015 It = CacheLookup.HitIt; |
1011 if (CacheLookup.MappedName) { | 1016 if (CacheLookup.MappedName) { |
1012 Filename = CacheLookup.MappedName; | 1017 Filename = CacheLookup.MappedName; |
1015 } | 1020 } |
1016 } else { | 1021 } else { |
1017 // MISS: This is the first query, or the previous query didn't match | 1022 // MISS: This is the first query, or the previous query didn't match |
1018 // our search start. We will fill in our found location below, so prime | 1023 // our search start. We will fill in our found location below, so prime |
1019 // the start point value. | 1024 // the start point value. |
1020 CacheLookup.reset(/*NewStartIt=*/NextIt); | 1025 CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt); |
1021 | 1026 |
1022 if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) { | 1027 if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) { |
1023 // Handle cold misses of user includes in the presence of many header | 1028 // Handle cold misses of user includes in the presence of many header |
1024 // maps. We avoid searching perhaps thousands of header maps by | 1029 // maps. We avoid searching perhaps thousands of header maps by |
1025 // jumping directly to the correct one or jumping beyond all of them. | 1030 // jumping directly to the correct one or jumping beyond all of them. |
1030 else | 1035 else |
1031 // In index => Start with a specific header map | 1036 // In index => Start with a specific header map |
1032 It = search_dir_nth(Iter->second); | 1037 It = search_dir_nth(Iter->second); |
1033 } | 1038 } |
1034 } | 1039 } |
1035 } else | 1040 } else { |
1036 CacheLookup.reset(/*NewStartIt=*/NextIt); | 1041 CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt); |
1042 } | |
1037 | 1043 |
1038 SmallString<64> MappedName; | 1044 SmallString<64> MappedName; |
1039 | 1045 |
1040 // Check each directory in sequence to see if it contains this file. | 1046 // Check each directory in sequence to see if it contains this file. |
1041 for (; It != search_dir_end(); ++It) { | 1047 for (; It != search_dir_end(); ++It) { |
1042 bool InUserSpecifiedSystemFramework = false; | 1048 bool InUserSpecifiedSystemFramework = false; |
1043 bool IsInHeaderMap = false; | 1049 bool IsInHeaderMap = false; |
1044 bool IsFrameworkFoundInDir = false; | 1050 bool IsFrameworkFoundInDir = false; |
1045 Optional<FileEntryRef> File = It->LookupFile( | 1051 OptionalFileEntryRef File = It->LookupFile( |
1046 Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, | 1052 Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, |
1047 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, | 1053 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, |
1048 IsInHeaderMap, MappedName, OpenFile); | 1054 IsInHeaderMap, MappedName, OpenFile); |
1049 if (!MappedName.empty()) { | 1055 if (!MappedName.empty()) { |
1050 assert(IsInHeaderMap && "MappedName should come from a header map"); | 1056 assert(IsInHeaderMap && "MappedName should come from a header map"); |
1114 } | 1120 } |
1115 | 1121 |
1116 bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; | 1122 bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; |
1117 if (!Includers.empty()) | 1123 if (!Includers.empty()) |
1118 diagnoseFrameworkInclude( | 1124 diagnoseFrameworkInclude( |
1119 Diags, IncludeLoc, Includers.front().second->getName(), Filename, | 1125 Diags, IncludeLoc, Includers.front().second.getName(), Filename, |
1120 &File->getFileEntry(), isAngled, FoundByHeaderMap); | 1126 &File->getFileEntry(), isAngled, FoundByHeaderMap); |
1121 | 1127 |
1122 // Remember this location for the next lookup we do. | 1128 // Remember this location for the next lookup we do. |
1123 cacheLookupSuccess(CacheLookup, It, IncludeLoc); | 1129 cacheLookupSuccess(CacheLookup, It, IncludeLoc); |
1124 return File; | 1130 return File; |
1135 SmallString<128> ScratchFilename; | 1141 SmallString<128> ScratchFilename; |
1136 ScratchFilename += IncludingHFI.Framework; | 1142 ScratchFilename += IncludingHFI.Framework; |
1137 ScratchFilename += '/'; | 1143 ScratchFilename += '/'; |
1138 ScratchFilename += Filename; | 1144 ScratchFilename += Filename; |
1139 | 1145 |
1140 Optional<FileEntryRef> File = LookupFile( | 1146 OptionalFileEntryRef File = LookupFile( |
1141 ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, &CurDir, | 1147 ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, &CurDir, |
1142 Includers.front(), SearchPath, RelativePath, RequestingModule, | 1148 Includers.front(), SearchPath, RelativePath, RequestingModule, |
1143 SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); | 1149 SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); |
1144 | 1150 |
1145 if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, | 1151 if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, |
1164 return MSFE; | 1170 return MSFE; |
1165 } | 1171 } |
1166 | 1172 |
1167 // Otherwise, didn't find it. Remember we didn't find this. | 1173 // Otherwise, didn't find it. Remember we didn't find this. |
1168 CacheLookup.HitIt = search_dir_end(); | 1174 CacheLookup.HitIt = search_dir_end(); |
1169 return None; | 1175 return std::nullopt; |
1170 } | 1176 } |
1171 | 1177 |
1172 /// LookupSubframeworkHeader - Look up a subframework for the specified | 1178 /// LookupSubframeworkHeader - Look up a subframework for the specified |
1173 /// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from | 1179 /// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from |
1174 /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox | 1180 /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox |
1175 /// is a subframework within Carbon.framework. If so, return the FileEntry | 1181 /// is a subframework within Carbon.framework. If so, return the FileEntry |
1176 /// for the designated file, otherwise return null. | 1182 /// for the designated file, otherwise return null. |
1177 Optional<FileEntryRef> HeaderSearch::LookupSubframeworkHeader( | 1183 OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader( |
1178 StringRef Filename, const FileEntry *ContextFileEnt, | 1184 StringRef Filename, const FileEntry *ContextFileEnt, |
1179 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, | 1185 SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, |
1180 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { | 1186 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { |
1181 assert(ContextFileEnt && "No context file?"); | 1187 assert(ContextFileEnt && "No context file?"); |
1182 | 1188 |
1183 // Framework names must have a '/' in the filename. Find it. | 1189 // Framework names must have a '/' in the filename. Find it. |
1184 // FIXME: Should we permit '\' on Windows? | 1190 // FIXME: Should we permit '\' on Windows? |
1185 size_t SlashPos = Filename.find('/'); | 1191 size_t SlashPos = Filename.find('/'); |
1186 if (SlashPos == StringRef::npos) | 1192 if (SlashPos == StringRef::npos) |
1187 return None; | 1193 return std::nullopt; |
1188 | 1194 |
1189 // Look up the base framework name of the ContextFileEnt. | 1195 // Look up the base framework name of the ContextFileEnt. |
1190 StringRef ContextName = ContextFileEnt->getName(); | 1196 StringRef ContextName = ContextFileEnt->getName(); |
1191 | 1197 |
1192 // If the context info wasn't a framework, couldn't be a subframework. | 1198 // If the context info wasn't a framework, couldn't be a subframework. |
1193 const unsigned DotFrameworkLen = 10; | 1199 const unsigned DotFrameworkLen = 10; |
1194 auto FrameworkPos = ContextName.find(".framework"); | 1200 auto FrameworkPos = ContextName.find(".framework"); |
1195 if (FrameworkPos == StringRef::npos || | 1201 if (FrameworkPos == StringRef::npos || |
1196 (ContextName[FrameworkPos + DotFrameworkLen] != '/' && | 1202 (ContextName[FrameworkPos + DotFrameworkLen] != '/' && |
1197 ContextName[FrameworkPos + DotFrameworkLen] != '\\')) | 1203 ContextName[FrameworkPos + DotFrameworkLen] != '\\')) |
1198 return None; | 1204 return std::nullopt; |
1199 | 1205 |
1200 SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + | 1206 SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + |
1201 FrameworkPos + | 1207 FrameworkPos + |
1202 DotFrameworkLen + 1); | 1208 DotFrameworkLen + 1); |
1203 | 1209 |
1213 // Some other location? | 1219 // Some other location? |
1214 if (CacheLookup.second.Directory && | 1220 if (CacheLookup.second.Directory && |
1215 CacheLookup.first().size() == FrameworkName.size() && | 1221 CacheLookup.first().size() == FrameworkName.size() && |
1216 memcmp(CacheLookup.first().data(), &FrameworkName[0], | 1222 memcmp(CacheLookup.first().data(), &FrameworkName[0], |
1217 CacheLookup.first().size()) != 0) | 1223 CacheLookup.first().size()) != 0) |
1218 return None; | 1224 return std::nullopt; |
1219 | 1225 |
1220 // Cache subframework. | 1226 // Cache subframework. |
1221 if (!CacheLookup.second.Directory) { | 1227 if (!CacheLookup.second.Directory) { |
1222 ++NumSubFrameworkLookups; | 1228 ++NumSubFrameworkLookups; |
1223 | 1229 |
1224 // If the framework dir doesn't exist, we fail. | 1230 // If the framework dir doesn't exist, we fail. |
1225 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName); | 1231 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName); |
1226 if (!Dir) | 1232 if (!Dir) |
1227 return None; | 1233 return std::nullopt; |
1228 | 1234 |
1229 // Otherwise, if it does, remember that this is the right direntry for this | 1235 // Otherwise, if it does, remember that this is the right direntry for this |
1230 // framework. | 1236 // framework. |
1231 CacheLookup.second.Directory = Dir; | 1237 CacheLookup.second.Directory = Dir; |
1232 } | 1238 } |
1260 | 1266 |
1261 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); | 1267 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); |
1262 File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); | 1268 File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); |
1263 | 1269 |
1264 if (!File) | 1270 if (!File) |
1265 return None; | 1271 return std::nullopt; |
1266 } | 1272 } |
1267 | 1273 |
1268 // This file is a system header or C++ unfriendly if the old file is. | 1274 // This file is a system header or C++ unfriendly if the old file is. |
1269 // | 1275 // |
1270 // Note that the temporary 'DirInfo' is required here, as either call to | 1276 // Note that the temporary 'DirInfo' is required here, as either call to |
1272 // of evaluation. | 1278 // of evaluation. |
1273 unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; | 1279 unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; |
1274 getFileInfo(&File->getFileEntry()).DirInfo = DirInfo; | 1280 getFileInfo(&File->getFileEntry()).DirInfo = DirInfo; |
1275 | 1281 |
1276 FrameworkName.pop_back(); // remove the trailing '/' | 1282 FrameworkName.pop_back(); // remove the trailing '/' |
1277 if (!findUsableModuleForFrameworkHeader(&File->getFileEntry(), FrameworkName, | 1283 if (!findUsableModuleForFrameworkHeader(*File, FrameworkName, |
1278 RequestingModule, SuggestedModule, | 1284 RequestingModule, SuggestedModule, |
1279 /*IsSystem*/ false)) | 1285 /*IsSystem*/ false)) |
1280 return None; | 1286 return std::nullopt; |
1281 | 1287 |
1282 return *File; | 1288 return *File; |
1283 } | 1289 } |
1284 | 1290 |
1285 //===----------------------------------------------------------------------===// | 1291 //===----------------------------------------------------------------------===// |
1368 return nullptr; | 1374 return nullptr; |
1369 | 1375 |
1370 return HFI; | 1376 return HFI; |
1371 } | 1377 } |
1372 | 1378 |
1373 bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { | 1379 bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) const { |
1374 // Check if we've entered this file and found an include guard or #pragma | 1380 // Check if we've entered this file and found an include guard or #pragma |
1375 // once. Note that we dor't check for #import, because that's not a property | 1381 // once. Note that we dor't check for #import, because that's not a property |
1376 // of the file itself. | 1382 // of the file itself. |
1377 if (auto *HFI = getExistingFileInfo(File)) | 1383 if (auto *HFI = getExistingFileInfo(File)) |
1378 return HFI->isPragmaOnce || HFI->ControllingMacro || | 1384 return HFI->isPragmaOnce || HFI->ControllingMacro || |
1552 FixUpDirectories.push_back(*Dir); | 1558 FixUpDirectories.push_back(*Dir); |
1553 } while (true); | 1559 } while (true); |
1554 } | 1560 } |
1555 | 1561 |
1556 ModuleMap::KnownHeader | 1562 ModuleMap::KnownHeader |
1557 HeaderSearch::findModuleForHeader(const FileEntry *File, bool AllowTextual, | 1563 HeaderSearch::findModuleForHeader(FileEntryRef File, bool AllowTextual, |
1558 bool AllowExcluded) const { | 1564 bool AllowExcluded) const { |
1559 if (ExternalSource) { | 1565 if (ExternalSource) { |
1560 // Make sure the external source has handled header info about this file, | 1566 // Make sure the external source has handled header info about this file, |
1561 // which includes whether the file is part of a module. | 1567 // which includes whether the file is part of a module. |
1562 (void)getExistingFileInfo(File); | 1568 (void)getExistingFileInfo(File); |
1563 } | 1569 } |
1564 return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded); | 1570 return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded); |
1565 } | 1571 } |
1566 | 1572 |
1567 ArrayRef<ModuleMap::KnownHeader> | 1573 ArrayRef<ModuleMap::KnownHeader> |
1568 HeaderSearch::findAllModulesForHeader(const FileEntry *File) const { | 1574 HeaderSearch::findAllModulesForHeader(FileEntryRef File) const { |
1569 if (ExternalSource) { | 1575 if (ExternalSource) { |
1570 // Make sure the external source has handled header info about this file, | 1576 // Make sure the external source has handled header info about this file, |
1571 // which includes whether the file is part of a module. | 1577 // which includes whether the file is part of a module. |
1572 (void)getExistingFileInfo(File); | 1578 (void)getExistingFileInfo(File); |
1573 } | 1579 } |
1574 return ModMap.findAllModulesForHeader(File); | 1580 return ModMap.findAllModulesForHeader(File); |
1575 } | 1581 } |
1576 | 1582 |
1577 static bool suggestModule(HeaderSearch &HS, const FileEntry *File, | 1583 ArrayRef<ModuleMap::KnownHeader> |
1584 HeaderSearch::findResolvedModulesForHeader(const FileEntry *File) const { | |
1585 if (ExternalSource) { | |
1586 // Make sure the external source has handled header info about this file, | |
1587 // which includes whether the file is part of a module. | |
1588 (void)getExistingFileInfo(File); | |
1589 } | |
1590 return ModMap.findResolvedModulesForHeader(File); | |
1591 } | |
1592 | |
1593 static bool suggestModule(HeaderSearch &HS, FileEntryRef File, | |
1578 Module *RequestingModule, | 1594 Module *RequestingModule, |
1579 ModuleMap::KnownHeader *SuggestedModule) { | 1595 ModuleMap::KnownHeader *SuggestedModule) { |
1580 ModuleMap::KnownHeader Module = | 1596 ModuleMap::KnownHeader Module = |
1581 HS.findModuleForHeader(File, /*AllowTextual*/true); | 1597 HS.findModuleForHeader(File, /*AllowTextual*/true); |
1582 | 1598 |
1608 | 1624 |
1609 return true; | 1625 return true; |
1610 } | 1626 } |
1611 | 1627 |
1612 bool HeaderSearch::findUsableModuleForHeader( | 1628 bool HeaderSearch::findUsableModuleForHeader( |
1613 const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, | 1629 FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule, |
1614 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { | 1630 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { |
1615 if (File && needModuleLookup(RequestingModule, SuggestedModule)) { | 1631 if (needModuleLookup(RequestingModule, SuggestedModule)) { |
1616 // If there is a module that corresponds to this header, suggest it. | 1632 // If there is a module that corresponds to this header, suggest it. |
1617 hasModuleMap(File->getName(), Root, IsSystemHeaderDir); | 1633 hasModuleMap(File.getName(), Root, IsSystemHeaderDir); |
1618 return suggestModule(*this, File, RequestingModule, SuggestedModule); | 1634 return suggestModule(*this, File, RequestingModule, SuggestedModule); |
1619 } | 1635 } |
1620 return true; | 1636 return true; |
1621 } | 1637 } |
1622 | 1638 |
1623 bool HeaderSearch::findUsableModuleForFrameworkHeader( | 1639 bool HeaderSearch::findUsableModuleForFrameworkHeader( |
1624 const FileEntry *File, StringRef FrameworkName, Module *RequestingModule, | 1640 FileEntryRef File, StringRef FrameworkName, Module *RequestingModule, |
1625 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { | 1641 ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { |
1626 // If we're supposed to suggest a module, look for one now. | 1642 // If we're supposed to suggest a module, look for one now. |
1627 if (needModuleLookup(RequestingModule, SuggestedModule)) { | 1643 if (needModuleLookup(RequestingModule, SuggestedModule)) { |
1628 // Find the top-level framework based on this framework. | 1644 // Find the top-level framework based on this framework. |
1629 SmallVector<std::string, 4> SubmodulePath; | 1645 SmallVector<std::string, 4> SubmodulePath; |
1630 Optional<DirectoryEntryRef> TopFrameworkDir = | 1646 OptionalDirectoryEntryRef TopFrameworkDir = |
1631 ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); | 1647 ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); |
1632 assert(TopFrameworkDir && "Could not find the top-most framework dir"); | 1648 assert(TopFrameworkDir && "Could not find the top-most framework dir"); |
1633 | 1649 |
1634 // Determine the name of the top-level framework. | 1650 // Determine the name of the top-level framework. |
1635 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); | 1651 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); |
1645 return suggestModule(*this, File, RequestingModule, SuggestedModule); | 1661 return suggestModule(*this, File, RequestingModule, SuggestedModule); |
1646 } | 1662 } |
1647 return true; | 1663 return true; |
1648 } | 1664 } |
1649 | 1665 |
1650 static const FileEntry *getPrivateModuleMap(const FileEntry *File, | 1666 static const FileEntry *getPrivateModuleMap(FileEntryRef File, |
1651 FileManager &FileMgr) { | 1667 FileManager &FileMgr) { |
1652 StringRef Filename = llvm::sys::path::filename(File->getName()); | 1668 StringRef Filename = llvm::sys::path::filename(File.getName()); |
1653 SmallString<128> PrivateFilename(File->getDir()->getName()); | 1669 SmallString<128> PrivateFilename(File.getDir().getName()); |
1654 if (Filename == "module.map") | 1670 if (Filename == "module.map") |
1655 llvm::sys::path::append(PrivateFilename, "module_private.map"); | 1671 llvm::sys::path::append(PrivateFilename, "module_private.map"); |
1656 else if (Filename == "module.modulemap") | 1672 else if (Filename == "module.modulemap") |
1657 llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); | 1673 llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); |
1658 else | 1674 else |
1660 if (auto File = FileMgr.getFile(PrivateFilename)) | 1676 if (auto File = FileMgr.getFile(PrivateFilename)) |
1661 return *File; | 1677 return *File; |
1662 return nullptr; | 1678 return nullptr; |
1663 } | 1679 } |
1664 | 1680 |
1665 bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, | 1681 bool HeaderSearch::loadModuleMapFile(FileEntryRef File, bool IsSystem, |
1666 FileID ID, unsigned *Offset, | 1682 FileID ID, unsigned *Offset, |
1667 StringRef OriginalModuleMapFile) { | 1683 StringRef OriginalModuleMapFile) { |
1668 // Find the directory for the module. For frameworks, that may require going | 1684 // Find the directory for the module. For frameworks, that may require going |
1669 // up from the 'Modules' directory. | 1685 // up from the 'Modules' directory. |
1670 Optional<DirectoryEntryRef> Dir; | 1686 OptionalDirectoryEntryRef Dir; |
1671 if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) { | 1687 if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) { |
1672 Dir = FileMgr.getOptionalDirectoryRef("."); | 1688 Dir = FileMgr.getOptionalDirectoryRef("."); |
1673 } else { | 1689 } else { |
1674 if (!OriginalModuleMapFile.empty()) { | 1690 if (!OriginalModuleMapFile.empty()) { |
1675 // We're building a preprocessed module map. Find or invent the directory | 1691 // We're building a preprocessed module map. Find or invent the directory |
1679 if (!Dir) { | 1695 if (!Dir) { |
1680 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0); | 1696 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0); |
1681 Dir = FakeFile.getDir(); | 1697 Dir = FakeFile.getDir(); |
1682 } | 1698 } |
1683 } else { | 1699 } else { |
1684 // TODO: Replace with `Dir = File.getDir()` when `File` is switched to | 1700 Dir = File.getDir(); |
1685 // `FileEntryRef`. | |
1686 Dir = FileMgr.getOptionalDirectoryRef(File->getDir()->getName()); | |
1687 } | 1701 } |
1688 | 1702 |
1689 assert(Dir && "parent must exist"); | 1703 assert(Dir && "parent must exist"); |
1690 StringRef DirName(Dir->getName()); | 1704 StringRef DirName(Dir->getName()); |
1691 if (llvm::sys::path::filename(DirName) == "Modules") { | 1705 if (llvm::sys::path::filename(DirName) == "Modules") { |
1710 } | 1724 } |
1711 llvm_unreachable("Unknown load module map result"); | 1725 llvm_unreachable("Unknown load module map result"); |
1712 } | 1726 } |
1713 | 1727 |
1714 HeaderSearch::LoadModuleMapResult | 1728 HeaderSearch::LoadModuleMapResult |
1715 HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, | 1729 HeaderSearch::loadModuleMapFileImpl(FileEntryRef File, bool IsSystem, |
1716 DirectoryEntryRef Dir, FileID ID, | 1730 DirectoryEntryRef Dir, FileID ID, |
1717 unsigned *Offset) { | 1731 unsigned *Offset) { |
1718 assert(File && "expected FileEntry"); | |
1719 | |
1720 // Check whether we've already loaded this module map, and mark it as being | 1732 // Check whether we've already loaded this module map, and mark it as being |
1721 // loaded in case we recursively try to load it from itself. | 1733 // loaded in case we recursively try to load it from itself. |
1722 auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true)); | 1734 auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true)); |
1723 if (!AddResult.second) | 1735 if (!AddResult.second) |
1724 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; | 1736 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; |
1738 | 1750 |
1739 // This directory has a module map. | 1751 // This directory has a module map. |
1740 return LMM_NewlyLoaded; | 1752 return LMM_NewlyLoaded; |
1741 } | 1753 } |
1742 | 1754 |
1743 const FileEntry * | 1755 OptionalFileEntryRef |
1744 HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) { | 1756 HeaderSearch::lookupModuleMapFile(DirectoryEntryRef Dir, bool IsFramework) { |
1745 if (!HSOpts->ImplicitModuleMaps) | 1757 if (!HSOpts->ImplicitModuleMaps) |
1746 return nullptr; | 1758 return std::nullopt; |
1747 // For frameworks, the preferred spelling is Modules/module.modulemap, but | 1759 // For frameworks, the preferred spelling is Modules/module.modulemap, but |
1748 // module.map at the framework root is also accepted. | 1760 // module.map at the framework root is also accepted. |
1749 SmallString<128> ModuleMapFileName(Dir->getName()); | 1761 SmallString<128> ModuleMapFileName(Dir.getName()); |
1750 if (IsFramework) | 1762 if (IsFramework) |
1751 llvm::sys::path::append(ModuleMapFileName, "Modules"); | 1763 llvm::sys::path::append(ModuleMapFileName, "Modules"); |
1752 llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); | 1764 llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); |
1753 if (auto F = FileMgr.getFile(ModuleMapFileName)) | 1765 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) |
1754 return *F; | 1766 return *F; |
1755 | 1767 |
1756 // Continue to allow module.map | 1768 // Continue to allow module.map |
1757 ModuleMapFileName = Dir->getName(); | 1769 ModuleMapFileName = Dir.getName(); |
1758 llvm::sys::path::append(ModuleMapFileName, "module.map"); | 1770 llvm::sys::path::append(ModuleMapFileName, "module.map"); |
1759 if (auto F = FileMgr.getFile(ModuleMapFileName)) | 1771 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) |
1760 return *F; | 1772 return *F; |
1761 | 1773 |
1762 // For frameworks, allow to have a private module map with a preferred | 1774 // For frameworks, allow to have a private module map with a preferred |
1763 // spelling when a public module map is absent. | 1775 // spelling when a public module map is absent. |
1764 if (IsFramework) { | 1776 if (IsFramework) { |
1765 ModuleMapFileName = Dir->getName(); | 1777 ModuleMapFileName = Dir.getName(); |
1766 llvm::sys::path::append(ModuleMapFileName, "Modules", | 1778 llvm::sys::path::append(ModuleMapFileName, "Modules", |
1767 "module.private.modulemap"); | 1779 "module.private.modulemap"); |
1768 if (auto F = FileMgr.getFile(ModuleMapFileName)) | 1780 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) |
1769 return *F; | 1781 return *F; |
1770 } | 1782 } |
1771 return nullptr; | 1783 return std::nullopt; |
1772 } | 1784 } |
1773 | 1785 |
1774 Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir, | 1786 Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir, |
1775 bool IsSystem) { | 1787 bool IsSystem) { |
1776 if (Module *Module = ModMap.findModule(Name)) | |
1777 return Module; | |
1778 | |
1779 // Try to load a module map file. | 1788 // Try to load a module map file. |
1780 switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) { | 1789 switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) { |
1781 case LMM_InvalidModuleMap: | 1790 case LMM_InvalidModuleMap: |
1782 // Try to infer a module map from the framework directory. | 1791 // Try to infer a module map from the framework directory. |
1783 if (HSOpts->ImplicitModuleMaps) | 1792 if (HSOpts->ImplicitModuleMaps) |
1784 ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr); | 1793 ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr); |
1785 break; | 1794 break; |
1786 | 1795 |
1787 case LMM_AlreadyLoaded: | |
1788 case LMM_NoDirectory: | 1796 case LMM_NoDirectory: |
1789 return nullptr; | 1797 return nullptr; |
1790 | 1798 |
1799 case LMM_AlreadyLoaded: | |
1791 case LMM_NewlyLoaded: | 1800 case LMM_NewlyLoaded: |
1792 break; | 1801 break; |
1793 } | 1802 } |
1794 | 1803 |
1795 return ModMap.findModule(Name); | 1804 return ModMap.findModule(Name); |
1809 bool IsFramework) { | 1818 bool IsFramework) { |
1810 auto KnownDir = DirectoryHasModuleMap.find(Dir); | 1819 auto KnownDir = DirectoryHasModuleMap.find(Dir); |
1811 if (KnownDir != DirectoryHasModuleMap.end()) | 1820 if (KnownDir != DirectoryHasModuleMap.end()) |
1812 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; | 1821 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; |
1813 | 1822 |
1814 if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { | 1823 if (OptionalFileEntryRef ModuleMapFile = |
1824 lookupModuleMapFile(Dir, IsFramework)) { | |
1815 LoadModuleMapResult Result = | 1825 LoadModuleMapResult Result = |
1816 loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir); | 1826 loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir); |
1817 // Add Dir explicitly in case ModuleMapFile is in a subdirectory. | 1827 // Add Dir explicitly in case ModuleMapFile is in a subdirectory. |
1818 // E.g. Foo.framework/Modules/module.modulemap | 1828 // E.g. Foo.framework/Modules/module.modulemap |
1819 // ^Dir ^ModuleMapFile | 1829 // ^Dir ^ModuleMapFile |
1820 if (Result == LMM_NewlyLoaded) | 1830 if (Result == LMM_NewlyLoaded) |
1821 DirectoryHasModuleMap[Dir] = true; | 1831 DirectoryHasModuleMap[Dir] = true; |
1834 for (DirectoryLookup &DL : search_dir_range()) { | 1844 for (DirectoryLookup &DL : search_dir_range()) { |
1835 bool IsSystem = DL.isSystemHeaderDirectory(); | 1845 bool IsSystem = DL.isSystemHeaderDirectory(); |
1836 if (DL.isFramework()) { | 1846 if (DL.isFramework()) { |
1837 std::error_code EC; | 1847 std::error_code EC; |
1838 SmallString<128> DirNative; | 1848 SmallString<128> DirNative; |
1839 llvm::sys::path::native(DL.getFrameworkDir()->getName(), DirNative); | 1849 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative); |
1840 | 1850 |
1841 // Search each of the ".framework" directories to load them as modules. | 1851 // Search each of the ".framework" directories to load them as modules. |
1842 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); | 1852 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); |
1843 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), | 1853 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), |
1844 DirEnd; | 1854 DirEnd; |
1897 | 1907 |
1898 if (SearchDir.haveSearchedAllModuleMaps()) | 1908 if (SearchDir.haveSearchedAllModuleMaps()) |
1899 return; | 1909 return; |
1900 | 1910 |
1901 std::error_code EC; | 1911 std::error_code EC; |
1902 SmallString<128> Dir = SearchDir.getDir()->getName(); | 1912 SmallString<128> Dir = SearchDir.getDirRef()->getName(); |
1903 FileMgr.makeAbsolutePath(Dir); | 1913 FileMgr.makeAbsolutePath(Dir); |
1904 SmallString<128> DirNative; | 1914 SmallString<128> DirNative; |
1905 llvm::sys::path::native(Dir, DirNative); | 1915 llvm::sys::path::native(Dir, DirNative); |
1906 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); | 1916 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); |
1907 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; | 1917 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; |
1908 Dir != DirEnd && !EC; Dir.increment(EC)) { | 1918 Dir != DirEnd && !EC; Dir.increment(EC)) { |
1919 if (Dir->type() == llvm::sys::fs::file_type::regular_file) | |
1920 continue; | |
1909 bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework"; | 1921 bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework"; |
1910 if (IsFramework == SearchDir.isFramework()) | 1922 if (IsFramework == SearchDir.isFramework()) |
1911 loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), | 1923 loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), |
1912 SearchDir.isFramework()); | 1924 SearchDir.isFramework()); |
1913 } | 1925 } |
1914 | 1926 |
1915 SearchDir.setSearchedAllModuleMaps(true); | 1927 SearchDir.setSearchedAllModuleMaps(true); |
1916 } | 1928 } |
1917 | 1929 |
1918 std::string HeaderSearch::suggestPathToFileForDiagnostics( | 1930 std::string HeaderSearch::suggestPathToFileForDiagnostics( |
1919 const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) { | 1931 const FileEntry *File, llvm::StringRef MainFile, bool *IsAngled) const { |
1920 // FIXME: We assume that the path name currently cached in the FileEntry is | 1932 // FIXME: We assume that the path name currently cached in the FileEntry is |
1921 // the most appropriate one for this analysis (and that it's spelled the | 1933 // the most appropriate one for this analysis (and that it's spelled the |
1922 // same way as the corresponding header search path). | 1934 // same way as the corresponding header search path). |
1923 return suggestPathToFileForDiagnostics(File->getName(), /*WorkingDir=*/"", | 1935 return suggestPathToFileForDiagnostics(File->getName(), /*WorkingDir=*/"", |
1924 MainFile, IsSystem); | 1936 MainFile, IsAngled); |
1925 } | 1937 } |
1926 | 1938 |
1927 std::string HeaderSearch::suggestPathToFileForDiagnostics( | 1939 std::string HeaderSearch::suggestPathToFileForDiagnostics( |
1928 llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile, | 1940 llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile, |
1929 bool *IsSystem) { | 1941 bool *IsAngled) const { |
1930 using namespace llvm::sys; | 1942 using namespace llvm::sys; |
1943 | |
1944 llvm::SmallString<32> FilePath = File; | |
1945 // remove_dots switches to backslashes on windows as a side-effect! | |
1946 // We always want to suggest forward slashes for includes. | |
1947 // (not remove_dots(..., posix) as that misparses windows paths). | |
1948 path::remove_dots(FilePath, /*remove_dot_dot=*/true); | |
1949 path::native(FilePath, path::Style::posix); | |
1950 File = FilePath; | |
1931 | 1951 |
1932 unsigned BestPrefixLength = 0; | 1952 unsigned BestPrefixLength = 0; |
1933 // Checks whether `Dir` is a strict path prefix of `File`. If so and that's | 1953 // Checks whether `Dir` is a strict path prefix of `File`. If so and that's |
1934 // the longest prefix we've seen so for it, returns true and updates the | 1954 // the longest prefix we've seen so for it, returns true and updates the |
1935 // `BestPrefixLength` accordingly. | 1955 // `BestPrefixLength` accordingly. |
1936 auto CheckDir = [&](llvm::StringRef Dir) -> bool { | 1956 auto CheckDir = [&](llvm::SmallString<32> Dir) -> bool { |
1937 llvm::SmallString<32> DirPath(Dir.begin(), Dir.end()); | |
1938 if (!WorkingDir.empty() && !path::is_absolute(Dir)) | 1957 if (!WorkingDir.empty() && !path::is_absolute(Dir)) |
1939 fs::make_absolute(WorkingDir, DirPath); | 1958 fs::make_absolute(WorkingDir, Dir); |
1940 path::remove_dots(DirPath, /*remove_dot_dot=*/true); | 1959 path::remove_dots(Dir, /*remove_dot_dot=*/true); |
1941 Dir = DirPath; | |
1942 for (auto NI = path::begin(File), NE = path::end(File), | 1960 for (auto NI = path::begin(File), NE = path::end(File), |
1943 DI = path::begin(Dir), DE = path::end(Dir); | 1961 DI = path::begin(Dir), DE = path::end(Dir); |
1944 /*termination condition in loop*/; ++NI, ++DI) { | 1962 NI != NE; ++NI, ++DI) { |
1945 // '.' components in File are ignored. | |
1946 while (NI != NE && *NI == ".") | |
1947 ++NI; | |
1948 if (NI == NE) | |
1949 break; | |
1950 | |
1951 // '.' components in Dir are ignored. | |
1952 while (DI != DE && *DI == ".") | |
1953 ++DI; | |
1954 if (DI == DE) { | 1963 if (DI == DE) { |
1955 // Dir is a prefix of File, up to '.' components and choice of path | 1964 // Dir is a prefix of File, up to choice of path separators. |
1956 // separators. | |
1957 unsigned PrefixLength = NI - path::begin(File); | 1965 unsigned PrefixLength = NI - path::begin(File); |
1958 if (PrefixLength > BestPrefixLength) { | 1966 if (PrefixLength > BestPrefixLength) { |
1959 BestPrefixLength = PrefixLength; | 1967 BestPrefixLength = PrefixLength; |
1960 return true; | 1968 return true; |
1961 } | 1969 } |
1984 }; | 1992 }; |
1985 | 1993 |
1986 bool BestPrefixIsFramework = false; | 1994 bool BestPrefixIsFramework = false; |
1987 for (const DirectoryLookup &DL : search_dir_range()) { | 1995 for (const DirectoryLookup &DL : search_dir_range()) { |
1988 if (DL.isNormalDir()) { | 1996 if (DL.isNormalDir()) { |
1989 StringRef Dir = DL.getDir()->getName(); | 1997 StringRef Dir = DL.getDirRef()->getName(); |
1990 if (CheckDir(Dir)) { | 1998 if (CheckDir(Dir)) { |
1991 if (IsSystem) | 1999 if (IsAngled) |
1992 *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic()); | 2000 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic()); |
1993 BestPrefixIsFramework = false; | 2001 BestPrefixIsFramework = false; |
1994 } | 2002 } |
1995 } else if (DL.isFramework()) { | 2003 } else if (DL.isFramework()) { |
1996 StringRef Dir = DL.getFrameworkDir()->getName(); | 2004 StringRef Dir = DL.getFrameworkDirRef()->getName(); |
1997 if (CheckDir(Dir)) { | 2005 if (CheckDir(Dir)) { |
1998 if (IsSystem) | 2006 // Framework includes by convention use <>. |
1999 *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic()); | 2007 if (IsAngled) |
2008 *IsAngled = BestPrefixLength; | |
2000 BestPrefixIsFramework = true; | 2009 BestPrefixIsFramework = true; |
2001 } | 2010 } |
2002 } | 2011 } |
2003 } | 2012 } |
2004 | 2013 |
2005 // Try to shorten include path using TUs directory, if we couldn't find any | 2014 // Try to shorten include path using TUs directory, if we couldn't find any |
2006 // suitable prefix in include search paths. | 2015 // suitable prefix in include search paths. |
2007 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) { | 2016 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) { |
2008 if (IsSystem) | 2017 if (IsAngled) |
2009 *IsSystem = false; | 2018 *IsAngled = false; |
2010 BestPrefixIsFramework = false; | 2019 BestPrefixIsFramework = false; |
2011 } | 2020 } |
2012 | 2021 |
2013 // Try resolving resulting filename via reverse search in header maps, | 2022 // Try resolving resulting filename via reverse search in header maps, |
2014 // key from header name is user preferred name for the include file. | 2023 // key from header name is user preferred name for the include file. |