17 #include "clang/Config/config.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/FileSystem.h"
28 #include "llvm/Support/Path.h"
29 #include "llvm/Support/raw_ostream.h"
31 using namespace clang;
32 using namespace clang::frontend;
39 class InitHeaderSearch {
40 std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
43 std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
46 std::string IncludeSysroot;
51 InitHeaderSearch(
HeaderSearch &HS,
bool verbose, StringRef sysroot)
52 : Headers(HS),
Verbose(verbose), IncludeSysroot(sysroot),
53 HasSysroot(!(sysroot.empty() || sysroot ==
"/")) {
58 void AddPath(
const Twine &Path,
IncludeDirGroup Group,
bool isFramework);
67 void AddSystemHeaderPrefix(StringRef Prefix,
bool IsSystemHeader) {
68 SystemHeaderPrefixes.emplace_back(Prefix, IsSystemHeader);
73 void AddGnuCPlusPlusIncludePaths(StringRef
Base,
77 const llvm::Triple &triple);
81 void AddMinGWCPlusPlusIncludePaths(StringRef
Base,
86 void AddDefaultCIncludePaths(
const llvm::Triple &triple,
91 void AddDefaultCPlusPlusIncludePaths(
const llvm::Triple &triple,
96 void AddDefaultIncludePaths(
const LangOptions &Lang,
97 const llvm::Triple &triple,
108 #if defined(LLVM_ON_WIN32)
109 return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
111 return llvm::sys::path::is_absolute(Path);
115 void InitHeaderSearch::AddPath(
const Twine &Path,
IncludeDirGroup Group,
121 StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
123 AddUnmappedPath(IncludeSysroot + Path, Group, isFramework);
128 AddUnmappedPath(Path, Group, isFramework);
131 void InitHeaderSearch::AddUnmappedPath(
const Twine &Path,
IncludeDirGroup Group,
133 assert(!Path.isTriviallyEmpty() &&
"can't handle empty path here");
137 StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
151 IncludePath.push_back(
159 if (
const FileEntry *FE = FM.getFile(MappedPathStr)) {
160 if (
const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
162 IncludePath.push_back(
163 std::make_pair(Group,
171 llvm::errs() <<
"ignoring nonexistent directory \""
172 << MappedPathStr <<
"\"\n";
175 void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef
Base,
179 const llvm::Triple &triple) {
184 llvm::Triple::ArchType arch = triple.getArch();
185 bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
187 AddPath(Base +
"/" + ArchDir +
"/" + Dir64,
CXXSystem,
false);
189 AddPath(Base +
"/" + ArchDir +
"/" + Dir32,
CXXSystem,
false);
192 AddPath(Base +
"/backward",
CXXSystem,
false);
195 void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
198 AddPath(Base +
"/" + Arch +
"/" + Version +
"/include/c++",
200 AddPath(Base +
"/" + Arch +
"/" + Version +
"/include/c++/" + Arch,
202 AddPath(Base +
"/" + Arch +
"/" + Version +
"/include/c++/backward",
206 void InitHeaderSearch::AddDefaultCIncludePaths(
const llvm::Triple &triple,
208 llvm::Triple::OSType os = triple.getOS();
212 case llvm::Triple::CloudABI:
213 case llvm::Triple::FreeBSD:
214 case llvm::Triple::NetBSD:
215 case llvm::Triple::OpenBSD:
216 case llvm::Triple::Bitrig:
217 case llvm::Triple::NaCl:
219 case llvm::Triple::Win32:
220 if (triple.getEnvironment() != llvm::Triple::Cygnus)
224 AddPath(
"/usr/local/include",
System,
false);
235 llvm::sys::path::append(P,
"include");
245 StringRef CIncludeDirs(C_INCLUDE_DIRS);
246 if (CIncludeDirs !=
"") {
248 CIncludeDirs.split(dirs,
":");
257 case llvm::Triple::Linux:
258 llvm_unreachable(
"Include management is handled in the driver.");
260 case llvm::Triple::CloudABI: {
263 llvm::sys::path::append(P,
"../../..", triple.str(),
"include");
264 AddPath(P,
System,
false);
268 case llvm::Triple::Haiku:
269 AddPath(
"/boot/common/include",
System,
false);
270 AddPath(
"/boot/develop/headers/os",
System,
false);
271 AddPath(
"/boot/develop/headers/os/app",
System,
false);
272 AddPath(
"/boot/develop/headers/os/arch",
System,
false);
273 AddPath(
"/boot/develop/headers/os/device",
System,
false);
274 AddPath(
"/boot/develop/headers/os/drivers",
System,
false);
275 AddPath(
"/boot/develop/headers/os/game",
System,
false);
276 AddPath(
"/boot/develop/headers/os/interface",
System,
false);
277 AddPath(
"/boot/develop/headers/os/kernel",
System,
false);
278 AddPath(
"/boot/develop/headers/os/locale",
System,
false);
279 AddPath(
"/boot/develop/headers/os/mail",
System,
false);
280 AddPath(
"/boot/develop/headers/os/media",
System,
false);
281 AddPath(
"/boot/develop/headers/os/midi",
System,
false);
282 AddPath(
"/boot/develop/headers/os/midi2",
System,
false);
283 AddPath(
"/boot/develop/headers/os/net",
System,
false);
284 AddPath(
"/boot/develop/headers/os/storage",
System,
false);
285 AddPath(
"/boot/develop/headers/os/support",
System,
false);
286 AddPath(
"/boot/develop/headers/os/translation",
System,
false);
287 AddPath(
"/boot/develop/headers/os/add-ons/graphics",
System,
false);
288 AddPath(
"/boot/develop/headers/os/add-ons/input_server",
System,
false);
289 AddPath(
"/boot/develop/headers/os/add-ons/screen_saver",
System,
false);
290 AddPath(
"/boot/develop/headers/os/add-ons/tracker",
System,
false);
291 AddPath(
"/boot/develop/headers/os/be_apps/Deskbar",
System,
false);
292 AddPath(
"/boot/develop/headers/os/be_apps/NetPositive",
System,
false);
293 AddPath(
"/boot/develop/headers/os/be_apps/Tracker",
System,
false);
294 AddPath(
"/boot/develop/headers/cpp",
System,
false);
295 AddPath(
"/boot/develop/headers/cpp/i586-pc-haiku",
System,
false);
296 AddPath(
"/boot/develop/headers/3rdparty",
System,
false);
297 AddPath(
"/boot/develop/headers/bsd",
System,
false);
298 AddPath(
"/boot/develop/headers/glibc",
System,
false);
299 AddPath(
"/boot/develop/headers/posix",
System,
false);
300 AddPath(
"/boot/develop/headers",
System,
false);
302 case llvm::Triple::RTEMS:
304 case llvm::Triple::Win32:
305 switch (triple.getEnvironment()) {
306 default: llvm_unreachable(
"Include management is handled in the driver.");
307 case llvm::Triple::Cygnus:
308 AddPath(
"/usr/include/w32api",
System,
false);
310 case llvm::Triple::GNU:
319 case llvm::Triple::CloudABI:
320 case llvm::Triple::RTEMS:
321 case llvm::Triple::NaCl:
329 void InitHeaderSearch::
330 AddDefaultCPlusPlusIncludePaths(
const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts) {
331 llvm::Triple::OSType os = triple.getOS();
334 if (triple.isOSDarwin()) {
335 switch (triple.getArch()) {
338 case llvm::Triple::ppc:
339 case llvm::Triple::ppc64:
340 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.2.1",
341 "powerpc-apple-darwin10",
"",
"ppc64",
343 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.0.0",
344 "powerpc-apple-darwin10",
"",
"ppc64",
348 case llvm::Triple::x86:
349 case llvm::Triple::x86_64:
350 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.2.1",
351 "i686-apple-darwin10",
"",
"x86_64", triple);
352 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.0.0",
353 "i686-apple-darwin8",
"",
"", triple);
356 case llvm::Triple::arm:
357 case llvm::Triple::thumb:
358 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.2.1",
359 "arm-apple-darwin10",
"v7",
"", triple);
360 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.2.1",
361 "arm-apple-darwin10",
"v6",
"", triple);
364 case llvm::Triple::aarch64:
365 AddGnuCPlusPlusIncludePaths(
"/usr/include/c++/4.2.1",
366 "arm64-apple-darwin10",
"",
"", triple);
373 case llvm::Triple::Linux:
374 llvm_unreachable(
"Include management is handled in the driver.");
376 case llvm::Triple::Win32:
377 switch (triple.getEnvironment()) {
378 default: llvm_unreachable(
"Include management is handled in the driver.");
379 case llvm::Triple::Cygnus:
381 AddMinGWCPlusPlusIncludePaths(
"/usr/lib/gcc",
"i686-pc-cygwin",
"4.7.3");
382 AddMinGWCPlusPlusIncludePaths(
"/usr/lib/gcc",
"i686-pc-cygwin",
"4.5.3");
383 AddMinGWCPlusPlusIncludePaths(
"/usr/lib/gcc",
"i686-pc-cygwin",
"4.3.4");
385 AddMinGWCPlusPlusIncludePaths(
"/usr/lib/gcc",
"i686-pc-cygwin",
"4.3.2");
389 case llvm::Triple::DragonFly:
390 if (llvm::sys::fs::exists(
"/usr/lib/gcc47"))
391 AddPath(
"/usr/include/c++/4.7",
CXXSystem,
false);
393 AddPath(
"/usr/include/c++/4.4",
CXXSystem,
false);
395 case llvm::Triple::OpenBSD: {
396 std::string t = triple.getTriple();
397 if (t.substr(0, 6) ==
"x86_64")
398 t.replace(0, 6,
"amd64");
399 AddGnuCPlusPlusIncludePaths(
"/usr/include/g++",
403 case llvm::Triple::Minix:
404 AddGnuCPlusPlusIncludePaths(
"/usr/gnu/include/c++/4.4.3",
407 case llvm::Triple::Solaris:
408 AddGnuCPlusPlusIncludePaths(
"/usr/gcc/4.5/include/c++/4.5.2/",
409 "i386-pc-solaris2.11",
"",
"", triple);
416 void InitHeaderSearch::AddDefaultIncludePaths(
const LangOptions &Lang,
417 const llvm::Triple &triple,
423 switch (triple.getOS()) {
427 case llvm::Triple::Linux:
430 case llvm::Triple::Win32:
431 if (triple.getEnvironment() != llvm::Triple::Cygnus ||
432 triple.isOSBinFormatMachO())
440 if (triple.isOSDarwin()) {
445 StringRef NoVer = llvm::sys::path::parent_path(HSOpts.
ResourceDir);
447 StringRef Lib = llvm::sys::path::parent_path(NoVer);
452 llvm::sys::path::append(P,
"include",
"c++",
"v1");
458 if (triple.getOS() == llvm::Triple::Solaris)
459 AddPath(
"/usr/include/c++/v1/support/solaris",
CXXSystem,
false);
461 AddPath(
"/usr/include/c++/v1",
CXXSystem,
false);
463 AddDefaultCPlusPlusIncludePaths(triple, HSOpts);
467 AddDefaultCIncludePaths(triple, HSOpts);
471 if (triple.isOSDarwin()) {
472 AddPath(
"/System/Library/Frameworks",
System,
true);
473 AddPath(
"/Library/Frameworks",
System,
true);
482 unsigned First,
bool Verbose) {
483 llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
484 llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
485 llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
486 unsigned NonSystemRemoved = 0;
487 for (
unsigned i = First; i != SearchList.size(); ++i) {
488 unsigned DirToRemove = i;
494 if (SeenDirs.insert(CurEntry.
getDir()).second)
501 assert(CurEntry.
isHeaderMap() &&
"Not a headermap or normal dir?");
503 if (SeenHeaderMaps.insert(CurEntry.
getHeaderMap()).second)
517 for (FirstDir = 0; ; ++FirstDir) {
518 assert(FirstDir != i &&
"Didn't find dupe?");
532 assert(CurEntry.
isHeaderMap() &&
"Not a headermap or normal dir?");
542 if (SearchList[FirstDir].getDirCharacteristic() ==
SrcMgr::C_User)
543 DirToRemove = FirstDir;
547 llvm::errs() <<
"ignoring duplicate directory \""
548 << CurEntry.
getName() <<
"\"\n";
549 if (DirToRemove != i)
550 llvm::errs() <<
" as it is a non-system directory that duplicates "
551 <<
"a system directory\n";
553 if (DirToRemove != i)
558 SearchList.erase(SearchList.begin()+DirToRemove);
561 return NonSystemRemoved;
565 void InitHeaderSearch::Realize(
const LangOptions &Lang) {
567 std::vector<DirectoryLookup> SearchList;
568 SearchList.reserve(IncludePath.size());
571 for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
574 SearchList.push_back(it->second);
578 unsigned NumQuoted = SearchList.size();
580 for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
583 SearchList.push_back(it->second);
587 unsigned NumAngled = SearchList.size();
589 for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
592 (!Lang.ObjC1 && !Lang.CPlusPlus && it->first ==
CSystem) ||
593 (Lang.CPlusPlus && it->first ==
CXXSystem) ||
594 (Lang.ObjC1 && !Lang.CPlusPlus && it->first ==
ObjCSystem) ||
595 (Lang.ObjC1 && Lang.CPlusPlus && it->first ==
ObjCXXSystem))
596 SearchList.push_back(it->second);
599 for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
601 if (it->first ==
After)
602 SearchList.push_back(it->second);
609 NumAngled -= NonSystemRemoved;
611 bool DontSearchCurDir =
false;
612 Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir);
614 Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
618 llvm::errs() <<
"#include \"...\" search starts here:\n";
619 for (
unsigned i = 0, e = SearchList.size(); i != e; ++i) {
621 llvm::errs() <<
"#include <...> search starts here:\n";
622 const char *Name = SearchList[i].getName();
624 if (SearchList[i].isNormalDir())
626 else if (SearchList[i].isFramework())
627 Suffix =
" (framework directory)";
629 assert(SearchList[i].isHeaderMap() &&
"Unknown DirectoryLookup");
630 Suffix =
" (headermap)";
632 llvm::errs() <<
" " << Name << Suffix <<
"\n";
634 llvm::errs() <<
"End of search list.\n";
641 const llvm::Triple &Triple) {
645 for (
unsigned i = 0, e = HSOpts.
UserEntries.size(); i != e; ++i) {
654 Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
663 llvm::sys::path::append(P,
"include");
Paths for '#include <>' added by '-I'.
Implements support for file system lookup, file system caching, and directory search management...
Defines the clang::FileManager interface and associated types.
SrcMgr::CharacteristicKind getDirCharacteristic() const
Like System, but only used for C++.
Like System, but only used for ObjC++.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Like System, but searched after the system directories.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const DirectoryEntry * getDirectory(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
const HeaderMap * getHeaderMap() const
Defines the clang::LangOptions interface.
LookupType_t getLookupType() const
bool isNormalDir() const
isNormalDir - Return true if this is a normal directory, not a header map.
void setBuiltinIncludeDir(const DirectoryEntry *Dir)
Set the directory that contains Clang-supplied include files, such as our stdarg.h or tgmath...
void ApplyHeaderSearchOptions(HeaderSearch &HS, const HeaderSearchOptions &HSOpts, const LangOptions &Lang, const llvm::Triple &triple)
Apply the header search options to get given HeaderSearch object.
const DirectoryEntry * getFrameworkDir() const
Cached information about one file (either on disk or in the virtual file system). ...
Like System, but only used for ObjC.
'#include ""' paths, added by 'gcc -iquote'.
Like System, but only used for C.
const char * getName() const
Cached information about one directory (either on disk or in the virtual file system).
bool isHeaderMap() const
isHeaderMap - Return true if this is a header map, not a normal directory.
const DirectoryEntry * getDir() const