blob: 98a044f115d6aa412caae137454cc4f9a628c45c [file] [log] [blame]
Alex Lorenze82d89c2014-08-22 22:56:03 +00001//===- CodeCoverage.cpp - Coverage tool based on profiling instrumentation-===//
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// The 'CodeCoverageTool' class implements a command line tool to analyze and
11// report coverage information using the profiling instrumentation and code
12// coverage mapping.
13//
14//===----------------------------------------------------------------------===//
15
Alex Lorenze82d89c2014-08-22 22:56:03 +000016#include "RenderingSupport.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000017#include "CoverageFilters.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000018#include "CoverageReport.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000019#include "CoverageSummary.h"
20#include "CoverageViewOptions.h"
21#include "SourceCoverageView.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000022#include "llvm/ADT/SmallString.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000023#include "llvm/ADT/StringRef.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000024#include "llvm/ProfileData/CoverageMapping.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000025#include "llvm/ProfileData/InstrProfReader.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000026#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/FileSystem.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000028#include "llvm/Support/Format.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000029#include "llvm/Support/ManagedStatic.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000030#include "llvm/Support/Path.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000031#include "llvm/Support/PrettyStackTrace.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/Signals.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000033#include <functional>
Justin Bognere53be062014-09-09 05:32:18 +000034#include <system_error>
Alex Lorenze82d89c2014-08-22 22:56:03 +000035
36using namespace llvm;
37using namespace coverage;
38
39namespace {
Alex Lorenze82d89c2014-08-22 22:56:03 +000040/// \brief The implementation of the coverage tool.
41class CodeCoverageTool {
42public:
43 enum Command {
44 /// \brief The show command.
45 Show,
46 /// \brief The report command.
47 Report
48 };
49
50 /// \brief Print the error message to the error output stream.
51 void error(const Twine &Message, StringRef Whence = "");
52
53 /// \brief Return a memory buffer for the given source file.
54 ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile);
55
Justin Bogner953e2402014-09-20 15:31:56 +000056 /// \brief Create source views for the expansions of the view.
57 void attachExpansionSubViews(SourceCoverageView &View,
58 ArrayRef<ExpansionRecord> Expansions,
59 CoverageMapping &Coverage);
Alex Lorenze82d89c2014-08-22 22:56:03 +000060
Justin Bogner953e2402014-09-20 15:31:56 +000061 /// \brief Create the source view of a particular function.
Justin Bogner5a6edad2014-09-19 19:07:17 +000062 std::unique_ptr<SourceCoverageView>
Justin Bogner953e2402014-09-20 15:31:56 +000063 createFunctionView(const FunctionRecord &Function, CoverageMapping &Coverage);
Alex Lorenze82d89c2014-08-22 22:56:03 +000064
65 /// \brief Create the main source view of a particular source file.
Justin Bogner5a6edad2014-09-19 19:07:17 +000066 std::unique_ptr<SourceCoverageView>
Justin Bogner953e2402014-09-20 15:31:56 +000067 createSourceFileView(StringRef SourceFile, CoverageMapping &Coverage);
Alex Lorenze82d89c2014-08-22 22:56:03 +000068
69 /// \brief Load the coverage mapping data. Return true if an error occured.
Justin Bogner953e2402014-09-20 15:31:56 +000070 std::unique_ptr<CoverageMapping> load();
Alex Lorenze82d89c2014-08-22 22:56:03 +000071
72 int run(Command Cmd, int argc, const char **argv);
73
74 typedef std::function<int(int, const char **)> CommandLineParserType;
75
76 int show(int argc, const char **argv,
77 CommandLineParserType commandLineParser);
78
79 int report(int argc, const char **argv,
80 CommandLineParserType commandLineParser);
81
Justin Bognerf6c50552014-10-30 20:51:24 +000082 std::string ObjectFilename;
Alex Lorenze82d89c2014-08-22 22:56:03 +000083 CoverageViewOptions ViewOpts;
Justin Bogner953e2402014-09-20 15:31:56 +000084 std::string PGOFilename;
Alex Lorenze82d89c2014-08-22 22:56:03 +000085 CoverageFiltersMatchAll Filters;
86 std::vector<std::string> SourceFiles;
87 std::vector<std::pair<std::string, std::unique_ptr<MemoryBuffer>>>
88 LoadedSourceFiles;
Alex Lorenze82d89c2014-08-22 22:56:03 +000089 bool CompareFilenamesOnly;
Justin Bogner116c1662014-09-19 08:13:12 +000090 StringMap<std::string> RemappedFilenames;
Alex Lorenze82d89c2014-08-22 22:56:03 +000091};
92}
93
94void CodeCoverageTool::error(const Twine &Message, StringRef Whence) {
95 errs() << "error: ";
96 if (!Whence.empty())
97 errs() << Whence << ": ";
98 errs() << Message << "\n";
99}
100
101ErrorOr<const MemoryBuffer &>
102CodeCoverageTool::getSourceFile(StringRef SourceFile) {
Justin Bogner116c1662014-09-19 08:13:12 +0000103 // If we've remapped filenames, look up the real location for this file.
104 if (!RemappedFilenames.empty()) {
105 auto Loc = RemappedFilenames.find(SourceFile);
106 if (Loc != RemappedFilenames.end())
107 SourceFile = Loc->second;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000108 }
Justin Bogner116c1662014-09-19 08:13:12 +0000109 for (const auto &Files : LoadedSourceFiles)
110 if (sys::fs::equivalent(SourceFile, Files.first))
111 return *Files.second;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000112 auto Buffer = MemoryBuffer::getFile(SourceFile);
113 if (auto EC = Buffer.getError()) {
114 error(EC.message(), SourceFile);
115 return EC;
116 }
Justin Bogner116c1662014-09-19 08:13:12 +0000117 LoadedSourceFiles.push_back(
118 std::make_pair(SourceFile, std::move(Buffer.get())));
Alex Lorenze82d89c2014-08-22 22:56:03 +0000119 return *LoadedSourceFiles.back().second;
120}
121
Justin Bogner953e2402014-09-20 15:31:56 +0000122void
123CodeCoverageTool::attachExpansionSubViews(SourceCoverageView &View,
124 ArrayRef<ExpansionRecord> Expansions,
125 CoverageMapping &Coverage) {
Alex Lorenze82d89c2014-08-22 22:56:03 +0000126 if (!ViewOpts.ShowExpandedRegions)
127 return;
Justin Bogner953e2402014-09-20 15:31:56 +0000128 for (const auto &Expansion : Expansions) {
129 auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
130 if (ExpansionCoverage.empty())
Alex Lorenze82d89c2014-08-22 22:56:03 +0000131 continue;
Justin Bogner953e2402014-09-20 15:31:56 +0000132 auto SourceBuffer = getSourceFile(ExpansionCoverage.getFilename());
133 if (!SourceBuffer)
Alex Lorenze82d89c2014-08-22 22:56:03 +0000134 continue;
Justin Bogner953e2402014-09-20 15:31:56 +0000135
136 auto SubViewExpansions = ExpansionCoverage.getExpansions();
137 auto SubView = llvm::make_unique<SourceCoverageView>(
138 SourceBuffer.get(), ViewOpts, std::move(ExpansionCoverage));
139 attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
140 View.addExpansion(Expansion.Region, std::move(SubView));
Alex Lorenze82d89c2014-08-22 22:56:03 +0000141 }
142}
143
Justin Bogner5a6edad2014-09-19 19:07:17 +0000144std::unique_ptr<SourceCoverageView>
Justin Bogner953e2402014-09-20 15:31:56 +0000145CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
146 CoverageMapping &Coverage) {
147 auto FunctionCoverage = Coverage.getCoverageForFunction(Function);
148 if (FunctionCoverage.empty())
Justin Bogner5a6edad2014-09-19 19:07:17 +0000149 return nullptr;
Justin Bogner953e2402014-09-20 15:31:56 +0000150 auto SourceBuffer = getSourceFile(FunctionCoverage.getFilename());
Justin Bogner5a6edad2014-09-19 19:07:17 +0000151 if (!SourceBuffer)
152 return nullptr;
Justin Bogner953e2402014-09-20 15:31:56 +0000153
154 auto Expansions = FunctionCoverage.getExpansions();
155 auto View = llvm::make_unique<SourceCoverageView>(
156 SourceBuffer.get(), ViewOpts, std::move(FunctionCoverage));
157 attachExpansionSubViews(*View, Expansions, Coverage);
158
159 return View;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000160}
161
Justin Bogner953e2402014-09-20 15:31:56 +0000162std::unique_ptr<SourceCoverageView>
163CodeCoverageTool::createSourceFileView(StringRef SourceFile,
164 CoverageMapping &Coverage) {
Justin Bogner5a6edad2014-09-19 19:07:17 +0000165 auto SourceBuffer = getSourceFile(SourceFile);
166 if (!SourceBuffer)
167 return nullptr;
Justin Bogner953e2402014-09-20 15:31:56 +0000168 auto FileCoverage = Coverage.getCoverageForFile(SourceFile);
169 if (FileCoverage.empty())
Justin Bogner5a6edad2014-09-19 19:07:17 +0000170 return nullptr;
Justin Bogner953e2402014-09-20 15:31:56 +0000171
172 auto Expansions = FileCoverage.getExpansions();
173 auto View = llvm::make_unique<SourceCoverageView>(
174 SourceBuffer.get(), ViewOpts, std::move(FileCoverage));
175 attachExpansionSubViews(*View, Expansions, Coverage);
176
177 for (auto Function : Coverage.getInstantiations(SourceFile)) {
178 auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
179 auto SubViewExpansions = SubViewCoverage.getExpansions();
180 auto SubView = llvm::make_unique<SourceCoverageView>(
181 SourceBuffer.get(), ViewOpts, std::move(SubViewCoverage));
182 attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
183
184 if (SubView) {
Justin Bogner5e1400a2014-09-17 05:33:20 +0000185 unsigned FileID = Function->CountedRegions.front().FileID;
186 unsigned Line = 0;
187 for (const auto &CR : Function->CountedRegions)
188 if (CR.FileID == FileID)
189 Line = std::max(CR.LineEnd, Line);
Justin Bogner953e2402014-09-20 15:31:56 +0000190 View->addInstantiation(Function->Name, Line, std::move(SubView));
Alex Lorenze82d89c2014-08-22 22:56:03 +0000191 }
192 }
Justin Bogner5a6edad2014-09-19 19:07:17 +0000193 return View;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000194}
195
Justin Bogner953e2402014-09-20 15:31:56 +0000196std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
Justin Bogner19a93ba2014-09-20 17:19:52 +0000197 auto CoverageOrErr = CoverageMapping::load(ObjectFilename, PGOFilename);
Justin Bogner953e2402014-09-20 15:31:56 +0000198 if (std::error_code EC = CoverageOrErr.getError()) {
199 colored_ostream(errs(), raw_ostream::RED)
200 << "error: Failed to load coverage: " << EC.message();
201 errs() << "\n";
202 return nullptr;
203 }
204 auto Coverage = std::move(CoverageOrErr.get());
205 unsigned Mismatched = Coverage->getMismatchedCount();
206 if (Mismatched) {
207 colored_ostream(errs(), raw_ostream::RED)
208 << "warning: " << Mismatched << " functions have mismatched data. ";
209 errs() << "\n";
Alex Lorenze82d89c2014-08-22 22:56:03 +0000210 }
Justin Bogner116c1662014-09-19 08:13:12 +0000211
212 if (CompareFilenamesOnly) {
Justin Bogner953e2402014-09-20 15:31:56 +0000213 auto CoveredFiles = Coverage.get()->getUniqueSourceFiles();
Justin Bogner116c1662014-09-19 08:13:12 +0000214 for (auto &SF : SourceFiles) {
215 StringRef SFBase = sys::path::filename(SF);
216 for (const auto &CF : CoveredFiles)
217 if (SFBase == sys::path::filename(CF)) {
218 RemappedFilenames[CF] = SF;
219 SF = CF;
220 break;
221 }
222 }
223 }
224
Justin Bogner953e2402014-09-20 15:31:56 +0000225 return Coverage;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000226}
227
228int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
229 // Print a stack trace if we signal out.
230 sys::PrintStackTraceOnErrorSignal();
231 PrettyStackTraceProgram X(argc, argv);
232 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
233
Justin Bognerf6c50552014-10-30 20:51:24 +0000234 cl::opt<std::string, true> ObjectFilename(
235 cl::Positional, cl::Required, cl::location(this->ObjectFilename),
236 cl::desc("Covered executable or object file."));
237
Alex Lorenze82d89c2014-08-22 22:56:03 +0000238 cl::list<std::string> InputSourceFiles(
239 cl::Positional, cl::desc("<Source files>"), cl::ZeroOrMore);
240
Justin Bogner953e2402014-09-20 15:31:56 +0000241 cl::opt<std::string, true> PGOFilename(
242 "instr-profile", cl::Required, cl::location(this->PGOFilename),
Alex Lorenze82d89c2014-08-22 22:56:03 +0000243 cl::desc(
244 "File with the profile data obtained after an instrumented run"));
245
246 cl::opt<bool> DebugDump("dump", cl::Optional,
247 cl::desc("Show internal debug dump"));
248
249 cl::opt<bool> FilenameEquivalence(
250 "filename-equivalence", cl::Optional,
Justin Bogner116c1662014-09-19 08:13:12 +0000251 cl::desc("Treat source files as equivalent to paths in the coverage data "
252 "when the file names match, even if the full paths do not"));
Alex Lorenze82d89c2014-08-22 22:56:03 +0000253
254 cl::OptionCategory FilteringCategory("Function filtering options");
255
256 cl::list<std::string> NameFilters(
257 "name", cl::Optional,
258 cl::desc("Show code coverage only for functions with the given name"),
259 cl::ZeroOrMore, cl::cat(FilteringCategory));
260
261 cl::list<std::string> NameRegexFilters(
262 "name-regex", cl::Optional,
263 cl::desc("Show code coverage only for functions that match the given "
264 "regular expression"),
265 cl::ZeroOrMore, cl::cat(FilteringCategory));
266
267 cl::opt<double> RegionCoverageLtFilter(
268 "region-coverage-lt", cl::Optional,
269 cl::desc("Show code coverage only for functions with region coverage "
270 "less than the given threshold"),
271 cl::cat(FilteringCategory));
272
273 cl::opt<double> RegionCoverageGtFilter(
274 "region-coverage-gt", cl::Optional,
275 cl::desc("Show code coverage only for functions with region coverage "
276 "greater than the given threshold"),
277 cl::cat(FilteringCategory));
278
279 cl::opt<double> LineCoverageLtFilter(
280 "line-coverage-lt", cl::Optional,
281 cl::desc("Show code coverage only for functions with line coverage less "
282 "than the given threshold"),
283 cl::cat(FilteringCategory));
284
285 cl::opt<double> LineCoverageGtFilter(
286 "line-coverage-gt", cl::Optional,
287 cl::desc("Show code coverage only for functions with line coverage "
288 "greater than the given threshold"),
289 cl::cat(FilteringCategory));
290
291 auto commandLineParser = [&, this](int argc, const char **argv) -> int {
292 cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
293 ViewOpts.Debug = DebugDump;
294 CompareFilenamesOnly = FilenameEquivalence;
295
Alex Lorenze82d89c2014-08-22 22:56:03 +0000296 // Create the function filters
297 if (!NameFilters.empty() || !NameRegexFilters.empty()) {
298 auto NameFilterer = new CoverageFilters;
299 for (const auto &Name : NameFilters)
300 NameFilterer->push_back(llvm::make_unique<NameCoverageFilter>(Name));
301 for (const auto &Regex : NameRegexFilters)
302 NameFilterer->push_back(
303 llvm::make_unique<NameRegexCoverageFilter>(Regex));
304 Filters.push_back(std::unique_ptr<CoverageFilter>(NameFilterer));
305 }
306 if (RegionCoverageLtFilter.getNumOccurrences() ||
307 RegionCoverageGtFilter.getNumOccurrences() ||
308 LineCoverageLtFilter.getNumOccurrences() ||
309 LineCoverageGtFilter.getNumOccurrences()) {
310 auto StatFilterer = new CoverageFilters;
311 if (RegionCoverageLtFilter.getNumOccurrences())
312 StatFilterer->push_back(llvm::make_unique<RegionCoverageFilter>(
313 RegionCoverageFilter::LessThan, RegionCoverageLtFilter));
314 if (RegionCoverageGtFilter.getNumOccurrences())
315 StatFilterer->push_back(llvm::make_unique<RegionCoverageFilter>(
316 RegionCoverageFilter::GreaterThan, RegionCoverageGtFilter));
317 if (LineCoverageLtFilter.getNumOccurrences())
318 StatFilterer->push_back(llvm::make_unique<LineCoverageFilter>(
319 LineCoverageFilter::LessThan, LineCoverageLtFilter));
320 if (LineCoverageGtFilter.getNumOccurrences())
321 StatFilterer->push_back(llvm::make_unique<LineCoverageFilter>(
322 RegionCoverageFilter::GreaterThan, LineCoverageGtFilter));
323 Filters.push_back(std::unique_ptr<CoverageFilter>(StatFilterer));
324 }
325
Justin Bogner116c1662014-09-19 08:13:12 +0000326 for (const auto &File : InputSourceFiles) {
327 SmallString<128> Path(File);
328 if (std::error_code EC = sys::fs::make_absolute(Path)) {
329 errs() << "error: " << File << ": " << EC.message();
330 return 1;
331 }
332 SourceFiles.push_back(Path.str());
333 }
Alex Lorenze82d89c2014-08-22 22:56:03 +0000334 return 0;
335 };
336
Alex Lorenze82d89c2014-08-22 22:56:03 +0000337 switch (Cmd) {
338 case Show:
339 return show(argc, argv, commandLineParser);
340 case Report:
341 return report(argc, argv, commandLineParser);
342 }
343 return 0;
344}
345
346int CodeCoverageTool::show(int argc, const char **argv,
347 CommandLineParserType commandLineParser) {
348
349 cl::OptionCategory ViewCategory("Viewing options");
350
351 cl::opt<bool> ShowLineExecutionCounts(
352 "show-line-counts", cl::Optional,
353 cl::desc("Show the execution counts for each line"), cl::init(true),
354 cl::cat(ViewCategory));
355
356 cl::opt<bool> ShowRegions(
357 "show-regions", cl::Optional,
358 cl::desc("Show the execution counts for each region"),
359 cl::cat(ViewCategory));
360
361 cl::opt<bool> ShowBestLineRegionsCounts(
362 "show-line-counts-or-regions", cl::Optional,
363 cl::desc("Show the execution counts for each line, or the execution "
364 "counts for each region on lines that have multiple regions"),
365 cl::cat(ViewCategory));
366
367 cl::opt<bool> ShowExpansions("show-expansions", cl::Optional,
368 cl::desc("Show expanded source regions"),
369 cl::cat(ViewCategory));
370
371 cl::opt<bool> ShowInstantiations("show-instantiations", cl::Optional,
372 cl::desc("Show function instantiations"),
373 cl::cat(ViewCategory));
374
375 cl::opt<bool> NoColors("no-colors", cl::Optional,
376 cl::desc("Don't show text colors"), cl::init(false),
377 cl::cat(ViewCategory));
378
379 auto Err = commandLineParser(argc, argv);
380 if (Err)
381 return Err;
382
383 ViewOpts.Colors = !NoColors;
384 ViewOpts.ShowLineNumbers = true;
385 ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 ||
386 !ShowRegions || ShowBestLineRegionsCounts;
387 ViewOpts.ShowRegionMarkers = ShowRegions || ShowBestLineRegionsCounts;
388 ViewOpts.ShowLineStatsOrRegionMarkers = ShowBestLineRegionsCounts;
389 ViewOpts.ShowExpandedRegions = ShowExpansions;
390 ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
391
Justin Bogner953e2402014-09-20 15:31:56 +0000392 auto Coverage = load();
393 if (!Coverage)
Alex Lorenze82d89c2014-08-22 22:56:03 +0000394 return 1;
395
396 if (!Filters.empty()) {
397 // Show functions
Justin Bogner953e2402014-09-20 15:31:56 +0000398 for (const auto &Function : Coverage->getCoveredFunctions()) {
399 if (!Filters.matches(Function))
Alex Lorenze82d89c2014-08-22 22:56:03 +0000400 continue;
Justin Bogner953e2402014-09-20 15:31:56 +0000401
402 auto mainView = createFunctionView(Function, *Coverage);
Justin Bogner5a6edad2014-09-19 19:07:17 +0000403 if (!mainView) {
404 ViewOpts.colored_ostream(outs(), raw_ostream::RED)
Justin Bogner953e2402014-09-20 15:31:56 +0000405 << "warning: Could not read coverage for '" << Function.Name;
Justin Bogner5a6edad2014-09-19 19:07:17 +0000406 outs() << "\n";
407 continue;
408 }
Justin Bogner953e2402014-09-20 15:31:56 +0000409 ViewOpts.colored_ostream(outs(), raw_ostream::CYAN) << Function.Name
410 << ":";
Alex Lorenze82d89c2014-08-22 22:56:03 +0000411 outs() << "\n";
Justin Bogner5a6edad2014-09-19 19:07:17 +0000412 mainView->render(outs(), /*WholeFile=*/false);
Justin Bogner953e2402014-09-20 15:31:56 +0000413 outs() << "\n";
Alex Lorenze82d89c2014-08-22 22:56:03 +0000414 }
415 return 0;
416 }
417
418 // Show files
419 bool ShowFilenames = SourceFiles.size() != 1;
420
Justin Bogner116c1662014-09-19 08:13:12 +0000421 if (SourceFiles.empty())
Alex Lorenze82d89c2014-08-22 22:56:03 +0000422 // Get the source files from the function coverage mapping
Justin Bogner953e2402014-09-20 15:31:56 +0000423 for (StringRef Filename : Coverage->getUniqueSourceFiles())
Alex Lorenze82d89c2014-08-22 22:56:03 +0000424 SourceFiles.push_back(Filename);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000425
426 for (const auto &SourceFile : SourceFiles) {
Justin Bogner953e2402014-09-20 15:31:56 +0000427 auto mainView = createSourceFileView(SourceFile, *Coverage);
Justin Bogner5a6edad2014-09-19 19:07:17 +0000428 if (!mainView) {
Alex Lorenze82d89c2014-08-22 22:56:03 +0000429 ViewOpts.colored_ostream(outs(), raw_ostream::RED)
430 << "warning: The file '" << SourceFile << "' isn't covered.";
431 outs() << "\n";
432 continue;
433 }
434
435 if (ShowFilenames) {
436 ViewOpts.colored_ostream(outs(), raw_ostream::CYAN) << SourceFile << ":";
437 outs() << "\n";
438 }
Justin Bogner5a6edad2014-09-19 19:07:17 +0000439 mainView->render(outs(), /*Wholefile=*/true);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000440 if (SourceFiles.size() > 1)
441 outs() << "\n";
442 }
443
444 return 0;
445}
446
447int CodeCoverageTool::report(int argc, const char **argv,
448 CommandLineParserType commandLineParser) {
449 cl::opt<bool> NoColors("no-colors", cl::Optional,
450 cl::desc("Don't show text colors"), cl::init(false));
451
452 auto Err = commandLineParser(argc, argv);
453 if (Err)
454 return Err;
455
456 ViewOpts.Colors = !NoColors;
457
Justin Bogner953e2402014-09-20 15:31:56 +0000458 auto Coverage = load();
459 if (!Coverage)
Alex Lorenze82d89c2014-08-22 22:56:03 +0000460 return 1;
461
462 CoverageSummary Summarizer;
Justin Bognerd5fca922014-11-14 01:50:32 +0000463 Summarizer.createSummaries(*Coverage);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000464 CoverageReport Report(ViewOpts, Summarizer);
465 if (SourceFiles.empty() && Filters.empty()) {
466 Report.renderFileReports(llvm::outs());
467 return 0;
468 }
469
470 Report.renderFunctionReports(llvm::outs());
471 return 0;
472}
473
Justin Bognerd249a3b2014-10-30 20:57:49 +0000474int showMain(int argc, const char *argv[]) {
Alex Lorenze82d89c2014-08-22 22:56:03 +0000475 CodeCoverageTool Tool;
476 return Tool.run(CodeCoverageTool::Show, argc, argv);
477}
478
Justin Bognerd249a3b2014-10-30 20:57:49 +0000479int reportMain(int argc, const char *argv[]) {
Alex Lorenze82d89c2014-08-22 22:56:03 +0000480 CodeCoverageTool Tool;
481 return Tool.run(CodeCoverageTool::Report, argc, argv);
482}