InitHeaderSearch.cpp revision 125b4cb35536e45201f8f2cb19ee620e3ad67c49
1//===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the InitHeaderSearch class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifdef HAVE_CLANG_CONFIG_H
15# include "clang/Config/config.h"
16#endif
17
18#include "clang/Frontend/Utils.h"
19#include "clang/Basic/FileManager.h"
20#include "clang/Basic/LangOptions.h"
21#include "clang/Frontend/HeaderSearchOptions.h"
22#include "clang/Lex/HeaderSearch.h"
23#include "llvm/ADT/SmallString.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/StringExtras.h"
27#include "llvm/ADT/Triple.h"
28#include "llvm/ADT/Twine.h"
29#include "llvm/Support/raw_ostream.h"
30#include "llvm/Support/Path.h"
31#include "llvm/Config/config.h"
32#ifdef _MSC_VER
33  #define WIN32_LEAN_AND_MEAN 1
34  #include <windows.h>
35#endif
36using namespace clang;
37using namespace clang::frontend;
38
39namespace {
40
41/// InitHeaderSearch - This class makes it easier to set the search paths of
42///  a HeaderSearch object. InitHeaderSearch stores several search path lists
43///  internally, which can be sent to a HeaderSearch object in one swoop.
44class InitHeaderSearch {
45  std::vector<DirectoryLookup> IncludeGroup[4];
46  HeaderSearch& Headers;
47  bool Verbose;
48  std::string IncludeSysroot;
49  bool IsNotEmptyOrRoot;
50
51public:
52
53  InitHeaderSearch(HeaderSearch &HS, bool verbose, llvm::StringRef sysroot)
54    : Headers(HS), Verbose(verbose), IncludeSysroot(sysroot),
55      IsNotEmptyOrRoot(!(sysroot.empty() || sysroot == "/")) {
56  }
57
58  /// AddPath - Add the specified path to the specified group list.
59  void AddPath(const llvm::Twine &Path, IncludeDirGroup Group,
60               bool isCXXAware, bool isUserSupplied,
61               bool isFramework, bool IgnoreSysRoot = false);
62
63  /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
64  ///  libstdc++.
65  void AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
66                                   llvm::StringRef ArchDir,
67                                   llvm::StringRef Dir32,
68                                   llvm::StringRef Dir64,
69                                   const llvm::Triple &triple);
70
71  /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW
72  ///  libstdc++.
73  void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
74                                     llvm::StringRef Arch,
75                                     llvm::StringRef Version);
76
77  /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
78  /// separator. The processing follows that of the CPATH variable for gcc.
79  void AddDelimitedPaths(llvm::StringRef String);
80
81  // AddDefaultCIncludePaths - Add paths that should always be searched.
82  void AddDefaultCIncludePaths(const llvm::Triple &triple,
83                               const HeaderSearchOptions &HSOpts);
84
85  // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
86  //  compiling c++.
87  void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
88
89  /// AddDefaultSystemIncludePaths - Adds the default system include paths so
90  ///  that e.g. stdio.h is found.
91  void AddDefaultSystemIncludePaths(const LangOptions &Lang,
92                                    const llvm::Triple &triple,
93                                    const HeaderSearchOptions &HSOpts);
94
95  /// Realize - Merges all search path lists into one list and send it to
96  /// HeaderSearch.
97  void Realize();
98};
99
100}
101
102void InitHeaderSearch::AddPath(const llvm::Twine &Path,
103                               IncludeDirGroup Group, bool isCXXAware,
104                               bool isUserSupplied, bool isFramework,
105                               bool IgnoreSysRoot) {
106  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
107  FileManager &FM = Headers.getFileMgr();
108
109  // Compute the actual path, taking into consideration -isysroot.
110  llvm::SmallString<256> MappedPathStorage;
111  llvm::StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
112
113  // Handle isysroot.
114  if (Group == System && !IgnoreSysRoot &&
115      llvm::sys::path::is_absolute(MappedPathStr) &&
116      IsNotEmptyOrRoot) {
117    MappedPathStorage.clear();
118    MappedPathStr =
119      (IncludeSysroot + Path).toStringRef(MappedPathStorage);
120  }
121
122  // Compute the DirectoryLookup type.
123  SrcMgr::CharacteristicKind Type;
124  if (Group == Quoted || Group == Angled)
125    Type = SrcMgr::C_User;
126  else if (isCXXAware)
127    Type = SrcMgr::C_System;
128  else
129    Type = SrcMgr::C_ExternCSystem;
130
131
132  // If the directory exists, add it.
133  if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
134    IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
135                                                  isFramework));
136    return;
137  }
138
139  // Check to see if this is an apple-style headermap (which are not allowed to
140  // be frameworks).
141  if (!isFramework) {
142    if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
143      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
144        // It is a headermap, add it to the search path.
145        IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
146        return;
147      }
148    }
149  }
150
151  if (Verbose)
152    llvm::errs() << "ignoring nonexistent directory \""
153                 << MappedPathStr << "\"\n";
154}
155
156
157void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) {
158  if (at.empty()) // Empty string should not add '.' path.
159    return;
160
161  llvm::StringRef::size_type delim;
162  while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) {
163    if (delim == 0)
164      AddPath(".", Angled, false, true, false);
165    else
166      AddPath(at.substr(0, delim), Angled, false, true, false);
167    at = at.substr(delim + 1);
168  }
169
170  if (at.empty())
171    AddPath(".", Angled, false, true, false);
172  else
173    AddPath(at, Angled, false, true, false);
174}
175
176void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
177                                                   llvm::StringRef ArchDir,
178                                                   llvm::StringRef Dir32,
179                                                   llvm::StringRef Dir64,
180                                                   const llvm::Triple &triple) {
181  // Add the base dir
182  AddPath(Base, System, true, false, false);
183
184  // Add the multilib dirs
185  llvm::Triple::ArchType arch = triple.getArch();
186  bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
187  if (is64bit)
188    AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
189  else
190    AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
191
192  // Add the backward dir
193  AddPath(Base + "/backward", System, true, false, false);
194}
195
196void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
197                                                     llvm::StringRef Arch,
198                                                     llvm::StringRef Version) {
199  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
200          System, true, false, false);
201  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
202          System, true, false, false);
203  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
204          System, true, false, false);
205}
206
207  // FIXME: This probably should goto to some platform utils place.
208#ifdef _MSC_VER
209
210  // Read registry string.
211  // This also supports a means to look for high-versioned keys by use
212  // of a $VERSION placeholder in the key path.
213  // $VERSION in the key path is a placeholder for the version number,
214  // causing the highest value path to be searched for and used.
215  // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
216  // There can be additional characters in the component.  Only the numberic
217  // characters are compared.
218static bool getSystemRegistryString(const char *keyPath, const char *valueName,
219                                    char *value, size_t maxLength) {
220  HKEY hRootKey = NULL;
221  HKEY hKey = NULL;
222  const char* subKey = NULL;
223  DWORD valueType;
224  DWORD valueSize = maxLength - 1;
225  long lResult;
226  bool returnValue = false;
227  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
228    hRootKey = HKEY_CLASSES_ROOT;
229    subKey = keyPath + 18;
230  }
231  else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
232    hRootKey = HKEY_USERS;
233    subKey = keyPath + 11;
234  }
235  else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
236    hRootKey = HKEY_LOCAL_MACHINE;
237    subKey = keyPath + 19;
238  }
239  else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
240    hRootKey = HKEY_CURRENT_USER;
241    subKey = keyPath + 18;
242  }
243  else
244    return(false);
245  const char *placeHolder = strstr(subKey, "$VERSION");
246  char bestName[256];
247  bestName[0] = '\0';
248  // If we have a $VERSION placeholder, do the highest-version search.
249  if (placeHolder) {
250    const char *keyEnd = placeHolder - 1;
251    const char *nextKey = placeHolder;
252    // Find end of previous key.
253    while ((keyEnd > subKey) && (*keyEnd != '\\'))
254      keyEnd--;
255    // Find end of key containing $VERSION.
256    while (*nextKey && (*nextKey != '\\'))
257      nextKey++;
258    size_t partialKeyLength = keyEnd - subKey;
259    char partialKey[256];
260    if (partialKeyLength > sizeof(partialKey))
261      partialKeyLength = sizeof(partialKey);
262    strncpy(partialKey, subKey, partialKeyLength);
263    partialKey[partialKeyLength] = '\0';
264    HKEY hTopKey = NULL;
265    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
266    if (lResult == ERROR_SUCCESS) {
267      char keyName[256];
268      int bestIndex = -1;
269      double bestValue = 0.0;
270      DWORD index, size = sizeof(keyName) - 1;
271      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
272          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
273        const char *sp = keyName;
274        while (*sp && !isdigit(*sp))
275          sp++;
276        if (!*sp)
277          continue;
278        const char *ep = sp + 1;
279        while (*ep && (isdigit(*ep) || (*ep == '.')))
280          ep++;
281        char numBuf[32];
282        strncpy(numBuf, sp, sizeof(numBuf) - 1);
283        numBuf[sizeof(numBuf) - 1] = '\0';
284        double value = strtod(numBuf, NULL);
285        if (value > bestValue) {
286          bestIndex = (int)index;
287          bestValue = value;
288          strcpy(bestName, keyName);
289        }
290        size = sizeof(keyName) - 1;
291      }
292      // If we found the highest versioned key, open the key and get the value.
293      if (bestIndex != -1) {
294        // Append rest of key.
295        strncat(bestName, nextKey, sizeof(bestName) - 1);
296        bestName[sizeof(bestName) - 1] = '\0';
297        // Open the chosen key path remainder.
298        lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
299        if (lResult == ERROR_SUCCESS) {
300          lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
301            (LPBYTE)value, &valueSize);
302          if (lResult == ERROR_SUCCESS)
303            returnValue = true;
304          RegCloseKey(hKey);
305        }
306      }
307      RegCloseKey(hTopKey);
308    }
309  }
310  else {
311    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
312    if (lResult == ERROR_SUCCESS) {
313      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
314        (LPBYTE)value, &valueSize);
315      if (lResult == ERROR_SUCCESS)
316        returnValue = true;
317      RegCloseKey(hKey);
318    }
319  }
320  return(returnValue);
321}
322#else // _MSC_VER
323  // Read registry string.
324static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
325  return(false);
326}
327#endif // _MSC_VER
328
329  // Get Visual Studio installation directory.
330static bool getVisualStudioDir(std::string &path) {
331  // First check the environment variables that vsvars32.bat sets.
332  const char* vcinstalldir = getenv("VCINSTALLDIR");
333  if(vcinstalldir) {
334    char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
335    if (p)
336      *p = '\0';
337    path = vcinstalldir;
338    return(true);
339  }
340
341  char vsIDEInstallDir[256];
342  char vsExpressIDEInstallDir[256];
343  // Then try the windows registry.
344  bool hasVCDir = getSystemRegistryString(
345    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
346    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
347  bool hasVCExpressDir = getSystemRegistryString(
348    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
349    "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
350    // If we have both vc80 and vc90, pick version we were compiled with.
351  if (hasVCDir && vsIDEInstallDir[0]) {
352    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
353    if (p)
354      *p = '\0';
355    path = vsIDEInstallDir;
356    return(true);
357  }
358  else if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
359    char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
360    if (p)
361      *p = '\0';
362    path = vsExpressIDEInstallDir;
363    return(true);
364  }
365  else {
366    // Try the environment.
367    const char* vs100comntools = getenv("VS100COMNTOOLS");
368    const char* vs90comntools = getenv("VS90COMNTOOLS");
369    const char* vs80comntools = getenv("VS80COMNTOOLS");
370    const char* vscomntools = NULL;
371
372    // Try to find the version that we were compiled with
373    if(false) {}
374    #if (_MSC_VER >= 1600)  // VC100
375    else if(vs100comntools) {
376      vscomntools = vs100comntools;
377    }
378    #elif (_MSC_VER == 1500) // VC80
379    else if(vs90comntools) {
380      vscomntools = vs90comntools;
381    }
382    #elif (_MSC_VER == 1400) // VC80
383    else if(vs80comntools) {
384      vscomntools = vs80comntools;
385    }
386    #endif
387    // Otherwise find any version we can
388    else if (vs100comntools)
389      vscomntools = vs100comntools;
390    else if (vs90comntools)
391      vscomntools = vs90comntools;
392    else if (vs80comntools)
393      vscomntools = vs80comntools;
394
395    if (vscomntools && *vscomntools) {
396      char *p = const_cast<char *>(strstr(vscomntools, "\\Common7\\Tools"));
397      if (p)
398        *p = '\0';
399      path = vscomntools;
400      return(true);
401    }
402    else
403      return(false);
404  }
405  return(false);
406}
407
408  // Get Windows SDK installation directory.
409static bool getWindowsSDKDir(std::string &path) {
410  char windowsSDKInstallDir[256];
411  // Try the Windows registry.
412  bool hasSDKDir = getSystemRegistryString(
413   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
414    "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1);
415    // If we have both vc80 and vc90, pick version we were compiled with.
416  if (hasSDKDir && windowsSDKInstallDir[0]) {
417    path = windowsSDKInstallDir;
418    return(true);
419  }
420  return(false);
421}
422
423void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
424                                            const HeaderSearchOptions &HSOpts) {
425  llvm::Triple::OSType os = triple.getOS();
426
427  switch (os) {
428  case llvm::Triple::NetBSD:
429    break;
430  default:
431    // FIXME: temporary hack: hard-coded paths.
432    AddPath("/usr/local/include", System, true, false, false);
433    break;
434  }
435
436  // Builtin includes use #include_next directives and should be positioned
437  // just prior C include dirs.
438  if (HSOpts.UseBuiltinIncludes) {
439    // Ignore the sys root, we *always* look for clang headers relative to
440    // supplied path.
441    llvm::sys::Path P(HSOpts.ResourceDir);
442    P.appendComponent("include");
443    AddPath(P.str(), System, false, false, false, /*IgnoreSysRoot=*/ true);
444  }
445
446  // Add dirs specified via 'configure --with-c-include-dirs'.
447  llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
448  if (CIncludeDirs != "") {
449    llvm::SmallVector<llvm::StringRef, 5> dirs;
450    CIncludeDirs.split(dirs, ":");
451    for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
452         i != dirs.end();
453         ++i)
454      AddPath(*i, System, false, false, false);
455    return;
456  }
457
458  switch (os) {
459  case llvm::Triple::Win32: {
460    std::string VSDir;
461    std::string WindowsSDKDir;
462    if (getVisualStudioDir(VSDir)) {
463      AddPath(VSDir + "\\VC\\include", System, false, false, false);
464      if (getWindowsSDKDir(WindowsSDKDir))
465        AddPath(WindowsSDKDir + "\\include", System, false, false, false);
466      else
467        AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
468                System, false, false, false);
469    } else {
470      // Default install paths.
471      AddPath("C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
472              System, false, false, false);
473      AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
474              System, false, false, false);
475      AddPath(
476        "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
477        System, false, false, false);
478      AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include",
479              System, false, false, false);
480      AddPath(
481        "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include",
482        System, false, false, false);
483    }
484    break;
485  }
486  case llvm::Triple::Haiku:
487    AddPath("/boot/common/include", System, true, false, false);
488    AddPath("/boot/develop/headers/os", System, true, false, false);
489    AddPath("/boot/develop/headers/os/app", System, true, false, false);
490    AddPath("/boot/develop/headers/os/arch", System, true, false, false);
491    AddPath("/boot/develop/headers/os/device", System, true, false, false);
492    AddPath("/boot/develop/headers/os/drivers", System, true, false, false);
493    AddPath("/boot/develop/headers/os/game", System, true, false, false);
494    AddPath("/boot/develop/headers/os/interface", System, true, false, false);
495    AddPath("/boot/develop/headers/os/kernel", System, true, false, false);
496    AddPath("/boot/develop/headers/os/locale", System, true, false, false);
497    AddPath("/boot/develop/headers/os/mail", System, true, false, false);
498    AddPath("/boot/develop/headers/os/media", System, true, false, false);
499    AddPath("/boot/develop/headers/os/midi", System, true, false, false);
500    AddPath("/boot/develop/headers/os/midi2", System, true, false, false);
501    AddPath("/boot/develop/headers/os/net", System, true, false, false);
502    AddPath("/boot/develop/headers/os/storage", System, true, false, false);
503    AddPath("/boot/develop/headers/os/support", System, true, false, false);
504    AddPath("/boot/develop/headers/os/translation",
505      System, true, false, false);
506    AddPath("/boot/develop/headers/os/add-ons/graphics",
507      System, true, false, false);
508    AddPath("/boot/develop/headers/os/add-ons/input_server",
509      System, true, false, false);
510    AddPath("/boot/develop/headers/os/add-ons/screen_saver",
511      System, true, false, false);
512    AddPath("/boot/develop/headers/os/add-ons/tracker",
513      System, true, false, false);
514    AddPath("/boot/develop/headers/os/be_apps/Deskbar",
515      System, true, false, false);
516    AddPath("/boot/develop/headers/os/be_apps/NetPositive",
517      System, true, false, false);
518    AddPath("/boot/develop/headers/os/be_apps/Tracker",
519      System, true, false, false);
520    AddPath("/boot/develop/headers/cpp", System, true, false, false);
521    AddPath("/boot/develop/headers/cpp/i586-pc-haiku",
522      System, true, false, false);
523    AddPath("/boot/develop/headers/3rdparty", System, true, false, false);
524    AddPath("/boot/develop/headers/bsd", System, true, false, false);
525    AddPath("/boot/develop/headers/glibc", System, true, false, false);
526    AddPath("/boot/develop/headers/posix", System, true, false, false);
527    AddPath("/boot/develop/headers",  System, true, false, false);
528    break;
529  case llvm::Triple::Cygwin:
530    AddPath("/usr/include/w32api", System, true, false, false);
531    break;
532  case llvm::Triple::MinGW64:
533  case llvm::Triple::MinGW32:
534    AddPath("c:/mingw/include", System, true, false, false);
535    break;
536  default:
537    break;
538  }
539
540  AddPath("/usr/include", System, false, false, false);
541}
542
543void InitHeaderSearch::
544AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
545  llvm::Triple::OSType os = triple.getOS();
546  llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
547  if (CxxIncludeRoot != "") {
548    llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
549    if (CxxIncludeArch == "")
550      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
551                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
552                                  triple);
553    else
554      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
555                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
556                                  triple);
557    return;
558  }
559  // FIXME: temporary hack: hard-coded paths.
560  switch (os) {
561  case llvm::Triple::Cygwin:
562    // Cygwin-1.7
563    AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
564    // g++-4 / Cygwin-1.5
565    AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
566    // FIXME: Do we support g++-3.4.4?
567    AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4");
568    break;
569  case llvm::Triple::MinGW64:
570    // Try gcc 4.5.0
571    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.5.0");
572    // Try gcc 4.4.0
573    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
574    // Try gcc 4.3.0
575    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
576    // Fall through.
577  case llvm::Triple::MinGW32:
578    // Try gcc 4.5.0
579    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
580    // Try gcc 4.4.0
581    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
582    // Try gcc 4.3.0
583    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
584    break;
585  case llvm::Triple::Darwin:
586    switch (triple.getArch()) {
587    default: break;
588
589    case llvm::Triple::ppc:
590    case llvm::Triple::ppc64:
591      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
592                                  "powerpc-apple-darwin10", "", "ppc64",
593                                  triple);
594      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
595                                  "powerpc-apple-darwin10", "", "ppc64",
596                                  triple);
597      break;
598
599    case llvm::Triple::x86:
600    case llvm::Triple::x86_64:
601      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
602                                  "i686-apple-darwin10", "", "x86_64", triple);
603      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
604                                  "i686-apple-darwin8", "", "", triple);
605      break;
606
607    case llvm::Triple::arm:
608    case llvm::Triple::thumb:
609      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
610                                  "arm-apple-darwin10", "v7", "", triple);
611      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
612                                  "arm-apple-darwin10", "v6", "", triple);
613      break;
614    }
615    break;
616  case llvm::Triple::DragonFly:
617    AddPath("/usr/include/c++/4.1", System, true, false, false);
618    break;
619  case llvm::Triple::Linux:
620    //===------------------------------------------------------------------===//
621    // Debian based distros.
622    // Note: these distros symlink /usr/include/c++/X.Y.Z -> X.Y
623    //===------------------------------------------------------------------===//
624    // Ubuntu 10.10 "Maverick Meerkat" -- gcc-4.4.5
625    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
626                                "i686-linux-gnu", "", "64", triple);
627    // The rest of 10.10 is the same as previous versions.
628
629    // Ubuntu 10.04 LTS "Lucid Lynx" -- gcc-4.4.3
630    // Ubuntu 9.10 "Karmic Koala"    -- gcc-4.4.1
631    // Debian 6.0 "squeeze"          -- gcc-4.4.2
632    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
633                                "x86_64-linux-gnu", "32", "", triple);
634    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
635                                "i486-linux-gnu", "", "64", triple);
636    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
637                                "arm-linux-gnueabi", "", "", triple);
638    // Ubuntu 9.04 "Jaunty Jackalope" -- gcc-4.3.3
639    // Ubuntu 8.10 "Intrepid Ibex"    -- gcc-4.3.2
640    // Debian 5.0 "lenny"             -- gcc-4.3.2
641    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
642                                "x86_64-linux-gnu", "32", "", triple);
643    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
644                                "i486-linux-gnu", "", "64", triple);
645    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
646                                "arm-linux-gnueabi", "", "", triple);
647    // Ubuntu 8.04.4 LTS "Hardy Heron"     -- gcc-4.2.4
648    // Ubuntu 8.04.[0-3] LTS "Hardy Heron" -- gcc-4.2.3
649    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2",
650                                "x86_64-linux-gnu", "32", "", triple);
651    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2",
652                                "i486-linux-gnu", "", "64", triple);
653    // Ubuntu 7.10 "Gutsy Gibbon" -- gcc-4.1.3
654    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1",
655                                "x86_64-linux-gnu", "32", "", triple);
656    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1",
657                                "i486-linux-gnu", "", "64", triple);
658
659    //===------------------------------------------------------------------===//
660    // Redhat based distros.
661    //===------------------------------------------------------------------===//
662    // Fedora 14
663    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1",
664                                "x86_64-redhat-linux", "32", "", triple);
665    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1",
666                                "i686-redhat-linux", "", "", triple);
667    // Fedora 13
668    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
669                                "x86_64-redhat-linux", "32", "", triple);
670    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
671                                "i686-redhat-linux","", "", triple);
672    // Fedora 12
673    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
674                                "x86_64-redhat-linux", "32", "", triple);
675    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
676                                "i686-redhat-linux","", "", triple);
677    // Fedora 12 (pre-FEB-2010)
678    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
679                                "x86_64-redhat-linux", "32", "", triple);
680    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
681                                "i686-redhat-linux","", "", triple);
682    // Fedora 11
683    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
684                                "x86_64-redhat-linux", "32", "", triple);
685    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
686                                "i586-redhat-linux","", "", triple);
687    // Fedora 10
688    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
689                                "x86_64-redhat-linux", "32", "", triple);
690    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
691                                "i386-redhat-linux","", "", triple);
692    // Fedora 9
693    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
694                                "x86_64-redhat-linux", "32", "", triple);
695    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
696                                "i386-redhat-linux", "", "", triple);
697    // Fedora 8
698    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
699                                "x86_64-redhat-linux", "", "", triple);
700    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
701                                "i386-redhat-linux", "", "", triple);
702
703    //===------------------------------------------------------------------===//
704
705    // Exherbo (2010-01-25)
706    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
707                                "x86_64-pc-linux-gnu", "32", "", triple);
708    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
709                                "i686-pc-linux-gnu", "", "", triple);
710
711    // openSUSE 11.1 32 bit
712    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
713                                "i586-suse-linux", "", "", triple);
714    // openSUSE 11.1 64 bit
715    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
716                                "x86_64-suse-linux", "32", "", triple);
717    // openSUSE 11.2
718    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
719                                "i586-suse-linux", "", "", triple);
720    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
721                                "x86_64-suse-linux", "", "", triple);
722
723    // openSUSE 11.4
724    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
725                                "i586-suse-linux", "", "", triple);
726    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
727                                "x86_64-suse-linux", "", "", triple);
728
729    // Arch Linux 2008-06-24
730    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
731                                "i686-pc-linux-gnu", "", "", triple);
732    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
733                                "x86_64-unknown-linux-gnu", "", "", triple);
734    // Gentoo x86 2010.0 stable
735    AddGnuCPlusPlusIncludePaths(
736      "/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/include/g++-v4",
737      "i686-pc-linux-gnu", "", "", triple);
738    // Gentoo x86 2009.1 stable
739    AddGnuCPlusPlusIncludePaths(
740      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
741      "i686-pc-linux-gnu", "", "", triple);
742    // Gentoo x86 2009.0 stable
743    AddGnuCPlusPlusIncludePaths(
744      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
745      "i686-pc-linux-gnu", "", "", triple);
746    // Gentoo x86 2008.0 stable
747    AddGnuCPlusPlusIncludePaths(
748      "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
749      "i686-pc-linux-gnu", "", "", triple);
750
751    // Gentoo amd64 gcc 4.4.5
752    AddGnuCPlusPlusIncludePaths(
753        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4",
754        "x86_64-pc-linux-gnu", "32", "", triple);
755    // Gentoo amd64 gcc 4.4.4
756    AddGnuCPlusPlusIncludePaths(
757        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4",
758        "x86_64-pc-linux-gnu", "32", "", triple);
759    // Gentoo amd64 gcc 4.4.3
760    AddGnuCPlusPlusIncludePaths(
761        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4",
762        "x86_64-pc-linux-gnu", "32", "", triple);
763    // Gentoo amd64 gcc 4.3.2
764    AddGnuCPlusPlusIncludePaths(
765        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4",
766        "x86_64-pc-linux-gnu", "", "", triple);
767    // Gentoo amd64 stable
768    AddGnuCPlusPlusIncludePaths(
769        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
770        "i686-pc-linux-gnu", "", "", triple);
771
772    // Gentoo amd64 llvm-gcc trunk
773    AddGnuCPlusPlusIncludePaths(
774        "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1",
775        "x86_64-pc-linux-gnu", "", "", triple);
776
777    break;
778  case llvm::Triple::FreeBSD:
779    // FreeBSD 8.0
780    // FreeBSD 7.3
781    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
782    break;
783  case llvm::Triple::NetBSD:
784    AddGnuCPlusPlusIncludePaths("/usr/include/g++", "", "", "", triple);
785    break;
786  case llvm::Triple::OpenBSD: {
787    std::string t = triple.getTriple();
788    if (t.substr(0, 6) == "x86_64")
789      t.replace(0, 6, "amd64");
790    AddGnuCPlusPlusIncludePaths("/usr/include/g++",
791                                t, "", "", triple);
792    break;
793  }
794  case llvm::Triple::Minix:
795    AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
796                                "", "", "", triple);
797    break;
798  case llvm::Triple::Solaris:
799    // Solaris - Fall though..
800  case llvm::Triple::AuroraUX:
801    // AuroraUX
802    AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
803                                "i386-pc-solaris2.11", "", "", triple);
804    break;
805  default:
806    break;
807  }
808}
809
810void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
811                                                    const llvm::Triple &triple,
812                                            const HeaderSearchOptions &HSOpts) {
813  if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) {
814    if (!HSOpts.CXXSystemIncludes.empty()) {
815      for (unsigned i = 0, e = HSOpts.CXXSystemIncludes.size(); i != e; ++i)
816        AddPath(HSOpts.CXXSystemIncludes[i], System, true, false, false);
817    } else
818      AddDefaultCPlusPlusIncludePaths(triple);
819  }
820
821  AddDefaultCIncludePaths(triple, HSOpts);
822
823  // Add the default framework include paths on Darwin.
824  if (triple.getOS() == llvm::Triple::Darwin) {
825    AddPath("/System/Library/Frameworks", System, true, false, true);
826    AddPath("/Library/Frameworks", System, true, false, true);
827  }
828}
829
830/// RemoveDuplicates - If there are duplicate directory entries in the specified
831/// search list, remove the later (dead) ones.
832static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
833                             bool Verbose) {
834  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
835  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
836  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
837  for (unsigned i = 0; i != SearchList.size(); ++i) {
838    unsigned DirToRemove = i;
839
840    const DirectoryLookup &CurEntry = SearchList[i];
841
842    if (CurEntry.isNormalDir()) {
843      // If this isn't the first time we've seen this dir, remove it.
844      if (SeenDirs.insert(CurEntry.getDir()))
845        continue;
846    } else if (CurEntry.isFramework()) {
847      // If this isn't the first time we've seen this framework dir, remove it.
848      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
849        continue;
850    } else {
851      assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
852      // If this isn't the first time we've seen this headermap, remove it.
853      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
854        continue;
855    }
856
857    // If we have a normal #include dir/framework/headermap that is shadowed
858    // later in the chain by a system include location, we actually want to
859    // ignore the user's request and drop the user dir... keeping the system
860    // dir.  This is weird, but required to emulate GCC's search path correctly.
861    //
862    // Since dupes of system dirs are rare, just rescan to find the original
863    // that we're nuking instead of using a DenseMap.
864    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
865      // Find the dir that this is the same of.
866      unsigned FirstDir;
867      for (FirstDir = 0; ; ++FirstDir) {
868        assert(FirstDir != i && "Didn't find dupe?");
869
870        const DirectoryLookup &SearchEntry = SearchList[FirstDir];
871
872        // If these are different lookup types, then they can't be the dupe.
873        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
874          continue;
875
876        bool isSame;
877        if (CurEntry.isNormalDir())
878          isSame = SearchEntry.getDir() == CurEntry.getDir();
879        else if (CurEntry.isFramework())
880          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
881        else {
882          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
883          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
884        }
885
886        if (isSame)
887          break;
888      }
889
890      // If the first dir in the search path is a non-system dir, zap it
891      // instead of the system one.
892      if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
893        DirToRemove = FirstDir;
894    }
895
896    if (Verbose) {
897      llvm::errs() << "ignoring duplicate directory \""
898                   << CurEntry.getName() << "\"\n";
899      if (DirToRemove != i)
900        llvm::errs() << "  as it is a non-system directory that duplicates "
901                     << "a system directory\n";
902    }
903
904    // This is reached if the current entry is a duplicate.  Remove the
905    // DirToRemove (usually the current dir).
906    SearchList.erase(SearchList.begin()+DirToRemove);
907    --i;
908  }
909}
910
911
912void InitHeaderSearch::Realize() {
913  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
914  std::vector<DirectoryLookup> SearchList;
915  SearchList = IncludeGroup[Angled];
916  SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
917                    IncludeGroup[System].end());
918  SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
919                    IncludeGroup[After].end());
920  RemoveDuplicates(SearchList, Verbose);
921  RemoveDuplicates(IncludeGroup[Quoted], Verbose);
922
923  // Prepend QUOTED list on the search list.
924  SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
925                    IncludeGroup[Quoted].end());
926
927
928  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
929  Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
930                         DontSearchCurDir);
931
932  // If verbose, print the list of directories that will be searched.
933  if (Verbose) {
934    llvm::errs() << "#include \"...\" search starts here:\n";
935    unsigned QuotedIdx = IncludeGroup[Quoted].size();
936    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
937      if (i == QuotedIdx)
938        llvm::errs() << "#include <...> search starts here:\n";
939      const char *Name = SearchList[i].getName();
940      const char *Suffix;
941      if (SearchList[i].isNormalDir())
942        Suffix = "";
943      else if (SearchList[i].isFramework())
944        Suffix = " (framework directory)";
945      else {
946        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
947        Suffix = " (headermap)";
948      }
949      llvm::errs() << " " << Name << Suffix << "\n";
950    }
951    llvm::errs() << "End of search list.\n";
952  }
953}
954
955void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
956                                     const HeaderSearchOptions &HSOpts,
957                                     const LangOptions &Lang,
958                                     const llvm::Triple &Triple) {
959  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
960
961  // Add the user defined entries.
962  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
963    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
964    Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
965                 !E.IsSysRootRelative);
966  }
967
968  // Add entries from CPATH and friends.
969  Init.AddDelimitedPaths(HSOpts.EnvIncPath);
970  if (Lang.CPlusPlus && Lang.ObjC1)
971    Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
972  else if (Lang.CPlusPlus)
973    Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
974  else if (Lang.ObjC1)
975    Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
976  else
977    Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
978
979  if (HSOpts.UseStandardIncludes)
980    Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts);
981
982  Init.Realize();
983}
984