aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h')
-rw-r--r--contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h251
1 files changed, 172 insertions, 79 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index a9f2b4d0c6fc..051363b075de 100644
--- a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -1,14 +1,13 @@
//===- ModuleDepCollector.h - Callbacks to collect deps ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
-#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
+#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
+#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
@@ -17,16 +16,21 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Serialization/ASTReader.h"
+#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/raw_ostream.h"
+#include <optional>
#include <string>
#include <unordered_map>
+#include <variant>
namespace clang {
namespace tooling {
namespace dependencies {
+class DependencyActionController;
class DependencyConsumer;
/// Modular dependency that has already been built prior to the dependency scan.
@@ -47,25 +51,61 @@ struct ModuleID {
/// or a header-name for C++20 header units.
std::string ModuleName;
- /// The context hash of a module represents the set of compiler options that
- /// may make one version of a module incompatible with another. This includes
- /// things like language mode, predefined macros, header search paths, etc...
+ /// The context hash of a module represents the compiler options that affect
+ /// the resulting command-line invocation.
+ ///
+ /// Modules with the same name and ContextHash but different invocations could
+ /// cause non-deterministic build results.
///
/// Modules with the same name but a different \c ContextHash should be
/// treated as separate modules for the purpose of a build.
std::string ContextHash;
bool operator==(const ModuleID &Other) const {
- return ModuleName == Other.ModuleName && ContextHash == Other.ContextHash;
+ return std::tie(ModuleName, ContextHash) ==
+ std::tie(Other.ModuleName, Other.ContextHash);
}
-};
-struct ModuleIDHasher {
- std::size_t operator()(const ModuleID &MID) const {
- return llvm::hash_combine(MID.ModuleName, MID.ContextHash);
+ bool operator<(const ModuleID& Other) const {
+ return std::tie(ModuleName, ContextHash) <
+ std::tie(Other.ModuleName, Other.ContextHash);
}
};
+/// P1689ModuleInfo - Represents the needed information of standard C++20
+/// modules for P1689 format.
+struct P1689ModuleInfo {
+ /// The name of the module. This may include `:` for partitions.
+ std::string ModuleName;
+
+ /// Optional. The source path to the module.
+ std::string SourcePath;
+
+ /// If this module is a standard c++ interface unit.
+ bool IsStdCXXModuleInterface = true;
+
+ enum class ModuleType {
+ NamedCXXModule
+ // To be supported
+ // AngleHeaderUnit,
+ // QuoteHeaderUnit
+ };
+ ModuleType Type = ModuleType::NamedCXXModule;
+};
+
+/// An output from a module compilation, such as the path of the module file.
+enum class ModuleOutputKind {
+ /// The module file (.pcm). Required.
+ ModuleFile,
+ /// The path of the dependency file (.d), if any.
+ DependencyFile,
+ /// The null-separated list of names to use as the targets in the dependency
+ /// file, if any. Defaults to the value of \c ModuleFile, as in the driver.
+ DependencyTargets,
+ /// The path of the serialized diagnostic file (.dia), if any.
+ DiagnosticSerializationFile,
+};
+
struct ModuleDeps {
/// The identifier of the module.
ModuleID ID;
@@ -79,13 +119,14 @@ struct ModuleDeps {
/// additionally appear in \c FileDeps as a dependency.
std::string ClangModuleMapFile;
- /// The path to where an implicit build would put the PCM for this module.
- std::string ImplicitModulePCMPath;
-
/// A collection of absolute paths to files that this module directly depends
/// on, not including transitive dependencies.
llvm::StringSet<> FileDeps;
+ /// A collection of absolute paths to module map files that this module needs
+ /// to know about. The ordering is significant.
+ std::vector<std::string> ModuleMapFileDeps;
+
/// A collection of prebuilt modular dependencies this module directly depends
/// on, not including transitive dependencies.
std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
@@ -97,43 +138,17 @@ struct ModuleDeps {
/// determined that the differences are benign for this compilation.
std::vector<ModuleID> ClangModuleDeps;
- // Used to track which modules that were discovered were directly imported by
- // the primary TU.
- bool ImportedByMainFile = false;
+ /// Get (or compute) the compiler invocation that can be used to build this
+ /// module. Does not include argv[0].
+ const std::vector<std::string> &getBuildArguments();
- /// Compiler invocation that can be used to build this module (without paths).
- CompilerInvocation Invocation;
+private:
+ friend class ModuleDepCollectorPP;
- /// Gets the canonical command line suitable for passing to clang.
- ///
- /// \param LookupPCMPath This function is called to fill in "-fmodule-file="
- /// arguments and the "-o" argument. It needs to return
- /// a path for where the PCM for the given module is to
- /// be located.
- /// \param LookupModuleDeps This function is called to collect the full
- /// transitive set of dependencies for this
- /// compilation and fill in "-fmodule-map-file="
- /// arguments.
- std::vector<std::string> getCanonicalCommandLine(
- std::function<StringRef(ModuleID)> LookupPCMPath,
- std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const;
-
- /// Gets the canonical command line suitable for passing to clang, excluding
- /// arguments containing modules-related paths: "-fmodule-file=", "-o",
- /// "-fmodule-map-file=".
- std::vector<std::string> getCanonicalCommandLineWithoutModulePaths() const;
+ std::variant<std::monostate, CowCompilerInvocation, std::vector<std::string>>
+ BuildInfo;
};
-namespace detail {
-/// Collect the paths of PCM and module map files for the modules in \c Modules
-/// transitively.
-void collectPCMAndModuleMapPaths(
- llvm::ArrayRef<ModuleID> Modules,
- std::function<StringRef(ModuleID)> LookupPCMPath,
- std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps,
- std::vector<std::string> &PCMPaths, std::vector<std::string> &ModMapPaths);
-} // namespace detail
-
class ModuleDepCollector;
/// Callback that records textual includes and direct modular includes/imports
@@ -142,17 +157,16 @@ class ModuleDepCollector;
/// \c DependencyConsumer of the parent \c ModuleDepCollector.
class ModuleDepCollectorPP final : public PPCallbacks {
public:
- ModuleDepCollectorPP(CompilerInstance &I, ModuleDepCollector &MDC)
- : Instance(I), MDC(MDC) {}
+ ModuleDepCollectorPP(ModuleDepCollector &MDC) : MDC(MDC) {}
- void FileChanged(SourceLocation Loc, FileChangeReason Reason,
- SrcMgr::CharacteristicKind FileType,
- FileID PrevFID) override;
+ void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType, FileID PrevFID,
+ SourceLocation Loc) override;
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
- CharSourceRange FilenameRange, const FileEntry *File,
- StringRef SearchPath, StringRef RelativePath,
- const Module *Imported,
+ CharSourceRange FilenameRange,
+ OptionalFileEntryRef File, StringRef SearchPath,
+ StringRef RelativePath, const Module *Imported,
SrcMgr::CharacteristicKind FileType) override;
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
const Module *Imported) override;
@@ -160,29 +174,35 @@ public:
void EndOfMainFile() override;
private:
- /// The compiler instance for the current translation unit.
- CompilerInstance &Instance;
/// The parent dependency collector.
ModuleDepCollector &MDC;
- /// Working set of direct modular dependencies.
- llvm::DenseSet<const Module *> DirectModularDeps;
- /// Working set of direct modular dependencies that have already been built.
- llvm::DenseSet<const Module *> DirectPrebuiltModularDeps;
void handleImport(const Module *Imported);
/// Adds direct modular dependencies that have already been built to the
/// ModuleDeps instance.
- void addDirectPrebuiltModuleDeps(const Module *M, ModuleDeps &MD);
+ void
+ addAllSubmodulePrebuiltDeps(const Module *M, ModuleDeps &MD,
+ llvm::DenseSet<const Module *> &SeenSubmodules);
+ void addModulePrebuiltDeps(const Module *M, ModuleDeps &MD,
+ llvm::DenseSet<const Module *> &SeenSubmodules);
/// Traverses the previously collected direct modular dependencies to discover
/// transitive modular dependencies and fills the parent \c ModuleDepCollector
/// with both.
- ModuleID handleTopLevelModule(const Module *M);
+ /// Returns the ID or nothing if the dependency is spurious and is ignored.
+ std::optional<ModuleID> handleTopLevelModule(const Module *M);
void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
llvm::DenseSet<const Module *> &AddedModules);
void addModuleDep(const Module *M, ModuleDeps &MD,
llvm::DenseSet<const Module *> &AddedModules);
+
+ /// Traverses the affecting modules and updates \c MD with references to the
+ /// parent \c ModuleDepCollector info.
+ void addAllAffectingClangModules(const Module *M, ModuleDeps &MD,
+ llvm::DenseSet<const Module *> &AddedModules);
+ void addAffectingClangModule(const Module *M, ModuleDeps &MD,
+ llvm::DenseSet<const Module *> &AddedModules);
};
/// Collects modular and non-modular dependencies of the main file by attaching
@@ -190,19 +210,28 @@ private:
class ModuleDepCollector final : public DependencyCollector {
public:
ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
- CompilerInstance &I, DependencyConsumer &C,
- CompilerInvocation &&OriginalCI);
+ CompilerInstance &ScanInstance, DependencyConsumer &C,
+ DependencyActionController &Controller,
+ CompilerInvocation OriginalCI,
+ ScanningOptimizations OptimizeArgs, bool EagerLoadModules,
+ bool IsStdModuleP1689Format);
void attachToPreprocessor(Preprocessor &PP) override;
void attachToASTReader(ASTReader &R) override;
+ /// Apply any changes implied by the discovered dependencies to the given
+ /// invocation, (e.g. disable implicit modules, add explicit module paths).
+ void applyDiscoveredDependencies(CompilerInvocation &CI);
+
private:
friend ModuleDepCollectorPP;
- /// The compiler instance for the current translation unit.
- CompilerInstance &Instance;
+ /// The compiler instance for scanning the current translation unit.
+ CompilerInstance &ScanInstance;
/// The consumer of collected dependency information.
DependencyConsumer &Consumer;
+ /// Callbacks for computing dependency information.
+ DependencyActionController &Controller;
/// Path to the main source file.
std::string MainFile;
/// Hash identifying the compilation conditions of the current TU.
@@ -211,24 +240,88 @@ private:
/// textually included header files.
std::vector<std::string> FileDeps;
/// Direct and transitive modular dependencies of the main source file.
- std::unordered_map<const Module *, ModuleDeps> ModularDeps;
+ llvm::MapVector<const Module *, std::unique_ptr<ModuleDeps>> ModularDeps;
+ /// Secondary mapping for \c ModularDeps allowing lookup by ModuleID without
+ /// a preprocessor. Storage owned by \c ModularDeps.
+ llvm::DenseMap<ModuleID, ModuleDeps *> ModuleDepsByID;
+ /// Direct modular dependencies that have already been built.
+ llvm::MapVector<const Module *, PrebuiltModuleDep> DirectPrebuiltModularDeps;
+ /// Working set of direct modular dependencies.
+ llvm::SetVector<const Module *> DirectModularDeps;
/// Options that control the dependency output generation.
std::unique_ptr<DependencyOutputOptions> Opts;
- /// The original Clang invocation passed to dependency scanner.
- CompilerInvocation OriginalInvocation;
+ /// A Clang invocation that's based on the original TU invocation and that has
+ /// been partially transformed into one that can perform explicit build of
+ /// a discovered modular dependency. Note that this still needs to be adjusted
+ /// for each individual module.
+ CowCompilerInvocation CommonInvocation;
+ /// Whether to optimize the modules' command-line arguments.
+ ScanningOptimizations OptimizeArgs;
+ /// Whether to set up command-lines to load PCM files eagerly.
+ bool EagerLoadModules;
+ /// If we're generating dependency output in P1689 format
+ /// for standard C++ modules.
+ bool IsStdModuleP1689Format;
+
+ std::optional<P1689ModuleInfo> ProvidedStdCXXModule;
+ std::vector<P1689ModuleInfo> RequiredStdCXXModules;
/// Checks whether the module is known as being prebuilt.
bool isPrebuiltModule(const Module *M);
- /// Constructs a CompilerInvocation that can be used to build the given
- /// module, excluding paths to discovered modular dependencies that are yet to
- /// be built.
- CompilerInvocation
- makeInvocationForModuleBuildWithoutPaths(const ModuleDeps &Deps) const;
+ /// Adds \p Path to \c FileDeps, making it absolute if necessary.
+ void addFileDep(StringRef Path);
+ /// Adds \p Path to \c MD.FileDeps, making it absolute if necessary.
+ void addFileDep(ModuleDeps &MD, StringRef Path);
+
+ /// Get a Clang invocation adjusted to build the given modular dependency.
+ /// This excludes paths that are yet-to-be-provided by the build system.
+ CowCompilerInvocation getInvocationAdjustedForModuleBuildWithoutOutputs(
+ const ModuleDeps &Deps,
+ llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
+
+ /// Collect module map files for given modules.
+ llvm::DenseSet<const FileEntry *>
+ collectModuleMapFiles(ArrayRef<ModuleID> ClangModuleDeps) const;
+
+ /// Add module map files to the invocation, if needed.
+ void addModuleMapFiles(CompilerInvocation &CI,
+ ArrayRef<ModuleID> ClangModuleDeps) const;
+ /// Add module files (pcm) to the invocation, if needed.
+ void addModuleFiles(CompilerInvocation &CI,
+ ArrayRef<ModuleID> ClangModuleDeps) const;
+ void addModuleFiles(CowCompilerInvocation &CI,
+ ArrayRef<ModuleID> ClangModuleDeps) const;
+
+ /// Add paths that require looking up outputs to the given dependencies.
+ void addOutputPaths(CowCompilerInvocation &CI, ModuleDeps &Deps);
+
+ /// Compute the context hash for \p Deps, and create the mapping
+ /// \c ModuleDepsByID[Deps.ID] = &Deps.
+ void associateWithContextHash(const CowCompilerInvocation &CI,
+ ModuleDeps &Deps);
};
} // end namespace dependencies
} // end namespace tooling
} // end namespace clang
-#endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
+namespace llvm {
+inline hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID) {
+ return hash_combine(ID.ModuleName, ID.ContextHash);
+}
+
+template <> struct DenseMapInfo<clang::tooling::dependencies::ModuleID> {
+ using ModuleID = clang::tooling::dependencies::ModuleID;
+ static inline ModuleID getEmptyKey() { return ModuleID{"", ""}; }
+ static inline ModuleID getTombstoneKey() {
+ return ModuleID{"~", "~"}; // ~ is not a valid module name or context hash
+ }
+ static unsigned getHashValue(const ModuleID &ID) { return hash_value(ID); }
+ static bool isEqual(const ModuleID &LHS, const ModuleID &RHS) {
+ return LHS == RHS;
+ }
+};
+} // namespace llvm
+
+#endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H