/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- HeaderSearch.cpp - Resolve Header File Locations -------------------===// |
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 DirectoryLookup and HeaderSearch interfaces. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/Lex/HeaderSearch.h" |
14 | | #include "clang/Basic/Diagnostic.h" |
15 | | #include "clang/Basic/FileManager.h" |
16 | | #include "clang/Basic/IdentifierTable.h" |
17 | | #include "clang/Basic/Module.h" |
18 | | #include "clang/Basic/SourceManager.h" |
19 | | #include "clang/Lex/DirectoryLookup.h" |
20 | | #include "clang/Lex/ExternalPreprocessorSource.h" |
21 | | #include "clang/Lex/HeaderMap.h" |
22 | | #include "clang/Lex/HeaderSearchOptions.h" |
23 | | #include "clang/Lex/LexDiagnostic.h" |
24 | | #include "clang/Lex/ModuleMap.h" |
25 | | #include "clang/Lex/Preprocessor.h" |
26 | | #include "llvm/ADT/APInt.h" |
27 | | #include "llvm/ADT/Hashing.h" |
28 | | #include "llvm/ADT/SmallString.h" |
29 | | #include "llvm/ADT/SmallVector.h" |
30 | | #include "llvm/ADT/StringRef.h" |
31 | | #include "llvm/Support/Allocator.h" |
32 | | #include "llvm/Support/Capacity.h" |
33 | | #include "llvm/Support/ErrorHandling.h" |
34 | | #include "llvm/Support/FileSystem.h" |
35 | | #include "llvm/Support/Path.h" |
36 | | #include "llvm/Support/VirtualFileSystem.h" |
37 | | #include <algorithm> |
38 | | #include <cassert> |
39 | | #include <cstddef> |
40 | | #include <cstdio> |
41 | | #include <cstring> |
42 | | #include <string> |
43 | | #include <system_error> |
44 | | #include <utility> |
45 | | |
46 | | using namespace clang; |
47 | | |
48 | | const IdentifierInfo * |
49 | 993k | HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) { |
50 | 993k | if (ControllingMacro) { |
51 | 516k | if (ControllingMacro->isOutOfDate()) { |
52 | 3 | assert(External && "We must have an external source if we have a " |
53 | 3 | "controlling macro that is out of date."); |
54 | 3 | External->updateOutOfDateIdentifier( |
55 | 3 | *const_cast<IdentifierInfo *>(ControllingMacro)); |
56 | 3 | } |
57 | 516k | return ControllingMacro; |
58 | 516k | } |
59 | 477k | |
60 | 477k | if (!ControllingMacroID || !External65 ) |
61 | 477k | return nullptr; |
62 | 65 | |
63 | 65 | ControllingMacro = External->GetIdentifier(ControllingMacroID); |
64 | 65 | return ControllingMacro; |
65 | 65 | } |
66 | | |
67 | 5.27k | ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default; |
68 | | |
69 | | HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, |
70 | | SourceManager &SourceMgr, DiagnosticsEngine &Diags, |
71 | | const LangOptions &LangOpts, |
72 | | const TargetInfo *Target) |
73 | | : HSOpts(std::move(HSOpts)), Diags(Diags), |
74 | | FileMgr(SourceMgr.getFileManager()), FrameworkMap(64), |
75 | 44.2k | ModMap(SourceMgr, Diags, LangOpts, Target, *this) {} |
76 | | |
77 | 3 | void HeaderSearch::PrintStats() { |
78 | 3 | fprintf(stderr, "\n*** HeaderSearch Stats:\n"); |
79 | 3 | fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); |
80 | 3 | unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; |
81 | 151 | for (unsigned i = 0, e = FileInfo.size(); i != e; ++i148 ) { |
82 | 148 | NumOnceOnlyFiles += FileInfo[i].isImport; |
83 | 148 | if (MaxNumIncludes < FileInfo[i].NumIncludes) |
84 | 3 | MaxNumIncludes = FileInfo[i].NumIncludes; |
85 | 148 | NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; |
86 | 148 | } |
87 | 3 | fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); |
88 | 3 | fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); |
89 | 3 | fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); |
90 | 3 | |
91 | 3 | fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); |
92 | 3 | fprintf(stderr, " %d #includes skipped due to" |
93 | 3 | " the multi-include optimization.\n", NumMultiIncludeFileOptzn); |
94 | 3 | |
95 | 3 | fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); |
96 | 3 | fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); |
97 | 3 | } |
98 | | |
99 | | /// CreateHeaderMap - This method returns a HeaderMap for the specified |
100 | | /// FileEntry, uniquing them through the 'HeaderMaps' datastructure. |
101 | 34 | const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { |
102 | 34 | // We expect the number of headermaps to be small, and almost always empty. |
103 | 34 | // If it ever grows, use of a linear search should be re-evaluated. |
104 | 34 | if (!HeaderMaps.empty()) { |
105 | 22 | for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i11 ) |
106 | 11 | // Pointer equality comparison of FileEntries works because they are |
107 | 11 | // already uniqued by inode. |
108 | 11 | if (HeaderMaps[i].first == FE) |
109 | 0 | return HeaderMaps[i].second.get(); |
110 | 11 | } |
111 | 34 | |
112 | 34 | if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) { |
113 | 30 | HeaderMaps.emplace_back(FE, std::move(HM)); |
114 | 30 | return HeaderMaps.back().second.get(); |
115 | 30 | } |
116 | 4 | |
117 | 4 | return nullptr; |
118 | 4 | } |
119 | | |
120 | | /// Get filenames for all registered header maps. |
121 | | void HeaderSearch::getHeaderMapFileNames( |
122 | 35 | SmallVectorImpl<std::string> &Names) const { |
123 | 35 | for (auto &HM : HeaderMaps) |
124 | 1 | Names.push_back(HM.first->getName()); |
125 | 35 | } |
126 | | |
127 | 1.68k | std::string HeaderSearch::getCachedModuleFileName(Module *Module) { |
128 | 1.68k | const FileEntry *ModuleMap = |
129 | 1.68k | getModuleMap().getModuleMapFileForUniquing(Module); |
130 | 1.68k | return getCachedModuleFileName(Module->Name, ModuleMap->getName()); |
131 | 1.68k | } |
132 | | |
133 | | std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, |
134 | 1.73k | bool FileMapOnly) { |
135 | 1.73k | // First check the module name to pcm file map. |
136 | 1.73k | auto i (HSOpts->PrebuiltModuleFiles.find(ModuleName)); |
137 | 1.73k | if (i != HSOpts->PrebuiltModuleFiles.end()) |
138 | 11 | return i->second; |
139 | 1.72k | |
140 | 1.72k | if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty()7 ) |
141 | 1.71k | return {}; |
142 | 7 | |
143 | 7 | // Then go through each prebuilt module directory and try to find the pcm |
144 | 7 | // file. |
145 | 7 | for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { |
146 | 7 | SmallString<256> Result(Dir); |
147 | 7 | llvm::sys::fs::make_absolute(Result); |
148 | 7 | llvm::sys::path::append(Result, ModuleName + ".pcm"); |
149 | 7 | if (getFileMgr().getFile(Result.str())) |
150 | 7 | return Result.str().str(); |
151 | 7 | } |
152 | 7 | return {}0 ; |
153 | 7 | } |
154 | | |
155 | | std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, |
156 | 1.72k | StringRef ModuleMapPath) { |
157 | 1.72k | // If we don't have a module cache path or aren't supposed to use one, we |
158 | 1.72k | // can't do anything. |
159 | 1.72k | if (getModuleCachePath().empty()) |
160 | 12 | return {}; |
161 | 1.71k | |
162 | 1.71k | SmallString<256> Result(getModuleCachePath()); |
163 | 1.71k | llvm::sys::fs::make_absolute(Result); |
164 | 1.71k | |
165 | 1.71k | if (HSOpts->DisableModuleHash) { |
166 | 171 | llvm::sys::path::append(Result, ModuleName + ".pcm"); |
167 | 1.54k | } else { |
168 | 1.54k | // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should |
169 | 1.54k | // ideally be globally unique to this particular module. Name collisions |
170 | 1.54k | // in the hash are safe (because any translation unit can only import one |
171 | 1.54k | // module with each name), but result in a loss of caching. |
172 | 1.54k | // |
173 | 1.54k | // To avoid false-negatives, we form as canonical a path as we can, and map |
174 | 1.54k | // to lower-case in case we're on a case-insensitive file system. |
175 | 1.54k | std::string Parent = llvm::sys::path::parent_path(ModuleMapPath); |
176 | 1.54k | if (Parent.empty()) |
177 | 1 | Parent = "."; |
178 | 1.54k | auto *Dir = FileMgr.getDirectory(Parent); |
179 | 1.54k | if (!Dir) |
180 | 0 | return {}; |
181 | 1.54k | auto DirName = FileMgr.getCanonicalName(Dir); |
182 | 1.54k | auto FileName = llvm::sys::path::filename(ModuleMapPath); |
183 | 1.54k | |
184 | 1.54k | llvm::hash_code Hash = |
185 | 1.54k | llvm::hash_combine(DirName.lower(), FileName.lower()); |
186 | 1.54k | |
187 | 1.54k | SmallString<128> HashStr; |
188 | 1.54k | llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36); |
189 | 1.54k | llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm"); |
190 | 1.54k | } |
191 | 1.71k | return Result.str().str(); |
192 | 1.71k | } |
193 | | |
194 | | Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch, |
195 | 35.3k | bool AllowExtraModuleMapSearch) { |
196 | 35.3k | // Look in the module map to determine if there is a module by this name. |
197 | 35.3k | Module *Module = ModMap.findModule(ModuleName); |
198 | 35.3k | if (Module || !AllowSearch1.01k || !HSOpts->ImplicitModuleMaps1.01k ) |
199 | 34.7k | return Module; |
200 | 609 | |
201 | 609 | StringRef SearchName = ModuleName; |
202 | 609 | Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); |
203 | 609 | |
204 | 609 | // The facility for "private modules" -- adjacent, optional module maps named |
205 | 609 | // module.private.modulemap that are supposed to define private submodules -- |
206 | 609 | // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private. |
207 | 609 | // |
208 | 609 | // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate |
209 | 609 | // should also rename to Foo_Private. Representing private as submodules |
210 | 609 | // could force building unwanted dependencies into the parent module and cause |
211 | 609 | // dependency cycles. |
212 | 609 | if (!Module && SearchName.consume_back("_Private")32 ) |
213 | 4 | Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); |
214 | 609 | if (!Module && SearchName.consume_back("Private")29 ) |
215 | 4 | Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); |
216 | 609 | return Module; |
217 | 609 | } |
218 | | |
219 | | Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, |
220 | 617 | bool AllowExtraModuleMapSearch) { |
221 | 617 | Module *Module = nullptr; |
222 | 617 | |
223 | 617 | // Look through the various header search paths to load any available module |
224 | 617 | // maps, searching for a module map that describes this module. |
225 | 780 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx163 ) { |
226 | 746 | if (SearchDirs[Idx].isFramework()) { |
227 | 268 | // Search for or infer a module map for a framework. Here we use |
228 | 268 | // SearchName rather than ModuleName, to permit finding private modules |
229 | 268 | // named FooPrivate in buggy frameworks named Foo. |
230 | 268 | SmallString<128> FrameworkDirName; |
231 | 268 | FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName(); |
232 | 268 | llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); |
233 | 268 | if (const DirectoryEntry *FrameworkDir |
234 | 217 | = FileMgr.getDirectory(FrameworkDirName)) { |
235 | 217 | bool IsSystem |
236 | 217 | = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; |
237 | 217 | Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); |
238 | 217 | if (Module) |
239 | 206 | break; |
240 | 540 | } |
241 | 268 | } |
242 | 540 | |
243 | 540 | // FIXME: Figure out how header maps and module maps will work together. |
244 | 540 | |
245 | 540 | // Only deal with normal search directories. |
246 | 540 | if (!SearchDirs[Idx].isNormalDir()) |
247 | 66 | continue; |
248 | 474 | |
249 | 474 | bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory(); |
250 | 474 | // Search for a module map file in this directory. |
251 | 474 | if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, |
252 | 474 | /*IsFramework*/false) == LMM_NewlyLoaded) { |
253 | 396 | // We just loaded a module map file; check whether the module is |
254 | 396 | // available now. |
255 | 396 | Module = ModMap.findModule(ModuleName); |
256 | 396 | if (Module) |
257 | 359 | break; |
258 | 115 | } |
259 | 115 | |
260 | 115 | // Search for a module map in a subdirectory with the same name as the |
261 | 115 | // module. |
262 | 115 | SmallString<128> NestedModuleMapDirName; |
263 | 115 | NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName(); |
264 | 115 | llvm::sys::path::append(NestedModuleMapDirName, ModuleName); |
265 | 115 | if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, |
266 | 115 | /*IsFramework*/false) == LMM_NewlyLoaded){ |
267 | 14 | // If we just loaded a module map file, look for the module again. |
268 | 14 | Module = ModMap.findModule(ModuleName); |
269 | 14 | if (Module) |
270 | 14 | break; |
271 | 101 | } |
272 | 101 | |
273 | 101 | // If we've already performed the exhaustive search for module maps in this |
274 | 101 | // search directory, don't do it again. |
275 | 101 | if (SearchDirs[Idx].haveSearchedAllModuleMaps()) |
276 | 25 | continue; |
277 | 76 | |
278 | 76 | // Load all module maps in the immediate subdirectories of this search |
279 | 76 | // directory if ModuleName was from @import. |
280 | 76 | if (AllowExtraModuleMapSearch) |
281 | 73 | loadSubdirectoryModuleMaps(SearchDirs[Idx]); |
282 | 76 | |
283 | 76 | // Look again for the module. |
284 | 76 | Module = ModMap.findModule(ModuleName); |
285 | 76 | if (Module) |
286 | 4 | break; |
287 | 76 | } |
288 | 617 | |
289 | 617 | return Module; |
290 | 617 | } |
291 | | |
292 | | //===----------------------------------------------------------------------===// |
293 | | // File lookup within a DirectoryLookup scope |
294 | | //===----------------------------------------------------------------------===// |
295 | | |
296 | | /// getName - Return the directory or filename corresponding to this lookup |
297 | | /// object. |
298 | 300 | StringRef DirectoryLookup::getName() const { |
299 | 300 | if (isNormalDir()) |
300 | 211 | return getDir()->getName(); |
301 | 89 | if (isFramework()) |
302 | 88 | return getFrameworkDir()->getName(); |
303 | 1 | assert(isHeaderMap() && "Unknown DirectoryLookup"); |
304 | 1 | return getHeaderMap()->getFileName(); |
305 | 1 | } |
306 | | |
307 | | const FileEntry *HeaderSearch::getFileAndSuggestModule( |
308 | | StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir, |
309 | | bool IsSystemHeaderDir, Module *RequestingModule, |
310 | 1.75M | ModuleMap::KnownHeader *SuggestedModule) { |
311 | 1.75M | // If we have a module map that might map this header, load it and |
312 | 1.75M | // check whether we'll have a suggestion for a module. |
313 | 1.75M | const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true); |
314 | 1.75M | if (!File) |
315 | 753k | return nullptr; |
316 | 1.00M | |
317 | 1.00M | // If there is a module that corresponds to this header, suggest it. |
318 | 1.00M | if (!findUsableModuleForHeader(File, Dir ? Dir1.00M : File->getDir()291 , |
319 | 1.00M | RequestingModule, SuggestedModule, |
320 | 1.00M | IsSystemHeaderDir)) |
321 | 8 | return nullptr; |
322 | 1.00M | |
323 | 1.00M | return File; |
324 | 1.00M | } |
325 | | |
326 | | /// LookupFile - Lookup the specified file in this search path, returning it |
327 | | /// if it exists or returning null if not. |
328 | | const FileEntry *DirectoryLookup::LookupFile( |
329 | | StringRef &Filename, |
330 | | HeaderSearch &HS, |
331 | | SourceLocation IncludeLoc, |
332 | | SmallVectorImpl<char> *SearchPath, |
333 | | SmallVectorImpl<char> *RelativePath, |
334 | | Module *RequestingModule, |
335 | | ModuleMap::KnownHeader *SuggestedModule, |
336 | | bool &InUserSpecifiedSystemFramework, |
337 | | bool &IsFrameworkFound, |
338 | | bool &HasBeenMapped, |
339 | 1.59M | SmallVectorImpl<char> &MappedName) const { |
340 | 1.59M | InUserSpecifiedSystemFramework = false; |
341 | 1.59M | HasBeenMapped = false; |
342 | 1.59M | |
343 | 1.59M | SmallString<1024> TmpDir; |
344 | 1.59M | if (isNormalDir()) { |
345 | 1.57M | // Concatenate the requested file onto the directory. |
346 | 1.57M | TmpDir = getDir()->getName(); |
347 | 1.57M | llvm::sys::path::append(TmpDir, Filename); |
348 | 1.57M | if (SearchPath) { |
349 | 1.52M | StringRef SearchPathRef(getDir()->getName()); |
350 | 1.52M | SearchPath->clear(); |
351 | 1.52M | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
352 | 1.52M | } |
353 | 1.57M | if (RelativePath) { |
354 | 1.52M | RelativePath->clear(); |
355 | 1.52M | RelativePath->append(Filename.begin(), Filename.end()); |
356 | 1.52M | } |
357 | 1.57M | |
358 | 1.57M | return HS.getFileAndSuggestModule(TmpDir, IncludeLoc, getDir(), |
359 | 1.57M | isSystemHeaderDirectory(), |
360 | 1.57M | RequestingModule, SuggestedModule); |
361 | 1.57M | } |
362 | 18.9k | |
363 | 18.9k | if (isFramework()) |
364 | 18.9k | return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, |
365 | 18.9k | RequestingModule, SuggestedModule, |
366 | 18.9k | InUserSpecifiedSystemFramework, IsFrameworkFound); |
367 | 40 | |
368 | 40 | assert(isHeaderMap() && "Unknown directory lookup"); |
369 | 40 | const HeaderMap *HM = getHeaderMap(); |
370 | 40 | SmallString<1024> Path; |
371 | 40 | StringRef Dest = HM->lookupFilename(Filename, Path); |
372 | 40 | if (Dest.empty()) |
373 | 22 | return nullptr; |
374 | 18 | |
375 | 18 | const FileEntry *Result; |
376 | 18 | |
377 | 18 | // Check if the headermap maps the filename to a framework include |
378 | 18 | // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the |
379 | 18 | // framework include. |
380 | 18 | if (llvm::sys::path::is_relative(Dest)) { |
381 | 18 | MappedName.clear(); |
382 | 18 | MappedName.append(Dest.begin(), Dest.end()); |
383 | 18 | Filename = StringRef(MappedName.begin(), MappedName.size()); |
384 | 18 | HasBeenMapped = true; |
385 | 18 | Result = HM->LookupFile(Filename, HS.getFileMgr()); |
386 | 18 | } else { |
387 | 0 | Result = HS.getFileMgr().getFile(Dest); |
388 | 0 | } |
389 | 18 | |
390 | 18 | if (Result) { |
391 | 0 | if (SearchPath) { |
392 | 0 | StringRef SearchPathRef(getName()); |
393 | 0 | SearchPath->clear(); |
394 | 0 | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
395 | 0 | } |
396 | 0 | if (RelativePath) { |
397 | 0 | RelativePath->clear(); |
398 | 0 | RelativePath->append(Filename.begin(), Filename.end()); |
399 | 0 | } |
400 | 0 | } |
401 | 18 | return Result; |
402 | 18 | } |
403 | | |
404 | | /// Given a framework directory, find the top-most framework directory. |
405 | | /// |
406 | | /// \param FileMgr The file manager to use for directory lookups. |
407 | | /// \param DirName The name of the framework directory. |
408 | | /// \param SubmodulePath Will be populated with the submodule path from the |
409 | | /// returned top-level module to the originally named framework. |
410 | | static const DirectoryEntry * |
411 | | getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, |
412 | 10.1k | SmallVectorImpl<std::string> &SubmodulePath) { |
413 | 10.1k | assert(llvm::sys::path::extension(DirName) == ".framework" && |
414 | 10.1k | "Not a framework directory"); |
415 | 10.1k | |
416 | 10.1k | // Note: as an egregious but useful hack we use the real path here, because |
417 | 10.1k | // frameworks moving between top-level frameworks to embedded frameworks tend |
418 | 10.1k | // to be symlinked, and we base the logical structure of modules on the |
419 | 10.1k | // physical layout. In particular, we need to deal with crazy includes like |
420 | 10.1k | // |
421 | 10.1k | // #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h> |
422 | 10.1k | // |
423 | 10.1k | // where 'Bar' used to be embedded in 'Foo', is now a top-level framework |
424 | 10.1k | // which one should access with, e.g., |
425 | 10.1k | // |
426 | 10.1k | // #include <Bar/Wibble.h> |
427 | 10.1k | // |
428 | 10.1k | // Similar issues occur when a top-level framework has moved into an |
429 | 10.1k | // embedded framework. |
430 | 10.1k | const DirectoryEntry *TopFrameworkDir = FileMgr.getDirectory(DirName); |
431 | 10.1k | DirName = FileMgr.getCanonicalName(TopFrameworkDir); |
432 | 141k | do { |
433 | 141k | // Get the parent directory name. |
434 | 141k | DirName = llvm::sys::path::parent_path(DirName); |
435 | 141k | if (DirName.empty()) |
436 | 10.1k | break; |
437 | 131k | |
438 | 131k | // Determine whether this directory exists. |
439 | 131k | const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); |
440 | 131k | if (!Dir) |
441 | 0 | break; |
442 | 131k | |
443 | 131k | // If this is a framework directory, then we're a subframework of this |
444 | 131k | // framework. |
445 | 131k | if (llvm::sys::path::extension(DirName) == ".framework") { |
446 | 46 | SubmodulePath.push_back(llvm::sys::path::stem(DirName)); |
447 | 46 | TopFrameworkDir = Dir; |
448 | 46 | } |
449 | 131k | } while (true); |
450 | 10.1k | |
451 | 10.1k | return TopFrameworkDir; |
452 | 10.1k | } |
453 | | |
454 | | static bool needModuleLookup(Module *RequestingModule, |
455 | 1.02M | bool HasSuggestedModule) { |
456 | 1.02M | return HasSuggestedModule || |
457 | 1.02M | (15.5k RequestingModule15.5k && RequestingModule->NoUndeclaredIncludes57 ); |
458 | 1.02M | } |
459 | | |
460 | | /// DoFrameworkLookup - Do a lookup of the specified file in the current |
461 | | /// DirectoryLookup, which is a framework directory. |
462 | | const FileEntry *DirectoryLookup::DoFrameworkLookup( |
463 | | StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, |
464 | | SmallVectorImpl<char> *RelativePath, Module *RequestingModule, |
465 | | ModuleMap::KnownHeader *SuggestedModule, |
466 | 18.9k | bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const { |
467 | 18.9k | FileManager &FileMgr = HS.getFileMgr(); |
468 | 18.9k | |
469 | 18.9k | // Framework names must have a '/' in the filename. |
470 | 18.9k | size_t SlashPos = Filename.find('/'); |
471 | 18.9k | if (SlashPos == StringRef::npos) return nullptr8.78k ; |
472 | 10.1k | |
473 | 10.1k | // Find out if this is the home for the specified framework, by checking |
474 | 10.1k | // HeaderSearch. Possible answers are yes/no and unknown. |
475 | 10.1k | FrameworkCacheEntry &CacheEntry = |
476 | 10.1k | HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); |
477 | 10.1k | |
478 | 10.1k | // If it is known and in some other directory, fail. |
479 | 10.1k | if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()9.76k ) |
480 | 10 | return nullptr; |
481 | 10.1k | |
482 | 10.1k | // Otherwise, construct the path to this framework dir. |
483 | 10.1k | |
484 | 10.1k | // FrameworkName = "/System/Library/Frameworks/" |
485 | 10.1k | SmallString<1024> FrameworkName; |
486 | 10.1k | FrameworkName += getFrameworkDir()->getName(); |
487 | 10.1k | if (FrameworkName.empty() || FrameworkName.back() != '/') |
488 | 10.1k | FrameworkName.push_back('/'); |
489 | 10.1k | |
490 | 10.1k | // FrameworkName = "/System/Library/Frameworks/Cocoa" |
491 | 10.1k | StringRef ModuleName(Filename.begin(), SlashPos); |
492 | 10.1k | FrameworkName += ModuleName; |
493 | 10.1k | |
494 | 10.1k | // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" |
495 | 10.1k | FrameworkName += ".framework/"; |
496 | 10.1k | |
497 | 10.1k | // If the cache entry was unresolved, populate it now. |
498 | 10.1k | if (!CacheEntry.Directory) { |
499 | 418 | HS.IncrementFrameworkLookupCount(); |
500 | 418 | |
501 | 418 | // If the framework dir doesn't exist, we fail. |
502 | 418 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); |
503 | 418 | if (!Dir) return nullptr86 ; |
504 | 332 | |
505 | 332 | // Otherwise, if it does, remember that this is the right direntry for this |
506 | 332 | // framework. |
507 | 332 | CacheEntry.Directory = getFrameworkDir(); |
508 | 332 | |
509 | 332 | // If this is a user search directory, check if the framework has been |
510 | 332 | // user-specified as a system framework. |
511 | 332 | if (getDirCharacteristic() == SrcMgr::C_User) { |
512 | 230 | SmallString<1024> SystemFrameworkMarker(FrameworkName); |
513 | 230 | SystemFrameworkMarker += ".system_framework"; |
514 | 230 | if (llvm::sys::fs::exists(SystemFrameworkMarker)) { |
515 | 5 | CacheEntry.IsUserSpecifiedSystemFramework = true; |
516 | 5 | } |
517 | 230 | } |
518 | 332 | } |
519 | 10.1k | |
520 | 10.1k | // Set out flags. |
521 | 10.1k | InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; |
522 | 10.0k | IsFrameworkFound = CacheEntry.Directory; |
523 | 10.0k | |
524 | 10.0k | if (RelativePath) { |
525 | 10.0k | RelativePath->clear(); |
526 | 10.0k | RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); |
527 | 10.0k | } |
528 | 10.0k | |
529 | 10.0k | // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" |
530 | 10.0k | unsigned OrigSize = FrameworkName.size(); |
531 | 10.0k | |
532 | 10.0k | FrameworkName += "Headers/"; |
533 | 10.0k | |
534 | 10.0k | if (SearchPath) { |
535 | 10.0k | SearchPath->clear(); |
536 | 10.0k | // Without trailing '/'. |
537 | 10.0k | SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); |
538 | 10.0k | } |
539 | 10.0k | |
540 | 10.0k | FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); |
541 | 10.0k | const FileEntry *FE = FileMgr.getFile(FrameworkName, |
542 | 10.0k | /*OpenFile=*/!SuggestedModule); |
543 | 10.0k | if (!FE) { |
544 | 31 | // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" |
545 | 31 | const char *Private = "Private"; |
546 | 31 | FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, |
547 | 31 | Private+strlen(Private)); |
548 | 31 | if (SearchPath) |
549 | 31 | SearchPath->insert(SearchPath->begin()+OrigSize, Private, |
550 | 31 | Private+strlen(Private)); |
551 | 31 | |
552 | 31 | FE = FileMgr.getFile(FrameworkName, /*OpenFile=*/!SuggestedModule); |
553 | 31 | } |
554 | 10.0k | |
555 | 10.0k | // If we found the header and are allowed to suggest a module, do so now. |
556 | 10.0k | if (FE && needModuleLookup(RequestingModule, SuggestedModule)10.0k ) { |
557 | 10.0k | // Find the framework in which this header occurs. |
558 | 10.0k | StringRef FrameworkPath = FE->getDir()->getName(); |
559 | 10.0k | bool FoundFramework = false; |
560 | 20.1k | do { |
561 | 20.1k | // Determine whether this directory exists. |
562 | 20.1k | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath); |
563 | 20.1k | if (!Dir) |
564 | 0 | break; |
565 | 20.1k | |
566 | 20.1k | // If this is a framework directory, then we're a subframework of this |
567 | 20.1k | // framework. |
568 | 20.1k | if (llvm::sys::path::extension(FrameworkPath) == ".framework") { |
569 | 10.0k | FoundFramework = true; |
570 | 10.0k | break; |
571 | 10.0k | } |
572 | 10.1k | |
573 | 10.1k | // Get the parent directory name. |
574 | 10.1k | FrameworkPath = llvm::sys::path::parent_path(FrameworkPath); |
575 | 10.1k | if (FrameworkPath.empty()) |
576 | 0 | break; |
577 | 10.1k | } while (true); |
578 | 10.0k | |
579 | 10.0k | bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; |
580 | 10.1k | if (FoundFramework) { |
581 | 10.0k | if (!HS.findUsableModuleForFrameworkHeader( |
582 | 10.0k | FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem)) |
583 | 0 | return nullptr; |
584 | 65 | } else { |
585 | 65 | if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule, |
586 | 65 | SuggestedModule, IsSystem)) |
587 | 0 | return nullptr; |
588 | 10.1k | } |
589 | 10.0k | } |
590 | 10.1k | return FE; |
591 | 10.1k | } |
592 | | |
593 | 44.2k | void HeaderSearch::setTarget(const TargetInfo &Target) { |
594 | 44.2k | ModMap.setTarget(Target); |
595 | 44.2k | } |
596 | | |
597 | | //===----------------------------------------------------------------------===// |
598 | | // Header File Location. |
599 | | //===----------------------------------------------------------------------===// |
600 | | |
601 | | /// Return true with a diagnostic if the file that MSVC would have found |
602 | | /// fails to match the one that Clang would have found with MSVC header search |
603 | | /// disabled. |
604 | | static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags, |
605 | | const FileEntry *MSFE, const FileEntry *FE, |
606 | 884k | SourceLocation IncludeLoc) { |
607 | 884k | if (MSFE && FE != MSFE2 ) { |
608 | 1 | Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName(); |
609 | 1 | return true; |
610 | 1 | } |
611 | 884k | return false; |
612 | 884k | } |
613 | | |
614 | 18 | static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { |
615 | 18 | assert(!Str.empty()); |
616 | 18 | char *CopyStr = Alloc.Allocate<char>(Str.size()+1); |
617 | 18 | std::copy(Str.begin(), Str.end(), CopyStr); |
618 | 18 | CopyStr[Str.size()] = '\0'; |
619 | 18 | return CopyStr; |
620 | 18 | } |
621 | | |
622 | | static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader, |
623 | 998k | SmallVectorImpl<char> &FrameworkName) { |
624 | 998k | using namespace llvm::sys; |
625 | 998k | path::const_iterator I = path::begin(Path); |
626 | 998k | path::const_iterator E = path::end(Path); |
627 | 998k | IsPrivateHeader = false; |
628 | 998k | |
629 | 998k | // Detect different types of framework style paths: |
630 | 998k | // |
631 | 998k | // ...Foo.framework/{Headers,PrivateHeaders} |
632 | 998k | // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} |
633 | 998k | // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} |
634 | 998k | // ...<other variations with 'Versions' like in the above path> |
635 | 998k | // |
636 | 998k | // and some other variations among these lines. |
637 | 998k | int FoundComp = 0; |
638 | 13.5M | while (I != E) { |
639 | 12.5M | if (*I == "Headers") |
640 | 21.8k | ++FoundComp; |
641 | 12.5M | if (I->endswith(".framework")) { |
642 | 21.5k | FrameworkName.append(I->begin(), I->end()); |
643 | 21.5k | ++FoundComp; |
644 | 21.5k | } |
645 | 12.5M | if (*I == "PrivateHeaders") { |
646 | 21 | ++FoundComp; |
647 | 21 | IsPrivateHeader = true; |
648 | 21 | } |
649 | 12.5M | ++I; |
650 | 12.5M | } |
651 | 998k | |
652 | 998k | return !FrameworkName.empty() && FoundComp >= 221.5k ; |
653 | 998k | } |
654 | | |
655 | | static void |
656 | | diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, |
657 | | StringRef Includer, StringRef IncludeFilename, |
658 | | const FileEntry *IncludeFE, bool isAngled = false, |
659 | 986k | bool FoundByHeaderMap = false) { |
660 | 986k | bool IsIncluderPrivateHeader = false; |
661 | 986k | SmallString<128> FromFramework, ToFramework; |
662 | 986k | if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework)) |
663 | 974k | return; |
664 | 11.6k | bool IsIncludeePrivateHeader = false; |
665 | 11.6k | bool IsIncludeeInFramework = isFrameworkStylePath( |
666 | 11.6k | IncludeFE->getName(), IsIncludeePrivateHeader, ToFramework); |
667 | 11.6k | |
668 | 11.6k | if (!isAngled && !FoundByHeaderMap41 ) { |
669 | 35 | SmallString<128> NewInclude("<"); |
670 | 35 | if (IsIncludeeInFramework) { |
671 | 16 | NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework |
672 | 16 | NewInclude += "/"; |
673 | 16 | } |
674 | 35 | NewInclude += IncludeFilename; |
675 | 35 | NewInclude += ">"; |
676 | 35 | Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) |
677 | 35 | << IncludeFilename |
678 | 35 | << FixItHint::CreateReplacement(IncludeLoc, NewInclude); |
679 | 35 | } |
680 | 11.6k | |
681 | 11.6k | // Headers in Foo.framework/Headers should not include headers |
682 | 11.6k | // from Foo.framework/PrivateHeaders, since this violates public/private |
683 | 11.6k | // API boundaries and can cause modular dependency cycles. |
684 | 11.6k | if (!IsIncluderPrivateHeader && IsIncludeeInFramework11.5k && |
685 | 11.6k | IsIncludeePrivateHeader9.89k && FromFramework == ToFramework7 ) |
686 | 7 | Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public) |
687 | 7 | << IncludeFilename; |
688 | 11.6k | } |
689 | | |
690 | | /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, |
691 | | /// return null on failure. isAngled indicates whether the file reference is |
692 | | /// for system \#include's or not (i.e. using <> instead of ""). Includers, if |
693 | | /// non-empty, indicates where the \#including file(s) are, in case a relative |
694 | | /// search is needed. Microsoft mode will pass all \#including files. |
695 | | const FileEntry *HeaderSearch::LookupFile( |
696 | | StringRef Filename, SourceLocation IncludeLoc, bool isAngled, |
697 | | const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, |
698 | | ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, |
699 | | SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, |
700 | | Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, |
701 | | bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, |
702 | 1.02M | bool BuildSystemModule) { |
703 | 1.02M | if (IsMapped) |
704 | 999k | *IsMapped = false; |
705 | 1.02M | |
706 | 1.02M | if (IsFrameworkFound) |
707 | 999k | *IsFrameworkFound = false; |
708 | 1.02M | |
709 | 1.02M | if (SuggestedModule) |
710 | 999k | *SuggestedModule = ModuleMap::KnownHeader(); |
711 | 1.02M | |
712 | 1.02M | // If 'Filename' is absolute, check to see if it exists and no searching. |
713 | 1.02M | if (llvm::sys::path::is_absolute(Filename)) { |
714 | 291 | CurDir = nullptr; |
715 | 291 | |
716 | 291 | // If this was an #include_next "/absolute/file", fail. |
717 | 291 | if (FromDir) return nullptr0 ; |
718 | 291 | |
719 | 291 | if (SearchPath) |
720 | 278 | SearchPath->clear(); |
721 | 291 | if (RelativePath) { |
722 | 278 | RelativePath->clear(); |
723 | 278 | RelativePath->append(Filename.begin(), Filename.end()); |
724 | 278 | } |
725 | 291 | // Otherwise, just return the file. |
726 | 291 | return getFileAndSuggestModule(Filename, IncludeLoc, nullptr, |
727 | 291 | /*IsSystemHeaderDir*/false, |
728 | 291 | RequestingModule, SuggestedModule); |
729 | 291 | } |
730 | 1.02M | |
731 | 1.02M | // This is the header that MSVC's header search would have found. |
732 | 1.02M | const FileEntry *MSFE = nullptr; |
733 | 1.02M | ModuleMap::KnownHeader MSSuggestedModule; |
734 | 1.02M | |
735 | 1.02M | // Unless disabled, check to see if the file is in the #includer's |
736 | 1.02M | // directory. This cannot be based on CurDir, because each includer could be |
737 | 1.02M | // a #include of a subdirectory (#include "foo/bar.h") and a subsequent |
738 | 1.02M | // include of "baz.h" should resolve to "whatever/foo/baz.h". |
739 | 1.02M | // This search is not done for <> headers. |
740 | 1.02M | if (!Includers.empty() && !isAngled997k && !NoCurDirSearch182k ) { |
741 | 182k | SmallString<1024> TmpDir; |
742 | 182k | bool First = true; |
743 | 182k | for (const auto &IncluderAndDir : Includers) { |
744 | 182k | const FileEntry *Includer = IncluderAndDir.first; |
745 | 182k | |
746 | 182k | // Concatenate the requested file onto the directory. |
747 | 182k | // FIXME: Portability. Filename concatenation should be in sys::Path. |
748 | 182k | TmpDir = IncluderAndDir.second->getName(); |
749 | 182k | TmpDir.push_back('/'); |
750 | 182k | TmpDir.append(Filename.begin(), Filename.end()); |
751 | 182k | |
752 | 182k | // FIXME: We don't cache the result of getFileInfo across the call to |
753 | 182k | // getFileAndSuggestModule, because it's a reference to an element of |
754 | 182k | // a container that could be reallocated across this call. |
755 | 182k | // |
756 | 182k | // If we have no includer, that means we're processing a #include |
757 | 182k | // from a module build. We should treat this as a system header if we're |
758 | 182k | // building a [system] module. |
759 | 182k | bool IncluderIsSystemHeader = |
760 | 182k | Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User180k : |
761 | 182k | BuildSystemModule2.17k ; |
762 | 182k | if (const FileEntry *FE = getFileAndSuggestModule( |
763 | 140k | TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, |
764 | 140k | RequestingModule, SuggestedModule)) { |
765 | 140k | if (!Includer) { |
766 | 2.17k | assert(First && "only first includer can have no file"); |
767 | 2.17k | return FE; |
768 | 2.17k | } |
769 | 138k | |
770 | 138k | // Leave CurDir unset. |
771 | 138k | // This file is a system header or C++ unfriendly if the old file is. |
772 | 138k | // |
773 | 138k | // Note that we only use one of FromHFI/ToHFI at once, due to potential |
774 | 138k | // reallocation of the underlying vector potentially making the first |
775 | 138k | // reference binding dangling. |
776 | 138k | HeaderFileInfo &FromHFI = getFileInfo(Includer); |
777 | 138k | unsigned DirInfo = FromHFI.DirInfo; |
778 | 138k | bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; |
779 | 138k | StringRef Framework = FromHFI.Framework; |
780 | 138k | |
781 | 138k | HeaderFileInfo &ToHFI = getFileInfo(FE); |
782 | 138k | ToHFI.DirInfo = DirInfo; |
783 | 138k | ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; |
784 | 138k | ToHFI.Framework = Framework; |
785 | 138k | |
786 | 138k | if (SearchPath) { |
787 | 137k | StringRef SearchPathRef(IncluderAndDir.second->getName()); |
788 | 137k | SearchPath->clear(); |
789 | 137k | SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); |
790 | 137k | } |
791 | 138k | if (RelativePath) { |
792 | 137k | RelativePath->clear(); |
793 | 137k | RelativePath->append(Filename.begin(), Filename.end()); |
794 | 137k | } |
795 | 138k | if (First) { |
796 | 138k | diagnoseFrameworkInclude(Diags, IncludeLoc, |
797 | 138k | IncluderAndDir.second->getName(), Filename, |
798 | 138k | FE); |
799 | 138k | return FE; |
800 | 138k | } |
801 | 6 | |
802 | 6 | // Otherwise, we found the path via MSVC header search rules. If |
803 | 6 | // -Wmsvc-include is enabled, we have to keep searching to see if we |
804 | 6 | // would've found this header in -I or -isystem directories. |
805 | 6 | if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) { |
806 | 4 | return FE; |
807 | 4 | } else { |
808 | 2 | MSFE = FE; |
809 | 2 | if (SuggestedModule) { |
810 | 2 | MSSuggestedModule = *SuggestedModule; |
811 | 2 | *SuggestedModule = ModuleMap::KnownHeader(); |
812 | 2 | } |
813 | 2 | break; |
814 | 2 | } |
815 | 42.2k | } |
816 | 42.2k | First = false; |
817 | 42.2k | } |
818 | 182k | } |
819 | 1.02M | |
820 | 1.02M | CurDir = nullptr; |
821 | 884k | |
822 | 884k | // If this is a system #include, ignore the user #include locs. |
823 | 884k | unsigned i = isAngled ? AngledDirIdx841k : 042.2k ; |
824 | 884k | |
825 | 884k | // If this is a #include_next request, start searching after the directory the |
826 | 884k | // file was found in. |
827 | 884k | if (FromDir) |
828 | 26.8k | i = FromDir-&SearchDirs[0]; |
829 | 884k | |
830 | 884k | // Cache all of the lookups performed by this method. Many headers are |
831 | 884k | // multiply included, and the "pragma once" optimization prevents them from |
832 | 884k | // being relex/pp'd, but they would still have to search through a |
833 | 884k | // (potentially huge) series of SearchDirs to find it. |
834 | 884k | LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; |
835 | 884k | |
836 | 884k | // If the entry has been previously looked up, the first value will be |
837 | 884k | // non-zero. If the value is equal to i (the start point of our search), then |
838 | 884k | // this is a matching hit. |
839 | 884k | if (!SkipCache884k && CacheLookup.StartIdx == i+1) { |
840 | 480k | // Skip querying potentially lots of directories for this lookup. |
841 | 480k | i = CacheLookup.HitIdx; |
842 | 480k | if (CacheLookup.MappedName) { |
843 | 6 | Filename = CacheLookup.MappedName; |
844 | 6 | if (IsMapped) |
845 | 6 | *IsMapped = true; |
846 | 6 | } |
847 | 480k | } else { |
848 | 403k | // Otherwise, this is the first query, or the previous query didn't match |
849 | 403k | // our search start. We will fill in our found location below, so prime the |
850 | 403k | // start point value. |
851 | 403k | CacheLookup.reset(/*StartIdx=*/i+1); |
852 | 403k | } |
853 | 884k | |
854 | 884k | SmallString<64> MappedName; |
855 | 884k | |
856 | 884k | // Check each directory in sequence to see if it contains this file. |
857 | 1.60M | for (; i != SearchDirs.size(); ++i719k ) { |
858 | 1.59M | bool InUserSpecifiedSystemFramework = false; |
859 | 1.59M | bool HasBeenMapped = false; |
860 | 1.59M | bool IsFrameworkFoundInDir = false; |
861 | 1.59M | const FileEntry *FE = SearchDirs[i].LookupFile( |
862 | 1.59M | Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, |
863 | 1.59M | SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, |
864 | 1.59M | HasBeenMapped, MappedName); |
865 | 1.59M | if (HasBeenMapped) { |
866 | 18 | CacheLookup.MappedName = |
867 | 18 | copyString(Filename, LookupFileCache.getAllocator()); |
868 | 18 | if (IsMapped) |
869 | 18 | *IsMapped = true; |
870 | 18 | } |
871 | 1.59M | if (IsFrameworkFound) |
872 | 1.53M | // Because we keep a filename remapped for subsequent search directory |
873 | 1.53M | // lookups, ignore IsFrameworkFoundInDir after the first remapping and not |
874 | 1.53M | // just for remapping in a current search directory. |
875 | 1.53M | *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName10.0k ); |
876 | 1.59M | if (!FE) continue719k ; |
877 | 874k | |
878 | 874k | CurDir = &SearchDirs[i]; |
879 | 874k | |
880 | 874k | // This file is a system header or C++ unfriendly if the dir is. |
881 | 874k | HeaderFileInfo &HFI = getFileInfo(FE); |
882 | 874k | HFI.DirInfo = CurDir->getDirCharacteristic(); |
883 | 874k | |
884 | 874k | // If the directory characteristic is User but this framework was |
885 | 874k | // user-specified to be treated as a system framework, promote the |
886 | 874k | // characteristic. |
887 | 874k | if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework23.3k ) |
888 | 1 | HFI.DirInfo = SrcMgr::C_System; |
889 | 874k | |
890 | 874k | // If the filename matches a known system header prefix, override |
891 | 874k | // whether the file is a system header. |
892 | 874k | for (unsigned j = SystemHeaderPrefixes.size(); j; --j12 ) { |
893 | 20 | if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) { |
894 | 8 | HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System4 |
895 | 8 | : SrcMgr::C_User4 ; |
896 | 8 | break; |
897 | 8 | } |
898 | 20 | } |
899 | 874k | |
900 | 874k | // If this file is found in a header map and uses the framework style of |
901 | 874k | // includes, then this header is part of a framework we're building. |
902 | 874k | if (CurDir->isIndexHeaderMap()) { |
903 | 0 | size_t SlashPos = Filename.find('/'); |
904 | 0 | if (SlashPos != StringRef::npos) { |
905 | 0 | HFI.IndexHeaderMapHeader = 1; |
906 | 0 | HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), |
907 | 0 | SlashPos)); |
908 | 0 | } |
909 | 0 | } |
910 | 874k | |
911 | 874k | if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { |
912 | 1 | if (SuggestedModule) |
913 | 1 | *SuggestedModule = MSSuggestedModule; |
914 | 1 | return MSFE; |
915 | 1 | } |
916 | 874k | |
917 | 874k | bool FoundByHeaderMap = !IsMapped ? false15.1k : *IsMapped859k ; |
918 | 874k | if (!Includers.empty()) |
919 | 848k | diagnoseFrameworkInclude(Diags, IncludeLoc, |
920 | 848k | Includers.front().second->getName(), Filename, |
921 | 848k | FE, isAngled, FoundByHeaderMap); |
922 | 874k | |
923 | 874k | // Remember this location for the next lookup we do. |
924 | 874k | CacheLookup.HitIdx = i; |
925 | 874k | return FE; |
926 | 874k | } |
927 | 884k | |
928 | 884k | // If we are including a file with a quoted include "foo.h" from inside |
929 | 884k | // a header in a framework that is currently being built, and we couldn't |
930 | 884k | // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where |
931 | 884k | // "Foo" is the name of the framework in which the including header was found. |
932 | 884k | if (9.43k !Includers.empty()9.43k && Includers.front().first8.93k && !isAngled8.93k && |
933 | 9.43k | Filename.find('/') == StringRef::npos139 ) { |
934 | 89 | HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first); |
935 | 89 | if (IncludingHFI.IndexHeaderMapHeader) { |
936 | 0 | SmallString<128> ScratchFilename; |
937 | 0 | ScratchFilename += IncludingHFI.Framework; |
938 | 0 | ScratchFilename += '/'; |
939 | 0 | ScratchFilename += Filename; |
940 | 0 |
|
941 | 0 | const FileEntry *FE = LookupFile( |
942 | 0 | ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir, |
943 | 0 | Includers.front(), SearchPath, RelativePath, RequestingModule, |
944 | 0 | SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); |
945 | 0 |
|
946 | 0 | if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { |
947 | 0 | if (SuggestedModule) |
948 | 0 | *SuggestedModule = MSSuggestedModule; |
949 | 0 | return MSFE; |
950 | 0 | } |
951 | 0 |
|
952 | 0 | LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; |
953 | 0 | CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx; |
954 | 0 | // FIXME: SuggestedModule. |
955 | 0 | return FE; |
956 | 0 | } |
957 | 89 | } |
958 | 9.43k | |
959 | 9.43k | if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) { |
960 | 0 | if (SuggestedModule) |
961 | 0 | *SuggestedModule = MSSuggestedModule; |
962 | 0 | return MSFE; |
963 | 0 | } |
964 | 9.43k | |
965 | 9.43k | // Otherwise, didn't find it. Remember we didn't find this. |
966 | 9.43k | CacheLookup.HitIdx = SearchDirs.size(); |
967 | 9.43k | return nullptr; |
968 | 9.43k | } |
969 | | |
970 | | /// LookupSubframeworkHeader - Look up a subframework for the specified |
971 | | /// \#include file. For example, if \#include'ing <HIToolbox/HIToolbox.h> from |
972 | | /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox |
973 | | /// is a subframework within Carbon.framework. If so, return the FileEntry |
974 | | /// for the designated file, otherwise return null. |
975 | | const FileEntry *HeaderSearch:: |
976 | | LookupSubframeworkHeader(StringRef Filename, |
977 | | const FileEntry *ContextFileEnt, |
978 | | SmallVectorImpl<char> *SearchPath, |
979 | | SmallVectorImpl<char> *RelativePath, |
980 | | Module *RequestingModule, |
981 | 45.2k | ModuleMap::KnownHeader *SuggestedModule) { |
982 | 45.2k | assert(ContextFileEnt && "No context file?"); |
983 | 45.2k | |
984 | 45.2k | // Framework names must have a '/' in the filename. Find it. |
985 | 45.2k | // FIXME: Should we permit '\' on Windows? |
986 | 45.2k | size_t SlashPos = Filename.find('/'); |
987 | 45.2k | if (SlashPos == StringRef::npos) return nullptr45.1k ; |
988 | 162 | |
989 | 162 | // Look up the base framework name of the ContextFileEnt. |
990 | 162 | StringRef ContextName = ContextFileEnt->getName(); |
991 | 162 | |
992 | 162 | // If the context info wasn't a framework, couldn't be a subframework. |
993 | 162 | const unsigned DotFrameworkLen = 10; |
994 | 162 | auto FrameworkPos = ContextName.find(".framework"); |
995 | 162 | if (FrameworkPos == StringRef::npos || |
996 | 162 | (38 ContextName[FrameworkPos + DotFrameworkLen] != '/'38 && |
997 | 38 | ContextName[FrameworkPos + DotFrameworkLen] != '\\'0 )) |
998 | 124 | return nullptr; |
999 | 38 | |
1000 | 38 | SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + |
1001 | 38 | FrameworkPos + |
1002 | 38 | DotFrameworkLen + 1); |
1003 | 38 | |
1004 | 38 | // Append Frameworks/HIToolbox.framework/ |
1005 | 38 | FrameworkName += "Frameworks/"; |
1006 | 38 | FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); |
1007 | 38 | FrameworkName += ".framework/"; |
1008 | 38 | |
1009 | 38 | auto &CacheLookup = |
1010 | 38 | *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos), |
1011 | 38 | FrameworkCacheEntry())).first; |
1012 | 38 | |
1013 | 38 | // Some other location? |
1014 | 38 | if (CacheLookup.second.Directory && |
1015 | 38 | CacheLookup.first().size() == FrameworkName.size()4 && |
1016 | 38 | memcmp(CacheLookup.first().data(), &FrameworkName[0], |
1017 | 0 | CacheLookup.first().size()) != 0) |
1018 | 0 | return nullptr; |
1019 | 38 | |
1020 | 38 | // Cache subframework. |
1021 | 38 | if (!CacheLookup.second.Directory) { |
1022 | 34 | ++NumSubFrameworkLookups; |
1023 | 34 | |
1024 | 34 | // If the framework dir doesn't exist, we fail. |
1025 | 34 | const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); |
1026 | 34 | if (!Dir) return nullptr0 ; |
1027 | 34 | |
1028 | 34 | // Otherwise, if it does, remember that this is the right direntry for this |
1029 | 34 | // framework. |
1030 | 34 | CacheLookup.second.Directory = Dir; |
1031 | 34 | } |
1032 | 38 | |
1033 | 38 | const FileEntry *FE = nullptr; |
1034 | 38 | |
1035 | 38 | if (RelativePath) { |
1036 | 38 | RelativePath->clear(); |
1037 | 38 | RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); |
1038 | 38 | } |
1039 | 38 | |
1040 | 38 | // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" |
1041 | 38 | SmallString<1024> HeadersFilename(FrameworkName); |
1042 | 38 | HeadersFilename += "Headers/"; |
1043 | 38 | if (SearchPath) { |
1044 | 38 | SearchPath->clear(); |
1045 | 38 | // Without trailing '/'. |
1046 | 38 | SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); |
1047 | 38 | } |
1048 | 38 | |
1049 | 38 | HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); |
1050 | 38 | if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) { |
1051 | 2 | // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" |
1052 | 2 | HeadersFilename = FrameworkName; |
1053 | 2 | HeadersFilename += "PrivateHeaders/"; |
1054 | 2 | if (SearchPath) { |
1055 | 2 | SearchPath->clear(); |
1056 | 2 | // Without trailing '/'. |
1057 | 2 | SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); |
1058 | 2 | } |
1059 | 2 | |
1060 | 2 | HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); |
1061 | 2 | if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) |
1062 | 0 | return nullptr; |
1063 | 38 | } |
1064 | 38 | |
1065 | 38 | // This file is a system header or C++ unfriendly if the old file is. |
1066 | 38 | // |
1067 | 38 | // Note that the temporary 'DirInfo' is required here, as either call to |
1068 | 38 | // getFileInfo could resize the vector and we don't want to rely on order |
1069 | 38 | // of evaluation. |
1070 | 38 | unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; |
1071 | 38 | getFileInfo(FE).DirInfo = DirInfo; |
1072 | 38 | |
1073 | 38 | FrameworkName.pop_back(); // remove the trailing '/' |
1074 | 38 | if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule, |
1075 | 38 | SuggestedModule, /*IsSystem*/ false)) |
1076 | 0 | return nullptr; |
1077 | 38 | |
1078 | 38 | return FE; |
1079 | 38 | } |
1080 | | |
1081 | | //===----------------------------------------------------------------------===// |
1082 | | // File Info Management. |
1083 | | //===----------------------------------------------------------------------===// |
1084 | | |
1085 | | /// Merge the header file info provided by \p OtherHFI into the current |
1086 | | /// header file info (\p HFI) |
1087 | | static void mergeHeaderFileInfo(HeaderFileInfo &HFI, |
1088 | 4.70k | const HeaderFileInfo &OtherHFI) { |
1089 | 4.70k | assert(OtherHFI.External && "expected to merge external HFI"); |
1090 | 4.70k | |
1091 | 4.70k | HFI.isImport |= OtherHFI.isImport; |
1092 | 4.70k | HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; |
1093 | 4.70k | HFI.isModuleHeader |= OtherHFI.isModuleHeader; |
1094 | 4.70k | HFI.NumIncludes += OtherHFI.NumIncludes; |
1095 | 4.70k | |
1096 | 4.70k | if (!HFI.ControllingMacro && !HFI.ControllingMacroID4.69k ) { |
1097 | 4.69k | HFI.ControllingMacro = OtherHFI.ControllingMacro; |
1098 | 4.69k | HFI.ControllingMacroID = OtherHFI.ControllingMacroID; |
1099 | 4.69k | } |
1100 | 4.70k | |
1101 | 4.70k | HFI.DirInfo = OtherHFI.DirInfo; |
1102 | 4.70k | HFI.External = (!HFI.IsValid || HFI.External2.57k ); |
1103 | 4.70k | HFI.IsValid = true; |
1104 | 4.70k | HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; |
1105 | 4.70k | |
1106 | 4.70k | if (HFI.Framework.empty()) |
1107 | 4.70k | HFI.Framework = OtherHFI.Framework; |
1108 | 4.70k | } |
1109 | | |
1110 | | /// getFileInfo - Return the HeaderFileInfo structure for the specified |
1111 | | /// FileEntry. |
1112 | 3.90M | HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { |
1113 | 3.90M | if (FE->getUID() >= FileInfo.size()) |
1114 | 588k | FileInfo.resize(FE->getUID() + 1); |
1115 | 3.90M | |
1116 | 3.90M | HeaderFileInfo *HFI = &FileInfo[FE->getUID()]; |
1117 | 3.90M | // FIXME: Use a generation count to check whether this is really up to date. |
1118 | 3.90M | if (ExternalSource && !HFI->Resolved11.0k ) { |
1119 | 3.81k | HFI->Resolved = true; |
1120 | 3.81k | auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); |
1121 | 3.81k | |
1122 | 3.81k | HFI = &FileInfo[FE->getUID()]; |
1123 | 3.81k | if (ExternalHFI.External) |
1124 | 2.70k | mergeHeaderFileInfo(*HFI, ExternalHFI); |
1125 | 3.81k | } |
1126 | 3.90M | |
1127 | 3.90M | HFI->IsValid = true; |
1128 | 3.90M | // We have local information about this header file, so it's no longer |
1129 | 3.90M | // strictly external. |
1130 | 3.90M | HFI->External = false; |
1131 | 3.90M | return *HFI; |
1132 | 3.90M | } |
1133 | | |
1134 | | const HeaderFileInfo * |
1135 | | HeaderSearch::getExistingFileInfo(const FileEntry *FE, |
1136 | 158k | bool WantExternal) const { |
1137 | 158k | // If we have an external source, ensure we have the latest information. |
1138 | 158k | // FIXME: Use a generation count to check whether this is really up to date. |
1139 | 158k | HeaderFileInfo *HFI; |
1140 | 158k | if (ExternalSource) { |
1141 | 26.8k | if (FE->getUID() >= FileInfo.size()) { |
1142 | 1.16k | if (!WantExternal) |
1143 | 0 | return nullptr; |
1144 | 1.16k | FileInfo.resize(FE->getUID() + 1); |
1145 | 1.16k | } |
1146 | 26.8k | |
1147 | 26.8k | HFI = &FileInfo[FE->getUID()]; |
1148 | 26.8k | if (!WantExternal && (24.4k !HFI->IsValid24.4k || HFI->External21.5k )) |
1149 | 2.93k | return nullptr; |
1150 | 23.8k | if (!HFI->Resolved) { |
1151 | 22.5k | HFI->Resolved = true; |
1152 | 22.5k | auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); |
1153 | 22.5k | |
1154 | 22.5k | HFI = &FileInfo[FE->getUID()]; |
1155 | 22.5k | if (ExternalHFI.External) |
1156 | 2.00k | mergeHeaderFileInfo(*HFI, ExternalHFI); |
1157 | 22.5k | } |
1158 | 131k | } else if (FE->getUID() >= FileInfo.size()) { |
1159 | 87.0k | return nullptr; |
1160 | 87.0k | } else { |
1161 | 44.6k | HFI = &FileInfo[FE->getUID()]; |
1162 | 44.6k | } |
1163 | 158k | |
1164 | 158k | if (68.5k !HFI->IsValid68.5k || (53.2k HFI->External53.2k && !WantExternal274 )) |
1165 | 15.2k | return nullptr; |
1166 | 53.2k | |
1167 | 53.2k | return HFI; |
1168 | 53.2k | } |
1169 | | |
1170 | 340 | bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { |
1171 | 340 | // Check if we've ever seen this file as a header. |
1172 | 340 | if (auto *HFI = getExistingFileInfo(File)) |
1173 | 340 | return HFI->isPragmaOnce || HFI->isImport332 || HFI->ControllingMacro294 || |
1174 | 340 | HFI->ControllingMacroID277 ; |
1175 | 0 | return false; |
1176 | 0 | } |
1177 | | |
1178 | | void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE, |
1179 | | ModuleMap::ModuleHeaderRole Role, |
1180 | 94.5k | bool isCompilingModuleHeader) { |
1181 | 94.5k | bool isModularHeader = !(Role & ModuleMap::TextualHeader); |
1182 | 94.5k | |
1183 | 94.5k | // Don't mark the file info as non-external if there's nothing to change. |
1184 | 94.5k | if (!isCompilingModuleHeader) { |
1185 | 92.1k | if (!isModularHeader) |
1186 | 2.16k | return; |
1187 | 89.9k | auto *HFI = getExistingFileInfo(FE); |
1188 | 89.9k | if (HFI && HFI->isModuleHeader692 ) |
1189 | 667 | return; |
1190 | 91.6k | } |
1191 | 91.6k | |
1192 | 91.6k | auto &HFI = getFileInfo(FE); |
1193 | 91.6k | HFI.isModuleHeader |= isModularHeader; |
1194 | 91.6k | HFI.isCompilingModuleHeader |= isCompilingModuleHeader; |
1195 | 91.6k | } |
1196 | | |
1197 | | bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, |
1198 | | const FileEntry *File, bool isImport, |
1199 | 998k | bool ModulesEnabled, Module *M) { |
1200 | 998k | ++NumIncluded; // Count # of attempted #includes. |
1201 | 998k | |
1202 | 998k | // Get information about this file. |
1203 | 998k | HeaderFileInfo &FileInfo = getFileInfo(File); |
1204 | 998k | |
1205 | 998k | // FIXME: this is a workaround for the lack of proper modules-aware support |
1206 | 998k | // for #import / #pragma once |
1207 | 998k | auto TryEnterImported = [&]() -> bool { |
1208 | 4.32k | if (!ModulesEnabled) |
1209 | 4.21k | return false; |
1210 | 107 | // Ensure FileInfo bits are up to date. |
1211 | 107 | ModMap.resolveHeaderDirectives(File); |
1212 | 107 | // Modules with builtins are special; multiple modules use builtins as |
1213 | 107 | // modular headers, example: |
1214 | 107 | // |
1215 | 107 | // module stddef { header "stddef.h" export * } |
1216 | 107 | // |
1217 | 107 | // After module map parsing, this expands to: |
1218 | 107 | // |
1219 | 107 | // module stddef { |
1220 | 107 | // header "/path_to_builtin_dirs/stddef.h" |
1221 | 107 | // textual "stddef.h" |
1222 | 107 | // } |
1223 | 107 | // |
1224 | 107 | // It's common that libc++ and system modules will both define such |
1225 | 107 | // submodules. Make sure cached results for a builtin header won't |
1226 | 107 | // prevent other builtin modules to potentially enter the builtin header. |
1227 | 107 | // Note that builtins are header guarded and the decision to actually |
1228 | 107 | // enter them is postponed to the controlling macros logic below. |
1229 | 107 | bool TryEnterHdr = false; |
1230 | 107 | if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader82 ) |
1231 | 80 | TryEnterHdr = File->getDir() == ModMap.getBuiltinDir() && |
1232 | 80 | ModuleMap::isBuiltinHeader( |
1233 | 26 | llvm::sys::path::filename(File->getName())); |
1234 | 107 | |
1235 | 107 | // Textual headers can be #imported from different modules. Since ObjC |
1236 | 107 | // headers find in the wild might rely only on #import and do not contain |
1237 | 107 | // controlling macros, be conservative and only try to enter textual headers |
1238 | 107 | // if such macro is present. |
1239 | 107 | if (!FileInfo.isModuleHeader && |
1240 | 107 | FileInfo.getControllingMacro(ExternalLookup)24 ) |
1241 | 1 | TryEnterHdr = true; |
1242 | 107 | return TryEnterHdr; |
1243 | 107 | }; |
1244 | 998k | |
1245 | 998k | // If this is a #import directive, check that we have not already imported |
1246 | 998k | // this header. |
1247 | 998k | if (isImport) { |
1248 | 7.10k | // If this has already been imported, don't import it again. |
1249 | 7.10k | FileInfo.isImport = true; |
1250 | 7.10k | |
1251 | 7.10k | // Has this already been #import'ed or #include'd? |
1252 | 7.10k | if (FileInfo.NumIncludes && !TryEnterImported()4.05k ) |
1253 | 4.05k | return false; |
1254 | 991k | } else { |
1255 | 991k | // Otherwise, if this is a #include of a file that was previously #import'd |
1256 | 991k | // or if this is the second #include of a #pragma once file, ignore it. |
1257 | 991k | if (FileInfo.isImport && !TryEnterImported()267 ) |
1258 | 267 | return false; |
1259 | 993k | } |
1260 | 993k | |
1261 | 993k | // Next, check to see if the file is wrapped with #ifndef guards. If so, and |
1262 | 993k | // if the macro that guards it is defined, we know the #include has no effect. |
1263 | 993k | if (const IdentifierInfo *ControllingMacro |
1264 | 516k | = FileInfo.getControllingMacro(ExternalLookup)) { |
1265 | 516k | // If the header corresponds to a module, check whether the macro is already |
1266 | 516k | // defined in that module rather than checking in the current set of visible |
1267 | 516k | // modules. |
1268 | 516k | if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)158 |
1269 | 516k | : PP.isMacroDefined(ControllingMacro)515k ) { |
1270 | 515k | ++NumMultiIncludeFileOptzn; |
1271 | 515k | return false; |
1272 | 515k | } |
1273 | 478k | } |
1274 | 478k | |
1275 | 478k | // Increment the number of times this file has been included. |
1276 | 478k | ++FileInfo.NumIncludes; |
1277 | 478k | |
1278 | 478k | return true; |
1279 | 478k | } |
1280 | | |
1281 | 1 | size_t HeaderSearch::getTotalMemory() const { |
1282 | 1 | return SearchDirs.capacity() |
1283 | 1 | + llvm::capacity_in_bytes(FileInfo) |
1284 | 1 | + llvm::capacity_in_bytes(HeaderMaps) |
1285 | 1 | + LookupFileCache.getAllocator().getTotalMemory() |
1286 | 1 | + FrameworkMap.getAllocator().getTotalMemory(); |
1287 | 1 | } |
1288 | | |
1289 | 0 | StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { |
1290 | 0 | return FrameworkNames.insert(Framework).first->first(); |
1291 | 0 | } |
1292 | | |
1293 | | bool HeaderSearch::hasModuleMap(StringRef FileName, |
1294 | | const DirectoryEntry *Root, |
1295 | 989k | bool IsSystem) { |
1296 | 989k | if (!HSOpts->ImplicitModuleMaps) |
1297 | 985k | return false; |
1298 | 3.99k | |
1299 | 3.99k | SmallVector<const DirectoryEntry *, 2> FixUpDirectories; |
1300 | 3.99k | |
1301 | 3.99k | StringRef DirName = FileName; |
1302 | 4.81k | do { |
1303 | 4.81k | // Get the parent directory name. |
1304 | 4.81k | DirName = llvm::sys::path::parent_path(DirName); |
1305 | 4.81k | if (DirName.empty()) |
1306 | 20 | return false; |
1307 | 4.79k | |
1308 | 4.79k | // Determine whether this directory exists. |
1309 | 4.79k | const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); |
1310 | 4.79k | if (!Dir) |
1311 | 0 | return false; |
1312 | 4.79k | |
1313 | 4.79k | // Try to load the module map file in this directory. |
1314 | 4.79k | switch (loadModuleMapFile(Dir, IsSystem, |
1315 | 4.79k | llvm::sys::path::extension(Dir->getName()) == |
1316 | 4.79k | ".framework")) { |
1317 | 4.79k | case LMM_NewlyLoaded: |
1318 | 3.78k | case LMM_AlreadyLoaded: |
1319 | 3.78k | // Success. All of the directories we stepped through inherit this module |
1320 | 3.78k | // map file. |
1321 | 4.10k | for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I314 ) |
1322 | 314 | DirectoryHasModuleMap[FixUpDirectories[I]] = true; |
1323 | 3.78k | return true; |
1324 | 3.78k | |
1325 | 3.78k | case LMM_NoDirectory: |
1326 | 1.01k | case LMM_InvalidModuleMap: |
1327 | 1.01k | break; |
1328 | 1.01k | } |
1329 | 1.01k | |
1330 | 1.01k | // If we hit the top of our search, we're done. |
1331 | 1.01k | if (Dir == Root) |
1332 | 184 | return false; |
1333 | 828 | |
1334 | 828 | // Keep track of all of the directories we checked, so we can mark them as |
1335 | 828 | // having module maps if we eventually do find a module map. |
1336 | 828 | FixUpDirectories.push_back(Dir); |
1337 | 828 | } while (true); |
1338 | 3.99k | } |
1339 | | |
1340 | | ModuleMap::KnownHeader |
1341 | | HeaderSearch::findModuleForHeader(const FileEntry *File, |
1342 | 999k | bool AllowTextual) const { |
1343 | 999k | if (ExternalSource) { |
1344 | 1.41k | // Make sure the external source has handled header info about this file, |
1345 | 1.41k | // which includes whether the file is part of a module. |
1346 | 1.41k | (void)getExistingFileInfo(File); |
1347 | 1.41k | } |
1348 | 999k | return ModMap.findModuleForHeader(File, AllowTextual); |
1349 | 999k | } |
1350 | | |
1351 | | static bool suggestModule(HeaderSearch &HS, const FileEntry *File, |
1352 | | Module *RequestingModule, |
1353 | 999k | ModuleMap::KnownHeader *SuggestedModule) { |
1354 | 999k | ModuleMap::KnownHeader Module = |
1355 | 999k | HS.findModuleForHeader(File, /*AllowTextual*/true); |
1356 | 999k | if (SuggestedModule) |
1357 | 999k | *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader) |
1358 | 999k | ? ModuleMap::KnownHeader()224 |
1359 | 999k | : Module999k ; |
1360 | 999k | |
1361 | 999k | // If this module specifies [no_undeclared_includes], we cannot find any |
1362 | 999k | // file that's in a non-dependency module. |
1363 | 999k | if (RequestingModule && Module4.05k && RequestingModule->NoUndeclaredIncludes3.57k ) { |
1364 | 46 | HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/false); |
1365 | 46 | if (!RequestingModule->directlyUses(Module.getModule())) { |
1366 | 8 | return false; |
1367 | 8 | } |
1368 | 999k | } |
1369 | 999k | |
1370 | 999k | return true; |
1371 | 999k | } |
1372 | | |
1373 | | bool HeaderSearch::findUsableModuleForHeader( |
1374 | | const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, |
1375 | 1.00M | ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { |
1376 | 1.00M | if (File && needModuleLookup(RequestingModule, SuggestedModule)) { |
1377 | 989k | // If there is a module that corresponds to this header, suggest it. |
1378 | 989k | hasModuleMap(File->getName(), Root, IsSystemHeaderDir); |
1379 | 989k | return suggestModule(*this, File, RequestingModule, SuggestedModule); |
1380 | 989k | } |
1381 | 15.5k | return true; |
1382 | 15.5k | } |
1383 | | |
1384 | | bool HeaderSearch::findUsableModuleForFrameworkHeader( |
1385 | | const FileEntry *File, StringRef FrameworkName, Module *RequestingModule, |
1386 | 10.1k | ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { |
1387 | 10.1k | // If we're supposed to suggest a module, look for one now. |
1388 | 10.1k | if (needModuleLookup(RequestingModule, SuggestedModule)) { |
1389 | 10.1k | // Find the top-level framework based on this framework. |
1390 | 10.1k | SmallVector<std::string, 4> SubmodulePath; |
1391 | 10.1k | const DirectoryEntry *TopFrameworkDir |
1392 | 10.1k | = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); |
1393 | 10.1k | |
1394 | 10.1k | // Determine the name of the top-level framework. |
1395 | 10.1k | StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); |
1396 | 10.1k | |
1397 | 10.1k | // Load this framework module. If that succeeds, find the suggested module |
1398 | 10.1k | // for this header, if any. |
1399 | 10.1k | loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystemFramework); |
1400 | 10.1k | |
1401 | 10.1k | // FIXME: This can find a module not part of ModuleName, which is |
1402 | 10.1k | // important so that we're consistent about whether this header |
1403 | 10.1k | // corresponds to a module. Possibly we should lock down framework modules |
1404 | 10.1k | // so that this is not possible. |
1405 | 10.1k | return suggestModule(*this, File, RequestingModule, SuggestedModule); |
1406 | 10.1k | } |
1407 | 0 | return true; |
1408 | 0 | } |
1409 | | |
1410 | | static const FileEntry *getPrivateModuleMap(const FileEntry *File, |
1411 | 2.93k | FileManager &FileMgr) { |
1412 | 2.93k | StringRef Filename = llvm::sys::path::filename(File->getName()); |
1413 | 2.93k | SmallString<128> PrivateFilename(File->getDir()->getName()); |
1414 | 2.93k | if (Filename == "module.map") |
1415 | 955 | llvm::sys::path::append(PrivateFilename, "module_private.map"); |
1416 | 1.97k | else if (Filename == "module.modulemap") |
1417 | 1.58k | llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); |
1418 | 398 | else |
1419 | 398 | return nullptr; |
1420 | 2.53k | return FileMgr.getFile(PrivateFilename); |
1421 | 2.53k | } |
1422 | | |
1423 | | bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, |
1424 | | FileID ID, unsigned *Offset, |
1425 | 1.73k | StringRef OriginalModuleMapFile) { |
1426 | 1.73k | // Find the directory for the module. For frameworks, that may require going |
1427 | 1.73k | // up from the 'Modules' directory. |
1428 | 1.73k | const DirectoryEntry *Dir = nullptr; |
1429 | 1.73k | if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) |
1430 | 51 | Dir = FileMgr.getDirectory("."); |
1431 | 1.68k | else { |
1432 | 1.68k | if (!OriginalModuleMapFile.empty()) { |
1433 | 16 | // We're building a preprocessed module map. Find or invent the directory |
1434 | 16 | // that it originally occupied. |
1435 | 16 | Dir = FileMgr.getDirectory( |
1436 | 16 | llvm::sys::path::parent_path(OriginalModuleMapFile)); |
1437 | 16 | if (!Dir) { |
1438 | 0 | auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0); |
1439 | 0 | Dir = FakeFile->getDir(); |
1440 | 0 | } |
1441 | 1.67k | } else { |
1442 | 1.67k | Dir = File->getDir(); |
1443 | 1.67k | } |
1444 | 1.68k | |
1445 | 1.68k | StringRef DirName(Dir->getName()); |
1446 | 1.68k | if (llvm::sys::path::filename(DirName) == "Modules") { |
1447 | 96 | DirName = llvm::sys::path::parent_path(DirName); |
1448 | 96 | if (DirName.endswith(".framework")) |
1449 | 75 | Dir = FileMgr.getDirectory(DirName); |
1450 | 96 | // FIXME: This assert can fail if there's a race between the above check |
1451 | 96 | // and the removal of the directory. |
1452 | 96 | assert(Dir && "parent must exist"); |
1453 | 96 | } |
1454 | 1.68k | } |
1455 | 1.73k | |
1456 | 1.73k | switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) { |
1457 | 1.73k | case LMM_AlreadyLoaded: |
1458 | 1.73k | case LMM_NewlyLoaded: |
1459 | 1.73k | return false; |
1460 | 1.73k | case LMM_NoDirectory: |
1461 | 2 | case LMM_InvalidModuleMap: |
1462 | 2 | return true; |
1463 | 0 | } |
1464 | 0 | llvm_unreachable("Unknown load module map result"); |
1465 | 0 | } |
1466 | | |
1467 | | HeaderSearch::LoadModuleMapResult |
1468 | | HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, |
1469 | | const DirectoryEntry *Dir, FileID ID, |
1470 | 5.96k | unsigned *Offset) { |
1471 | 5.96k | assert(File && "expected FileEntry"); |
1472 | 5.96k | |
1473 | 5.96k | // Check whether we've already loaded this module map, and mark it as being |
1474 | 5.96k | // loaded in case we recursively try to load it from itself. |
1475 | 5.96k | auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true)); |
1476 | 5.96k | if (!AddResult.second) |
1477 | 2.94k | return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap0 ; |
1478 | 3.02k | |
1479 | 3.02k | if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) { |
1480 | 87 | LoadedModuleMaps[File] = false; |
1481 | 87 | return LMM_InvalidModuleMap; |
1482 | 87 | } |
1483 | 2.93k | |
1484 | 2.93k | // Try to load a corresponding private module map. |
1485 | 2.93k | if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) { |
1486 | 142 | if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) { |
1487 | 0 | LoadedModuleMaps[File] = false; |
1488 | 0 | return LMM_InvalidModuleMap; |
1489 | 0 | } |
1490 | 2.93k | } |
1491 | 2.93k | |
1492 | 2.93k | // This directory has a module map. |
1493 | 2.93k | return LMM_NewlyLoaded; |
1494 | 2.93k | } |
1495 | | |
1496 | | const FileEntry * |
1497 | 15.6k | HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) { |
1498 | 15.6k | if (!HSOpts->ImplicitModuleMaps) |
1499 | 9.68k | return nullptr; |
1500 | 5.93k | // For frameworks, the preferred spelling is Modules/module.modulemap, but |
1501 | 5.93k | // module.map at the framework root is also accepted. |
1502 | 5.93k | SmallString<128> ModuleMapFileName(Dir->getName()); |
1503 | 5.93k | if (IsFramework) |
1504 | 1.03k | llvm::sys::path::append(ModuleMapFileName, "Modules"); |
1505 | 5.93k | llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); |
1506 | 5.93k | if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName)) |
1507 | 2.97k | return F; |
1508 | 2.96k | |
1509 | 2.96k | // Continue to allow module.map |
1510 | 2.96k | ModuleMapFileName = Dir->getName(); |
1511 | 2.96k | llvm::sys::path::append(ModuleMapFileName, "module.map"); |
1512 | 2.96k | return FileMgr.getFile(ModuleMapFileName); |
1513 | 2.96k | } |
1514 | | |
1515 | | Module *HeaderSearch::loadFrameworkModule(StringRef Name, |
1516 | | const DirectoryEntry *Dir, |
1517 | 10.6k | bool IsSystem) { |
1518 | 10.6k | if (Module *Module = ModMap.findModule(Name)) |
1519 | 301 | return Module; |
1520 | 10.3k | |
1521 | 10.3k | // Try to load a module map file. |
1522 | 10.3k | switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) { |
1523 | 10.3k | case LMM_InvalidModuleMap: |
1524 | 9.89k | // Try to infer a module map from the framework directory. |
1525 | 9.89k | if (HSOpts->ImplicitModuleMaps) |
1526 | 207 | ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr); |
1527 | 9.89k | break; |
1528 | 10.3k | |
1529 | 10.3k | case LMM_AlreadyLoaded: |
1530 | 3 | case LMM_NoDirectory: |
1531 | 3 | return nullptr; |
1532 | 3 | |
1533 | 412 | case LMM_NewlyLoaded: |
1534 | 412 | break; |
1535 | 10.3k | } |
1536 | 10.3k | |
1537 | 10.3k | return ModMap.findModule(Name); |
1538 | 10.3k | } |
1539 | | |
1540 | | HeaderSearch::LoadModuleMapResult |
1541 | | HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem, |
1542 | 4.01k | bool IsFramework) { |
1543 | 4.01k | if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) |
1544 | 508 | return loadModuleMapFile(Dir, IsSystem, IsFramework); |
1545 | 3.50k | |
1546 | 3.50k | return LMM_NoDirectory; |
1547 | 3.50k | } |
1548 | | |
1549 | | HeaderSearch::LoadModuleMapResult |
1550 | | HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, |
1551 | 16.1k | bool IsFramework) { |
1552 | 16.1k | auto KnownDir = DirectoryHasModuleMap.find(Dir); |
1553 | 16.1k | if (KnownDir != DirectoryHasModuleMap.end()) |
1554 | 691 | return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap0 ; |
1555 | 15.4k | |
1556 | 15.4k | if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { |
1557 | 4.22k | LoadModuleMapResult Result = |
1558 | 4.22k | loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir); |
1559 | 4.22k | // Add Dir explicitly in case ModuleMapFile is in a subdirectory. |
1560 | 4.22k | // E.g. Foo.framework/Modules/module.modulemap |
1561 | 4.22k | // ^Dir ^ModuleMapFile |
1562 | 4.22k | if (Result == LMM_NewlyLoaded) |
1563 | 1.29k | DirectoryHasModuleMap[Dir] = true; |
1564 | 2.93k | else if (Result == LMM_InvalidModuleMap) |
1565 | 85 | DirectoryHasModuleMap[Dir] = false; |
1566 | 4.22k | return Result; |
1567 | 4.22k | } |
1568 | 11.2k | return LMM_InvalidModuleMap; |
1569 | 11.2k | } |
1570 | | |
1571 | 2 | void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { |
1572 | 2 | Modules.clear(); |
1573 | 2 | |
1574 | 2 | if (HSOpts->ImplicitModuleMaps) { |
1575 | 2 | // Load module maps for each of the header search directories. |
1576 | 10 | for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx8 ) { |
1577 | 8 | bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory(); |
1578 | 8 | if (SearchDirs[Idx].isFramework()) { |
1579 | 4 | std::error_code EC; |
1580 | 4 | SmallString<128> DirNative; |
1581 | 4 | llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(), |
1582 | 4 | DirNative); |
1583 | 4 | |
1584 | 4 | // Search each of the ".framework" directories to load them as modules. |
1585 | 4 | llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); |
1586 | 4 | for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), |
1587 | 4 | DirEnd; |
1588 | 298 | Dir != DirEnd && !EC294 ; Dir.increment(EC)294 ) { |
1589 | 294 | if (llvm::sys::path::extension(Dir->path()) != ".framework") |
1590 | 4 | continue; |
1591 | 290 | |
1592 | 290 | const DirectoryEntry *FrameworkDir = |
1593 | 290 | FileMgr.getDirectory(Dir->path()); |
1594 | 290 | if (!FrameworkDir) |
1595 | 0 | continue; |
1596 | 290 | |
1597 | 290 | // Load this framework module. |
1598 | 290 | loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, |
1599 | 290 | IsSystem); |
1600 | 290 | } |
1601 | 4 | continue; |
1602 | 4 | } |
1603 | 4 | |
1604 | 4 | // FIXME: Deal with header maps. |
1605 | 4 | if (SearchDirs[Idx].isHeaderMap()) |
1606 | 0 | continue; |
1607 | 4 | |
1608 | 4 | // Try to load a module map file for the search directory. |
1609 | 4 | loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, |
1610 | 4 | /*IsFramework*/ false); |
1611 | 4 | |
1612 | 4 | // Try to load module map files for immediate subdirectories of this |
1613 | 4 | // search directory. |
1614 | 4 | loadSubdirectoryModuleMaps(SearchDirs[Idx]); |
1615 | 4 | } |
1616 | 2 | } |
1617 | 2 | |
1618 | 2 | // Populate the list of modules. |
1619 | 2 | for (ModuleMap::module_iterator M = ModMap.module_begin(), |
1620 | 2 | MEnd = ModMap.module_end(); |
1621 | 336 | M != MEnd; ++M334 ) { |
1622 | 334 | Modules.push_back(M->getValue()); |
1623 | 334 | } |
1624 | 2 | } |
1625 | | |
1626 | 38 | void HeaderSearch::loadTopLevelSystemModules() { |
1627 | 38 | if (!HSOpts->ImplicitModuleMaps) |
1628 | 0 | return; |
1629 | 38 | |
1630 | 38 | // Load module maps for each of the header search directories. |
1631 | 106 | for (unsigned Idx = 0, N = SearchDirs.size(); 38 Idx != N; ++Idx68 ) { |
1632 | 68 | // We only care about normal header directories. |
1633 | 68 | if (!SearchDirs[Idx].isNormalDir()) { |
1634 | 6 | continue; |
1635 | 6 | } |
1636 | 62 | |
1637 | 62 | // Try to load a module map file for the search directory. |
1638 | 62 | loadModuleMapFile(SearchDirs[Idx].getDir(), |
1639 | 62 | SearchDirs[Idx].isSystemHeaderDirectory(), |
1640 | 62 | SearchDirs[Idx].isFramework()); |
1641 | 62 | } |
1642 | 38 | } |
1643 | | |
1644 | 77 | void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { |
1645 | 77 | assert(HSOpts->ImplicitModuleMaps && |
1646 | 77 | "Should not be loading subdirectory module maps"); |
1647 | 77 | |
1648 | 77 | if (SearchDir.haveSearchedAllModuleMaps()) |
1649 | 0 | return; |
1650 | 77 | |
1651 | 77 | std::error_code EC; |
1652 | 77 | SmallString<128> Dir = SearchDir.getDir()->getName(); |
1653 | 77 | FileMgr.makeAbsolutePath(Dir); |
1654 | 77 | SmallString<128> DirNative; |
1655 | 77 | llvm::sys::path::native(Dir, DirNative); |
1656 | 77 | llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); |
1657 | 77 | for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; |
1658 | 4.00k | Dir != DirEnd && !EC3.92k ; Dir.increment(EC)3.92k ) { |
1659 | 3.92k | bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework"; |
1660 | 3.92k | if (IsFramework == SearchDir.isFramework()) |
1661 | 3.90k | loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), |
1662 | 3.90k | SearchDir.isFramework()); |
1663 | 3.92k | } |
1664 | 77 | |
1665 | 77 | SearchDir.setSearchedAllModuleMaps(true); |
1666 | 77 | } |
1667 | | |
1668 | | std::string HeaderSearch::suggestPathToFileForDiagnostics( |
1669 | 195 | const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) { |
1670 | 195 | // FIXME: We assume that the path name currently cached in the FileEntry is |
1671 | 195 | // the most appropriate one for this analysis (and that it's spelled the |
1672 | 195 | // same way as the corresponding header search path). |
1673 | 195 | return suggestPathToFileForDiagnostics(File->getName(), /*WorkingDir=*/"", |
1674 | 195 | MainFile, IsSystem); |
1675 | 195 | } |
1676 | | |
1677 | | std::string HeaderSearch::suggestPathToFileForDiagnostics( |
1678 | | llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile, |
1679 | 204 | bool *IsSystem) { |
1680 | 204 | using namespace llvm::sys; |
1681 | 204 | |
1682 | 204 | unsigned BestPrefixLength = 0; |
1683 | 204 | // Checks whether Dir and File shares a common prefix, if they do and that's |
1684 | 204 | // the longest prefix we've seen so for it returns true and updates the |
1685 | 204 | // BestPrefixLength accordingly. |
1686 | 403 | auto CheckDir = [&](llvm::StringRef Dir) -> bool { |
1687 | 403 | llvm::SmallString<32> DirPath(Dir.begin(), Dir.end()); |
1688 | 403 | if (!WorkingDir.empty() && !path::is_absolute(Dir)3 ) |
1689 | 2 | fs::make_absolute(WorkingDir, DirPath); |
1690 | 403 | path::remove_dots(DirPath, /*remove_dot_dot=*/true); |
1691 | 403 | Dir = DirPath; |
1692 | 403 | for (auto NI = path::begin(File), NE = path::end(File), |
1693 | 403 | DI = path::begin(Dir), DE = path::end(Dir); |
1694 | 4.15k | /*termination condition in loop*/; ++NI, ++DI3.75k ) { |
1695 | 4.15k | // '.' components in File are ignored. |
1696 | 4.15k | while (NI != NE && *NI == ".") |
1697 | 2 | ++NI; |
1698 | 4.15k | if (NI == NE) |
1699 | 0 | break; |
1700 | 4.15k | |
1701 | 4.15k | // '.' components in Dir are ignored. |
1702 | 4.15k | while (DI != DE && *DI == "."3.95k ) |
1703 | 0 | ++DI; |
1704 | 4.15k | if (DI == DE) { |
1705 | 205 | // Dir is a prefix of File, up to '.' components and choice of path |
1706 | 205 | // separators. |
1707 | 205 | unsigned PrefixLength = NI - path::begin(File); |
1708 | 205 | if (PrefixLength > BestPrefixLength) { |
1709 | 204 | BestPrefixLength = PrefixLength; |
1710 | 204 | return true; |
1711 | 204 | } |
1712 | 1 | break; |
1713 | 1 | } |
1714 | 3.95k | |
1715 | 3.95k | // Consider all path separators equal. |
1716 | 3.95k | if (NI->size() == 1 && DI->size() == 1422 && |
1717 | 3.95k | path::is_separator(NI->front())422 && path::is_separator(DI->front())402 ) |
1718 | 402 | continue; |
1719 | 3.54k | |
1720 | 3.54k | if (*NI != *DI) |
1721 | 198 | break; |
1722 | 3.54k | } |
1723 | 403 | return false199 ; |
1724 | 403 | }; |
1725 | 204 | |
1726 | 605 | for (unsigned I = 0; I != SearchDirs.size(); ++I401 ) { |
1727 | 401 | // FIXME: Support this search within frameworks and header maps. |
1728 | 401 | if (!SearchDirs[I].isNormalDir()) |
1729 | 0 | continue; |
1730 | 401 | |
1731 | 401 | StringRef Dir = SearchDirs[I].getDir()->getName(); |
1732 | 401 | if (CheckDir(Dir) && IsSystem203 ) |
1733 | 195 | *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false0 ; |
1734 | 401 | } |
1735 | 204 | |
1736 | 204 | // Try to shorten include path using TUs directory, if we couldn't find any |
1737 | 204 | // suitable prefix in include search paths. |
1738 | 204 | if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))2 && IsSystem1 ) |
1739 | 0 | *IsSystem = false; |
1740 | 204 | |
1741 | 204 | |
1742 | 204 | return path::convert_to_slash(File.drop_front(BestPrefixLength)); |
1743 | 204 | } |