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