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