1 //===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
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
7 //===----------------------------------------------------------------------===//
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"
31 using namespace clang
;
32 using namespace clang::frontend
;
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
;
54 std::string IncludeSysroot
;
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
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
,
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
,
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
) {
111 return !Path
.empty() && llvm::sys::path::is_separator(Path
[0]);
113 return llvm::sys::path::is_absolute(Path
);
117 bool InitHeaderSearch::AddPath(const Twine
&Path
, IncludeDirGroup Group
,
119 std::optional
<unsigned> UserEntryIdx
) {
120 // Add the path with sysroot prepended, if desired and this is a system header
123 SmallString
<256> MappedPathStorage
;
124 StringRef MappedPathStr
= Path
.toStringRef(MappedPathStorage
);
125 if (CanPrefixSysroot(MappedPathStr
)) {
126 return AddUnmappedPath(IncludeSysroot
+ Path
, Group
, isFramework
,
131 return AddUnmappedPath(Path
, Group
, isFramework
, UserEntryIdx
);
134 bool InitHeaderSearch::AddUnmappedPath(const Twine
&Path
, IncludeDirGroup Group
,
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
)
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
;
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
),
167 // Check to see if this is an apple-style headermap (which are not allowed to
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
),
182 llvm::errs() << "ignoring nonexistent directory \""
183 << MappedPathStr
<< "\"\n";
187 void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base
,
190 AddPath(Base
+ "/" + Arch
+ "/" + Version
+ "/include/c++",
192 AddPath(Base
+ "/" + Arch
+ "/" + Version
+ "/include/c++/" + Arch
,
194 AddPath(Base
+ "/" + Arch
+ "/" + Version
+ "/include/c++/backward",
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
) {
207 case llvm::Triple::Win32
:
208 if (triple
.getEnvironment() != llvm::Triple::Cygnus
)
212 // FIXME: temporary hack: hard-coded paths.
213 AddPath("/usr/local/include", System
, false);
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
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
)
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);
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);
250 case llvm::Triple::GNU
:
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();
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
:
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");
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
:
312 case llvm::Triple::Win32
:
313 if (triple
.getEnvironment() != llvm::Triple::Cygnus
||
314 triple
.isOSBinFormatMachO())
318 case llvm::Triple::UnknownOS
:
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
))
341 // NOTE: some additional header search logic is handled in the driver for
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);
349 AddPath("/System/Library/Frameworks", System
, true);
350 AddPath("/Library/Frameworks", System
, true);
356 if (Lang
.CPlusPlus
&& !Lang
.AsmPreprocessor
&&
357 HSOpts
.UseStandardCXXIncludes
&& HSOpts
.UseStandardSystemIncludes
) {
358 if (HSOpts
.UseLibcxx
) {
359 AddPath("/usr/include/c++/v1", CXXSystem
, false);
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
)
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
)
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
)
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.
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())
417 if (CurEntry
.isNormalDir())
418 isSame
= SearchEntry
.getDir() == CurEntry
.getDir();
419 else if (CurEntry
.isFramework())
420 isSame
= SearchEntry
.getFrameworkDir() == CurEntry
.getFrameworkDir();
422 assert(CurEntry
.isHeaderMap() && "Not a headermap or normal dir?");
423 isSame
= SearchEntry
.getHeaderMap() == CurEntry
.getHeaderMap();
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
;
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
)
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
);
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
; });
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
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.
524 llvm::errs() << "#include \"...\" search starts here:\n";
525 for (unsigned i
= 0, e
= SearchList
.size(); i
!= e
; ++i
) {
527 llvm::errs() << "#include <...> search starts here:\n";
528 StringRef Name
= SearchList
[i
].Lookup
.getName();
530 if (SearchList
[i
].Lookup
.isNormalDir())
532 else if (SearchList
[i
].Lookup
.isFramework())
533 Suffix
= " (framework directory)";
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
);
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
);