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