Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/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
166k
      : 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
93.4k
      : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)),
60
93.4k
        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
4
  void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
77
4
    SystemHeaderPrefixes.emplace_back(std::string(Prefix), IsSystemHeader);
78
4
  }
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
16.3k
static bool CanPrefixSysroot(StringRef Path) {
110
#if defined(_WIN32)
111
  return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
112
#else
113
16.3k
  return llvm::sys::path::is_absolute(Path);
114
16.3k
#endif
115
16.3k
}
116
117
bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
118
                               bool isFramework,
119
84.0k
                               std::optional<unsigned> UserEntryIdx) {
120
  // Add the path with sysroot prepended, if desired and this is a system header
121
  // group.
122
84.0k
  if (HasSysroot) {
123
16.3k
    SmallString<256> MappedPathStorage;
124
16.3k
    StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
125
16.3k
    if (CanPrefixSysroot(MappedPathStr)) {
126
16.3k
      return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework,
127
16.3k
                             UserEntryIdx);
128
16.3k
    }
129
16.3k
  }
130
131
67.6k
  return AddUnmappedPath(Path, Group, isFramework, UserEntryIdx);
132
84.0k
}
133
134
bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
135
                                       bool isFramework,
136
243k
                                       std::optional<unsigned> UserEntryIdx) {
137
243k
  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
138
139
243k
  FileManager &FM = Headers.getFileMgr();
140
243k
  SmallString<256> MappedPathStorage;
141
243k
  StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
142
143
  // If use system headers while cross-compiling, emit the warning.
144
243k
  if (HasSysroot && 
(55.7k
MappedPathStr.startswith("/usr/include")55.7k
||
145
55.7k
                     
MappedPathStr.startswith("/usr/local/include")55.7k
)) {
146
25
    Headers.getDiags().Report(diag::warn_poison_system_directories)
147
25
        << MappedPathStr;
148
25
  }
149
150
  // Compute the DirectoryLookup type.
151
243k
  SrcMgr::CharacteristicKind Type;
152
243k
  if (Group == Quoted || 
Group == Angled243k
||
Group == IndexHeaderMap230k
) {
153
13.2k
    Type = SrcMgr::C_User;
154
230k
  } else if (Group == ExternCSystem) {
155
55.6k
    Type = SrcMgr::C_ExternCSystem;
156
174k
  } else {
157
174k
    Type = SrcMgr::C_System;
158
174k
  }
159
160
  // If the directory exists, add it.
161
243k
  if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
162
166k
    IncludePath.emplace_back(Group, DirectoryLookup(*DE, Type, isFramework),
163
166k
                             UserEntryIdx);
164
166k
    return true;
165
166k
  }
166
167
  // Check to see if this is an apple-style headermap (which are not allowed to
168
  // be frameworks).
169
77.0k
  if (!isFramework) {
170
68.5k
    if (auto FE = FM.getOptionalFileRef(MappedPathStr)) {
171
43
      if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
172
        // It is a headermap, add it to the search path.
173
39
        IncludePath.emplace_back(
174
39
            Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap),
175
39
            UserEntryIdx);
176
39
        return true;
177
39
      }
178
43
    }
179
68.5k
  }
180
181
76.9k
  if (Verbose)
182
54
    llvm::errs() << "ignoring nonexistent directory \""
183
54
                 << MappedPathStr << "\"\n";
184
76.9k
  return false;
185
77.0k
}
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
22.2k
                                            const HeaderSearchOptions &HSOpts) {
200
22.2k
  if (!ShouldAddDefaultIncludePaths(triple))
201
0
    llvm_unreachable("Include management is handled in the driver.");
202
203
22.2k
  llvm::Triple::OSType os = triple.getOS();
204
205
22.2k
  if (HSOpts.UseStandardSystemIncludes) {
206
10.7k
    switch (os) {
207
0
    case llvm::Triple::Win32:
208
0
      if (triple.getEnvironment() != llvm::Triple::Cygnus)
209
0
        break;
210
0
      [[fallthrough]];
211
10.7k
    default:
212
      // FIXME: temporary hack: hard-coded paths.
213
10.7k
      AddPath("/usr/local/include", System, false);
214
10.7k
      break;
215
10.7k
    }
216
10.7k
  }
217
218
  // Builtin includes use #include_next directives and should be positioned
219
  // just prior C include dirs.
220
22.2k
  if (HSOpts.UseBuiltinIncludes) {
221
    // Ignore the sys root, we *always* look for clang headers relative to
222
    // supplied path.
223
22.2k
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
224
22.2k
    llvm::sys::path::append(P, "include");
225
22.2k
    AddUnmappedPath(P, ExternCSystem, false);
226
22.2k
  }
227
228
  // All remaining additions are for system include directories, early exit if
229
  // we aren't using them.
230
22.2k
  if (!HSOpts.UseStandardSystemIncludes)
231
11.5k
    return;
232
233
  // Add dirs specified via 'configure --with-c-include-dirs'.
234
10.7k
  StringRef CIncludeDirs(C_INCLUDE_DIRS);
235
10.7k
  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
10.7k
  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
10.7k
  default:
255
10.7k
    break;
256
10.7k
  }
257
258
10.7k
  AddPath("/usr/include", ExternCSystem, false);
259
10.7k
}
260
261
void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
262
    const LangOptions &LangOpts, const llvm::Triple &triple,
263
8.72k
    const HeaderSearchOptions &HSOpts) {
264
8.72k
  if (!ShouldAddDefaultIncludePaths(triple))
265
0
    llvm_unreachable("Include management is handled in the driver.");
266
267
  // FIXME: temporary hack: hard-coded paths.
268
8.72k
  llvm::Triple::OSType os = triple.getOS();
269
8.72k
  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
8.72k
  default:
284
8.72k
    break;
285
8.72k
  }
286
8.72k
}
287
288
bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
289
124k
    const llvm::Triple &triple) {
290
124k
  switch (triple.getOS()) {
291
287
  case llvm::Triple::AIX:
292
290
  case llvm::Triple::DragonFly:
293
297
  case llvm::Triple::ELFIAMCU:
294
304
  case llvm::Triple::Emscripten:
295
388
  case llvm::Triple::FreeBSD:
296
432
  case llvm::Triple::Fuchsia:
297
440
  case llvm::Triple::Haiku:
298
442
  case llvm::Triple::Hurd:
299
8.66k
  case llvm::Triple::Linux:
300
8.66k
  case llvm::Triple::LiteOS:
301
8.68k
  case llvm::Triple::NaCl:
302
8.74k
  case llvm::Triple::NetBSD:
303
8.79k
  case llvm::Triple::OpenBSD:
304
8.85k
  case llvm::Triple::PS4:
305
8.88k
  case llvm::Triple::PS5:
306
8.90k
  case llvm::Triple::RTEMS:
307
8.91k
  case llvm::Triple::Solaris:
308
8.92k
  case llvm::Triple::WASI:
309
8.95k
  case llvm::Triple::ZOS:
310
8.95k
    return false;
311
312
9.38k
  case llvm::Triple::Win32:
313
9.38k
    if (triple.getEnvironment() != llvm::Triple::Cygnus ||
314
9.38k
        
triple.isOSBinFormatMachO()36
)
315
9.34k
      return false;
316
35
    break;
317
318
52.1k
  case llvm::Triple::UnknownOS:
319
52.1k
    if (triple.isWasm())
320
124
      return false;
321
52.0k
    break;
322
323
53.9k
  default:
324
53.9k
    break;
325
124k
  }
326
327
106k
  return true; // Everything else uses AddDefaultIncludePaths().
328
124k
}
329
330
void InitHeaderSearch::AddDefaultIncludePaths(
331
    const LangOptions &Lang, const llvm::Triple &triple,
332
93.4k
    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
93.4k
  if (!ShouldAddDefaultIncludePaths(triple))
339
18.4k
    return;
340
341
  // NOTE: some additional header search logic is handled in the driver for
342
  // Darwin.
343
75.0k
  if (triple.isOSDarwin()) {
344
52.8k
    if (HSOpts.UseStandardSystemIncludes) {
345
      // Add the default framework include paths on Darwin.
346
31.2k
      if (triple.isDriverKit()) {
347
6
        AddPath("/System/DriverKit/System/Library/Frameworks", System, true);
348
31.2k
      } else {
349
31.2k
        AddPath("/System/Library/Frameworks", System, true);
350
31.2k
        AddPath("/Library/Frameworks", System, true);
351
31.2k
      }
352
31.2k
    }
353
52.8k
    return;
354
52.8k
  }
355
356
22.2k
  if (Lang.CPlusPlus && 
!Lang.AsmPreprocessor17.5k
&&
357
22.2k
      
HSOpts.UseStandardCXXIncludes17.5k
&&
HSOpts.UseStandardSystemIncludes17.5k
) {
358
8.73k
    if (HSOpts.UseLibcxx) {
359
8
      AddPath("/usr/include/c++/v1", CXXSystem, false);
360
8.72k
    } else {
361
8.72k
      AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
362
8.72k
    }
363
8.73k
  }
364
365
22.2k
  AddDefaultCIncludePaths(triple, HSOpts);
366
22.2k
}
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
280k
                                 unsigned First, bool Verbose) {
373
280k
  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
374
280k
  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
375
280k
  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
376
280k
  unsigned NonSystemRemoved = 0;
377
459k
  for (unsigned i = First; i != SearchList.size(); 
++i179k
) {
378
179k
    unsigned DirToRemove = i;
379
380
179k
    const DirectoryLookup &CurEntry = SearchList[i].Lookup;
381
382
179k
    if (CurEntry.isNormalDir()) {
383
      // If this isn't the first time we've seen this dir, remove it.
384
123k
      if (SeenDirs.insert(CurEntry.getDir()).second)
385
111k
        continue;
386
123k
    } else 
if (55.5k
CurEntry.isFramework()55.5k
) {
387
      // If this isn't the first time we've seen this framework dir, remove it.
388
55.4k
      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
389
55.4k
        continue;
390
55.4k
    } else {
391
59
      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
59
      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
394
59
        continue;
395
59
    }
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
12.0k
    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
405
      // Find the dir that this is the same of.
406
11.8k
      unsigned FirstDir;
407
12.5k
      for (FirstDir = First;; 
++FirstDir681
) {
408
12.5k
        assert(FirstDir != i && "Didn't find dupe?");
409
410
12.5k
        const DirectoryLookup &SearchEntry = SearchList[FirstDir].Lookup;
411
412
        // If these are different lookup types, then they can't be the dupe.
413
12.5k
        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
414
64
          continue;
415
416
12.5k
        bool isSame;
417
12.5k
        if (CurEntry.isNormalDir())
418
12.5k
          isSame = SearchEntry.getDir() == CurEntry.getDir();
419
1
        else if (CurEntry.isFramework())
420
1
          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
12.5k
        if (isSame)
427
11.8k
          break;
428
12.5k
      }
429
430
      // If the first dir in the search path is a non-system dir, zap it
431
      // instead of the system one.
432
11.8k
      if (SearchList[FirstDir].Lookup.getDirCharacteristic() == SrcMgr::C_User)
433
17
        DirToRemove = FirstDir;
434
11.8k
    }
435
436
12.0k
    if (Verbose) {
437
3
      llvm::errs() << "ignoring duplicate directory \""
438
3
                   << CurEntry.getName() << "\"\n";
439
3
      if (DirToRemove != i)
440
0
        llvm::errs() << "  as it is a non-system directory that duplicates "
441
0
                     << "a system directory\n";
442
3
    }
443
12.0k
    if (DirToRemove != i)
444
17
      ++NonSystemRemoved;
445
446
    // This is reached if the current entry is a duplicate.  Remove the
447
    // DirToRemove (usually the current dir).
448
12.0k
    SearchList.erase(SearchList.begin()+DirToRemove);
449
12.0k
    --i;
450
12.0k
  }
451
280k
  return NonSystemRemoved;
452
280k
}
453
454
/// Extract DirectoryLookups from DirectoryLookupInfos.
455
static std::vector<DirectoryLookup>
456
93.4k
extractLookups(const std::vector<DirectoryLookupInfo> &Infos) {
457
93.4k
  std::vector<DirectoryLookup> Lookups;
458
93.4k
  Lookups.reserve(Infos.size());
459
93.4k
  llvm::transform(Infos, std::back_inserter(Lookups),
460
154k
                  [](const DirectoryLookupInfo &Info) { return Info.Lookup; });
461
93.4k
  return Lookups;
462
93.4k
}
463
464
/// Collect the mapping between indices of DirectoryLookups and UserEntries.
465
static llvm::DenseMap<unsigned, unsigned>
466
93.4k
mapToUserEntries(const std::vector<DirectoryLookupInfo> &Infos) {
467
93.4k
  llvm::DenseMap<unsigned, unsigned> LookupsToUserEntries;
468
247k
  for (unsigned I = 0, E = Infos.size(); I < E; 
++I154k
) {
469
    // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
470
154k
    if (Infos[I].UserEntryIdx)
471
88.9k
      LookupsToUserEntries.insert({I, *Infos[I].UserEntryIdx});
472
154k
  }
473
93.4k
  return LookupsToUserEntries;
474
93.4k
}
475
476
93.4k
void InitHeaderSearch::Realize(const LangOptions &Lang) {
477
  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
478
93.4k
  std::vector<DirectoryLookupInfo> SearchList;
479
93.4k
  SearchList.reserve(IncludePath.size());
480
481
  // Quoted arguments go first.
482
93.4k
  for (auto &Include : IncludePath)
483
166k
    if (Include.Group == Quoted)
484
66
      SearchList.push_back(Include);
485
486
  // Deduplicate and remember index.
487
93.4k
  RemoveDuplicates(SearchList, 0, Verbose);
488
93.4k
  unsigned NumQuoted = SearchList.size();
489
490
93.4k
  for (auto &Include : IncludePath)
491
166k
    if (Include.Group == Angled || 
Include.Group == IndexHeaderMap153k
)
492
13.0k
      SearchList.push_back(Include);
493
494
93.4k
  RemoveDuplicates(SearchList, NumQuoted, Verbose);
495
93.4k
  unsigned NumAngled = SearchList.size();
496
497
93.4k
  for (auto &Include : IncludePath)
498
166k
    if (Include.Group == System || 
Include.Group == ExternCSystem35.2k
||
499
166k
        
(15.0k
!Lang.ObjC15.0k
&&
!Lang.CPlusPlus11.1k
&&
Include.Group == CSystem3.12k
) ||
500
166k
        
(/*FIXME !Lang.ObjC && */ 15.0k
Lang.CPlusPlus15.0k
&&
501
15.0k
         
Include.Group == CXXSystem9.23k
) ||
502
166k
        
(13.1k
Lang.ObjC13.1k
&&
!Lang.CPlusPlus3.59k
&&
Include.Group == ObjCSystem2.64k
) ||
503
166k
        
(13.1k
Lang.ObjC13.1k
&&
Lang.CPlusPlus3.59k
&&
Include.Group == ObjCXXSystem943
))
504
153k
      SearchList.push_back(Include);
505
506
93.4k
  for (auto &Include : IncludePath)
507
166k
    if (Include.Group == After)
508
17
      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
93.4k
  unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
514
93.4k
  NumAngled -= NonSystemRemoved;
515
516
93.4k
  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
517
93.4k
  Headers.SetSearchPaths(extractLookups(SearchList), NumQuoted, NumAngled,
518
93.4k
                         DontSearchCurDir, mapToUserEntries(SearchList));
519
520
93.4k
  Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
521
522
  // If verbose, print the list of directories that will be searched.
523
93.4k
  if (Verbose) {
524
57
    llvm::errs() << "#include \"...\" search starts here:\n";
525
252
    for (unsigned i = 0, e = SearchList.size(); i != e; 
++i195
) {
526
195
      if (i == NumQuoted)
527
54
        llvm::errs() << "#include <...> search starts here:\n";
528
195
      StringRef Name = SearchList[i].Lookup.getName();
529
195
      const char *Suffix;
530
195
      if (SearchList[i].Lookup.isNormalDir())
531
139
        Suffix = "";
532
56
      else if (SearchList[i].Lookup.isFramework())
533
55
        Suffix = " (framework directory)";
534
1
      else {
535
1
        assert(SearchList[i].Lookup.isHeaderMap() && "Unknown DirectoryLookup");
536
1
        Suffix = " (headermap)";
537
1
      }
538
195
      llvm::errs() << " " << Name << Suffix << "\n";
539
195
    }
540
57
    llvm::errs() << "End of search list.\n";
541
57
  }
542
93.4k
}
543
544
void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
545
                                     const HeaderSearchOptions &HSOpts,
546
                                     const LangOptions &Lang,
547
93.4k
                                     const llvm::Triple &Triple) {
548
93.4k
  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
549
550
  // Add the user defined entries.
551
230k
  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; 
++i137k
) {
552
137k
    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
553
137k
    if (E.IgnoreSysRoot) {
554
137k
      Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework, i);
555
137k
    } else {
556
5
      Init.AddPath(E.Path, E.Group, E.IsFramework, i);
557
5
    }
558
137k
  }
559
560
93.4k
  Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
561
562
93.4k
  for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; 
++i4
)
563
4
    Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
564
4
                               HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
565
566
93.4k
  if (HSOpts.UseBuiltinIncludes) {
567
    // Set up the builtin include directory in the module map.
568
93.4k
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
569
93.4k
    llvm::sys::path::append(P, "include");
570
93.4k
    if (auto Dir = HS.getFileMgr().getOptionalDirectoryRef(P))
571
52.4k
      HS.getModuleMap().setBuiltinIncludeDir(*Dir);
572
93.4k
  }
573
574
93.4k
  Init.Realize(Lang);
575
93.4k
}