InitHeaderSearch.cpp revision b2cf89f50c2072d94c51a1128c2d6dbe9db6bdd1
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/ErrorHandling.h"
31#include "llvm/Support/Path.h"
32#include "llvm/Config/config.h"
33using namespace clang;
34using namespace clang::frontend;
35
36namespace {
37
38/// InitHeaderSearch - This class makes it easier to set the search paths of
39///  a HeaderSearch object. InitHeaderSearch stores several search path lists
40///  internally, which can be sent to a HeaderSearch object in one swoop.
41class InitHeaderSearch {
42  std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
43  typedef std::vector<std::pair<IncludeDirGroup,
44                      DirectoryLookup> >::const_iterator path_iterator;
45  HeaderSearch &Headers;
46  bool Verbose;
47  std::string IncludeSysroot;
48  bool IsNotEmptyOrRoot;
49
50public:
51
52  InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
53    : Headers(HS), Verbose(verbose), IncludeSysroot(sysroot),
54      IsNotEmptyOrRoot(!(sysroot.empty() || sysroot == "/")) {
55  }
56
57  /// AddPath - Add the specified path to the specified group list.
58  void AddPath(const Twine &Path, IncludeDirGroup Group,
59               bool isCXXAware, bool isUserSupplied,
60               bool isFramework, bool IgnoreSysRoot = false);
61
62  /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
63  ///  libstdc++.
64  void AddGnuCPlusPlusIncludePaths(StringRef Base,
65                                   StringRef ArchDir,
66                                   StringRef Dir32,
67                                   StringRef Dir64,
68                                   const llvm::Triple &triple);
69
70  /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW
71  ///  libstdc++.
72  void AddMinGWCPlusPlusIncludePaths(StringRef Base,
73                                     StringRef Arch,
74                                     StringRef Version);
75
76  /// AddMinGW64CXXPaths - Add the necessary paths to support
77  /// libstdc++ of x86_64-w64-mingw32 aka mingw-w64.
78  void AddMinGW64CXXPaths(StringRef Base,
79                          StringRef Version);
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                                       const HeaderSearchOptions &HSOpts);
89
90  /// AddDefaultSystemIncludePaths - Adds the default system include paths so
91  ///  that e.g. stdio.h is found.
92  void AddDefaultIncludePaths(const LangOptions &Lang,
93                              const llvm::Triple &triple,
94                              const HeaderSearchOptions &HSOpts);
95
96  /// Realize - Merges all search path lists into one list and send it to
97  /// HeaderSearch.
98  void Realize(const LangOptions &Lang);
99};
100
101}  // end anonymous namespace.
102
103void InitHeaderSearch::AddPath(const Twine &Path,
104                               IncludeDirGroup Group, bool isCXXAware,
105                               bool isUserSupplied, bool isFramework,
106                               bool IgnoreSysRoot) {
107  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
108  FileManager &FM = Headers.getFileMgr();
109
110  // Compute the actual path, taking into consideration -isysroot.
111  llvm::SmallString<256> MappedPathStorage;
112  StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
113
114  // Handle isysroot.
115  if ((Group == System || Group == CXXSystem) && !IgnoreSysRoot &&
116#if defined(_WIN32)
117      !MappedPathStr.empty() &&
118      llvm::sys::path::is_separator(MappedPathStr[0]) &&
119#else
120      llvm::sys::path::is_absolute(MappedPathStr) &&
121#endif
122      IsNotEmptyOrRoot) {
123    MappedPathStorage.clear();
124    MappedPathStr =
125      (IncludeSysroot + Path).toStringRef(MappedPathStorage);
126  }
127
128  // Compute the DirectoryLookup type.
129  SrcMgr::CharacteristicKind Type;
130  if (Group == Quoted || Group == Angled || Group == IndexHeaderMap)
131    Type = SrcMgr::C_User;
132  else if (isCXXAware)
133    Type = SrcMgr::C_System;
134  else
135    Type = SrcMgr::C_ExternCSystem;
136
137
138  // If the directory exists, add it.
139  if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
140    IncludePath.push_back(std::make_pair(Group, DirectoryLookup(DE, Type,
141                          isUserSupplied, isFramework)));
142    return;
143  }
144
145  // Check to see if this is an apple-style headermap (which are not allowed to
146  // be frameworks).
147  if (!isFramework) {
148    if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
149      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
150        // It is a headermap, add it to the search path.
151        IncludePath.push_back(std::make_pair(Group, DirectoryLookup(HM, Type,
152                              isUserSupplied, Group == IndexHeaderMap)));
153        return;
154      }
155    }
156  }
157
158  if (Verbose)
159    llvm::errs() << "ignoring nonexistent directory \""
160                 << MappedPathStr << "\"\n";
161}
162
163void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
164                                                   StringRef ArchDir,
165                                                   StringRef Dir32,
166                                                   StringRef Dir64,
167                                                   const llvm::Triple &triple) {
168  // Add the base dir
169  AddPath(Base, CXXSystem, true, false, false);
170
171  // Add the multilib dirs
172  llvm::Triple::ArchType arch = triple.getArch();
173  bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
174  if (is64bit)
175    AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, true, false, false);
176  else
177    AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, true, false, false);
178
179  // Add the backward dir
180  AddPath(Base + "/backward", CXXSystem, true, false, false);
181}
182
183void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
184                                                     StringRef Arch,
185                                                     StringRef Version) {
186  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
187          CXXSystem, true, false, false);
188  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
189          CXXSystem, true, false, false);
190  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
191          CXXSystem, true, false, false);
192}
193
194void InitHeaderSearch::AddMinGW64CXXPaths(StringRef Base,
195                                          StringRef Version) {
196  // Assumes Base is HeaderSearchOpts' ResourceDir
197  AddPath(Base + "/../../../include/c++/" + Version,
198          CXXSystem, true, false, false);
199  AddPath(Base + "/../../../include/c++/" + Version + "/x86_64-w64-mingw32",
200          CXXSystem, true, false, false);
201  AddPath(Base + "/../../../include/c++/" + Version + "/i686-w64-mingw32",
202          CXXSystem, true, false, false);
203  AddPath(Base + "/../../../include/c++/" + Version + "/backward",
204          CXXSystem, true, false, false);
205}
206
207void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
208                                            const HeaderSearchOptions &HSOpts) {
209  llvm::Triple::OSType os = triple.getOS();
210
211  if (HSOpts.UseStandardSystemIncludes) {
212    switch (os) {
213    case llvm::Triple::FreeBSD:
214    case llvm::Triple::NetBSD:
215      break;
216    default:
217      // FIXME: temporary hack: hard-coded paths.
218      AddPath("/usr/local/include", System, true, false, false);
219      break;
220    }
221  }
222
223  // Builtin includes use #include_next directives and should be positioned
224  // just prior C include dirs.
225  if (HSOpts.UseBuiltinIncludes) {
226    // Ignore the sys root, we *always* look for clang headers relative to
227    // supplied path.
228    llvm::sys::Path P(HSOpts.ResourceDir);
229    P.appendComponent("include");
230    AddPath(P.str(), System, false, false, false, /*IgnoreSysRoot=*/ true);
231  }
232
233  // All remaining additions are for system include directories, early exit if
234  // we aren't using them.
235  if (!HSOpts.UseStandardSystemIncludes)
236    return;
237
238  // Add dirs specified via 'configure --with-c-include-dirs'.
239  StringRef CIncludeDirs(C_INCLUDE_DIRS);
240  if (CIncludeDirs != "") {
241    SmallVector<StringRef, 5> dirs;
242    CIncludeDirs.split(dirs, ":");
243    for (SmallVectorImpl<StringRef>::iterator i = dirs.begin();
244         i != dirs.end();
245         ++i)
246      AddPath(*i, System, false, false, false);
247    return;
248  }
249
250  switch (os) {
251  case llvm::Triple::Win32:
252    llvm_unreachable("Windows include management is handled in the driver.");
253
254  case llvm::Triple::Haiku:
255    AddPath("/boot/common/include", System, true, false, false);
256    AddPath("/boot/develop/headers/os", System, true, false, false);
257    AddPath("/boot/develop/headers/os/app", System, true, false, false);
258    AddPath("/boot/develop/headers/os/arch", System, true, false, false);
259    AddPath("/boot/develop/headers/os/device", System, true, false, false);
260    AddPath("/boot/develop/headers/os/drivers", System, true, false, false);
261    AddPath("/boot/develop/headers/os/game", System, true, false, false);
262    AddPath("/boot/develop/headers/os/interface", System, true, false, false);
263    AddPath("/boot/develop/headers/os/kernel", System, true, false, false);
264    AddPath("/boot/develop/headers/os/locale", System, true, false, false);
265    AddPath("/boot/develop/headers/os/mail", System, true, false, false);
266    AddPath("/boot/develop/headers/os/media", System, true, false, false);
267    AddPath("/boot/develop/headers/os/midi", System, true, false, false);
268    AddPath("/boot/develop/headers/os/midi2", System, true, false, false);
269    AddPath("/boot/develop/headers/os/net", System, true, false, false);
270    AddPath("/boot/develop/headers/os/storage", System, true, false, false);
271    AddPath("/boot/develop/headers/os/support", System, true, false, false);
272    AddPath("/boot/develop/headers/os/translation",
273      System, true, false, false);
274    AddPath("/boot/develop/headers/os/add-ons/graphics",
275      System, true, false, false);
276    AddPath("/boot/develop/headers/os/add-ons/input_server",
277      System, true, false, false);
278    AddPath("/boot/develop/headers/os/add-ons/screen_saver",
279      System, true, false, false);
280    AddPath("/boot/develop/headers/os/add-ons/tracker",
281      System, true, false, false);
282    AddPath("/boot/develop/headers/os/be_apps/Deskbar",
283      System, true, false, false);
284    AddPath("/boot/develop/headers/os/be_apps/NetPositive",
285      System, true, false, false);
286    AddPath("/boot/develop/headers/os/be_apps/Tracker",
287      System, true, false, false);
288    AddPath("/boot/develop/headers/cpp", System, true, false, false);
289    AddPath("/boot/develop/headers/cpp/i586-pc-haiku",
290      System, true, false, false);
291    AddPath("/boot/develop/headers/3rdparty", System, true, false, false);
292    AddPath("/boot/develop/headers/bsd", System, true, false, false);
293    AddPath("/boot/develop/headers/glibc", System, true, false, false);
294    AddPath("/boot/develop/headers/posix", System, true, false, false);
295    AddPath("/boot/develop/headers",  System, true, false, false);
296    break;
297  case llvm::Triple::RTEMS:
298    break;
299  case llvm::Triple::Cygwin:
300    AddPath("/usr/include/w32api", System, true, false, false);
301    break;
302  case llvm::Triple::MinGW32: {
303      // mingw-w64 crt include paths
304      llvm::sys::Path P(HSOpts.ResourceDir);
305      P.appendComponent("../../../i686-w64-mingw32/include"); // <sysroot>/i686-w64-mingw32/include
306      AddPath(P.str(), System, true, false, false);
307      P = llvm::sys::Path(HSOpts.ResourceDir);
308      P.appendComponent("../../../x86_64-w64-mingw32/include"); // <sysroot>/x86_64-w64-mingw32/include
309      AddPath(P.str(), System, true, false, false);
310      // mingw.org crt include paths
311      P = llvm::sys::Path(HSOpts.ResourceDir);
312      P.appendComponent("../../../include"); // <sysroot>/include
313      AddPath(P.str(), System, true, false, false);
314      AddPath("/mingw/include", System, true, false, false);
315      AddPath("c:/mingw/include", System, true, false, false);
316    }
317    break;
318
319  case llvm::Triple::Linux:
320    // Generic Debian multiarch support:
321    if (triple.getArch() == llvm::Triple::x86_64) {
322      AddPath("/usr/include/x86_64-linux-gnu", System, false, false, false);
323      AddPath("/usr/include/i686-linux-gnu/64", System, false, false, false);
324      AddPath("/usr/include/i486-linux-gnu/64", System, false, false, false);
325    } else if (triple.getArch() == llvm::Triple::x86) {
326      AddPath("/usr/include/x86_64-linux-gnu/32", System, false, false, false);
327      AddPath("/usr/include/i686-linux-gnu", System, false, false, false);
328      AddPath("/usr/include/i486-linux-gnu", System, false, false, false);
329      AddPath("/usr/include/i386-linux-gnu", System, false, false, false);
330    } else if (triple.getArch() == llvm::Triple::arm) {
331      AddPath("/usr/include/arm-linux-gnueabi", System, false, false, false);
332    }
333  default:
334    break;
335  }
336
337  if ( os != llvm::Triple::RTEMS )
338    AddPath("/usr/include", System, false, false, false);
339}
340
341void InitHeaderSearch::
342AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) {
343  llvm::Triple::OSType os = triple.getOS();
344  StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
345  if (CxxIncludeRoot != "") {
346    StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
347    if (CxxIncludeArch == "")
348      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
349                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
350                                  triple);
351    else
352      AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
353                                  CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
354                                  triple);
355    return;
356  }
357  // FIXME: temporary hack: hard-coded paths.
358
359  if (triple.isOSDarwin()) {
360    switch (triple.getArch()) {
361    default: break;
362
363    case llvm::Triple::ppc:
364    case llvm::Triple::ppc64:
365      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
366                                  "powerpc-apple-darwin10", "", "ppc64",
367                                  triple);
368      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
369                                  "powerpc-apple-darwin10", "", "ppc64",
370                                  triple);
371      break;
372
373    case llvm::Triple::x86:
374    case llvm::Triple::x86_64:
375      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
376                                  "i686-apple-darwin10", "", "x86_64", triple);
377      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
378                                  "i686-apple-darwin8", "", "", triple);
379      break;
380
381    case llvm::Triple::arm:
382    case llvm::Triple::thumb:
383      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
384                                  "arm-apple-darwin10", "v7", "", triple);
385      AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
386                                  "arm-apple-darwin10", "v6", "", triple);
387      break;
388    }
389    return;
390  }
391
392  switch (os) {
393  case llvm::Triple::Cygwin:
394    // Cygwin-1.7
395    AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
396    // g++-4 / Cygwin-1.5
397    AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
398    // FIXME: Do we support g++-3.4.4?
399    AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4");
400    break;
401  case llvm::Triple::MinGW32:
402    // mingw-w64 C++ include paths (i686-w64-mingw32 and x86_64-w64-mingw32)
403    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.0");
404    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.1");
405    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.2");
406    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.3");
407    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.6.0");
408    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.6.1");
409    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.6.2");
410    AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.0");
411    // mingw.org C++ include paths
412    AddMinGWCPlusPlusIncludePaths("/mingw/lib/gcc", "mingw32", "4.5.2"); //MSYS
413    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
414    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
415    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
416    break;
417  case llvm::Triple::DragonFly:
418    AddPath("/usr/include/c++/4.1", CXXSystem, true, false, false);
419    break;
420  case llvm::Triple::Linux:
421    //===------------------------------------------------------------------===//
422    // Debian based distros.
423    // Note: these distros symlink /usr/include/c++/X.Y.Z -> X.Y
424    //===------------------------------------------------------------------===//
425
426    // Ubuntu 11.11 "Oneiric Ocelot" -- gcc-4.6.0
427    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6",
428                                "x86_64-linux-gnu", "32", "", triple);
429    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6",
430                                "i686-linux-gnu", "", "64", triple);
431    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6",
432                                "i486-linux-gnu", "", "64", triple);
433    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6",
434                                "arm-linux-gnueabi", "", "", triple);
435
436    // Ubuntu 11.04 "Natty Narwhal" -- gcc-4.5.2
437    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
438                                "x86_64-linux-gnu", "32", "", triple);
439    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
440                                "i686-linux-gnu", "", "64", triple);
441    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
442                                "i486-linux-gnu", "", "64", triple);
443    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
444                                "arm-linux-gnueabi", "", "", triple);
445
446    // Ubuntu 10.10 "Maverick Meerkat" -- gcc-4.4.5
447    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
448                                "i686-linux-gnu", "", "64", triple);
449    // The rest of 10.10 is the same as previous versions.
450
451    // Ubuntu 10.04 LTS "Lucid Lynx" -- gcc-4.4.3
452    // Ubuntu 9.10 "Karmic Koala"    -- gcc-4.4.1
453    // Debian 6.0 "squeeze"          -- gcc-4.4.2
454    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
455                                "x86_64-linux-gnu", "32", "", triple);
456    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
457                                "i486-linux-gnu", "", "64", triple);
458    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
459                                "arm-linux-gnueabi", "", "", triple);
460    // Ubuntu 9.04 "Jaunty Jackalope" -- gcc-4.3.3
461    // Ubuntu 8.10 "Intrepid Ibex"    -- gcc-4.3.2
462    // Debian 5.0 "lenny"             -- gcc-4.3.2
463    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
464                                "x86_64-linux-gnu", "32", "", triple);
465    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
466                                "i486-linux-gnu", "", "64", triple);
467    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
468                                "arm-linux-gnueabi", "", "", triple);
469    // Ubuntu 8.04.4 LTS "Hardy Heron"     -- gcc-4.2.4
470    // Ubuntu 8.04.[0-3] LTS "Hardy Heron" -- gcc-4.2.3
471    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2",
472                                "x86_64-linux-gnu", "32", "", triple);
473    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2",
474                                "i486-linux-gnu", "", "64", triple);
475    // Ubuntu 7.10 "Gutsy Gibbon" -- gcc-4.1.3
476    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1",
477                                "x86_64-linux-gnu", "32", "", triple);
478    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1",
479                                "i486-linux-gnu", "", "64", triple);
480
481    //===------------------------------------------------------------------===//
482    // Redhat based distros.
483    //===------------------------------------------------------------------===//
484    // Fedora 15 (GCC 4.6.1)
485    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.1",
486                                "x86_64-redhat-linux", "32", "", triple);
487    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.1",
488                                "i686-redhat-linux", "", "", triple);
489    // Fedora 15 (GCC 4.6.0)
490    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0",
491                                "x86_64-redhat-linux", "32", "", triple);
492    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0",
493                                "i686-redhat-linux", "", "", triple);
494    // Fedora 14
495    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1",
496                                "x86_64-redhat-linux", "32", "", triple);
497    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1",
498                                "i686-redhat-linux", "", "", triple);
499    // RHEL5(gcc44)
500    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
501                                "x86_64-redhat-linux6E", "32", "", triple);
502    // Fedora 13
503    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
504                                "x86_64-redhat-linux", "32", "", triple);
505    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
506                                "i686-redhat-linux","", "", triple);
507    // Fedora 12
508    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
509                                "x86_64-redhat-linux", "32", "", triple);
510    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
511                                "i686-redhat-linux","", "", triple);
512    // Fedora 12 (pre-FEB-2010)
513    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
514                                "x86_64-redhat-linux", "32", "", triple);
515    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
516                                "i686-redhat-linux","", "", triple);
517    // Fedora 11
518    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
519                                "x86_64-redhat-linux", "32", "", triple);
520    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
521                                "i586-redhat-linux","", "", triple);
522    // Fedora 10
523    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
524                                "x86_64-redhat-linux", "32", "", triple);
525    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
526                                "i386-redhat-linux","", "", triple);
527    // Fedora 9
528    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
529                                "x86_64-redhat-linux", "32", "", triple);
530    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
531                                "i386-redhat-linux", "", "", triple);
532    // Fedora 8
533    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
534                                "x86_64-redhat-linux", "", "", triple);
535    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
536                                "i386-redhat-linux", "", "", triple);
537
538    // RHEL 5
539    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.1",
540                                "x86_64-redhat-linux", "32", "", triple);
541    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.1",
542                                "i386-redhat-linux", "", "", triple);
543
544
545    //===------------------------------------------------------------------===//
546
547    // Exherbo (2010-01-25)
548    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
549                                "x86_64-pc-linux-gnu", "32", "", triple);
550    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
551                                "i686-pc-linux-gnu", "", "", triple);
552
553    // openSUSE 11.1 32 bit
554    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
555                                "i586-suse-linux", "", "", triple);
556    // openSUSE 11.1 64 bit
557    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
558                                "x86_64-suse-linux", "32", "", triple);
559    // openSUSE 11.2
560    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
561                                "i586-suse-linux", "", "", triple);
562    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
563                                "x86_64-suse-linux", "", "", triple);
564
565    // openSUSE 11.4
566    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
567                                "i586-suse-linux", "", "", triple);
568    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
569                                "x86_64-suse-linux", "", "", triple);
570
571    // openSUSE 12.1
572    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6",
573                                "i586-suse-linux", "", "", triple);
574    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6",
575                                "x86_64-suse-linux", "", "", triple);
576    // Arch Linux 2008-06-24
577    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
578                                "i686-pc-linux-gnu", "", "", triple);
579    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
580                                "x86_64-unknown-linux-gnu", "", "", triple);
581
582    // Arch Linux gcc 4.6
583    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.1",
584                                "i686-pc-linux-gnu", "", "", triple);
585    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.1",
586                                "x86_64-unknown-linux-gnu", "", "", triple);
587    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0",
588                                "i686-pc-linux-gnu", "", "", triple);
589    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0",
590                                "x86_64-unknown-linux-gnu", "", "", triple);
591
592    // Slackware gcc 4.5.2 (13.37)
593    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.2",
594                                "i486-slackware-linux", "", "", triple);
595    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.2",
596                                "x86_64-slackware-linux", "", "", triple);
597    // Slackware gcc 4.5.3 (-current)
598    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.3",
599                                "i486-slackware-linux", "", "", triple);
600    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.3",
601                                "x86_64-slackware-linux", "", "", triple);
602
603    // Gentoo x86 gcc 4.5.3
604    AddGnuCPlusPlusIncludePaths(
605      "/usr/lib/gcc/i686-pc-linux-gnu/4.5.3/include/g++-v4",
606      "i686-pc-linux-gnu", "", "", triple);
607    // Gentoo x86 gcc 4.5.2
608    AddGnuCPlusPlusIncludePaths(
609      "/usr/lib/gcc/i686-pc-linux-gnu/4.5.2/include/g++-v4",
610      "i686-pc-linux-gnu", "", "", triple);
611    // Gentoo x86 gcc 4.4.5
612    AddGnuCPlusPlusIncludePaths(
613      "/usr/lib/gcc/i686-pc-linux-gnu/4.4.5/include/g++-v4",
614      "i686-pc-linux-gnu", "", "", triple);
615    // Gentoo x86 gcc 4.4.4
616    AddGnuCPlusPlusIncludePaths(
617      "/usr/lib/gcc/i686-pc-linux-gnu/4.4.4/include/g++-v4",
618      "i686-pc-linux-gnu", "", "", triple);
619   // Gentoo x86 2010.0 stable
620    AddGnuCPlusPlusIncludePaths(
621      "/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/include/g++-v4",
622      "i686-pc-linux-gnu", "", "", triple);
623    // Gentoo x86 2009.1 stable
624    AddGnuCPlusPlusIncludePaths(
625      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
626      "i686-pc-linux-gnu", "", "", triple);
627    // Gentoo x86 2009.0 stable
628    AddGnuCPlusPlusIncludePaths(
629      "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
630      "i686-pc-linux-gnu", "", "", triple);
631    // Gentoo x86 2008.0 stable
632    AddGnuCPlusPlusIncludePaths(
633      "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
634      "i686-pc-linux-gnu", "", "", triple);
635    // Gentoo x86 llvm-gcc trunk
636    AddGnuCPlusPlusIncludePaths(
637        "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1",
638        "i686-pc-linux-gnu", "", "", triple);
639
640    // Gentoo amd64 gcc 4.5.3
641    AddGnuCPlusPlusIncludePaths(
642        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/include/g++-v4",
643        "x86_64-pc-linux-gnu", "32", "", triple);
644    // Gentoo amd64 gcc 4.5.2
645    AddGnuCPlusPlusIncludePaths(
646        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4",
647        "x86_64-pc-linux-gnu", "32", "", triple);
648    // Gentoo amd64 gcc 4.4.5
649    AddGnuCPlusPlusIncludePaths(
650        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4",
651        "x86_64-pc-linux-gnu", "32", "", triple);
652    // Gentoo amd64 gcc 4.4.4
653    AddGnuCPlusPlusIncludePaths(
654        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4",
655        "x86_64-pc-linux-gnu", "32", "", triple);
656    // Gentoo amd64 gcc 4.4.3
657    AddGnuCPlusPlusIncludePaths(
658        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4",
659        "x86_64-pc-linux-gnu", "32", "", triple);
660    // Gentoo amd64 gcc 4.3.4
661    AddGnuCPlusPlusIncludePaths(
662        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4",
663        "x86_64-pc-linux-gnu", "", "", triple);
664    // Gentoo amd64 gcc 4.3.2
665    AddGnuCPlusPlusIncludePaths(
666        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4",
667        "x86_64-pc-linux-gnu", "", "", triple);
668    // Gentoo amd64 stable
669    AddGnuCPlusPlusIncludePaths(
670        "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
671        "x86_64-pc-linux-gnu", "", "", triple);
672
673    // Gentoo amd64 llvm-gcc trunk
674    AddGnuCPlusPlusIncludePaths(
675        "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1",
676        "x86_64-pc-linux-gnu", "", "", triple);
677
678    break;
679  case llvm::Triple::FreeBSD:
680    // FreeBSD 8.0
681    // FreeBSD 7.3
682    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
683    break;
684  case llvm::Triple::NetBSD:
685    AddGnuCPlusPlusIncludePaths("/usr/include/g++", "", "", "", triple);
686    break;
687  case llvm::Triple::OpenBSD: {
688    std::string t = triple.getTriple();
689    if (t.substr(0, 6) == "x86_64")
690      t.replace(0, 6, "amd64");
691    AddGnuCPlusPlusIncludePaths("/usr/include/g++",
692                                t, "", "", triple);
693    break;
694  }
695  case llvm::Triple::Minix:
696    AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
697                                "", "", "", triple);
698    break;
699  case llvm::Triple::Solaris:
700    // Solaris - Fall though..
701  case llvm::Triple::AuroraUX:
702    // AuroraUX
703    AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
704                                "i386-pc-solaris2.11", "", "", triple);
705    break;
706  default:
707    break;
708  }
709}
710
711void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
712                                              const llvm::Triple &triple,
713                                            const HeaderSearchOptions &HSOpts) {
714  // NB: This code path is going away. All of the logic is moving into the
715  // driver which has the information necessary to do target-specific
716  // selections of default include paths. Each target which moves there will be
717  // exempted from this logic here until we can delete the entire pile of code.
718  switch (triple.getOS()) {
719  default:
720    break; // Everything else continues to use this routine's logic.
721
722  case llvm::Triple::Win32:
723    return;
724  }
725
726  if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes &&
727      HSOpts.UseStandardSystemIncludes) {
728    if (HSOpts.UseLibcxx) {
729      if (triple.isOSDarwin()) {
730        // On Darwin, libc++ may be installed alongside the compiler in
731        // lib/c++/v1.
732        llvm::sys::Path P(HSOpts.ResourceDir);
733        if (!P.isEmpty()) {
734          P.eraseComponent();  // Remove version from foo/lib/clang/version
735          P.eraseComponent();  // Remove clang from foo/lib/clang
736
737          // Get foo/lib/c++/v1
738          P.appendComponent("c++");
739          P.appendComponent("v1");
740          AddPath(P.str(), CXXSystem, true, false, false, true);
741        }
742      }
743
744      AddPath("/usr/include/c++/v1", CXXSystem, true, false, false);
745    } else {
746      AddDefaultCPlusPlusIncludePaths(triple, HSOpts);
747    }
748  }
749
750  AddDefaultCIncludePaths(triple, HSOpts);
751
752  // Add the default framework include paths on Darwin.
753  if (HSOpts.UseStandardSystemIncludes) {
754    if (triple.isOSDarwin()) {
755      AddPath("/System/Library/Frameworks", System, true, false, true);
756      AddPath("/Library/Frameworks", System, true, false, true);
757    }
758  }
759}
760
761/// RemoveDuplicates - If there are duplicate directory entries in the specified
762/// search list, remove the later (dead) ones.  Returns the number of non-system
763/// headers removed, which is used to update NumAngled.
764static unsigned RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
765                                 unsigned First, bool Verbose) {
766  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
767  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
768  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
769  unsigned NonSystemRemoved = 0;
770  for (unsigned i = First; i != SearchList.size(); ++i) {
771    unsigned DirToRemove = i;
772
773    const DirectoryLookup &CurEntry = SearchList[i];
774
775    if (CurEntry.isNormalDir()) {
776      // If this isn't the first time we've seen this dir, remove it.
777      if (SeenDirs.insert(CurEntry.getDir()))
778        continue;
779    } else if (CurEntry.isFramework()) {
780      // If this isn't the first time we've seen this framework dir, remove it.
781      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
782        continue;
783    } else {
784      assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
785      // If this isn't the first time we've seen this headermap, remove it.
786      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
787        continue;
788    }
789
790    // If we have a normal #include dir/framework/headermap that is shadowed
791    // later in the chain by a system include location, we actually want to
792    // ignore the user's request and drop the user dir... keeping the system
793    // dir.  This is weird, but required to emulate GCC's search path correctly.
794    //
795    // Since dupes of system dirs are rare, just rescan to find the original
796    // that we're nuking instead of using a DenseMap.
797    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
798      // Find the dir that this is the same of.
799      unsigned FirstDir;
800      for (FirstDir = 0; ; ++FirstDir) {
801        assert(FirstDir != i && "Didn't find dupe?");
802
803        const DirectoryLookup &SearchEntry = SearchList[FirstDir];
804
805        // If these are different lookup types, then they can't be the dupe.
806        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
807          continue;
808
809        bool isSame;
810        if (CurEntry.isNormalDir())
811          isSame = SearchEntry.getDir() == CurEntry.getDir();
812        else if (CurEntry.isFramework())
813          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
814        else {
815          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
816          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
817        }
818
819        if (isSame)
820          break;
821      }
822
823      // If the first dir in the search path is a non-system dir, zap it
824      // instead of the system one.
825      if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
826        DirToRemove = FirstDir;
827    }
828
829    if (Verbose) {
830      llvm::errs() << "ignoring duplicate directory \""
831                   << CurEntry.getName() << "\"\n";
832      if (DirToRemove != i)
833        llvm::errs() << "  as it is a non-system directory that duplicates "
834                     << "a system directory\n";
835    }
836    if (DirToRemove != i)
837      ++NonSystemRemoved;
838
839    // This is reached if the current entry is a duplicate.  Remove the
840    // DirToRemove (usually the current dir).
841    SearchList.erase(SearchList.begin()+DirToRemove);
842    --i;
843  }
844  return NonSystemRemoved;
845}
846
847
848void InitHeaderSearch::Realize(const LangOptions &Lang) {
849  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
850  std::vector<DirectoryLookup> SearchList;
851  SearchList.reserve(IncludePath.size());
852
853  // Quoted arguments go first.
854  for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
855       it != ie; ++it) {
856    if (it->first == Quoted)
857      SearchList.push_back(it->second);
858  }
859  // Deduplicate and remember index.
860  RemoveDuplicates(SearchList, 0, Verbose);
861  unsigned NumQuoted = SearchList.size();
862
863  for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
864       it != ie; ++it) {
865    if (it->first == Angled || it->first == IndexHeaderMap)
866      SearchList.push_back(it->second);
867  }
868
869  RemoveDuplicates(SearchList, NumQuoted, Verbose);
870  unsigned NumAngled = SearchList.size();
871
872  for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
873       it != ie; ++it) {
874    if (it->first == System ||
875        (!Lang.ObjC1 && !Lang.CPlusPlus && it->first == CSystem)    ||
876        (/*FIXME !Lang.ObjC1 && */Lang.CPlusPlus  && it->first == CXXSystem)  ||
877        (Lang.ObjC1  && !Lang.CPlusPlus && it->first == ObjCSystem) ||
878        (Lang.ObjC1  && Lang.CPlusPlus  && it->first == ObjCXXSystem))
879      SearchList.push_back(it->second);
880  }
881
882  for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
883       it != ie; ++it) {
884    if (it->first == After)
885      SearchList.push_back(it->second);
886  }
887
888  // Remove duplicates across both the Angled and System directories.  GCC does
889  // this and failing to remove duplicates across these two groups breaks
890  // #include_next.
891  unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
892  NumAngled -= NonSystemRemoved;
893
894  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
895  Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir);
896
897  // If verbose, print the list of directories that will be searched.
898  if (Verbose) {
899    llvm::errs() << "#include \"...\" search starts here:\n";
900    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
901      if (i == NumQuoted)
902        llvm::errs() << "#include <...> search starts here:\n";
903      const char *Name = SearchList[i].getName();
904      const char *Suffix;
905      if (SearchList[i].isNormalDir())
906        Suffix = "";
907      else if (SearchList[i].isFramework())
908        Suffix = " (framework directory)";
909      else {
910        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
911        Suffix = " (headermap)";
912      }
913      llvm::errs() << " " << Name << Suffix << "\n";
914    }
915    llvm::errs() << "End of search list.\n";
916  }
917}
918
919void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
920                                     const HeaderSearchOptions &HSOpts,
921                                     const LangOptions &Lang,
922                                     const llvm::Triple &Triple) {
923  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
924
925  // Add the user defined entries.
926  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
927    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
928    Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
929                 E.IgnoreSysRoot);
930  }
931
932  Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
933
934  Init.Realize(Lang);
935}
936