Coverage Report

Created: 2020-09-19 12:23

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