Coverage Report

Created: 2019-07-24 05:18

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