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