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