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 !Filename.substr(SlashPos + 1).startswith(".."); 294 295 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); 296 if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 297 /*openFile=*/!AutomaticImport)) { 298 if (AutomaticImport) 299 *SuggestedModule = StringRef(Filename.begin(), SlashPos); 300 return FE; 301 } 302 303 // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 304 const char *Private = "Private"; 305 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 306 Private+strlen(Private)); 307 if (SearchPath != NULL) 308 SearchPath->insert(SearchPath->begin()+OrigSize, Private, 309 Private+strlen(Private)); 310 311 const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 312 /*openFile=*/!AutomaticImport); 313 if (FE && AutomaticImport) 314 *SuggestedModule = StringRef(Filename.begin(), SlashPos); 315 return FE; 316 } 317 318 319 //===----------------------------------------------------------------------===// 320 // Header File Location. 321 //===----------------------------------------------------------------------===// 322 323 324 /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, 325 /// return null on failure. isAngled indicates whether the file reference is 326 /// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if 327 /// non-null, indicates where the #including file is, in case a relative search 328 /// is needed. 329 const FileEntry *HeaderSearch::LookupFile( 330 StringRef Filename, 331 bool isAngled, 332 const DirectoryLookup *FromDir, 333 const DirectoryLookup *&CurDir, 334 const FileEntry *CurFileEnt, 335 SmallVectorImpl<char> *SearchPath, 336 SmallVectorImpl<char> *RelativePath, 337 StringRef *SuggestedModule) 338 { 339 if (SuggestedModule) 340 *SuggestedModule = StringRef(); 341 342 // If 'Filename' is absolute, check to see if it exists and no searching. 343 if (llvm::sys::path::is_absolute(Filename)) { 344 CurDir = 0; 345 346 // If this was an #include_next "/absolute/file", fail. 347 if (FromDir) return 0; 348 349 if (SearchPath != NULL) 350 SearchPath->clear(); 351 if (RelativePath != NULL) { 352 RelativePath->clear(); 353 RelativePath->append(Filename.begin(), Filename.end()); 354 } 355 // Otherwise, just return the file. 356 return FileMgr.getFile(Filename, /*openFile=*/true); 357 } 358 359 // Unless disabled, check to see if the file is in the #includer's 360 // directory. This has to be based on CurFileEnt, not CurDir, because 361 // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and 362 // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". 363 // This search is not done for <> headers. 364 if (CurFileEnt && !isAngled && !NoCurDirSearch) { 365 llvm::SmallString<1024> TmpDir; 366 // Concatenate the requested file onto the directory. 367 // FIXME: Portability. Filename concatenation should be in sys::Path. 368 TmpDir += CurFileEnt->getDir()->getName(); 369 TmpDir.push_back('/'); 370 TmpDir.append(Filename.begin(), Filename.end()); 371 if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) { 372 // Leave CurDir unset. 373 // This file is a system header or C++ unfriendly if the old file is. 374 // 375 // Note that the temporary 'DirInfo' is required here, as either call to 376 // getFileInfo could resize the vector and we don't want to rely on order 377 // of evaluation. 378 unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; 379 getFileInfo(FE).DirInfo = DirInfo; 380 if (SearchPath != NULL) { 381 StringRef SearchPathRef(CurFileEnt->getDir()->getName()); 382 SearchPath->clear(); 383 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 384 } 385 if (RelativePath != NULL) { 386 RelativePath->clear(); 387 RelativePath->append(Filename.begin(), Filename.end()); 388 } 389 return FE; 390 } 391 } 392 393 CurDir = 0; 394 395 // If this is a system #include, ignore the user #include locs. 396 unsigned i = isAngled ? AngledDirIdx : 0; 397 398 // If this is a #include_next request, start searching after the directory the 399 // file was found in. 400 if (FromDir) 401 i = FromDir-&SearchDirs[0]; 402 403 // Cache all of the lookups performed by this method. Many headers are 404 // multiply included, and the "pragma once" optimization prevents them from 405 // being relex/pp'd, but they would still have to search through a 406 // (potentially huge) series of SearchDirs to find it. 407 std::pair<unsigned, unsigned> &CacheLookup = 408 LookupFileCache.GetOrCreateValue(Filename).getValue(); 409 410 // If the entry has been previously looked up, the first value will be 411 // non-zero. If the value is equal to i (the start point of our search), then 412 // this is a matching hit. 413 if (CacheLookup.first == i+1) { 414 // Skip querying potentially lots of directories for this lookup. 415 i = CacheLookup.second; 416 } else { 417 // Otherwise, this is the first query, or the previous query didn't match 418 // our search start. We will fill in our found location below, so prime the 419 // start point value. 420 CacheLookup.first = i+1; 421 } 422 423 // Check each directory in sequence to see if it contains this file. 424 for (; i != SearchDirs.size(); ++i) { 425 const FileEntry *FE = 426 SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, 427 BuildingModule, SuggestedModule); 428 if (!FE) continue; 429 430 CurDir = &SearchDirs[i]; 431 432 // This file is a system header or C++ unfriendly if the dir is. 433 HeaderFileInfo &HFI = getFileInfo(FE); 434 HFI.DirInfo = CurDir->getDirCharacteristic(); 435 436 // If this file is found in a header map and uses the framework style of 437 // includes, then this header is part of a framework we're building. 438 if (CurDir->isIndexHeaderMap()) { 439 size_t SlashPos = Filename.find('/'); 440 if (SlashPos != StringRef::npos) { 441 HFI.IndexHeaderMapHeader = 1; 442 HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), 443 SlashPos)); 444 } 445 } 446 447 // Remember this location for the next lookup we do. 448 CacheLookup.second = i; 449 return FE; 450 } 451 452 // If we are including a file with a quoted include "foo.h" from inside 453 // a header in a framework that is currently being built, and we couldn't 454 // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where 455 // "Foo" is the name of the framework in which the including header was found. 456 if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { 457 HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); 458 if (IncludingHFI.IndexHeaderMapHeader) { 459 llvm::SmallString<128> ScratchFilename; 460 ScratchFilename += IncludingHFI.Framework; 461 ScratchFilename += '/'; 462 ScratchFilename += Filename; 463 464 const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true, 465 FromDir, CurDir, CurFileEnt, 466 SearchPath, RelativePath, 467 SuggestedModule); 468 std::pair<unsigned, unsigned> &CacheLookup 469 = LookupFileCache.GetOrCreateValue(Filename).getValue(); 470 CacheLookup.second 471 = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second; 472 return Result; 473 } 474 } 475 476 // Otherwise, didn't find it. Remember we didn't find this. 477 CacheLookup.second = SearchDirs.size(); 478 return 0; 479 } 480 481 /// LookupSubframeworkHeader - Look up a subframework for the specified 482 /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from 483 /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 484 /// is a subframework within Carbon.framework. If so, return the FileEntry 485 /// for the designated file, otherwise return null. 486 const FileEntry *HeaderSearch:: 487 LookupSubframeworkHeader(StringRef Filename, 488 const FileEntry *ContextFileEnt, 489 SmallVectorImpl<char> *SearchPath, 490 SmallVectorImpl<char> *RelativePath) { 491 assert(ContextFileEnt && "No context file?"); 492 493 // Framework names must have a '/' in the filename. Find it. 494 size_t SlashPos = Filename.find('/'); 495 if (SlashPos == StringRef::npos) return 0; 496 497 // Look up the base framework name of the ContextFileEnt. 498 const char *ContextName = ContextFileEnt->getName(); 499 500 // If the context info wasn't a framework, couldn't be a subframework. 501 const char *FrameworkPos = strstr(ContextName, ".framework/"); 502 if (FrameworkPos == 0) 503 return 0; 504 505 llvm::SmallString<1024> FrameworkName(ContextName, 506 FrameworkPos+strlen(".framework/")); 507 508 // Append Frameworks/HIToolbox.framework/ 509 FrameworkName += "Frameworks/"; 510 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 511 FrameworkName += ".framework/"; 512 513 llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 514 FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); 515 516 // Some other location? 517 if (CacheLookup.getValue() && 518 CacheLookup.getKeyLength() == FrameworkName.size() && 519 memcmp(CacheLookup.getKeyData(), &FrameworkName[0], 520 CacheLookup.getKeyLength()) != 0) 521 return 0; 522 523 // Cache subframework. 524 if (CacheLookup.getValue() == 0) { 525 ++NumSubFrameworkLookups; 526 527 // If the framework dir doesn't exist, we fail. 528 const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); 529 if (Dir == 0) return 0; 530 531 // Otherwise, if it does, remember that this is the right direntry for this 532 // framework. 533 CacheLookup.setValue(Dir); 534 } 535 536 const FileEntry *FE = 0; 537 538 if (RelativePath != NULL) { 539 RelativePath->clear(); 540 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 541 } 542 543 // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 544 llvm::SmallString<1024> HeadersFilename(FrameworkName); 545 HeadersFilename += "Headers/"; 546 if (SearchPath != NULL) { 547 SearchPath->clear(); 548 // Without trailing '/'. 549 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 550 } 551 552 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 553 if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { 554 555 // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 556 HeadersFilename = FrameworkName; 557 HeadersFilename += "PrivateHeaders/"; 558 if (SearchPath != NULL) { 559 SearchPath->clear(); 560 // Without trailing '/'. 561 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 562 } 563 564 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 565 if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) 566 return 0; 567 } 568 569 // This file is a system header or C++ unfriendly if the old file is. 570 // 571 // Note that the temporary 'DirInfo' is required here, as either call to 572 // getFileInfo could resize the vector and we don't want to rely on order 573 // of evaluation. 574 unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; 575 getFileInfo(FE).DirInfo = DirInfo; 576 return FE; 577 } 578 579 //===----------------------------------------------------------------------===// 580 // File Info Management. 581 //===----------------------------------------------------------------------===// 582 583 /// \brief Merge the header file info provided by \p OtherHFI into the current 584 /// header file info (\p HFI) 585 static void mergeHeaderFileInfo(HeaderFileInfo &HFI, 586 const HeaderFileInfo &OtherHFI) { 587 HFI.isImport |= OtherHFI.isImport; 588 HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; 589 HFI.NumIncludes += OtherHFI.NumIncludes; 590 591 if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { 592 HFI.ControllingMacro = OtherHFI.ControllingMacro; 593 HFI.ControllingMacroID = OtherHFI.ControllingMacroID; 594 } 595 596 if (OtherHFI.External) { 597 HFI.DirInfo = OtherHFI.DirInfo; 598 HFI.External = OtherHFI.External; 599 HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; 600 } 601 602 if (HFI.Framework.empty()) 603 HFI.Framework = OtherHFI.Framework; 604 605 HFI.Resolved = true; 606 } 607 608 /// getFileInfo - Return the HeaderFileInfo structure for the specified 609 /// FileEntry. 610 HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { 611 if (FE->getUID() >= FileInfo.size()) 612 FileInfo.resize(FE->getUID()+1); 613 614 HeaderFileInfo &HFI = FileInfo[FE->getUID()]; 615 if (ExternalSource && !HFI.Resolved) 616 mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE)); 617 return HFI; 618 } 619 620 bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { 621 // Check if we've ever seen this file as a header. 622 if (File->getUID() >= FileInfo.size()) 623 return false; 624 625 // Resolve header file info from the external source, if needed. 626 HeaderFileInfo &HFI = FileInfo[File->getUID()]; 627 if (ExternalSource && !HFI.Resolved) 628 mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File)); 629 630 return HFI.isPragmaOnce || HFI.ControllingMacro || HFI.ControllingMacroID; 631 } 632 633 void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { 634 if (UID >= FileInfo.size()) 635 FileInfo.resize(UID+1); 636 HFI.Resolved = true; 637 FileInfo[UID] = HFI; 638 } 639 640 /// ShouldEnterIncludeFile - Mark the specified file as a target of of a 641 /// #include, #include_next, or #import directive. Return false if #including 642 /// the file will have no effect or true if we should include it. 643 bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ 644 ++NumIncluded; // Count # of attempted #includes. 645 646 // Get information about this file. 647 HeaderFileInfo &FileInfo = getFileInfo(File); 648 649 // If this is a #import directive, check that we have not already imported 650 // this header. 651 if (isImport) { 652 // If this has already been imported, don't import it again. 653 FileInfo.isImport = true; 654 655 // Has this already been #import'ed or #include'd? 656 if (FileInfo.NumIncludes) return false; 657 } else { 658 // Otherwise, if this is a #include of a file that was previously #import'd 659 // or if this is the second #include of a #pragma once file, ignore it. 660 if (FileInfo.isImport) 661 return false; 662 } 663 664 // Next, check to see if the file is wrapped with #ifndef guards. If so, and 665 // if the macro that guards it is defined, we know the #include has no effect. 666 if (const IdentifierInfo *ControllingMacro 667 = FileInfo.getControllingMacro(ExternalLookup)) 668 if (ControllingMacro->hasMacroDefinition()) { 669 ++NumMultiIncludeFileOptzn; 670 return false; 671 } 672 673 // Increment the number of times this file has been included. 674 ++FileInfo.NumIncludes; 675 676 return true; 677 } 678 679 size_t HeaderSearch::getTotalMemory() const { 680 return SearchDirs.capacity() 681 + llvm::capacity_in_bytes(FileInfo) 682 + llvm::capacity_in_bytes(HeaderMaps) 683 + LookupFileCache.getAllocator().getTotalMemory() 684 + FrameworkMap.getAllocator().getTotalMemory(); 685 } 686 687 StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { 688 return FrameworkNames.GetOrCreateValue(Framework).getKey(); 689 } 690