Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
Line
Count
Source
1
//===- ModuleDepCollector.h - Callbacks to collect deps ---------*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
11
#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
12
13
#include "clang/Basic/LLVM.h"
14
#include "clang/Basic/SourceManager.h"
15
#include "clang/Frontend/Utils.h"
16
#include "clang/Lex/HeaderSearch.h"
17
#include "clang/Lex/PPCallbacks.h"
18
#include "clang/Serialization/ASTReader.h"
19
#include "llvm/ADT/DenseMap.h"
20
#include "llvm/ADT/StringSet.h"
21
#include "llvm/Support/raw_ostream.h"
22
23
#include <string>
24
25
namespace clang {
26
namespace tooling {
27
namespace dependencies {
28
29
class DependencyConsumer;
30
31
/// This is used to refer to a specific module.
32
///
33
/// See \c ModuleDeps for details about what these members mean.
34
struct ClangModuleDep {
35
  std::string ModuleName;
36
  std::string ContextHash;
37
};
38
39
struct ModuleDeps {
40
  /// The name of the module. This may include `:` for C++20 module partitons,
41
  /// or a header-name for C++20 header units.
42
  std::string ModuleName;
43
44
  /// The context hash of a module represents the set of compiler options that
45
  /// may make one version of a module incompatible with another. This includes
46
  /// things like language mode, predefined macros, header search paths, etc...
47
  ///
48
  /// Modules with the same name but a different \c ContextHash should be
49
  /// treated as separate modules for the purpose of a build.
50
  std::string ContextHash;
51
52
  /// The path to the modulemap file which defines this module.
53
  ///
54
  /// This can be used to explicitly build this module. This file will
55
  /// additionally appear in \c FileDeps as a dependency.
56
  std::string ClangModuleMapFile;
57
58
  /// The path to where an implicit build would put the PCM for this module.
59
  std::string ImplicitModulePCMPath;
60
61
  /// A collection of absolute paths to files that this module directly depends
62
  /// on, not including transitive dependencies.
63
  llvm::StringSet<> FileDeps;
64
65
  /// A list of modules this module directly depends on, not including
66
  /// transitive dependencies.
67
  ///
68
  /// This may include modules with a different context hash when it can be
69
  /// determined that the differences are benign for this compilation.
70
  std::vector<ClangModuleDep> ClangModuleDeps;
71
72
  /// A partial command line that can be used to build this module.
73
  ///
74
  /// Call \c getFullCommandLine() to get a command line suitable for passing to
75
  /// clang.
76
  std::vector<std::string> NonPathCommandLine;
77
78
  // Used to track which modules that were discovered were directly imported by
79
  // the primary TU.
80
  bool ImportedByMainFile = false;
81
82
  /// Gets the full command line suitable for passing to clang.
83
  ///
84
  /// \param LookupPCMPath this function is called to fill in `-fmodule-file=`
85
  ///                      flags and for the `-o` flag. It needs to return a
86
  ///                      path for where the PCM for the given module is to
87
  ///                      be located.
88
  /// \param LookupModuleDeps this fucntion is called to collect the full
89
  ///                         transitive set of dependencies for this
90
  ///                         compilation.
91
  std::vector<std::string> getFullCommandLine(
92
      std::function<StringRef(ClangModuleDep)> LookupPCMPath,
93
      std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps) const;
94
};
95
96
namespace detail {
97
/// Append the `-fmodule-file=` and `-fmodule-map-file=` arguments for the
98
/// modules in \c Modules transitively, along with other needed arguments to
99
/// use explicitly built modules.
100
void appendCommonModuleArguments(
101
    llvm::ArrayRef<ClangModuleDep> Modules,
102
    std::function<StringRef(ClangModuleDep)> LookupPCMPath,
103
    std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps,
104
    std::vector<std::string> &Result);
105
} // namespace detail
106
107
class ModuleDepCollector;
108
109
class ModuleDepCollectorPP final : public PPCallbacks {
110
public:
111
  ModuleDepCollectorPP(CompilerInstance &I, ModuleDepCollector &MDC)
112
4
      : Instance(I), MDC(MDC) {}
113
114
  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
115
                   SrcMgr::CharacteristicKind FileType,
116
                   FileID PrevFID) override;
117
  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
118
                          StringRef FileName, bool IsAngled,
119
                          CharSourceRange FilenameRange, const FileEntry *File,
120
                          StringRef SearchPath, StringRef RelativePath,
121
                          const Module *Imported,
122
                          SrcMgr::CharacteristicKind FileType) override;
123
  void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
124
                    const Module *Imported) override;
125
126
  void EndOfMainFile() override;
127
128
private:
129
  CompilerInstance &Instance;
130
  ModuleDepCollector &MDC;
131
  llvm::DenseSet<const Module *> DirectDeps;
132
133
  void handleImport(const Module *Imported);
134
  void handleTopLevelModule(const Module *M);
135
  void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
136
                           llvm::DenseSet<const Module *> &AddedModules);
137
  void addModuleDep(const Module *M, ModuleDeps &MD,
138
                    llvm::DenseSet<const Module *> &AddedModules);
139
};
140
141
class ModuleDepCollector final : public DependencyCollector {
142
public:
143
  ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
144
                     CompilerInstance &I, DependencyConsumer &C);
145
146
  void attachToPreprocessor(Preprocessor &PP) override;
147
  void attachToASTReader(ASTReader &R) override;
148
149
private:
150
  friend ModuleDepCollectorPP;
151
152
  CompilerInstance &Instance;
153
  DependencyConsumer &Consumer;
154
  std::string MainFile;
155
  std::string ContextHash;
156
  std::vector<std::string> MainDeps;
157
  std::unordered_map<std::string, ModuleDeps> Deps;
158
  std::unique_ptr<DependencyOutputOptions> Opts;
159
};
160
161
} // end namespace dependencies
162
} // end namespace tooling
163
} // end namespace clang
164
165
#endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H