/src/llvm-project/clang/lib/Basic/Module.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Module.cpp - Describe a module -------------------------------------===// |
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 defines the Module class, which describes a module in the source |
10 | | // code. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/Basic/Module.h" |
15 | | #include "clang/Basic/CharInfo.h" |
16 | | #include "clang/Basic/FileManager.h" |
17 | | #include "clang/Basic/LangOptions.h" |
18 | | #include "clang/Basic/SourceLocation.h" |
19 | | #include "clang/Basic/TargetInfo.h" |
20 | | #include "llvm/ADT/ArrayRef.h" |
21 | | #include "llvm/ADT/SmallVector.h" |
22 | | #include "llvm/ADT/StringMap.h" |
23 | | #include "llvm/ADT/StringRef.h" |
24 | | #include "llvm/ADT/StringSwitch.h" |
25 | | #include "llvm/Support/Compiler.h" |
26 | | #include "llvm/Support/ErrorHandling.h" |
27 | | #include "llvm/Support/raw_ostream.h" |
28 | | #include <algorithm> |
29 | | #include <cassert> |
30 | | #include <functional> |
31 | | #include <string> |
32 | | #include <utility> |
33 | | #include <vector> |
34 | | |
35 | | using namespace clang; |
36 | | |
37 | | Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, |
38 | | bool IsFramework, bool IsExplicit, unsigned VisibilityID) |
39 | | : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), |
40 | | VisibilityID(VisibilityID), IsUnimportable(false), |
41 | | HasIncompatibleModuleFile(false), IsAvailable(true), |
42 | | IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit), |
43 | | IsSystem(false), IsExternC(false), IsInferred(false), |
44 | | InferSubmodules(false), InferExplicitSubmodules(false), |
45 | | InferExportWildcard(false), ConfigMacrosExhaustive(false), |
46 | | NoUndeclaredIncludes(false), ModuleMapIsPrivate(false), |
47 | 0 | NamedModuleHasInit(true), NameVisibility(Hidden) { |
48 | 0 | if (Parent) { |
49 | 0 | IsAvailable = Parent->isAvailable(); |
50 | 0 | IsUnimportable = Parent->isUnimportable(); |
51 | 0 | IsSystem = Parent->IsSystem; |
52 | 0 | IsExternC = Parent->IsExternC; |
53 | 0 | NoUndeclaredIncludes = Parent->NoUndeclaredIncludes; |
54 | 0 | ModuleMapIsPrivate = Parent->ModuleMapIsPrivate; |
55 | |
|
56 | 0 | Parent->SubModuleIndex[Name] = Parent->SubModules.size(); |
57 | 0 | Parent->SubModules.push_back(this); |
58 | 0 | } |
59 | 0 | } |
60 | | |
61 | 0 | Module::~Module() { |
62 | 0 | for (auto *Submodule : SubModules) { |
63 | 0 | delete Submodule; |
64 | 0 | } |
65 | 0 | } |
66 | | |
67 | 0 | static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) { |
68 | 0 | StringRef Platform = Target.getPlatformName(); |
69 | 0 | StringRef Env = Target.getTriple().getEnvironmentName(); |
70 | | |
71 | | // Attempt to match platform and environment. |
72 | 0 | if (Platform == Feature || Target.getTriple().getOSName() == Feature || |
73 | 0 | Env == Feature) |
74 | 0 | return true; |
75 | | |
76 | 0 | auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) { |
77 | 0 | auto Pos = LHS.find('-'); |
78 | 0 | if (Pos == StringRef::npos) |
79 | 0 | return false; |
80 | 0 | SmallString<128> NewLHS = LHS.slice(0, Pos); |
81 | 0 | NewLHS += LHS.slice(Pos+1, LHS.size()); |
82 | 0 | return NewLHS == RHS; |
83 | 0 | }; |
84 | |
|
85 | 0 | SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName(); |
86 | | // Darwin has different but equivalent variants for simulators, example: |
87 | | // 1. x86_64-apple-ios-simulator |
88 | | // 2. x86_64-apple-iossimulator |
89 | | // where both are valid examples of the same platform+environment but in the |
90 | | // variant (2) the simulator is hardcoded as part of the platform name. Both |
91 | | // forms above should match for "iossimulator" requirement. |
92 | 0 | if (Target.getTriple().isOSDarwin() && PlatformEnv.ends_with("simulator")) |
93 | 0 | return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature); |
94 | | |
95 | 0 | return PlatformEnv == Feature; |
96 | 0 | } |
97 | | |
98 | | /// Determine whether a translation unit built using the current |
99 | | /// language options has the given feature. |
100 | | static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, |
101 | 0 | const TargetInfo &Target) { |
102 | 0 | bool HasFeature = llvm::StringSwitch<bool>(Feature) |
103 | 0 | .Case("altivec", LangOpts.AltiVec) |
104 | 0 | .Case("blocks", LangOpts.Blocks) |
105 | 0 | .Case("coroutines", LangOpts.Coroutines) |
106 | 0 | .Case("cplusplus", LangOpts.CPlusPlus) |
107 | 0 | .Case("cplusplus11", LangOpts.CPlusPlus11) |
108 | 0 | .Case("cplusplus14", LangOpts.CPlusPlus14) |
109 | 0 | .Case("cplusplus17", LangOpts.CPlusPlus17) |
110 | 0 | .Case("cplusplus20", LangOpts.CPlusPlus20) |
111 | 0 | .Case("cplusplus23", LangOpts.CPlusPlus23) |
112 | 0 | .Case("cplusplus26", LangOpts.CPlusPlus26) |
113 | 0 | .Case("c99", LangOpts.C99) |
114 | 0 | .Case("c11", LangOpts.C11) |
115 | 0 | .Case("c17", LangOpts.C17) |
116 | 0 | .Case("c23", LangOpts.C23) |
117 | 0 | .Case("freestanding", LangOpts.Freestanding) |
118 | 0 | .Case("gnuinlineasm", LangOpts.GNUAsm) |
119 | 0 | .Case("objc", LangOpts.ObjC) |
120 | 0 | .Case("objc_arc", LangOpts.ObjCAutoRefCount) |
121 | 0 | .Case("opencl", LangOpts.OpenCL) |
122 | 0 | .Case("tls", Target.isTLSSupported()) |
123 | 0 | .Case("zvector", LangOpts.ZVector) |
124 | 0 | .Default(Target.hasFeature(Feature) || |
125 | 0 | isPlatformEnvironment(Target, Feature)); |
126 | 0 | if (!HasFeature) |
127 | 0 | HasFeature = llvm::is_contained(LangOpts.ModuleFeatures, Feature); |
128 | 0 | return HasFeature; |
129 | 0 | } |
130 | | |
131 | | bool Module::isUnimportable(const LangOptions &LangOpts, |
132 | | const TargetInfo &Target, Requirement &Req, |
133 | 0 | Module *&ShadowingModule) const { |
134 | 0 | if (!IsUnimportable) |
135 | 0 | return false; |
136 | | |
137 | 0 | for (const Module *Current = this; Current; Current = Current->Parent) { |
138 | 0 | if (Current->ShadowingModule) { |
139 | 0 | ShadowingModule = Current->ShadowingModule; |
140 | 0 | return true; |
141 | 0 | } |
142 | 0 | for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) { |
143 | 0 | if (hasFeature(Current->Requirements[I].first, LangOpts, Target) != |
144 | 0 | Current->Requirements[I].second) { |
145 | 0 | Req = Current->Requirements[I]; |
146 | 0 | return true; |
147 | 0 | } |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | 0 | llvm_unreachable("could not find a reason why module is unimportable"); |
152 | 0 | } |
153 | | |
154 | | // The -fmodule-name option tells the compiler to textually include headers in |
155 | | // the specified module, meaning Clang won't build the specified module. This |
156 | | // is useful in a number of situations, for instance, when building a library |
157 | | // that vends a module map, one might want to avoid hitting intermediate build |
158 | | // products containing the module map or avoid finding the system installed |
159 | | // modulemap for that library. |
160 | 0 | bool Module::isForBuilding(const LangOptions &LangOpts) const { |
161 | 0 | StringRef TopLevelName = getTopLevelModuleName(); |
162 | 0 | StringRef CurrentModule = LangOpts.CurrentModule; |
163 | | |
164 | | // When building the implementation of framework Foo, we want to make sure |
165 | | // that Foo *and* Foo_Private are textually included and no modules are built |
166 | | // for either. |
167 | 0 | if (!LangOpts.isCompilingModule() && getTopLevelModule()->IsFramework && |
168 | 0 | CurrentModule == LangOpts.ModuleName && |
169 | 0 | !CurrentModule.ends_with("_Private") && |
170 | 0 | TopLevelName.ends_with("_Private")) |
171 | 0 | TopLevelName = TopLevelName.drop_back(8); |
172 | |
|
173 | 0 | return TopLevelName == CurrentModule; |
174 | 0 | } |
175 | | |
176 | | bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, |
177 | | Requirement &Req, |
178 | | UnresolvedHeaderDirective &MissingHeader, |
179 | 0 | Module *&ShadowingModule) const { |
180 | 0 | if (IsAvailable) |
181 | 0 | return true; |
182 | | |
183 | 0 | if (isUnimportable(LangOpts, Target, Req, ShadowingModule)) |
184 | 0 | return false; |
185 | | |
186 | | // FIXME: All missing headers are listed on the top-level module. Should we |
187 | | // just look there? |
188 | 0 | for (const Module *Current = this; Current; Current = Current->Parent) { |
189 | 0 | if (!Current->MissingHeaders.empty()) { |
190 | 0 | MissingHeader = Current->MissingHeaders.front(); |
191 | 0 | return false; |
192 | 0 | } |
193 | 0 | } |
194 | | |
195 | 0 | llvm_unreachable("could not find a reason why module is unavailable"); |
196 | 0 | } |
197 | | |
198 | 0 | bool Module::isSubModuleOf(const Module *Other) const { |
199 | 0 | for (auto *Parent = this; Parent; Parent = Parent->Parent) { |
200 | 0 | if (Parent == Other) |
201 | 0 | return true; |
202 | 0 | } |
203 | 0 | return false; |
204 | 0 | } |
205 | | |
206 | 0 | const Module *Module::getTopLevelModule() const { |
207 | 0 | const Module *Result = this; |
208 | 0 | while (Result->Parent) |
209 | 0 | Result = Result->Parent; |
210 | |
|
211 | 0 | return Result; |
212 | 0 | } |
213 | | |
214 | | static StringRef getModuleNameFromComponent( |
215 | 0 | const std::pair<std::string, SourceLocation> &IdComponent) { |
216 | 0 | return IdComponent.first; |
217 | 0 | } |
218 | | |
219 | 0 | static StringRef getModuleNameFromComponent(StringRef R) { return R; } |
220 | | |
221 | | template<typename InputIter> |
222 | | static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End, |
223 | 0 | bool AllowStringLiterals = true) { |
224 | 0 | for (InputIter It = Begin; It != End; ++It) { |
225 | 0 | if (It != Begin) |
226 | 0 | OS << "."; |
227 | |
|
228 | 0 | StringRef Name = getModuleNameFromComponent(*It); |
229 | 0 | if (!AllowStringLiterals || isValidAsciiIdentifier(Name)) |
230 | 0 | OS << Name; |
231 | 0 | else { |
232 | 0 | OS << '"'; |
233 | 0 | OS.write_escaped(Name); |
234 | 0 | OS << '"'; |
235 | 0 | } |
236 | 0 | } |
237 | 0 | } Unexecuted instantiation: Module.cpp:void printModuleId<std::__1::reverse_iterator<llvm::StringRef*> >(llvm::raw_ostream&, std::__1::reverse_iterator<llvm::StringRef*>, std::__1::reverse_iterator<llvm::StringRef*>, bool) Unexecuted instantiation: Module.cpp:void printModuleId<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*>(llvm::raw_ostream&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*, bool) Unexecuted instantiation: Module.cpp:void printModuleId<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, clang::SourceLocation> const*>(llvm::raw_ostream&, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, clang::SourceLocation> const*, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, clang::SourceLocation> const*, bool) |
238 | | |
239 | | template<typename Container> |
240 | 0 | static void printModuleId(raw_ostream &OS, const Container &C) { |
241 | 0 | return printModuleId(OS, C.begin(), C.end()); |
242 | 0 | } |
243 | | |
244 | 0 | std::string Module::getFullModuleName(bool AllowStringLiterals) const { |
245 | 0 | SmallVector<StringRef, 2> Names; |
246 | | |
247 | | // Build up the set of module names (from innermost to outermost). |
248 | 0 | for (const Module *M = this; M; M = M->Parent) |
249 | 0 | Names.push_back(M->Name); |
250 | |
|
251 | 0 | std::string Result; |
252 | |
|
253 | 0 | llvm::raw_string_ostream Out(Result); |
254 | 0 | printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals); |
255 | 0 | Out.flush(); |
256 | |
|
257 | 0 | return Result; |
258 | 0 | } |
259 | | |
260 | 0 | bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const { |
261 | 0 | for (const Module *M = this; M; M = M->Parent) { |
262 | 0 | if (nameParts.empty() || M->Name != nameParts.back()) |
263 | 0 | return false; |
264 | 0 | nameParts = nameParts.drop_back(); |
265 | 0 | } |
266 | 0 | return nameParts.empty(); |
267 | 0 | } |
268 | | |
269 | 0 | OptionalDirectoryEntryRef Module::getEffectiveUmbrellaDir() const { |
270 | 0 | if (const auto *Hdr = std::get_if<FileEntryRef>(&Umbrella)) |
271 | 0 | return Hdr->getDir(); |
272 | 0 | if (const auto *Dir = std::get_if<DirectoryEntryRef>(&Umbrella)) |
273 | 0 | return *Dir; |
274 | 0 | return std::nullopt; |
275 | 0 | } |
276 | | |
277 | 0 | void Module::addTopHeader(FileEntryRef File) { |
278 | 0 | assert(File); |
279 | 0 | TopHeaders.insert(File); |
280 | 0 | } |
281 | | |
282 | 0 | ArrayRef<FileEntryRef> Module::getTopHeaders(FileManager &FileMgr) { |
283 | 0 | if (!TopHeaderNames.empty()) { |
284 | 0 | for (StringRef TopHeaderName : TopHeaderNames) |
285 | 0 | if (auto FE = FileMgr.getOptionalFileRef(TopHeaderName)) |
286 | 0 | TopHeaders.insert(*FE); |
287 | 0 | TopHeaderNames.clear(); |
288 | 0 | } |
289 | |
|
290 | 0 | return llvm::ArrayRef(TopHeaders.begin(), TopHeaders.end()); |
291 | 0 | } |
292 | | |
293 | 0 | bool Module::directlyUses(const Module *Requested) { |
294 | 0 | auto *Top = getTopLevelModule(); |
295 | | |
296 | | // A top-level module implicitly uses itself. |
297 | 0 | if (Requested->isSubModuleOf(Top)) |
298 | 0 | return true; |
299 | | |
300 | 0 | for (auto *Use : Top->DirectUses) |
301 | 0 | if (Requested->isSubModuleOf(Use)) |
302 | 0 | return true; |
303 | | |
304 | | // Anyone is allowed to use our builtin stdarg.h and stddef.h and their |
305 | | // accompanying modules. |
306 | 0 | if (Requested->getTopLevelModuleName() == "_Builtin_stdarg" || |
307 | 0 | Requested->getTopLevelModuleName() == "_Builtin_stddef") |
308 | 0 | return true; |
309 | | |
310 | 0 | if (NoUndeclaredIncludes) |
311 | 0 | UndeclaredUses.insert(Requested); |
312 | |
|
313 | 0 | return false; |
314 | 0 | } |
315 | | |
316 | | void Module::addRequirement(StringRef Feature, bool RequiredState, |
317 | | const LangOptions &LangOpts, |
318 | 0 | const TargetInfo &Target) { |
319 | 0 | Requirements.push_back(Requirement(std::string(Feature), RequiredState)); |
320 | | |
321 | | // If this feature is currently available, we're done. |
322 | 0 | if (hasFeature(Feature, LangOpts, Target) == RequiredState) |
323 | 0 | return; |
324 | | |
325 | 0 | markUnavailable(/*Unimportable*/true); |
326 | 0 | } |
327 | | |
328 | 0 | void Module::markUnavailable(bool Unimportable) { |
329 | 0 | auto needUpdate = [Unimportable](Module *M) { |
330 | 0 | return M->IsAvailable || (!M->IsUnimportable && Unimportable); |
331 | 0 | }; |
332 | |
|
333 | 0 | if (!needUpdate(this)) |
334 | 0 | return; |
335 | | |
336 | 0 | SmallVector<Module *, 2> Stack; |
337 | 0 | Stack.push_back(this); |
338 | 0 | while (!Stack.empty()) { |
339 | 0 | Module *Current = Stack.back(); |
340 | 0 | Stack.pop_back(); |
341 | |
|
342 | 0 | if (!needUpdate(Current)) |
343 | 0 | continue; |
344 | | |
345 | 0 | Current->IsAvailable = false; |
346 | 0 | Current->IsUnimportable |= Unimportable; |
347 | 0 | for (auto *Submodule : Current->submodules()) { |
348 | 0 | if (needUpdate(Submodule)) |
349 | 0 | Stack.push_back(Submodule); |
350 | 0 | } |
351 | 0 | } |
352 | 0 | } |
353 | | |
354 | 0 | Module *Module::findSubmodule(StringRef Name) const { |
355 | 0 | llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name); |
356 | 0 | if (Pos == SubModuleIndex.end()) |
357 | 0 | return nullptr; |
358 | | |
359 | 0 | return SubModules[Pos->getValue()]; |
360 | 0 | } |
361 | | |
362 | 0 | Module *Module::findOrInferSubmodule(StringRef Name) { |
363 | 0 | llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name); |
364 | 0 | if (Pos != SubModuleIndex.end()) |
365 | 0 | return SubModules[Pos->getValue()]; |
366 | 0 | if (!InferSubmodules) |
367 | 0 | return nullptr; |
368 | 0 | Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0); |
369 | 0 | Result->InferExplicitSubmodules = InferExplicitSubmodules; |
370 | 0 | Result->InferSubmodules = InferSubmodules; |
371 | 0 | Result->InferExportWildcard = InferExportWildcard; |
372 | 0 | if (Result->InferExportWildcard) |
373 | 0 | Result->Exports.push_back(Module::ExportDecl(nullptr, true)); |
374 | 0 | return Result; |
375 | 0 | } |
376 | | |
377 | 0 | Module *Module::getGlobalModuleFragment() const { |
378 | 0 | assert(isNamedModuleUnit() && "We should only query the global module " |
379 | 0 | "fragment from the C++ 20 Named modules"); |
380 | | |
381 | 0 | for (auto *SubModule : SubModules) |
382 | 0 | if (SubModule->isExplicitGlobalModule()) |
383 | 0 | return SubModule; |
384 | | |
385 | 0 | return nullptr; |
386 | 0 | } |
387 | | |
388 | 0 | Module *Module::getPrivateModuleFragment() const { |
389 | 0 | assert(isNamedModuleUnit() && "We should only query the private module " |
390 | 0 | "fragment from the C++ 20 Named modules"); |
391 | | |
392 | 0 | for (auto *SubModule : SubModules) |
393 | 0 | if (SubModule->isPrivateModule()) |
394 | 0 | return SubModule; |
395 | | |
396 | 0 | return nullptr; |
397 | 0 | } |
398 | | |
399 | 0 | void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const { |
400 | | // All non-explicit submodules are exported. |
401 | 0 | for (std::vector<Module *>::const_iterator I = SubModules.begin(), |
402 | 0 | E = SubModules.end(); |
403 | 0 | I != E; ++I) { |
404 | 0 | Module *Mod = *I; |
405 | 0 | if (!Mod->IsExplicit) |
406 | 0 | Exported.push_back(Mod); |
407 | 0 | } |
408 | | |
409 | | // Find re-exported modules by filtering the list of imported modules. |
410 | 0 | bool AnyWildcard = false; |
411 | 0 | bool UnrestrictedWildcard = false; |
412 | 0 | SmallVector<Module *, 4> WildcardRestrictions; |
413 | 0 | for (unsigned I = 0, N = Exports.size(); I != N; ++I) { |
414 | 0 | Module *Mod = Exports[I].getPointer(); |
415 | 0 | if (!Exports[I].getInt()) { |
416 | | // Export a named module directly; no wildcards involved. |
417 | 0 | Exported.push_back(Mod); |
418 | |
|
419 | 0 | continue; |
420 | 0 | } |
421 | | |
422 | | // Wildcard export: export all of the imported modules that match |
423 | | // the given pattern. |
424 | 0 | AnyWildcard = true; |
425 | 0 | if (UnrestrictedWildcard) |
426 | 0 | continue; |
427 | | |
428 | 0 | if (Module *Restriction = Exports[I].getPointer()) |
429 | 0 | WildcardRestrictions.push_back(Restriction); |
430 | 0 | else { |
431 | 0 | WildcardRestrictions.clear(); |
432 | 0 | UnrestrictedWildcard = true; |
433 | 0 | } |
434 | 0 | } |
435 | | |
436 | | // If there were any wildcards, push any imported modules that were |
437 | | // re-exported by the wildcard restriction. |
438 | 0 | if (!AnyWildcard) |
439 | 0 | return; |
440 | | |
441 | 0 | for (unsigned I = 0, N = Imports.size(); I != N; ++I) { |
442 | 0 | Module *Mod = Imports[I]; |
443 | 0 | bool Acceptable = UnrestrictedWildcard; |
444 | 0 | if (!Acceptable) { |
445 | | // Check whether this module meets one of the restrictions. |
446 | 0 | for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) { |
447 | 0 | Module *Restriction = WildcardRestrictions[R]; |
448 | 0 | if (Mod == Restriction || Mod->isSubModuleOf(Restriction)) { |
449 | 0 | Acceptable = true; |
450 | 0 | break; |
451 | 0 | } |
452 | 0 | } |
453 | 0 | } |
454 | |
|
455 | 0 | if (!Acceptable) |
456 | 0 | continue; |
457 | | |
458 | 0 | Exported.push_back(Mod); |
459 | 0 | } |
460 | 0 | } |
461 | | |
462 | 0 | void Module::buildVisibleModulesCache() const { |
463 | 0 | assert(VisibleModulesCache.empty() && "cache does not need building"); |
464 | | |
465 | | // This module is visible to itself. |
466 | 0 | VisibleModulesCache.insert(this); |
467 | | |
468 | | // Every imported module is visible. |
469 | 0 | SmallVector<Module *, 16> Stack(Imports.begin(), Imports.end()); |
470 | 0 | while (!Stack.empty()) { |
471 | 0 | Module *CurrModule = Stack.pop_back_val(); |
472 | | |
473 | | // Every module transitively exported by an imported module is visible. |
474 | 0 | if (VisibleModulesCache.insert(CurrModule).second) |
475 | 0 | CurrModule->getExportedModules(Stack); |
476 | 0 | } |
477 | 0 | } |
478 | | |
479 | 0 | void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const { |
480 | 0 | OS.indent(Indent); |
481 | 0 | if (IsFramework) |
482 | 0 | OS << "framework "; |
483 | 0 | if (IsExplicit) |
484 | 0 | OS << "explicit "; |
485 | 0 | OS << "module "; |
486 | 0 | printModuleId(OS, &Name, &Name + 1); |
487 | |
|
488 | 0 | if (IsSystem || IsExternC) { |
489 | 0 | OS.indent(Indent + 2); |
490 | 0 | if (IsSystem) |
491 | 0 | OS << " [system]"; |
492 | 0 | if (IsExternC) |
493 | 0 | OS << " [extern_c]"; |
494 | 0 | } |
495 | |
|
496 | 0 | OS << " {\n"; |
497 | |
|
498 | 0 | if (!Requirements.empty()) { |
499 | 0 | OS.indent(Indent + 2); |
500 | 0 | OS << "requires "; |
501 | 0 | for (unsigned I = 0, N = Requirements.size(); I != N; ++I) { |
502 | 0 | if (I) |
503 | 0 | OS << ", "; |
504 | 0 | if (!Requirements[I].second) |
505 | 0 | OS << "!"; |
506 | 0 | OS << Requirements[I].first; |
507 | 0 | } |
508 | 0 | OS << "\n"; |
509 | 0 | } |
510 | |
|
511 | 0 | if (std::optional<Header> H = getUmbrellaHeaderAsWritten()) { |
512 | 0 | OS.indent(Indent + 2); |
513 | 0 | OS << "umbrella header \""; |
514 | 0 | OS.write_escaped(H->NameAsWritten); |
515 | 0 | OS << "\"\n"; |
516 | 0 | } else if (std::optional<DirectoryName> D = getUmbrellaDirAsWritten()) { |
517 | 0 | OS.indent(Indent + 2); |
518 | 0 | OS << "umbrella \""; |
519 | 0 | OS.write_escaped(D->NameAsWritten); |
520 | 0 | OS << "\"\n"; |
521 | 0 | } |
522 | |
|
523 | 0 | if (!ConfigMacros.empty() || ConfigMacrosExhaustive) { |
524 | 0 | OS.indent(Indent + 2); |
525 | 0 | OS << "config_macros "; |
526 | 0 | if (ConfigMacrosExhaustive) |
527 | 0 | OS << "[exhaustive]"; |
528 | 0 | for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) { |
529 | 0 | if (I) |
530 | 0 | OS << ", "; |
531 | 0 | OS << ConfigMacros[I]; |
532 | 0 | } |
533 | 0 | OS << "\n"; |
534 | 0 | } |
535 | |
|
536 | 0 | struct { |
537 | 0 | StringRef Prefix; |
538 | 0 | HeaderKind Kind; |
539 | 0 | } Kinds[] = {{"", HK_Normal}, |
540 | 0 | {"textual ", HK_Textual}, |
541 | 0 | {"private ", HK_Private}, |
542 | 0 | {"private textual ", HK_PrivateTextual}, |
543 | 0 | {"exclude ", HK_Excluded}}; |
544 | |
|
545 | 0 | for (auto &K : Kinds) { |
546 | 0 | assert(&K == &Kinds[K.Kind] && "kinds in wrong order"); |
547 | 0 | for (auto &H : Headers[K.Kind]) { |
548 | 0 | OS.indent(Indent + 2); |
549 | 0 | OS << K.Prefix << "header \""; |
550 | 0 | OS.write_escaped(H.NameAsWritten); |
551 | 0 | OS << "\" { size " << H.Entry.getSize() |
552 | 0 | << " mtime " << H.Entry.getModificationTime() << " }\n"; |
553 | 0 | } |
554 | 0 | } |
555 | 0 | for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) { |
556 | 0 | for (auto &U : *Unresolved) { |
557 | 0 | OS.indent(Indent + 2); |
558 | 0 | OS << Kinds[U.Kind].Prefix << "header \""; |
559 | 0 | OS.write_escaped(U.FileName); |
560 | 0 | OS << "\""; |
561 | 0 | if (U.Size || U.ModTime) { |
562 | 0 | OS << " {"; |
563 | 0 | if (U.Size) |
564 | 0 | OS << " size " << *U.Size; |
565 | 0 | if (U.ModTime) |
566 | 0 | OS << " mtime " << *U.ModTime; |
567 | 0 | OS << " }"; |
568 | 0 | } |
569 | 0 | OS << "\n"; |
570 | 0 | } |
571 | 0 | } |
572 | |
|
573 | 0 | if (!ExportAsModule.empty()) { |
574 | 0 | OS.indent(Indent + 2); |
575 | 0 | OS << "export_as" << ExportAsModule << "\n"; |
576 | 0 | } |
577 | |
|
578 | 0 | for (auto *Submodule : submodules()) |
579 | | // Print inferred subframework modules so that we don't need to re-infer |
580 | | // them (requires expensive directory iteration + stat calls) when we build |
581 | | // the module. Regular inferred submodules are OK, as we need to look at all |
582 | | // those header files anyway. |
583 | 0 | if (!Submodule->IsInferred || Submodule->IsFramework) |
584 | 0 | Submodule->print(OS, Indent + 2, Dump); |
585 | |
|
586 | 0 | for (unsigned I = 0, N = Exports.size(); I != N; ++I) { |
587 | 0 | OS.indent(Indent + 2); |
588 | 0 | OS << "export "; |
589 | 0 | if (Module *Restriction = Exports[I].getPointer()) { |
590 | 0 | OS << Restriction->getFullModuleName(true); |
591 | 0 | if (Exports[I].getInt()) |
592 | 0 | OS << ".*"; |
593 | 0 | } else { |
594 | 0 | OS << "*"; |
595 | 0 | } |
596 | 0 | OS << "\n"; |
597 | 0 | } |
598 | |
|
599 | 0 | for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { |
600 | 0 | OS.indent(Indent + 2); |
601 | 0 | OS << "export "; |
602 | 0 | printModuleId(OS, UnresolvedExports[I].Id); |
603 | 0 | if (UnresolvedExports[I].Wildcard) |
604 | 0 | OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*"); |
605 | 0 | OS << "\n"; |
606 | 0 | } |
607 | |
|
608 | 0 | if (Dump) { |
609 | 0 | for (Module *M : Imports) { |
610 | 0 | OS.indent(Indent + 2); |
611 | 0 | llvm::errs() << "import " << M->getFullModuleName() << "\n"; |
612 | 0 | } |
613 | 0 | } |
614 | |
|
615 | 0 | for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) { |
616 | 0 | OS.indent(Indent + 2); |
617 | 0 | OS << "use "; |
618 | 0 | OS << DirectUses[I]->getFullModuleName(true); |
619 | 0 | OS << "\n"; |
620 | 0 | } |
621 | |
|
622 | 0 | for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) { |
623 | 0 | OS.indent(Indent + 2); |
624 | 0 | OS << "use "; |
625 | 0 | printModuleId(OS, UnresolvedDirectUses[I]); |
626 | 0 | OS << "\n"; |
627 | 0 | } |
628 | |
|
629 | 0 | for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { |
630 | 0 | OS.indent(Indent + 2); |
631 | 0 | OS << "link "; |
632 | 0 | if (LinkLibraries[I].IsFramework) |
633 | 0 | OS << "framework "; |
634 | 0 | OS << "\""; |
635 | 0 | OS.write_escaped(LinkLibraries[I].Library); |
636 | 0 | OS << "\""; |
637 | 0 | } |
638 | |
|
639 | 0 | for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) { |
640 | 0 | OS.indent(Indent + 2); |
641 | 0 | OS << "conflict "; |
642 | 0 | printModuleId(OS, UnresolvedConflicts[I].Id); |
643 | 0 | OS << ", \""; |
644 | 0 | OS.write_escaped(UnresolvedConflicts[I].Message); |
645 | 0 | OS << "\"\n"; |
646 | 0 | } |
647 | |
|
648 | 0 | for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) { |
649 | 0 | OS.indent(Indent + 2); |
650 | 0 | OS << "conflict "; |
651 | 0 | OS << Conflicts[I].Other->getFullModuleName(true); |
652 | 0 | OS << ", \""; |
653 | 0 | OS.write_escaped(Conflicts[I].Message); |
654 | 0 | OS << "\"\n"; |
655 | 0 | } |
656 | |
|
657 | 0 | if (InferSubmodules) { |
658 | 0 | OS.indent(Indent + 2); |
659 | 0 | if (InferExplicitSubmodules) |
660 | 0 | OS << "explicit "; |
661 | 0 | OS << "module * {\n"; |
662 | 0 | if (InferExportWildcard) { |
663 | 0 | OS.indent(Indent + 4); |
664 | 0 | OS << "export *\n"; |
665 | 0 | } |
666 | 0 | OS.indent(Indent + 2); |
667 | 0 | OS << "}\n"; |
668 | 0 | } |
669 | |
|
670 | 0 | OS.indent(Indent); |
671 | 0 | OS << "}\n"; |
672 | 0 | } |
673 | | |
674 | 0 | LLVM_DUMP_METHOD void Module::dump() const { |
675 | 0 | print(llvm::errs(), 0, true); |
676 | 0 | } |
677 | | |
678 | | void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc, |
679 | 0 | VisibleCallback Vis, ConflictCallback Cb) { |
680 | | // We can't import a global module fragment so the location can be invalid. |
681 | 0 | assert((M->isGlobalModule() || Loc.isValid()) && |
682 | 0 | "setVisible expects a valid import location"); |
683 | 0 | if (isVisible(M)) |
684 | 0 | return; |
685 | | |
686 | 0 | ++Generation; |
687 | |
|
688 | 0 | struct Visiting { |
689 | 0 | Module *M; |
690 | 0 | Visiting *ExportedBy; |
691 | 0 | }; |
692 | |
|
693 | 0 | std::function<void(Visiting)> VisitModule = [&](Visiting V) { |
694 | | // Nothing to do for a module that's already visible. |
695 | 0 | unsigned ID = V.M->getVisibilityID(); |
696 | 0 | if (ImportLocs.size() <= ID) |
697 | 0 | ImportLocs.resize(ID + 1); |
698 | 0 | else if (ImportLocs[ID].isValid()) |
699 | 0 | return; |
700 | | |
701 | 0 | ImportLocs[ID] = Loc; |
702 | 0 | Vis(V.M); |
703 | | |
704 | | // Make any exported modules visible. |
705 | 0 | SmallVector<Module *, 16> Exports; |
706 | 0 | V.M->getExportedModules(Exports); |
707 | 0 | for (Module *E : Exports) { |
708 | | // Don't import non-importable modules. |
709 | 0 | if (!E->isUnimportable()) |
710 | 0 | VisitModule({E, &V}); |
711 | 0 | } |
712 | |
|
713 | 0 | for (auto &C : V.M->Conflicts) { |
714 | 0 | if (isVisible(C.Other)) { |
715 | 0 | llvm::SmallVector<Module*, 8> Path; |
716 | 0 | for (Visiting *I = &V; I; I = I->ExportedBy) |
717 | 0 | Path.push_back(I->M); |
718 | 0 | Cb(Path, C.Other, C.Message); |
719 | 0 | } |
720 | 0 | } |
721 | 0 | }; |
722 | 0 | VisitModule({M, nullptr}); |
723 | 0 | } |
724 | | |
725 | | void VisibleModuleSet::makeTransitiveImportsVisible(Module *M, |
726 | | SourceLocation Loc, |
727 | | VisibleCallback Vis, |
728 | 0 | ConflictCallback Cb) { |
729 | 0 | for (auto *I : M->Imports) |
730 | 0 | setVisible(I, Loc, Vis, Cb); |
731 | 0 | } |
732 | | |
733 | | ASTSourceDescriptor::ASTSourceDescriptor(Module &M) |
734 | 0 | : Signature(M.Signature), ClangModule(&M) { |
735 | 0 | if (M.Directory) |
736 | 0 | Path = M.Directory->getName(); |
737 | 0 | if (auto File = M.getASTFile()) |
738 | 0 | ASTFile = File->getName(); |
739 | 0 | } |
740 | | |
741 | 0 | std::string ASTSourceDescriptor::getModuleName() const { |
742 | 0 | if (ClangModule) |
743 | 0 | return ClangModule->Name; |
744 | 0 | else |
745 | 0 | return std::string(PCHModuleName); |
746 | 0 | } |