InitHeaderSearch.cpp revision 455fe3c9dc1cd5457e3e99c2381199f6aa748dee
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#include "clang/Frontend/Utils.h"
15#include "clang/Basic/FileManager.h"
16#include "clang/Basic/LangOptions.h"
17#include "clang/Frontend/HeaderSearchOptions.h"
18#include "clang/Lex/HeaderSearch.h"
19#include "llvm/ADT/SmallString.h"
20#include "llvm/ADT/SmallPtrSet.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/ADT/Triple.h"
24#include "llvm/ADT/Twine.h"
25#include "llvm/Support/raw_ostream.h"
26#include "llvm/System/Path.h"
27#include "llvm/Config/config.h"
28#ifdef _MSC_VER
29  #define WIN32_LEAN_AND_MEAN 1
30  #include <windows.h>
31#endif
32using namespace clang;
33using namespace clang::frontend;
34
35namespace {
36
37/// InitHeaderSearch - This class makes it easier to set the search paths of
38///  a HeaderSearch object. InitHeaderSearch stores several search path lists
39///  internally, which can be sent to a HeaderSearch object in one swoop.
40class InitHeaderSearch {
41  std::vector<DirectoryLookup> IncludeGroup[4];
42  HeaderSearch& Headers;
43  bool Verbose;
44  std::string isysroot;
45
46public:
47
48  InitHeaderSearch(HeaderSearch &HS,
49      bool verbose = false, const std::string &iSysroot = "")
50    : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
51
52  /// AddPath - Add the specified path to the specified group list.
53  void AddPath(const llvm::Twine &Path, IncludeDirGroup Group,
54               bool isCXXAware, bool isUserSupplied,
55               bool isFramework, bool IgnoreSysRoot = false);
56
57  /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu
58  ///  libstdc++.
59  void AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
60                                   llvm::StringRef ArchDir,
61                                   llvm::StringRef Dir32,
62                                   llvm::StringRef Dir64,
63                                   const llvm::Triple &triple);
64
65  /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW
66  ///  libstdc++.
67  void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
68                                     llvm::StringRef Arch,
69                                     llvm::StringRef Version);
70
71  /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
72  /// separator. The processing follows that of the CPATH variable for gcc.
73  void AddDelimitedPaths(llvm::StringRef String);
74
75  // AddDefaultCIncludePaths - Add paths that should always be searched.
76  void AddDefaultCIncludePaths(const llvm::Triple &triple);
77
78  // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
79  //  compiling c++.
80  void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
81
82  /// AddDefaultSystemIncludePaths - Adds the default system include paths so
83  ///  that e.g. stdio.h is found.
84  void AddDefaultSystemIncludePaths(const LangOptions &Lang,
85                                    const llvm::Triple &triple);
86
87  /// Realize - Merges all search path lists into one list and send it to
88  /// HeaderSearch.
89  void Realize();
90};
91
92}
93
94void InitHeaderSearch::AddPath(const llvm::Twine &Path,
95                               IncludeDirGroup Group, bool isCXXAware,
96                               bool isUserSupplied, bool isFramework,
97                               bool IgnoreSysRoot) {
98  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
99  FileManager &FM = Headers.getFileMgr();
100
101  // Compute the actual path, taking into consideration -isysroot.
102  llvm::SmallString<256> MappedPathStr;
103  llvm::raw_svector_ostream MappedPath(MappedPathStr);
104
105  // Handle isysroot.
106  if (Group == System && !IgnoreSysRoot) {
107    // FIXME: Portability.  This should be a sys::Path interface, this doesn't
108    // handle things like C:\ right, nor win32 \\network\device\blah.
109    if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present.
110      MappedPath << isysroot;
111  }
112
113  Path.print(MappedPath);
114
115  // Compute the DirectoryLookup type.
116  SrcMgr::CharacteristicKind Type;
117  if (Group == Quoted || Group == Angled)
118    Type = SrcMgr::C_User;
119  else if (isCXXAware)
120    Type = SrcMgr::C_System;
121  else
122    Type = SrcMgr::C_ExternCSystem;
123
124
125  // If the directory exists, add it.
126  if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) {
127    IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
128                                                  isFramework));
129    return;
130  }
131
132  // Check to see if this is an apple-style headermap (which are not allowed to
133  // be frameworks).
134  if (!isFramework) {
135    if (const FileEntry *FE = FM.getFile(MappedPath.str())) {
136      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
137        // It is a headermap, add it to the search path.
138        IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
139        return;
140      }
141    }
142  }
143
144  if (Verbose)
145    llvm::errs() << "ignoring nonexistent directory \""
146                 << MappedPath.str() << "\"\n";
147}
148
149
150void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) {
151  if (at.empty()) // Empty string should not add '.' path.
152    return;
153
154  llvm::StringRef::size_type delim;
155  while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) {
156    if (delim == 0)
157      AddPath(".", Angled, false, true, false);
158    else
159      AddPath(at.substr(0, delim), Angled, false, true, false);
160    at = at.substr(delim + 1);
161  }
162
163  if (at.empty())
164    AddPath(".", Angled, false, true, false);
165  else
166    AddPath(at, Angled, false, true, false);
167}
168
169void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
170                                                   llvm::StringRef ArchDir,
171                                                   llvm::StringRef Dir32,
172                                                   llvm::StringRef Dir64,
173                                                   const llvm::Triple &triple) {
174  // Add the base dir
175  AddPath(Base, System, true, false, false);
176
177  // Add the multilib dirs
178  llvm::Triple::ArchType arch = triple.getArch();
179  bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
180  if (is64bit)
181    AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
182  else
183    AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
184
185  // Add the backward dir
186  AddPath(Base + "/backward", System, true, false, false);
187}
188
189void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
190                                                     llvm::StringRef Arch,
191                                                     llvm::StringRef Version) {
192  llvm::Twine localBase = Base + "/" + Arch + "/" + Version + "/include";
193  AddPath(localBase, System, true, false, false);
194  AddPath(localBase + "/c++", System, true, false, false);
195  AddPath(localBase + "/c++/backward", System, true, false, false);
196}
197
198  // FIXME: This probably should goto to some platform utils place.
199#ifdef _MSC_VER
200
201  // Read registry string.
202  // This also supports a means to look for high-versioned keys by use
203  // of a $VERSION placeholder in the key path.
204  // $VERSION in the key path is a placeholder for the version number,
205  // causing the highest value path to be searched for and used.
206  // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
207  // There can be additional characters in the component.  Only the numberic
208  // characters are compared.
209bool getSystemRegistryString(const char *keyPath, const char *valueName,
210                       char *value, size_t maxLength) {
211  HKEY hRootKey = NULL;
212  HKEY hKey = NULL;
213  const char* subKey = NULL;
214  DWORD valueType;
215  DWORD valueSize = maxLength - 1;
216  long lResult;
217  bool returnValue = false;
218  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
219    hRootKey = HKEY_CLASSES_ROOT;
220    subKey = keyPath + 18;
221  }
222  else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
223    hRootKey = HKEY_USERS;
224    subKey = keyPath + 11;
225  }
226  else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
227    hRootKey = HKEY_LOCAL_MACHINE;
228    subKey = keyPath + 19;
229  }
230  else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
231    hRootKey = HKEY_CURRENT_USER;
232    subKey = keyPath + 18;
233  }
234  else
235    return(false);
236  const char *placeHolder = strstr(subKey, "$VERSION");
237  char bestName[256];
238  bestName[0] = '\0';
239  // If we have a $VERSION placeholder, do the highest-version search.
240  if (placeHolder) {
241    const char *keyEnd = placeHolder - 1;
242    const char *nextKey = placeHolder;
243    // Find end of previous key.
244    while ((keyEnd > subKey) && (*keyEnd != '\\'))
245      keyEnd--;
246    // Find end of key containing $VERSION.
247    while (*nextKey && (*nextKey != '\\'))
248      nextKey++;
249    size_t partialKeyLength = keyEnd - subKey;
250    char partialKey[256];
251    if (partialKeyLength > sizeof(partialKey))
252      partialKeyLength = sizeof(partialKey);
253    strncpy(partialKey, subKey, partialKeyLength);
254    partialKey[partialKeyLength] = '\0';
255    HKEY hTopKey = NULL;
256    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
257    if (lResult == ERROR_SUCCESS) {
258      char keyName[256];
259      int bestIndex = -1;
260      double bestValue = 0.0;
261      DWORD index, size = sizeof(keyName) - 1;
262      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
263          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
264        const char *sp = keyName;
265        while (*sp && !isdigit(*sp))
266          sp++;
267        if (!*sp)
268          continue;
269        const char *ep = sp + 1;
270        while (*ep && (isdigit(*ep) || (*ep == '.')))
271          ep++;
272        char numBuf[32];
273        strncpy(numBuf, sp, sizeof(numBuf) - 1);
274        numBuf[sizeof(numBuf) - 1] = '\0';
275        double value = strtod(numBuf, NULL);
276        if (value > bestValue) {
277          bestIndex = (int)index;
278          bestValue = value;
279          strcpy(bestName, keyName);
280        }
281        size = sizeof(keyName) - 1;
282      }
283      // If we found the highest versioned key, open the key and get the value.
284      if (bestIndex != -1) {
285        // Append rest of key.
286        strncat(bestName, nextKey, sizeof(bestName) - 1);
287        bestName[sizeof(bestName) - 1] = '\0';
288        // Open the chosen key path remainder.
289        lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
290        if (lResult == ERROR_SUCCESS) {
291          lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
292            (LPBYTE)value, &valueSize);
293          if (lResult == ERROR_SUCCESS)
294            returnValue = true;
295          RegCloseKey(hKey);
296        }
297      }
298      RegCloseKey(hTopKey);
299    }
300  }
301  else {
302    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
303    if (lResult == ERROR_SUCCESS) {
304      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
305        (LPBYTE)value, &valueSize);
306      if (lResult == ERROR_SUCCESS)
307        returnValue = true;
308      RegCloseKey(hKey);
309    }
310  }
311  return(returnValue);
312}
313#else // _MSC_VER
314  // Read registry string.
315bool getSystemRegistryString(const char *, const char *, char *, size_t) {
316  return(false);
317}
318#endif // _MSC_VER
319
320  // Get Visual Studio installation directory.
321bool getVisualStudioDir(std::string &path) {
322  char vsIDEInstallDir[256];
323  // Try the Windows registry first.
324  bool hasVCDir = getSystemRegistryString(
325    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
326    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
327    // If we have both vc80 and vc90, pick version we were compiled with.
328  if (hasVCDir && vsIDEInstallDir[0]) {
329    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
330    if (p)
331      *p = '\0';
332    path = vsIDEInstallDir;
333    return(true);
334  }
335  else {
336    // Try the environment.
337    const char* vs90comntools = getenv("VS90COMNTOOLS");
338    const char* vs80comntools = getenv("VS80COMNTOOLS");
339    const char* vscomntools = NULL;
340      // If we have both vc80 and vc90, pick version we were compiled with.
341    if (vs90comntools && vs80comntools) {
342      #if (_MSC_VER >= 1500)  // VC90
343          vscomntools = vs90comntools;
344      #elif (_MSC_VER == 1400) // VC80
345          vscomntools = vs80comntools;
346      #else
347          vscomntools = vs90comntools;
348      #endif
349    }
350    else if (vs90comntools)
351      vscomntools = vs90comntools;
352    else if (vs80comntools)
353      vscomntools = vs80comntools;
354    if (vscomntools && *vscomntools) {
355      char *p = (char*)strstr(vscomntools, "\\Common7\\Tools");
356      if (p)
357        *p = '\0';
358      path = vscomntools;
359      return(true);
360    }
361    else
362      return(false);
363  }
364  return(false);
365}
366
367  // Get Windows SDK installation directory.
368bool getWindowsSDKDir(std::string &path) {
369  char windowsSDKInstallDir[256];
370  // Try the Windows registry.
371  bool hasSDKDir = getSystemRegistryString(
372   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
373    "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1);
374    // If we have both vc80 and vc90, pick version we were compiled with.
375  if (hasSDKDir && windowsSDKInstallDir[0]) {
376    path = windowsSDKInstallDir;
377    return(true);
378  }
379  return(false);
380}
381
382void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
383  // FIXME: temporary hack: hard-coded paths.
384  llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
385  if (CIncludeDirs != "") {
386    llvm::SmallVector<llvm::StringRef, 5> dirs;
387    CIncludeDirs.split(dirs, ":");
388    for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
389         i != dirs.end();
390         ++i)
391      AddPath(*i, System, false, false, false);
392    return;
393  }
394  llvm::Triple::OSType os = triple.getOS();
395  switch (os) {
396  case llvm::Triple::Win32:
397    {
398      std::string VSDir;
399      std::string WindowsSDKDir;
400      if (getVisualStudioDir(VSDir)) {
401        AddPath(VSDir + "\\VC\\include", System, false, false, false);
402        if (getWindowsSDKDir(WindowsSDKDir))
403          AddPath(WindowsSDKDir, System, false, false, false);
404        else
405          AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
406            System, false, false, false);
407      }
408      else {
409          // Default install paths.
410        AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
411          System, false, false, false);
412        AddPath(
413        "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
414          System, false, false, false);
415        AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include",
416          System, false, false, false);
417        AddPath(
418        "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include",
419          System, false, false, false);
420          // For some clang developers.
421        AddPath("G:/Program Files/Microsoft Visual Studio 9.0/VC/include",
422          System, false, false, false);
423        AddPath(
424        "G:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
425          System, false, false, false);
426      }
427    }
428    break;
429  case llvm::Triple::MinGW64:
430  case llvm::Triple::MinGW32:
431    AddPath("c:/mingw/include", System, true, false, false);
432    break;
433  default:
434    break;
435  }
436
437  AddPath("/usr/local/include", System, false, false, false);
438  AddPath("/usr/include", System, false, false, false);
439}
440
441void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
442  llvm::Triple::OSType os = triple.getOS();
443  llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
444  if (CxxIncludeRoot != "") {
445    llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
446    if (CxxIncludeArch == "")
447      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
448                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
449    else
450      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
451                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
452    return;
453  }
454  // FIXME: temporary hack: hard-coded paths.
455  switch (os) {
456  case llvm::Triple::Cygwin:
457    AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
458        System, true, false, false);
459    AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
460        System, true, false, false);
461    break;
462  case llvm::Triple::MinGW64:
463    // Try gcc 4.4.0
464    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
465    // Try gcc 4.3.0
466    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
467    // Fall through.
468  case llvm::Triple::MinGW32:
469    // Try gcc 4.4.0
470    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
471    // Try gcc 4.3.0
472    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
473    break;
474  case llvm::Triple::Darwin:
475    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
476                                "i686-apple-darwin10", "", "x86_64", triple);
477    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
478                                "i686-apple-darwin8", "", "", triple);
479    break;
480  case llvm::Triple::Linux:
481    // Ubuntu 7.10 - Gutsy Gibbon
482    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
483                                "i486-linux-gnu", "", "", triple);
484    // Ubuntu 9.04
485    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
486                                "x86_64-linux-gnu","32", "", triple);
487    // Ubuntu 9.10
488    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
489                                "x86_64-linux-gnu", "32", "", triple);
490    // Fedora 8
491    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
492                                "i386-redhat-linux", "", "", triple);
493    // Fedora 9
494    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
495                                "i386-redhat-linux", "", "", triple);
496    // Fedora 10
497    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
498                                "i386-redhat-linux","", "", triple);
499
500    // Fedora 11
501    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
502                                "i586-redhat-linux","", "", triple);
503
504    // Fedora 12
505    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
506                                "i686-redhat-linux","", "", triple);
507
508    // openSUSE 11.1 32 bit
509    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
510                                "i586-suse-linux", "", "", triple);
511    // openSUSE 11.1 64 bit
512    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
513                                "x86_64-suse-linux", "32", "", triple);
514    // openSUSE 11.2
515    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
516                                "i586-suse-linux", "", "", triple);
517    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
518                                "x86_64-suse-linux", "", "", triple);
519    // Arch Linux 2008-06-24
520    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
521                                "i686-pc-linux-gnu", "", "", triple);
522    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
523                                "x86_64-unknown-linux-gnu", "", "", triple);
524    // Gentoo x86 2009.1 stable
525    AddGnuCPlusPlusIncludePaths(
526      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
527      "i686-pc-linux-gnu", "", "", triple);
528    // Gentoo x86 2009.0 stable
529    AddGnuCPlusPlusIncludePaths(
530      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
531      "i686-pc-linux-gnu", "", "", triple);
532    // Gentoo x86 2008.0 stable
533    AddGnuCPlusPlusIncludePaths(
534      "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
535      "i686-pc-linux-gnu", "", "", triple);
536    // Ubuntu 8.10
537    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
538                                "i486-pc-linux-gnu", "", "", triple);
539    // Ubuntu 9.04
540    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
541                                "i486-linux-gnu","", "", triple);
542    // Gentoo amd64 stable
543    AddGnuCPlusPlusIncludePaths(
544        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
545        "i686-pc-linux-gnu", "", "", triple);
546    // Exherbo (2009-10-26)
547    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
548                                "x86_64-pc-linux-gnu", "32", "", triple);
549    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
550                                "i686-pc-linux-gnu", "", "", triple);
551    break;
552  case llvm::Triple::FreeBSD:
553    // DragonFly
554    AddPath("/usr/include/c++/4.1", System, true, false, false);
555    // FreeBSD
556    AddPath("/usr/include/c++/4.2", System, true, false, false);
557    break;
558  case llvm::Triple::Solaris:
559    // Solaris - Fall though..
560  case llvm::Triple::AuroraUX:
561    // AuroraUX
562    AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
563                                "i386-pc-solaris2.11", "", "", triple);
564    break;
565  default:
566    break;
567  }
568}
569
570void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
571                                                    const llvm::Triple &triple) {
572  if (Lang.CPlusPlus)
573    AddDefaultCPlusPlusIncludePaths(triple);
574
575  AddDefaultCIncludePaths(triple);
576
577  // Add the default framework include paths on Darwin.
578  if (triple.getOS() == llvm::Triple::Darwin) {
579    AddPath("/System/Library/Frameworks", System, true, false, true);
580    AddPath("/Library/Frameworks", System, true, false, true);
581  }
582}
583
584/// RemoveDuplicates - If there are duplicate directory entries in the specified
585/// search list, remove the later (dead) ones.
586static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
587                             bool Verbose) {
588  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
589  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
590  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
591  for (unsigned i = 0; i != SearchList.size(); ++i) {
592    unsigned DirToRemove = i;
593
594    const DirectoryLookup &CurEntry = SearchList[i];
595
596    if (CurEntry.isNormalDir()) {
597      // If this isn't the first time we've seen this dir, remove it.
598      if (SeenDirs.insert(CurEntry.getDir()))
599        continue;
600    } else if (CurEntry.isFramework()) {
601      // If this isn't the first time we've seen this framework dir, remove it.
602      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
603        continue;
604    } else {
605      assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
606      // If this isn't the first time we've seen this headermap, remove it.
607      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
608        continue;
609    }
610
611    // If we have a normal #include dir/framework/headermap that is shadowed
612    // later in the chain by a system include location, we actually want to
613    // ignore the user's request and drop the user dir... keeping the system
614    // dir.  This is weird, but required to emulate GCC's search path correctly.
615    //
616    // Since dupes of system dirs are rare, just rescan to find the original
617    // that we're nuking instead of using a DenseMap.
618    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
619      // Find the dir that this is the same of.
620      unsigned FirstDir;
621      for (FirstDir = 0; ; ++FirstDir) {
622        assert(FirstDir != i && "Didn't find dupe?");
623
624        const DirectoryLookup &SearchEntry = SearchList[FirstDir];
625
626        // If these are different lookup types, then they can't be the dupe.
627        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
628          continue;
629
630        bool isSame;
631        if (CurEntry.isNormalDir())
632          isSame = SearchEntry.getDir() == CurEntry.getDir();
633        else if (CurEntry.isFramework())
634          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
635        else {
636          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
637          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
638        }
639
640        if (isSame)
641          break;
642      }
643
644      // If the first dir in the search path is a non-system dir, zap it
645      // instead of the system one.
646      if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
647        DirToRemove = FirstDir;
648    }
649
650    if (Verbose) {
651      llvm::errs() << "ignoring duplicate directory \""
652                   << CurEntry.getName() << "\"\n";
653      if (DirToRemove != i)
654        llvm::errs() << "  as it is a non-system directory that duplicates "
655                     << "a system directory\n";
656    }
657
658    // This is reached if the current entry is a duplicate.  Remove the
659    // DirToRemove (usually the current dir).
660    SearchList.erase(SearchList.begin()+DirToRemove);
661    --i;
662  }
663}
664
665
666void InitHeaderSearch::Realize() {
667  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
668  std::vector<DirectoryLookup> SearchList;
669  SearchList = IncludeGroup[Angled];
670  SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
671                    IncludeGroup[System].end());
672  SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
673                    IncludeGroup[After].end());
674  RemoveDuplicates(SearchList, Verbose);
675  RemoveDuplicates(IncludeGroup[Quoted], Verbose);
676
677  // Prepend QUOTED list on the search list.
678  SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
679                    IncludeGroup[Quoted].end());
680
681
682  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
683  Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
684                         DontSearchCurDir);
685
686  // If verbose, print the list of directories that will be searched.
687  if (Verbose) {
688    llvm::errs() << "#include \"...\" search starts here:\n";
689    unsigned QuotedIdx = IncludeGroup[Quoted].size();
690    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
691      if (i == QuotedIdx)
692        llvm::errs() << "#include <...> search starts here:\n";
693      const char *Name = SearchList[i].getName();
694      const char *Suffix;
695      if (SearchList[i].isNormalDir())
696        Suffix = "";
697      else if (SearchList[i].isFramework())
698        Suffix = " (framework directory)";
699      else {
700        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
701        Suffix = " (headermap)";
702      }
703      llvm::errs() << " " << Name << Suffix << "\n";
704    }
705    llvm::errs() << "End of search list.\n";
706  }
707}
708
709void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
710                                     const HeaderSearchOptions &HSOpts,
711                                     const LangOptions &Lang,
712                                     const llvm::Triple &Triple) {
713  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
714
715  // Add the user defined entries.
716  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
717    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
718    Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
719                 false);
720  }
721
722  // Add entries from CPATH and friends.
723  Init.AddDelimitedPaths(HSOpts.EnvIncPath);
724  if (Lang.CPlusPlus && Lang.ObjC1)
725    Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
726  else if (Lang.CPlusPlus)
727    Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
728  else if (Lang.ObjC1)
729    Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
730  else
731    Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
732
733  if (!HSOpts.BuiltinIncludePath.empty()) {
734    // Ignore the sys root, we *always* look for clang headers relative to
735    // supplied path.
736    Init.AddPath(HSOpts.BuiltinIncludePath, System,
737                 false, false, false, /*IgnoreSysRoot=*/ true);
738  }
739
740  if (HSOpts.UseStandardIncludes)
741    Init.AddDefaultSystemIncludePaths(Lang, Triple);
742
743  Init.Realize();
744}
745