Coverage Report

Created: 2020-02-25 14:32

/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
59.3k
        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.0k
static bool CanPrefixSysroot(StringRef Path) {
108
#if defined(_WIN32)
109
  return !Path.empty() && llvm::sys::path::is_separator(Path[0]);
110
#else
111
  return llvm::sys::path::is_absolute(Path);
112
21.0k
#endif
113
21.0k
}
114
115
bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group,
116
62.9k
                               bool isFramework) {
117
62.9k
  // Add the path with sysroot prepended, if desired and this is a system header
118
62.9k
  // group.
119
62.9k
  if (HasSysroot) {
120
21.0k
    SmallString<256> MappedPathStorage;
121
21.0k
    StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
122
21.0k
    if (CanPrefixSysroot(MappedPathStr)) {
123
21.0k
      return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework);
124
21.0k
    }
125
41.8k
  }
126
41.8k
127
41.8k
  return AddUnmappedPath(Path, Group, isFramework);
128
41.8k
}
129
130
bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
131
202k
                                       bool isFramework) {
132
202k
  assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
133
202k
134
202k
  FileManager &FM = Headers.getFileMgr();
135
202k
  SmallString<256> MappedPathStorage;
136
202k
  StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
137
202k
138
202k
  // If use system headers while cross-compiling, emit the warning.
139
202k
  if (HasSysroot && 
(82.7k
MappedPathStr.startswith("/usr/include")82.7k
||
140
82.7k
                     
MappedPathStr.startswith("/usr/local/include")82.7k
)) {
141
7
    Headers.getDiags().Report(diag::warn_poison_system_directories)
142
7
        << MappedPathStr;
143
7
  }
144
202k
145
202k
  // Compute the DirectoryLookup type.
146
202k
  SrcMgr::CharacteristicKind Type;
147
202k
  if (Group == Quoted || 
Group == Angled202k
||
Group == IndexHeaderMap181k
) {
148
20.7k
    Type = SrcMgr::C_User;
149
181k
  } else if (Group == ExternCSystem) {
150
30.9k
    Type = SrcMgr::C_ExternCSystem;
151
150k
  } else {
152
150k
    Type = SrcMgr::C_System;
153
150k
  }
154
202k
155
202k
  // If the directory exists, add it.
156
202k
  if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
157
137k
    IncludePath.push_back(
158
137k
      std::make_pair(Group, DirectoryLookup(*DE, Type, isFramework)));
159
137k
    return true;
160
137k
  }
161
64.6k
162
64.6k
  // Check to see if this is an apple-style headermap (which are not allowed to
163
64.6k
  // be frameworks).
164
64.6k
  if (!isFramework) {
165
54.0k
    if (auto FE = FM.getFile(MappedPathStr)) {
166
33
      if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
167
29
        // 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
64.6k
    }
174
54.0k
  }
175
64.6k
176
64.6k
  if (Verbose)
177
62
    llvm::errs() << "ignoring nonexistent directory \""
178
62
                 << MappedPathStr << "\"\n";
179
64.6k
  return false;
180
64.6k
}
181
182
bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
183
                                                   StringRef ArchDir,
184
                                                   StringRef Dir32,
185
                                                   StringRef Dir64,
186
0
                                                   const llvm::Triple &triple) {
187
0
  // Add the base dir
188
0
  bool IsBaseFound = AddPath(Base, CXXSystem, false);
189
0
190
0
  // 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
0
  // 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
9.86k
                                            const HeaderSearchOptions &HSOpts) {
216
9.86k
  llvm::Triple::OSType os = triple.getOS();
217
9.86k
218
9.86k
  if (triple.isOSDarwin()) {
219
0
    llvm_unreachable("Include management is handled in the driver.");
220
0
  }
221
9.86k
222
9.86k
  if (HSOpts.UseStandardSystemIncludes) {
223
2.52k
    switch (os) {
224
36
    case llvm::Triple::CloudABI:
225
36
    case llvm::Triple::FreeBSD:
226
36
    case llvm::Triple::NetBSD:
227
36
    case llvm::Triple::OpenBSD:
228
36
    case llvm::Triple::NaCl:
229
36
    case llvm::Triple::PS4:
230
36
    case llvm::Triple::ELFIAMCU:
231
36
    case llvm::Triple::Fuchsia:
232
36
      break;
233
36
    case llvm::Triple::Win32:
234
0
      if (triple.getEnvironment() != llvm::Triple::Cygnus)
235
0
        break;
236
0
      LLVM_FALLTHROUGH;
237
2.49k
    default:
238
2.49k
      // FIXME: temporary hack: hard-coded paths.
239
2.49k
      AddPath("/usr/local/include", System, false);
240
2.49k
      break;
241
9.86k
    }
242
9.86k
  }
243
9.86k
244
9.86k
  // Builtin includes use #include_next directives and should be positioned
245
9.86k
  // just prior C include dirs.
246
9.86k
  if (HSOpts.UseBuiltinIncludes) {
247
9.86k
    // Ignore the sys root, we *always* look for clang headers relative to
248
9.86k
    // supplied path.
249
9.86k
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
250
9.86k
    llvm::sys::path::append(P, "include");
251
9.86k
    AddUnmappedPath(P, ExternCSystem, false);
252
9.86k
  }
253
9.86k
254
9.86k
  // All remaining additions are for system include directories, early exit if
255
9.86k
  // we aren't using them.
256
9.86k
  if (!HSOpts.UseStandardSystemIncludes)
257
7.33k
    return;
258
2.52k
259
2.52k
  // Add dirs specified via 'configure --with-c-include-dirs'.
260
2.52k
  StringRef CIncludeDirs(C_INCLUDE_DIRS);
261
2.52k
  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
2.52k
269
2.52k
  switch (os) {
270
0
  case llvm::Triple::Linux:
271
0
  case llvm::Triple::Hurd:
272
0
  case llvm::Triple::Solaris:
273
0
    llvm_unreachable("Include management is handled in the driver.");
274
0
275
4
  case llvm::Triple::CloudABI: {
276
4
    // <sysroot>/<triple>/include
277
4
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
278
4
    llvm::sys::path::append(P, "../../..", triple.str(), "include");
279
4
    AddPath(P, System, false);
280
4
    break;
281
0
  }
282
0
283
0
  case llvm::Triple::Haiku:
284
0
    AddPath("/boot/system/non-packaged/develop/headers", System, false);
285
0
    AddPath("/boot/system/develop/headers/os", System, false);
286
0
    AddPath("/boot/system/develop/headers/os/app", System, false);
287
0
    AddPath("/boot/system/develop/headers/os/arch", System, false);
288
0
    AddPath("/boot/system/develop/headers/os/device", System, false);
289
0
    AddPath("/boot/system/develop/headers/os/drivers", System, false);
290
0
    AddPath("/boot/system/develop/headers/os/game", System, false);
291
0
    AddPath("/boot/system/develop/headers/os/interface", System, false);
292
0
    AddPath("/boot/system/develop/headers/os/kernel", System, false);
293
0
    AddPath("/boot/system/develop/headers/os/locale", System, false);
294
0
    AddPath("/boot/system/develop/headers/os/mail", System, false);
295
0
    AddPath("/boot/system/develop/headers/os/media", System, false);
296
0
    AddPath("/boot/system/develop/headers/os/midi", System, false);
297
0
    AddPath("/boot/system/develop/headers/os/midi2", System, false);
298
0
    AddPath("/boot/system/develop/headers/os/net", System, false);
299
0
    AddPath("/boot/system/develop/headers/os/opengl", System, false);
300
0
    AddPath("/boot/system/develop/headers/os/storage", System, false);
301
0
    AddPath("/boot/system/develop/headers/os/support", System, false);
302
0
    AddPath("/boot/system/develop/headers/os/translation", System, false);
303
0
    AddPath("/boot/system/develop/headers/os/add-ons/graphics", System, false);
304
0
    AddPath("/boot/system/develop/headers/os/add-ons/input_server", System, false);
305
0
    AddPath("/boot/system/develop/headers/os/add-ons/mail_daemon", System, false);
306
0
    AddPath("/boot/system/develop/headers/os/add-ons/registrar", System, false);
307
0
    AddPath("/boot/system/develop/headers/os/add-ons/screen_saver", System, false);
308
0
    AddPath("/boot/system/develop/headers/os/add-ons/tracker", System, false);
309
0
    AddPath("/boot/system/develop/headers/os/be_apps/Deskbar", System, false);
310
0
    AddPath("/boot/system/develop/headers/os/be_apps/NetPositive", System, false);
311
0
    AddPath("/boot/system/develop/headers/os/be_apps/Tracker", System, false);
312
0
    AddPath("/boot/system/develop/headers/3rdparty", System, false);
313
0
    AddPath("/boot/system/develop/headers/bsd", System, false);
314
0
    AddPath("/boot/system/develop/headers/glibc", System, false);
315
0
    AddPath("/boot/system/develop/headers/posix", System, false);
316
0
    AddPath("/boot/system/develop/headers",  System, false);
317
0
    break;
318
4
  case llvm::Triple::RTEMS:
319
4
    break;
320
0
  case llvm::Triple::Win32:
321
0
    switch (triple.getEnvironment()) {
322
0
    default: llvm_unreachable("Include management is handled in the driver.");
323
0
    case llvm::Triple::Cygnus:
324
0
      AddPath("/usr/include/w32api", System, false);
325
0
      break;
326
0
    case llvm::Triple::GNU:
327
0
      break;
328
0
    }
329
0
    break;
330
2.51k
  default:
331
2.51k
    break;
332
2.52k
  }
333
2.52k
334
2.52k
  switch (os) {
335
16
  case llvm::Triple::CloudABI:
336
16
  case llvm::Triple::RTEMS:
337
16
  case llvm::Triple::NaCl:
338
16
  case llvm::Triple::ELFIAMCU:
339
16
  case llvm::Triple::Fuchsia:
340
16
    break;
341
16
  case llvm::Triple::PS4: {
342
6
    // <isysroot> gets prepended later in AddPath().
343
6
    std::string BaseSDKPath = "";
344
6
    if (!HasSysroot) {
345
5
      const char *envValue = getenv("SCE_ORBIS_SDK_DIR");
346
5
      if (envValue)
347
1
        BaseSDKPath = envValue;
348
4
      else {
349
4
        // HSOpts.ResourceDir variable contains the location of Clang's
350
4
        // resource files.
351
4
        // Assuming that Clang is configured for PS4 without
352
4
        // --with-clang-resource-dir option, the location of Clang's resource
353
4
        // files is <SDK_DIR>/host_tools/lib/clang
354
4
        SmallString<128> P = StringRef(HSOpts.ResourceDir);
355
4
        llvm::sys::path::append(P, "../../..");
356
4
        BaseSDKPath = std::string(P.str());
357
4
      }
358
5
    }
359
6
    AddPath(BaseSDKPath + "/target/include", System, false);
360
6
    if (triple.isPS4CPU())
361
6
      AddPath(BaseSDKPath + "/target/include_common", System, false);
362
6
    LLVM_FALLTHROUGH;
363
6
  }
364
2.51k
  default:
365
2.51k
    AddPath("/usr/include", ExternCSystem, false);
366
2.51k
    break;
367
2.52k
  }
368
2.52k
}
369
370
void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
371
    const LangOptions &LangOpts, const llvm::Triple &triple,
372
2.01k
    const HeaderSearchOptions &HSOpts) {
373
2.01k
  llvm::Triple::OSType os = triple.getOS();
374
2.01k
  // FIXME: temporary hack: hard-coded paths.
375
2.01k
376
2.01k
  if (triple.isOSDarwin()) {
377
0
    llvm_unreachable("Include management is handled in the driver.");
378
0
  }
379
2.01k
380
2.01k
  switch (os) {
381
0
  case llvm::Triple::Linux:
382
0
  case llvm::Triple::Hurd:
383
0
  case llvm::Triple::Solaris:
384
0
    llvm_unreachable("Include management is handled in the driver.");
385
0
    break;
386
0
  case llvm::Triple::Win32:
387
0
    switch (triple.getEnvironment()) {
388
0
    default: llvm_unreachable("Include management is handled in the driver.");
389
0
    case llvm::Triple::Cygnus:
390
0
      // Cygwin-1.7
391
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3");
392
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3");
393
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
394
0
      // g++-4 / Cygwin-1.5
395
0
      AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
396
0
      break;
397
0
    }
398
0
    break;
399
0
  case llvm::Triple::DragonFly:
400
0
    AddPath("/usr/include/c++/5.0", CXXSystem, false);
401
0
    break;
402
0
  case llvm::Triple::Minix:
403
0
    AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
404
0
                                "", "", "", triple);
405
0
    break;
406
2.01k
  default:
407
2.01k
    break;
408
2.01k
  }
409
2.01k
}
410
411
void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
412
                                              const llvm::Triple &triple,
413
59.3k
                                            const HeaderSearchOptions &HSOpts) {
414
59.3k
  // NB: This code path is going away. All of the logic is moving into the
415
59.3k
  // driver which has the information necessary to do target-specific
416
59.3k
  // selections of default include paths. Each target which moves there will be
417
59.3k
  // exempted from this logic here until we can delete the entire pile of code.
418
59.3k
  switch (triple.getOS()) {
419
45.6k
  default:
420
45.6k
    break; // Everything else continues to use this routine's logic.
421
0
422
2.79k
  case llvm::Triple::Emscripten:
423
2.79k
  case llvm::Triple::Linux:
424
2.79k
  case llvm::Triple::Hurd:
425
2.79k
  case llvm::Triple::Solaris:
426
2.79k
  case llvm::Triple::WASI:
427
2.79k
    return;
428
2.79k
429
2.79k
  case llvm::Triple::Win32:
430
1.27k
    if (triple.getEnvironment() != llvm::Triple::Cygnus ||
431
1.27k
        
triple.isOSBinFormatMachO()15
)
432
1.25k
      return;
433
15
    break;
434
15
435
9.54k
  case llvm::Triple::UnknownOS:
436
9.54k
    if (triple.getArch() == llvm::Triple::wasm32 ||
437
9.54k
        
triple.getArch() == llvm::Triple::wasm649.50k
)
438
67
      return;
439
9.47k
    break;
440
55.1k
  }
441
55.1k
442
55.1k
  // All header search logic is handled in the Driver for Darwin.
443
55.1k
  if (triple.isOSDarwin()) {
444
45.3k
    if (HSOpts.UseStandardSystemIncludes) {
445
28.9k
      // Add the default framework include paths on Darwin.
446
28.9k
      AddPath("/System/Library/Frameworks", System, true);
447
28.9k
      AddPath("/Library/Frameworks", System, true);
448
28.9k
    }
449
45.3k
    return;
450
45.3k
  }
451
9.86k
452
9.86k
  if (Lang.CPlusPlus && 
!Lang.AsmPreprocessor7.54k
&&
453
9.86k
      
HSOpts.UseStandardCXXIncludes7.54k
&&
HSOpts.UseStandardSystemIncludes7.52k
) {
454
2.01k
    if (HSOpts.UseLibcxx) {
455
4
      AddPath("/usr/include/c++/v1", CXXSystem, false);
456
2.01k
    } else {
457
2.01k
      AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
458
2.01k
    }
459
2.01k
  }
460
9.86k
461
9.86k
  AddDefaultCIncludePaths(triple, HSOpts);
462
9.86k
}
463
464
/// RemoveDuplicates - If there are duplicate directory entries in the specified
465
/// search list, remove the later (dead) ones.  Returns the number of non-system
466
/// headers removed, which is used to update NumAngled.
467
static unsigned RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
468
177k
                                 unsigned First, bool Verbose) {
469
177k
  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
470
177k
  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
471
177k
  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
472
177k
  unsigned NonSystemRemoved = 0;
473
336k
  for (unsigned i = First; i != SearchList.size(); 
++i158k
) {
474
158k
    unsigned DirToRemove = i;
475
158k
476
158k
    const DirectoryLookup &CurEntry = SearchList[i];
477
158k
478
158k
    if (CurEntry.isNormalDir()) {
479
110k
      // If this isn't the first time we've seen this dir, remove it.
480
110k
      if (SeenDirs.insert(CurEntry.getDir()).second)
481
102k
        continue;
482
48.2k
    } else if (CurEntry.isFramework()) {
483
48.1k
      // If this isn't the first time we've seen this framework dir, remove it.
484
48.1k
      if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
485
48.1k
        continue;
486
39
    } else {
487
39
      assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
488
39
      // If this isn't the first time we've seen this headermap, remove it.
489
39
      if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
490
39
        continue;
491
7.64k
    }
492
7.64k
493
7.64k
    // If we have a normal #include dir/framework/headermap that is shadowed
494
7.64k
    // later in the chain by a system include location, we actually want to
495
7.64k
    // ignore the user's request and drop the user dir... keeping the system
496
7.64k
    // dir.  This is weird, but required to emulate GCC's search path correctly.
497
7.64k
    //
498
7.64k
    // Since dupes of system dirs are rare, just rescan to find the original
499
7.64k
    // that we're nuking instead of using a DenseMap.
500
7.64k
    if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
501
7.48k
      // Find the dir that this is the same of.
502
7.48k
      unsigned FirstDir;
503
7.69k
      for (FirstDir = First;; 
++FirstDir208
) {
504
7.69k
        assert(FirstDir != i && "Didn't find dupe?");
505
7.69k
506
7.69k
        const DirectoryLookup &SearchEntry = SearchList[FirstDir];
507
7.69k
508
7.69k
        // If these are different lookup types, then they can't be the dupe.
509
7.69k
        if (SearchEntry.getLookupType() != CurEntry.getLookupType())
510
40
          continue;
511
7.65k
512
7.65k
        bool isSame;
513
7.65k
        if (CurEntry.isNormalDir())
514
7.65k
          isSame = SearchEntry.getDir() == CurEntry.getDir();
515
2
        else if (CurEntry.isFramework())
516
2
          isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
517
0
        else {
518
0
          assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
519
0
          isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
520
0
        }
521
7.65k
522
7.65k
        if (isSame)
523
7.48k
          break;
524
7.65k
      }
525
7.48k
526
7.48k
      // If the first dir in the search path is a non-system dir, zap it
527
7.48k
      // instead of the system one.
528
7.48k
      if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
529
12
        DirToRemove = FirstDir;
530
7.48k
    }
531
7.64k
532
7.64k
    if (Verbose) {
533
3
      llvm::errs() << "ignoring duplicate directory \""
534
3
                   << CurEntry.getName() << "\"\n";
535
3
      if (DirToRemove != i)
536
0
        llvm::errs() << "  as it is a non-system directory that duplicates "
537
0
                     << "a system directory\n";
538
3
    }
539
7.64k
    if (DirToRemove != i)
540
12
      ++NonSystemRemoved;
541
7.64k
542
7.64k
    // This is reached if the current entry is a duplicate.  Remove the
543
7.64k
    // DirToRemove (usually the current dir).
544
7.64k
    SearchList.erase(SearchList.begin()+DirToRemove);
545
7.64k
    --i;
546
7.64k
  }
547
177k
  return NonSystemRemoved;
548
177k
}
549
550
551
59.3k
void InitHeaderSearch::Realize(const LangOptions &Lang) {
552
59.3k
  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
553
59.3k
  std::vector<DirectoryLookup> SearchList;
554
59.3k
  SearchList.reserve(IncludePath.size());
555
59.3k
556
59.3k
  // Quoted arguments go first.
557
59.3k
  for (auto &Include : IncludePath)
558
137k
    if (Include.first == Quoted)
559
50
      SearchList.push_back(Include.second);
560
59.3k
561
59.3k
  // Deduplicate and remember index.
562
59.3k
  RemoveDuplicates(SearchList, 0, Verbose);
563
59.3k
  unsigned NumQuoted = SearchList.size();
564
59.3k
565
59.3k
  for (auto &Include : IncludePath)
566
137k
    if (Include.first == Angled || 
Include.first == IndexHeaderMap117k
)
567
20.6k
      SearchList.push_back(Include.second);
568
59.3k
569
59.3k
  RemoveDuplicates(SearchList, NumQuoted, Verbose);
570
59.3k
  unsigned NumAngled = SearchList.size();
571
59.3k
572
59.3k
  for (auto &Include : IncludePath)
573
137k
    if (Include.first == System || 
Include.first == ExternCSystem39.0k
||
574
137k
        
(20.7k
!Lang.ObjC20.7k
&&
!Lang.CPlusPlus16.2k
&&
Include.first == CSystem4.93k
) ||
575
137k
        
(/*FIXME !Lang.ObjC && */ 20.7k
Lang.CPlusPlus20.7k
&&
576
20.7k
         
Include.first == CXXSystem11.9k
) ||
577
137k
        
(20.7k
Lang.ObjC20.7k
&&
!Lang.CPlusPlus4.51k
&&
Include.first == ObjCSystem3.91k
) ||
578
137k
        
(20.7k
Lang.ObjC20.7k
&&
Lang.CPlusPlus4.51k
&&
Include.first == ObjCXXSystem598
))
579
116k
      SearchList.push_back(Include.second);
580
59.3k
581
59.3k
  for (auto &Include : IncludePath)
582
137k
    if (Include.first == After)
583
11
      SearchList.push_back(Include.second);
584
59.3k
585
59.3k
  // Remove duplicates across both the Angled and System directories.  GCC does
586
59.3k
  // this and failing to remove duplicates across these two groups breaks
587
59.3k
  // #include_next.
588
59.3k
  unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
589
59.3k
  NumAngled -= NonSystemRemoved;
590
59.3k
591
59.3k
  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
592
59.3k
  Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir);
593
59.3k
594
59.3k
  Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
595
59.3k
596
59.3k
  // If verbose, print the list of directories that will be searched.
597
59.3k
  if (Verbose) {
598
52
    llvm::errs() << "#include \"...\" search starts here:\n";
599
250
    for (unsigned i = 0, e = SearchList.size(); i != e; 
++i198
) {
600
198
      if (i == NumQuoted)
601
50
        llvm::errs() << "#include <...> search starts here:\n";
602
198
      StringRef Name = SearchList[i].getName();
603
198
      const char *Suffix;
604
198
      if (SearchList[i].isNormalDir())
605
137
        Suffix = "";
606
61
      else if (SearchList[i].isFramework())
607
61
        Suffix = " (framework directory)";
608
0
      else {
609
0
        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
610
0
        Suffix = " (headermap)";
611
0
      }
612
198
      llvm::errs() << " " << Name << Suffix << "\n";
613
198
    }
614
52
    llvm::errs() << "End of search list.\n";
615
52
  }
616
59.3k
}
617
618
void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
619
                                     const HeaderSearchOptions &HSOpts,
620
                                     const LangOptions &Lang,
621
59.2k
                                     const llvm::Triple &Triple) {
622
59.2k
  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
623
59.2k
624
59.2k
  // Add the user defined entries.
625
188k
  for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; 
++i129k
) {
626
129k
    const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
627
129k
    if (E.IgnoreSysRoot) {
628
129k
      Init.AddUnmappedPath(E.Path, E.Group, E.IsFramework);
629
129k
    } else {
630
0
      Init.AddPath(E.Path, E.Group, E.IsFramework);
631
0
    }
632
129k
  }
633
59.2k
634
59.2k
  Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
635
59.2k
636
59.3k
  for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; 
++i4
)
637
4
    Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
638
4
                               HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
639
59.2k
640
59.2k
  if (HSOpts.UseBuiltinIncludes) {
641
59.2k
    // Set up the builtin include directory in the module map.
642
59.2k
    SmallString<128> P = StringRef(HSOpts.ResourceDir);
643
59.2k
    llvm::sys::path::append(P, "include");
644
59.2k
    if (auto Dir = HS.getFileMgr().getDirectory(P))
645
39.4k
      HS.getModuleMap().setBuiltinIncludeDir(*Dir);
646
59.2k
  }
647
59.2k
648
59.2k
  Init.Realize(Lang);
649
59.2k
}