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