clang API Documentation

InitHeaderSearch.cpp

Go to the documentation of this file.
00001 //===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the InitHeaderSearch class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Frontend/Utils.h"
00015 #include "clang/Basic/FileManager.h"
00016 #include "clang/Basic/LangOptions.h"
00017 #include "clang/Frontend/HeaderSearchOptions.h"
00018 #include "clang/Lex/HeaderSearch.h"
00019 #include "llvm/ADT/SmallString.h"
00020 #include "llvm/ADT/SmallPtrSet.h"
00021 #include "llvm/ADT/SmallVector.h"
00022 #include "llvm/ADT/StringExtras.h"
00023 #include "llvm/ADT/Triple.h"
00024 #include "llvm/ADT/Twine.h"
00025 #include "llvm/Support/raw_ostream.h"
00026 #include "llvm/System/Path.h"
00027 #include "llvm/Config/config.h"
00028 #ifdef _MSC_VER
00029   #define WIN32_LEAN_AND_MEAN 1
00030   #include <windows.h>
00031 #endif
00032 using namespace clang;
00033 using namespace clang::frontend;
00034 
00035 namespace {
00036 
00037 /// InitHeaderSearch - This class makes it easier to set the search paths of
00038 ///  a HeaderSearch object. InitHeaderSearch stores several search path lists
00039 ///  internally, which can be sent to a HeaderSearch object in one swoop.
00040 class InitHeaderSearch {
00041   std::vector<DirectoryLookup> IncludeGroup[4];
00042   HeaderSearch& Headers;
00043   bool Verbose;
00044   std::string isysroot;
00045 
00046 public:
00047 
00048   InitHeaderSearch(HeaderSearch &HS,
00049       bool verbose = false, const std::string &iSysroot = "")
00050     : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
00051 
00052   /// AddPath - Add the specified path to the specified group list.
00053   void AddPath(const llvm::Twine &Path, IncludeDirGroup Group,
00054                bool isCXXAware, bool isUserSupplied,
00055                bool isFramework, bool IgnoreSysRoot = false);
00056 
00057   /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
00058   ///  libstdc++.
00059   void AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
00060                                    llvm::StringRef ArchDir,
00061                                    llvm::StringRef Dir32,
00062                                    llvm::StringRef Dir64,
00063                                    const llvm::Triple &triple);
00064 
00065   /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW
00066   ///  libstdc++.
00067   void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
00068                                      llvm::StringRef Arch,
00069                                      llvm::StringRef Version);
00070 
00071   /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
00072   /// separator. The processing follows that of the CPATH variable for gcc.
00073   void AddDelimitedPaths(llvm::StringRef String);
00074 
00075   // AddDefaultCIncludePaths - Add paths that should always be searched.
00076   void AddDefaultCIncludePaths(const llvm::Triple &triple);
00077 
00078   // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
00079   //  compiling c++.
00080   void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
00081 
00082   /// AddDefaultSystemIncludePaths - Adds the default system include paths so
00083   ///  that e.g. stdio.h is found.
00084   void AddDefaultSystemIncludePaths(const LangOptions &Lang,
00085                                     const llvm::Triple &triple,
00086                                     bool UseStandardCXXIncludes);
00087 
00088   /// Realize - Merges all search path lists into one list and send it to
00089   /// HeaderSearch.
00090   void Realize();
00091 };
00092 
00093 }
00094 
00095 void InitHeaderSearch::AddPath(const llvm::Twine &Path,
00096                                IncludeDirGroup Group, bool isCXXAware,
00097                                bool isUserSupplied, bool isFramework,
00098                                bool IgnoreSysRoot) {
00099   assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
00100   FileManager &FM = Headers.getFileMgr();
00101 
00102   // Compute the actual path, taking into consideration -isysroot.
00103   llvm::SmallString<256> MappedPathStr;
00104   llvm::raw_svector_ostream MappedPath(MappedPathStr);
00105 
00106   // Handle isysroot.
00107   if (Group == System && !IgnoreSysRoot) {
00108     // FIXME: Portability.  This should be a sys::Path interface, this doesn't
00109     // handle things like C:\ right, nor win32 \\network\device\blah.
00110     if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present.
00111       MappedPath << isysroot;
00112   }
00113 
00114   Path.print(MappedPath);
00115 
00116   // Compute the DirectoryLookup type.
00117   SrcMgr::CharacteristicKind Type;
00118   if (Group == Quoted || Group == Angled)
00119     Type = SrcMgr::C_User;
00120   else if (isCXXAware)
00121     Type = SrcMgr::C_System;
00122   else
00123     Type = SrcMgr::C_ExternCSystem;
00124 
00125 
00126   // If the directory exists, add it.
00127   if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) {
00128     IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
00129                                                   isFramework));
00130     return;
00131   }
00132 
00133   // Check to see if this is an apple-style headermap (which are not allowed to
00134   // be frameworks).
00135   if (!isFramework) {
00136     if (const FileEntry *FE = FM.getFile(MappedPath.str())) {
00137       if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
00138         // It is a headermap, add it to the search path.
00139         IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
00140         return;
00141       }
00142     }
00143   }
00144 
00145   if (Verbose)
00146     llvm::errs() << "ignoring nonexistent directory \""
00147                  << MappedPath.str() << "\"\n";
00148 }
00149 
00150 
00151 void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) {
00152   if (at.empty()) // Empty string should not add '.' path.
00153     return;
00154 
00155   llvm::StringRef::size_type delim;
00156   while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) {
00157     if (delim == 0)
00158       AddPath(".", Angled, false, true, false);
00159     else
00160       AddPath(at.substr(0, delim), Angled, false, true, false);
00161     at = at.substr(delim + 1);
00162   }
00163 
00164   if (at.empty())
00165     AddPath(".", Angled, false, true, false);
00166   else
00167     AddPath(at, Angled, false, true, false);
00168 }
00169 
00170 void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
00171                                                    llvm::StringRef ArchDir,
00172                                                    llvm::StringRef Dir32,
00173                                                    llvm::StringRef Dir64,
00174                                                    const llvm::Triple &triple) {
00175   // Add the base dir
00176   AddPath(Base, System, true, false, false);
00177 
00178   // Add the multilib dirs
00179   llvm::Triple::ArchType arch = triple.getArch();
00180   bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
00181   if (is64bit)
00182     AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
00183   else
00184     AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
00185 
00186   // Add the backward dir
00187   AddPath(Base + "/backward", System, true, false, false);
00188 }
00189 
00190 void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
00191                                                      llvm::StringRef Arch,
00192                                                      llvm::StringRef Version) {
00193   AddPath(Base + "/" + Arch + "/" + Version + "/include",
00194           System, true, false, false);
00195   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
00196           System, true, false, false);
00197   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
00198           System, true, false, false);
00199 }
00200 
00201   // FIXME: This probably should goto to some platform utils place.
00202 #ifdef _MSC_VER
00203 
00204   // Read registry string.
00205   // This also supports a means to look for high-versioned keys by use
00206   // of a $VERSION placeholder in the key path.
00207   // $VERSION in the key path is a placeholder for the version number,
00208   // causing the highest value path to be searched for and used.
00209   // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
00210   // There can be additional characters in the component.  Only the numberic
00211   // characters are compared.
00212 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
00213                                     char *value, size_t maxLength) {
00214   HKEY hRootKey = NULL;
00215   HKEY hKey = NULL;
00216   const char* subKey = NULL;
00217   DWORD valueType;
00218   DWORD valueSize = maxLength - 1;
00219   long lResult;
00220   bool returnValue = false;
00221   if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
00222     hRootKey = HKEY_CLASSES_ROOT;
00223     subKey = keyPath + 18;
00224   }
00225   else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
00226     hRootKey = HKEY_USERS;
00227     subKey = keyPath + 11;
00228   }
00229   else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
00230     hRootKey = HKEY_LOCAL_MACHINE;
00231     subKey = keyPath + 19;
00232   }
00233   else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
00234     hRootKey = HKEY_CURRENT_USER;
00235     subKey = keyPath + 18;
00236   }
00237   else
00238     return(false);
00239   const char *placeHolder = strstr(subKey, "$VERSION");
00240   char bestName[256];
00241   bestName[0] = '\0';
00242   // If we have a $VERSION placeholder, do the highest-version search.
00243   if (placeHolder) {
00244     const char *keyEnd = placeHolder - 1;
00245     const char *nextKey = placeHolder;
00246     // Find end of previous key.
00247     while ((keyEnd > subKey) && (*keyEnd != '\\'))
00248       keyEnd--;
00249     // Find end of key containing $VERSION.
00250     while (*nextKey && (*nextKey != '\\'))
00251       nextKey++;
00252     size_t partialKeyLength = keyEnd - subKey;
00253     char partialKey[256];
00254     if (partialKeyLength > sizeof(partialKey))
00255       partialKeyLength = sizeof(partialKey);
00256     strncpy(partialKey, subKey, partialKeyLength);
00257     partialKey[partialKeyLength] = '\0';
00258     HKEY hTopKey = NULL;
00259     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
00260     if (lResult == ERROR_SUCCESS) {
00261       char keyName[256];
00262       int bestIndex = -1;
00263       double bestValue = 0.0;
00264       DWORD index, size = sizeof(keyName) - 1;
00265       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
00266           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
00267         const char *sp = keyName;
00268         while (*sp && !isdigit(*sp))
00269           sp++;
00270         if (!*sp)
00271           continue;
00272         const char *ep = sp + 1;
00273         while (*ep && (isdigit(*ep) || (*ep == '.')))
00274           ep++;
00275         char numBuf[32];
00276         strncpy(numBuf, sp, sizeof(numBuf) - 1);
00277         numBuf[sizeof(numBuf) - 1] = '\0';
00278         double value = strtod(numBuf, NULL);
00279         if (value > bestValue) {
00280           bestIndex = (int)index;
00281           bestValue = value;
00282           strcpy(bestName, keyName);
00283         }
00284         size = sizeof(keyName) - 1;
00285       }
00286       // If we found the highest versioned key, open the key and get the value.
00287       if (bestIndex != -1) {
00288         // Append rest of key.
00289         strncat(bestName, nextKey, sizeof(bestName) - 1);
00290         bestName[sizeof(bestName) - 1] = '\0';
00291         // Open the chosen key path remainder.
00292         lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
00293         if (lResult == ERROR_SUCCESS) {
00294           lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
00295             (LPBYTE)value, &valueSize);
00296           if (lResult == ERROR_SUCCESS)
00297             returnValue = true;
00298           RegCloseKey(hKey);
00299         }
00300       }
00301       RegCloseKey(hTopKey);
00302     }
00303   }
00304   else {
00305     lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
00306     if (lResult == ERROR_SUCCESS) {
00307       lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
00308         (LPBYTE)value, &valueSize);
00309       if (lResult == ERROR_SUCCESS)
00310         returnValue = true;
00311       RegCloseKey(hKey);
00312     }
00313   }
00314   return(returnValue);
00315 }
00316 #else // _MSC_VER
00317   // Read registry string.
00318 static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
00319   return(false);
00320 }
00321 #endif // _MSC_VER
00322 
00323   // Get Visual Studio installation directory.
00324 static bool getVisualStudioDir(std::string &path) {
00325   char vsIDEInstallDir[256];
00326   // Try the Windows registry first.
00327   bool hasVCDir = getSystemRegistryString(
00328     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
00329     "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
00330     // If we have both vc80 and vc90, pick version we were compiled with. 
00331   if (hasVCDir && vsIDEInstallDir[0]) {
00332     char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
00333     if (p)
00334       *p = '\0';
00335     path = vsIDEInstallDir;
00336     return(true);
00337   }
00338   else {
00339     // Try the environment.
00340     const char* vs90comntools = getenv("VS90COMNTOOLS");
00341     const char* vs80comntools = getenv("VS80COMNTOOLS");
00342     const char* vscomntools = NULL;
00343       // If we have both vc80 and vc90, pick version we were compiled with. 
00344     if (vs90comntools && vs80comntools) {
00345       #if (_MSC_VER >= 1500)  // VC90
00346           vscomntools = vs90comntools;
00347       #elif (_MSC_VER == 1400) // VC80
00348           vscomntools = vs80comntools;
00349       #else
00350           vscomntools = vs90comntools;
00351       #endif
00352     }
00353     else if (vs90comntools)
00354       vscomntools = vs90comntools;
00355     else if (vs80comntools)
00356       vscomntools = vs80comntools;
00357     if (vscomntools && *vscomntools) {
00358       char *p = const_cast<char *>(strstr(vscomntools, "\\Common7\\Tools"));
00359       if (p)
00360         *p = '\0';
00361       path = vscomntools;
00362       return(true);
00363     }
00364     else
00365       return(false);
00366   }
00367   return(false);
00368 }
00369 
00370   // Get Windows SDK installation directory.
00371 static bool getWindowsSDKDir(std::string &path) {
00372   char windowsSDKInstallDir[256];
00373   // Try the Windows registry.
00374   bool hasSDKDir = getSystemRegistryString(
00375    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
00376     "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1);
00377     // If we have both vc80 and vc90, pick version we were compiled with. 
00378   if (hasSDKDir && windowsSDKInstallDir[0]) {
00379     path = windowsSDKInstallDir;
00380     return(true);
00381   }
00382   return(false);
00383 }
00384 
00385 void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
00386   // FIXME: temporary hack: hard-coded paths.
00387   llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
00388   if (CIncludeDirs != "") {
00389     llvm::SmallVector<llvm::StringRef, 5> dirs;
00390     CIncludeDirs.split(dirs, ":");
00391     for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
00392          i != dirs.end();
00393          ++i) 
00394       AddPath(*i, System, false, false, false);
00395     return;
00396   }
00397   llvm::Triple::OSType os = triple.getOS();
00398   switch (os) {
00399   case llvm::Triple::Win32:
00400     {
00401       std::string VSDir;
00402       std::string WindowsSDKDir;
00403       if (getVisualStudioDir(VSDir)) {
00404         AddPath(VSDir + "\\VC\\include", System, false, false, false);
00405         if (getWindowsSDKDir(WindowsSDKDir))
00406           AddPath(WindowsSDKDir, System, false, false, false);
00407         else
00408           AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
00409             System, false, false, false);
00410       }
00411       else {
00412           // Default install paths.
00413         AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
00414           System, false, false, false);
00415         AddPath(
00416         "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
00417           System, false, false, false);
00418         AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include",
00419           System, false, false, false);
00420         AddPath(
00421         "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include",
00422           System, false, false, false);
00423           // For some clang developers.
00424         AddPath("G:/Program Files/Microsoft Visual Studio 9.0/VC/include",
00425           System, false, false, false);
00426         AddPath(
00427         "G:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
00428           System, false, false, false);
00429       }
00430     }
00431     break;
00432   case llvm::Triple::Haiku:
00433     AddPath("/boot/common/include", System, true, false, false);
00434     AddPath("/boot/develop/headers/os", System, true, false, false);
00435     AddPath("/boot/develop/headers/os/app", System, true, false, false);
00436     AddPath("/boot/develop/headers/os/arch", System, true, false, false);
00437     AddPath("/boot/develop/headers/os/device", System, true, false, false);
00438     AddPath("/boot/develop/headers/os/drivers", System, true, false, false);
00439     AddPath("/boot/develop/headers/os/game", System, true, false, false); 
00440     AddPath("/boot/develop/headers/os/interface", System, true, false, false);
00441     AddPath("/boot/develop/headers/os/kernel", System, true, false, false);
00442     AddPath("/boot/develop/headers/os/locale", System, true, false, false);
00443     AddPath("/boot/develop/headers/os/mail", System, true, false, false);
00444     AddPath("/boot/develop/headers/os/media", System, true, false, false);
00445     AddPath("/boot/develop/headers/os/midi", System, true, false, false);
00446     AddPath("/boot/develop/headers/os/midi2", System, true, false, false);
00447     AddPath("/boot/develop/headers/os/net", System, true, false, false);
00448     AddPath("/boot/develop/headers/os/storage", System, true, false, false);
00449     AddPath("/boot/develop/headers/os/support", System, true, false, false);
00450     AddPath("/boot/develop/headers/os/translation",
00451       System, true, false, false);
00452     AddPath("/boot/develop/headers/os/add-ons/graphics", 
00453       System, true, false, false);
00454     AddPath("/boot/develop/headers/os/add-ons/input_server", 
00455       System, true, false, false);
00456     AddPath("/boot/develop/headers/os/add-ons/screen_saver", 
00457       System, true, false, false);
00458     AddPath("/boot/develop/headers/os/add-ons/tracker", 
00459       System, true, false, false);
00460     AddPath("/boot/develop/headers/os/be_apps/Deskbar",
00461       System, true, false, false);
00462     AddPath("/boot/develop/headers/os/be_apps/NetPositive",
00463       System, true, false, false);
00464     AddPath("/boot/develop/headers/os/be_apps/Tracker",
00465       System, true, false, false);
00466     AddPath("/boot/develop/headers/cpp", System, true, false, false);
00467     AddPath("/boot/develop/headers/cpp/i586-pc-haiku", 
00468       System, true, false, false);
00469     AddPath("/boot/develop/headers/3rdparty", System, true, false, false);
00470     AddPath("/boot/develop/headers/bsd", System, true, false, false);
00471     AddPath("/boot/develop/headers/glibc", System, true, false, false);
00472     AddPath("/boot/develop/headers/posix", System, true, false, false);
00473     AddPath("/boot/develop/headers",  System, true, false, false);
00474     break;
00475   case llvm::Triple::MinGW64:
00476   case llvm::Triple::MinGW32:
00477     AddPath("c:/mingw/include", System, true, false, false);
00478     break;
00479   default:
00480     break;
00481   }
00482 
00483   AddPath("/usr/local/include", System, true, false, false);
00484   AddPath("/usr/include", System, false, false, false);
00485 }
00486 
00487 void InitHeaderSearch::
00488 AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
00489   llvm::Triple::OSType os = triple.getOS();
00490   llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
00491   if (CxxIncludeRoot != "") {
00492     llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
00493     if (CxxIncludeArch == "")
00494       AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
00495                                   CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
00496                                   triple);
00497     else
00498       AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
00499                                   CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
00500                                   triple);
00501     return;
00502   }
00503   // FIXME: temporary hack: hard-coded paths.
00504   switch (os) {
00505   case llvm::Triple::Cygwin:
00506     AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
00507         System, true, false, false);
00508     AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
00509         System, true, false, false);
00510     break;
00511   case llvm::Triple::MinGW64:
00512     // Try gcc 4.4.0
00513     AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
00514     // Try gcc 4.3.0
00515     AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
00516     // Fall through.
00517   case llvm::Triple::MinGW32:
00518     // Try gcc 4.4.0
00519     AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
00520     // Try gcc 4.3.0
00521     AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
00522     break;
00523   case llvm::Triple::Darwin:
00524     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
00525                                 "i686-apple-darwin10", "", "x86_64", triple);
00526     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
00527                                 "i686-apple-darwin8", "", "", triple);
00528     break;
00529   case llvm::Triple::DragonFly:
00530     AddPath("/usr/include/c++/4.1", System, true, false, false);
00531     break;
00532   case llvm::Triple::Linux:
00533     // Exherbo (2010-01-25)
00534     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
00535                                 "x86_64-pc-linux-gnu", "32", "", triple);
00536     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
00537                                 "i686-pc-linux-gnu", "", "", triple);
00538     // Debian sid
00539     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
00540                                 "x86_64-linux-gnu", "32", "", triple);
00541     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
00542                                 "i486-linux-gnu", "64", "", triple);
00543     // Ubuntu 7.10 - Gutsy Gibbon
00544     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
00545                                 "i486-linux-gnu", "", "", triple);
00546     // Ubuntu 9.04
00547     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
00548                                 "x86_64-linux-gnu","32", "", triple);
00549     // Ubuntu 9.10
00550     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
00551                                 "x86_64-linux-gnu", "32", "", triple);
00552     // Fedora 8
00553     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
00554                                 "i386-redhat-linux", "", "", triple);
00555     // Fedora 9
00556     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
00557                                 "i386-redhat-linux", "", "", triple);
00558     // Fedora 10
00559     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
00560                                 "i386-redhat-linux","", "", triple);
00561 
00562     // Fedora 10 x86_64
00563     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
00564                                 "x86_64-redhat-linux", "32", "", triple);
00565 
00566     // Fedora 11
00567     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
00568                                 "i586-redhat-linux","", "", triple);
00569 
00570     // Fedora 11 x86_64
00571     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
00572                                 "x86_64-redhat-linux", "32", "", triple);
00573 
00574     // Fedora 12
00575     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
00576                                 "i686-redhat-linux","", "", triple);
00577 
00578     // Fedora 12 x86_64
00579     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
00580                                 "x86_64-redhat-linux", "32", "", triple);
00581 
00582     // Fedora 12 (February-2010+)
00583     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
00584                                 "i686-redhat-linux","", "", triple);
00585 
00586     // Fedora 12 (February-2010+) x86_64
00587     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
00588                                 "x86_64-redhat-linux", "32", "", triple);
00589 
00590     // openSUSE 11.1 32 bit
00591     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
00592                                 "i586-suse-linux", "", "", triple);
00593     // openSUSE 11.1 64 bit
00594     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
00595                                 "x86_64-suse-linux", "32", "", triple);
00596     // openSUSE 11.2
00597     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
00598                                 "i586-suse-linux", "", "", triple);
00599     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
00600                                 "x86_64-suse-linux", "", "", triple);
00601     // Arch Linux 2008-06-24
00602     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
00603                                 "i686-pc-linux-gnu", "", "", triple);
00604     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
00605                                 "x86_64-unknown-linux-gnu", "", "", triple);
00606     // Gentoo x86 2009.1 stable
00607     AddGnuCPlusPlusIncludePaths(
00608       "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
00609       "i686-pc-linux-gnu", "", "", triple);
00610     // Gentoo x86 2009.0 stable
00611     AddGnuCPlusPlusIncludePaths(
00612       "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
00613       "i686-pc-linux-gnu", "", "", triple);
00614     // Gentoo x86 2008.0 stable
00615     AddGnuCPlusPlusIncludePaths(
00616       "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
00617       "i686-pc-linux-gnu", "", "", triple);
00618     // Ubuntu 8.10
00619     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
00620                                 "i486-pc-linux-gnu", "", "", triple);
00621     // Ubuntu 9.04
00622     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
00623                                 "i486-linux-gnu","", "", triple);
00624     // Gentoo amd64 stable
00625     AddGnuCPlusPlusIncludePaths(
00626         "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
00627         "i686-pc-linux-gnu", "", "", triple);
00628         
00629     // Gentoo amd64 gcc 4.3.2
00630     AddGnuCPlusPlusIncludePaths(
00631         "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4",
00632         "x86_64-pc-linux-gnu", "", "", triple);
00633         
00634     // Gentoo amd64 gcc 4.4.3
00635     AddGnuCPlusPlusIncludePaths(
00636         "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4",
00637         "x86_64-pc-linux-gnu", "32", "", triple);
00638     
00639     break;
00640   case llvm::Triple::FreeBSD:
00641     AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
00642     break;
00643   case llvm::Triple::Solaris:
00644     // Solaris - Fall though..
00645   case llvm::Triple::AuroraUX:
00646     // AuroraUX
00647     AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
00648                                 "i386-pc-solaris2.11", "", "", triple);
00649     break;
00650   default:
00651     break;
00652   }
00653 }
00654 
00655 void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
00656                                                     const llvm::Triple &triple,
00657                                                   bool UseStandardCXXIncludes) {
00658   if (Lang.CPlusPlus && UseStandardCXXIncludes)
00659     AddDefaultCPlusPlusIncludePaths(triple);
00660 
00661   AddDefaultCIncludePaths(triple);
00662 
00663   // Add the default framework include paths on Darwin.
00664   if (triple.getOS() == llvm::Triple::Darwin) {
00665     AddPath("/System/Library/Frameworks", System, true, false, true);
00666     AddPath("/Library/Frameworks", System, true, false, true);
00667   }
00668 }
00669 
00670 /// RemoveDuplicates - If there are duplicate directory entries in the specified
00671 /// search list, remove the later (dead) ones.
00672 static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
00673                              bool Verbose) {
00674   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
00675   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
00676   llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
00677   for (unsigned i = 0; i != SearchList.size(); ++i) {
00678     unsigned DirToRemove = i;
00679 
00680     const DirectoryLookup &CurEntry = SearchList[i];
00681 
00682     if (CurEntry.isNormalDir()) {
00683       // If this isn't the first time we've seen this dir, remove it.
00684       if (SeenDirs.insert(CurEntry.getDir()))
00685         continue;
00686     } else if (CurEntry.isFramework()) {
00687       // If this isn't the first time we've seen this framework dir, remove it.
00688       if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
00689         continue;
00690     } else {
00691       assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
00692       // If this isn't the first time we've seen this headermap, remove it.
00693       if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
00694         continue;
00695     }
00696 
00697     // If we have a normal #include dir/framework/headermap that is shadowed
00698     // later in the chain by a system include location, we actually want to
00699     // ignore the user's request and drop the user dir... keeping the system
00700     // dir.  This is weird, but required to emulate GCC's search path correctly.
00701     //
00702     // Since dupes of system dirs are rare, just rescan to find the original
00703     // that we're nuking instead of using a DenseMap.
00704     if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
00705       // Find the dir that this is the same of.
00706       unsigned FirstDir;
00707       for (FirstDir = 0; ; ++FirstDir) {
00708         assert(FirstDir != i && "Didn't find dupe?");
00709 
00710         const DirectoryLookup &SearchEntry = SearchList[FirstDir];
00711 
00712         // If these are different lookup types, then they can't be the dupe.
00713         if (SearchEntry.getLookupType() != CurEntry.getLookupType())
00714           continue;
00715 
00716         bool isSame;
00717         if (CurEntry.isNormalDir())
00718           isSame = SearchEntry.getDir() == CurEntry.getDir();
00719         else if (CurEntry.isFramework())
00720           isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
00721         else {
00722           assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
00723           isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
00724         }
00725 
00726         if (isSame)
00727           break;
00728       }
00729 
00730       // If the first dir in the search path is a non-system dir, zap it
00731       // instead of the system one.
00732       if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
00733         DirToRemove = FirstDir;
00734     }
00735 
00736     if (Verbose) {
00737       llvm::errs() << "ignoring duplicate directory \""
00738                    << CurEntry.getName() << "\"\n";
00739       if (DirToRemove != i)
00740         llvm::errs() << "  as it is a non-system directory that duplicates "
00741                      << "a system directory\n";
00742     }
00743 
00744     // This is reached if the current entry is a duplicate.  Remove the
00745     // DirToRemove (usually the current dir).
00746     SearchList.erase(SearchList.begin()+DirToRemove);
00747     --i;
00748   }
00749 }
00750 
00751 
00752 void InitHeaderSearch::Realize() {
00753   // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
00754   std::vector<DirectoryLookup> SearchList;
00755   SearchList = IncludeGroup[Angled];
00756   SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
00757                     IncludeGroup[System].end());
00758   SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
00759                     IncludeGroup[After].end());
00760   RemoveDuplicates(SearchList, Verbose);
00761   RemoveDuplicates(IncludeGroup[Quoted], Verbose);
00762 
00763   // Prepend QUOTED list on the search list.
00764   SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
00765                     IncludeGroup[Quoted].end());
00766 
00767 
00768   bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
00769   Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
00770                          DontSearchCurDir);
00771 
00772   // If verbose, print the list of directories that will be searched.
00773   if (Verbose) {
00774     llvm::errs() << "#include \"...\" search starts here:\n";
00775     unsigned QuotedIdx = IncludeGroup[Quoted].size();
00776     for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
00777       if (i == QuotedIdx)
00778         llvm::errs() << "#include <...> search starts here:\n";
00779       const char *Name = SearchList[i].getName();
00780       const char *Suffix;
00781       if (SearchList[i].isNormalDir())
00782         Suffix = "";
00783       else if (SearchList[i].isFramework())
00784         Suffix = " (framework directory)";
00785       else {
00786         assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
00787         Suffix = " (headermap)";
00788       }
00789       llvm::errs() << " " << Name << Suffix << "\n";
00790     }
00791     llvm::errs() << "End of search list.\n";
00792   }
00793 }
00794 
00795 void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
00796                                      const HeaderSearchOptions &HSOpts,
00797                                      const LangOptions &Lang,
00798                                      const llvm::Triple &Triple) {
00799   InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
00800 
00801   // Add the user defined entries.
00802   for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
00803     const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
00804     Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
00805                  false);
00806   }
00807 
00808   // Add entries from CPATH and friends.
00809   Init.AddDelimitedPaths(HSOpts.EnvIncPath);
00810   if (Lang.CPlusPlus && Lang.ObjC1)
00811     Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
00812   else if (Lang.CPlusPlus)
00813     Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
00814   else if (Lang.ObjC1)
00815     Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
00816   else
00817     Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
00818 
00819   if (HSOpts.UseBuiltinIncludes) {
00820     // Ignore the sys root, we *always* look for clang headers relative to
00821     // supplied path.
00822     llvm::sys::Path P(HSOpts.ResourceDir);
00823     P.appendComponent("include");
00824     Init.AddPath(P.str(), System, false, false, false, /*IgnoreSysRoot=*/ true);
00825   }
00826 
00827   if (HSOpts.UseStandardIncludes)
00828     Init.AddDefaultSystemIncludePaths(Lang, Triple, 
00829                                       HSOpts.UseStandardCXXIncludes);
00830 
00831   Init.Realize();
00832 }