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