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