Coverage Report

Created: 2022-01-18 06:27

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