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"
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),
44 InferSubmodules(
false), InferExplicitSubmodules(
false),
45 InferExportWildcard(
false), ConfigMacrosExhaustive(
false),
46 NoUndeclaredIncludes(
false), ModuleMapIsPrivate(
false),
47 NamedModuleHasInit(
true), NameVisibility(Hidden) {
57 Parent->SubModules.push_back(
this);
62 for (
auto *Submodule : SubModules) {
68 StringRef Platform =
Target.getPlatformName();
69 StringRef
Env =
Target.getTriple().getEnvironmentName();
72 if (Platform == Feature ||
Target.getTriple().getOSName() == Feature ||
76 auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {
77 auto Pos = LHS.find(
'-');
78 if (Pos == StringRef::npos)
81 NewLHS += LHS.slice(Pos+1, LHS.size());
92 if (
Target.getTriple().isOSDarwin() && PlatformEnv.endswith(
"simulator"))
93 return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);
95 return PlatformEnv == Feature;
102 bool HasFeature = llvm::StringSwitch<bool>(Feature)
103 .Case(
"altivec", LangOpts.AltiVec)
104 .Case(
"blocks", LangOpts.Blocks)
105 .Case(
"coroutines", LangOpts.Coroutines)
106 .Case(
"cplusplus", LangOpts.CPlusPlus)
107 .Case(
"cplusplus11", LangOpts.CPlusPlus11)
108 .Case(
"cplusplus14", LangOpts.CPlusPlus14)
109 .Case(
"cplusplus17", LangOpts.CPlusPlus17)
110 .Case(
"cplusplus20", LangOpts.CPlusPlus20)
111 .Case(
"cplusplus23", LangOpts.CPlusPlus23)
112 .Case(
"cplusplus26", LangOpts.CPlusPlus26)
113 .Case(
"c99", LangOpts.C99)
114 .Case(
"c11", LangOpts.C11)
115 .Case(
"c17", LangOpts.C17)
116 .Case(
"c23", LangOpts.C23)
117 .Case(
"freestanding", LangOpts.Freestanding)
118 .Case(
"gnuinlineasm", LangOpts.GNUAsm)
119 .Case(
"objc", LangOpts.ObjC)
120 .Case(
"objc_arc", LangOpts.ObjCAutoRefCount)
121 .Case(
"opencl", LangOpts.OpenCL)
122 .Case(
"tls",
Target.isTLSSupported())
123 .Case(
"zvector", LangOpts.ZVector)
124 .Default(
Target.hasFeature(Feature) ||
133 Module *&ShadowingModule)
const {
137 for (
const Module *Current =
this; Current; Current = Current->Parent) {
138 if (Current->ShadowingModule) {
142 for (
unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
144 Current->Requirements[I].second) {
145 Req = Current->Requirements[I];
151 llvm_unreachable(
"could not find a reason why module is unimportable");
169 !CurrentModule.endswith(
"_Private") && TopLevelName.endswith(
"_Private"))
170 TopLevelName = TopLevelName.drop_back(8);
172 return TopLevelName == CurrentModule;
178 Module *&ShadowingModule)
const {
187 for (
const Module *Current =
this; Current; Current = Current->Parent) {
188 if (!Current->MissingHeaders.empty()) {
189 MissingHeader = Current->MissingHeaders.front();
194 llvm_unreachable(
"could not find a reason why module is unavailable");
214 const std::pair<std::string, SourceLocation> &IdComponent) {
215 return IdComponent.first;
220template<
typename InputIter>
222 bool AllowStringLiterals =
true) {
223 for (InputIter It =
Begin; It != End; ++It) {
232 OS.write_escaped(Name);
238template<
typename Container>
248 Names.push_back(M->Name);
252 llvm::raw_string_ostream Out(
Result);
253 printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
261 if (nameParts.empty() || M->Name != nameParts.back())
263 nameParts = nameParts.drop_back();
265 return nameParts.empty();
269 if (
const auto *Hdr = std::get_if<FileEntryRef>(&
Umbrella))
270 return Hdr->getDir();
271 if (
const auto *Dir = std::get_if<DirectoryEntryRef>(&
Umbrella))
278 TopHeaders.insert(
File);
282 if (!TopHeaderNames.empty()) {
283 for (StringRef TopHeaderName : TopHeaderNames)
285 TopHeaders.insert(*FE);
286 TopHeaderNames.clear();
299 for (
auto *Use : Top->DirectUses)
328 auto needUpdate = [Unimportable](
Module *M) {
329 return M->IsAvailable || (!M->IsUnimportable && Unimportable);
332 if (!needUpdate(
this))
336 Stack.push_back(
this);
337 while (!Stack.empty()) {
338 Module *Current = Stack.back();
341 if (!needUpdate(Current))
344 Current->IsAvailable =
false;
345 Current->IsUnimportable |= Unimportable;
346 for (
auto *Submodule : Current->submodules()) {
347 if (needUpdate(Submodule))
348 Stack.push_back(Submodule);
354 llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(
Name);
355 if (Pos == SubModuleIndex.end())
358 return SubModules[Pos->getValue()];
362 llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(
Name);
363 if (Pos != SubModuleIndex.end())
364 return SubModules[Pos->getValue()];
371 if (
Result->InferExportWildcard)
378 "fragment from the C++ 20 Named modules");
380 for (
auto *SubModule : SubModules)
381 if (SubModule->isExplicitGlobalModule())
389 "fragment from the C++ 20 Named modules");
391 for (
auto *SubModule : SubModules)
392 if (SubModule->isPrivateModule())
400 for (std::vector<Module *>::const_iterator I = SubModules.begin(),
401 E = SubModules.end();
405 Exported.push_back(Mod);
409 bool AnyWildcard =
false;
410 bool UnrestrictedWildcard =
false;
412 for (
unsigned I = 0, N =
Exports.size(); I != N; ++I) {
416 Exported.push_back(Mod);
424 if (UnrestrictedWildcard)
428 WildcardRestrictions.push_back(Restriction);
430 WildcardRestrictions.clear();
431 UnrestrictedWildcard =
true;
440 for (
unsigned I = 0, N =
Imports.size(); I != N; ++I) {
442 bool Acceptable = UnrestrictedWildcard;
445 for (
unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
446 Module *Restriction = WildcardRestrictions[R];
457 Exported.push_back(Mod);
461void Module::buildVisibleModulesCache()
const {
462 assert(VisibleModulesCache.empty() &&
"cache does not need building");
465 VisibleModulesCache.insert(
this);
469 while (!Stack.empty()) {
470 Module *CurrModule = Stack.pop_back_val();
473 if (VisibleModulesCache.insert(CurrModule).second)
488 OS.indent(Indent + 2);
498 OS.indent(Indent + 2);
500 for (
unsigned I = 0, N =
Requirements.size(); I != N; ++I) {
511 OS.indent(Indent + 2);
512 OS <<
"umbrella header \"";
513 OS.write_escaped(H->NameAsWritten);
516 OS.indent(Indent + 2);
518 OS.write_escaped(D->NameAsWritten);
523 OS.indent(Indent + 2);
524 OS <<
"config_macros ";
526 OS <<
"[exhaustive]";
527 for (
unsigned I = 0, N =
ConfigMacros.size(); I != N; ++I) {
544 for (
auto &K : Kinds) {
545 assert(&K == &Kinds[K.Kind] &&
"kinds in wrong order");
546 for (
auto &H :
Headers[K.Kind]) {
547 OS.indent(Indent + 2);
548 OS << K.Prefix <<
"header \"";
549 OS.write_escaped(H.NameAsWritten);
550 OS <<
"\" { size " << H.Entry.getSize()
551 <<
" mtime " << H.Entry.getModificationTime() <<
" }\n";
556 OS.indent(Indent + 2);
557 OS << Kinds[
U.Kind].Prefix <<
"header \"";
558 OS.write_escaped(
U.FileName);
560 if (
U.Size ||
U.ModTime) {
563 OS <<
" size " << *
U.Size;
565 OS <<
" mtime " << *
U.ModTime;
573 OS.indent(Indent + 2);
582 if (!Submodule->IsInferred || Submodule->IsFramework)
583 Submodule->print(OS, Indent + 2, Dump);
585 for (
unsigned I = 0, N =
Exports.size(); I != N; ++I) {
586 OS.indent(Indent + 2);
589 OS << Restriction->getFullModuleName(
true);
599 OS.indent(Indent + 2);
609 OS.indent(Indent + 2);
610 llvm::errs() <<
"import " << M->getFullModuleName() <<
"\n";
614 for (
unsigned I = 0, N =
DirectUses.size(); I != N; ++I) {
615 OS.indent(Indent + 2);
622 OS.indent(Indent + 2);
628 for (
unsigned I = 0, N =
LinkLibraries.size(); I != N; ++I) {
629 OS.indent(Indent + 2);
639 OS.indent(Indent + 2);
647 for (
unsigned I = 0, N =
Conflicts.size(); I != N; ++I) {
648 OS.indent(Indent + 2);
650 OS <<
Conflicts[I].Other->getFullModuleName(
true);
657 OS.indent(Indent + 2);
660 OS <<
"module * {\n";
662 OS.indent(Indent + 4);
665 OS.indent(Indent + 2);
674 print(llvm::errs(), 0,
true);
681 "setVisible expects a valid import location");
689 Visiting *ExportedBy;
692 std::function<void(Visiting)> VisitModule = [&](Visiting
V) {
694 unsigned ID =
V.M->getVisibilityID();
695 if (ImportLocs.size() <= ID)
696 ImportLocs.resize(ID + 1);
697 else if (ImportLocs[ID].isValid())
700 ImportLocs[ID] = Loc;
705 V.M->getExportedModules(Exports);
706 for (
Module *E : Exports) {
708 if (!E->isUnimportable())
709 VisitModule({E, &
V});
712 for (
auto &
C :
V.M->Conflicts) {
715 for (Visiting *I = &
V; I; I = I->ExportedBy)
716 Path.push_back(I->M);
717 Cb(Path,
C.Other,
C.Message);
721 VisitModule({M,
nullptr});
733 : Signature(M.Signature), ClangModule(&M) {
737 ASTFile =
File->getName();
742 return ClangModule->
Name;
744 return std::string(PCHModuleName);
Defines the clang::FileManager interface and associated types.
Defines the clang::LangOptions interface.
static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature)
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target)
Determine whether a translation unit built using the current language options has the given feature.
static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End, bool AllowStringLiterals=true)
static StringRef getModuleNameFromComponent(const std::pair< std::string, SourceLocation > &IdComponent)
Defines the clang::Module class, which describes a module in the source code.
static bool HasFeature(const Preprocessor &PP, StringRef Feature)
HasFeature - Return true if we recognize and implement the feature specified by the identifier as a s...
Defines the clang::SourceLocation class and associated facilities.
std::string getModuleName() const
ASTSourceDescriptor()=default
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Implements support for file system lookup, file system caching, and directory search management.
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::string ModuleName
The module currently being compiled as specified by -fmodule-name.
bool isCompilingModule() const
Are we compiling a module?
std::string CurrentModule
The name of the current module, of which the main source file is a part.
std::vector< std::string > ModuleFeatures
The names of any features to enable in module 'requires' decls in addition to the hard-coded list in ...
Describes a module or submodule.
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
void addRequirement(StringRef Feature, bool RequiredState, const LangOptions &LangOpts, const TargetInfo &Target)
Add the given feature requirement to the list of features required by this module.
unsigned IsExplicit
Whether this is an explicit submodule.
SmallVector< ExportDecl, 2 > Exports
The set of export declarations.
bool isForBuilding(const LangOptions &LangOpts) const
Determine whether this module can be built in this compilation.
std::variant< std::monostate, FileEntryRef, DirectoryEntryRef > Umbrella
The umbrella header or directory.
Module * findOrInferSubmodule(StringRef Name)
unsigned InferSubmodules
Whether we should infer submodules for this module based on the headers.
Module * findSubmodule(StringRef Name) const
Find the submodule with the given name.
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr Directory
The build directory of this module.
bool directlyUses(const Module *Requested)
Determine whether this module has declared its intention to directly use another module.
std::vector< std::string > ConfigMacros
The set of "configuration macros", which are macros that (intentionally) change how this module is bu...
unsigned IsUnimportable
Whether this module has declared itself unimportable, either because it's missing a requirement from ...
void print(raw_ostream &OS, unsigned Indent=0, bool Dump=false) const
Print the module map for this module to the given stream.
bool isNamedModuleUnit() const
Is this a C++20 named module unit.
SmallVector< UnresolvedHeaderDirective, 1 > MissingHeaders
Headers that are mentioned in the module map file but could not be found on the file system.
Module * Parent
The parent of this module.
void markUnavailable(bool Unimportable)
Mark this module and all of its submodules as unavailable.
SmallVector< UnresolvedHeaderDirective, 1 > UnresolvedHeaders
Headers that are mentioned in the module map file but that we have not yet attempted to resolve to a ...
ModuleKind Kind
The kind of this module.
bool isUnimportable() const
Determine whether this module has been declared unimportable.
bool fullModuleNameIs(ArrayRef< StringRef > nameParts) const
Whether the full name of this module is equal to joining nameParts with "."s.
Module * getPrivateModuleFragment() const
Get the Private Module Fragment (sub-module) for this module, it there is one.
SmallVector< Header, 2 > Headers[5]
The headers that are part of this module.
llvm::SmallSetVector< Module *, 2 > Imports
The set of modules imported by this module, and on which this module depends.
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
std::string Name
The name of this module.
Module * getGlobalModuleFragment() const
Get the Global Module Fragment (sub-module) for this module, it there is one.
llvm::iterator_range< submodule_iterator > submodules()
unsigned IsExternC
Whether this is an 'extern "C"' module (which implicitly puts all headers in it within an 'extern "C"...
unsigned ModuleMapIsPrivate
Whether this module came from a "private" module map, found next to a regular (public) module map.
llvm::SmallVector< LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used.
SmallVector< UnresolvedExportDecl, 2 > UnresolvedExports
The set of export declarations that have yet to be resolved.
std::optional< Header > getUmbrellaHeaderAsWritten() const
Retrieve the umbrella header as written.
SmallVector< Requirement, 2 > Requirements
The set of language features required to use this module.
llvm::SmallSetVector< const Module *, 2 > UndeclaredUses
When NoUndeclaredIncludes is true, the set of modules this module tried to import but didn't because ...
SmallVector< ModuleId, 2 > UnresolvedDirectUses
The set of use declarations that have yet to be resolved.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules.
SmallVector< Module *, 2 > DirectUses
The directly used modules.
unsigned ConfigMacrosExhaustive
Whether the set of configuration macros is exhaustive.
bool isGlobalModule() const
Does this Module scope describe a fragment of the global module within some C++ module.
unsigned InferExportWildcard
Whether, when inferring submodules, the inferr submodules should export all modules they import (e....
void getExportedModules(SmallVectorImpl< Module * > &Exported) const
Appends this module's list of exported modules to Exported.
std::pair< std::string, bool > Requirement
An individual requirement: a feature name and a flag indicating the required state of that feature.
std::vector< UnresolvedConflict > UnresolvedConflicts
The list of conflicts for which the module-id has not yet been resolved.
bool isSubModuleOf(const Module *Other) const
Check if this module is a (possibly transitive) submodule of Other.
ArrayRef< FileEntryRef > getTopHeaders(FileManager &FileMgr)
The top-level headers associated with this module.
OptionalFileEntryRefDegradesToFileEntryPtr getASTFile() const
The serialized AST file for this module, if one was created.
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
llvm::PointerIntPair< Module *, 1, bool > ExportDecl
Describes an exported module.
std::optional< DirectoryName > getUmbrellaDirAsWritten() const
Retrieve the umbrella directory as written.
void dump() const
Dump the contents of this module to the given output stream.
Module * ShadowingModule
A module with the same name that shadows this module.
unsigned IsFramework
Whether this is a framework module.
std::string ExportAsModule
The module through which entities defined in this module will eventually be exposed,...
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
void addTopHeader(FileEntryRef File)
Add a top-level header associated with this module.
unsigned IsAvailable
Whether this module is available in the current translation unit.
unsigned InferExplicitSubmodules
Whether, when inferring submodules, the inferred submodules should be explicit.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
OptionalDirectoryEntryRef getEffectiveUmbrellaDir() const
Get the effective umbrella directory for this module: either the one explicitly written in the module...
std::vector< Conflict > Conflicts
The list of conflicts.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Exposes information about the current target.
void makeTransitiveImportsVisible(Module *M, SourceLocation Loc, VisibleCallback Vis=[](Module *) {}, ConflictCallback Cb=[](ArrayRef< Module * >, Module *, StringRef) {})
Make transitive imports visible for [module.import]/7.
llvm::function_ref< void(ArrayRef< Module * > Path, Module *Conflict, StringRef Message)> ConflictCallback
A callback to call when a module conflict is found.
llvm::function_ref< void(Module *M)> VisibleCallback
A callback to call when a module is made visible (directly or indirectly) by a call to setVisible.
bool isVisible(const Module *M) const
Determine whether a module is visible.
void setVisible(Module *M, SourceLocation Loc, VisibleCallback Vis=[](Module *) {}, ConflictCallback Cb=[](ArrayRef< Module * >, Module *, StringRef) {})
Make a specific module visible.
Defines the clang::TargetInfo interface.
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
@ Result
The result type of a method or function.
@ Other
Other implicit parameter.