Coverage Report

Created: 2021-09-21 08:58

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