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