xref: /freebsd/contrib/llvm-project/clang/lib/Lex/InitHeaderSearch.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
104eeddc0SDimitry Andric //===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
204eeddc0SDimitry Andric //
304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604eeddc0SDimitry Andric //
704eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
804eeddc0SDimitry Andric //
904eeddc0SDimitry Andric // This file implements the InitHeaderSearch class.
1004eeddc0SDimitry Andric //
1104eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
1204eeddc0SDimitry Andric 
1304eeddc0SDimitry Andric #include "clang/Basic/DiagnosticFrontend.h"
1404eeddc0SDimitry Andric #include "clang/Basic/FileManager.h"
1504eeddc0SDimitry Andric #include "clang/Basic/LangOptions.h"
1604eeddc0SDimitry Andric #include "clang/Config/config.h" // C_INCLUDE_DIRS
1704eeddc0SDimitry Andric #include "clang/Lex/HeaderMap.h"
1804eeddc0SDimitry Andric #include "clang/Lex/HeaderSearch.h"
1904eeddc0SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
2004eeddc0SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
2104eeddc0SDimitry Andric #include "llvm/ADT/SmallString.h"
2204eeddc0SDimitry Andric #include "llvm/ADT/SmallVector.h"
2304eeddc0SDimitry Andric #include "llvm/ADT/StringExtras.h"
2404eeddc0SDimitry Andric #include "llvm/ADT/Triple.h"
2504eeddc0SDimitry Andric #include "llvm/ADT/Twine.h"
2604eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h"
2704eeddc0SDimitry Andric #include "llvm/Support/Path.h"
2804eeddc0SDimitry Andric #include "llvm/Support/raw_ostream.h"
29*bdd1243dSDimitry Andric #include <optional>
3004eeddc0SDimitry Andric 
3104eeddc0SDimitry Andric using namespace clang;
3204eeddc0SDimitry Andric using namespace clang::frontend;
3304eeddc0SDimitry Andric 
3404eeddc0SDimitry Andric namespace {
3504eeddc0SDimitry Andric /// Holds information about a single DirectoryLookup object.
3604eeddc0SDimitry Andric struct DirectoryLookupInfo {
3704eeddc0SDimitry Andric   IncludeDirGroup Group;
3804eeddc0SDimitry Andric   DirectoryLookup Lookup;
39*bdd1243dSDimitry Andric   std::optional<unsigned> UserEntryIdx;
4004eeddc0SDimitry Andric 
4104eeddc0SDimitry Andric   DirectoryLookupInfo(IncludeDirGroup Group, DirectoryLookup Lookup,
42*bdd1243dSDimitry Andric                       std::optional<unsigned> UserEntryIdx)
4304eeddc0SDimitry Andric       : Group(Group), Lookup(Lookup), UserEntryIdx(UserEntryIdx) {}
4404eeddc0SDimitry Andric };
4504eeddc0SDimitry Andric 
46*bdd1243dSDimitry Andric /// This class makes it easier to set the search paths of a HeaderSearch object.
47*bdd1243dSDimitry Andric /// InitHeaderSearch stores several search path lists internally, which can be
48*bdd1243dSDimitry Andric /// sent to a HeaderSearch object in one swoop.
4904eeddc0SDimitry Andric class InitHeaderSearch {
5004eeddc0SDimitry Andric   std::vector<DirectoryLookupInfo> IncludePath;
5104eeddc0SDimitry Andric   std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
5204eeddc0SDimitry Andric   HeaderSearch &Headers;
5304eeddc0SDimitry Andric   bool Verbose;
5404eeddc0SDimitry Andric   std::string IncludeSysroot;
5504eeddc0SDimitry Andric   bool HasSysroot;
5604eeddc0SDimitry Andric 
5704eeddc0SDimitry Andric public:
5804eeddc0SDimitry Andric   InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
5904eeddc0SDimitry Andric       : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)),
6004eeddc0SDimitry Andric         HasSysroot(!(sysroot.empty() || sysroot == "/")) {}
6104eeddc0SDimitry Andric 
62*bdd1243dSDimitry Andric   /// Add the specified path to the specified group list, prefixing the sysroot
63*bdd1243dSDimitry Andric   /// if used.
6404eeddc0SDimitry Andric   /// Returns true if the path exists, false if it was ignored.
6504eeddc0SDimitry Andric   bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework,
66*bdd1243dSDimitry Andric                std::optional<unsigned> UserEntryIdx = std::nullopt);
6704eeddc0SDimitry Andric 
68*bdd1243dSDimitry Andric   /// Add the specified path to the specified group list, without performing any
69*bdd1243dSDimitry Andric   /// sysroot remapping.
7004eeddc0SDimitry Andric   /// Returns true if the path exists, false if it was ignored.
7104eeddc0SDimitry Andric   bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
7204eeddc0SDimitry Andric                        bool isFramework,
73*bdd1243dSDimitry Andric                        std::optional<unsigned> UserEntryIdx = std::nullopt);
7404eeddc0SDimitry Andric 
75*bdd1243dSDimitry Andric   /// Add the specified prefix to the system header prefix list.
7604eeddc0SDimitry Andric   void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
7704eeddc0SDimitry Andric     SystemHeaderPrefixes.emplace_back(std::string(Prefix), IsSystemHeader);
7804eeddc0SDimitry Andric   }
7904eeddc0SDimitry Andric 
80*bdd1243dSDimitry Andric   /// Add the necessary paths to support a gnu libstdc++.
8104eeddc0SDimitry Andric   /// Returns true if the \p Base path was found, false if it does not exist.
8204eeddc0SDimitry Andric   bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir,
8304eeddc0SDimitry Andric                                    StringRef Dir32, StringRef Dir64,
8404eeddc0SDimitry Andric                                    const llvm::Triple &triple);
8504eeddc0SDimitry Andric 
86*bdd1243dSDimitry Andric   /// Add the necessary paths to support a MinGW libstdc++.
8704eeddc0SDimitry Andric   void AddMinGWCPlusPlusIncludePaths(StringRef Base,
8804eeddc0SDimitry Andric                                      StringRef Arch,
8904eeddc0SDimitry Andric                                      StringRef Version);
9004eeddc0SDimitry Andric 
91*bdd1243dSDimitry Andric   /// Add paths that should always be searched.
9204eeddc0SDimitry Andric   void AddDefaultCIncludePaths(const llvm::Triple &triple,
9304eeddc0SDimitry Andric                                const HeaderSearchOptions &HSOpts);
9404eeddc0SDimitry Andric 
95*bdd1243dSDimitry Andric   /// Add paths that should be searched when compiling c++.
9604eeddc0SDimitry Andric   void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts,
9704eeddc0SDimitry Andric                                        const llvm::Triple &triple,
9804eeddc0SDimitry Andric                                        const HeaderSearchOptions &HSOpts);
9904eeddc0SDimitry Andric 
100*bdd1243dSDimitry Andric   /// Returns true iff AddDefaultIncludePaths should do anything.  If this
101*bdd1243dSDimitry Andric   /// returns false, include paths should instead be handled in the driver.
102*bdd1243dSDimitry Andric   bool ShouldAddDefaultIncludePaths(const llvm::Triple &triple);
103*bdd1243dSDimitry Andric 
104*bdd1243dSDimitry Andric   /// Adds the default system include paths so that e.g. stdio.h is found.
10504eeddc0SDimitry Andric   void AddDefaultIncludePaths(const LangOptions &Lang,
10604eeddc0SDimitry Andric                               const llvm::Triple &triple,
10704eeddc0SDimitry Andric                               const HeaderSearchOptions &HSOpts);
10804eeddc0SDimitry Andric 
109*bdd1243dSDimitry Andric   /// Merges all search path lists into one list and send it to HeaderSearch.
11004eeddc0SDimitry Andric   void Realize(const LangOptions &Lang);
11104eeddc0SDimitry Andric };
11204eeddc0SDimitry Andric 
11304eeddc0SDimitry Andric }  // end anonymous namespace.
11404eeddc0SDimitry Andric 
11504eeddc0SDimitry Andric static bool CanPrefixSysroot(StringRef Path) {
11604eeddc0SDimitry Andric #if defined(_WIN32)
11704eeddc0SDimitry Andric   return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
11804eeddc0SDimitry Andric #else
11904eeddc0SDimitry Andric   return llvm::sys::path::is_absolute(Path);
12004eeddc0SDimitry Andric #endif
12104eeddc0SDimitry Andric }
12204eeddc0SDimitry Andric 
12304eeddc0SDimitry Andric bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
12404eeddc0SDimitry Andric                                bool isFramework,
125*bdd1243dSDimitry Andric                                std::optional<unsigned> UserEntryIdx) {
12604eeddc0SDimitry Andric   // Add the path with sysroot prepended, if desired and this is a system header
12704eeddc0SDimitry Andric   // group.
12804eeddc0SDimitry Andric   if (HasSysroot) {
12904eeddc0SDimitry Andric     SmallString<256> MappedPathStorage;
13004eeddc0SDimitry Andric     StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
13104eeddc0SDimitry Andric     if (CanPrefixSysroot(MappedPathStr)) {
13204eeddc0SDimitry Andric       return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework,
13304eeddc0SDimitry Andric                              UserEntryIdx);
13404eeddc0SDimitry Andric     }
13504eeddc0SDimitry Andric   }
13604eeddc0SDimitry Andric 
13704eeddc0SDimitry Andric   return AddUnmappedPath(Path, Group, isFramework, UserEntryIdx);
13804eeddc0SDimitry Andric }
13904eeddc0SDimitry Andric 
14004eeddc0SDimitry Andric bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
14104eeddc0SDimitry Andric                                        bool isFramework,
142*bdd1243dSDimitry Andric                                        std::optional<unsigned> UserEntryIdx) {
14304eeddc0SDimitry Andric   assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
14404eeddc0SDimitry Andric 
14504eeddc0SDimitry Andric   FileManager &FM = Headers.getFileMgr();
14604eeddc0SDimitry Andric   SmallString<256> MappedPathStorage;
14704eeddc0SDimitry Andric   StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
14804eeddc0SDimitry Andric 
14904eeddc0SDimitry Andric   // If use system headers while cross-compiling, emit the warning.
15004eeddc0SDimitry Andric   if (HasSysroot && (MappedPathStr.startswith("/usr/include") ||
15104eeddc0SDimitry Andric                      MappedPathStr.startswith("/usr/local/include"))) {
15204eeddc0SDimitry Andric     Headers.getDiags().Report(diag::warn_poison_system_directories)
15304eeddc0SDimitry Andric         << MappedPathStr;
15404eeddc0SDimitry Andric   }
15504eeddc0SDimitry Andric 
15604eeddc0SDimitry Andric   // Compute the DirectoryLookup type.
15704eeddc0SDimitry Andric   SrcMgr::CharacteristicKind Type;
15804eeddc0SDimitry Andric   if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) {
15904eeddc0SDimitry Andric     Type = SrcMgr::C_User;
16004eeddc0SDimitry Andric   } else if (Group == ExternCSystem) {
16104eeddc0SDimitry Andric     Type = SrcMgr::C_ExternCSystem;
16204eeddc0SDimitry Andric   } else {
16304eeddc0SDimitry Andric     Type = SrcMgr::C_System;
16404eeddc0SDimitry Andric   }
16504eeddc0SDimitry Andric 
16604eeddc0SDimitry Andric   // If the directory exists, add it.
16704eeddc0SDimitry Andric   if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
16804eeddc0SDimitry Andric     IncludePath.emplace_back(Group, DirectoryLookup(*DE, Type, isFramework),
16904eeddc0SDimitry Andric                              UserEntryIdx);
17004eeddc0SDimitry Andric     return true;
17104eeddc0SDimitry Andric   }
17204eeddc0SDimitry Andric 
17304eeddc0SDimitry Andric   // Check to see if this is an apple-style headermap (which are not allowed to
17404eeddc0SDimitry Andric   // be frameworks).
17504eeddc0SDimitry Andric   if (!isFramework) {
17604eeddc0SDimitry Andric     if (auto FE = FM.getFile(MappedPathStr)) {
17704eeddc0SDimitry Andric       if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
17804eeddc0SDimitry Andric         // It is a headermap, add it to the search path.
17904eeddc0SDimitry Andric         IncludePath.emplace_back(
18004eeddc0SDimitry Andric             Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap),
18104eeddc0SDimitry Andric             UserEntryIdx);
18204eeddc0SDimitry Andric         return true;
18304eeddc0SDimitry Andric       }
18404eeddc0SDimitry Andric     }
18504eeddc0SDimitry Andric   }
18604eeddc0SDimitry Andric 
18704eeddc0SDimitry Andric   if (Verbose)
18804eeddc0SDimitry Andric     llvm::errs() << "ignoring nonexistent directory \""
18904eeddc0SDimitry Andric                  << MappedPathStr << "\"\n";
19004eeddc0SDimitry Andric   return false;
19104eeddc0SDimitry Andric }
19204eeddc0SDimitry Andric 
19304eeddc0SDimitry Andric bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
19404eeddc0SDimitry Andric                                                    StringRef ArchDir,
19504eeddc0SDimitry Andric                                                    StringRef Dir32,
19604eeddc0SDimitry Andric                                                    StringRef Dir64,
19704eeddc0SDimitry Andric                                                    const llvm::Triple &triple) {
19804eeddc0SDimitry Andric   // Add the base dir
19904eeddc0SDimitry Andric   bool IsBaseFound = AddPath(Base, CXXSystem, false);
20004eeddc0SDimitry Andric 
20104eeddc0SDimitry Andric   // Add the multilib dirs
20204eeddc0SDimitry Andric   llvm::Triple::ArchType arch = triple.getArch();
20304eeddc0SDimitry Andric   bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
20404eeddc0SDimitry Andric   if (is64bit)
20504eeddc0SDimitry Andric     AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, false);
20604eeddc0SDimitry Andric   else
20704eeddc0SDimitry Andric     AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, false);
20804eeddc0SDimitry Andric 
20904eeddc0SDimitry Andric   // Add the backward dir
21004eeddc0SDimitry Andric   AddPath(Base + "/backward", CXXSystem, false);
21104eeddc0SDimitry Andric   return IsBaseFound;
21204eeddc0SDimitry Andric }
21304eeddc0SDimitry Andric 
21404eeddc0SDimitry Andric void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
21504eeddc0SDimitry Andric                                                      StringRef Arch,
21604eeddc0SDimitry Andric                                                      StringRef Version) {
21704eeddc0SDimitry Andric   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
21804eeddc0SDimitry Andric           CXXSystem, false);
21904eeddc0SDimitry Andric   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
22004eeddc0SDimitry Andric           CXXSystem, false);
22104eeddc0SDimitry Andric   AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
22204eeddc0SDimitry Andric           CXXSystem, false);
22304eeddc0SDimitry Andric }
22404eeddc0SDimitry Andric 
22504eeddc0SDimitry Andric void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
22604eeddc0SDimitry Andric                                             const HeaderSearchOptions &HSOpts) {
227*bdd1243dSDimitry Andric   if (!ShouldAddDefaultIncludePaths(triple))
22804eeddc0SDimitry Andric     llvm_unreachable("Include management is handled in the driver.");
229*bdd1243dSDimitry Andric 
230*bdd1243dSDimitry Andric   llvm::Triple::OSType os = triple.getOS();
23104eeddc0SDimitry Andric 
23204eeddc0SDimitry Andric   if (HSOpts.UseStandardSystemIncludes) {
23304eeddc0SDimitry Andric     switch (os) {
23404eeddc0SDimitry Andric     case llvm::Triple::CloudABI:
23504eeddc0SDimitry Andric     case llvm::Triple::NaCl:
23604eeddc0SDimitry Andric     case llvm::Triple::PS4:
23781ad6265SDimitry Andric     case llvm::Triple::PS5:
23804eeddc0SDimitry Andric     case llvm::Triple::ELFIAMCU:
23904eeddc0SDimitry Andric       break;
24004eeddc0SDimitry Andric     case llvm::Triple::Win32:
24104eeddc0SDimitry Andric       if (triple.getEnvironment() != llvm::Triple::Cygnus)
24204eeddc0SDimitry Andric         break;
243*bdd1243dSDimitry Andric       [[fallthrough]];
24404eeddc0SDimitry Andric     default:
24504eeddc0SDimitry Andric       // FIXME: temporary hack: hard-coded paths.
24604eeddc0SDimitry Andric       AddPath("/usr/local/include", System, false);
24704eeddc0SDimitry Andric       break;
24804eeddc0SDimitry Andric     }
24904eeddc0SDimitry Andric   }
25004eeddc0SDimitry Andric 
25104eeddc0SDimitry Andric   // Builtin includes use #include_next directives and should be positioned
25204eeddc0SDimitry Andric   // just prior C include dirs.
25304eeddc0SDimitry Andric   if (HSOpts.UseBuiltinIncludes) {
25404eeddc0SDimitry Andric     // Ignore the sys root, we *always* look for clang headers relative to
25504eeddc0SDimitry Andric     // supplied path.
25604eeddc0SDimitry Andric     SmallString<128> P = StringRef(HSOpts.ResourceDir);
25704eeddc0SDimitry Andric     llvm::sys::path::append(P, "include");
25804eeddc0SDimitry Andric     AddUnmappedPath(P, ExternCSystem, false);
25904eeddc0SDimitry Andric   }
26004eeddc0SDimitry Andric 
26104eeddc0SDimitry Andric   // All remaining additions are for system include directories, early exit if
26204eeddc0SDimitry Andric   // we aren't using them.
26304eeddc0SDimitry Andric   if (!HSOpts.UseStandardSystemIncludes)
26404eeddc0SDimitry Andric     return;
26504eeddc0SDimitry Andric 
26604eeddc0SDimitry Andric   // Add dirs specified via 'configure --with-c-include-dirs'.
26704eeddc0SDimitry Andric   StringRef CIncludeDirs(C_INCLUDE_DIRS);
26804eeddc0SDimitry Andric   if (CIncludeDirs != "") {
26904eeddc0SDimitry Andric     SmallVector<StringRef, 5> dirs;
27004eeddc0SDimitry Andric     CIncludeDirs.split(dirs, ":");
27104eeddc0SDimitry Andric     for (StringRef dir : dirs)
27204eeddc0SDimitry Andric       AddPath(dir, ExternCSystem, false);
27304eeddc0SDimitry Andric     return;
27404eeddc0SDimitry Andric   }
27504eeddc0SDimitry Andric 
27604eeddc0SDimitry Andric   switch (os) {
27704eeddc0SDimitry Andric   case llvm::Triple::CloudABI: {
27804eeddc0SDimitry Andric     // <sysroot>/<triple>/include
27904eeddc0SDimitry Andric     SmallString<128> P = StringRef(HSOpts.ResourceDir);
28004eeddc0SDimitry Andric     llvm::sys::path::append(P, "../../..", triple.str(), "include");
28104eeddc0SDimitry Andric     AddPath(P, System, false);
28204eeddc0SDimitry Andric     break;
28304eeddc0SDimitry Andric   }
28404eeddc0SDimitry Andric 
28504eeddc0SDimitry Andric   case llvm::Triple::Haiku:
28604eeddc0SDimitry Andric     AddPath("/boot/system/non-packaged/develop/headers", System, false);
28704eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os", System, false);
28804eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/app", System, false);
28904eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/arch", System, false);
29004eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/device", System, false);
29104eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/drivers", System, false);
29204eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/game", System, false);
29304eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/interface", System, false);
29404eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/kernel", System, false);
29504eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/locale", System, false);
29604eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/mail", System, false);
29704eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/media", System, false);
29804eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/midi", System, false);
29904eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/midi2", System, false);
30004eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/net", System, false);
30104eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/opengl", System, false);
30204eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/storage", System, false);
30304eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/support", System, false);
30404eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/translation", System, false);
30504eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/add-ons/graphics", System, false);
30604eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/add-ons/input_server", System, false);
30704eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/add-ons/mail_daemon", System, false);
30804eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/add-ons/registrar", System, false);
30904eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/add-ons/screen_saver", System, false);
31004eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/add-ons/tracker", System, false);
31104eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/be_apps/Deskbar", System, false);
31204eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/be_apps/NetPositive", System, false);
31304eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/os/be_apps/Tracker", System, false);
31404eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/3rdparty", System, false);
31504eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/bsd", System, false);
31604eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/glibc", System, false);
31704eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers/posix", System, false);
31804eeddc0SDimitry Andric     AddPath("/boot/system/develop/headers",  System, false);
31904eeddc0SDimitry Andric     break;
32004eeddc0SDimitry Andric   case llvm::Triple::RTEMS:
32104eeddc0SDimitry Andric     break;
32204eeddc0SDimitry Andric   case llvm::Triple::Win32:
32304eeddc0SDimitry Andric     switch (triple.getEnvironment()) {
32404eeddc0SDimitry Andric     default: llvm_unreachable("Include management is handled in the driver.");
32504eeddc0SDimitry Andric     case llvm::Triple::Cygnus:
32604eeddc0SDimitry Andric       AddPath("/usr/include/w32api", System, false);
32704eeddc0SDimitry Andric       break;
32804eeddc0SDimitry Andric     case llvm::Triple::GNU:
32904eeddc0SDimitry Andric       break;
33004eeddc0SDimitry Andric     }
33104eeddc0SDimitry Andric     break;
33204eeddc0SDimitry Andric   default:
33304eeddc0SDimitry Andric     break;
33404eeddc0SDimitry Andric   }
33504eeddc0SDimitry Andric 
33604eeddc0SDimitry Andric   switch (os) {
33704eeddc0SDimitry Andric   case llvm::Triple::CloudABI:
33804eeddc0SDimitry Andric   case llvm::Triple::RTEMS:
33904eeddc0SDimitry Andric   case llvm::Triple::NaCl:
34004eeddc0SDimitry Andric   case llvm::Triple::ELFIAMCU:
34104eeddc0SDimitry Andric     break;
34281ad6265SDimitry Andric   case llvm::Triple::PS4:
34381ad6265SDimitry Andric   case llvm::Triple::PS5: {
34404eeddc0SDimitry Andric     // <isysroot> gets prepended later in AddPath().
34504eeddc0SDimitry Andric     std::string BaseSDKPath;
34604eeddc0SDimitry Andric     if (!HasSysroot) {
34781ad6265SDimitry Andric       const char *EnvVar = (os == llvm::Triple::PS4) ? "SCE_ORBIS_SDK_DIR"
34881ad6265SDimitry Andric                                                      : "SCE_PROSPERO_SDK_DIR";
34981ad6265SDimitry Andric       const char *envValue = getenv(EnvVar);
35004eeddc0SDimitry Andric       if (envValue)
35104eeddc0SDimitry Andric         BaseSDKPath = envValue;
35204eeddc0SDimitry Andric       else {
35304eeddc0SDimitry Andric         // HSOpts.ResourceDir variable contains the location of Clang's
35404eeddc0SDimitry Andric         // resource files.
35504eeddc0SDimitry Andric         // Assuming that Clang is configured for PS4 without
35604eeddc0SDimitry Andric         // --with-clang-resource-dir option, the location of Clang's resource
35704eeddc0SDimitry Andric         // files is <SDK_DIR>/host_tools/lib/clang
35804eeddc0SDimitry Andric         SmallString<128> P = StringRef(HSOpts.ResourceDir);
35904eeddc0SDimitry Andric         llvm::sys::path::append(P, "../../..");
36004eeddc0SDimitry Andric         BaseSDKPath = std::string(P.str());
36104eeddc0SDimitry Andric       }
36204eeddc0SDimitry Andric     }
36304eeddc0SDimitry Andric     AddPath(BaseSDKPath + "/target/include", System, false);
36404eeddc0SDimitry Andric     AddPath(BaseSDKPath + "/target/include_common", System, false);
36581ad6265SDimitry Andric     break;
36604eeddc0SDimitry Andric   }
36704eeddc0SDimitry Andric   default:
36804eeddc0SDimitry Andric     AddPath("/usr/include", ExternCSystem, false);
36904eeddc0SDimitry Andric     break;
37004eeddc0SDimitry Andric   }
37104eeddc0SDimitry Andric }
37204eeddc0SDimitry Andric 
37304eeddc0SDimitry Andric void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
37404eeddc0SDimitry Andric     const LangOptions &LangOpts, const llvm::Triple &triple,
37504eeddc0SDimitry Andric     const HeaderSearchOptions &HSOpts) {
376*bdd1243dSDimitry Andric   if (!ShouldAddDefaultIncludePaths(triple))
377*bdd1243dSDimitry Andric     llvm_unreachable("Include management is handled in the driver.");
378*bdd1243dSDimitry Andric 
37904eeddc0SDimitry Andric   // FIXME: temporary hack: hard-coded paths.
380*bdd1243dSDimitry Andric   llvm::Triple::OSType os = triple.getOS();
38104eeddc0SDimitry Andric   switch (os) {
38204eeddc0SDimitry Andric   case llvm::Triple::Win32:
38304eeddc0SDimitry Andric     switch (triple.getEnvironment()) {
38404eeddc0SDimitry Andric     default: llvm_unreachable("Include management is handled in the driver.");
38504eeddc0SDimitry Andric     case llvm::Triple::Cygnus:
38604eeddc0SDimitry Andric       // Cygwin-1.7
38704eeddc0SDimitry Andric       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3");
38804eeddc0SDimitry Andric       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3");
38904eeddc0SDimitry Andric       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
39004eeddc0SDimitry Andric       // g++-4 / Cygwin-1.5
39104eeddc0SDimitry Andric       AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
39204eeddc0SDimitry Andric       break;
39304eeddc0SDimitry Andric     }
39404eeddc0SDimitry Andric     break;
39504eeddc0SDimitry Andric   case llvm::Triple::DragonFly:
39604eeddc0SDimitry Andric     AddPath("/usr/include/c++/5.0", CXXSystem, false);
39704eeddc0SDimitry Andric     break;
39804eeddc0SDimitry Andric   case llvm::Triple::Minix:
39904eeddc0SDimitry Andric     AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
40004eeddc0SDimitry Andric                                 "", "", "", triple);
40104eeddc0SDimitry Andric     break;
40204eeddc0SDimitry Andric   default:
40304eeddc0SDimitry Andric     break;
40404eeddc0SDimitry Andric   }
40504eeddc0SDimitry Andric }
40604eeddc0SDimitry Andric 
407*bdd1243dSDimitry Andric bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
408*bdd1243dSDimitry Andric     const llvm::Triple &triple) {
40904eeddc0SDimitry Andric   switch (triple.getOS()) {
410*bdd1243dSDimitry Andric   case llvm::Triple::AIX:
41104eeddc0SDimitry Andric   case llvm::Triple::Emscripten:
412*bdd1243dSDimitry Andric   case llvm::Triple::FreeBSD:
413*bdd1243dSDimitry Andric   case llvm::Triple::NetBSD:
41404eeddc0SDimitry Andric   case llvm::Triple::OpenBSD:
415*bdd1243dSDimitry Andric   case llvm::Triple::Fuchsia:
416*bdd1243dSDimitry Andric   case llvm::Triple::Hurd:
417*bdd1243dSDimitry Andric   case llvm::Triple::Linux:
41804eeddc0SDimitry Andric   case llvm::Triple::Solaris:
41904eeddc0SDimitry Andric   case llvm::Triple::WASI:
420*bdd1243dSDimitry Andric     return false;
42104eeddc0SDimitry Andric 
42204eeddc0SDimitry Andric   case llvm::Triple::Win32:
42304eeddc0SDimitry Andric     if (triple.getEnvironment() != llvm::Triple::Cygnus ||
42404eeddc0SDimitry Andric         triple.isOSBinFormatMachO())
425*bdd1243dSDimitry Andric       return false;
42604eeddc0SDimitry Andric     break;
42704eeddc0SDimitry Andric 
42804eeddc0SDimitry Andric   case llvm::Triple::UnknownOS:
42904eeddc0SDimitry Andric     if (triple.isWasm())
430*bdd1243dSDimitry Andric       return false;
431*bdd1243dSDimitry Andric     break;
432*bdd1243dSDimitry Andric 
433*bdd1243dSDimitry Andric   default:
43404eeddc0SDimitry Andric     break;
43504eeddc0SDimitry Andric   }
43604eeddc0SDimitry Andric 
437*bdd1243dSDimitry Andric   return true; // Everything else uses AddDefaultIncludePaths().
438*bdd1243dSDimitry Andric }
439*bdd1243dSDimitry Andric 
440*bdd1243dSDimitry Andric void InitHeaderSearch::AddDefaultIncludePaths(
441*bdd1243dSDimitry Andric     const LangOptions &Lang, const llvm::Triple &triple,
442*bdd1243dSDimitry Andric     const HeaderSearchOptions &HSOpts) {
443*bdd1243dSDimitry Andric   // NB: This code path is going away. All of the logic is moving into the
444*bdd1243dSDimitry Andric   // driver which has the information necessary to do target-specific
445*bdd1243dSDimitry Andric   // selections of default include paths. Each target which moves there will be
446*bdd1243dSDimitry Andric   // exempted from this logic in ShouldAddDefaultIncludePaths() until we can
447*bdd1243dSDimitry Andric   // delete the entire pile of code.
448*bdd1243dSDimitry Andric   if (!ShouldAddDefaultIncludePaths(triple))
449*bdd1243dSDimitry Andric     return;
450*bdd1243dSDimitry Andric 
451*bdd1243dSDimitry Andric   // NOTE: some additional header search logic is handled in the driver for
452*bdd1243dSDimitry Andric   // Darwin.
45304eeddc0SDimitry Andric   if (triple.isOSDarwin()) {
45404eeddc0SDimitry Andric     if (HSOpts.UseStandardSystemIncludes) {
45504eeddc0SDimitry Andric       // Add the default framework include paths on Darwin.
456*bdd1243dSDimitry Andric       if (triple.isDriverKit()) {
457*bdd1243dSDimitry Andric         AddPath("/System/DriverKit/System/Library/Frameworks", System, true);
458*bdd1243dSDimitry Andric       } else {
45904eeddc0SDimitry Andric         AddPath("/System/Library/Frameworks", System, true);
46004eeddc0SDimitry Andric         AddPath("/Library/Frameworks", System, true);
46104eeddc0SDimitry Andric       }
462*bdd1243dSDimitry Andric     }
46304eeddc0SDimitry Andric     return;
46404eeddc0SDimitry Andric   }
46504eeddc0SDimitry Andric 
46604eeddc0SDimitry Andric   if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
46704eeddc0SDimitry Andric       HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
46804eeddc0SDimitry Andric     if (HSOpts.UseLibcxx) {
46904eeddc0SDimitry Andric       AddPath("/usr/include/c++/v1", CXXSystem, false);
47004eeddc0SDimitry Andric     } else {
47104eeddc0SDimitry Andric       AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
47204eeddc0SDimitry Andric     }
47304eeddc0SDimitry Andric   }
47404eeddc0SDimitry Andric 
47504eeddc0SDimitry Andric   AddDefaultCIncludePaths(triple, HSOpts);
47604eeddc0SDimitry Andric }
47704eeddc0SDimitry Andric 
478*bdd1243dSDimitry Andric /// If there are duplicate directory entries in the specified search list,
479*bdd1243dSDimitry Andric /// remove the later (dead) ones.  Returns the number of non-system headers
480*bdd1243dSDimitry Andric /// removed, which is used to update NumAngled.
48104eeddc0SDimitry Andric static unsigned RemoveDuplicates(std::vector<DirectoryLookupInfo> &SearchList,
48204eeddc0SDimitry Andric                                  unsigned First, bool Verbose) {
48304eeddc0SDimitry Andric   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
48404eeddc0SDimitry Andric   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
48504eeddc0SDimitry Andric   llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
48604eeddc0SDimitry Andric   unsigned NonSystemRemoved = 0;
48704eeddc0SDimitry Andric   for (unsigned i = First; i != SearchList.size(); ++i) {
48804eeddc0SDimitry Andric     unsigned DirToRemove = i;
48904eeddc0SDimitry Andric 
49004eeddc0SDimitry Andric     const DirectoryLookup &CurEntry = SearchList[i].Lookup;
49104eeddc0SDimitry Andric 
49204eeddc0SDimitry Andric     if (CurEntry.isNormalDir()) {
49304eeddc0SDimitry Andric       // If this isn't the first time we've seen this dir, remove it.
49404eeddc0SDimitry Andric       if (SeenDirs.insert(CurEntry.getDir()).second)
49504eeddc0SDimitry Andric         continue;
49604eeddc0SDimitry Andric     } else if (CurEntry.isFramework()) {
49704eeddc0SDimitry Andric       // If this isn't the first time we've seen this framework dir, remove it.
49804eeddc0SDimitry Andric       if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
49904eeddc0SDimitry Andric         continue;
50004eeddc0SDimitry Andric     } else {
50104eeddc0SDimitry Andric       assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
50204eeddc0SDimitry Andric       // If this isn't the first time we've seen this headermap, remove it.
50304eeddc0SDimitry Andric       if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
50404eeddc0SDimitry Andric         continue;
50504eeddc0SDimitry Andric     }
50604eeddc0SDimitry Andric 
50704eeddc0SDimitry Andric     // If we have a normal #include dir/framework/headermap that is shadowed
50804eeddc0SDimitry Andric     // later in the chain by a system include location, we actually want to
50904eeddc0SDimitry Andric     // ignore the user's request and drop the user dir... keeping the system
51004eeddc0SDimitry Andric     // dir.  This is weird, but required to emulate GCC's search path correctly.
51104eeddc0SDimitry Andric     //
51204eeddc0SDimitry Andric     // Since dupes of system dirs are rare, just rescan to find the original
51304eeddc0SDimitry Andric     // that we're nuking instead of using a DenseMap.
51404eeddc0SDimitry Andric     if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
51504eeddc0SDimitry Andric       // Find the dir that this is the same of.
51604eeddc0SDimitry Andric       unsigned FirstDir;
51704eeddc0SDimitry Andric       for (FirstDir = First;; ++FirstDir) {
51804eeddc0SDimitry Andric         assert(FirstDir != i && "Didn't find dupe?");
51904eeddc0SDimitry Andric 
52004eeddc0SDimitry Andric         const DirectoryLookup &SearchEntry = SearchList[FirstDir].Lookup;
52104eeddc0SDimitry Andric 
52204eeddc0SDimitry Andric         // If these are different lookup types, then they can't be the dupe.
52304eeddc0SDimitry Andric         if (SearchEntry.getLookupType() != CurEntry.getLookupType())
52404eeddc0SDimitry Andric           continue;
52504eeddc0SDimitry Andric 
52604eeddc0SDimitry Andric         bool isSame;
52704eeddc0SDimitry Andric         if (CurEntry.isNormalDir())
52804eeddc0SDimitry Andric           isSame = SearchEntry.getDir() == CurEntry.getDir();
52904eeddc0SDimitry Andric         else if (CurEntry.isFramework())
53004eeddc0SDimitry Andric           isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
53104eeddc0SDimitry Andric         else {
53204eeddc0SDimitry Andric           assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
53304eeddc0SDimitry Andric           isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
53404eeddc0SDimitry Andric         }
53504eeddc0SDimitry Andric 
53604eeddc0SDimitry Andric         if (isSame)
53704eeddc0SDimitry Andric           break;
53804eeddc0SDimitry Andric       }
53904eeddc0SDimitry Andric 
54004eeddc0SDimitry Andric       // If the first dir in the search path is a non-system dir, zap it
54104eeddc0SDimitry Andric       // instead of the system one.
54204eeddc0SDimitry Andric       if (SearchList[FirstDir].Lookup.getDirCharacteristic() == SrcMgr::C_User)
54304eeddc0SDimitry Andric         DirToRemove = FirstDir;
54404eeddc0SDimitry Andric     }
54504eeddc0SDimitry Andric 
54604eeddc0SDimitry Andric     if (Verbose) {
54704eeddc0SDimitry Andric       llvm::errs() << "ignoring duplicate directory \""
54804eeddc0SDimitry Andric                    << CurEntry.getName() << "\"\n";
54904eeddc0SDimitry Andric       if (DirToRemove != i)
55004eeddc0SDimitry Andric         llvm::errs() << "  as it is a non-system directory that duplicates "
55104eeddc0SDimitry Andric                      << "a system directory\n";
55204eeddc0SDimitry Andric     }
55304eeddc0SDimitry Andric     if (DirToRemove != i)
55404eeddc0SDimitry Andric       ++NonSystemRemoved;
55504eeddc0SDimitry Andric 
55604eeddc0SDimitry Andric     // This is reached if the current entry is a duplicate.  Remove the
55704eeddc0SDimitry Andric     // DirToRemove (usually the current dir).
55804eeddc0SDimitry Andric     SearchList.erase(SearchList.begin()+DirToRemove);
55904eeddc0SDimitry Andric     --i;
56004eeddc0SDimitry Andric   }
56104eeddc0SDimitry Andric   return NonSystemRemoved;
56204eeddc0SDimitry Andric }
56304eeddc0SDimitry Andric 
56404eeddc0SDimitry Andric /// Extract DirectoryLookups from DirectoryLookupInfos.
56504eeddc0SDimitry Andric static std::vector<DirectoryLookup>
56604eeddc0SDimitry Andric extractLookups(const std::vector<DirectoryLookupInfo> &Infos) {
56704eeddc0SDimitry Andric   std::vector<DirectoryLookup> Lookups;
56804eeddc0SDimitry Andric   Lookups.reserve(Infos.size());
56904eeddc0SDimitry Andric   llvm::transform(Infos, std::back_inserter(Lookups),
57004eeddc0SDimitry Andric                   [](const DirectoryLookupInfo &Info) { return Info.Lookup; });
57104eeddc0SDimitry Andric   return Lookups;
57204eeddc0SDimitry Andric }
57304eeddc0SDimitry Andric 
57404eeddc0SDimitry Andric /// Collect the mapping between indices of DirectoryLookups and UserEntries.
57504eeddc0SDimitry Andric static llvm::DenseMap<unsigned, unsigned>
57604eeddc0SDimitry Andric mapToUserEntries(const std::vector<DirectoryLookupInfo> &Infos) {
57704eeddc0SDimitry Andric   llvm::DenseMap<unsigned, unsigned> LookupsToUserEntries;
57804eeddc0SDimitry Andric   for (unsigned I = 0, E = Infos.size(); I < E; ++I) {
57904eeddc0SDimitry Andric     // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
58004eeddc0SDimitry Andric     if (Infos[I].UserEntryIdx)
58104eeddc0SDimitry Andric       LookupsToUserEntries.insert({I, *Infos[I].UserEntryIdx});
58204eeddc0SDimitry Andric   }
58304eeddc0SDimitry Andric   return LookupsToUserEntries;
58404eeddc0SDimitry Andric }
58504eeddc0SDimitry Andric 
58604eeddc0SDimitry Andric void InitHeaderSearch::Realize(const LangOptions &Lang) {
58704eeddc0SDimitry Andric   // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
58804eeddc0SDimitry Andric   std::vector<DirectoryLookupInfo> SearchList;
58904eeddc0SDimitry Andric   SearchList.reserve(IncludePath.size());
59004eeddc0SDimitry Andric 
59104eeddc0SDimitry Andric   // Quoted arguments go first.
59204eeddc0SDimitry Andric   for (auto &Include : IncludePath)
59304eeddc0SDimitry Andric     if (Include.Group == Quoted)
59404eeddc0SDimitry Andric       SearchList.push_back(Include);
59504eeddc0SDimitry Andric 
59604eeddc0SDimitry Andric   // Deduplicate and remember index.
59704eeddc0SDimitry Andric   RemoveDuplicates(SearchList, 0, Verbose);
59804eeddc0SDimitry Andric   unsigned NumQuoted = SearchList.size();
59904eeddc0SDimitry Andric 
60004eeddc0SDimitry Andric   for (auto &Include : IncludePath)
60104eeddc0SDimitry Andric     if (Include.Group == Angled || Include.Group == IndexHeaderMap)
60204eeddc0SDimitry Andric       SearchList.push_back(Include);
60304eeddc0SDimitry Andric 
60404eeddc0SDimitry Andric   RemoveDuplicates(SearchList, NumQuoted, Verbose);
60504eeddc0SDimitry Andric   unsigned NumAngled = SearchList.size();
60604eeddc0SDimitry Andric 
60704eeddc0SDimitry Andric   for (auto &Include : IncludePath)
60804eeddc0SDimitry Andric     if (Include.Group == System || Include.Group == ExternCSystem ||
60904eeddc0SDimitry Andric         (!Lang.ObjC && !Lang.CPlusPlus && Include.Group == CSystem) ||
61004eeddc0SDimitry Andric         (/*FIXME !Lang.ObjC && */ Lang.CPlusPlus &&
61104eeddc0SDimitry Andric          Include.Group == CXXSystem) ||
61204eeddc0SDimitry Andric         (Lang.ObjC && !Lang.CPlusPlus && Include.Group == ObjCSystem) ||
61304eeddc0SDimitry Andric         (Lang.ObjC && Lang.CPlusPlus && Include.Group == ObjCXXSystem))
61404eeddc0SDimitry Andric       SearchList.push_back(Include);
61504eeddc0SDimitry Andric 
61604eeddc0SDimitry Andric   for (auto &Include : IncludePath)
61704eeddc0SDimitry Andric     if (Include.Group == After)
61804eeddc0SDimitry Andric       SearchList.push_back(Include);
61904eeddc0SDimitry Andric 
62004eeddc0SDimitry Andric   // Remove duplicates across both the Angled and System directories.  GCC does
62104eeddc0SDimitry Andric   // this and failing to remove duplicates across these two groups breaks
62204eeddc0SDimitry Andric   // #include_next.
62304eeddc0SDimitry Andric   unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
62404eeddc0SDimitry Andric   NumAngled -= NonSystemRemoved;
62504eeddc0SDimitry Andric 
62604eeddc0SDimitry Andric   bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
62704eeddc0SDimitry Andric   Headers.SetSearchPaths(extractLookups(SearchList), NumQuoted, NumAngled,
62804eeddc0SDimitry Andric                          DontSearchCurDir, mapToUserEntries(SearchList));
62904eeddc0SDimitry Andric 
63004eeddc0SDimitry Andric   Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
63104eeddc0SDimitry Andric 
63204eeddc0SDimitry Andric   // If verbose, print the list of directories that will be searched.
63304eeddc0SDimitry Andric   if (Verbose) {
63404eeddc0SDimitry Andric     llvm::errs() << "#include \"...\" search starts here:\n";
63504eeddc0SDimitry Andric     for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
63604eeddc0SDimitry Andric       if (i == NumQuoted)
63704eeddc0SDimitry Andric         llvm::errs() << "#include <...> search starts here:\n";
63804eeddc0SDimitry Andric       StringRef Name = SearchList[i].Lookup.getName();
63904eeddc0SDimitry Andric       const char *Suffix;
64004eeddc0SDimitry Andric       if (SearchList[i].Lookup.isNormalDir())
64104eeddc0SDimitry Andric         Suffix = "";
64204eeddc0SDimitry Andric       else if (SearchList[i].Lookup.isFramework())
64304eeddc0SDimitry Andric         Suffix = " (framework directory)";
64404eeddc0SDimitry Andric       else {
64504eeddc0SDimitry Andric         assert(SearchList[i].Lookup.isHeaderMap() && "Unknown DirectoryLookup");
64604eeddc0SDimitry Andric         Suffix = " (headermap)";
64704eeddc0SDimitry Andric       }
64804eeddc0SDimitry Andric       llvm::errs() << " " << Name << Suffix << "\n";
64904eeddc0SDimitry Andric     }
65004eeddc0SDimitry Andric     llvm::errs() << "End of search list.\n";
65104eeddc0SDimitry Andric   }
65204eeddc0SDimitry Andric }
65304eeddc0SDimitry Andric 
65404eeddc0SDimitry Andric void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
65504eeddc0SDimitry Andric                                      const HeaderSearchOptions &HSOpts,
65604eeddc0SDimitry Andric                                      const LangOptions &Lang,
65704eeddc0SDimitry Andric                                      const llvm::Triple &Triple) {
65804eeddc0SDimitry Andric   InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
65904eeddc0SDimitry Andric 
66004eeddc0SDimitry Andric   // Add the user defined entries.
66104eeddc0SDimitry Andric   for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
66204eeddc0SDimitry Andric     const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
66304eeddc0SDimitry Andric     if (E.IgnoreSysRoot) {
66404eeddc0SDimitry Andric       Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework, i);
66504eeddc0SDimitry Andric     } else {
66604eeddc0SDimitry Andric       Init.AddPath(E.Path, E.Group, E.IsFramework, i);
66704eeddc0SDimitry Andric     }
66804eeddc0SDimitry Andric   }
66904eeddc0SDimitry Andric 
67004eeddc0SDimitry Andric   Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
67104eeddc0SDimitry Andric 
67204eeddc0SDimitry Andric   for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i)
67304eeddc0SDimitry Andric     Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
67404eeddc0SDimitry Andric                                HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
67504eeddc0SDimitry Andric 
67604eeddc0SDimitry Andric   if (HSOpts.UseBuiltinIncludes) {
67704eeddc0SDimitry Andric     // Set up the builtin include directory in the module map.
67804eeddc0SDimitry Andric     SmallString<128> P = StringRef(HSOpts.ResourceDir);
67904eeddc0SDimitry Andric     llvm::sys::path::append(P, "include");
68004eeddc0SDimitry Andric     if (auto Dir = HS.getFileMgr().getDirectory(P))
68104eeddc0SDimitry Andric       HS.getModuleMap().setBuiltinIncludeDir(*Dir);
68204eeddc0SDimitry Andric   }
68304eeddc0SDimitry Andric 
68404eeddc0SDimitry Andric   Init.Realize(Lang);
68504eeddc0SDimitry Andric }
686