aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h')
-rw-r--r--contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h187
1 files changed, 112 insertions, 75 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h
index 41f85a1f572d..867cb6eab42f 100644
--- a/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h
+++ b/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h
@@ -20,8 +20,8 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -30,6 +30,7 @@
#include "llvm/ADT/Twine.h"
#include <ctime>
#include <memory>
+#include <optional>
#include <string>
#include <utility>
@@ -56,8 +57,8 @@ public:
/// contents.
/// \param File The file itself.
/// \param IsSystem Whether this is a module map from a system include path.
- virtual void moduleMapFileRead(SourceLocation FileStart,
- const FileEntry &File, bool IsSystem) {}
+ virtual void moduleMapFileRead(SourceLocation FileStart, FileEntryRef File,
+ bool IsSystem) {}
/// Called when a header is added during module map parsing.
///
@@ -66,10 +67,8 @@ public:
/// Called when an umbrella header is added during module map parsing.
///
- /// \param FileMgr FileManager instance
/// \param Header The umbrella header to collect.
- virtual void moduleMapAddUmbrellaHeader(FileManager *FileMgr,
- const FileEntry *Header) {}
+ virtual void moduleMapAddUmbrellaHeader(FileEntryRef Header) {}
};
class ModuleMap {
@@ -83,7 +82,7 @@ class ModuleMap {
/// The directory used for Clang-supplied, builtin include headers,
/// such as "stdint.h".
- const DirectoryEntry *BuiltinIncludeDir = nullptr;
+ OptionalDirectoryEntryRef BuiltinIncludeDir;
/// Language options used to parse the module map itself.
///
@@ -136,9 +135,11 @@ public:
/// should be textually included.
TextualHeader = 0x2,
+ /// This header is explicitly excluded from the module.
+ ExcludedHeader = 0x4,
+
// Caution: Adding an enumerator needs other changes.
// Adjust the number of bits for KnownHeader::Storage.
- // Adjust the bitfield HeaderFileInfo::HeaderRole size.
// Adjust the HeaderFileInfoTrait::ReadData streaming.
// Adjust the HeaderFileInfoTrait::EmitData streaming.
// Adjust ModuleMap::addHeader.
@@ -150,10 +151,13 @@ public:
/// Convert a header role to a kind.
static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role);
+ /// Check if the header with the given role is a modular one.
+ static bool isModular(ModuleHeaderRole Role);
+
/// A header that is known to reside within a given module,
/// whether it was included or excluded.
class KnownHeader {
- llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
+ llvm::PointerIntPair<Module *, 3, ModuleHeaderRole> Storage;
public:
KnownHeader() : Storage(nullptr, NormalHeader) {}
@@ -174,7 +178,7 @@ public:
/// Whether this header is available in the module.
bool isAvailable() const {
- return getModule()->isAvailable();
+ return getRole() != ExcludedHeader && getModule()->isAvailable();
}
/// Whether this header is accessible from the specified module.
@@ -190,13 +194,12 @@ public:
}
};
- using AdditionalModMapsSet = llvm::SmallPtrSet<const FileEntry *, 1>;
+ using AdditionalModMapsSet = llvm::DenseSet<FileEntryRef>;
private:
friend class ModuleMapParser;
- using HeadersMap =
- llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>;
+ using HeadersMap = llvm::DenseMap<FileEntryRef, SmallVector<KnownHeader, 1>>;
/// Mapping from each header to the module that owns the contents of
/// that header.
@@ -229,16 +232,20 @@ private:
/// The set of attributes that can be attached to a module.
struct Attributes {
/// Whether this is a system module.
+ LLVM_PREFERRED_TYPE(bool)
unsigned IsSystem : 1;
/// Whether this is an extern "C" module.
+ LLVM_PREFERRED_TYPE(bool)
unsigned IsExternC : 1;
/// Whether this is an exhaustive set of configuration macros.
+ LLVM_PREFERRED_TYPE(bool)
unsigned IsExhaustive : 1;
/// Whether files in this module can only include non-modular headers
/// and headers from used modules.
+ LLVM_PREFERRED_TYPE(bool)
unsigned NoUndeclaredIncludes : 1;
Attributes()
@@ -249,14 +256,15 @@ private:
/// A directory for which framework modules can be inferred.
struct InferredDirectory {
/// Whether to infer modules from this directory.
+ LLVM_PREFERRED_TYPE(bool)
unsigned InferModules : 1;
/// The attributes to use for inferred modules.
Attributes Attrs;
/// If \c InferModules is non-zero, the module map file that allowed
- /// inferred modules. Otherwise, nullptr.
- const FileEntry *ModuleMapFile;
+ /// inferred modules. Otherwise, nullopt.
+ OptionalFileEntryRef ModuleMapFile;
/// The names of modules that cannot be inferred within this
/// directory.
@@ -271,7 +279,8 @@ private:
/// A mapping from an inferred module to the module map that allowed the
/// inference.
- llvm::DenseMap<const Module *, const FileEntry *> InferredModuleAllowedBy;
+ // FIXME: Consider making the values non-optional.
+ llvm::DenseMap<const Module *, OptionalFileEntryRef> InferredModuleAllowedBy;
llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps;
@@ -328,7 +337,7 @@ private:
/// \param NeedsFramework If M is not a framework but a missing header would
/// be found in case M was, set it to true. False otherwise.
/// \return The resolved file, if any.
- Optional<FileEntryRef>
+ OptionalFileEntryRef
findHeader(Module *M, const Module::UnresolvedHeaderDirective &Header,
SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework);
@@ -352,7 +361,7 @@ private:
/// If \p File represents a builtin header within Clang's builtin include
/// directory, this also loads all of the module maps to see if it will get
/// associated with a specific module (e.g. in /usr/include).
- HeadersMap::iterator findKnownHeader(const FileEntry *File);
+ HeadersMap::iterator findKnownHeader(FileEntryRef File);
/// Searches for a module whose umbrella directory contains \p File.
///
@@ -360,22 +369,22 @@ private:
///
/// \param IntermediateDirs On success, contains the set of directories
/// searched before finding \p File.
- KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
- SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
+ KnownHeader findHeaderInUmbrellaDirs(
+ FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs);
/// Given that \p File is not in the Headers map, look it up within
/// umbrella directories and find or create a module for it.
- KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File);
+ KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File);
/// A convenience method to determine if \p File is (possibly nested)
/// in an umbrella directory.
- bool isHeaderInUmbrellaDirs(const FileEntry *File) {
- SmallVector<const DirectoryEntry *, 2> IntermediateDirs;
+ bool isHeaderInUmbrellaDirs(FileEntryRef File) {
+ SmallVector<DirectoryEntryRef, 2> IntermediateDirs;
return static_cast<bool>(findHeaderInUmbrellaDirs(File, IntermediateDirs));
}
- Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
- Attributes Attrs, Module *Parent);
+ Module *inferFrameworkModule(DirectoryEntryRef FrameworkDir, Attributes Attrs,
+ Module *Parent);
public:
/// Construct a new module map.
@@ -399,20 +408,18 @@ public:
/// Set the target information.
void setTarget(const TargetInfo &Target);
- /// Set the directory that contains Clang-supplied include
- /// files, such as our stdarg.h or tgmath.h.
- void setBuiltinIncludeDir(const DirectoryEntry *Dir) {
- BuiltinIncludeDir = Dir;
- }
+ /// Set the directory that contains Clang-supplied include files, such as our
+ /// stdarg.h or tgmath.h.
+ void setBuiltinIncludeDir(DirectoryEntryRef Dir) { BuiltinIncludeDir = Dir; }
/// Get the directory that contains Clang-supplied include files.
- const DirectoryEntry *getBuiltinDir() const {
- return BuiltinIncludeDir;
- }
+ OptionalDirectoryEntryRef getBuiltinDir() const { return BuiltinIncludeDir; }
/// Is this a compiler builtin header?
- static bool isBuiltinHeader(StringRef FileName);
- bool isBuiltinHeader(const FileEntry *File);
+ bool isBuiltinHeader(FileEntryRef File);
+
+ bool shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
+ Module *Module) const;
/// Add a module map callback.
void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) {
@@ -433,8 +440,8 @@ public:
/// \returns The module KnownHeader, which provides the module that owns the
/// given header file. The KnownHeader is default constructed to indicate
/// that no module owns this header file.
- KnownHeader findModuleForHeader(const FileEntry *File,
- bool AllowTextual = false);
+ KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual = false,
+ bool AllowExcluded = false);
/// Retrieve all the modules that contain the given header file. Note that
/// this does not implicitly load module maps, except for builtin headers,
@@ -443,12 +450,11 @@ public:
///
/// Typically, \ref findModuleForHeader should be used instead, as it picks
/// the preferred module for the header.
- ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File);
+ ArrayRef<KnownHeader> findAllModulesForHeader(FileEntryRef File);
/// Like \ref findAllModulesForHeader, but do not attempt to infer module
/// ownership from umbrella headers if we've not already done so.
- ArrayRef<KnownHeader>
- findResolvedModulesForHeader(const FileEntry *File) const;
+ ArrayRef<KnownHeader> findResolvedModulesForHeader(FileEntryRef File) const;
/// Resolve all lazy header directives for the specified file.
///
@@ -456,8 +462,11 @@ public:
/// is effectively internal, but is exposed so HeaderSearch can call it.
void resolveHeaderDirectives(const FileEntry *File) const;
- /// Resolve all lazy header directives for the specified module.
- void resolveHeaderDirectives(Module *Mod) const;
+ /// Resolve lazy header directives for the specified module. If File is
+ /// provided, only headers with same size and modtime are resolved. If File
+ /// is not set, all headers are resolved.
+ void resolveHeaderDirectives(Module *Mod,
+ std::optional<const FileEntry *> File) const;
/// Reports errors if a module must not include a specific file.
///
@@ -476,15 +485,15 @@ public:
void diagnoseHeaderInclusion(Module *RequestingModule,
bool RequestingModuleIsModuleInterface,
SourceLocation FilenameLoc, StringRef Filename,
- const FileEntry *File);
+ FileEntryRef File);
/// Determine whether the given header is part of a module
/// marked 'unavailable'.
- bool isHeaderInUnavailableModule(const FileEntry *Header) const;
+ bool isHeaderInUnavailableModule(FileEntryRef Header) const;
/// Determine whether the given header is unavailable as part
/// of the specified module.
- bool isHeaderUnavailableInModule(const FileEntry *Header,
+ bool isHeaderUnavailableInModule(FileEntryRef Header,
const Module *RequestingModule) const;
/// Retrieve a module with the given name.
@@ -538,13 +547,23 @@ public:
///
/// We model the global module fragment as a submodule of the module
/// interface unit. Unfortunately, we can't create the module interface
- /// unit's Module until later, because we don't know what it will be called.
- Module *createGlobalModuleFragmentForModuleUnit(SourceLocation Loc);
+ /// unit's Module until later, because we don't know what it will be called
+ /// usually. See C++20 [module.unit]/7.2 for the case we could know its
+ /// parent.
+ Module *createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
+ Module *Parent = nullptr);
+ Module *createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
+ Module *Parent);
/// Create a global module fragment for a C++ module interface unit.
Module *createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
SourceLocation Loc);
+ /// Create a new C++ module with the specified kind, and reparent any pending
+ /// global module fragment(s) to it.
+ Module *createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
+ Module::ModuleKind Kind);
+
/// Create a new module for a C++ module interface unit.
/// The module must not already exist, and will be configured for the current
/// compilation.
@@ -552,16 +571,23 @@ public:
/// Note that this also sets the current module to the newly-created module.
///
/// \returns The newly-created module.
- Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
- Module *GlobalModule);
+ Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
- /// Create a header module from the specified list of headers.
- Module *createHeaderModule(StringRef Name, ArrayRef<Module::Header> Headers);
+ /// Create a new module for a C++ module implementation unit.
+ /// The interface module for this implementation (implicitly imported) must
+ /// exist and be loaded and present in the modules map.
+ ///
+ /// \returns The newly-created module.
+ Module *createModuleForImplementationUnit(SourceLocation Loc, StringRef Name);
+
+ /// Create a C++20 header unit.
+ Module *createHeaderUnit(SourceLocation Loc, StringRef Name,
+ Module::Header H);
/// Infer the contents of a framework module map from the given
/// framework directory.
- Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
- bool IsSystem, Module *Parent);
+ Module *inferFrameworkModule(DirectoryEntryRef FrameworkDir, bool IsSystem,
+ Module *Parent);
/// Create a new top-level module that is shadowed by
/// \p ShadowingModule.
@@ -581,6 +607,12 @@ public:
return ModuleScopeIDs[ExistingModule] < CurrentModuleScopeID;
}
+ /// Check whether a framework module can be inferred in the given directory.
+ bool canInferFrameworkModule(const DirectoryEntry *Dir) const {
+ auto It = InferredDirectories.find(Dir);
+ return It != InferredDirectories.end() && It->getSecond().InferModules;
+ }
+
/// Retrieve the module map file containing the definition of the given
/// module.
///
@@ -588,7 +620,7 @@ public:
///
/// \returns The file entry for the module map file containing the given
/// module, or nullptr if the module definition was inferred.
- const FileEntry *getContainingModuleMapFile(const Module *Module) const;
+ OptionalFileEntryRef getContainingModuleMapFile(const Module *Module) const;
/// Get the module map file that (along with the module name) uniquely
/// identifies this module.
@@ -599,9 +631,18 @@ public:
/// of inferred modules, returns the module map that allowed the inference
/// (e.g. contained 'module *'). Otherwise, returns
/// getContainingModuleMapFile().
- const FileEntry *getModuleMapFileForUniquing(const Module *M) const;
+ OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const;
- void setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap);
+ void setInferredModuleAllowedBy(Module *M, OptionalFileEntryRef ModMap);
+
+ /// Canonicalize \p Path in a manner suitable for a module map file. In
+ /// particular, this canonicalizes the parent directory separately from the
+ /// filename so that it does not affect header resolution relative to the
+ /// modulemap.
+ ///
+ /// \returns an error code if any filesystem operations failed. In this case
+ /// \p Path is not modified.
+ std::error_code canonicalizeModuleMapPath(SmallVectorImpl<char> &Path);
/// Get any module map files other than getModuleMapFileForUniquing(M)
/// that define submodules of a top-level module \p M. This is cheaper than
@@ -614,7 +655,7 @@ public:
return &I->second;
}
- void addAdditionalModuleMapFile(const Module *M, const FileEntry *ModuleMap);
+ void addAdditionalModuleMapFile(const Module *M, FileEntryRef ModuleMap);
/// Resolve all of the unresolved exports in the given module.
///
@@ -646,26 +687,22 @@ public:
/// false otherwise.
bool resolveConflicts(Module *Mod, bool Complain);
- /// Sets the umbrella header of the given module to the given
- /// header.
- void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
- const Twine &NameAsWritten,
- const Twine &PathRelativeToRootModuleDirectory);
+ /// Sets the umbrella header of the given module to the given header.
+ void
+ setUmbrellaHeaderAsWritten(Module *Mod, FileEntryRef UmbrellaHeader,
+ const Twine &NameAsWritten,
+ const Twine &PathRelativeToRootModuleDirectory);
- /// Sets the umbrella directory of the given module to the given
- /// directory.
- void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
- const Twine &NameAsWritten,
- const Twine &PathRelativeToRootModuleDirectory);
+ /// Sets the umbrella directory of the given module to the given directory.
+ void setUmbrellaDirAsWritten(Module *Mod, DirectoryEntryRef UmbrellaDir,
+ const Twine &NameAsWritten,
+ const Twine &PathRelativeToRootModuleDirectory);
/// Adds this header to the given module.
/// \param Role The role of the header wrt the module.
void addHeader(Module *Mod, Module::Header Header,
ModuleHeaderRole Role, bool Imported = false);
- /// Marks this header as being excluded from the given module.
- void excludeHeader(Module *Mod, Module::Header Header);
-
/// Parse the given module map file, and record any modules we
/// encounter.
///
@@ -686,9 +723,9 @@ public:
/// that caused us to load this module map file, if any.
///
/// \returns true if an error occurred, false otherwise.
- bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
- const DirectoryEntry *HomeDir,
- FileID ID = FileID(), unsigned *Offset = nullptr,
+ bool parseModuleMapFile(FileEntryRef File, bool IsSystem,
+ DirectoryEntryRef HomeDir, FileID ID = FileID(),
+ unsigned *Offset = nullptr,
SourceLocation ExternModuleLoc = SourceLocation());
/// Dump the contents of the module map, for debugging purposes.
@@ -708,10 +745,10 @@ public:
}
/// Return a cached module load.
- llvm::Optional<Module *> getCachedModuleLoad(const IdentifierInfo &II) {
+ std::optional<Module *> getCachedModuleLoad(const IdentifierInfo &II) {
auto I = CachedModuleLoads.find(&II);
if (I == CachedModuleLoads.end())
- return None;
+ return std::nullopt;
return I->second;
}
};