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