Coverage Report

Created: 2021-09-21 08:58

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- DependencyScanningTool.cpp - clang-scan-deps service ---------------===//
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
#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h"
10
#include "clang/Frontend/Utils.h"
11
12
namespace clang{
13
namespace tooling{
14
namespace dependencies{
15
16
std::vector<std::string> FullDependencies::getAdditionalArgs(
17
    std::function<StringRef(ModuleID)> LookupPCMPath,
18
18
    std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
19
18
  std::vector<std::string> Ret = getAdditionalArgsWithoutModulePaths();
20
21
18
  std::vector<std::string> PCMPaths;
22
18
  std::vector<std::string> ModMapPaths;
23
18
  dependencies::detail::collectPCMAndModuleMapPaths(
24
18
      ClangModuleDeps, LookupPCMPath, LookupModuleDeps, PCMPaths, ModMapPaths);
25
18
  for (const std::string &PCMPath : PCMPaths)
26
23
    Ret.push_back("-fmodule-file=" + PCMPath);
27
18
  for (const std::string &ModMapPath : ModMapPaths)
28
23
    Ret.push_back("-fmodule-map-file=" + ModMapPath);
29
30
18
  return Ret;
31
18
}
32
33
std::vector<std::string>
34
33
FullDependencies::getAdditionalArgsWithoutModulePaths() const {
35
33
  std::vector<std::string> Args{
36
33
      "-fno-implicit-modules",
37
33
      "-fno-implicit-module-maps",
38
33
  };
39
40
33
  for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps) {
41
1
    Args.push_back("-fmodule-file=" + PMD.ModuleName + "=" + PMD.PCMFile);
42
1
    Args.push_back("-fmodule-map-file=" + PMD.ModuleMapFile);
43
1
  }
44
45
33
  return Args;
46
33
}
47
48
DependencyScanningTool::DependencyScanningTool(
49
    DependencyScanningService &Service)
50
248
    : Worker(Service) {}
51
52
llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
53
    const std::vector<std::string> &CommandLine, StringRef CWD,
54
132
    llvm::Optional<StringRef> ModuleName) {
55
  /// Prints out all of the gathered dependencies into a string.
56
132
  class MakeDependencyPrinterConsumer : public DependencyConsumer {
57
132
  public:
58
132
    void
59
132
    handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
60
130
      this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
61
130
    }
62
63
363
    void handleFileDependency(StringRef File) override {
64
363
      Dependencies.push_back(std::string(File));
65
363
    }
66
67
132
    void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
68
      // Same as `handleModuleDependency`.
69
0
    }
70
71
132
    void handleModuleDependency(ModuleDeps MD) override {
72
      // These are ignored for the make format as it can't support the full
73
      // set of deps, and handleFileDependency handles enough for implicitly
74
      // built modules to work.
75
0
    }
76
77
132
    void handleContextHash(std::string Hash) override 
{}0
78
79
132
    void printDependencies(std::string &S) {
80
125
      assert(Opts && "Handled dependency output options.");
81
82
0
      class DependencyPrinter : public DependencyFileGenerator {
83
125
      public:
84
125
        DependencyPrinter(DependencyOutputOptions &Opts,
85
125
                          ArrayRef<std::string> Dependencies)
86
125
            : DependencyFileGenerator(Opts) {
87
125
          for (const auto &Dep : Dependencies)
88
355
            addDependency(Dep);
89
125
        }
90
91
126
        void printDependencies(std::string &S) {
92
126
          llvm::raw_string_ostream OS(S);
93
126
          outputDependencyFile(OS);
94
126
        }
95
125
      };
96
97
125
      DependencyPrinter Generator(*Opts, Dependencies);
98
125
      Generator.printDependencies(S);
99
125
    }
100
101
132
  private:
102
132
    std::unique_ptr<DependencyOutputOptions> Opts;
103
132
    std::vector<std::string> Dependencies;
104
132
  };
105
106
132
  MakeDependencyPrinterConsumer Consumer;
107
132
  auto Result =
108
132
      Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
109
132
  if (Result)
110
6
    return std::move(Result);
111
126
  std::string Output;
112
126
  Consumer.printDependencies(Output);
113
126
  return Output;
114
132
}
115
116
llvm::Expected<FullDependenciesResult>
117
DependencyScanningTool::getFullDependencies(
118
    const std::vector<std::string> &CommandLine, StringRef CWD,
119
    const llvm::StringSet<> &AlreadySeen,
120
33
    llvm::Optional<StringRef> ModuleName) {
121
33
  class FullDependencyPrinterConsumer : public DependencyConsumer {
122
33
  public:
123
33
    FullDependencyPrinterConsumer(const llvm::StringSet<> &AlreadySeen)
124
33
        : AlreadySeen(AlreadySeen) {}
125
126
33
    void
127
33
    handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {}
128
129
36
    void handleFileDependency(StringRef File) override {
130
36
      Dependencies.push_back(std::string(File));
131
36
    }
132
133
33
    void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
134
1
      PrebuiltModuleDeps.emplace_back(std::move(PMD));
135
1
    }
136
137
43
    void handleModuleDependency(ModuleDeps MD) override {
138
43
      ClangModuleDeps[MD.ID.ContextHash + MD.ID.ModuleName] = std::move(MD);
139
43
    }
140
141
33
    void handleContextHash(std::string Hash) override {
142
29
      ContextHash = std::move(Hash);
143
29
    }
144
145
33
    FullDependenciesResult getFullDependencies() const {
146
33
      FullDependencies FD;
147
148
33
      FD.ID.ContextHash = std::move(ContextHash);
149
150
33
      FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
151
152
43
      for (auto &&M : ClangModuleDeps) {
153
43
        auto &MD = M.second;
154
43
        if (MD.ImportedByMainFile)
155
36
          FD.ClangModuleDeps.push_back(MD.ID);
156
43
      }
157
158
33
      FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
159
160
33
      FullDependenciesResult FDR;
161
162
43
      for (auto &&M : ClangModuleDeps) {
163
        // TODO: Avoid handleModuleDependency even being called for modules
164
        //   we've already seen.
165
43
        if (AlreadySeen.count(M.first))
166
0
          continue;
167
43
        FDR.DiscoveredModules.push_back(std::move(M.second));
168
43
      }
169
170
33
      FDR.FullDeps = std::move(FD);
171
33
      return FDR;
172
33
    }
173
174
33
  private:
175
33
    std::vector<std::string> Dependencies;
176
33
    std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
177
33
    std::map<std::string, ModuleDeps> ClangModuleDeps;
178
33
    std::string ContextHash;
179
33
    std::vector<std::string> OutputPaths;
180
33
    const llvm::StringSet<> &AlreadySeen;
181
33
  };
182
183
33
  FullDependencyPrinterConsumer Consumer(AlreadySeen);
184
33
  llvm::Error Result =
185
33
      Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
186
33
  if (Result)
187
0
    return std::move(Result);
188
33
  return Consumer.getFullDependencies();
189
33
}
190
191
} // end namespace dependencies
192
} // end namespace tooling
193
} // end namespace clang