HeaderSearch.cpp revision 65e02fa80e1c185f18e5f81cefc30d75383a7301
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" 1832bef4edba854303800b3b01cb49a282e5da4f69Michael J. Spencer#include "llvm/Support/FileSystem.h" 1903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/SmallString.h" 21eabea45e23abc07e917f0d4bce15054ce75623efTed Kremenek#include "llvm/Support/Capacity.h" 223daed52a57d03765223021f5f921bdc280c8f3ccChris Lattner#include <cstdio> 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 258c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregorconst IdentifierInfo * 268c5a760b82e73ed90b560090772db97e2ae27b09Douglas GregorHeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { 278c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor if (ControllingMacro) 288c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return ControllingMacro; 298c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor 308c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor if (!ControllingMacroID || !External) 318c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return 0; 328c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor 338c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor ControllingMacro = External->GetIdentifier(ControllingMacroID); 348c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return ControllingMacro; 358c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor} 368c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor 37cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas GregorExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} 38cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 3939b49bcaaddb1049234fca9500c0ac02c088e23dChris LattnerHeaderSearch::HeaderSearch(FileManager &FM) 4039b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner : FileMgr(FM), FrameworkMap(64) { 4174a5fd8bcc68b540b58f6fcd2d80e6e926966e71Nico Weber AngledDirIdx = 0; 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SystemDirIdx = 0; 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NoCurDirSearch = false; 441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 458c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor ExternalLookup = 0; 46cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor ExternalSource = 0; 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumIncluded = 0; 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumMultiIncludeFileOptzn = 0; 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumFrameworkLookups = NumSubFrameworkLookups = 0; 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 52822da61b74ce14e89b3fa8774db18c833aa5748bChris LattnerHeaderSearch::~HeaderSearch() { 53822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner // Delete headermaps. 54822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 55822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner delete HeaderMaps[i].second; 56822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner} 571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid HeaderSearch::PrintStats() { 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "\n*** HeaderSearch Stats:\n"); 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumOnceOnlyFiles += FileInfo[i].isImport; 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (MaxNumIncludes < FileInfo[i].NumIncludes) 655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer MaxNumIncludes = FileInfo[i].NumIncludes; 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); 695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); 711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #includes skipped due to" 745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer " the multi-include optimization.\n", NumMultiIncludeFileOptzn); 751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); 775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); 785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 80822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner/// CreateHeaderMap - This method returns a HeaderMap for the specified 81822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. 821bfd4a6313ea8ebf710c46c10111732cc65d51f6Chris Lattnerconst HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { 83822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner // We expect the number of headermaps to be small, and almost always empty. 84df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // If it ever grows, use of a linear search should be re-evaluated. 85822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner if (!HeaderMaps.empty()) { 86822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 87df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // Pointer equality comparison of FileEntries works because they are 88df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // already uniqued by inode. 891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (HeaderMaps[i].first == FE) 90822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return HeaderMaps[i].second; 91822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner } 921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) { 94822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner HeaderMaps.push_back(std::make_pair(FE, HM)); 95822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return HM; 96822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner } 971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return 0; 99822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner} 100822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 101df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner//===----------------------------------------------------------------------===// 102df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner// File lookup within a DirectoryLookup scope 103df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner//===----------------------------------------------------------------------===// 104df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 1053af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner/// getName - Return the directory or filename corresponding to this lookup 1063af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner/// object. 1073af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattnerconst char *DirectoryLookup::getName() const { 1083af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner if (isNormalDir()) 1093af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner return getDir()->getName(); 1103af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner if (isFramework()) 1113af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner return getFrameworkDir()->getName(); 1123af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner assert(isHeaderMap() && "Unknown DirectoryLookup"); 1133af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner return getHeaderMap()->getFileName(); 1143af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner} 1153af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner 1163af66a9335966e9114e660cf7aafbb9272190ec2Chris Lattner 117df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner/// LookupFile - Lookup the specified file in this search path, returning it 118df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner/// if it exists or returning null if not. 119b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruthconst FileEntry *DirectoryLookup::LookupFile( 1205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Filename, 1217412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek HeaderSearch &HS, 1225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *SearchPath, 1235f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *RelativePath) const { 124df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner llvm::SmallString<1024> TmpDir; 125afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (isNormalDir()) { 126afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Concatenate the requested file onto the directory. 127a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman TmpDir = getDir()->getName(); 128a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman llvm::sys::path::append(TmpDir, Filename); 1297412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) { 1305f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef SearchPathRef(getDir()->getName()); 1317412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 1327412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 1337412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 1347412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (RelativePath != NULL) { 1357412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->clear(); 1367412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->append(Filename.begin(), Filename.end()); 1377412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 1383cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); 139afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner } 1401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 141afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (isFramework()) 1427412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath); 1431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 144b09e71fd52d0e7fdf3e88b1df72ea0cee5d9b37bChris Lattner assert(isHeaderMap() && "Unknown directory lookup"); 1457412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek const FileEntry * const Result = getHeaderMap()->LookupFile( 1467412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek Filename, HS.getFileMgr()); 1477412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (Result) { 1487412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) { 1495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef SearchPathRef(getName()); 1507412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 1517412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 1527412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 1537412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (RelativePath != NULL) { 1547412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->clear(); 1557412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->append(Filename.begin(), Filename.end()); 1567412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 1577412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 1587412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek return Result; 159df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner} 160df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 161df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 162afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner/// DoFrameworkLookup - Do a lookup of the specified file in the current 163afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner/// DirectoryLookup, which is a framework directory. 164b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruthconst FileEntry *DirectoryLookup::DoFrameworkLookup( 1655f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Filename, 1667412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek HeaderSearch &HS, 1675f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *SearchPath, 1685f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *RelativePath) const { 169afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner FileManager &FileMgr = HS.getFileMgr(); 1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Framework names must have a '/' in the filename. 172a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner size_t SlashPos = Filename.find('/'); 1735f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (SlashPos == StringRef::npos) return 0; 1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 175afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Find out if this is the home for the specified framework, by checking 176afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // HeaderSearch. Possible answer are yes/no and unknown. 1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const DirectoryEntry *&FrameworkDirCache = 178a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); 1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 180afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // If it is known and in some other directory, fail. 181afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir()) 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 184afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Otherwise, construct the path to this framework dir. 1851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/" 1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> FrameworkName; 188afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner FrameworkName += getFrameworkDir()->getName(); 1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FrameworkName.empty() || FrameworkName.back() != '/') 1905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.push_back('/'); 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/Cocoa" 193a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" 1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += ".framework/"; 1971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 198afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // If the cache entry is still unresolved, query to see if the cache entry is 199afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // still unresolved. If so, check its existence now. 200afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (FrameworkDirCache == 0) { 201afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner HS.IncrementFrameworkLookupCount(); 2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the framework dir doesn't exist, we fail. 204afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // FIXME: It's probably more efficient to query this with FileMgr.getDir. 20532bef4edba854303800b3b01cb49a282e5da4f69Michael J. Spencer bool Exists; 20632bef4edba854303800b3b01cb49a282e5da4f69Michael J. Spencer if (llvm::sys::fs::exists(FrameworkName.str(), Exists) || !Exists) 2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if it does, remember that this is the right direntry for this 2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // framework. 211afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner FrameworkDirCache = getFrameworkDir(); 2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2147412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (RelativePath != NULL) { 2157412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->clear(); 2167412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 2177412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 2187412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned OrigSize = FrameworkName.size(); 2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += "Headers/"; 2237412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 2247412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) { 2257412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 2267412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek // Without trailing '/'. 2277412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); 2287412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 2297412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 230a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); 2313cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), 2323cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis /*openFile=*/true)) { 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 234b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruth } 2351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *Private = "Private"; 2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Private+strlen(Private)); 2407412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) 2417412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->insert(SearchPath->begin()+OrigSize, Private, 2427412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek Private+strlen(Private)); 2437412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 2443cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis return FileMgr.getFile(FrameworkName.str(), /*openFile=*/true); 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 247df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 248afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner//===----------------------------------------------------------------------===// 249afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner// Header File Location. 250afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner//===----------------------------------------------------------------------===// 251afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner 252afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner 2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// return null on failure. isAngled indicates whether the file reference is 25510fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor/// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if 25610fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor/// non-null, indicates where the #including file is, in case a relative search 25710fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor/// is needed. 258b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruthconst FileEntry *HeaderSearch::LookupFile( 2595f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Filename, 260b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruth bool isAngled, 261b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruth const DirectoryLookup *FromDir, 262b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruth const DirectoryLookup *&CurDir, 263b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruth const FileEntry *CurFileEnt, 2645f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *SearchPath, 2655f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *RelativePath) { 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If 'Filename' is absolute, check to see if it exists and no searching. 267256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_absolute(Filename)) { 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = 0; 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this was an #include_next "/absolute/file", fail. 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FromDir) return 0; 2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2737412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) 2747412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 2757412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (RelativePath != NULL) { 2767412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->clear(); 2777412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->append(Filename.begin(), Filename.end()); 2787412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, just return the file. 2803cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis return FileMgr.getFile(Filename, /*openFile=*/true); 2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28365e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // If we are including a file with a quoted include "foo.h" from inside 28465e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // a header in a framework that is currently being built, change the include 28565e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // to <Foo/foo.h>, where "Foo" is the name of the framework in which the 28665e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // including header was found. 28765e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor llvm::SmallString<128> ScratchFilename; 28865e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { 28965e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); 29065e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor if (IncludingHFI.IndexHeaderMapHeader) { 29165e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor isAngled = true; 29265e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor ScratchFilename += IncludingHFI.Framework; 29365e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor ScratchFilename += '/'; 29465e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor ScratchFilename += Filename; 29565e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor Filename = ScratchFilename; 29665e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor } 29765e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor } 29865e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor 29965e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // Unless disabled, check to see if the file is in the #includer's 30010fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // directory. This has to be based on CurFileEnt, not CurDir, because 30110fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and 302df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". 303df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // This search is not done for <> headers. 30410fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor if (CurFileEnt && !isAngled && !NoCurDirSearch) { 30510fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor llvm::SmallString<1024> TmpDir; 30610fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // Concatenate the requested file onto the directory. 30710fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // FIXME: Portability. Filename concatenation should be in sys::Path. 30810fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor TmpDir += CurFileEnt->getDir()->getName(); 30910fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor TmpDir.push_back('/'); 31010fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor TmpDir.append(Filename.begin(), Filename.end()); 3113cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) { 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Leave CurDir unset. 31310fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // This file is a system header or C++ unfriendly if the old file is. 31410fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // 31510fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // Note that the temporary 'DirInfo' is required here, as either call to 31610fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // getFileInfo could resize the vector and we don't want to rely on order 31710fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor // of evaluation. 31810fe93d57c11f068aa4d78eb4ca7f60329818306Douglas Gregor unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; 319c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner getFileInfo(FE).DirInfo = DirInfo; 3207412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) { 3215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef SearchPathRef(CurFileEnt->getDir()->getName()); 3227412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 3237412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); 3247412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 3257412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (RelativePath != NULL) { 3267412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->clear(); 3277412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->append(Filename.begin(), Filename.end()); 3287412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = 0; 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a system #include, ignore the user #include locs. 33674a5fd8bcc68b540b58f6fcd2d80e6e926966e71Nico Weber unsigned i = isAngled ? AngledDirIdx : 0; 3371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a #include_next request, start searching after the directory the 3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // file was found in. 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FromDir) 3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer i = FromDir-&SearchDirs[0]; 3421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3439960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Cache all of the lookups performed by this method. Many headers are 3449960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // multiply included, and the "pragma once" optimization prevents them from 3459960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // being relex/pp'd, but they would still have to search through a 3469960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // (potentially huge) series of SearchDirs to find it. 3479960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner std::pair<unsigned, unsigned> &CacheLookup = 348a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner LookupFileCache.GetOrCreateValue(Filename).getValue(); 3499960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner 3509960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // If the entry has been previously looked up, the first value will be 3519960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // non-zero. If the value is equal to i (the start point of our search), then 3529960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // this is a matching hit. 3539960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner if (CacheLookup.first == i+1) { 3549960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Skip querying potentially lots of directories for this lookup. 3559960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner i = CacheLookup.second; 3569960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner } else { 3579960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Otherwise, this is the first query, or the previous query didn't match 3589960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // our search start. We will fill in our found location below, so prime the 3599960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // start point value. 3609960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.first = i+1; 3619960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner } 3621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check each directory in sequence to see if it contains this file. 3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer for (; i != SearchDirs.size(); ++i) { 3651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const FileEntry *FE = 3667412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath); 367afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner if (!FE) continue; 3681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 369afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner CurDir = &SearchDirs[i]; 3701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 371afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // This file is a system header or C++ unfriendly if the dir is. 37265e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor HeaderFileInfo &HFI = getFileInfo(FE); 37365e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor HFI.DirInfo = CurDir->getDirCharacteristic(); 37465e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor 37565e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // If this file is found in a header map and uses the framework style of 37665e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor // includes, then this header is part of a framework we're building. 37765e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor if (CurDir->isIndexHeaderMap()) { 37865e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor size_t SlashPos = Filename.find('/'); 37965e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor if (SlashPos != StringRef::npos) { 38065e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor HFI.IndexHeaderMapHeader = 1; 38165e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), 38265e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor SlashPos)); 38365e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor } 38465e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor } 38565e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor 386afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner // Remember this location for the next lookup we do. 387afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner CacheLookup.second = i; 388afded5bbb85607023c710c3d6a96c372feb84d7fChris Lattner return FE; 3895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3919960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Otherwise, didn't find it. Remember we didn't find this. 3929960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.second = SearchDirs.size(); 3935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// LookupSubframeworkHeader - Look up a subframework for the specified 3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from 3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 3995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is a subframework within Carbon.framework. If so, return the FileEntry 4005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for the designated file, otherwise return null. 4015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *HeaderSearch:: 4025f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerLookupSubframeworkHeader(StringRef Filename, 403b5142bb7af5c70fffd09f05172a1379a35a9c29aChandler Carruth const FileEntry *ContextFileEnt, 4045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *SearchPath, 4055f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<char> *RelativePath) { 4069415a0cc93117b69add4e1dc0f11146f3479ee1aChris Lattner assert(ContextFileEnt && "No context file?"); 4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Framework names must have a '/' in the filename. Find it. 409a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner size_t SlashPos = Filename.find('/'); 4105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (SlashPos == StringRef::npos) return 0; 4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Look up the base framework name of the ContextFileEnt. 4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *ContextName = ContextFileEnt->getName(); 4141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the context info wasn't a framework, couldn't be a subframework. 4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FrameworkPos = strstr(ContextName, ".framework/"); 4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FrameworkPos == 0) 4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::SmallString<1024> FrameworkName(ContextName, 4215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkPos+strlen(".framework/")); 4225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Append Frameworks/HIToolbox.framework/ 4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += "Frameworks/"; 425a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); 4265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += ".framework/"; 4275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 4296538227d51df249b07c8ab80ae376f5c1d14403cChris Lattner FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); 4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Some other location? 4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() && 4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.getKeyLength() == FrameworkName.size() && 4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer memcmp(CacheLookup.getKeyData(), &FrameworkName[0], 4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.getKeyLength()) != 0) 4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Cache subframework. 4395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() == 0) { 4405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumSubFrameworkLookups; 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the framework dir doesn't exist, we fail. 44339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); 4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (Dir == 0) return 0; 4451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if it does, remember that this is the right direntry for this 4475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // framework. 4485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.setValue(Dir); 4495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *FE = 0; 4525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4537412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (RelativePath != NULL) { 4547412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->clear(); 4557412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); 4567412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 4577412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 4585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 4595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> HeadersFilename(FrameworkName); 4605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename += "Headers/"; 4617412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) { 4627412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 4637412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek // Without trailing '/'. 4647412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 4657412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 4667412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 467a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 4683cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { 4691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 4715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename = FrameworkName; 4725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename += "PrivateHeaders/"; 4737412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek if (SearchPath != NULL) { 4747412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->clear(); 4757412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek // Without trailing '/'. 4767412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); 4777412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek } 4787412494982c8b50c90961302c3a718633b2c3ab7Manuel Klimek 479a139481e62fdb209d9d87a54a5733f989d2e8d51Chris Lattner HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); 4803cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) 4815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 4825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 4831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This file is a system header or C++ unfriendly if the old file is. 485ca63fa00786e51c207c829f4182f11a6c6b552beTed Kremenek // 486c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner // Note that the temporary 'DirInfo' is required here, as either call to 487c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner // getFileInfo could resize the vector and we don't want to rely on order 488c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner // of evaluation. 489c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; 490c9dde4f9572423723d9490336799f68050dfefa6Chris Lattner getFileInfo(FE).DirInfo = DirInfo; 4915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 4925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 4955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// File Info Management. 4965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 4975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 49983d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff/// getFileInfo - Return the HeaderFileInfo structure for the specified 5005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// FileEntry. 50183d63c78810556d26b62ac4cbae2eda6cdd2570cSteve NaroffHeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { 5025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FE->getUID() >= FileInfo.size()) 5035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfo.resize(FE->getUID()+1); 504cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 505cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor HeaderFileInfo &HFI = FileInfo[FE->getUID()]; 506cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (ExternalSource && !HFI.Resolved) { 507cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor HFI = ExternalSource->GetHeaderFileInfo(FE); 508cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor HFI.Resolved = true; 509cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor } 510cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor return HFI; 5111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 5125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 513dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregorbool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { 514dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor // Check if we've ever seen this file as a header. 515dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor if (File->getUID() >= FileInfo.size()) 516dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor return false; 517dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor 518dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor // Resolve header file info from the external source, if needed. 519dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor HeaderFileInfo &HFI = FileInfo[File->getUID()]; 520dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor if (ExternalSource && !HFI.Resolved) { 521dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor HFI = ExternalSource->GetHeaderFileInfo(File); 522dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor HFI.Resolved = true; 523dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor } 524dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor 525dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor return HFI.isPragmaOnce || HFI.ControllingMacro || HFI.ControllingMacroID; 526dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor} 527dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor 52883d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroffvoid HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { 52983d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff if (UID >= FileInfo.size()) 53083d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff FileInfo.resize(UID+1); 531cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor HFI.Resolved = true; 53283d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff FileInfo[UID] = HFI; 53383d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff} 53483d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff 5355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ShouldEnterIncludeFile - Mark the specified file as a target of of a 5365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// #include, #include_next, or #import directive. Return false if #including 5375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// the file will have no effect or true if we should include it. 5385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerbool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ 5395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumIncluded; // Count # of attempted #includes. 5405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 5415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get information about this file. 54283d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff HeaderFileInfo &FileInfo = getFileInfo(File); 5431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a #import directive, check that we have not already imported 5455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // this header. 5465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (isImport) { 5475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this has already been imported, don't import it again. 5485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfo.isImport = true; 5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Has this already been #import'ed or #include'd? 5515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileInfo.NumIncludes) return false; 5525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else { 5535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if this is a #include of a file that was previously #import'd 5545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // or if this is the second #include of a #pragma once file, ignore it. 5555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileInfo.isImport) 5565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return false; 5575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 5581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Next, check to see if the file is wrapped with #ifndef guards. If so, and 5605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // if the macro that guards it is defined, we know the #include has no effect. 5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const IdentifierInfo *ControllingMacro 5628c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor = FileInfo.getControllingMacro(ExternalLookup)) 5638c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor if (ControllingMacro->hasMacroDefinition()) { 5648c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor ++NumMultiIncludeFileOptzn; 5658c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor return false; 5668c5a760b82e73ed90b560090772db97e2ae27b09Douglas Gregor } 5671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Increment the number of times this file has been included. 5695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++FileInfo.NumIncludes; 5701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return true; 5725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 5735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 574d1194fbbf65374bfa3578eb40a547e4f97b497d1Ted Kremeneksize_t HeaderSearch::getTotalMemory() const { 575d1194fbbf65374bfa3578eb40a547e4f97b497d1Ted Kremenek return SearchDirs.capacity() 576eabea45e23abc07e917f0d4bce15054ce75623efTed Kremenek + llvm::capacity_in_bytes(FileInfo) 577eabea45e23abc07e917f0d4bce15054ce75623efTed Kremenek + llvm::capacity_in_bytes(HeaderMaps) 578d1194fbbf65374bfa3578eb40a547e4f97b497d1Ted Kremenek + LookupFileCache.getAllocator().getTotalMemory() 579d1194fbbf65374bfa3578eb40a547e4f97b497d1Ted Kremenek + FrameworkMap.getAllocator().getTotalMemory(); 580d1194fbbf65374bfa3578eb40a547e4f97b497d1Ted Kremenek} 58165e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor 58265e02fa80e1c185f18e5f81cefc30d75383a7301Douglas GregorStringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { 58365e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor return FrameworkNames.GetOrCreateValue(Framework).getKey(); 58465e02fa80e1c185f18e5f81cefc30d75383a7301Douglas Gregor} 585