HeaderSearch.cpp revision 39b49bcaaddb1049234fca9500c0ac02c088e23d
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- HeaderSearch.cpp - Resolve Header File Locations ---===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the DirectoryLookup and HeaderSearch interfaces. 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Lex/HeaderSearch.h" 15822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner#include "clang/Lex/HeaderMap.h" 16c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#include "clang/Basic/FileManager.h" 17c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#include "clang/Basic/IdentifierTable.h" 185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/System/Path.h" 195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/SmallString.h" 203daed52a57d03765223021f5f921bdc280c8f3ccChris Lattner#include <cstdio> 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 238c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregorconst IdentifierInfo * 248c5a760b82e73ed90b560090772db97e2ae27b09Douglas GregorHeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { 258c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor if (ControllingMacro) 268c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return ControllingMacro; 278c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor 288c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor if (!ControllingMacroID || !External) 298c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return 0; 308c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor 318c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor ControllingMacro = External->GetIdentifier(ControllingMacroID); 328c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return ControllingMacro; 338c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor} 348c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor 3539b49bcaaddb1049234fca9500c0ac02c088e23dChris LattnerHeaderSearch::HeaderSearch(FileManager &FM) 3639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner : FileMgr(FM), FrameworkMap(64) { 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SystemDirIdx = 0; 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NoCurDirSearch = false; 391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 408c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor ExternalLookup = 0; 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumIncluded = 0; 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumMultiIncludeFileOptzn = 0; 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumFrameworkLookups = NumSubFrameworkLookups = 0; 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 46822da61b74ce14e89b3fa8774db18c833aa5748bChris LattnerHeaderSearch::~HeaderSearch() { 47822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner // Delete headermaps. 48822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 49822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner delete HeaderMaps[i].second; 50822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner} 511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid HeaderSearch::PrintStats() { 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "\n*** HeaderSearch Stats:\n"); 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumOnceOnlyFiles += FileInfo[i].isImport; 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (MaxNumIncludes < FileInfo[i].NumIncludes) 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer MaxNumIncludes = FileInfo[i].NumIncludes; 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); 651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #includes skipped due to" 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer " the multi-include optimization.\n", NumMultiIncludeFileOptzn); 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 74822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner/// CreateHeaderMap - This method returns a HeaderMap for the specified 75822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. 761bfd4a6313ea8ebf710c46c10111732cc65d51f6Chris Lattnerconst HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { 77822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner // We expect the number of headermaps to be small, and almost always empty. 78df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // If it ever grows, use of a linear search should be re-evaluated. 79822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner if (!HeaderMaps.empty()) { 80822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 81df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // Pointer equality comparison of FileEntries works because they are 82df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // already uniqued by inode. 831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (HeaderMaps[i].first == FE) 84822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return HeaderMaps[i].second; 85822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner } 861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8739b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) { 88822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner HeaderMaps.push_back(std::make_pair(FE, HM)); 89822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return HM; 90822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner } 911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return 0; 93822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner} 94822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 95df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner//===----------------------------------------------------------------------===// 96df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner// File lookup within a DirectoryLookup scope 97df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner//===----------------------------------------------------------------------===// 98df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 993af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner/// getName - Return the directory or filename corresponding to this lookup 1003af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner/// object. 1013af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattnerconst char *DirectoryLookup::getName() const { 1023af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner if (isNormalDir()) 1033af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner return getDir()->getName(); 1043af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner if (isFramework()) 1053af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner return getFrameworkDir()->getName(); 1063af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner assert(isHeaderMap() && "Unknown DirectoryLookup"); 1073af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner return getHeaderMap()->getFileName(); 1083af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner} 1093af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner 1103af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner 111df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner/// LookupFile - Lookup the specified file in this search path, returning it 112df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner/// if it exists or returning null if not. 113a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattnerconst FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename, 114afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner HeaderSearch &HS) const { 115df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner llvm::SmallString<1024> TmpDir; 116afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (isNormalDir()) { 117afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Concatenate the requested file onto the directory. 118afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // FIXME: Portability. Filename concatenation should be in sys::Path. 119afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner TmpDir += getDir()->getName(); 120afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner TmpDir.push_back('/'); 121a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner TmpDir.append(Filename.begin(), Filename.end()); 12239b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return HS.getFileMgr().getFile(TmpDir.str()); 123afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner } 1241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 125afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (isFramework()) 126a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner return DoFrameworkLookup(Filename, HS); 1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 128b09e71fd52d0e7fdf3e88b1df72ea0cee5d9b37bChris Lattner assert(isHeaderMap() && "Unknown directory lookup"); 12939b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return getHeaderMap()->LookupFile(Filename, HS.getFileMgr()); 130df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner} 131df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 132df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 133afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner/// DoFrameworkLookup - Do a lookup of the specified file in the current 134afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner/// DirectoryLookup, which is a framework directory. 135a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattnerconst FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, 136afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner HeaderSearch &HS) const { 137afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner FileManager &FileMgr = HS.getFileMgr(); 1381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Framework names must have a '/' in the filename. 140a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner size_t SlashPos = Filename.find('/'); 141a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner if (SlashPos == llvm::StringRef::npos) return 0; 1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 143afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Find out if this is the home for the specified framework, by checking 144afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // HeaderSearch. Possible answer are yes/no and unknown. 1451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const DirectoryEntry *&FrameworkDirCache = 146a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); 1471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 148afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // If it is known and in some other directory, fail. 149afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir()) 1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Otherwise, construct the path to this framework dir. 1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/" 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> FrameworkName; 156afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner FrameworkName += getFrameworkDir()->getName(); 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FrameworkName.empty() || FrameworkName.back() != '/') 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.push_back('/'); 1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/Cocoa" 161a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += ".framework/"; 1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 166afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // If the cache entry is still unresolved, query to see if the cache entry is 167afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // still unresolved. If so, check its existence now. 168afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (FrameworkDirCache == 0) { 169afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner HS.IncrementFrameworkLookupCount(); 1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the framework dir doesn't exist, we fail. 172afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // FIXME: It's probably more efficient to query this with FileMgr.getDir. 1731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (!llvm::sys::Path(std::string(FrameworkName.begin(), 1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.end())).exists()) 1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if it does, remember that this is the right direntry for this 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // framework. 179afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner FrameworkDirCache = getFrameworkDir(); 1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" 1835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned OrigSize = FrameworkName.size(); 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += "Headers/"; 186a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); 18739b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str())) 1885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 1891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *Private = "Private"; 1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Private+strlen(Private)); 19439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return FileMgr.getFile(FrameworkName.str()); 1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 197df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 198afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner//===----------------------------------------------------------------------===// 199afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner// Header File Location. 200afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner//===----------------------------------------------------------------------===// 201afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner 202afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner 2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, 2045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// return null on failure. isAngled indicates whether the file reference is 20510fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor/// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if 20610fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor/// non-null, indicates where the #including file is, in case a relative search 20710fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor/// is needed. 208a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattnerconst FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, 2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer bool isAngled, 2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryLookup *FromDir, 2115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryLookup *&CurDir, 21210fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor const FileEntry *CurFileEnt) { 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If 'Filename' is absolute, check to see if it exists and no searching. 214a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner if (llvm::sys::Path::isAbsolute(Filename.begin(), Filename.size())) { 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = 0; 2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this was an #include_next "/absolute/file", fail. 2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FromDir) return 0; 2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, just return the file. 22139b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return FileMgr.getFile(Filename); 2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Step #0, unless disabled, check to see if the file is in the #includer's 22510fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // directory. This has to be based on CurFileEnt, not CurDir, because 22610fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and 227df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". 228df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // This search is not done for <> headers. 22910fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor if (CurFileEnt && !isAngled && !NoCurDirSearch) { 23010fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor llvm::SmallString<1024> TmpDir; 23110fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // Concatenate the requested file onto the directory. 23210fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // FIXME: Portability. Filename concatenation should be in sys::Path. 23310fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor TmpDir += CurFileEnt->getDir()->getName(); 23410fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor TmpDir.push_back('/'); 23510fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor TmpDir.append(Filename.begin(), Filename.end()); 23639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner if (const FileEntry *FE = FileMgr.getFile(TmpDir.str())) { 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Leave CurDir unset. 23810fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // This file is a system header or C++ unfriendly if the old file is. 23910fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // 24010fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // Note that the temporary 'DirInfo' is required here, as either call to 24110fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // getFileInfo could resize the vector and we don't want to rely on order 24210fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // of evaluation. 24310fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; 244c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner getFileInfo(FE).DirInfo = DirInfo; 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = 0; 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a system #include, ignore the user #include locs. 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned i = isAngled ? SystemDirIdx : 0; 2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a #include_next request, start searching after the directory the 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // file was found in. 2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FromDir) 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer i = FromDir-&SearchDirs[0]; 2581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2599960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Cache all of the lookups performed by this method. Many headers are 2609960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // multiply included, and the "pragma once" optimization prevents them from 2619960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // being relex/pp'd, but they would still have to search through a 2629960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // (potentially huge) series of SearchDirs to find it. 2639960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner std::pair<unsigned, unsigned> &CacheLookup = 264a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner LookupFileCache.GetOrCreateValue(Filename).getValue(); 2659960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner 2669960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // If the entry has been previously looked up, the first value will be 2679960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // non-zero. If the value is equal to i (the start point of our search), then 2689960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // this is a matching hit. 2699960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner if (CacheLookup.first == i+1) { 2709960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Skip querying potentially lots of directories for this lookup. 2719960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner i = CacheLookup.second; 2729960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner } else { 2739960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Otherwise, this is the first query, or the previous query didn't match 2749960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // our search start. We will fill in our found location below, so prime the 2759960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // start point value. 2769960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.first = i+1; 2779960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner } 2781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check each directory in sequence to see if it contains this file. 2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer for (; i != SearchDirs.size(); ++i) { 2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const FileEntry *FE = 282a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner SearchDirs[i].LookupFile(Filename, *this); 283afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (!FE) continue; 2841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 285afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner CurDir = &SearchDirs[i]; 2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 287afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // This file is a system header or C++ unfriendly if the dir is. 288afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner getFileInfo(FE).DirInfo = CurDir->getDirCharacteristic(); 2891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 290afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Remember this location for the next lookup we do. 291afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner CacheLookup.second = i; 292afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner return FE; 2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2959960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Otherwise, didn't find it. Remember we didn't find this. 2969960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.second = SearchDirs.size(); 2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// LookupSubframeworkHeader - Look up a subframework for the specified 3015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from 3025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 3035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is a subframework within Carbon.framework. If so, return the FileEntry 3045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for the designated file, otherwise return null. 3055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *HeaderSearch:: 306a139481e62fdb209d9d87a54a5733f989d2e8d51Chris LattnerLookupSubframeworkHeader(llvm::StringRef Filename, 3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *ContextFileEnt) { 3089415a0cc93117b69add4e1dc0f11146f3479ee1aChris Lattner assert(ContextFileEnt && "No context file?"); 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Framework names must have a '/' in the filename. Find it. 311a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner size_t SlashPos = Filename.find('/'); 312a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner if (SlashPos == llvm::StringRef::npos) return 0; 3131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Look up the base framework name of the ContextFileEnt. 3155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *ContextName = ContextFileEnt->getName(); 3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the context info wasn't a framework, couldn't be a subframework. 3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FrameworkPos = strstr(ContextName, ".framework/"); 3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FrameworkPos == 0) 3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::SmallString<1024> FrameworkName(ContextName, 3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkPos+strlen(".framework/")); 3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Append Frameworks/HIToolbox.framework/ 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += "Frameworks/"; 327a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += ".framework/"; 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 3316538227d51df249b07c8ab80ae376f5c1d14403cChris Lattner FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Some other location? 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() && 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.getKeyLength() == FrameworkName.size() && 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer memcmp(CacheLookup.getKeyData(), &FrameworkName[0], 3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.getKeyLength()) != 0) 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Cache subframework. 3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() == 0) { 3425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumSubFrameworkLookups; 3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the framework dir doesn't exist, we fail. 34539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); 3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (Dir == 0) return 0; 3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if it does, remember that this is the right direntry for this 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // framework. 3505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.setValue(Dir); 3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *FE = 0; 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 3565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> HeadersFilename(FrameworkName); 3575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename += "Headers/"; 358a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 35939b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner if (!(FE = FileMgr.getFile(HeadersFilename.str()))) { 3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 3625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename = FrameworkName; 3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename += "PrivateHeaders/"; 364a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 36539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner if (!(FE = FileMgr.getFile(HeadersFilename.str()))) 3665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This file is a system header or C++ unfriendly if the old file is. 370ca63fa00786e51c207c829f4182f11a6c6b552beTed Kremenek // 371c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner // Note that the temporary 'DirInfo' is required here, as either call to 372c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner // getFileInfo could resize the vector and we don't want to rely on order 373c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner // of evaluation. 374c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; 375c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner getFileInfo(FE).DirInfo = DirInfo; 3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 3775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// File Info Management. 3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 3825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 38483d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff/// getFileInfo - Return the HeaderFileInfo structure for the specified 3855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// FileEntry. 38683d63c78810556d26b62ac4cbae2eda6cdd2570cSteve NaroffHeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { 3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FE->getUID() >= FileInfo.size()) 3885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfo.resize(FE->getUID()+1); 3895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FileInfo[FE->getUID()]; 3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 3915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 39283d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroffvoid HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { 39383d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff if (UID >= FileInfo.size()) 39483d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff FileInfo.resize(UID+1); 39583d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff FileInfo[UID] = HFI; 39683d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff} 39783d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff 3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ShouldEnterIncludeFile - Mark the specified file as a target of of a 3995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// #include, #include_next, or #import directive. Return false if #including 4005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// the file will have no effect or true if we should include it. 4015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerbool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ 4025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumIncluded; // Count # of attempted #includes. 4035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get information about this file. 40583d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff HeaderFileInfo &FileInfo = getFileInfo(File); 4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a #import directive, check that we have not already imported 4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // this header. 4095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (isImport) { 4105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this has already been imported, don't import it again. 4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfo.isImport = true; 4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Has this already been #import'ed or #include'd? 4145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileInfo.NumIncludes) return false; 4155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else { 4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if this is a #include of a file that was previously #import'd 4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // or if this is the second #include of a #pragma once file, ignore it. 4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileInfo.isImport) 4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return false; 4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 4211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Next, check to see if the file is wrapped with #ifndef guards. If so, and 4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // if the macro that guards it is defined, we know the #include has no effect. 4241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const IdentifierInfo *ControllingMacro 4258c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor = FileInfo.getControllingMacro(ExternalLookup)) 4268c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor if (ControllingMacro->hasMacroDefinition()) { 4278c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor ++NumMultiIncludeFileOptzn; 4288c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return false; 4298c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor } 4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Increment the number of times this file has been included. 4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++FileInfo.NumIncludes; 4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return true; 4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 438