clang API Documentation

InitHeaderSearch.cpp
Go to the documentation of this file.
00001 //===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the InitHeaderSearch class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Frontend/Utils.h"
00015 #include "clang/Basic/FileManager.h"
00016 #include "clang/Basic/LangOptions.h"
00017 #include "clang/Config/config.h" // C_INCLUDE_DIRS
00018 #include "clang/Lex/HeaderSearch.h"
00019 #include "clang/Lex/HeaderSearchOptions.h"
00020 #include "llvm/ADT/SmallPtrSet.h"
00021 #include "llvm/ADT/SmallString.h"
00022 #include "llvm/ADT/SmallVector.h"
00023 #include "llvm/ADT/StringExtras.h"
00024 #include "llvm/ADT/Triple.h"
00025 #include "llvm/ADT/Twine.h"
00026 #include "llvm/Support/ErrorHandling.h"
00027 #include "llvm/Support/FileSystem.h"
00028 #include "llvm/Support/Path.h"
00029 #include "llvm/Support/raw_ostream.h"
00030 
00031 using namespace clang;
00032 using namespace clang::frontend;
00033 
00034 namespace {
00035 
00036 /// InitHeaderSearch - This class makes it easier to set the search paths of
00037 ///  a HeaderSearch object. InitHeaderSearch stores several search path lists
00038 ///  internally, which can be sent to a HeaderSearch object in one swoop.
00039 class InitHeaderSearch {
00040   std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
00041   typedef std::vector<std::pair<IncludeDirGroup,
00042                       DirectoryLookup> >::const_iterator path_iterator;
00043   std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
00044   HeaderSearch &Headers;
00045   bool Verbose;
00046   std::string IncludeSysroot;
00047   bool HasSysroot;
00048 
00049 public:
00050 
00051   InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
00052     : Headers(HS), Verbose(verbose), IncludeSysroot(sysroot),
00053       HasSysroot(!(sysroot.empty() || sysroot == "/")) {
00054   }
00055 
00056   /// AddPath - Add the specified path to the specified group list, prefixing
00057   /// the sysroot if used.
00058   void AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework);
00059 
00060   /// AddUnmappedPath - Add the specified path to the specified group list,
00061   /// without performing any sysroot remapping.
00062   void AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
00063                        bool isFramework);
00064 
00065   /// AddSystemHeaderPrefix - Add the specified prefix to the system header
00066   /// prefix list.
00067   void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
00068     SystemHeaderPrefixes.push_back(std::make_pair(Prefix, IsSystemHeader));
00069   }
00070 
00071   /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
00072   ///  libstdc++.
00073   void AddGnuCPlusPlusIncludePaths(StringRef Base,
00074                                    StringRef ArchDir,
00075                                    StringRef Dir32,
00076                                    StringRef Dir64,
00077                                    const llvm::Triple &triple);
00078 
00079   /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW
00080   ///  libstdc++.
00081   void AddMinGWCPlusPlusIncludePaths(StringRef Base,
00082                                      StringRef Arch,
00083                                      StringRef Version);
00084 
00085   /// AddMinGW64CXXPaths - Add the necessary paths to support
00086   /// libstdc++ of x86_64-w64-mingw32 aka mingw-w64.
00087   void AddMinGW64CXXPaths(StringRef Base,
00088                           StringRef Version);
00089 
00090   // AddDefaultCIncludePaths - Add paths that should always be searched.
00091   void AddDefaultCIncludePaths(const llvm::Triple &triple,
00092                                const HeaderSearchOptions &HSOpts);
00093 
00094   // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
00095   //  compiling c++.
00096   void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple,
00097                                        const HeaderSearchOptions &HSOpts);
00098 
00099   /// AddDefaultSystemIncludePaths - Adds the default system include paths so
00100   ///  that e.g. stdio.h is found.
00101   void AddDefaultIncludePaths(const LangOptions &Lang,
00102                               const llvm::Triple &triple,
00103                               const HeaderSearchOptions &HSOpts);
00104 
00105   /// Realize - Merges all search path lists into one list and send it to
00106   /// HeaderSearch.
00107   void Realize(const LangOptions &Lang);
00108 };
00109 
00110 }  // end anonymous namespace.
00111 
00112 static bool CanPrefixSysroot(StringRef Path) {
00113 #if defined(LLVM_ON_WIN32)
00114   return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
00115 #else
00116   return llvm::sys::path::is_absolute(Path);
00117 #endif
00118 }
00119 
00120 void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
00121                                bool isFramework) {
00122   // Add the path with sysroot prepended, if desired and this is a system header
00123   // group.
00124   if (HasSysroot) {
00125     SmallString<256> MappedPathStorage;
00126     StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
00127     if (CanPrefixSysroot(MappedPathStr)) {
00128       AddUnmappedPath(IncludeSysroot + Path, Group, isFramework);
00129       return;
00130     }
00131   }
00132 
00133   AddUnmappedPath(Path, Group, isFramework);
00134 }
00135 
00136 void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
00137                                        bool isFramework) {
00138   assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
00139 
00140   FileManager &FM = Headers.getFileMgr();
00141   SmallString<256> MappedPathStorage;
00142   StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
00143 
00144   // Compute the DirectoryLookup type.
00145   SrcMgr::CharacteristicKind Type;
00146   if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) {
00147     Type = SrcMgr::C_User;
00148   } else if (Group == ExternCSystem) {
00149     Type = SrcMgr::C_ExternCSystem;
00150   } else {
00151     Type = SrcMgr::C_System;
00152   }
00153 
00154   // If the directory exists, add it.
00155   if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
00156     IncludePath.push_back(
00157       std::make_pair(Group, DirectoryLookup(DE, Type, isFramework)));
00158     return;
00159   }
00160 
00161   // Check to see if this is an apple-style headermap (which are not allowed to
00162   // be frameworks).
00163   if (!isFramework) {
00164     if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
00165       if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
00166         // It is a headermap, add it to the search path.
00167         IncludePath.push_back(
00168           std::make_pair(Group,
00169                          DirectoryLookup(HM, Type, Group == IndexHeaderMap)));
00170         return;
00171       }
00172     }
00173   }
00174 
00175   if (Verbose)
00176     llvm::errs() << "ignoring nonexistent directory \""
00177                  << MappedPathStr << "\"\n";
00178 }
00179 
00180 void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
00181                                                    StringRef ArchDir,
00182                                                    StringRef Dir32,
00183                                                    StringRef Dir64,
00184                                                    const llvm::Triple &triple) {
00185   // Add the base dir
00186   AddPath(Base, CXXSystem, false);
00187 
00188   // Add the multilib dirs
00189   llvm::Triple::ArchType arch = triple.getArch();
00190   bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
00191   if (is64bit)
00192     AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, false);
00193   else
00194     AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, false);
00195 
00196   // Add the backward dir
00197   AddPath(Base + "/backward", CXXSystem, false);
00198 }
00199 
00200 void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
00201                                                      StringRef Arch,
00202                                                      StringRef Version) {
00203   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
00204           CXXSystem, false);
00205   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
00206           CXXSystem, false);
00207   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
00208           CXXSystem, false);
00209 }
00210 
00211 void InitHeaderSearch::AddMinGW64CXXPaths(StringRef Base,
00212                                           StringRef Version) {
00213   // Assumes Base is HeaderSearchOpts' ResourceDir
00214   AddPath(Base + "/../../../include/c++/" + Version,
00215           CXXSystem, false);
00216   AddPath(Base + "/../../../include/c++/" + Version + "/x86_64-w64-mingw32",
00217           CXXSystem, false);
00218   AddPath(Base + "/../../../include/c++/" + Version + "/i686-w64-mingw32",
00219           CXXSystem, false);
00220   AddPath(Base + "/../../../include/c++/" + Version + "/backward",
00221           CXXSystem, false);
00222 }
00223 
00224 void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
00225                                             const HeaderSearchOptions &HSOpts) {
00226   llvm::Triple::OSType os = triple.getOS();
00227 
00228   if (HSOpts.UseStandardSystemIncludes) {
00229     switch (os) {
00230     case llvm::Triple::FreeBSD:
00231     case llvm::Triple::NetBSD:
00232     case llvm::Triple::OpenBSD:
00233     case llvm::Triple::Bitrig:
00234       break;
00235     default:
00236       // FIXME: temporary hack: hard-coded paths.
00237       AddPath("/usr/local/include", System, false);
00238       break;
00239     }
00240   }
00241 
00242   // Builtin includes use #include_next directives and should be positioned
00243   // just prior C include dirs.
00244   if (HSOpts.UseBuiltinIncludes) {
00245     // Ignore the sys root, we *always* look for clang headers relative to
00246     // supplied path.
00247     SmallString<128> P = StringRef(HSOpts.ResourceDir);
00248     llvm::sys::path::append(P, "include");
00249     AddUnmappedPath(P.str(), ExternCSystem, false);
00250   }
00251 
00252   // All remaining additions are for system include directories, early exit if
00253   // we aren't using them.
00254   if (!HSOpts.UseStandardSystemIncludes)
00255     return;
00256 
00257   // Add dirs specified via 'configure --with-c-include-dirs'.
00258   StringRef CIncludeDirs(C_INCLUDE_DIRS);
00259   if (CIncludeDirs != "") {
00260     SmallVector<StringRef, 5> dirs;
00261     CIncludeDirs.split(dirs, ":");
00262     for (SmallVectorImpl<StringRef>::iterator i = dirs.begin();
00263          i != dirs.end();
00264          ++i)
00265       AddPath(*i, ExternCSystem, false);
00266     return;
00267   }
00268 
00269   switch (os) {
00270   case llvm::Triple::Linux:
00271     llvm_unreachable("Include management is handled in the driver.");
00272 
00273   case llvm::Triple::Haiku:
00274     AddPath("/boot/common/include", System, false);
00275     AddPath("/boot/develop/headers/os", System, false);
00276     AddPath("/boot/develop/headers/os/app", System, false);
00277     AddPath("/boot/develop/headers/os/arch", System, false);
00278     AddPath("/boot/develop/headers/os/device", System, false);
00279     AddPath("/boot/develop/headers/os/drivers", System, false);
00280     AddPath("/boot/develop/headers/os/game", System, false);
00281     AddPath("/boot/develop/headers/os/interface", System, false);
00282     AddPath("/boot/develop/headers/os/kernel", System, false);
00283     AddPath("/boot/develop/headers/os/locale", System, false);
00284     AddPath("/boot/develop/headers/os/mail", System, false);
00285     AddPath("/boot/develop/headers/os/media", System, false);
00286     AddPath("/boot/develop/headers/os/midi", System, false);
00287     AddPath("/boot/develop/headers/os/midi2", System, false);
00288     AddPath("/boot/develop/headers/os/net", System, false);
00289     AddPath("/boot/develop/headers/os/storage", System, false);
00290     AddPath("/boot/develop/headers/os/support", System, false);
00291     AddPath("/boot/develop/headers/os/translation", System, false);
00292     AddPath("/boot/develop/headers/os/add-ons/graphics", System, false);
00293     AddPath("/boot/develop/headers/os/add-ons/input_server", System, false);
00294     AddPath("/boot/develop/headers/os/add-ons/screen_saver", System, false);
00295     AddPath("/boot/develop/headers/os/add-ons/tracker", System, false);
00296     AddPath("/boot/develop/headers/os/be_apps/Deskbar", System, false);
00297     AddPath("/boot/develop/headers/os/be_apps/NetPositive", System, false);
00298     AddPath("/boot/develop/headers/os/be_apps/Tracker", System, false);
00299     AddPath("/boot/develop/headers/cpp", System, false);
00300     AddPath("/boot/develop/headers/cpp/i586-pc-haiku", System, false);
00301     AddPath("/boot/develop/headers/3rdparty", System, false);
00302     AddPath("/boot/develop/headers/bsd", System, false);
00303     AddPath("/boot/develop/headers/glibc", System, false);
00304     AddPath("/boot/develop/headers/posix", System, false);
00305     AddPath("/boot/develop/headers",  System, false);
00306     break;
00307   case llvm::Triple::RTEMS:
00308     break;
00309   case llvm::Triple::Win32:
00310     switch (triple.getEnvironment()) {
00311     default: llvm_unreachable("Include management is handled in the driver.");
00312     case llvm::Triple::Cygnus:
00313       AddPath("/usr/include/w32api", System, false);
00314       break;
00315     case llvm::Triple::GNU:
00316       // mingw-w64 crt include paths
00317       // <sysroot>/i686-w64-mingw32/include
00318       SmallString<128> P = StringRef(HSOpts.ResourceDir);
00319       llvm::sys::path::append(P, "../../../i686-w64-mingw32/include");
00320       AddPath(P.str(), System, false);
00321 
00322       // <sysroot>/x86_64-w64-mingw32/include
00323       P.resize(HSOpts.ResourceDir.size());
00324       llvm::sys::path::append(P, "../../../x86_64-w64-mingw32/include");
00325       AddPath(P.str(), System, false);
00326 
00327       // mingw.org crt include paths
00328       // <sysroot>/include
00329       P.resize(HSOpts.ResourceDir.size());
00330       llvm::sys::path::append(P, "../../../include");
00331       AddPath(P.str(), System, false);
00332       AddPath("/mingw/include", System, false);
00333 #if defined(LLVM_ON_WIN32)
00334       AddPath("c:/mingw/include", System, false); 
00335 #endif
00336       break;
00337     }
00338     break;
00339   default:
00340     break;
00341   }
00342 
00343   if ( os != llvm::Triple::RTEMS )
00344     AddPath("/usr/include", ExternCSystem, false);
00345 }
00346 
00347 void InitHeaderSearch::
00348 AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) {
00349   llvm::Triple::OSType os = triple.getOS();
00350   // FIXME: temporary hack: hard-coded paths.
00351 
00352   if (triple.isOSDarwin()) {
00353     switch (triple.getArch()) {
00354     default: break;
00355 
00356     case llvm::Triple::ppc:
00357     case llvm::Triple::ppc64:
00358       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
00359                                   "powerpc-apple-darwin10", "", "ppc64",
00360                                   triple);
00361       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
00362                                   "powerpc-apple-darwin10", "", "ppc64",
00363                                   triple);
00364       break;
00365 
00366     case llvm::Triple::x86:
00367     case llvm::Triple::x86_64:
00368       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
00369                                   "i686-apple-darwin10", "", "x86_64", triple);
00370       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
00371                                   "i686-apple-darwin8", "", "", triple);
00372       break;
00373 
00374     case llvm::Triple::arm:
00375     case llvm::Triple::thumb:
00376       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
00377                                   "arm-apple-darwin10", "v7", "", triple);
00378       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
00379                                   "arm-apple-darwin10", "v6", "", triple);
00380       break;
00381 
00382     case llvm::Triple::aarch64:
00383       AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
00384                                   "arm64-apple-darwin10", "", "", triple);
00385       break;
00386     }
00387     return;
00388   }
00389 
00390   switch (os) {
00391   case llvm::Triple::Linux:
00392     llvm_unreachable("Include management is handled in the driver.");
00393     break;
00394   case llvm::Triple::Win32:
00395     switch (triple.getEnvironment()) {
00396     default: llvm_unreachable("Include management is handled in the driver.");
00397     case llvm::Triple::Cygnus:
00398       // Cygwin-1.7
00399       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3");
00400       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3");
00401       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
00402       // g++-4 / Cygwin-1.5
00403       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
00404       break;
00405     case llvm::Triple::GNU:
00406       // mingw-w64 C++ include paths (i686-w64-mingw32 and x86_64-w64-mingw32)
00407       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.0");
00408       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.1");
00409       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.2");
00410       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.3");
00411       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.0");
00412       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.1");
00413       AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.2");
00414       // mingw.org C++ include paths
00415 #if defined(LLVM_ON_WIN32)
00416       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.0");
00417       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.1");
00418       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.2");
00419       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.3");
00420       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.0");
00421       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.1");
00422       AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.2");
00423 #endif
00424       break;
00425     }
00426   case llvm::Triple::DragonFly:
00427     if (llvm::sys::fs::exists("/usr/lib/gcc47"))
00428       AddPath("/usr/include/c++/4.7", CXXSystem, false);
00429     else
00430       AddPath("/usr/include/c++/4.4", CXXSystem, false);
00431     break;
00432   case llvm::Triple::OpenBSD: {
00433     std::string t = triple.getTriple();
00434     if (t.substr(0, 6) == "x86_64")
00435       t.replace(0, 6, "amd64");
00436     AddGnuCPlusPlusIncludePaths("/usr/include/g++",
00437                                 t, "", "", triple);
00438     break;
00439   }
00440   case llvm::Triple::Minix:
00441     AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
00442                                 "", "", "", triple);
00443     break;
00444   case llvm::Triple::Solaris:
00445     AddGnuCPlusPlusIncludePaths("/usr/gcc/4.5/include/c++/4.5.2/",
00446                                 "i386-pc-solaris2.11", "", "", triple);
00447     break;
00448   default:
00449     break;
00450   }
00451 }
00452 
00453 void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
00454                                               const llvm::Triple &triple,
00455                                             const HeaderSearchOptions &HSOpts) {
00456   // NB: This code path is going away. All of the logic is moving into the
00457   // driver which has the information necessary to do target-specific
00458   // selections of default include paths. Each target which moves there will be
00459   // exempted from this logic here until we can delete the entire pile of code.
00460   switch (triple.getOS()) {
00461   default:
00462     break; // Everything else continues to use this routine's logic.
00463 
00464   case llvm::Triple::Linux:
00465     return;
00466 
00467   case llvm::Triple::Win32:
00468     if (triple.getEnvironment() == llvm::Triple::MSVC ||
00469         triple.getEnvironment() == llvm::Triple::Itanium ||
00470         triple.getObjectFormat() == llvm::Triple::MachO)
00471       return;
00472     break;
00473   }
00474 
00475   if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes &&
00476       HSOpts.UseStandardSystemIncludes) {
00477     if (HSOpts.UseLibcxx) {
00478       if (triple.isOSDarwin()) {
00479         // On Darwin, libc++ may be installed alongside the compiler in
00480         // include/c++/v1.
00481         if (!HSOpts.ResourceDir.empty()) {
00482           // Remove version from foo/lib/clang/version
00483           StringRef NoVer = llvm::sys::path::parent_path(HSOpts.ResourceDir);
00484           // Remove clang from foo/lib/clang
00485           StringRef Lib = llvm::sys::path::parent_path(NoVer);
00486           // Remove lib from foo/lib
00487           SmallString<128> P = llvm::sys::path::parent_path(Lib);
00488 
00489           // Get foo/include/c++/v1
00490           llvm::sys::path::append(P, "include", "c++", "v1");
00491           AddUnmappedPath(P.str(), CXXSystem, false);
00492         }
00493       }
00494       // On Solaris, include the support directory for things like xlocale and
00495       // fudged system headers.
00496       if (triple.getOS() == llvm::Triple::Solaris) 
00497         AddPath("/usr/include/c++/v1/support/solaris", CXXSystem, false);
00498       
00499       AddPath("/usr/include/c++/v1", CXXSystem, false);
00500     } else {
00501       AddDefaultCPlusPlusIncludePaths(triple, HSOpts);
00502     }
00503   }
00504 
00505   AddDefaultCIncludePaths(triple, HSOpts);
00506 
00507   // Add the default framework include paths on Darwin.
00508   if (HSOpts.UseStandardSystemIncludes) {
00509     if (triple.isOSDarwin()) {
00510       AddPath("/System/Library/Frameworks", System, true);
00511       AddPath("/Library/Frameworks", System, true);
00512     }
00513   }
00514 }
00515 
00516 /// RemoveDuplicates - If there are duplicate directory entries in the specified
00517 /// search list, remove the later (dead) ones.  Returns the number of non-system
00518 /// headers removed, which is used to update NumAngled.
00519 static unsigned RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
00520                                  unsigned First, bool Verbose) {
00521   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
00522   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
00523   llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
00524   unsigned NonSystemRemoved = 0;
00525   for (unsigned i = First; i != SearchList.size(); ++i) {
00526     unsigned DirToRemove = i;
00527 
00528     const DirectoryLookup &CurEntry = SearchList[i];
00529 
00530     if (CurEntry.isNormalDir()) {
00531       // If this isn't the first time we've seen this dir, remove it.
00532       if (SeenDirs.insert(CurEntry.getDir()))
00533         continue;
00534     } else if (CurEntry.isFramework()) {
00535       // If this isn't the first time we've seen this framework dir, remove it.
00536       if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
00537         continue;
00538     } else {
00539       assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
00540       // If this isn't the first time we've seen this headermap, remove it.
00541       if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
00542         continue;
00543     }
00544 
00545     // If we have a normal #include dir/framework/headermap that is shadowed
00546     // later in the chain by a system include location, we actually want to
00547     // ignore the user's request and drop the user dir... keeping the system
00548     // dir.  This is weird, but required to emulate GCC's search path correctly.
00549     //
00550     // Since dupes of system dirs are rare, just rescan to find the original
00551     // that we're nuking instead of using a DenseMap.
00552     if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
00553       // Find the dir that this is the same of.
00554       unsigned FirstDir;
00555       for (FirstDir = 0; ; ++FirstDir) {
00556         assert(FirstDir != i && "Didn't find dupe?");
00557 
00558         const DirectoryLookup &SearchEntry = SearchList[FirstDir];
00559 
00560         // If these are different lookup types, then they can't be the dupe.
00561         if (SearchEntry.getLookupType() != CurEntry.getLookupType())
00562           continue;
00563 
00564         bool isSame;
00565         if (CurEntry.isNormalDir())
00566           isSame = SearchEntry.getDir() == CurEntry.getDir();
00567         else if (CurEntry.isFramework())
00568           isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
00569         else {
00570           assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
00571           isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
00572         }
00573 
00574         if (isSame)
00575           break;
00576       }
00577 
00578       // If the first dir in the search path is a non-system dir, zap it
00579       // instead of the system one.
00580       if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
00581         DirToRemove = FirstDir;
00582     }
00583 
00584     if (Verbose) {
00585       llvm::errs() << "ignoring duplicate directory \""
00586                    << CurEntry.getName() << "\"\n";
00587       if (DirToRemove != i)
00588         llvm::errs() << "  as it is a non-system directory that duplicates "
00589                      << "a system directory\n";
00590     }
00591     if (DirToRemove != i)
00592       ++NonSystemRemoved;
00593 
00594     // This is reached if the current entry is a duplicate.  Remove the
00595     // DirToRemove (usually the current dir).
00596     SearchList.erase(SearchList.begin()+DirToRemove);
00597     --i;
00598   }
00599   return NonSystemRemoved;
00600 }
00601 
00602 
00603 void InitHeaderSearch::Realize(const LangOptions &Lang) {
00604   // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
00605   std::vector<DirectoryLookup> SearchList;
00606   SearchList.reserve(IncludePath.size());
00607 
00608   // Quoted arguments go first.
00609   for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
00610        it != ie; ++it) {
00611     if (it->first == Quoted)
00612       SearchList.push_back(it->second);
00613   }
00614   // Deduplicate and remember index.
00615   RemoveDuplicates(SearchList, 0, Verbose);
00616   unsigned NumQuoted = SearchList.size();
00617 
00618   for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
00619        it != ie; ++it) {
00620     if (it->first == Angled || it->first == IndexHeaderMap)
00621       SearchList.push_back(it->second);
00622   }
00623 
00624   RemoveDuplicates(SearchList, NumQuoted, Verbose);
00625   unsigned NumAngled = SearchList.size();
00626 
00627   for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
00628        it != ie; ++it) {
00629     if (it->first == System || it->first == ExternCSystem ||
00630         (!Lang.ObjC1 && !Lang.CPlusPlus && it->first == CSystem)    ||
00631         (/*FIXME !Lang.ObjC1 && */Lang.CPlusPlus  && it->first == CXXSystem)  ||
00632         (Lang.ObjC1  && !Lang.CPlusPlus && it->first == ObjCSystem) ||
00633         (Lang.ObjC1  && Lang.CPlusPlus  && it->first == ObjCXXSystem))
00634       SearchList.push_back(it->second);
00635   }
00636 
00637   for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
00638        it != ie; ++it) {
00639     if (it->first == After)
00640       SearchList.push_back(it->second);
00641   }
00642 
00643   // Remove duplicates across both the Angled and System directories.  GCC does
00644   // this and failing to remove duplicates across these two groups breaks
00645   // #include_next.
00646   unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
00647   NumAngled -= NonSystemRemoved;
00648 
00649   bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
00650   Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir);
00651 
00652   Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
00653 
00654   // If verbose, print the list of directories that will be searched.
00655   if (Verbose) {
00656     llvm::errs() << "#include \"...\" search starts here:\n";
00657     for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
00658       if (i == NumQuoted)
00659         llvm::errs() << "#include <...> search starts here:\n";
00660       const char *Name = SearchList[i].getName();
00661       const char *Suffix;
00662       if (SearchList[i].isNormalDir())
00663         Suffix = "";
00664       else if (SearchList[i].isFramework())
00665         Suffix = " (framework directory)";
00666       else {
00667         assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
00668         Suffix = " (headermap)";
00669       }
00670       llvm::errs() << " " << Name << Suffix << "\n";
00671     }
00672     llvm::errs() << "End of search list.\n";
00673   }
00674 }
00675 
00676 void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
00677                                      const HeaderSearchOptions &HSOpts,
00678                                      const LangOptions &Lang,
00679                                      const llvm::Triple &Triple) {
00680   InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
00681 
00682   // Add the user defined entries.
00683   for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
00684     const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
00685     if (E.IgnoreSysRoot) {
00686       Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework);
00687     } else {
00688       Init.AddPath(E.Path, E.Group, E.IsFramework);
00689     }
00690   }
00691 
00692   Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
00693 
00694   for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i)
00695     Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
00696                                HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
00697 
00698   if (HSOpts.UseBuiltinIncludes) {
00699     // Set up the builtin include directory in the module map.
00700     SmallString<128> P = StringRef(HSOpts.ResourceDir);
00701     llvm::sys::path::append(P, "include");
00702     if (const DirectoryEntry *Dir = HS.getFileMgr().getDirectory(P.str()))
00703       HS.getModuleMap().setBuiltinIncludeDir(Dir);
00704   }
00705 
00706   Init.Realize(Lang);
00707 }