llvm-cov: Return unique_ptrs instead of filling objects (NFC)
[oota-llvm.git] / tools / llvm-cov / CodeCoverage.cpp
1 //===- 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
16 #include "RenderingSupport.h"
17 #include "CoverageViewOptions.h"
18 #include "CoverageFilters.h"
19 #include "SourceCoverageDataManager.h"
20 #include "SourceCoverageView.h"
21 #include "CoverageSummary.h"
22 #include "CoverageReport.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/ADT/SmallString.h"
26 #include "llvm/ADT/SmallSet.h"
27 #include "llvm/ADT/DenseSet.h"
28 #include "llvm/ProfileData/InstrProfReader.h"
29 #include "llvm/ProfileData/CoverageMapping.h"
30 #include "llvm/ProfileData/CoverageMappingReader.h"
31 #include "llvm/Support/CommandLine.h"
32 #include "llvm/Support/FileSystem.h"
33 #include "llvm/Support/ManagedStatic.h"
34 #include "llvm/Support/MemoryObject.h"
35 #include "llvm/Support/Format.h"
36 #include "llvm/Support/Path.h"
37 #include "llvm/Support/Signals.h"
38 #include "llvm/Support/PrettyStackTrace.h"
39 #include <functional>
40 #include <system_error>
41
42 using namespace llvm;
43 using namespace coverage;
44
45 namespace {
46 /// \brief Distribute the functions into instantiation sets.
47 ///
48 /// An instantiation set is a collection of functions that have the same source
49 /// code, ie, template functions specializations.
50 class FunctionInstantiationSetCollector {
51   typedef DenseMap<std::pair<unsigned, unsigned>,
52                    std::vector<const FunctionCoverageMapping *>> MapT;
53   MapT InstantiatedFunctions;
54
55 public:
56   void insert(const FunctionCoverageMapping &Function, unsigned FileID) {
57     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
58     while (I != E && I->FileID != FileID)
59       ++I;
60     assert(I != E && "function does not cover the given file");
61     auto &Functions = InstantiatedFunctions[I->startLoc()];
62     Functions.push_back(&Function);
63   }
64
65   MapT::iterator begin() {
66     return InstantiatedFunctions.begin();
67   }
68
69   MapT::iterator end() {
70     return InstantiatedFunctions.end();
71   }
72 };
73
74 /// \brief The implementation of the coverage tool.
75 class CodeCoverageTool {
76 public:
77   enum Command {
78     /// \brief The show command.
79     Show,
80     /// \brief The report command.
81     Report
82   };
83
84   /// \brief Print the error message to the error output stream.
85   void error(const Twine &Message, StringRef Whence = "");
86
87   /// \brief Return a memory buffer for the given source file.
88   ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile);
89
90   /// \brief Collect a set of function's file ids which correspond to the
91   /// given source file. Return false if the set is empty.
92   bool gatherInterestingFileIDs(StringRef SourceFile,
93                                 const FunctionCoverageMapping &Function,
94                                 SmallSet<unsigned, 8> &InterestingFileIDs);
95
96   /// \brief Find the file id which is not an expanded file id.
97   bool findMainViewFileID(StringRef SourceFile,
98                           const FunctionCoverageMapping &Function,
99                           unsigned &MainViewFileID);
100
101   bool findMainViewFileID(const FunctionCoverageMapping &Function,
102                           unsigned &MainViewFileID);
103
104   /// \brief Create a source view which shows coverage for an expansion
105   /// of a file.
106   std::unique_ptr<SourceCoverageView>
107   createExpansionSubView(const CountedRegion &ExpandedRegion,
108                          const FunctionCoverageMapping &Function);
109
110   void attachExpansionSubViews(SourceCoverageView &View, unsigned ViewFileID,
111                                const FunctionCoverageMapping &Function);
112
113   /// \brief Create a source view which shows coverage for an instantiation
114   /// of a funciton.
115   std::unique_ptr<SourceCoverageView>
116   createInstantiationSubView(StringRef SourceFile,
117                              const FunctionCoverageMapping &Function);
118
119   /// \brief Create the main source view of a particular source file.
120   std::unique_ptr<SourceCoverageView>
121   createSourceFileView(StringRef SourceFile,
122                        ArrayRef<FunctionCoverageMapping> FunctionMappingRecords,
123                        bool UseOnlyRegionsInMainFile = false);
124
125   /// \brief Load the coverage mapping data. Return true if an error occured.
126   bool load();
127
128   int run(Command Cmd, int argc, const char **argv);
129
130   typedef std::function<int(int, const char **)> CommandLineParserType;
131
132   int show(int argc, const char **argv,
133            CommandLineParserType commandLineParser);
134
135   int report(int argc, const char **argv,
136              CommandLineParserType commandLineParser);
137
138   StringRef ObjectFilename;
139   CoverageViewOptions ViewOpts;
140   std::unique_ptr<IndexedInstrProfReader> PGOReader;
141   CoverageFiltersMatchAll Filters;
142   std::vector<std::string> SourceFiles;
143   std::vector<std::pair<std::string, std::unique_ptr<MemoryBuffer>>>
144       LoadedSourceFiles;
145   std::vector<FunctionCoverageMapping> FunctionMappingRecords;
146   bool CompareFilenamesOnly;
147   StringMap<std::string> RemappedFilenames;
148 };
149 }
150
151 static std::vector<StringRef>
152 getUniqueFilenames(ArrayRef<FunctionCoverageMapping> FunctionMappingRecords) {
153   std::vector<StringRef> Filenames;
154   for (const auto &Function : FunctionMappingRecords)
155     for (const auto &Filename : Function.Filenames)
156       Filenames.push_back(Filename);
157   std::sort(Filenames.begin(), Filenames.end());
158   auto Last = std::unique(Filenames.begin(), Filenames.end());
159   Filenames.erase(Last, Filenames.end());
160   return Filenames;
161 }
162
163 void CodeCoverageTool::error(const Twine &Message, StringRef Whence) {
164   errs() << "error: ";
165   if (!Whence.empty())
166     errs() << Whence << ": ";
167   errs() << Message << "\n";
168 }
169
170 ErrorOr<const MemoryBuffer &>
171 CodeCoverageTool::getSourceFile(StringRef SourceFile) {
172   // If we've remapped filenames, look up the real location for this file.
173   if (!RemappedFilenames.empty()) {
174     auto Loc = RemappedFilenames.find(SourceFile);
175     if (Loc != RemappedFilenames.end())
176       SourceFile = Loc->second;
177   }
178   for (const auto &Files : LoadedSourceFiles)
179     if (sys::fs::equivalent(SourceFile, Files.first))
180       return *Files.second;
181   auto Buffer = MemoryBuffer::getFile(SourceFile);
182   if (auto EC = Buffer.getError()) {
183     error(EC.message(), SourceFile);
184     return EC;
185   }
186   LoadedSourceFiles.push_back(
187       std::make_pair(SourceFile, std::move(Buffer.get())));
188   return *LoadedSourceFiles.back().second;
189 }
190
191 bool CodeCoverageTool::gatherInterestingFileIDs(
192     StringRef SourceFile, const FunctionCoverageMapping &Function,
193     SmallSet<unsigned, 8> &InterestingFileIDs) {
194   bool Interesting = false;
195   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) {
196     if (SourceFile == Function.Filenames[I]) {
197       InterestingFileIDs.insert(I);
198       Interesting = true;
199     }
200   }
201   return Interesting;
202 }
203
204 bool
205 CodeCoverageTool::findMainViewFileID(StringRef SourceFile,
206                                      const FunctionCoverageMapping &Function,
207                                      unsigned &MainViewFileID) {
208   llvm::SmallVector<bool, 8> IsExpandedFile(Function.Filenames.size(), false);
209   llvm::SmallVector<bool, 8> FilenameEquivalence(Function.Filenames.size(),
210                                                  false);
211   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) {
212     if (SourceFile == Function.Filenames[I])
213       FilenameEquivalence[I] = true;
214   }
215   for (const auto &CR : Function.CountedRegions) {
216     if (CR.Kind == CounterMappingRegion::ExpansionRegion &&
217         FilenameEquivalence[CR.FileID])
218       IsExpandedFile[CR.ExpandedFileID] = true;
219   }
220   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) {
221     if (!FilenameEquivalence[I] || IsExpandedFile[I])
222       continue;
223     MainViewFileID = I;
224     return false;
225   }
226   return true;
227 }
228
229 bool
230 CodeCoverageTool::findMainViewFileID(const FunctionCoverageMapping &Function,
231                                      unsigned &MainViewFileID) {
232   llvm::SmallVector<bool, 8> IsExpandedFile(Function.Filenames.size(), false);
233   for (const auto &CR : Function.CountedRegions) {
234     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
235       IsExpandedFile[CR.ExpandedFileID] = true;
236   }
237   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) {
238     if (IsExpandedFile[I])
239       continue;
240     MainViewFileID = I;
241     return false;
242   }
243   return true;
244 }
245
246 std::unique_ptr<SourceCoverageView> CodeCoverageTool::createExpansionSubView(
247     const CountedRegion &ExpandedRegion,
248     const FunctionCoverageMapping &Function) {
249   auto SourceBuffer =
250       getSourceFile(Function.Filenames[ExpandedRegion.ExpandedFileID]);
251   if (!SourceBuffer)
252     return nullptr;
253   auto RegionManager = llvm::make_unique<SourceCoverageDataManager>();
254   for (const auto &CR : Function.CountedRegions) {
255     if (CR.FileID == ExpandedRegion.ExpandedFileID)
256       RegionManager->insert(CR);
257   }
258   auto SubView = llvm::make_unique<SourceCoverageView>(SourceBuffer.get(),
259                                                        ViewOpts);
260   SubView->load(std::move(RegionManager));
261   attachExpansionSubViews(*SubView, ExpandedRegion.ExpandedFileID, Function);
262   return SubView;
263 }
264
265 void CodeCoverageTool::attachExpansionSubViews(
266     SourceCoverageView &View, unsigned ViewFileID,
267     const FunctionCoverageMapping &Function) {
268   if (!ViewOpts.ShowExpandedRegions)
269     return;
270   for (const auto &CR : Function.CountedRegions) {
271     if (CR.Kind != CounterMappingRegion::ExpansionRegion)
272       continue;
273     if (CR.FileID != ViewFileID)
274       continue;
275     auto SubView = createExpansionSubView(CR, Function);
276     if (SubView)
277       View.addExpansion(CR, std::move(SubView));
278   }
279 }
280
281 std::unique_ptr<SourceCoverageView>
282 CodeCoverageTool::createInstantiationSubView(
283     StringRef SourceFile, const FunctionCoverageMapping &Function) {
284   auto RegionManager = llvm::make_unique<SourceCoverageDataManager>();
285   SmallSet<unsigned, 8> InterestingFileIDs;
286   if (!gatherInterestingFileIDs(SourceFile, Function, InterestingFileIDs))
287     return nullptr;
288   // Get the interesting regions
289   for (const auto &CR : Function.CountedRegions) {
290     if (InterestingFileIDs.count(CR.FileID))
291       RegionManager->insert(CR);
292   }
293
294   auto SourceBuffer = getSourceFile(SourceFile);
295   if (!SourceBuffer)
296     return nullptr;
297   auto SubView = llvm::make_unique<SourceCoverageView>(SourceBuffer.get(),
298                                                        ViewOpts);
299   SubView->load(std::move(RegionManager));
300   unsigned MainFileID;
301   if (!findMainViewFileID(SourceFile, Function, MainFileID))
302     attachExpansionSubViews(*SubView, MainFileID, Function);
303   return SubView;
304 }
305
306 std::unique_ptr<SourceCoverageView> CodeCoverageTool::createSourceFileView(
307     StringRef SourceFile,
308     ArrayRef<FunctionCoverageMapping> FunctionMappingRecords,
309     bool UseOnlyRegionsInMainFile) {
310   auto RegionManager = llvm::make_unique<SourceCoverageDataManager>();
311   FunctionInstantiationSetCollector InstantiationSetCollector;
312
313   auto SourceBuffer = getSourceFile(SourceFile);
314   if (!SourceBuffer)
315     return nullptr;
316   auto View =
317       llvm::make_unique<SourceCoverageView>(SourceBuffer.get(), ViewOpts);
318
319   for (const auto &Function : FunctionMappingRecords) {
320     unsigned MainFileID;
321     if (findMainViewFileID(SourceFile, Function, MainFileID))
322       continue;
323     SmallSet<unsigned, 8> InterestingFileIDs;
324     if (UseOnlyRegionsInMainFile) {
325       InterestingFileIDs.insert(MainFileID);
326     } else if (!gatherInterestingFileIDs(SourceFile, Function,
327                                          InterestingFileIDs))
328       continue;
329     // Get the interesting regions
330     for (const auto &CR : Function.CountedRegions) {
331       if (InterestingFileIDs.count(CR.FileID))
332         RegionManager->insert(CR);
333     }
334     InstantiationSetCollector.insert(Function, MainFileID);
335     attachExpansionSubViews(*View, MainFileID, Function);
336   }
337   if (RegionManager->getCoverageSegments().empty())
338     return nullptr;
339   View->load(std::move(RegionManager));
340   // Show instantiations
341   if (!ViewOpts.ShowFunctionInstantiations)
342     return View;
343   for (const auto &InstantiationSet : InstantiationSetCollector) {
344     if (InstantiationSet.second.size() < 2)
345       continue;
346     for (auto Function : InstantiationSet.second) {
347       unsigned FileID = Function->CountedRegions.front().FileID;
348       unsigned Line = 0;
349       for (const auto &CR : Function->CountedRegions)
350         if (CR.FileID == FileID)
351           Line = std::max(CR.LineEnd, Line);
352       auto SubView = createInstantiationSubView(SourceFile, *Function);
353       if (SubView)
354         View->addInstantiation(Function->Name, Line, std::move(SubView));
355     }
356   }
357   return View;
358 }
359
360 bool CodeCoverageTool::load() {
361   auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
362   if (auto EC = CounterMappingBuff.getError()) {
363     error(EC.message(), ObjectFilename);
364     return true;
365   }
366   ObjectFileCoverageMappingReader MappingReader(CounterMappingBuff.get());
367   if (auto EC = MappingReader.readHeader()) {
368     error(EC.message(), ObjectFilename);
369     return true;
370   }
371
372   std::vector<uint64_t> Counts;
373   for (const auto &I : MappingReader) {
374     FunctionCoverageMapping Function(I.FunctionName, I.Filenames);
375
376     // Create the mapping regions with evaluated execution counts
377     Counts.clear();
378     PGOReader->getFunctionCounts(Function.Name, I.FunctionHash, Counts);
379
380     // Get the biggest referenced counters
381     bool RegionError = false;
382     CounterMappingContext Ctx(I.Expressions, Counts);
383     for (const auto &R : I.MappingRegions) {
384       // Compute the values of mapped regions
385       if (ViewOpts.Debug) {
386         errs() << "File " << R.FileID << "| " << R.LineStart << ":"
387                << R.ColumnStart << " -> " << R.LineEnd << ":" << R.ColumnEnd
388                << " = ";
389         Ctx.dump(R.Count);
390         if (R.Kind == CounterMappingRegion::ExpansionRegion) {
391           errs() << " (Expanded file id = " << R.ExpandedFileID << ") ";
392         }
393         errs() << "\n";
394       }
395       ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(R.Count);
396       if (ExecutionCount) {
397         Function.CountedRegions.push_back(CountedRegion(R, *ExecutionCount));
398       } else if (!RegionError) {
399         colored_ostream(errs(), raw_ostream::RED)
400             << "error: Regions and counters don't match in a function '"
401             << Function.Name << "' (re-run the instrumented binary).";
402         errs() << "\n";
403         RegionError = true;
404       }
405     }
406
407     if (RegionError || !Filters.matches(Function))
408       continue;
409
410     FunctionMappingRecords.push_back(Function);
411   }
412
413   if (CompareFilenamesOnly) {
414     auto CoveredFiles = getUniqueFilenames(FunctionMappingRecords);
415     for (auto &SF : SourceFiles) {
416       StringRef SFBase = sys::path::filename(SF);
417       for (const auto &CF : CoveredFiles)
418         if (SFBase == sys::path::filename(CF)) {
419           RemappedFilenames[CF] = SF;
420           SF = CF;
421           break;
422         }
423     }
424   }
425
426   return false;
427 }
428
429 int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
430   // Print a stack trace if we signal out.
431   sys::PrintStackTraceOnErrorSignal();
432   PrettyStackTraceProgram X(argc, argv);
433   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
434
435   cl::list<std::string> InputSourceFiles(
436       cl::Positional, cl::desc("<Source files>"), cl::ZeroOrMore);
437
438   cl::opt<std::string> PGOFilename(
439       "instr-profile", cl::Required,
440       cl::desc(
441           "File with the profile data obtained after an instrumented run"));
442
443   cl::opt<bool> DebugDump("dump", cl::Optional,
444                           cl::desc("Show internal debug dump"));
445
446   cl::opt<bool> FilenameEquivalence(
447       "filename-equivalence", cl::Optional,
448       cl::desc("Treat source files as equivalent to paths in the coverage data "
449                "when the file names match, even if the full paths do not"));
450
451   cl::OptionCategory FilteringCategory("Function filtering options");
452
453   cl::list<std::string> NameFilters(
454       "name", cl::Optional,
455       cl::desc("Show code coverage only for functions with the given name"),
456       cl::ZeroOrMore, cl::cat(FilteringCategory));
457
458   cl::list<std::string> NameRegexFilters(
459       "name-regex", cl::Optional,
460       cl::desc("Show code coverage only for functions that match the given "
461                "regular expression"),
462       cl::ZeroOrMore, cl::cat(FilteringCategory));
463
464   cl::opt<double> RegionCoverageLtFilter(
465       "region-coverage-lt", cl::Optional,
466       cl::desc("Show code coverage only for functions with region coverage "
467                "less than the given threshold"),
468       cl::cat(FilteringCategory));
469
470   cl::opt<double> RegionCoverageGtFilter(
471       "region-coverage-gt", cl::Optional,
472       cl::desc("Show code coverage only for functions with region coverage "
473                "greater than the given threshold"),
474       cl::cat(FilteringCategory));
475
476   cl::opt<double> LineCoverageLtFilter(
477       "line-coverage-lt", cl::Optional,
478       cl::desc("Show code coverage only for functions with line coverage less "
479                "than the given threshold"),
480       cl::cat(FilteringCategory));
481
482   cl::opt<double> LineCoverageGtFilter(
483       "line-coverage-gt", cl::Optional,
484       cl::desc("Show code coverage only for functions with line coverage "
485                "greater than the given threshold"),
486       cl::cat(FilteringCategory));
487
488   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
489     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
490     ViewOpts.Debug = DebugDump;
491     CompareFilenamesOnly = FilenameEquivalence;
492
493     if (auto EC = IndexedInstrProfReader::create(PGOFilename, PGOReader)) {
494       error(EC.message(), PGOFilename);
495       return 1;
496     }
497
498     // Create the function filters
499     if (!NameFilters.empty() || !NameRegexFilters.empty()) {
500       auto NameFilterer = new CoverageFilters;
501       for (const auto &Name : NameFilters)
502         NameFilterer->push_back(llvm::make_unique<NameCoverageFilter>(Name));
503       for (const auto &Regex : NameRegexFilters)
504         NameFilterer->push_back(
505             llvm::make_unique<NameRegexCoverageFilter>(Regex));
506       Filters.push_back(std::unique_ptr<CoverageFilter>(NameFilterer));
507     }
508     if (RegionCoverageLtFilter.getNumOccurrences() ||
509         RegionCoverageGtFilter.getNumOccurrences() ||
510         LineCoverageLtFilter.getNumOccurrences() ||
511         LineCoverageGtFilter.getNumOccurrences()) {
512       auto StatFilterer = new CoverageFilters;
513       if (RegionCoverageLtFilter.getNumOccurrences())
514         StatFilterer->push_back(llvm::make_unique<RegionCoverageFilter>(
515             RegionCoverageFilter::LessThan, RegionCoverageLtFilter));
516       if (RegionCoverageGtFilter.getNumOccurrences())
517         StatFilterer->push_back(llvm::make_unique<RegionCoverageFilter>(
518             RegionCoverageFilter::GreaterThan, RegionCoverageGtFilter));
519       if (LineCoverageLtFilter.getNumOccurrences())
520         StatFilterer->push_back(llvm::make_unique<LineCoverageFilter>(
521             LineCoverageFilter::LessThan, LineCoverageLtFilter));
522       if (LineCoverageGtFilter.getNumOccurrences())
523         StatFilterer->push_back(llvm::make_unique<LineCoverageFilter>(
524             RegionCoverageFilter::GreaterThan, LineCoverageGtFilter));
525       Filters.push_back(std::unique_ptr<CoverageFilter>(StatFilterer));
526     }
527
528     for (const auto &File : InputSourceFiles) {
529       SmallString<128> Path(File);
530       if (std::error_code EC = sys::fs::make_absolute(Path)) {
531         errs() << "error: " << File << ": " << EC.message();
532         return 1;
533       }
534       SourceFiles.push_back(Path.str());
535     }
536     return 0;
537   };
538
539   // Parse the object filename
540   if (argc > 1) {
541     StringRef Arg(argv[1]);
542     if (Arg.equals_lower("-help") || Arg.equals_lower("-version")) {
543       cl::ParseCommandLineOptions(2, argv, "LLVM code coverage tool\n");
544       return 0;
545     }
546     ObjectFilename = Arg;
547
548     argv[1] = argv[0];
549     --argc;
550     ++argv;
551   } else {
552     errs() << sys::path::filename(argv[0]) << ": No executable file given!\n";
553     return 1;
554   }
555
556   switch (Cmd) {
557   case Show:
558     return show(argc, argv, commandLineParser);
559   case Report:
560     return report(argc, argv, commandLineParser);
561   }
562   return 0;
563 }
564
565 int CodeCoverageTool::show(int argc, const char **argv,
566                            CommandLineParserType commandLineParser) {
567
568   cl::OptionCategory ViewCategory("Viewing options");
569
570   cl::opt<bool> ShowLineExecutionCounts(
571       "show-line-counts", cl::Optional,
572       cl::desc("Show the execution counts for each line"), cl::init(true),
573       cl::cat(ViewCategory));
574
575   cl::opt<bool> ShowRegions(
576       "show-regions", cl::Optional,
577       cl::desc("Show the execution counts for each region"),
578       cl::cat(ViewCategory));
579
580   cl::opt<bool> ShowBestLineRegionsCounts(
581       "show-line-counts-or-regions", cl::Optional,
582       cl::desc("Show the execution counts for each line, or the execution "
583                "counts for each region on lines that have multiple regions"),
584       cl::cat(ViewCategory));
585
586   cl::opt<bool> ShowExpansions("show-expansions", cl::Optional,
587                                cl::desc("Show expanded source regions"),
588                                cl::cat(ViewCategory));
589
590   cl::opt<bool> ShowInstantiations("show-instantiations", cl::Optional,
591                                    cl::desc("Show function instantiations"),
592                                    cl::cat(ViewCategory));
593
594   cl::opt<bool> NoColors("no-colors", cl::Optional,
595                          cl::desc("Don't show text colors"), cl::init(false),
596                          cl::cat(ViewCategory));
597
598   auto Err = commandLineParser(argc, argv);
599   if (Err)
600     return Err;
601
602   ViewOpts.Colors = !NoColors;
603   ViewOpts.ShowLineNumbers = true;
604   ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 ||
605                            !ShowRegions || ShowBestLineRegionsCounts;
606   ViewOpts.ShowRegionMarkers = ShowRegions || ShowBestLineRegionsCounts;
607   ViewOpts.ShowLineStatsOrRegionMarkers = ShowBestLineRegionsCounts;
608   ViewOpts.ShowExpandedRegions = ShowExpansions;
609   ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
610
611   if (load())
612     return 1;
613
614   if (!Filters.empty()) {
615     // Show functions
616     for (const auto &Function : FunctionMappingRecords) {
617       unsigned MainFileID;
618       if (findMainViewFileID(Function, MainFileID))
619         continue;
620       StringRef SourceFile = Function.Filenames[MainFileID];
621       auto mainView = createSourceFileView(SourceFile, Function, true);
622       if (!mainView) {
623         ViewOpts.colored_ostream(outs(), raw_ostream::RED)
624             << "warning: Could not read coverage for '" << Function.Name
625             << " from " << SourceFile;
626         outs() << "\n";
627         continue;
628       }
629       ViewOpts.colored_ostream(outs(), raw_ostream::CYAN)
630           << Function.Name << " from " << SourceFile << ":";
631       outs() << "\n";
632       mainView->render(outs(), /*WholeFile=*/false);
633       if (FunctionMappingRecords.size() > 1)
634         outs() << "\n";
635     }
636     return 0;
637   }
638
639   // Show files
640   bool ShowFilenames = SourceFiles.size() != 1;
641
642   if (SourceFiles.empty())
643     // Get the source files from the function coverage mapping
644     for (StringRef Filename : getUniqueFilenames(FunctionMappingRecords))
645       SourceFiles.push_back(Filename);
646
647   for (const auto &SourceFile : SourceFiles) {
648     auto mainView = createSourceFileView(SourceFile, FunctionMappingRecords);
649     if (!mainView) {
650       ViewOpts.colored_ostream(outs(), raw_ostream::RED)
651           << "warning: The file '" << SourceFile << "' isn't covered.";
652       outs() << "\n";
653       continue;
654     }
655
656     if (ShowFilenames) {
657       ViewOpts.colored_ostream(outs(), raw_ostream::CYAN) << SourceFile << ":";
658       outs() << "\n";
659     }
660     mainView->render(outs(), /*Wholefile=*/true);
661     if (SourceFiles.size() > 1)
662       outs() << "\n";
663   }
664
665   return 0;
666 }
667
668 int CodeCoverageTool::report(int argc, const char **argv,
669                              CommandLineParserType commandLineParser) {
670   cl::opt<bool> NoColors("no-colors", cl::Optional,
671                          cl::desc("Don't show text colors"), cl::init(false));
672
673   auto Err = commandLineParser(argc, argv);
674   if (Err)
675     return Err;
676
677   ViewOpts.Colors = !NoColors;
678
679   if (load())
680     return 1;
681
682   CoverageSummary Summarizer;
683   Summarizer.createSummaries(FunctionMappingRecords);
684   CoverageReport Report(ViewOpts, Summarizer);
685   if (SourceFiles.empty() && Filters.empty()) {
686     Report.renderFileReports(llvm::outs());
687     return 0;
688   }
689
690   Report.renderFunctionReports(llvm::outs());
691   return 0;
692 }
693
694 int show_main(int argc, const char **argv) {
695   CodeCoverageTool Tool;
696   return Tool.run(CodeCoverageTool::Show, argc, argv);
697 }
698
699 int report_main(int argc, const char **argv) {
700   CodeCoverageTool Tool;
701   return Tool.run(CodeCoverageTool::Report, argc, argv);
702 }