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

source code of clang/lib/Basic/Module.cpp