1 //===--- HeaderSearch.cpp - Resolve Header File Locations ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the DirectoryLookup and HeaderSearch interfaces. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Lex/HeaderSearch.h" 15 #include "clang/Lex/HeaderMap.h" 16 #include "clang/Basic/FileManager.h" 17 #include "clang/Basic/IdentifierTable.h" 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/Support/Capacity.h" 22 #include <cstdio> 23 using namespace clang; 24 25 const IdentifierInfo * 26 HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { 27 if (ControllingMacro) 28 return ControllingMacro; 29 30 if (!ControllingMacroID || !External) 31 return 0; 32 33 ControllingMacro = External->GetIdentifier(ControllingMacroID); 34 return ControllingMacro; 35 } 36 37 ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} 38 39 HeaderSearch::HeaderSearch(FileManager &FM) 40 : FileMgr(FM), FrameworkMap(64) { 41 AngledDirIdx = 0; 42 SystemDirIdx = 0; 43 NoCurDirSearch = false; 44 45 ExternalLookup = 0; 46 ExternalSource = 0; 47 NumIncluded = 0; 48 NumMultiIncludeFileOptzn = 0; 49 NumFrameworkLookups = NumSubFrameworkLookups = 0; 50 } 51 52 HeaderSearch::~HeaderSearch() { 53 // Delete headermaps. 54 for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 55 delete HeaderMaps[i].second; 56 } 57 58 void HeaderSearch::PrintStats() { 59 fprintf(stderr, "\n*** HeaderSearch Stats:\n"); 60 fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); 61 unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; 62 for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { 63 NumOnceOnlyFiles += FileInfo[i].isImport; 64 if (MaxNumIncludes < FileInfo[i].NumIncludes) 65 MaxNumIncludes = FileInfo[i].NumIncludes; 66 NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; 67 } 68 fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); 69 fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); 70 fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); 71 72 fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); 73 fprintf(stderr, " %d #includes skipped due to" 74 " the multi-include optimization.\n", NumMultiIncludeFileOptzn); 75 76 fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); 77 fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); 78 } 79 80 /// CreateHeaderMap - This method returns a HeaderMap for the specified 81 /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. 82 const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { 83 // We expect the number of headermaps to be small, and almost always empty. 84 // If it ever grows, use of a linear search should be re-evaluated. 85 if (!HeaderMaps.empty()) { 86 for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 87 // Pointer equality comparison of FileEntries works because they are 88 // already uniqued by inode. 89 if (HeaderMaps[i].first == FE) 90 return HeaderMaps[i].second; 91 } 92 93 if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) { 94 HeaderMaps.push_back(std::make_pair(FE, HM)); 95 return HM; 96 } 97 98 return 0; 99 } 100 101 const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName, 102 std::string *ModuleFileName, 103 std::string *UmbrellaHeader) { 104 // If we don't have a module cache path, we can't do anything. 105 if (ModuleCachePath.empty()) { 106 if (ModuleFileName) 107 ModuleFileName->clear(); 108 return 0; 109 } 110 111 // Try to find the module path. 112 llvm::SmallString<256> FileName(ModuleCachePath); 113 llvm::sys::path::append(FileName, ModuleName + ".pcm"); 114 if (ModuleFileName) 115 *ModuleFileName = FileName.str(); 116 117 if (const FileEntry *ModuleFile 118 = getFileMgr().getFile(FileName, /*OpenFile=*/false, 119 /*CacheFailure=*/false)) 120 return ModuleFile; 121 122 // We didn't find the module. If we're not supposed to look for an 123 // umbrella header, this is the end of the road. 124 if (!UmbrellaHeader) 125 return 0; 126 127 // Look in each of the framework directories for an umbrella header with 128 // the same name as the module. 129 // FIXME: We need a way for non-frameworks to provide umbrella headers. 130 llvm::SmallString<128> UmbrellaHeaderName; 131 UmbrellaHeaderName = ModuleName; 132 UmbrellaHeaderName += '/'; 133 UmbrellaHeaderName += ModuleName; 134 UmbrellaHeaderName += ".h"; 135 for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { 136 // Skip non-framework include paths 137 if (!SearchDirs[Idx].isFramework()) 138 continue; 139 140 // Look for the umbrella header in this directory. 141 if (const FileEntry *HeaderFile 142 = SearchDirs[Idx].LookupFile(UmbrellaHeaderName, *this, 0, 0, 143 StringRef(), 0)) { 144 *UmbrellaHeader = HeaderFile->getName(); 145 return 0; 146 } 147 } 148 149 // We did not find an umbrella header. Clear out the UmbrellaHeader pointee 150 // so our caller knows that we failed. 151 UmbrellaHeader->clear(); 152 return 0; 153 } 154 155 //===----------------------------------------------------------------------===// 156 // File lookup within a DirectoryLookup scope 157 //===----------------------------------------------------------------------===// 158 159 /// getName - Return the directory or filename corresponding to this lookup 160 /// object. 161 const char *DirectoryLookup::getName() const { 162 if (isNormalDir()) 163 return getDir()->getName(); 164 if (isFramework()) 165 return getFrameworkDir()->getName(); 166 assert(isHeaderMap() && "Unknown DirectoryLookup"); 167 return getHeaderMap()->getFileName(); 168 } 169 170 171 /// LookupFile - Lookup the specified file in this search path, returning it 172 /// if it exists or returning null if not. 173 const FileEntry *DirectoryLookup::LookupFile( 174 StringRef Filename, 175 HeaderSearch &HS, 176 SmallVectorImpl<char> *SearchPath, 177 SmallVectorImpl<char> *RelativePath, 178 StringRef BuildingModule, 179 StringRef *SuggestedModule) const { 180 llvm::SmallString<1024> TmpDir; 181 if (isNormalDir()) { 182 // Concatenate the requested file onto the directory. 183 TmpDir = getDir()->getName(); 184 llvm::sys::path::append(TmpDir, Filename); 185 if (SearchPath != NULL) { 186 StringRef SearchPathRef(getDir()->getName()); 187 SearchPath->clear(); 188 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 189 } 190 if (RelativePath != NULL) { 191 RelativePath->clear(); 192 RelativePath->append(Filename.begin(), Filename.end()); 193 } 194 return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); 195 } 196 197 if (isFramework()) 198 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, 199 BuildingModule, SuggestedModule); 200 201 assert(isHeaderMap() && "Unknown directory lookup"); 202 const FileEntry * const Result = getHeaderMap()->LookupFile( 203 Filename, HS.getFileMgr()); 204 if (Result) { 205 if (SearchPath != NULL) { 206 StringRef SearchPathRef(getName()); 207 SearchPath->clear(); 208 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 209 } 210 if (RelativePath != NULL) { 211 RelativePath->clear(); 212 RelativePath->append(Filename.begin(), Filename.end()); 213 } 214 } 215 return Result; 216 } 217 218 219 /// DoFrameworkLookup - Do a lookup of the specified file in the current 220 /// DirectoryLookup, which is a framework directory. 221 const FileEntry *DirectoryLookup::DoFrameworkLookup( 222 StringRef Filename, 223 HeaderSearch &HS, 224 SmallVectorImpl<char> *SearchPath, 225 SmallVectorImpl<char> *RelativePath, 226 StringRef BuildingModule, 227 StringRef *SuggestedModule) const 228 { 229 FileManager &FileMgr = HS.getFileMgr(); 230 231 // Framework names must have a '/' in the filename. 232 size_t SlashPos = Filename.find('/'); 233 if (SlashPos == StringRef::npos) return 0; 234 235 // Find out if this is the home for the specified framework, by checking 236 // HeaderSearch. Possible answer are yes/no and unknown. 237 const DirectoryEntry *&FrameworkDirCache = 238 HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); 239 240 // If it is known and in some other directory, fail. 241 if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir()) 242 return 0; 243 244 // Otherwise, construct the path to this framework dir. 245 246 // FrameworkName = "/System/Library/Frameworks/" 247 llvm::SmallString<1024> FrameworkName; 248 FrameworkName += getFrameworkDir()->getName(); 249 if (FrameworkName.empty() || FrameworkName.back() != '/') 250 FrameworkName.push_back('/'); 251 252 // FrameworkName = "/System/Library/Frameworks/Cocoa" 253 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 254 255 // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" 256 FrameworkName += ".framework/"; 257 258 // If the cache entry is still unresolved, query to see if the cache entry is 259 // still unresolved. If so, check its existence now. 260 if (FrameworkDirCache == 0) { 261 HS.IncrementFrameworkLookupCount(); 262 263 // If the framework dir doesn't exist, we fail. 264 // FIXME: It's probably more efficient to query this with FileMgr.getDir. 265 bool Exists; 266 if (llvm::sys::fs::exists(FrameworkName.str(), Exists) || !Exists) 267 return 0; 268 269 // Otherwise, if it does, remember that this is the right direntry for this 270 // framework. 271 FrameworkDirCache = getFrameworkDir(); 272 } 273 274 if (RelativePath != NULL) { 275 RelativePath->clear(); 276 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 277 } 278 279 // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" 280 unsigned OrigSize = FrameworkName.size(); 281 282 FrameworkName += "Headers/"; 283 284 if (SearchPath != NULL) { 285 SearchPath->clear(); 286 // Without trailing '/'. 287 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); 288 } 289 290 /// Determine whether this is the module we're building or not. 291 bool AutomaticImport = SuggestedModule && 292 (BuildingModule != StringRef(Filename.begin(), SlashPos)); 293 294 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); 295 if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 296 /*openFile=*/!AutomaticImport)) { 297 if (AutomaticImport) 298 *SuggestedModule = StringRef(Filename.begin(), SlashPos); 299 return FE; 300 } 301 302 // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 303 const char *Private = "Private"; 304 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 305 Private+strlen(Private)); 306 if (SearchPath != NULL) 307 SearchPath->insert(SearchPath->begin()+OrigSize, Private, 308 Private+strlen(Private)); 309 310 const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 311 /*openFile=*/!AutomaticImport); 312 if (FE && AutomaticImport) 313 *SuggestedModule = StringRef(Filename.begin(), SlashPos); 314 return FE; 315 } 316 317 318 //===----------------------------------------------------------------------===// 319 // Header File Location. 320 //===----------------------------------------------------------------------===// 321 322 323 /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, 324 /// return null on failure. isAngled indicates whether the file reference is 325 /// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if 326 /// non-null, indicates where the #including file is, in case a relative search 327 /// is needed. 328 const FileEntry *HeaderSearch::LookupFile( 329 StringRef Filename, 330 bool isAngled, 331 const DirectoryLookup *FromDir, 332 const DirectoryLookup *&CurDir, 333 const FileEntry *CurFileEnt, 334 SmallVectorImpl<char> *SearchPath, 335 SmallVectorImpl<char> *RelativePath, 336 StringRef *SuggestedModule) 337 { 338 if (SuggestedModule) 339 *SuggestedModule = StringRef(); 340 341 // If 'Filename' is absolute, check to see if it exists and no searching. 342 if (llvm::sys::path::is_absolute(Filename)) { 343 CurDir = 0; 344 345 // If this was an #include_next "/absolute/file", fail. 346 if (FromDir) return 0; 347 348 if (SearchPath != NULL) 349 SearchPath->clear(); 350 if (RelativePath != NULL) { 351 RelativePath->clear(); 352 RelativePath->append(Filename.begin(), Filename.end()); 353 } 354 // Otherwise, just return the file. 355 return FileMgr.getFile(Filename, /*openFile=*/true); 356 } 357 358 // Unless disabled, check to see if the file is in the #includer's 359 // directory. This has to be based on CurFileEnt, not CurDir, because 360 // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and 361 // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". 362 // This search is not done for <> headers. 363 if (CurFileEnt && !isAngled && !NoCurDirSearch) { 364 llvm::SmallString<1024> TmpDir; 365 // Concatenate the requested file onto the directory. 366 // FIXME: Portability. Filename concatenation should be in sys::Path. 367 TmpDir += CurFileEnt->getDir()->getName(); 368 TmpDir.push_back('/'); 369 TmpDir.append(Filename.begin(), Filename.end()); 370 if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) { 371 // Leave CurDir unset. 372 // This file is a system header or C++ unfriendly if the old file is. 373 // 374 // Note that the temporary 'DirInfo' is required here, as either call to 375 // getFileInfo could resize the vector and we don't want to rely on order 376 // of evaluation. 377 unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; 378 getFileInfo(FE).DirInfo = DirInfo; 379 if (SearchPath != NULL) { 380 StringRef SearchPathRef(CurFileEnt->getDir()->getName()); 381 SearchPath->clear(); 382 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 383 } 384 if (RelativePath != NULL) { 385 RelativePath->clear(); 386 RelativePath->append(Filename.begin(), Filename.end()); 387 } 388 return FE; 389 } 390 } 391 392 CurDir = 0; 393 394 // If this is a system #include, ignore the user #include locs. 395 unsigned i = isAngled ? AngledDirIdx : 0; 396 397 // If this is a #include_next request, start searching after the directory the 398 // file was found in. 399 if (FromDir) 400 i = FromDir-&SearchDirs[0]; 401 402 // Cache all of the lookups performed by this method. Many headers are 403 // multiply included, and the "pragma once" optimization prevents them from 404 // being relex/pp'd, but they would still have to search through a 405 // (potentially huge) series of SearchDirs to find it. 406 std::pair<unsigned, unsigned> &CacheLookup = 407 LookupFileCache.GetOrCreateValue(Filename).getValue(); 408 409 // If the entry has been previously looked up, the first value will be 410 // non-zero. If the value is equal to i (the start point of our search), then 411 // this is a matching hit. 412 if (CacheLookup.first == i+1) { 413 // Skip querying potentially lots of directories for this lookup. 414 i = CacheLookup.second; 415 } else { 416 // Otherwise, this is the first query, or the previous query didn't match 417 // our search start. We will fill in our found location below, so prime the 418 // start point value. 419 CacheLookup.first = i+1; 420 } 421 422 // Check each directory in sequence to see if it contains this file. 423 for (; i != SearchDirs.size(); ++i) { 424 const FileEntry *FE = 425 SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, 426 BuildingModule, SuggestedModule); 427 if (!FE) continue; 428 429 CurDir = &SearchDirs[i]; 430 431 // This file is a system header or C++ unfriendly if the dir is. 432 HeaderFileInfo &HFI = getFileInfo(FE); 433 HFI.DirInfo = CurDir->getDirCharacteristic(); 434 435 // If this file is found in a header map and uses the framework style of 436 // includes, then this header is part of a framework we're building. 437 if (CurDir->isIndexHeaderMap()) { 438 size_t SlashPos = Filename.find('/'); 439 if (SlashPos != StringRef::npos) { 440 HFI.IndexHeaderMapHeader = 1; 441 HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), 442 SlashPos)); 443 } 444 } 445 446 // Remember this location for the next lookup we do. 447 CacheLookup.second = i; 448 return FE; 449 } 450 451 // If we are including a file with a quoted include "foo.h" from inside 452 // a header in a framework that is currently being built, and we couldn't 453 // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where 454 // "Foo" is the name of the framework in which the including header was found. 455 if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { 456 HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); 457 if (IncludingHFI.IndexHeaderMapHeader) { 458 llvm::SmallString<128> ScratchFilename; 459 ScratchFilename += IncludingHFI.Framework; 460 ScratchFilename += '/'; 461 ScratchFilename += Filename; 462 463 const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true, 464 FromDir, CurDir, CurFileEnt, 465 SearchPath, RelativePath, 466 SuggestedModule); 467 std::pair<unsigned, unsigned> &CacheLookup 468 = LookupFileCache.GetOrCreateValue(Filename).getValue(); 469 CacheLookup.second 470 = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second; 471 return Result; 472 } 473 } 474 475 // Otherwise, didn't find it. Remember we didn't find this. 476 CacheLookup.second = SearchDirs.size(); 477 return 0; 478 } 479 480 /// LookupSubframeworkHeader - Look up a subframework for the specified 481 /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from 482 /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 483 /// is a subframework within Carbon.framework. If so, return the FileEntry 484 /// for the designated file, otherwise return null. 485 const FileEntry *HeaderSearch:: 486 LookupSubframeworkHeader(StringRef Filename, 487 const FileEntry *ContextFileEnt, 488 SmallVectorImpl<char> *SearchPath, 489 SmallVectorImpl<char> *RelativePath) { 490 assert(ContextFileEnt && "No context file?"); 491 492 // Framework names must have a '/' in the filename. Find it. 493 size_t SlashPos = Filename.find('/'); 494 if (SlashPos == StringRef::npos) return 0; 495 496 // Look up the base framework name of the ContextFileEnt. 497 const char *ContextName = ContextFileEnt->getName(); 498 499 // If the context info wasn't a framework, couldn't be a subframework. 500 const char *FrameworkPos = strstr(ContextName, ".framework/"); 501 if (FrameworkPos == 0) 502 return 0; 503 504 llvm::SmallString<1024> FrameworkName(ContextName, 505 FrameworkPos+strlen(".framework/")); 506 507 // Append Frameworks/HIToolbox.framework/ 508 FrameworkName += "Frameworks/"; 509 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 510 FrameworkName += ".framework/"; 511 512 llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 513 FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); 514 515 // Some other location? 516 if (CacheLookup.getValue() && 517 CacheLookup.getKeyLength() == FrameworkName.size() && 518 memcmp(CacheLookup.getKeyData(), &FrameworkName[0], 519 CacheLookup.getKeyLength()) != 0) 520 return 0; 521 522 // Cache subframework. 523 if (CacheLookup.getValue() == 0) { 524 ++NumSubFrameworkLookups; 525 526 // If the framework dir doesn't exist, we fail. 527 const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); 528 if (Dir == 0) return 0; 529 530 // Otherwise, if it does, remember that this is the right direntry for this 531 // framework. 532 CacheLookup.setValue(Dir); 533 } 534 535 const FileEntry *FE = 0; 536 537 if (RelativePath != NULL) { 538 RelativePath->clear(); 539 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 540 } 541 542 // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 543 llvm::SmallString<1024> HeadersFilename(FrameworkName); 544 HeadersFilename += "Headers/"; 545 if (SearchPath != NULL) { 546 SearchPath->clear(); 547 // Without trailing '/'. 548 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 549 } 550 551 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 552 if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { 553 554 // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 555 HeadersFilename = FrameworkName; 556 HeadersFilename += "PrivateHeaders/"; 557 if (SearchPath != NULL) { 558 SearchPath->clear(); 559 // Without trailing '/'. 560 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 561 } 562 563 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 564 if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) 565 return 0; 566 } 567 568 // This file is a system header or C++ unfriendly if the old file is. 569 // 570 // Note that the temporary 'DirInfo' is required here, as either call to 571 // getFileInfo could resize the vector and we don't want to rely on order 572 // of evaluation. 573 unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; 574 getFileInfo(FE).DirInfo = DirInfo; 575 return FE; 576 } 577 578 //===----------------------------------------------------------------------===// 579 // File Info Management. 580 //===----------------------------------------------------------------------===// 581 582 583 /// getFileInfo - Return the HeaderFileInfo structure for the specified 584 /// FileEntry. 585 HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { 586 if (FE->getUID() >= FileInfo.size()) 587 FileInfo.resize(FE->getUID()+1); 588 589 HeaderFileInfo &HFI = FileInfo[FE->getUID()]; 590 if (ExternalSource && !HFI.Resolved) { 591 HFI = ExternalSource->GetHeaderFileInfo(FE); 592 HFI.Resolved = true; 593 } 594 return HFI; 595 } 596 597 bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { 598 // Check if we've ever seen this file as a header. 599 if (File->getUID() >= FileInfo.size()) 600 return false; 601 602 // Resolve header file info from the external source, if needed. 603 HeaderFileInfo &HFI = FileInfo[File->getUID()]; 604 if (ExternalSource && !HFI.Resolved) { 605 HFI = ExternalSource->GetHeaderFileInfo(File); 606 HFI.Resolved = true; 607 } 608 609 return HFI.isPragmaOnce || HFI.ControllingMacro || HFI.ControllingMacroID; 610 } 611 612 void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { 613 if (UID >= FileInfo.size()) 614 FileInfo.resize(UID+1); 615 HFI.Resolved = true; 616 FileInfo[UID] = HFI; 617 } 618 619 /// ShouldEnterIncludeFile - Mark the specified file as a target of of a 620 /// #include, #include_next, or #import directive. Return false if #including 621 /// the file will have no effect or true if we should include it. 622 bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ 623 ++NumIncluded; // Count # of attempted #includes. 624 625 // Get information about this file. 626 HeaderFileInfo &FileInfo = getFileInfo(File); 627 628 // If this is a #import directive, check that we have not already imported 629 // this header. 630 if (isImport) { 631 // If this has already been imported, don't import it again. 632 FileInfo.isImport = true; 633 634 // Has this already been #import'ed or #include'd? 635 if (FileInfo.NumIncludes) return false; 636 } else { 637 // Otherwise, if this is a #include of a file that was previously #import'd 638 // or if this is the second #include of a #pragma once file, ignore it. 639 if (FileInfo.isImport) 640 return false; 641 } 642 643 // Next, check to see if the file is wrapped with #ifndef guards. If so, and 644 // if the macro that guards it is defined, we know the #include has no effect. 645 if (const IdentifierInfo *ControllingMacro 646 = FileInfo.getControllingMacro(ExternalLookup)) 647 if (ControllingMacro->hasMacroDefinition()) { 648 ++NumMultiIncludeFileOptzn; 649 return false; 650 } 651 652 // Increment the number of times this file has been included. 653 ++FileInfo.NumIncludes; 654 655 return true; 656 } 657 658 size_t HeaderSearch::getTotalMemory() const { 659 return SearchDirs.capacity() 660 + llvm::capacity_in_bytes(FileInfo) 661 + llvm::capacity_in_bytes(HeaderMaps) 662 + LookupFileCache.getAllocator().getTotalMemory() 663 + FrameworkMap.getAllocator().getTotalMemory(); 664 } 665 666 StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { 667 return FrameworkNames.GetOrCreateValue(Framework).getKey(); 668 } 669