InitHeaderSearch.cpp revision 199990
194380Sdfr//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===//
294380Sdfr//
394380Sdfr//                     The LLVM Compiler Infrastructure
494380Sdfr//
594380Sdfr// This file is distributed under the University of Illinois Open Source
6313452Sjhb// License. See LICENSE.TXT for details.
794380Sdfr//
894380Sdfr//===----------------------------------------------------------------------===//
9119332Speter//
10119332Speter// This file implements the InitHeaderSearch class.
1194380Sdfr//
1294380Sdfr//===----------------------------------------------------------------------===//
1394380Sdfr
14177613Sjhb#include "clang/Frontend/Utils.h"
15227776Slstewart#include "clang/Basic/FileManager.h"
16164199Sru#include "clang/Basic/LangOptions.h"
17113989Sjhb#include "clang/Frontend/HeaderSearchOptions.h"
18255658Sjilles#include "clang/Lex/HeaderSearch.h"
19113989Sjhb#include "llvm/ADT/SmallString.h"
20161330Sjhb#include "llvm/ADT/SmallPtrSet.h"
21161330Sjhb#include "llvm/ADT/SmallVector.h"
2294380Sdfr#include "llvm/ADT/StringExtras.h"
2394380Sdfr#include "llvm/ADT/Triple.h"
2494380Sdfr#include "llvm/Support/raw_ostream.h"
2594380Sdfr#include "llvm/System/Path.h"
2694380Sdfr#include "llvm/Config/config.h"
2794380Sdfr#include <cstdio>
2894380Sdfr#ifdef _MSC_VER
2994380Sdfr  #define WIN32_LEAN_AND_MEAN 1
3094380Sdfr  #include <windows.h>
3194380Sdfr#endif
3294380Sdfrusing namespace clang;
3394380Sdfrusing namespace clang::frontend;
3494380Sdfr
3594380Sdfrnamespace {
3694380Sdfr
37232449Sjmallett/// InitHeaderSearch - This class makes it easier to set the search paths of
38205014Snwhitehorn///  a HeaderSearch object. InitHeaderSearch stores several search path lists
39205014Snwhitehorn///  internally, which can be sent to a HeaderSearch object in one swoop.
40119332Speterclass InitHeaderSearch {
4194380Sdfr  std::vector<DirectoryLookup> IncludeGroup[4];
4294380Sdfr  HeaderSearch& Headers;
4394380Sdfr  bool Verbose;
44100385Speter  std::string isysroot;
4594380Sdfr
46151360Spspublic:
47151360Sps
48151360Sps  InitHeaderSearch(HeaderSearch &HS,
49151360Sps      bool verbose = false, const std::string &iSysroot = "")
50151360Sps    : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
51151360Sps
52151360Sps  /// AddPath - Add the specified path to the specified group list.
53151360Sps  void AddPath(const llvm::StringRef &Path, IncludeDirGroup Group,
54151360Sps               bool isCXXAware, bool isUserSupplied,
55151360Sps               bool isFramework, bool IgnoreSysRoot = false);
56151360Sps
57151360Sps  /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu
58236027Sed  ///  libstdc++.
59236027Sed  void AddGnuCPlusPlusIncludePaths(const std::string &Base,
60151360Sps                                   const char *ArchDir,
61236027Sed                                   const char *Dir32,
62236027Sed                                   const char *Dir64,
63151360Sps                                   const llvm::Triple &triple);
64302095Sbrooks
65302095Sbrooks  /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW
66302095Sbrooks  ///  libstdc++.
67151721Speter  void AddMinGWCPlusPlusIncludePaths(const std::string &Base,
68151583Sps                                     const char *Arch,
69151583Sps                                     const char *Version);
70119332Speter
71100385Speter  /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
72100385Speter  /// separator. The processing follows that of the CPATH variable for gcc.
7394380Sdfr  void AddDelimitedPaths(const char *String);
74183271Sobrien
75183271Sobrien  // AddDefaultCIncludePaths - Add paths that should always be searched.
76183271Sobrien  void AddDefaultCIncludePaths(const llvm::Triple &triple);
77183271Sobrien
78183271Sobrien  // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
79119332Speter  //  compiling c++.
8094380Sdfr  void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
81236027Sed
82236027Sed  /// AddDefaultSystemIncludePaths - Adds the default system include paths so
8394380Sdfr  ///  that e.g. stdio.h is found.
84226349Smarcel  void AddDefaultSystemIncludePaths(const LangOptions &Lang,
85226349Smarcel                                    const llvm::Triple &triple);
86226349Smarcel
87226349Smarcel  /// Realize - Merges all search path lists into one list and send it to
88226349Smarcel  /// HeaderSearch.
89119332Speter  void Realize();
9094380Sdfr};
91100385Speter
92100385Speter}
9394380Sdfr
94125171Spetervoid InitHeaderSearch::AddPath(const llvm::StringRef &Path,
95125171Speter                               IncludeDirGroup Group, bool isCXXAware,
96125171Speter                               bool isUserSupplied, bool isFramework,
97125171Speter                               bool IgnoreSysRoot) {
98270692Skib  assert(!Path.empty() && "can't handle empty path here");
99270692Skib  FileManager &FM = Headers.getFileMgr();
100270692Skib
101270692Skib  // Compute the actual path, taking into consideration -isysroot.
102270692Skib  llvm::SmallString<256> MappedPath;
103119332Speter
10494380Sdfr  // Handle isysroot.
10594380Sdfr  if (Group == System && !IgnoreSysRoot) {
10694380Sdfr    // FIXME: Portability.  This should be a sys::Path interface, this doesn't
10794380Sdfr    // handle things like C:\ right, nor win32 \\network\device\blah.
108100385Speter    if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present.
10994380Sdfr      MappedPath.append(isysroot.begin(), isysroot.end());
110119332Speter  }
111100385Speter
11294380Sdfr  MappedPath.append(Path.begin(), Path.end());
11394380Sdfr
114119332Speter  // Compute the DirectoryLookup type.
11594380Sdfr  SrcMgr::CharacteristicKind Type;
116100385Speter  if (Group == Quoted || Group == Angled)
11794380Sdfr    Type = SrcMgr::C_User;
118119332Speter  else if (isCXXAware)
11994380Sdfr    Type = SrcMgr::C_System;
120100385Speter  else
12194380Sdfr    Type = SrcMgr::C_ExternCSystem;
12294380Sdfr
123119332Speter
12494380Sdfr  // If the directory exists, add it.
125100385Speter  if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) {
12694380Sdfr    IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
12794380Sdfr                                                  isFramework));
128119332Speter    return;
129100385Speter  }
13094380Sdfr
13194380Sdfr  // Check to see if this is an apple-style headermap (which are not allowed to
132119332Speter  // be frameworks).
13394380Sdfr  if (!isFramework) {
134100385Speter    if (const FileEntry *FE = FM.getFile(MappedPath.str())) {
13594380Sdfr      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
136119332Speter        // It is a headermap, add it to the search path.
137100385Speter        IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
138100385Speter        return;
13994380Sdfr      }
140190622Skib    }
141190622Skib  }
142190622Skib
143190622Skib  if (Verbose)
144119332Speter    llvm::errs() << "ignoring nonexistent directory \""
14594380Sdfr                 << MappedPath.str() << "\"\n";
14694380Sdfr}
14794380Sdfr
14894380Sdfr
14994380Sdfrvoid InitHeaderSearch::AddDelimitedPaths(const char *at) {
15094380Sdfr  if (*at == 0) // Empty string should not add '.' path.
151119332Speter    return;
15294380Sdfr
15394380Sdfr  const char* delim = strchr(at, llvm::sys::PathSeparator);
15494380Sdfr  while (delim != 0) {
15594380Sdfr    if (delim-at == 0)
15694380Sdfr      AddPath(".", Angled, false, true, false);
15794380Sdfr    else
15894380Sdfr      AddPath(llvm::StringRef(at, delim-at), Angled, false, true, false);
159119332Speter    at = delim + 1;
160157286Sps    delim = strchr(at, llvm::sys::PathSeparator);
161157286Sps  }
162157286Sps  if (*at == 0)
163157286Sps    AddPath(".", Angled, false, true, false);
16494380Sdfr  else
165119332Speter    AddPath(at, Angled, false, true, false);
16694380Sdfr}
167100385Speter
16894380Sdfrvoid InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base,
169119332Speter                                                   const char *ArchDir,
17094380Sdfr                                                   const char *Dir32,
171100385Speter                                                   const char *Dir64,
17294380Sdfr                                                   const llvm::Triple &triple) {
173119332Speter  // Add the base dir
17494380Sdfr  AddPath(Base, System, true, false, false);
175100385Speter
17694380Sdfr  // Add the multilib dirs
177184184Sjhb  llvm::Triple::ArchType arch = triple.getArch();
178184184Sjhb  bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
179184184Sjhb  if (is64bit)
180184184Sjhb    AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
181184184Sjhb  else
182184184Sjhb    AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
183119332Speter
18494380Sdfr  // Add the backward dir
18594380Sdfr  AddPath(Base + "/backward", System, true, false, false);
18694380Sdfr}
187236027Sed
18894380Sdfrvoid InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base,
189236027Sed                                                     const char *Arch,
19094380Sdfr                                                     const char *Version) {
191154596Sambrisko  std::string localBase = Base + "/" + Arch + "/" + Version + "/include";
192154596Sambrisko  AddPath(localBase, System, true, false, false);
193154596Sambrisko  AddPath(localBase + "/c++", System, true, false, false);
194154596Sambrisko  AddPath(localBase + "/c++/backward", System, true, false, false);
195165406Sjkim}
196165406Sjkim
197165406Sjkim  // FIXME: This probably should goto to some platform utils place.
198165406Sjkim#ifdef _MSC_VER
199165406Sjkim
200165406Sjkim  // Read registry string.
201165406Sjkim  // This also supports a means to look for high-versioned keys by use
202165406Sjkim  // of a $VERSION placeholder in the key path.
203165406Sjkim  // $VERSION in the key path is a placeholder for the version number,
204165406Sjkim  // causing the highest value path to be searched for and used.
205165406Sjkim  // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
206165406Sjkim  // There can be additional characters in the component.  Only the numberic
207165406Sjkim  // characters are compared.
208151358Spsbool getSystemRegistryString(const char *keyPath, const char *valueName,
209151358Sps                       char *value, size_t maxLength) {
210151358Sps  HKEY hRootKey = NULL;
211151358Sps  HKEY hKey = NULL;
212151358Sps  const char* subKey = NULL;
213151358Sps  DWORD valueType;
214151358Sps  DWORD valueSize = maxLength - 1;
215151358Sps  long lResult;
216151358Sps  bool returnValue = false;
217151358Sps  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
218151358Sps    hRootKey = HKEY_CLASSES_ROOT;
219151358Sps    subKey = keyPath + 18;
220253531Skib  }
221253531Skib  else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
222253531Skib    hRootKey = HKEY_USERS;
223253531Skib    subKey = keyPath + 11;
224253531Skib  }
225253531Skib  else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
226253531Skib    hRootKey = HKEY_LOCAL_MACHINE;
227253531Skib    subKey = keyPath + 19;
228253531Skib  }
229253531Skib  else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
230253531Skib    hRootKey = HKEY_CURRENT_USER;
231253531Skib    subKey = keyPath + 18;
232253531Skib  }
233253531Skib  else
234253531Skib    return(false);
235140481Sps  const char *placeHolder = strstr(subKey, "$VERSION");
236151356Sps  char bestName[256];
237151356Sps  bestName[0] = '\0';
238140481Sps  // If we have a $VERSION placeholder, do the highest-version search.
239253495Skib  if (placeHolder) {
240253495Skib    const char *keyEnd = placeHolder - 1;
241253495Skib    const char *nextKey = placeHolder;
242253495Skib    // Find end of previous key.
243253495Skib    while ((keyEnd > subKey) && (*keyEnd != '\\'))
244253495Skib      keyEnd--;
245185879Sjhb    // Find end of key containing $VERSION.
246185879Sjhb    while (*nextKey && (*nextKey != '\\'))
247185879Sjhb      nextKey++;
248185879Sjhb    size_t partialKeyLength = keyEnd - subKey;
249185879Sjhb    char partialKey[256];
250185879Sjhb    if (partialKeyLength > sizeof(partialKey))
251185879Sjhb      partialKeyLength = sizeof(partialKey);
252185879Sjhb    strncpy(partialKey, subKey, partialKeyLength);
253185879Sjhb    partialKey[partialKeyLength] = '\0';
254185879Sjhb    HKEY hTopKey = NULL;
255253531Skib    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
256185879Sjhb    if (lResult == ERROR_SUCCESS) {
257154587Sambrisko      char keyName[256];
258154587Sambrisko      int bestIndex = -1;
259154587Sambrisko      double bestValue = 0.0;
260154587Sambrisko      DWORD index, size = sizeof(keyName) - 1;
261147814Sjhb      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
262147814Sjhb          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
263147814Sjhb        const char *sp = keyName;
264147814Sjhb        while (*sp && !isdigit(*sp))
265236027Sed          sp++;
266236027Sed        if (!*sp)
267147814Sjhb          continue;
268147814Sjhb        const char *ep = sp + 1;
269147814Sjhb        while (*ep && (isdigit(*ep) || (*ep == '.')))
270147814Sjhb          ep++;
271147814Sjhb        char numBuf[32];
272236027Sed        strncpy(numBuf, sp, sizeof(numBuf) - 1);
273236027Sed        numBuf[sizeof(numBuf) - 1] = '\0';
274147814Sjhb        double value = strtod(numBuf, NULL);
275140482Sps        if (value > bestValue) {
276140482Sps          bestIndex = (int)index;
277140482Sps          bestValue = value;
278140482Sps          strcpy(bestName, keyName);
279220159Skib        }
280220159Skib        size = sizeof(keyName) - 1;
281220159Skib      }
282220159Skib      // If we found the highest versioned key, open the key and get the value.
283185879Sjhb      if (bestIndex != -1) {
284185879Sjhb        // Append rest of key.
285185879Sjhb        strncat(bestName, nextKey, sizeof(bestName) - 1);
286185879Sjhb        bestName[sizeof(bestName) - 1] = '\0';
287185879Sjhb        // Open the chosen key path remainder.
288185879Sjhb        lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
289185879Sjhb        if (lResult == ERROR_SUCCESS) {
290185879Sjhb          lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
291185879Sjhb            (LPBYTE)value, &valueSize);
292185879Sjhb          if (lResult == ERROR_SUCCESS)
293185879Sjhb            returnValue = true;
294185436Sbz          RegCloseKey(hKey);
295185436Sbz        }
296185436Sbz      }
297163020Sdavidxu      RegCloseKey(hTopKey);
298163020Sdavidxu    }
299163020Sdavidxu  }
300163020Sdavidxu  else {
301163020Sdavidxu    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
302163020Sdavidxu    if (lResult == ERROR_SUCCESS) {
303163020Sdavidxu      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
304163020Sdavidxu        (LPBYTE)value, &valueSize);
305163020Sdavidxu      if (lResult == ERROR_SUCCESS)
306185879Sjhb        returnValue = true;
307185879Sjhb      RegCloseKey(hKey);
308185879Sjhb    }
309185879Sjhb  }
310119332Speter  return(returnValue);
311114988Speter}
312142874Sps#else // _MSC_VER
313114988Speter  // Read registry string.
314142874Spsbool getSystemRegistryString(const char *, const char *, char *, size_t) {
315114988Speter  return(false);
316142874Sps}
317104739Speter#endif // _MSC_VER
318183189Sobrien
319183189Sobrien  // Get Visual Studio installation directory.
320183189Sobrienbool getVisualStudioDir(std::string &path) {
321183189Sobrien  char vsIDEInstallDir[256];
322183189Sobrien  // Try the Windows registry first.
323119332Speter  bool hasVCDir = getSystemRegistryString(
32494380Sdfr    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
32594380Sdfr    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
326236027Sed    // If we have both vc80 and vc90, pick version we were compiled with.
327236027Sed  if (hasVCDir && vsIDEInstallDir[0]) {
32894380Sdfr    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
329156115Sps    if (p)
33094380Sdfr      *p = '\0';
33194380Sdfr    path = vsIDEInstallDir;
33294380Sdfr    return(true);
333205328Skib  }
334205328Skib  else {
335205328Skib    // Try the environment.
336205328Skib    const char* vs90comntools = getenv("VS90COMNTOOLS");
337205328Skib    const char* vs80comntools = getenv("VS80COMNTOOLS");
338205328Skib    const char* vscomntools = NULL;
339205328Skib      // If we have both vc80 and vc90, pick version we were compiled with.
340205328Skib    if (vs90comntools && vs80comntools) {
341205328Skib      #if (_MSC_VER >= 1500)  // VC90
342205328Skib          vscomntools = vs90comntools;
343205328Skib      #elif (_MSC_VER == 1400) // VC80
344119332Speter          vscomntools = vs80comntools;
345114988Speter      #else
346114988Speter          vscomntools = vs90comntools;
347114988Speter      #endif
348114988Speter    }
349119332Speter    else if (vs90comntools)
350119332Speter      vscomntools = vs90comntools;
351119194Speter    else if (vs80comntools)
352150632Speter      vscomntools = vs80comntools;
353150632Speter    if (vscomntools && *vscomntools) {
354150632Speter      char *p = (char*)strstr(vscomntools, "\\Common7\\Tools");
355150632Speter      if (p)
356150632Speter        *p = '\0';
357150632Speter      path = vscomntools;
358150632Speter      return(true);
359150632Speter    }
360150632Speter    else
361150632Speter      return(false);
362205328Skib  }
363205328Skib  return(false);
364205328Skib}
365205328Skib
366162552Sdavidxu  // Get Windows SDK installation directory.
367162552Sdavidxubool getWindowsSDKDir(std::string &path) {
368162552Sdavidxu  char windowsSDKInstallDir[256];
369162537Sdavidxu  // Try the Windows registry.
370162537Sdavidxu  bool hasSDKDir = getSystemRegistryString(
371162537Sdavidxu   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
372163451Sdavidxu    "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1);
373162537Sdavidxu    // If we have both vc80 and vc90, pick version we were compiled with.
374162537Sdavidxu  if (hasSDKDir && windowsSDKInstallDir[0]) {
375162537Sdavidxu    path = windowsSDKInstallDir;
376162552Sdavidxu    return(true);
377162552Sdavidxu  }
378162552Sdavidxu  return(false);
379162552Sdavidxu}
380205328Skib
381205328Skibvoid InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
382205328Skib  // FIXME: temporary hack: hard-coded paths.
383205328Skib  llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
384205328Skib  if (CIncludeDirs != "") {
385205328Skib    llvm::SmallVector<llvm::StringRef, 5> dirs;
386205328Skib    CIncludeDirs.split(dirs, ":");
387205328Skib    for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
388205328Skib         i != dirs.end();
389205328Skib         ++i)
390205328Skib      AddPath(*i, System, false, false, false);
391205328Skib    return;
392205328Skib  }
393205328Skib  llvm::Triple::OSType os = triple.getOS();
394205328Skib  switch (os) {
395205328Skib  case llvm::Triple::Win32:
396205328Skib    {
397205328Skib      std::string VSDir;
398205328Skib      std::string WindowsSDKDir;
399205328Skib      if (getVisualStudioDir(VSDir)) {
400205328Skib        AddPath(VSDir + "\\VC\\include", System, false, false, false);
401205328Skib        if (getWindowsSDKDir(WindowsSDKDir))
402205328Skib          AddPath(WindowsSDKDir, System, false, false, false);
403205328Skib        else
404205328Skib          AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
405253531Skib            System, false, false, false);
406253531Skib      }
407253531Skib      else {
408253531Skib          // Default install paths.
409185879Sjhb        AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
410185879Sjhb          System, false, false, false);
411185879Sjhb        AddPath(
412185879Sjhb        "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
413205014Snwhitehorn          System, false, false, false);
414171214Speter        AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include",
415171214Speter          System, false, false, false);
416171214Speter        AddPath(
417171214Speter        "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include",
418205014Snwhitehorn          System, false, false, false);
419236027Sed          // For some clang developers.
420236027Sed        AddPath("G:/Program Files/Microsoft Visual Studio 9.0/VC/include",
421171214Speter          System, false, false, false);
422171214Speter        AddPath(
423171214Speter        "G:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
424171214Speter          System, false, false, false);
425171214Speter      }
426205014Snwhitehorn    }
427236027Sed    break;
428236027Sed  case llvm::Triple::MinGW64:
429171214Speter  case llvm::Triple::MinGW32:
430171214Speter    AddPath("c:/mingw/include", System, true, false, false);
431171214Speter    break;
432171214Speter  default:
433171214Speter    break;
434171214Speter  }
435171214Speter
436205014Snwhitehorn  AddPath("/usr/local/include", System, false, false, false);
437236027Sed  AddPath("/usr/include", System, false, false, false);
438236027Sed}
439171214Speter
440171214Spetervoid InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
441171214Speter  llvm::Triple::OSType os = triple.getOS();
442205014Snwhitehorn  llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
443236027Sed  if (CxxIncludeRoot != "") {
444236027Sed    llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
445171214Speter    if (CxxIncludeArch == "")
446171214Speter      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
447171214Speter                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
448171214Speter    else
449205014Snwhitehorn      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
450236027Sed                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
451236027Sed    return;
452171214Speter  }
453171214Speter  // FIXME: temporary hack: hard-coded paths.
454171214Speter  switch (os) {
455205014Snwhitehorn  case llvm::Triple::Cygwin:
456236027Sed    AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
457236027Sed        System, true, false, false);
458171214Speter    AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
459205014Snwhitehorn        System, true, false, false);
460205014Snwhitehorn    break;
461205014Snwhitehorn  case llvm::Triple::MinGW64:
462205014Snwhitehorn    // Try gcc 4.4.0
463205014Snwhitehorn    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
464236027Sed    // Try gcc 4.3.0
465236027Sed    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
466205014Snwhitehorn    // Fall through.
467205014Snwhitehorn  case llvm::Triple::MinGW32:
468205014Snwhitehorn    // Try gcc 4.4.0
469205014Snwhitehorn    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
470205014Snwhitehorn    // Try gcc 4.3.0
471236027Sed    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
472236027Sed    break;
473205014Snwhitehorn  case llvm::Triple::Darwin:
474205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
475205014Snwhitehorn                                "i686-apple-darwin10", "", "x86_64", triple);
476205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
477205014Snwhitehorn                                "i686-apple-darwin8", "", "", triple);
478205014Snwhitehorn    break;
479205014Snwhitehorn  case llvm::Triple::Linux:
480236027Sed    // Ubuntu 7.10 - Gutsy Gibbon
481236027Sed    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
482205014Snwhitehorn                                "i486-linux-gnu", "", "", triple);
483205014Snwhitehorn    // Ubuntu 9.04
484205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
485236027Sed                                "x86_64-linux-gnu","32", "", triple);
486236027Sed    // Ubuntu 9.10
487205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
488205014Snwhitehorn                                "x86_64-linux-gnu", "32", "", triple);
489205014Snwhitehorn    // Fedora 8
490205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
491236027Sed                                "i386-redhat-linux", "", "", triple);
492236027Sed    // Fedora 9
493205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
494205014Snwhitehorn                                "i386-redhat-linux", "", "", triple);
495205014Snwhitehorn    // Fedora 10
496236027Sed    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
497236027Sed                                "i386-redhat-linux","", "", triple);
498205014Snwhitehorn
499205014Snwhitehorn    // Fedora 11
500205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
501180434Sbrooks                                "i586-redhat-linux","", "", triple);
502180434Sbrooks
503205014Snwhitehorn    // openSUSE 11.1 32 bit
504236027Sed    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
505236027Sed                                "i586-suse-linux", "", "", triple);
506180434Sbrooks    // openSUSE 11.1 64 bit
507180434Sbrooks    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
508205014Snwhitehorn                                "x86_64-suse-linux", "32", "", triple);
509205014Snwhitehorn    // openSUSE 11.2
510205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
511236027Sed                                "i586-suse-linux", "", "", triple);
512236027Sed    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
513205014Snwhitehorn                                "x86_64-suse-linux", "", "", triple);
514205014Snwhitehorn    // Arch Linux 2008-06-24
515205014Snwhitehorn    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
516180434Sbrooks                                "i686-pc-linux-gnu", "", "", triple);
517180434Sbrooks    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
518180434Sbrooks                                "x86_64-unknown-linux-gnu", "", "", triple);
519236027Sed    // Gentoo x86 2009.1 stable
520236027Sed    AddGnuCPlusPlusIncludePaths(
521180434Sbrooks      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
522180434Sbrooks      "i686-pc-linux-gnu", "", "", triple);
523180434Sbrooks    // Gentoo x86 2009.0 stable
524180434Sbrooks    AddGnuCPlusPlusIncludePaths(
525180434Sbrooks      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
526236027Sed      "i686-pc-linux-gnu", "", "", triple);
527236027Sed    // Gentoo x86 2008.0 stable
528180434Sbrooks    AddGnuCPlusPlusIncludePaths(
529180434Sbrooks      "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
530180434Sbrooks      "i686-pc-linux-gnu", "", "", triple);
531180434Sbrooks    // Ubuntu 8.10
532180434Sbrooks    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
533180434Sbrooks                                "i486-pc-linux-gnu", "", "", triple);
534236027Sed    // Ubuntu 9.04
535236027Sed    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
536180434Sbrooks                                "i486-linux-gnu","", "", triple);
537180434Sbrooks    // Gentoo amd64 stable
538180434Sbrooks    AddGnuCPlusPlusIncludePaths(
539177790Skib        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
540177790Skib        "i686-pc-linux-gnu", "", "", triple);
541236027Sed    // Exherbo (2009-10-26)
542236027Sed    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
543177790Skib                                "x86_64-pc-linux-gnu", "32", "", triple);
544177790Skib    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
545177790Skib                                "i686-pc-linux-gnu", "", "", triple);
546177790Skib    break;
547177790Skib  case llvm::Triple::FreeBSD:
548177790Skib    // DragonFly
549177790Skib    AddPath("/usr/include/c++/4.1", System, true, false, false);
550177790Skib    // FreeBSD
551177790Skib    AddPath("/usr/include/c++/4.2", System, true, false, false);
552177790Skib    break;
553177790Skib  case llvm::Triple::Solaris:
554177790Skib    // Solaris - Fall though..
555191675Sjamie  case llvm::Triple::AuroraUX:
556191675Sjamie    // AuroraUX
557191675Sjamie    AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
558191675Sjamie                                "i386-pc-solaris2.11", "", "", triple);
559191675Sjamie    break;
560191675Sjamie  default:
561191675Sjamie    break;
562191675Sjamie  }
563191675Sjamie}
564191675Sjamie
565194919Sjhbvoid InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
566194919Sjhb                                                    const llvm::Triple &triple) {
567194919Sjhb  if (Lang.CPlusPlus)
568194919Sjhb    AddDefaultCPlusPlusIncludePaths(triple);
569194919Sjhb
570194919Sjhb  AddDefaultCIncludePaths(triple);
571194919Sjhb
572194919Sjhb  // Add the default framework include paths on Darwin.
573194919Sjhb  if (triple.getOS() == llvm::Triple::Darwin) {
574194919Sjhb    AddPath("/System/Library/Frameworks", System, true, false, true);
575194919Sjhb    AddPath("/Library/Frameworks", System, true, false, true);
576194919Sjhb  }
577194919Sjhb}
578194919Sjhb
579194919Sjhb/// RemoveDuplicates - If there are duplicate directory entries in the specified
580194919Sjhb/// search list, remove the later (dead) ones.
581198512Skibstatic void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
582198512Skib                             bool Verbose) {
583198512Skib  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
584198512Skib  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
585198512Skib  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
586198512Skib  for (unsigned i = 0; i != SearchList.size(); ++i) {
587198512Skib    unsigned DirToRemove = i;
588198512Skib
589250854Skib    const DirectoryLookup &CurEntry = SearchList[i];
590220792Smdf
591220792Smdf    if (CurEntry.isNormalDir()) {
592250854Skib      // If this isn't the first time we've seen this dir, remove it.
593226365Sjhb      if (SeenDirs.insert(CurEntry.getDir()))
594226365Sjhb        continue;
595226365Sjhb    } else if (CurEntry.isFramework()) {
596226365Sjhb      // If this isn't the first time we've seen this framework dir, remove it.
597220792Smdf      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
598227071Sjhb        continue;
599227071Sjhb    } else {
600250854Skib      assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
601227071Sjhb      // If this isn't the first time we've seen this headermap, remove it.
602227071Sjhb      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
603227071Sjhb        continue;
604227071Sjhb    }
605227071Sjhb
606227071Sjhb    // If we have a normal #include dir/framework/headermap that is shadowed
607242959Skib    // later in the chain by a system include location, we actually want to
608242959Skib    // ignore the user's request and drop the user dir... keeping the system
609250854Skib    // dir.  This is weird, but required to emulate GCC's search path correctly.
610250854Skib    //
611250854Skib    // Since dupes of system dirs are rare, just rescan to find the original
612242959Skib    // that we're nuking instead of using a DenseMap.
613242959Skib    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
614242959Skib      // Find the dir that this is the same of.
615242959Skib      unsigned FirstDir;
616242959Skib      for (FirstDir = 0; ; ++FirstDir) {
617250854Skib        assert(FirstDir != i && "Didn't find dupe?");
618250854Skib
619250854Skib        const DirectoryLookup &SearchEntry = SearchList[FirstDir];
620250854Skib
621250854Skib        // If these are different lookup types, then they can't be the dupe.
622250854Skib        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
623250854Skib          continue;
624250854Skib
625250854Skib        bool isSame;
626250854Skib        if (CurEntry.isNormalDir())
627250854Skib          isSame = SearchEntry.getDir() == CurEntry.getDir();
628250854Skib        else if (CurEntry.isFramework())
629250854Skib          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
630250854Skib        else {
631250854Skib          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
632250854Skib          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
633250854Skib        }
634250854Skib
635250854Skib        if (isSame)
636250854Skib          break;
637250854Skib      }
638250854Skib
639250854Skib      // If the first dir in the search path is a non-system dir, zap it
640250854Skib      // instead of the system one.
641250854Skib      if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
642250854Skib        DirToRemove = FirstDir;
643254482Spjd    }
644254482Spjd
645254482Spjd    if (Verbose) {
646254482Spjd      fprintf(stderr, "ignoring duplicate directory \"%s\"\n",
647254482Spjd              CurEntry.getName());
648254482Spjd      if (DirToRemove != i)
649254482Spjd        fprintf(stderr, "  as it is a non-system directory that duplicates"
650254482Spjd                " a system directory\n");
651254482Spjd    }
652254482Spjd
653251527Sglebius    // This is reached if the current entry is a duplicate.  Remove the
654251527Sglebius    // DirToRemove (usually the current dir).
655251527Sglebius    SearchList.erase(SearchList.begin()+DirToRemove);
656255709Sjhb    --i;
657255709Sjhb  }
658255709Sjhb}
659255709Sjhb
660255709Sjhb
661255709Sjhbvoid InitHeaderSearch::Realize() {
662255709Sjhb  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
663255709Sjhb  std::vector<DirectoryLookup> SearchList;
664255709Sjhb  SearchList = IncludeGroup[Angled];
665255709Sjhb  SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
666255709Sjhb                    IncludeGroup[System].end());
667255709Sjhb  SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
668255709Sjhb                    IncludeGroup[After].end());
669255709Sjhb  RemoveDuplicates(SearchList, Verbose);
670255709Sjhb  RemoveDuplicates(IncludeGroup[Quoted], Verbose);
671255709Sjhb
672255709Sjhb  // Prepend QUOTED list on the search list.
673255709Sjhb  SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
674274463Sdchagin                    IncludeGroup[Quoted].end());
675274463Sdchagin
676274463Sdchagin
677274463Sdchagin  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
678274463Sdchagin  Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
679274463Sdchagin                         DontSearchCurDir);
680277611Sjilles
681277611Sjilles  // If verbose, print the list of directories that will be searched.
682277611Sjilles  if (Verbose) {
683277611Sjilles    fprintf(stderr, "#include \"...\" search starts here:\n");
684277611Sjilles    unsigned QuotedIdx = IncludeGroup[Quoted].size();
685277611Sjilles    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
686277611Sjilles      if (i == QuotedIdx)
687277611Sjilles        fprintf(stderr, "#include <...> search starts here:\n");
688277611Sjilles      const char *Name = SearchList[i].getName();
689277611Sjilles      const char *Suffix;
690232449Sjmallett      if (SearchList[i].isNormalDir())
691205014Snwhitehorn        Suffix = "";
692205014Snwhitehorn      else if (SearchList[i].isFramework())
693119332Speter        Suffix = " (framework directory)";
694151360Sps      else {
695151360Sps        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
696151360Sps        Suffix = " (headermap)";
697119332Speter      }
698183271Sobrien      fprintf(stderr, " %s%s\n", Name, Suffix);
699119332Speter    }
700226349Smarcel    fprintf(stderr, "End of search list.\n");
701119332Speter  }
702125171Speter}
703270692Skib
704119332Spetervoid clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
705119332Speter                                     const HeaderSearchOptions &HSOpts,
706119332Speter                                     const LangOptions &Lang,
707119332Speter                                     const llvm::Triple &Triple) {
708119332Speter  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
709119332Speter
710119332Speter  // Add the user defined entries.
711119332Speter  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
712190622Skib    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
713119332Speter    Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
714119332Speter                 false);
715119332Speter  }
716119332Speter
717119332Speter  // Add entries from CPATH and friends.
718119332Speter  Init.AddDelimitedPaths(HSOpts.EnvIncPath.c_str());
719184184Sjhb  if (Lang.CPlusPlus && Lang.ObjC1)
720119332Speter    Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath.c_str());
721154596Sambrisko  else if (Lang.CPlusPlus)
722165406Sjkim    Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath.c_str());
723165406Sjkim  else if (Lang.ObjC1)
724151358Sps    Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath.c_str());
725151358Sps  else
726151358Sps    Init.AddDelimitedPaths(HSOpts.CEnvIncPath.c_str());
727253531Skib
728253531Skib  if (!HSOpts.BuiltinIncludePath.empty()) {
729253531Skib    // Ignore the sys root, we *always* look for clang headers relative to
730140481Sps    // supplied path.
731253495Skib    Init.AddPath(HSOpts.BuiltinIncludePath, System,
732185879Sjhb                 false, false, false, /*IgnoreSysRoot=*/ true);
733185879Sjhb  }
734185879Sjhb
735154587Sambrisko  if (HSOpts.UseStandardIncludes)
736147814Sjhb    Init.AddDefaultSystemIncludePaths(Lang, Triple);
737147814Sjhb
738140482Sps  Init.Realize();
739220159Skib}
740185879Sjhb