HeaderSearch.cpp revision df772336655fd84ee2c0ce514c93cef0b29d60d4
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- HeaderSearch.cpp - Resolve Header File Locations ---===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 55f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file was developed by Chris Lattner and is distributed under 65f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// the University of Illinois Open Source 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" 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerHeaderSearch::HeaderSearch(FileManager &FM) : FileMgr(FM), FrameworkMap(64) { 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SystemDirIdx = 0; 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NoCurDirSearch = false; 255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumIncluded = 0; 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumMultiIncludeFileOptzn = 0; 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumFrameworkLookups = NumSubFrameworkLookups = 0; 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 31822da61b74ce14e89b3fa8774db18c833aa5748bChris LattnerHeaderSearch::~HeaderSearch() { 32822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner // Delete headermaps. 33822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 34822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner delete HeaderMaps[i].second; 35822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner} 36822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid HeaderSearch::PrintStats() { 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "\n*** HeaderSearch Stats:\n"); 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumOnceOnlyFiles += FileInfo[i].isImport; 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (MaxNumIncludes < FileInfo[i].NumIncludes) 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer MaxNumIncludes = FileInfo[i].NumIncludes; 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, " %d #includes skipped due to" 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer " the multi-include optimization.\n", NumMultiIncludeFileOptzn); 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 59822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner/// CreateHeaderMap - This method returns a HeaderMap for the specified 60822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. 61822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattnerconst HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE, 62822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner std::string &ErrorInfo) { 63822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner // We expect the number of headermaps to be small, and almost always empty. 64df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // If it ever grows, use of a linear search should be re-evaluated. 65822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner if (!HeaderMaps.empty()) { 66822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) 67df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // Pointer equality comparison of FileEntries works because they are 68df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // already uniqued by inode. 69822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner if (HeaderMaps[i].first == FE) 70822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return HeaderMaps[i].second; 71822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner } 72822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 73822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner if (const HeaderMap *HM = HeaderMap::Create(FE, ErrorInfo)) { 74822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner HeaderMaps.push_back(std::make_pair(FE, HM)); 75822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return HM; 76822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner } 77822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 78822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner return 0; 79822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner} 80822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 81df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner//===----------------------------------------------------------------------===// 82df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner// File lookup within a DirectoryLookup scope 83df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner//===----------------------------------------------------------------------===// 84df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 85df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner/// LookupFile - Lookup the specified file in this search path, returning it 86df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner/// if it exists or returning null if not. 87df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattnerconst FileEntry *DirectoryLookup::LookupFile(const char *FilenameStart, 88df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner const char *FilenameEnd, 89df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner FileManager &FileMgr) const { 90df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner llvm::SmallString<1024> TmpDir; 91df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 92df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // Concatenate the requested file onto the directory. 93df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // FIXME: Portability. Filename concatenation should be in sys::Path. 94df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner TmpDir += getDir()->getName(); 95df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner TmpDir.push_back('/'); 96df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner TmpDir.append(FilenameStart, FilenameEnd); 97df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner return FileMgr.getFile(TmpDir.begin(), TmpDir.end()); 98df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner} 99df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 100df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 101822da61b74ce14e89b3fa8774db18c833aa5748bChris Lattner 1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Header File Location. 1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *HeaderSearch::DoFrameworkLookup(const DirectoryEntry *Dir, 1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FilenameStart, 1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FilenameEnd) { 1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Framework names must have a '/' in the filename. 1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *SlashPos = std::find(FilenameStart, FilenameEnd, '/'); 1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (SlashPos == FilenameEnd) return 0; 1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkMap.GetOrCreateValue(FilenameStart, SlashPos); 1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If it is some other directory, fail. 1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() && CacheLookup.getValue() != Dir) 1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/" 1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> FrameworkName; 1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += Dir->getName(); 1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FrameworkName.empty() || FrameworkName.back() != '/') 1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.push_back('/'); 1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/Cocoa" 1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.append(FilenameStart, SlashPos); 1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" 1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += ".framework/"; 1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() == 0) { 1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFrameworkLookups; 1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the framework dir doesn't exist, we fail. 1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!llvm::sys::Path(std::string(FrameworkName.begin(), 1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.end())).exists()) 1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if it does, remember that this is the right direntry for this 1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // framework. 1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.setValue(Dir); 1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" 1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned OrigSize = FrameworkName.size(); 1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += "Headers/"; 1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.append(SlashPos+1, FilenameEnd); 1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (const FileEntry *FE = FileMgr.getFile(FrameworkName.begin(), 1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.end())) { 1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" 1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *Private = "Private"; 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Private+strlen(Private)); 1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end()); 1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 162df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// return null on failure. isAngled indicates whether the file reference is 1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// non-null, indicates where the #including file is, in case a relative search 1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is needed. 1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, 1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FilenameEnd, 1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer bool isAngled, 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryLookup *FromDir, 1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryLookup *&CurDir, 1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *CurFileEnt) { 1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If 'Filename' is absolute, check to see if it exists and no searching. 1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Portability. This should be a sys::Path interface, this doesn't 1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // handle things like C:\foo.txt right, nor win32 \\network\device\blah. 1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FilenameStart[0] == '/') { 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = 0; 1795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this was an #include_next "/absolute/file", fail. 1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FromDir) return 0; 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, just return the file. 1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FileMgr.getFile(FilenameStart, FilenameEnd); 1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Step #0, unless disabled, check to see if the file is in the #includer's 188df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // directory. This has to be based on CurFileEnt, not CurDir, because 189df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and 190df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". 191df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner // This search is not done for <> headers. 1925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CurFileEnt && !isAngled && !NoCurDirSearch) { 193df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner llvm::SmallString<1024> TmpDir; 1945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Concatenate the requested file onto the directory. 1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Portability. Filename concatenation should be in sys::Path. 1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer TmpDir += CurFileEnt->getDir()->getName(); 1975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer TmpDir.push_back('/'); 1985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer TmpDir.append(FilenameStart, FilenameEnd); 1995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (const FileEntry *FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end())) { 2005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Leave CurDir unset. 2015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This file is a system header or C++ unfriendly if the old file is. 2025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer getFileInfo(FE).DirInfo = getFileInfo(CurFileEnt).DirInfo; 2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 2045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = 0; 2085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a system #include, ignore the user #include locs. 2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned i = isAngled ? SystemDirIdx : 0; 2115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a #include_next request, start searching after the directory the 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // file was found in. 2145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FromDir) 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer i = FromDir-&SearchDirs[0]; 2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2179960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Cache all of the lookups performed by this method. Many headers are 2189960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // multiply included, and the "pragma once" optimization prevents them from 2199960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // being relex/pp'd, but they would still have to search through a 2209960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // (potentially huge) series of SearchDirs to find it. 2219960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner std::pair<unsigned, unsigned> &CacheLookup = 2229960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner LookupFileCache.GetOrCreateValue(FilenameStart, FilenameEnd).getValue(); 2239960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner 2249960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // If the entry has been previously looked up, the first value will be 2259960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // non-zero. If the value is equal to i (the start point of our search), then 2269960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // this is a matching hit. 2279960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner if (CacheLookup.first == i+1) { 2289960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Skip querying potentially lots of directories for this lookup. 2299960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner i = CacheLookup.second; 2309960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner } else { 2319960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Otherwise, this is the first query, or the previous query didn't match 2329960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // our search start. We will fill in our found location below, so prime the 2339960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // start point value. 2349960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.first = i+1; 2359960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner } 236df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check each directory in sequence to see if it contains this file. 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer for (; i != SearchDirs.size(); ++i) { 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *FE = 0; 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!SearchDirs[i].isFramework()) { 241df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner FE = SearchDirs[i].LookupFile(FilenameStart, FilenameEnd, FileMgr); 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else { 243df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner FE = DoFrameworkLookup(SearchDirs[i].getFrameworkDir(), 244df772336655fd84ee2c0ce514c93cef0b29d60d4Chris Lattner FilenameStart, FilenameEnd); 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FE) { 2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CurDir = &SearchDirs[i]; 2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This file is a system header or C++ unfriendly if the dir is. 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer getFileInfo(FE).DirInfo = CurDir->getDirCharacteristic(); 2529960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner 2539960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Remember this location for the next lookup we do. 2549960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.second = i; 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2599960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner // Otherwise, didn't find it. Remember we didn't find this. 2609960ae8ecfa2c4278dac708a02e463f83fdf17e8Chris Lattner CacheLookup.second = SearchDirs.size(); 2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// LookupSubframeworkHeader - Look up a subframework for the specified 2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is a subframework within Carbon.framework. If so, return the FileEntry 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for the designated file, otherwise return null. 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *HeaderSearch:: 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerLookupSubframeworkHeader(const char *FilenameStart, 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FilenameEnd, 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *ContextFileEnt) { 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Framework names must have a '/' in the filename. Find it. 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *SlashPos = std::find(FilenameStart, FilenameEnd, '/'); 2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (SlashPos == FilenameEnd) return 0; 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Look up the base framework name of the ContextFileEnt. 2785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *ContextName = ContextFileEnt->getName(); 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the context info wasn't a framework, couldn't be a subframework. 2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *FrameworkPos = strstr(ContextName, ".framework/"); 2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FrameworkPos == 0) 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> FrameworkName(ContextName, 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkPos+strlen(".framework/")); 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Append Frameworks/HIToolbox.framework/ 2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += "Frameworks/"; 2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.append(FilenameStart, SlashPos); 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName += ".framework/"; 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkMap.GetOrCreateValue(FilenameStart, SlashPos); 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Some other location? 2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() && 2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.getKeyLength() == FrameworkName.size() && 2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer memcmp(CacheLookup.getKeyData(), &FrameworkName[0], 3005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.getKeyLength()) != 0) 3015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Cache subframework. 3045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (CacheLookup.getValue() == 0) { 3055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumSubFrameworkLookups; 3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If the framework dir doesn't exist, we fail. 3085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.begin(), 3095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FrameworkName.end()); 3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (Dir == 0) return 0; 3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if it does, remember that this is the right direntry for this 3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // framework. 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CacheLookup.setValue(Dir); 3155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const FileEntry *FE = 0; 3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" 3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::SmallString<1024> HeadersFilename(FrameworkName); 3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename += "Headers/"; 3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename.append(SlashPos+1, FilenameEnd); 3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!(FE = FileMgr.getFile(HeadersFilename.begin(), 3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename.end()))) { 3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" 3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename = FrameworkName; 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename += "PrivateHeaders/"; 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HeadersFilename.append(SlashPos+1, FilenameEnd); 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end()))) 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This file is a system header or C++ unfriendly if the old file is. 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer getFileInfo(FE).DirInfo = getFileInfo(ContextFileEnt).DirInfo; 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FE; 3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// File Info Management. 3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 3425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFileInfo - Return the PerFileInfo structure for the specified 3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// FileEntry. 3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerHeaderSearch::PerFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { 3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FE->getUID() >= FileInfo.size()) 3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfo.resize(FE->getUID()+1); 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FileInfo[FE->getUID()]; 3505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ShouldEnterIncludeFile - Mark the specified file as a target of of a 3535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// #include, #include_next, or #import directive. Return false if #including 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// the file will have no effect or true if we should include it. 3555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerbool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){ 3565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumIncluded; // Count # of attempted #includes. 3575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get information about this file. 3595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer PerFileInfo &FileInfo = getFileInfo(File); 3605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is a #import directive, check that we have not already imported 3625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // this header. 3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (isImport) { 3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this has already been imported, don't import it again. 3655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfo.isImport = true; 3665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Has this already been #import'ed or #include'd? 3685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileInfo.NumIncludes) return false; 3695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else { 3705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, if this is a #include of a file that was previously #import'd 3715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // or if this is the second #include of a #pragma once file, ignore it. 3725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileInfo.isImport) 3735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return false; 3745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Next, check to see if the file is wrapped with #ifndef guards. If so, and 3775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // if the macro that guards it is defined, we know the #include has no effect. 3789c46de446d18f4a28446cb798d4131bd05515699Chris Lattner if (FileInfo.ControllingMacro && 3799c46de446d18f4a28446cb798d4131bd05515699Chris Lattner FileInfo.ControllingMacro->hasMacroDefinition()) { 3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumMultiIncludeFileOptzn; 3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return false; 3825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Increment the number of times this file has been included. 3855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++FileInfo.NumIncludes; 3865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return true; 3885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 391