Home | History | Annotate | Line # | Download | only in Frontend
InitHeaderSearch.cpp revision 1.1.1.1.4.1
      1          1.1  joerg //===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
      2          1.1  joerg //
      3          1.1  joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4          1.1  joerg // See https://llvm.org/LICENSE.txt for license information.
      5          1.1  joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6          1.1  joerg //
      7          1.1  joerg //===----------------------------------------------------------------------===//
      8          1.1  joerg //
      9          1.1  joerg // This file implements the InitHeaderSearch class.
     10          1.1  joerg //
     11          1.1  joerg //===----------------------------------------------------------------------===//
     12          1.1  joerg 
     13          1.1  joerg #include "clang/Basic/FileManager.h"
     14          1.1  joerg #include "clang/Basic/LangOptions.h"
     15          1.1  joerg #include "clang/Config/config.h" // C_INCLUDE_DIRS
     16          1.1  joerg #include "clang/Frontend/FrontendDiagnostic.h"
     17          1.1  joerg #include "clang/Frontend/Utils.h"
     18          1.1  joerg #include "clang/Lex/HeaderMap.h"
     19          1.1  joerg #include "clang/Lex/HeaderSearch.h"
     20          1.1  joerg #include "clang/Lex/HeaderSearchOptions.h"
     21          1.1  joerg #include "llvm/ADT/SmallPtrSet.h"
     22          1.1  joerg #include "llvm/ADT/SmallString.h"
     23          1.1  joerg #include "llvm/ADT/SmallVector.h"
     24          1.1  joerg #include "llvm/ADT/StringExtras.h"
     25          1.1  joerg #include "llvm/ADT/Triple.h"
     26          1.1  joerg #include "llvm/ADT/Twine.h"
     27          1.1  joerg #include "llvm/Support/ErrorHandling.h"
     28          1.1  joerg #include "llvm/Support/Path.h"
     29          1.1  joerg #include "llvm/Support/raw_ostream.h"
     30          1.1  joerg 
     31          1.1  joerg using namespace clang;
     32          1.1  joerg using namespace clang::frontend;
     33          1.1  joerg 
     34          1.1  joerg namespace {
     35          1.1  joerg 
     36          1.1  joerg /// InitHeaderSearch - This class makes it easier to set the search paths of
     37          1.1  joerg ///  a HeaderSearch object. InitHeaderSearch stores several search path lists
     38          1.1  joerg ///  internally, which can be sent to a HeaderSearch object in one swoop.
     39          1.1  joerg class InitHeaderSearch {
     40          1.1  joerg   std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
     41          1.1  joerg   typedef std::vector<std::pair<IncludeDirGroup,
     42          1.1  joerg                       DirectoryLookup> >::const_iterator path_iterator;
     43          1.1  joerg   std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
     44          1.1  joerg   HeaderSearch &Headers;
     45          1.1  joerg   bool Verbose;
     46          1.1  joerg   std::string IncludeSysroot;
     47          1.1  joerg   bool HasSysroot;
     48          1.1  joerg 
     49          1.1  joerg public:
     50          1.1  joerg   InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
     51  1.1.1.1.4.1   cjep       : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)),
     52  1.1.1.1.4.1   cjep         HasSysroot(!(sysroot.empty() || sysroot == "/")) {}
     53          1.1  joerg 
     54          1.1  joerg   /// AddPath - Add the specified path to the specified group list, prefixing
     55          1.1  joerg   /// the sysroot if used.
     56          1.1  joerg   /// Returns true if the path exists, false if it was ignored.
     57          1.1  joerg   bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework);
     58          1.1  joerg 
     59          1.1  joerg   /// AddUnmappedPath - Add the specified path to the specified group list,
     60          1.1  joerg   /// without performing any sysroot remapping.
     61          1.1  joerg   /// Returns true if the path exists, false if it was ignored.
     62          1.1  joerg   bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
     63          1.1  joerg                        bool isFramework);
     64          1.1  joerg 
     65          1.1  joerg   /// AddSystemHeaderPrefix - Add the specified prefix to the system header
     66          1.1  joerg   /// prefix list.
     67          1.1  joerg   void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
     68  1.1.1.1.4.1   cjep     SystemHeaderPrefixes.emplace_back(std::string(Prefix), IsSystemHeader);
     69          1.1  joerg   }
     70          1.1  joerg 
     71          1.1  joerg   /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
     72          1.1  joerg   ///  libstdc++.
     73          1.1  joerg   /// Returns true if the \p Base path was found, false if it does not exist.
     74          1.1  joerg   bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir,
     75          1.1  joerg                                    StringRef Dir32, StringRef Dir64,
     76          1.1  joerg                                    const llvm::Triple &triple);
     77          1.1  joerg 
     78          1.1  joerg   /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW
     79          1.1  joerg   ///  libstdc++.
     80          1.1  joerg   void AddMinGWCPlusPlusIncludePaths(StringRef Base,
     81          1.1  joerg                                      StringRef Arch,
     82          1.1  joerg                                      StringRef Version);
     83          1.1  joerg 
     84          1.1  joerg   // AddDefaultCIncludePaths - Add paths that should always be searched.
     85          1.1  joerg   void AddDefaultCIncludePaths(const llvm::Triple &triple,
     86          1.1  joerg                                const HeaderSearchOptions &HSOpts);
     87          1.1  joerg 
     88          1.1  joerg   // AddDefaultCPlusPlusIncludePaths -  Add paths that should be searched when
     89          1.1  joerg   //  compiling c++.
     90          1.1  joerg   void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts,
     91          1.1  joerg                                        const llvm::Triple &triple,
     92          1.1  joerg                                        const HeaderSearchOptions &HSOpts);
     93          1.1  joerg 
     94          1.1  joerg   /// AddDefaultSystemIncludePaths - Adds the default system include paths so
     95          1.1  joerg   ///  that e.g. stdio.h is found.
     96          1.1  joerg   void AddDefaultIncludePaths(const LangOptions &Lang,
     97          1.1  joerg                               const llvm::Triple &triple,
     98          1.1  joerg                               const HeaderSearchOptions &HSOpts);
     99          1.1  joerg 
    100          1.1  joerg   /// Realize - Merges all search path lists into one list and send it to
    101          1.1  joerg   /// HeaderSearch.
    102          1.1  joerg   void Realize(const LangOptions &Lang);
    103          1.1  joerg };
    104          1.1  joerg 
    105          1.1  joerg }  // end anonymous namespace.
    106          1.1  joerg 
    107          1.1  joerg static bool CanPrefixSysroot(StringRef Path) {
    108          1.1  joerg #if defined(_WIN32)
    109          1.1  joerg   return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
    110          1.1  joerg #else
    111          1.1  joerg   return llvm::sys::path::is_absolute(Path);
    112          1.1  joerg #endif
    113          1.1  joerg }
    114          1.1  joerg 
    115          1.1  joerg bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
    116          1.1  joerg                                bool isFramework) {
    117          1.1  joerg   // Add the path with sysroot prepended, if desired and this is a system header
    118          1.1  joerg   // group.
    119          1.1  joerg   if (HasSysroot) {
    120          1.1  joerg     SmallString<256> MappedPathStorage;
    121          1.1  joerg     StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
    122          1.1  joerg     if (CanPrefixSysroot(MappedPathStr)) {
    123          1.1  joerg       return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework);
    124          1.1  joerg     }
    125          1.1  joerg   }
    126          1.1  joerg 
    127          1.1  joerg   return AddUnmappedPath(Path, Group, isFramework);
    128          1.1  joerg }
    129          1.1  joerg 
    130          1.1  joerg bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
    131          1.1  joerg                                        bool isFramework) {
    132          1.1  joerg   assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
    133          1.1  joerg 
    134          1.1  joerg   FileManager &FM = Headers.getFileMgr();
    135          1.1  joerg   SmallString<256> MappedPathStorage;
    136          1.1  joerg   StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
    137          1.1  joerg 
    138          1.1  joerg   // If use system headers while cross-compiling, emit the warning.
    139          1.1  joerg   if (HasSysroot && (MappedPathStr.startswith("/usr/include") ||
    140          1.1  joerg                      MappedPathStr.startswith("/usr/local/include"))) {
    141          1.1  joerg     Headers.getDiags().Report(diag::warn_poison_system_directories)
    142          1.1  joerg         << MappedPathStr;
    143          1.1  joerg   }
    144          1.1  joerg 
    145          1.1  joerg   // Compute the DirectoryLookup type.
    146          1.1  joerg   SrcMgr::CharacteristicKind Type;
    147          1.1  joerg   if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) {
    148          1.1  joerg     Type = SrcMgr::C_User;
    149          1.1  joerg   } else if (Group == ExternCSystem) {
    150          1.1  joerg     Type = SrcMgr::C_ExternCSystem;
    151          1.1  joerg   } else {
    152          1.1  joerg     Type = SrcMgr::C_System;
    153          1.1  joerg   }
    154          1.1  joerg 
    155          1.1  joerg   // If the directory exists, add it.
    156          1.1  joerg   if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
    157          1.1  joerg     IncludePath.push_back(
    158          1.1  joerg       std::make_pair(Group, DirectoryLookup(*DE, Type, isFramework)));
    159          1.1  joerg     return true;
    160          1.1  joerg   }
    161          1.1  joerg 
    162          1.1  joerg   // Check to see if this is an apple-style headermap (which are not allowed to
    163          1.1  joerg   // be frameworks).
    164          1.1  joerg   if (!isFramework) {
    165          1.1  joerg     if (auto FE = FM.getFile(MappedPathStr)) {
    166          1.1  joerg       if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
    167          1.1  joerg         // It is a headermap, add it to the search path.
    168          1.1  joerg         IncludePath.push_back(
    169          1.1  joerg           std::make_pair(Group,
    170          1.1  joerg                          DirectoryLookup(HM, Type, Group == IndexHeaderMap)));
    171          1.1  joerg         return true;
    172          1.1  joerg       }
    173          1.1  joerg     }
    174          1.1  joerg   }
    175          1.1  joerg 
    176          1.1  joerg   if (Verbose)
    177          1.1  joerg     llvm::errs() << "ignoring nonexistent directory \""
    178          1.1  joerg                  << MappedPathStr << "\"\n";
    179          1.1  joerg   return false;
    180          1.1  joerg }
    181          1.1  joerg 
    182          1.1  joerg bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
    183          1.1  joerg                                                    StringRef ArchDir,
    184          1.1  joerg                                                    StringRef Dir32,
    185          1.1  joerg                                                    StringRef Dir64,
    186          1.1  joerg                                                    const llvm::Triple &triple) {
    187          1.1  joerg   // Add the base dir
    188          1.1  joerg   bool IsBaseFound = AddPath(Base, CXXSystem, false);
    189          1.1  joerg 
    190          1.1  joerg   // Add the multilib dirs
    191          1.1  joerg   llvm::Triple::ArchType arch = triple.getArch();
    192          1.1  joerg   bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
    193          1.1  joerg   if (is64bit)
    194          1.1  joerg     AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, false);
    195          1.1  joerg   else
    196          1.1  joerg     AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, false);
    197          1.1  joerg 
    198          1.1  joerg   // Add the backward dir
    199          1.1  joerg   AddPath(Base + "/backward", CXXSystem, false);
    200          1.1  joerg   return IsBaseFound;
    201          1.1  joerg }
    202          1.1  joerg 
    203          1.1  joerg void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
    204          1.1  joerg                                                      StringRef Arch,
    205          1.1  joerg                                                      StringRef Version) {
    206          1.1  joerg   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
    207          1.1  joerg           CXXSystem, false);
    208          1.1  joerg   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
    209          1.1  joerg           CXXSystem, false);
    210          1.1  joerg   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
    211          1.1  joerg           CXXSystem, false);
    212          1.1  joerg }
    213          1.1  joerg 
    214          1.1  joerg void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
    215          1.1  joerg                                             const HeaderSearchOptions &HSOpts) {
    216          1.1  joerg   llvm::Triple::OSType os = triple.getOS();
    217          1.1  joerg 
    218          1.1  joerg   if (triple.isOSDarwin()) {
    219          1.1  joerg     llvm_unreachable("Include management is handled in the driver.");
    220          1.1  joerg   }
    221          1.1  joerg 
    222          1.1  joerg   if (HSOpts.UseStandardSystemIncludes) {
    223          1.1  joerg     switch (os) {
    224          1.1  joerg     case llvm::Triple::CloudABI:
    225          1.1  joerg     case llvm::Triple::FreeBSD:
    226          1.1  joerg     case llvm::Triple::NetBSD:
    227          1.1  joerg     case llvm::Triple::OpenBSD:
    228          1.1  joerg     case llvm::Triple::NaCl:
    229          1.1  joerg     case llvm::Triple::PS4:
    230          1.1  joerg     case llvm::Triple::ELFIAMCU:
    231          1.1  joerg     case llvm::Triple::Fuchsia:
    232          1.1  joerg       break;
    233          1.1  joerg     case llvm::Triple::Win32:
    234          1.1  joerg       if (triple.getEnvironment() != llvm::Triple::Cygnus)
    235          1.1  joerg         break;
    236          1.1  joerg       LLVM_FALLTHROUGH;
    237          1.1  joerg     default:
    238          1.1  joerg       // FIXME: temporary hack: hard-coded paths.
    239          1.1  joerg       AddPath("/usr/local/include", System, false);
    240          1.1  joerg       break;
    241          1.1  joerg     }
    242          1.1  joerg   }
    243          1.1  joerg 
    244          1.1  joerg   // Builtin includes use #include_next directives and should be positioned
    245          1.1  joerg   // just prior C include dirs.
    246          1.1  joerg   if (HSOpts.UseBuiltinIncludes) {
    247          1.1  joerg     // Ignore the sys root, we *always* look for clang headers relative to
    248          1.1  joerg     // supplied path.
    249          1.1  joerg     SmallString<128> P = StringRef(HSOpts.ResourceDir);
    250          1.1  joerg     llvm::sys::path::append(P, "include");
    251          1.1  joerg     AddUnmappedPath(P, ExternCSystem, false);
    252          1.1  joerg   }
    253          1.1  joerg 
    254          1.1  joerg   // All remaining additions are for system include directories, early exit if
    255          1.1  joerg   // we aren't using them.
    256          1.1  joerg   if (!HSOpts.UseStandardSystemIncludes)
    257          1.1  joerg     return;
    258          1.1  joerg 
    259          1.1  joerg   // Add dirs specified via 'configure --with-c-include-dirs'.
    260          1.1  joerg   StringRef CIncludeDirs(C_INCLUDE_DIRS);
    261          1.1  joerg   if (CIncludeDirs != "") {
    262          1.1  joerg     SmallVector<StringRef, 5> dirs;
    263          1.1  joerg     CIncludeDirs.split(dirs, ":");
    264          1.1  joerg     for (StringRef dir : dirs)
    265          1.1  joerg       AddPath(dir, ExternCSystem, false);
    266          1.1  joerg     return;
    267          1.1  joerg   }
    268          1.1  joerg 
    269          1.1  joerg   switch (os) {
    270          1.1  joerg   case llvm::Triple::Linux:
    271          1.1  joerg   case llvm::Triple::Hurd:
    272          1.1  joerg   case llvm::Triple::Solaris:
    273  1.1.1.1.4.1   cjep   case llvm::Triple::OpenBSD:
    274          1.1  joerg     llvm_unreachable("Include management is handled in the driver.");
    275          1.1  joerg 
    276          1.1  joerg   case llvm::Triple::CloudABI: {
    277          1.1  joerg     // <sysroot>/<triple>/include
    278          1.1  joerg     SmallString<128> P = StringRef(HSOpts.ResourceDir);
    279          1.1  joerg     llvm::sys::path::append(P, "../../..", triple.str(), "include");
    280          1.1  joerg     AddPath(P, System, false);
    281          1.1  joerg     break;
    282          1.1  joerg   }
    283          1.1  joerg 
    284          1.1  joerg   case llvm::Triple::Haiku:
    285          1.1  joerg     AddPath("/boot/system/non-packaged/develop/headers", System, false);
    286          1.1  joerg     AddPath("/boot/system/develop/headers/os", System, false);
    287          1.1  joerg     AddPath("/boot/system/develop/headers/os/app", System, false);
    288          1.1  joerg     AddPath("/boot/system/develop/headers/os/arch", System, false);
    289          1.1  joerg     AddPath("/boot/system/develop/headers/os/device", System, false);
    290          1.1  joerg     AddPath("/boot/system/develop/headers/os/drivers", System, false);
    291          1.1  joerg     AddPath("/boot/system/develop/headers/os/game", System, false);
    292          1.1  joerg     AddPath("/boot/system/develop/headers/os/interface", System, false);
    293          1.1  joerg     AddPath("/boot/system/develop/headers/os/kernel", System, false);
    294          1.1  joerg     AddPath("/boot/system/develop/headers/os/locale", System, false);
    295          1.1  joerg     AddPath("/boot/system/develop/headers/os/mail", System, false);
    296          1.1  joerg     AddPath("/boot/system/develop/headers/os/media", System, false);
    297          1.1  joerg     AddPath("/boot/system/develop/headers/os/midi", System, false);
    298          1.1  joerg     AddPath("/boot/system/develop/headers/os/midi2", System, false);
    299          1.1  joerg     AddPath("/boot/system/develop/headers/os/net", System, false);
    300          1.1  joerg     AddPath("/boot/system/develop/headers/os/opengl", System, false);
    301          1.1  joerg     AddPath("/boot/system/develop/headers/os/storage", System, false);
    302          1.1  joerg     AddPath("/boot/system/develop/headers/os/support", System, false);
    303          1.1  joerg     AddPath("/boot/system/develop/headers/os/translation", System, false);
    304          1.1  joerg     AddPath("/boot/system/develop/headers/os/add-ons/graphics", System, false);
    305          1.1  joerg     AddPath("/boot/system/develop/headers/os/add-ons/input_server", System, false);
    306          1.1  joerg     AddPath("/boot/system/develop/headers/os/add-ons/mail_daemon", System, false);
    307          1.1  joerg     AddPath("/boot/system/develop/headers/os/add-ons/registrar", System, false);
    308          1.1  joerg     AddPath("/boot/system/develop/headers/os/add-ons/screen_saver", System, false);
    309          1.1  joerg     AddPath("/boot/system/develop/headers/os/add-ons/tracker", System, false);
    310          1.1  joerg     AddPath("/boot/system/develop/headers/os/be_apps/Deskbar", System, false);
    311          1.1  joerg     AddPath("/boot/system/develop/headers/os/be_apps/NetPositive", System, false);
    312          1.1  joerg     AddPath("/boot/system/develop/headers/os/be_apps/Tracker", System, false);
    313          1.1  joerg     AddPath("/boot/system/develop/headers/3rdparty", System, false);
    314          1.1  joerg     AddPath("/boot/system/develop/headers/bsd", System, false);
    315          1.1  joerg     AddPath("/boot/system/develop/headers/glibc", System, false);
    316          1.1  joerg     AddPath("/boot/system/develop/headers/posix", System, false);
    317          1.1  joerg     AddPath("/boot/system/develop/headers",  System, false);
    318          1.1  joerg     break;
    319          1.1  joerg   case llvm::Triple::RTEMS:
    320          1.1  joerg     break;
    321          1.1  joerg   case llvm::Triple::Win32:
    322          1.1  joerg     switch (triple.getEnvironment()) {
    323          1.1  joerg     default: llvm_unreachable("Include management is handled in the driver.");
    324          1.1  joerg     case llvm::Triple::Cygnus:
    325          1.1  joerg       AddPath("/usr/include/w32api", System, false);
    326          1.1  joerg       break;
    327          1.1  joerg     case llvm::Triple::GNU:
    328          1.1  joerg       break;
    329          1.1  joerg     }
    330          1.1  joerg     break;
    331          1.1  joerg   default:
    332          1.1  joerg     break;
    333          1.1  joerg   }
    334          1.1  joerg 
    335          1.1  joerg   switch (os) {
    336          1.1  joerg   case llvm::Triple::CloudABI:
    337          1.1  joerg   case llvm::Triple::RTEMS:
    338          1.1  joerg   case llvm::Triple::NaCl:
    339          1.1  joerg   case llvm::Triple::ELFIAMCU:
    340          1.1  joerg   case llvm::Triple::Fuchsia:
    341          1.1  joerg     break;
    342          1.1  joerg   case llvm::Triple::PS4: {
    343          1.1  joerg     // <isysroot> gets prepended later in AddPath().
    344          1.1  joerg     std::string BaseSDKPath = "";
    345          1.1  joerg     if (!HasSysroot) {
    346          1.1  joerg       const char *envValue = getenv("SCE_ORBIS_SDK_DIR");
    347          1.1  joerg       if (envValue)
    348          1.1  joerg         BaseSDKPath = envValue;
    349          1.1  joerg       else {
    350          1.1  joerg         // HSOpts.ResourceDir variable contains the location of Clang's
    351          1.1  joerg         // resource files.
    352          1.1  joerg         // Assuming that Clang is configured for PS4 without
    353          1.1  joerg         // --with-clang-resource-dir option, the location of Clang's resource
    354          1.1  joerg         // files is <SDK_DIR>/host_tools/lib/clang
    355          1.1  joerg         SmallString<128> P = StringRef(HSOpts.ResourceDir);
    356          1.1  joerg         llvm::sys::path::append(P, "../../..");
    357  1.1.1.1.4.1   cjep         BaseSDKPath = std::string(P.str());
    358          1.1  joerg       }
    359          1.1  joerg     }
    360          1.1  joerg     AddPath(BaseSDKPath + "/target/include", System, false);
    361          1.1  joerg     if (triple.isPS4CPU())
    362          1.1  joerg       AddPath(BaseSDKPath + "/target/include_common", System, false);
    363          1.1  joerg     LLVM_FALLTHROUGH;
    364          1.1  joerg   }
    365          1.1  joerg   default:
    366          1.1  joerg     AddPath("/usr/include", ExternCSystem, false);
    367          1.1  joerg     break;
    368          1.1  joerg   }
    369          1.1  joerg }
    370          1.1  joerg 
    371          1.1  joerg void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
    372          1.1  joerg     const LangOptions &LangOpts, const llvm::Triple &triple,
    373          1.1  joerg     const HeaderSearchOptions &HSOpts) {
    374          1.1  joerg   llvm::Triple::OSType os = triple.getOS();
    375          1.1  joerg   // FIXME: temporary hack: hard-coded paths.
    376          1.1  joerg 
    377          1.1  joerg   if (triple.isOSDarwin()) {
    378          1.1  joerg     llvm_unreachable("Include management is handled in the driver.");
    379          1.1  joerg   }
    380          1.1  joerg 
    381          1.1  joerg   switch (os) {
    382          1.1  joerg   case llvm::Triple::Linux:
    383          1.1  joerg   case llvm::Triple::Hurd:
    384          1.1  joerg   case llvm::Triple::Solaris:
    385  1.1.1.1.4.1   cjep   case llvm::Triple::AIX:
    386          1.1  joerg     llvm_unreachable("Include management is handled in the driver.");
    387          1.1  joerg     break;
    388          1.1  joerg   case llvm::Triple::Win32:
    389          1.1  joerg     switch (triple.getEnvironment()) {
    390          1.1  joerg     default: llvm_unreachable("Include management is handled in the driver.");
    391          1.1  joerg     case llvm::Triple::Cygnus:
    392          1.1  joerg       // Cygwin-1.7
    393          1.1  joerg       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3");
    394          1.1  joerg       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3");
    395          1.1  joerg       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
    396          1.1  joerg       // g++-4 / Cygwin-1.5
    397          1.1  joerg       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
    398          1.1  joerg       break;
    399          1.1  joerg     }
    400          1.1  joerg     break;
    401          1.1  joerg   case llvm::Triple::DragonFly:
    402          1.1  joerg     AddPath("/usr/include/c++/5.0", CXXSystem, false);
    403          1.1  joerg     break;
    404          1.1  joerg   case llvm::Triple::Minix:
    405          1.1  joerg     AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
    406          1.1  joerg                                 "", "", "", triple);
    407          1.1  joerg     break;
    408          1.1  joerg   default:
    409          1.1  joerg     break;
    410          1.1  joerg   }
    411          1.1  joerg }
    412          1.1  joerg 
    413          1.1  joerg void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
    414          1.1  joerg                                               const llvm::Triple &triple,
    415          1.1  joerg                                             const HeaderSearchOptions &HSOpts) {
    416          1.1  joerg   // NB: This code path is going away. All of the logic is moving into the
    417          1.1  joerg   // driver which has the information necessary to do target-specific
    418          1.1  joerg   // selections of default include paths. Each target which moves there will be
    419          1.1  joerg   // exempted from this logic here until we can delete the entire pile of code.
    420          1.1  joerg   switch (triple.getOS()) {
    421          1.1  joerg   default:
    422          1.1  joerg     break; // Everything else continues to use this routine's logic.
    423          1.1  joerg 
    424          1.1  joerg   case llvm::Triple::Emscripten:
    425          1.1  joerg   case llvm::Triple::Linux:
    426          1.1  joerg   case llvm::Triple::Hurd:
    427  1.1.1.1.4.1   cjep   case llvm::Triple::OpenBSD:
    428          1.1  joerg   case llvm::Triple::Solaris:
    429          1.1  joerg   case llvm::Triple::WASI:
    430  1.1.1.1.4.1   cjep   case llvm::Triple::AIX:
    431          1.1  joerg     return;
    432          1.1  joerg 
    433          1.1  joerg   case llvm::Triple::Win32:
    434          1.1  joerg     if (triple.getEnvironment() != llvm::Triple::Cygnus ||
    435          1.1  joerg         triple.isOSBinFormatMachO())
    436          1.1  joerg       return;
    437          1.1  joerg     break;
    438          1.1  joerg 
    439          1.1  joerg   case llvm::Triple::UnknownOS:
    440  1.1.1.1.4.1   cjep     if (triple.isWasm())
    441          1.1  joerg       return;
    442          1.1  joerg     break;
    443          1.1  joerg   }
    444          1.1  joerg 
    445          1.1  joerg   // All header search logic is handled in the Driver for Darwin.
    446          1.1  joerg   if (triple.isOSDarwin()) {
    447          1.1  joerg     if (HSOpts.UseStandardSystemIncludes) {
    448          1.1  joerg       // Add the default framework include paths on Darwin.
    449          1.1  joerg       AddPath("/System/Library/Frameworks", System, true);
    450          1.1  joerg       AddPath("/Library/Frameworks", System, true);
    451          1.1  joerg     }
    452          1.1  joerg     return;
    453          1.1  joerg   }
    454          1.1  joerg 
    455          1.1  joerg   if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
    456          1.1  joerg       HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
    457          1.1  joerg     if (HSOpts.UseLibcxx) {
    458          1.1  joerg       AddPath("/usr/include/c++/v1", CXXSystem, false);
    459          1.1  joerg     } else {
    460          1.1  joerg       AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
    461          1.1  joerg     }
    462          1.1  joerg   }
    463          1.1  joerg 
    464          1.1  joerg   AddDefaultCIncludePaths(triple, HSOpts);
    465          1.1  joerg }
    466          1.1  joerg 
    467          1.1  joerg /// RemoveDuplicates - If there are duplicate directory entries in the specified
    468          1.1  joerg /// search list, remove the later (dead) ones.  Returns the number of non-system
    469          1.1  joerg /// headers removed, which is used to update NumAngled.
    470          1.1  joerg static unsigned RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
    471          1.1  joerg                                  unsigned First, bool Verbose) {
    472          1.1  joerg   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
    473          1.1  joerg   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
    474          1.1  joerg   llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
    475          1.1  joerg   unsigned NonSystemRemoved = 0;
    476          1.1  joerg   for (unsigned i = First; i != SearchList.size(); ++i) {
    477          1.1  joerg     unsigned DirToRemove = i;
    478          1.1  joerg 
    479          1.1  joerg     const DirectoryLookup &CurEntry = SearchList[i];
    480          1.1  joerg 
    481          1.1  joerg     if (CurEntry.isNormalDir()) {
    482          1.1  joerg       // If this isn't the first time we've seen this dir, remove it.
    483          1.1  joerg       if (SeenDirs.insert(CurEntry.getDir()).second)
    484          1.1  joerg         continue;
    485          1.1  joerg     } else if (CurEntry.isFramework()) {
    486          1.1  joerg       // If this isn't the first time we've seen this framework dir, remove it.
    487          1.1  joerg       if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
    488          1.1  joerg         continue;
    489          1.1  joerg     } else {
    490          1.1  joerg       assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
    491          1.1  joerg       // If this isn't the first time we've seen this headermap, remove it.
    492          1.1  joerg       if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
    493          1.1  joerg         continue;
    494          1.1  joerg     }
    495          1.1  joerg 
    496          1.1  joerg     // If we have a normal #include dir/framework/headermap that is shadowed
    497          1.1  joerg     // later in the chain by a system include location, we actually want to
    498          1.1  joerg     // ignore the user's request and drop the user dir... keeping the system
    499          1.1  joerg     // dir.  This is weird, but required to emulate GCC's search path correctly.
    500          1.1  joerg     //
    501          1.1  joerg     // Since dupes of system dirs are rare, just rescan to find the original
    502          1.1  joerg     // that we're nuking instead of using a DenseMap.
    503          1.1  joerg     if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
    504          1.1  joerg       // Find the dir that this is the same of.
    505          1.1  joerg       unsigned FirstDir;
    506          1.1  joerg       for (FirstDir = First;; ++FirstDir) {
    507          1.1  joerg         assert(FirstDir != i && "Didn't find dupe?");
    508          1.1  joerg 
    509          1.1  joerg         const DirectoryLookup &SearchEntry = SearchList[FirstDir];
    510          1.1  joerg 
    511          1.1  joerg         // If these are different lookup types, then they can't be the dupe.
    512          1.1  joerg         if (SearchEntry.getLookupType() != CurEntry.getLookupType())
    513          1.1  joerg           continue;
    514          1.1  joerg 
    515          1.1  joerg         bool isSame;
    516          1.1  joerg         if (CurEntry.isNormalDir())
    517          1.1  joerg           isSame = SearchEntry.getDir() == CurEntry.getDir();
    518          1.1  joerg         else if (CurEntry.isFramework())
    519          1.1  joerg           isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
    520          1.1  joerg         else {
    521          1.1  joerg           assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
    522          1.1  joerg           isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
    523          1.1  joerg         }
    524          1.1  joerg 
    525          1.1  joerg         if (isSame)
    526          1.1  joerg           break;
    527          1.1  joerg       }
    528          1.1  joerg 
    529          1.1  joerg       // If the first dir in the search path is a non-system dir, zap it
    530          1.1  joerg       // instead of the system one.
    531          1.1  joerg       if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
    532          1.1  joerg         DirToRemove = FirstDir;
    533          1.1  joerg     }
    534          1.1  joerg 
    535          1.1  joerg     if (Verbose) {
    536          1.1  joerg       llvm::errs() << "ignoring duplicate directory \""
    537          1.1  joerg                    << CurEntry.getName() << "\"\n";
    538          1.1  joerg       if (DirToRemove != i)
    539          1.1  joerg         llvm::errs() << "  as it is a non-system directory that duplicates "
    540          1.1  joerg                      << "a system directory\n";
    541          1.1  joerg     }
    542          1.1  joerg     if (DirToRemove != i)
    543          1.1  joerg       ++NonSystemRemoved;
    544          1.1  joerg 
    545          1.1  joerg     // This is reached if the current entry is a duplicate.  Remove the
    546          1.1  joerg     // DirToRemove (usually the current dir).
    547          1.1  joerg     SearchList.erase(SearchList.begin()+DirToRemove);
    548          1.1  joerg     --i;
    549          1.1  joerg   }
    550          1.1  joerg   return NonSystemRemoved;
    551          1.1  joerg }
    552          1.1  joerg 
    553          1.1  joerg 
    554          1.1  joerg void InitHeaderSearch::Realize(const LangOptions &Lang) {
    555          1.1  joerg   // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
    556          1.1  joerg   std::vector<DirectoryLookup> SearchList;
    557          1.1  joerg   SearchList.reserve(IncludePath.size());
    558          1.1  joerg 
    559          1.1  joerg   // Quoted arguments go first.
    560          1.1  joerg   for (auto &Include : IncludePath)
    561          1.1  joerg     if (Include.first == Quoted)
    562          1.1  joerg       SearchList.push_back(Include.second);
    563          1.1  joerg 
    564          1.1  joerg   // Deduplicate and remember index.
    565          1.1  joerg   RemoveDuplicates(SearchList, 0, Verbose);
    566          1.1  joerg   unsigned NumQuoted = SearchList.size();
    567          1.1  joerg 
    568          1.1  joerg   for (auto &Include : IncludePath)
    569          1.1  joerg     if (Include.first == Angled || Include.first == IndexHeaderMap)
    570          1.1  joerg       SearchList.push_back(Include.second);
    571          1.1  joerg 
    572          1.1  joerg   RemoveDuplicates(SearchList, NumQuoted, Verbose);
    573          1.1  joerg   unsigned NumAngled = SearchList.size();
    574          1.1  joerg 
    575          1.1  joerg   for (auto &Include : IncludePath)
    576          1.1  joerg     if (Include.first == System || Include.first == ExternCSystem ||
    577          1.1  joerg         (!Lang.ObjC && !Lang.CPlusPlus && Include.first == CSystem) ||
    578          1.1  joerg         (/*FIXME !Lang.ObjC && */ Lang.CPlusPlus &&
    579          1.1  joerg          Include.first == CXXSystem) ||
    580          1.1  joerg         (Lang.ObjC && !Lang.CPlusPlus && Include.first == ObjCSystem) ||
    581          1.1  joerg         (Lang.ObjC && Lang.CPlusPlus && Include.first == ObjCXXSystem))
    582          1.1  joerg       SearchList.push_back(Include.second);
    583          1.1  joerg 
    584          1.1  joerg   for (auto &Include : IncludePath)
    585          1.1  joerg     if (Include.first == After)
    586          1.1  joerg       SearchList.push_back(Include.second);
    587          1.1  joerg 
    588          1.1  joerg   // Remove duplicates across both the Angled and System directories.  GCC does
    589          1.1  joerg   // this and failing to remove duplicates across these two groups breaks
    590          1.1  joerg   // #include_next.
    591          1.1  joerg   unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
    592          1.1  joerg   NumAngled -= NonSystemRemoved;
    593          1.1  joerg 
    594          1.1  joerg   bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
    595          1.1  joerg   Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir);
    596          1.1  joerg 
    597          1.1  joerg   Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
    598          1.1  joerg 
    599          1.1  joerg   // If verbose, print the list of directories that will be searched.
    600          1.1  joerg   if (Verbose) {
    601          1.1  joerg     llvm::errs() << "#include \"...\" search starts here:\n";
    602          1.1  joerg     for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
    603          1.1  joerg       if (i == NumQuoted)
    604          1.1  joerg         llvm::errs() << "#include <...> search starts here:\n";
    605          1.1  joerg       StringRef Name = SearchList[i].getName();
    606          1.1  joerg       const char *Suffix;
    607          1.1  joerg       if (SearchList[i].isNormalDir())
    608          1.1  joerg         Suffix = "";
    609          1.1  joerg       else if (SearchList[i].isFramework())
    610          1.1  joerg         Suffix = " (framework directory)";
    611          1.1  joerg       else {
    612          1.1  joerg         assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
    613          1.1  joerg         Suffix = " (headermap)";
    614          1.1  joerg       }
    615          1.1  joerg       llvm::errs() << " " << Name << Suffix << "\n";
    616          1.1  joerg     }
    617          1.1  joerg     llvm::errs() << "End of search list.\n";
    618          1.1  joerg   }
    619          1.1  joerg }
    620          1.1  joerg 
    621          1.1  joerg void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
    622          1.1  joerg                                      const HeaderSearchOptions &HSOpts,
    623          1.1  joerg                                      const LangOptions &Lang,
    624          1.1  joerg                                      const llvm::Triple &Triple) {
    625          1.1  joerg   InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
    626          1.1  joerg 
    627          1.1  joerg   // Add the user defined entries.
    628          1.1  joerg   for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
    629          1.1  joerg     const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
    630          1.1  joerg     if (E.IgnoreSysRoot) {
    631          1.1  joerg       Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework);
    632          1.1  joerg     } else {
    633          1.1  joerg       Init.AddPath(E.Path, E.Group, E.IsFramework);
    634          1.1  joerg     }
    635          1.1  joerg   }
    636          1.1  joerg 
    637          1.1  joerg   Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
    638          1.1  joerg 
    639          1.1  joerg   for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i)
    640          1.1  joerg     Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
    641          1.1  joerg                                HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
    642          1.1  joerg 
    643          1.1  joerg   if (HSOpts.UseBuiltinIncludes) {
    644          1.1  joerg     // Set up the builtin include directory in the module map.
    645          1.1  joerg     SmallString<128> P = StringRef(HSOpts.ResourceDir);
    646          1.1  joerg     llvm::sys::path::append(P, "include");
    647          1.1  joerg     if (auto Dir = HS.getFileMgr().getDirectory(P))
    648          1.1  joerg       HS.getModuleMap().setBuiltinIncludeDir(*Dir);
    649          1.1  joerg   }
    650          1.1  joerg 
    651          1.1  joerg   Init.Realize(Lang);
    652          1.1  joerg }
    653