[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Lex / InitHeaderSearch.cpp
blob1f4c7a6d67b7f79bc2bb7ee22d2bcd4de80c99e0
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.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Basic/DiagnosticFrontend.h"
14 #include "clang/Basic/FileManager.h"
15 #include "clang/Basic/LangOptions.h"
16 #include "clang/Config/config.h" // C_INCLUDE_DIRS
17 #include "clang/Lex/HeaderMap.h"
18 #include "clang/Lex/HeaderSearch.h"
19 #include "clang/Lex/HeaderSearchOptions.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/Twine.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/Path.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/TargetParser/Triple.h"
29 #include <optional>
31 using namespace clang;
32 using namespace clang::frontend;
34 namespace {
35 /// Holds information about a single DirectoryLookup object.
36 struct DirectoryLookupInfo {
37 IncludeDirGroup Group;
38 DirectoryLookup Lookup;
39 std::optional<unsigned> UserEntryIdx;
41 DirectoryLookupInfo(IncludeDirGroup Group, DirectoryLookup Lookup,
42 std::optional<unsigned> UserEntryIdx)
43 : Group(Group), Lookup(Lookup), UserEntryIdx(UserEntryIdx) {}
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.
49 class 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;
57 public:
58 InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
59 : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)),
60 HasSysroot(!(sysroot.empty() || sysroot == "/")) {}
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);
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);
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);
80 /// Add the necessary paths to support a MinGW libstdc++.
81 void AddMinGWCPlusPlusIncludePaths(StringRef Base,
82 StringRef Arch,
83 StringRef Version);
85 /// Add paths that should always be searched.
86 void AddDefaultCIncludePaths(const llvm::Triple &triple,
87 const HeaderSearchOptions &HSOpts);
89 /// Add paths that should be searched when compiling c++.
90 void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts,
91 const llvm::Triple &triple,
92 const HeaderSearchOptions &HSOpts);
94 /// Returns true iff AddDefaultIncludePaths should do anything. If this
95 /// returns false, include paths should instead be handled in the driver.
96 bool ShouldAddDefaultIncludePaths(const llvm::Triple &triple);
98 /// Adds the default system include paths so that e.g. stdio.h is found.
99 void AddDefaultIncludePaths(const LangOptions &Lang,
100 const llvm::Triple &triple,
101 const HeaderSearchOptions &HSOpts);
103 /// Merges all search path lists into one list and send it to HeaderSearch.
104 void Realize(const LangOptions &Lang);
107 } // end anonymous namespace.
109 static bool CanPrefixSysroot(StringRef Path) {
110 #if defined(_WIN32)
111 return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
112 #else
113 return llvm::sys::path::is_absolute(Path);
114 #endif
117 bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
118 bool isFramework,
119 std::optional<unsigned> UserEntryIdx) {
120 // Add the path with sysroot prepended, if desired and this is a system header
121 // group.
122 if (HasSysroot) {
123 SmallString<256> MappedPathStorage;
124 StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
125 if (CanPrefixSysroot(MappedPathStr)) {
126 return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework,
127 UserEntryIdx);
131 return AddUnmappedPath(Path, Group, isFramework, UserEntryIdx);
134 bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
135 bool isFramework,
136 std::optional<unsigned> UserEntryIdx) {
137 assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
139 FileManager &FM = Headers.getFileMgr();
140 SmallString<256> MappedPathStorage;
141 StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
143 // If use system headers while cross-compiling, emit the warning.
144 if (HasSysroot && (MappedPathStr.startswith("/usr/include") ||
145 MappedPathStr.startswith("/usr/local/include"))) {
146 Headers.getDiags().Report(diag::warn_poison_system_directories)
147 << MappedPathStr;
150 // Compute the DirectoryLookup type.
151 SrcMgr::CharacteristicKind Type;
152 if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) {
153 Type = SrcMgr::C_User;
154 } else if (Group == ExternCSystem) {
155 Type = SrcMgr::C_ExternCSystem;
156 } else {
157 Type = SrcMgr::C_System;
160 // If the directory exists, add it.
161 if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
162 IncludePath.emplace_back(Group, DirectoryLookup(*DE, Type, isFramework),
163 UserEntryIdx);
164 return true;
167 // Check to see if this is an apple-style headermap (which are not allowed to
168 // be frameworks).
169 if (!isFramework) {
170 if (auto FE = FM.getOptionalFileRef(MappedPathStr)) {
171 if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
172 // It is a headermap, add it to the search path.
173 IncludePath.emplace_back(
174 Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap),
175 UserEntryIdx);
176 return true;
181 if (Verbose)
182 llvm::errs() << "ignoring nonexistent directory \""
183 << MappedPathStr << "\"\n";
184 return false;
187 void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
188 StringRef Arch,
189 StringRef Version) {
190 AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
191 CXXSystem, false);
192 AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
193 CXXSystem, false);
194 AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
195 CXXSystem, false);
198 void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
199 const HeaderSearchOptions &HSOpts) {
200 if (!ShouldAddDefaultIncludePaths(triple))
201 llvm_unreachable("Include management is handled in the driver.");
203 llvm::Triple::OSType os = triple.getOS();
205 if (HSOpts.UseStandardSystemIncludes) {
206 switch (os) {
207 case llvm::Triple::Win32:
208 if (triple.getEnvironment() != llvm::Triple::Cygnus)
209 break;
210 [[fallthrough]];
211 default:
212 // FIXME: temporary hack: hard-coded paths.
213 AddPath("/usr/local/include", System, false);
214 break;
218 // Builtin includes use #include_next directives and should be positioned
219 // just prior C include dirs.
220 if (HSOpts.UseBuiltinIncludes) {
221 // Ignore the sys root, we *always* look for clang headers relative to
222 // supplied path.
223 SmallString<128> P = StringRef(HSOpts.ResourceDir);
224 llvm::sys::path::append(P, "include");
225 AddUnmappedPath(P, ExternCSystem, false);
228 // All remaining additions are for system include directories, early exit if
229 // we aren't using them.
230 if (!HSOpts.UseStandardSystemIncludes)
231 return;
233 // Add dirs specified via 'configure --with-c-include-dirs'.
234 StringRef CIncludeDirs(C_INCLUDE_DIRS);
235 if (CIncludeDirs != "") {
236 SmallVector<StringRef, 5> dirs;
237 CIncludeDirs.split(dirs, ":");
238 for (StringRef dir : dirs)
239 AddPath(dir, ExternCSystem, false);
240 return;
243 switch (os) {
244 case llvm::Triple::Win32:
245 switch (triple.getEnvironment()) {
246 default: llvm_unreachable("Include management is handled in the driver.");
247 case llvm::Triple::Cygnus:
248 AddPath("/usr/include/w32api", System, false);
249 break;
250 case llvm::Triple::GNU:
251 break;
253 break;
254 default:
255 break;
258 AddPath("/usr/include", ExternCSystem, false);
261 void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
262 const LangOptions &LangOpts, const llvm::Triple &triple,
263 const HeaderSearchOptions &HSOpts) {
264 if (!ShouldAddDefaultIncludePaths(triple))
265 llvm_unreachable("Include management is handled in the driver.");
267 // FIXME: temporary hack: hard-coded paths.
268 llvm::Triple::OSType os = triple.getOS();
269 switch (os) {
270 case llvm::Triple::Win32:
271 switch (triple.getEnvironment()) {
272 default: llvm_unreachable("Include management is handled in the driver.");
273 case llvm::Triple::Cygnus:
274 // Cygwin-1.7
275 AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3");
276 AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3");
277 AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
278 // g++-4 / Cygwin-1.5
279 AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
280 break;
282 break;
283 default:
284 break;
288 bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
289 const llvm::Triple &triple) {
290 switch (triple.getOS()) {
291 case llvm::Triple::AIX:
292 case llvm::Triple::DragonFly:
293 case llvm::Triple::ELFIAMCU:
294 case llvm::Triple::Emscripten:
295 case llvm::Triple::FreeBSD:
296 case llvm::Triple::Fuchsia:
297 case llvm::Triple::Haiku:
298 case llvm::Triple::Hurd:
299 case llvm::Triple::Linux:
300 case llvm::Triple::LiteOS:
301 case llvm::Triple::NaCl:
302 case llvm::Triple::NetBSD:
303 case llvm::Triple::OpenBSD:
304 case llvm::Triple::PS4:
305 case llvm::Triple::PS5:
306 case llvm::Triple::RTEMS:
307 case llvm::Triple::Solaris:
308 case llvm::Triple::WASI:
309 case llvm::Triple::ZOS:
310 return false;
312 case llvm::Triple::Win32:
313 if (triple.getEnvironment() != llvm::Triple::Cygnus ||
314 triple.isOSBinFormatMachO())
315 return false;
316 break;
318 case llvm::Triple::UnknownOS:
319 if (triple.isWasm())
320 return false;
321 break;
323 default:
324 break;
327 return true; // Everything else uses AddDefaultIncludePaths().
330 void InitHeaderSearch::AddDefaultIncludePaths(
331 const LangOptions &Lang, const llvm::Triple &triple,
332 const HeaderSearchOptions &HSOpts) {
333 // NB: This code path is going away. All of the logic is moving into the
334 // driver which has the information necessary to do target-specific
335 // selections of default include paths. Each target which moves there will be
336 // exempted from this logic in ShouldAddDefaultIncludePaths() until we can
337 // delete the entire pile of code.
338 if (!ShouldAddDefaultIncludePaths(triple))
339 return;
341 // NOTE: some additional header search logic is handled in the driver for
342 // Darwin.
343 if (triple.isOSDarwin()) {
344 if (HSOpts.UseStandardSystemIncludes) {
345 // Add the default framework include paths on Darwin.
346 if (triple.isDriverKit()) {
347 AddPath("/System/DriverKit/System/Library/Frameworks", System, true);
348 } else {
349 AddPath("/System/Library/Frameworks", System, true);
350 AddPath("/Library/Frameworks", System, true);
353 return;
356 if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
357 HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
358 if (HSOpts.UseLibcxx) {
359 AddPath("/usr/include/c++/v1", CXXSystem, false);
360 } else {
361 AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
365 AddDefaultCIncludePaths(triple, HSOpts);
368 /// If there are duplicate directory entries in the specified search list,
369 /// remove the later (dead) ones. Returns the number of non-system headers
370 /// removed, which is used to update NumAngled.
371 static unsigned RemoveDuplicates(std::vector<DirectoryLookupInfo> &SearchList,
372 unsigned First, bool Verbose) {
373 llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
374 llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
375 llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
376 unsigned NonSystemRemoved = 0;
377 for (unsigned i = First; i != SearchList.size(); ++i) {
378 unsigned DirToRemove = i;
380 const DirectoryLookup &CurEntry = SearchList[i].Lookup;
382 if (CurEntry.isNormalDir()) {
383 // If this isn't the first time we've seen this dir, remove it.
384 if (SeenDirs.insert(CurEntry.getDir()).second)
385 continue;
386 } else if (CurEntry.isFramework()) {
387 // If this isn't the first time we've seen this framework dir, remove it.
388 if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
389 continue;
390 } else {
391 assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
392 // If this isn't the first time we've seen this headermap, remove it.
393 if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
394 continue;
397 // If we have a normal #include dir/framework/headermap that is shadowed
398 // later in the chain by a system include location, we actually want to
399 // ignore the user's request and drop the user dir... keeping the system
400 // dir. This is weird, but required to emulate GCC's search path correctly.
402 // Since dupes of system dirs are rare, just rescan to find the original
403 // that we're nuking instead of using a DenseMap.
404 if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
405 // Find the dir that this is the same of.
406 unsigned FirstDir;
407 for (FirstDir = First;; ++FirstDir) {
408 assert(FirstDir != i && "Didn't find dupe?");
410 const DirectoryLookup &SearchEntry = SearchList[FirstDir].Lookup;
412 // If these are different lookup types, then they can't be the dupe.
413 if (SearchEntry.getLookupType() != CurEntry.getLookupType())
414 continue;
416 bool isSame;
417 if (CurEntry.isNormalDir())
418 isSame = SearchEntry.getDir() == CurEntry.getDir();
419 else if (CurEntry.isFramework())
420 isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
421 else {
422 assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
423 isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
426 if (isSame)
427 break;
430 // If the first dir in the search path is a non-system dir, zap it
431 // instead of the system one.
432 if (SearchList[FirstDir].Lookup.getDirCharacteristic() == SrcMgr::C_User)
433 DirToRemove = FirstDir;
436 if (Verbose) {
437 llvm::errs() << "ignoring duplicate directory \""
438 << CurEntry.getName() << "\"\n";
439 if (DirToRemove != i)
440 llvm::errs() << " as it is a non-system directory that duplicates "
441 << "a system directory\n";
443 if (DirToRemove != i)
444 ++NonSystemRemoved;
446 // This is reached if the current entry is a duplicate. Remove the
447 // DirToRemove (usually the current dir).
448 SearchList.erase(SearchList.begin()+DirToRemove);
449 --i;
451 return NonSystemRemoved;
454 /// Extract DirectoryLookups from DirectoryLookupInfos.
455 static std::vector<DirectoryLookup>
456 extractLookups(const std::vector<DirectoryLookupInfo> &Infos) {
457 std::vector<DirectoryLookup> Lookups;
458 Lookups.reserve(Infos.size());
459 llvm::transform(Infos, std::back_inserter(Lookups),
460 [](const DirectoryLookupInfo &Info) { return Info.Lookup; });
461 return Lookups;
464 /// Collect the mapping between indices of DirectoryLookups and UserEntries.
465 static llvm::DenseMap<unsigned, unsigned>
466 mapToUserEntries(const std::vector<DirectoryLookupInfo> &Infos) {
467 llvm::DenseMap<unsigned, unsigned> LookupsToUserEntries;
468 for (unsigned I = 0, E = Infos.size(); I < E; ++I) {
469 // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
470 if (Infos[I].UserEntryIdx)
471 LookupsToUserEntries.insert({I, *Infos[I].UserEntryIdx});
473 return LookupsToUserEntries;
476 void InitHeaderSearch::Realize(const LangOptions &Lang) {
477 // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
478 std::vector<DirectoryLookupInfo> SearchList;
479 SearchList.reserve(IncludePath.size());
481 // Quoted arguments go first.
482 for (auto &Include : IncludePath)
483 if (Include.Group == Quoted)
484 SearchList.push_back(Include);
486 // Deduplicate and remember index.
487 RemoveDuplicates(SearchList, 0, Verbose);
488 unsigned NumQuoted = SearchList.size();
490 for (auto &Include : IncludePath)
491 if (Include.Group == Angled || Include.Group == IndexHeaderMap)
492 SearchList.push_back(Include);
494 RemoveDuplicates(SearchList, NumQuoted, Verbose);
495 unsigned NumAngled = SearchList.size();
497 for (auto &Include : IncludePath)
498 if (Include.Group == System || Include.Group == ExternCSystem ||
499 (!Lang.ObjC && !Lang.CPlusPlus && Include.Group == CSystem) ||
500 (/*FIXME !Lang.ObjC && */ Lang.CPlusPlus &&
501 Include.Group == CXXSystem) ||
502 (Lang.ObjC && !Lang.CPlusPlus && Include.Group == ObjCSystem) ||
503 (Lang.ObjC && Lang.CPlusPlus && Include.Group == ObjCXXSystem))
504 SearchList.push_back(Include);
506 for (auto &Include : IncludePath)
507 if (Include.Group == After)
508 SearchList.push_back(Include);
510 // Remove duplicates across both the Angled and System directories. GCC does
511 // this and failing to remove duplicates across these two groups breaks
512 // #include_next.
513 unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
514 NumAngled -= NonSystemRemoved;
516 bool DontSearchCurDir = false; // TODO: set to true if -I- is set?
517 Headers.SetSearchPaths(extractLookups(SearchList), NumQuoted, NumAngled,
518 DontSearchCurDir, mapToUserEntries(SearchList));
520 Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
522 // If verbose, print the list of directories that will be searched.
523 if (Verbose) {
524 llvm::errs() << "#include \"...\" search starts here:\n";
525 for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
526 if (i == NumQuoted)
527 llvm::errs() << "#include <...> search starts here:\n";
528 StringRef Name = SearchList[i].Lookup.getName();
529 const char *Suffix;
530 if (SearchList[i].Lookup.isNormalDir())
531 Suffix = "";
532 else if (SearchList[i].Lookup.isFramework())
533 Suffix = " (framework directory)";
534 else {
535 assert(SearchList[i].Lookup.isHeaderMap() && "Unknown DirectoryLookup");
536 Suffix = " (headermap)";
538 llvm::errs() << " " << Name << Suffix << "\n";
540 llvm::errs() << "End of search list.\n";
544 void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
545 const HeaderSearchOptions &HSOpts,
546 const LangOptions &Lang,
547 const llvm::Triple &Triple) {
548 InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
550 // Add the user defined entries.
551 for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
552 const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
553 if (E.IgnoreSysRoot) {
554 Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework, i);
555 } else {
556 Init.AddPath(E.Path, E.Group, E.IsFramework, i);
560 Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
562 for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i)
563 Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
564 HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
566 if (HSOpts.UseBuiltinIncludes) {
567 // Set up the builtin include directory in the module map.
568 SmallString<128> P = StringRef(HSOpts.ResourceDir);
569 llvm::sys::path::append(P, "include");
570 if (auto Dir = HS.getFileMgr().getOptionalDirectoryRef(P))
571 HS.getModuleMap().setBuiltinIncludeDir(*Dir);
574 Init.Realize(Lang);