Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Lex/InitHeaderSearch.cpp
Line
Count
Source (jump to first uncovered line)
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
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>
30
31
using namespace clang;
32
using namespace clang::frontend;
33
34
namespace {
35
/// Holds information about a single DirectoryLookup object.
36
struct DirectoryLookupInfo {
37
  IncludeDirGroup Group;
38
  DirectoryLookup Lookup;
39
  std::optional<unsigned> UserEntryIdx;
40
41
  DirectoryLookupInfo(IncludeDirGroup Group, DirectoryLookup Lookup,
42
                      std::optional<unsigned> UserEntryIdx)
43
0
      : 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.
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;
56
57
public:
58
  InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
59
      : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)),
60
46
        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
0
  void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
77
0
    SystemHeaderPrefixes.emplace_back(std::string(Prefix), IsSystemHeader);
78
0
  }
79
80
  /// Add the necessary paths to support a MinGW libstdc++.
81
  void AddMinGWCPlusPlusIncludePaths(StringRef Base,
82
                                     StringRef Arch,
83
                                     StringRef Version);
84
85
  /// Add paths that should always be searched.
86
  void AddDefaultCIncludePaths(const llvm::Triple &triple,
87
                               const HeaderSearchOptions &HSOpts);
88
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);
93
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);
97
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);
102
103
  /// Merges all search path lists into one list and send it to HeaderSearch.
104
  void Realize(const LangOptions &Lang);
105
};
106
107
}  // end anonymous namespace.
108
109
0
static bool CanPrefixSysroot(StringRef Path) {
110
#if defined(_WIN32)
111
  return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
112
#else
113
0
  return llvm::sys::path::is_absolute(Path);
114
0
#endif
115
0
}
116
117
bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
118
                               bool isFramework,
119
0
                               std::optional<unsigned> UserEntryIdx) {
120
  // Add the path with sysroot prepended, if desired and this is a system header
121
  // group.
122
0
  if (HasSysroot) {
123
0
    SmallString<256> MappedPathStorage;
124
0
    StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
125
0
    if (CanPrefixSysroot(MappedPathStr)) {
126
0
      return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework,
127
0
                             UserEntryIdx);
128
0
    }
129
0
  }
130
131
0
  return AddUnmappedPath(Path, Group, isFramework, UserEntryIdx);
132
0
}
133
134
bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
135
                                       bool isFramework,
136
0
                                       std::optional<unsigned> UserEntryIdx) {
137
0
  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
138
139
0
  FileManager &FM = Headers.getFileMgr();
140
0
  SmallString<256> MappedPathStorage;
141
0
  StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
142
143
  // If use system headers while cross-compiling, emit the warning.
144
0
  if (HasSysroot && (MappedPathStr.starts_with("/usr/include") ||
145
0
                     MappedPathStr.starts_with("/usr/local/include"))) {
146
0
    Headers.getDiags().Report(diag::warn_poison_system_directories)
147
0
        << MappedPathStr;
148
0
  }
149
150
  // Compute the DirectoryLookup type.
151
0
  SrcMgr::CharacteristicKind Type;
152
0
  if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) {
153
0
    Type = SrcMgr::C_User;
154
0
  } else if (Group == ExternCSystem) {
155
0
    Type = SrcMgr::C_ExternCSystem;
156
0
  } else {
157
0
    Type = SrcMgr::C_System;
158
0
  }
159
160
  // If the directory exists, add it.
161
0
  if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
162
0
    IncludePath.emplace_back(Group, DirectoryLookup(*DE, Type, isFramework),
163
0
                             UserEntryIdx);
164
0
    return true;
165
0
  }
166
167
  // Check to see if this is an apple-style headermap (which are not allowed to
168
  // be frameworks).
169
0
  if (!isFramework) {
170
0
    if (auto FE = FM.getOptionalFileRef(MappedPathStr)) {
171
0
      if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
172
        // It is a headermap, add it to the search path.
173
0
        IncludePath.emplace_back(
174
0
            Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap),
175
0
            UserEntryIdx);
176
0
        return true;
177
0
      }
178
0
    }
179
0
  }
180
181
0
  if (Verbose)
182
0
    llvm::errs() << "ignoring nonexistent directory \""
183
0
                 << MappedPathStr << "\"\n";
184
0
  return false;
185
0
}
186
187
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base,
188
                                                     StringRef Arch,
189
0
                                                     StringRef Version) {
190
0
  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
191
0
          CXXSystem, false);
192
0
  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
193
0
          CXXSystem, false);
194
0
  AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
195
0
          CXXSystem, false);
196
0
}
197
198
void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
199
0
                                            const HeaderSearchOptions &HSOpts) {
200
0
  if (!ShouldAddDefaultIncludePaths(triple))
201
0
    llvm_unreachable("Include management is handled in the driver.");
202
203
0
  llvm::Triple::OSType os = triple.getOS();
204
205
0
  if (HSOpts.UseStandardSystemIncludes) {
206
0
    switch (os) {
207
0
    case llvm::Triple::Win32:
208
0
      if (triple.getEnvironment() != llvm::Triple::Cygnus)
209
0
        break;
210
0
      [[fallthrough]];
211
0
    default:
212
      // FIXME: temporary hack: hard-coded paths.
213
0
      AddPath("/usr/local/include", System, false);
214
0
      break;
215
0
    }
216
0
  }
217
218
  // Builtin includes use #include_next directives and should be positioned
219
  // just prior C include dirs.
220
0
  if (HSOpts.UseBuiltinIncludes) {
221
    // Ignore the sys root, we *always* look for clang headers relative to
222
    // supplied path.
223
0
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
224
0
    llvm::sys::path::append(P, "include");
225
0
    AddUnmappedPath(P, ExternCSystem, false);
226
0
  }
227
228
  // All remaining additions are for system include directories, early exit if
229
  // we aren't using them.
230
0
  if (!HSOpts.UseStandardSystemIncludes)
231
0
    return;
232
233
  // Add dirs specified via 'configure --with-c-include-dirs'.
234
0
  StringRef CIncludeDirs(C_INCLUDE_DIRS);
235
0
  if (CIncludeDirs != "") {
236
0
    SmallVector<StringRef, 5> dirs;
237
0
    CIncludeDirs.split(dirs, ":");
238
0
    for (StringRef dir : dirs)
239
0
      AddPath(dir, ExternCSystem, false);
240
0
    return;
241
0
  }
242
243
0
  switch (os) {
244
0
  case llvm::Triple::Win32:
245
0
    switch (triple.getEnvironment()) {
246
0
    default: llvm_unreachable("Include management is handled in the driver.");
247
0
    case llvm::Triple::Cygnus:
248
0
      AddPath("/usr/include/w32api", System, false);
249
0
      break;
250
0
    case llvm::Triple::GNU:
251
0
      break;
252
0
    }
253
0
    break;
254
0
  default:
255
0
    break;
256
0
  }
257
258
0
  AddPath("/usr/include", ExternCSystem, false);
259
0
}
260
261
void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
262
    const LangOptions &LangOpts, const llvm::Triple &triple,
263
0
    const HeaderSearchOptions &HSOpts) {
264
0
  if (!ShouldAddDefaultIncludePaths(triple))
265
0
    llvm_unreachable("Include management is handled in the driver.");
266
267
  // FIXME: temporary hack: hard-coded paths.
268
0
  llvm::Triple::OSType os = triple.getOS();
269
0
  switch (os) {
270
0
  case llvm::Triple::Win32:
271
0
    switch (triple.getEnvironment()) {
272
0
    default: llvm_unreachable("Include management is handled in the driver.");
273
0
    case llvm::Triple::Cygnus:
274
      // Cygwin-1.7
275
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3");
276
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3");
277
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
278
      // g++-4 / Cygwin-1.5
279
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
280
0
      break;
281
0
    }
282
0
    break;
283
0
  default:
284
0
    break;
285
0
  }
286
0
}
287
288
bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
289
46
    const llvm::Triple &triple) {
290
46
  switch (triple.getOS()) {
291
0
  case llvm::Triple::AIX:
292
0
  case llvm::Triple::DragonFly:
293
0
  case llvm::Triple::ELFIAMCU:
294
0
  case llvm::Triple::Emscripten:
295
0
  case llvm::Triple::FreeBSD:
296
0
  case llvm::Triple::Fuchsia:
297
0
  case llvm::Triple::Haiku:
298
0
  case llvm::Triple::Hurd:
299
46
  case llvm::Triple::Linux:
300
46
  case llvm::Triple::LiteOS:
301
46
  case llvm::Triple::NaCl:
302
46
  case llvm::Triple::NetBSD:
303
46
  case llvm::Triple::OpenBSD:
304
46
  case llvm::Triple::PS4:
305
46
  case llvm::Triple::PS5:
306
46
  case llvm::Triple::RTEMS:
307
46
  case llvm::Triple::Solaris:
308
46
  case llvm::Triple::WASI:
309
46
  case llvm::Triple::ZOS:
310
46
    return false;
311
312
0
  case llvm::Triple::Win32:
313
0
    if (triple.getEnvironment() != llvm::Triple::Cygnus ||
314
0
        triple.isOSBinFormatMachO())
315
0
      return false;
316
0
    break;
317
318
0
  case llvm::Triple::UnknownOS:
319
0
    if (triple.isWasm())
320
0
      return false;
321
0
    break;
322
323
0
  default:
324
0
    break;
325
46
  }
326
327
0
  return true; // Everything else uses AddDefaultIncludePaths().
328
46
}
329
330
void InitHeaderSearch::AddDefaultIncludePaths(
331
    const LangOptions &Lang, const llvm::Triple &triple,
332
46
    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
46
  if (!ShouldAddDefaultIncludePaths(triple))
339
46
    return;
340
341
  // NOTE: some additional header search logic is handled in the driver for
342
  // Darwin.
343
0
  if (triple.isOSDarwin()) {
344
0
    if (HSOpts.UseStandardSystemIncludes) {
345
      // Add the default framework include paths on Darwin.
346
0
      if (triple.isDriverKit()) {
347
0
        AddPath("/System/DriverKit/System/Library/Frameworks", System, true);
348
0
      } else {
349
0
        AddPath("/System/Library/Frameworks", System, true);
350
0
        AddPath("/Library/Frameworks", System, true);
351
0
      }
352
0
    }
353
0
    return;
354
0
  }
355
356
0
  if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
357
0
      HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
358
0
    if (HSOpts.UseLibcxx) {
359
0
      AddPath("/usr/include/c++/v1", CXXSystem, false);
360
0
    } else {
361
0
      AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
362
0
    }
363
0
  }
364
365
0
  AddDefaultCIncludePaths(triple, HSOpts);
366
0
}
367
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
138
                                 unsigned First, bool Verbose) {
373
138
  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
374
138
  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
375
138
  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
376
138
  unsigned NonSystemRemoved = 0;
377
138
  for (unsigned i = First; i != SearchList.size(); ++i) {
378
0
    unsigned DirToRemove = i;
379
380
0
    const DirectoryLookup &CurEntry = SearchList[i].Lookup;
381
382
0
    if (CurEntry.isNormalDir()) {
383
      // If this isn't the first time we've seen this dir, remove it.
384
0
      if (SeenDirs.insert(CurEntry.getDir()).second)
385
0
        continue;
386
0
    } else if (CurEntry.isFramework()) {
387
      // If this isn't the first time we've seen this framework dir, remove it.
388
0
      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
389
0
        continue;
390
0
    } else {
391
0
      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
0
      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
394
0
        continue;
395
0
    }
396
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.
401
    //
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
0
    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
405
      // Find the dir that this is the same of.
406
0
      unsigned FirstDir;
407
0
      for (FirstDir = First;; ++FirstDir) {
408
0
        assert(FirstDir != i && "Didn't find dupe?");
409
410
0
        const DirectoryLookup &SearchEntry = SearchList[FirstDir].Lookup;
411
412
        // If these are different lookup types, then they can't be the dupe.
413
0
        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
414
0
          continue;
415
416
0
        bool isSame;
417
0
        if (CurEntry.isNormalDir())
418
0
          isSame = SearchEntry.getDir() == CurEntry.getDir();
419
0
        else if (CurEntry.isFramework())
420
0
          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
421
0
        else {
422
0
          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
423
0
          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
424
0
        }
425
426
0
        if (isSame)
427
0
          break;
428
0
      }
429
430
      // If the first dir in the search path is a non-system dir, zap it
431
      // instead of the system one.
432
0
      if (SearchList[FirstDir].Lookup.getDirCharacteristic() == SrcMgr::C_User)
433
0
        DirToRemove = FirstDir;
434
0
    }
435
436
0
    if (Verbose) {
437
0
      llvm::errs() << "ignoring duplicate directory \""
438
0
                   << CurEntry.getName() << "\"\n";
439
0
      if (DirToRemove != i)
440
0
        llvm::errs() << "  as it is a non-system directory that duplicates "
441
0
                     << "a system directory\n";
442
0
    }
443
0
    if (DirToRemove != i)
444
0
      ++NonSystemRemoved;
445
446
    // This is reached if the current entry is a duplicate.  Remove the
447
    // DirToRemove (usually the current dir).
448
0
    SearchList.erase(SearchList.begin()+DirToRemove);
449
0
    --i;
450
0
  }
451
138
  return NonSystemRemoved;
452
138
}
453
454
/// Extract DirectoryLookups from DirectoryLookupInfos.
455
static std::vector<DirectoryLookup>
456
46
extractLookups(const std::vector<DirectoryLookupInfo> &Infos) {
457
46
  std::vector<DirectoryLookup> Lookups;
458
46
  Lookups.reserve(Infos.size());
459
46
  llvm::transform(Infos, std::back_inserter(Lookups),
460
46
                  [](const DirectoryLookupInfo &Info) { return Info.Lookup; });
461
46
  return Lookups;
462
46
}
463
464
/// Collect the mapping between indices of DirectoryLookups and UserEntries.
465
static llvm::DenseMap<unsigned, unsigned>
466
46
mapToUserEntries(const std::vector<DirectoryLookupInfo> &Infos) {
467
46
  llvm::DenseMap<unsigned, unsigned> LookupsToUserEntries;
468
46
  for (unsigned I = 0, E = Infos.size(); I < E; ++I) {
469
    // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
470
0
    if (Infos[I].UserEntryIdx)
471
0
      LookupsToUserEntries.insert({I, *Infos[I].UserEntryIdx});
472
0
  }
473
46
  return LookupsToUserEntries;
474
46
}
475
476
46
void InitHeaderSearch::Realize(const LangOptions &Lang) {
477
  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
478
46
  std::vector<DirectoryLookupInfo> SearchList;
479
46
  SearchList.reserve(IncludePath.size());
480
481
  // Quoted arguments go first.
482
46
  for (auto &Include : IncludePath)
483
0
    if (Include.Group == Quoted)
484
0
      SearchList.push_back(Include);
485
486
  // Deduplicate and remember index.
487
46
  RemoveDuplicates(SearchList, 0, Verbose);
488
46
  unsigned NumQuoted = SearchList.size();
489
490
46
  for (auto &Include : IncludePath)
491
0
    if (Include.Group == Angled || Include.Group == IndexHeaderMap)
492
0
      SearchList.push_back(Include);
493
494
46
  RemoveDuplicates(SearchList, NumQuoted, Verbose);
495
46
  unsigned NumAngled = SearchList.size();
496
497
46
  for (auto &Include : IncludePath)
498
0
    if (Include.Group == System || Include.Group == ExternCSystem ||
499
0
        (!Lang.ObjC && !Lang.CPlusPlus && Include.Group == CSystem) ||
500
0
        (/*FIXME !Lang.ObjC && */ Lang.CPlusPlus &&
501
0
         Include.Group == CXXSystem) ||
502
0
        (Lang.ObjC && !Lang.CPlusPlus && Include.Group == ObjCSystem) ||
503
0
        (Lang.ObjC && Lang.CPlusPlus && Include.Group == ObjCXXSystem))
504
0
      SearchList.push_back(Include);
505
506
46
  for (auto &Include : IncludePath)
507
0
    if (Include.Group == After)
508
0
      SearchList.push_back(Include);
509
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
46
  unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
514
46
  NumAngled -= NonSystemRemoved;
515
516
46
  Headers.SetSearchPaths(extractLookups(SearchList), NumQuoted, NumAngled,
517
46
                         mapToUserEntries(SearchList));
518
519
46
  Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
520
521
  // If verbose, print the list of directories that will be searched.
522
46
  if (Verbose) {
523
0
    llvm::errs() << "#include \"...\" search starts here:\n";
524
0
    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
525
0
      if (i == NumQuoted)
526
0
        llvm::errs() << "#include <...> search starts here:\n";
527
0
      StringRef Name = SearchList[i].Lookup.getName();
528
0
      const char *Suffix;
529
0
      if (SearchList[i].Lookup.isNormalDir())
530
0
        Suffix = "";
531
0
      else if (SearchList[i].Lookup.isFramework())
532
0
        Suffix = " (framework directory)";
533
0
      else {
534
0
        assert(SearchList[i].Lookup.isHeaderMap() && "Unknown DirectoryLookup");
535
0
        Suffix = " (headermap)";
536
0
      }
537
0
      llvm::errs() << " " << Name << Suffix << "\n";
538
0
    }
539
0
    llvm::errs() << "End of search list.\n";
540
0
  }
541
46
}
542
543
void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
544
                                     const HeaderSearchOptions &HSOpts,
545
                                     const LangOptions &Lang,
546
46
                                     const llvm::Triple &Triple) {
547
46
  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
548
549
  // Add the user defined entries.
550
46
  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
551
0
    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
552
0
    if (E.IgnoreSysRoot) {
553
0
      Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework, i);
554
0
    } else {
555
0
      Init.AddPath(E.Path, E.Group, E.IsFramework, i);
556
0
    }
557
0
  }
558
559
46
  Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
560
561
46
  for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i)
562
0
    Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
563
0
                               HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
564
565
46
  if (HSOpts.UseBuiltinIncludes) {
566
    // Set up the builtin include directory in the module map.
567
46
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
568
46
    llvm::sys::path::append(P, "include");
569
46
    if (auto Dir = HS.getFileMgr().getOptionalDirectoryRef(P))
570
0
      HS.getModuleMap().setBuiltinIncludeDir(*Dir);
571
46
  }
572
573
46
  Init.Realize(Lang);
574
46
}