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 *UmbrellaHeader = HeaderFile->getName(); 144 return 0; 145 } 146 } 147 148 // We did not find an umbrella header. Clear out the UmbrellaHeader pointee 149 // so our caller knows that we failed. 150 UmbrellaHeader->clear(); 151 return 0; 152 } 153 154 //===----------------------------------------------------------------------===// 155 // File lookup within a DirectoryLookup scope 156 //===----------------------------------------------------------------------===// 157 158 /// getName - Return the directory or filename corresponding to this lookup 159 /// object. 160 const char *DirectoryLookup::getName() const { 161 if (isNormalDir()) 162 return getDir()->getName(); 163 if (isFramework()) 164 return getFrameworkDir()->getName(); 165 assert(isHeaderMap() && "Unknown DirectoryLookup"); 166 return getHeaderMap()->getFileName(); 167 } 168 169 170 /// LookupFile - Lookup the specified file in this search path, returning it 171 /// if it exists or returning null if not. 172 const FileEntry *DirectoryLookup::LookupFile( 173 StringRef Filename, 174 HeaderSearch &HS, 175 SmallVectorImpl<char> *SearchPath, 176 SmallVectorImpl<char> *RelativePath) const { 177 llvm::SmallString<1024> TmpDir; 178 if (isNormalDir()) { 179 // Concatenate the requested file onto the directory. 180 TmpDir = getDir()->getName(); 181 llvm::sys::path::append(TmpDir, Filename); 182 if (SearchPath != NULL) { 183 StringRef SearchPathRef(getDir()->getName()); 184 SearchPath->clear(); 185 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 186 } 187 if (RelativePath != NULL) { 188 RelativePath->clear(); 189 RelativePath->append(Filename.begin(), Filename.end()); 190 } 191 return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); 192 } 193 194 if (isFramework()) 195 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath); 196 197 assert(isHeaderMap() && "Unknown directory lookup"); 198 const FileEntry * const Result = getHeaderMap()->LookupFile( 199 Filename, HS.getFileMgr()); 200 if (Result) { 201 if (SearchPath != NULL) { 202 StringRef SearchPathRef(getName()); 203 SearchPath->clear(); 204 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 205 } 206 if (RelativePath != NULL) { 207 RelativePath->clear(); 208 RelativePath->append(Filename.begin(), Filename.end()); 209 } 210 } 211 return Result; 212 } 213 214 215 /// DoFrameworkLookup - Do a lookup of the specified file in the current 216 /// DirectoryLookup, which is a framework directory. 217 const FileEntry *DirectoryLookup::DoFrameworkLookup( 218 StringRef Filename, 219 HeaderSearch &HS, 220 SmallVectorImpl<char> *SearchPath, 221 SmallVectorImpl<char> *RelativePath) const { 222 FileManager &FileMgr = HS.getFileMgr(); 223 224 // Framework names must have a '/' in the filename. 225 size_t SlashPos = Filename.find('/'); 226 if (SlashPos == StringRef::npos) return 0; 227 228 // Find out if this is the home for the specified framework, by checking 229 // HeaderSearch. Possible answer are yes/no and unknown. 230 const DirectoryEntry *&FrameworkDirCache = 231 HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); 232 233 // If it is known and in some other directory, fail. 234 if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir()) 235 return 0; 236 237 // Otherwise, construct the path to this framework dir. 238 239 // FrameworkName = "/System/Library/Frameworks/" 240 llvm::SmallString<1024> FrameworkName; 241 FrameworkName += getFrameworkDir()->getName(); 242 if (FrameworkName.empty() || FrameworkName.back() != '/') 243 FrameworkName.push_back('/'); 244 245 // FrameworkName = "/System/Library/Frameworks/Cocoa" 246 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 247 248 // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" 249 FrameworkName += ".framework/"; 250 251 // If the cache entry is still unresolved, query to see if the cache entry is 252 // still unresolved. If so, check its existence now. 253 if (FrameworkDirCache == 0) { 254 HS.IncrementFrameworkLookupCount(); 255 256 // If the framework dir doesn't exist, we fail. 257 // FIXME: It's probably more efficient to query this with FileMgr.getDir. 258 bool Exists; 259 if (llvm::sys::fs::exists(FrameworkName.str(), Exists) || !Exists) 260 return 0; 261 262 // Otherwise, if it does, remember that this is the right direntry for this 263 // framework. 264 FrameworkDirCache = getFrameworkDir(); 265 } 266 267 if (RelativePath != NULL) { 268 RelativePath->clear(); 269 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 270 } 271 272 // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" 273 unsigned OrigSize = FrameworkName.size(); 274 275 FrameworkName += "Headers/"; 276 277 if (SearchPath != NULL) { 278 SearchPath->clear(); 279 // Without trailing '/'. 280 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); 281 } 282 283 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); 284 if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 285 /*openFile=*/true)) { 286 return FE; 287 } 288 289 // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 290 const char *Private = "Private"; 291 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 292 Private+strlen(Private)); 293 if (SearchPath != NULL) 294 SearchPath->insert(SearchPath->begin()+OrigSize, Private, 295 Private+strlen(Private)); 296 297 return FileMgr.getFile(FrameworkName.str(), /*openFile=*/true); 298 } 299 300 301 //===----------------------------------------------------------------------===// 302 // Header File Location. 303 //===----------------------------------------------------------------------===// 304 305 306 /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, 307 /// return null on failure. isAngled indicates whether the file reference is 308 /// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if 309 /// non-null, indicates where the #including file is, in case a relative search 310 /// is needed. 311 const FileEntry *HeaderSearch::LookupFile( 312 StringRef Filename, 313 bool isAngled, 314 const DirectoryLookup *FromDir, 315 const DirectoryLookup *&CurDir, 316 const FileEntry *CurFileEnt, 317 SmallVectorImpl<char> *SearchPath, 318 SmallVectorImpl<char> *RelativePath) { 319 // If 'Filename' is absolute, check to see if it exists and no searching. 320 if (llvm::sys::path::is_absolute(Filename)) { 321 CurDir = 0; 322 323 // If this was an #include_next "/absolute/file", fail. 324 if (FromDir) return 0; 325 326 if (SearchPath != NULL) 327 SearchPath->clear(); 328 if (RelativePath != NULL) { 329 RelativePath->clear(); 330 RelativePath->append(Filename.begin(), Filename.end()); 331 } 332 // Otherwise, just return the file. 333 return FileMgr.getFile(Filename, /*openFile=*/true); 334 } 335 336 // Unless disabled, check to see if the file is in the #includer's 337 // directory. This has to be based on CurFileEnt, not CurDir, because 338 // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and 339 // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". 340 // This search is not done for <> headers. 341 if (CurFileEnt && !isAngled && !NoCurDirSearch) { 342 llvm::SmallString<1024> TmpDir; 343 // Concatenate the requested file onto the directory. 344 // FIXME: Portability. Filename concatenation should be in sys::Path. 345 TmpDir += CurFileEnt->getDir()->getName(); 346 TmpDir.push_back('/'); 347 TmpDir.append(Filename.begin(), Filename.end()); 348 if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) { 349 // Leave CurDir unset. 350 // This file is a system header or C++ unfriendly if the old file is. 351 // 352 // Note that the temporary 'DirInfo' is required here, as either call to 353 // getFileInfo could resize the vector and we don't want to rely on order 354 // of evaluation. 355 unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; 356 getFileInfo(FE).DirInfo = DirInfo; 357 if (SearchPath != NULL) { 358 StringRef SearchPathRef(CurFileEnt->getDir()->getName()); 359 SearchPath->clear(); 360 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 361 } 362 if (RelativePath != NULL) { 363 RelativePath->clear(); 364 RelativePath->append(Filename.begin(), Filename.end()); 365 } 366 return FE; 367 } 368 } 369 370 CurDir = 0; 371 372 // If this is a system #include, ignore the user #include locs. 373 unsigned i = isAngled ? AngledDirIdx : 0; 374 375 // If this is a #include_next request, start searching after the directory the 376 // file was found in. 377 if (FromDir) 378 i = FromDir-&SearchDirs[0]; 379 380 // Cache all of the lookups performed by this method. Many headers are 381 // multiply included, and the "pragma once" optimization prevents them from 382 // being relex/pp'd, but they would still have to search through a 383 // (potentially huge) series of SearchDirs to find it. 384 std::pair<unsigned, unsigned> &CacheLookup = 385 LookupFileCache.GetOrCreateValue(Filename).getValue(); 386 387 // If the entry has been previously looked up, the first value will be 388 // non-zero. If the value is equal to i (the start point of our search), then 389 // this is a matching hit. 390 if (CacheLookup.first == i+1) { 391 // Skip querying potentially lots of directories for this lookup. 392 i = CacheLookup.second; 393 } else { 394 // Otherwise, this is the first query, or the previous query didn't match 395 // our search start. We will fill in our found location below, so prime the 396 // start point value. 397 CacheLookup.first = i+1; 398 } 399 400 // Check each directory in sequence to see if it contains this file. 401 for (; i != SearchDirs.size(); ++i) { 402 const FileEntry *FE = 403 SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath); 404 if (!FE) continue; 405 406 CurDir = &SearchDirs[i]; 407 408 // This file is a system header or C++ unfriendly if the dir is. 409 HeaderFileInfo &HFI = getFileInfo(FE); 410 HFI.DirInfo = CurDir->getDirCharacteristic(); 411 412 // If this file is found in a header map and uses the framework style of 413 // includes, then this header is part of a framework we're building. 414 if (CurDir->isIndexHeaderMap()) { 415 size_t SlashPos = Filename.find('/'); 416 if (SlashPos != StringRef::npos) { 417 HFI.IndexHeaderMapHeader = 1; 418 HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), 419 SlashPos)); 420 } 421 } 422 423 // Remember this location for the next lookup we do. 424 CacheLookup.second = i; 425 return FE; 426 } 427 428 // If we are including a file with a quoted include "foo.h" from inside 429 // a header in a framework that is currently being built, and we couldn't 430 // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where 431 // "Foo" is the name of the framework in which the including header was found. 432 if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { 433 HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); 434 if (IncludingHFI.IndexHeaderMapHeader) { 435 llvm::SmallString<128> ScratchFilename; 436 ScratchFilename += IncludingHFI.Framework; 437 ScratchFilename += '/'; 438 ScratchFilename += Filename; 439 440 const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true, 441 FromDir, CurDir, CurFileEnt, 442 SearchPath, RelativePath); 443 std::pair<unsigned, unsigned> &CacheLookup 444 = LookupFileCache.GetOrCreateValue(Filename).getValue(); 445 CacheLookup.second 446 = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second; 447 return Result; 448 } 449 } 450 451 // Otherwise, didn't find it. Remember we didn't find this. 452 CacheLookup.second = SearchDirs.size(); 453 return 0; 454 } 455 456 /// LookupSubframeworkHeader - Look up a subframework for the specified 457 /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from 458 /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 459 /// is a subframework within Carbon.framework. If so, return the FileEntry 460 /// for the designated file, otherwise return null. 461 const FileEntry *HeaderSearch:: 462 LookupSubframeworkHeader(StringRef Filename, 463 const FileEntry *ContextFileEnt, 464 SmallVectorImpl<char> *SearchPath, 465 SmallVectorImpl<char> *RelativePath) { 466 assert(ContextFileEnt && "No context file?"); 467 468 // Framework names must have a '/' in the filename. Find it. 469 size_t SlashPos = Filename.find('/'); 470 if (SlashPos == StringRef::npos) return 0; 471 472 // Look up the base framework name of the ContextFileEnt. 473 const char *ContextName = ContextFileEnt->getName(); 474 475 // If the context info wasn't a framework, couldn't be a subframework. 476 const char *FrameworkPos = strstr(ContextName, ".framework/"); 477 if (FrameworkPos == 0) 478 return 0; 479 480 llvm::SmallString<1024> FrameworkName(ContextName, 481 FrameworkPos+strlen(".framework/")); 482 483 // Append Frameworks/HIToolbox.framework/ 484 FrameworkName += "Frameworks/"; 485 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 486 FrameworkName += ".framework/"; 487 488 llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 489 FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); 490 491 // Some other location? 492 if (CacheLookup.getValue() && 493 CacheLookup.getKeyLength() == FrameworkName.size() && 494 memcmp(CacheLookup.getKeyData(), &FrameworkName[0], 495 CacheLookup.getKeyLength()) != 0) 496 return 0; 497 498 // Cache subframework. 499 if (CacheLookup.getValue() == 0) { 500 ++NumSubFrameworkLookups; 501 502 // If the framework dir doesn't exist, we fail. 503 const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); 504 if (Dir == 0) return 0; 505 506 // Otherwise, if it does, remember that this is the right direntry for this 507 // framework. 508 CacheLookup.setValue(Dir); 509 } 510 511 const FileEntry *FE = 0; 512 513 if (RelativePath != NULL) { 514 RelativePath->clear(); 515 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 516 } 517 518 // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 519 llvm::SmallString<1024> HeadersFilename(FrameworkName); 520 HeadersFilename += "Headers/"; 521 if (SearchPath != NULL) { 522 SearchPath->clear(); 523 // Without trailing '/'. 524 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 525 } 526 527 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 528 if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { 529 530 // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 531 HeadersFilename = FrameworkName; 532 HeadersFilename += "PrivateHeaders/"; 533 if (SearchPath != NULL) { 534 SearchPath->clear(); 535 // Without trailing '/'. 536 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 537 } 538 539 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 540 if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) 541 return 0; 542 } 543 544 // This file is a system header or C++ unfriendly if the old file is. 545 // 546 // Note that the temporary 'DirInfo' is required here, as either call to 547 // getFileInfo could resize the vector and we don't want to rely on order 548 // of evaluation. 549 unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; 550 getFileInfo(FE).DirInfo = DirInfo; 551 return FE; 552 } 553 554 //===----------------------------------------------------------------------===// 555 // File Info Management. 556 //===----------------------------------------------------------------------===// 557 558 559 /// getFileInfo - Return the HeaderFileInfo structure for the specified 560 /// FileEntry. 561 HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { 562 if (FE->getUID() >= FileInfo.size()) 563 FileInfo.resize(FE->getUID()+1); 564 565 HeaderFileInfo &HFI = FileInfo[FE->getUID()]; 566 if (ExternalSource && !HFI.Resolved) { 567 HFI = ExternalSource->GetHeaderFileInfo(FE); 568 HFI.Resolved = true; 569 } 570 return HFI; 571 } 572 573 bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { 574 // Check if we've ever seen this file as a header. 575 if (File->getUID() >= FileInfo.size()) 576 return false; 577 578 // Resolve header file info from the external source, if needed. 579 HeaderFileInfo &HFI = FileInfo[File->getUID()]; 580 if (ExternalSource && !HFI.Resolved) { 581 HFI = ExternalSource->GetHeaderFileInfo(File); 582 HFI.Resolved = true; 583 } 584 585 return HFI.isPragmaOnce || HFI.ControllingMacro || HFI.ControllingMacroID; 586 } 587 588 void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { 589 if (UID >= FileInfo.size()) 590 FileInfo.resize(UID+1); 591 HFI.Resolved = true; 592 FileInfo[UID] = HFI; 593 } 594 595 /// ShouldEnterIncludeFile - Mark the specified file as a target of of a 596 /// #include, #include_next, or #import directive. Return false if #including 597 /// the file will have no effect or true if we should include it. 598 bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ 599 ++NumIncluded; // Count # of attempted #includes. 600 601 // Get information about this file. 602 HeaderFileInfo &FileInfo = getFileInfo(File); 603 604 // If this is a #import directive, check that we have not already imported 605 // this header. 606 if (isImport) { 607 // If this has already been imported, don't import it again. 608 FileInfo.isImport = true; 609 610 // Has this already been #import'ed or #include'd? 611 if (FileInfo.NumIncludes) return false; 612 } else { 613 // Otherwise, if this is a #include of a file that was previously #import'd 614 // or if this is the second #include of a #pragma once file, ignore it. 615 if (FileInfo.isImport) 616 return false; 617 } 618 619 // Next, check to see if the file is wrapped with #ifndef guards. If so, and 620 // if the macro that guards it is defined, we know the #include has no effect. 621 if (const IdentifierInfo *ControllingMacro 622 = FileInfo.getControllingMacro(ExternalLookup)) 623 if (ControllingMacro->hasMacroDefinition()) { 624 ++NumMultiIncludeFileOptzn; 625 return false; 626 } 627 628 // Increment the number of times this file has been included. 629 ++FileInfo.NumIncludes; 630 631 return true; 632 } 633 634 size_t HeaderSearch::getTotalMemory() const { 635 return SearchDirs.capacity() 636 + llvm::capacity_in_bytes(FileInfo) 637 + llvm::capacity_in_bytes(HeaderMaps) 638 + LookupFileCache.getAllocator().getTotalMemory() 639 + FrameworkMap.getAllocator().getTotalMemory(); 640 } 641 642 StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { 643 return FrameworkNames.GetOrCreateValue(Framework).getKey(); 644 } 645