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