Index: llvm/trunk/docs/CommandGuide/llvm-cov.rst =================================================================== --- llvm/trunk/docs/CommandGuide/llvm-cov.rst +++ llvm/trunk/docs/CommandGuide/llvm-cov.rst @@ -167,14 +167,14 @@ SYNOPSIS ^^^^^^^^ -:program:`llvm-cov show` [*options*] -instr-profile *PROFILE* *BIN* [*SOURCES*] +:program:`llvm-cov show` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] [*SOURCES*] DESCRIPTION ^^^^^^^^^^^ -The :program:`llvm-cov show` command shows line by line coverage of a binary -*BIN* using the profile data *PROFILE*. It can optionally be filtered to only -show the coverage for the files listed in *SOURCES*. +The :program:`llvm-cov show` command shows line by line coverage of the +binaries *BIN*,... using the profile data *PROFILE*. It can optionally be +filtered to only show the coverage for the files listed in *SOURCES*. To use :program:`llvm-cov show`, you need a program that is compiled with instrumentation to emit profile and coverage data. To build such a program with @@ -183,7 +183,7 @@ to the link stage to make sure the necessary runtime libraries are linked in. The coverage information is stored in the built executable or library itself, -and this is what you should pass to :program:`llvm-cov show` as the *BIN* +and this is what you should pass to :program:`llvm-cov show` as a *BIN* argument. The profile data is generated by running this instrumented program normally. When the program exits it will write out a raw profile file, typically called ``default.profraw``, which can be converted to a format that @@ -292,14 +292,14 @@ SYNOPSIS ^^^^^^^^ -:program:`llvm-cov report` [*options*] -instr-profile *PROFILE* *BIN* [*SOURCES*] +:program:`llvm-cov report` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] [*SOURCES*] DESCRIPTION ^^^^^^^^^^^ -The :program:`llvm-cov report` command displays a summary of the coverage of a -binary *BIN* using the profile data *PROFILE*. It can optionally be filtered to -only show the coverage for the files listed in *SOURCES*. +The :program:`llvm-cov report` command displays a summary of the coverage of +the binaries *BIN*,... using the profile data *PROFILE*. It can optionally be +filtered to only show the coverage for the files listed in *SOURCES*. If no source files are provided, a summary line is printed for each file in the coverage data. If any files are provided, summaries are shown for each function @@ -332,13 +332,13 @@ SYNOPSIS ^^^^^^^^ -:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* +:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] DESCRIPTION ^^^^^^^^^^^ The :program:`llvm-cov export` command exports regions, functions, expansions, -and summaries of the coverage of a binary *BIN* using the profile data +and summaries of the coverage of the binaries *BIN*,... using the profile data *PROFILE* as JSON. For information on compiling programs for coverage and generating profile data, Index: llvm/trunk/test/tools/llvm-cov/load-multiple-objects.test =================================================================== --- llvm/trunk/test/tools/llvm-cov/load-multiple-objects.test +++ llvm/trunk/test/tools/llvm-cov/load-multiple-objects.test @@ -0,0 +1,11 @@ +// RUN: llvm-profdata merge %S/Inputs/multiple-files.proftext %S/Inputs/highlightedRanges.profdata -o %t.profdata + +// RUN: llvm-cov report -object %S/Inputs/multiple-files.covmapping -instr-profile %t.profdata | FileCheck %s -check-prefix=OBJ1 + +// RUN: llvm-cov report %S/Inputs/multiple-files.covmapping -object %S/Inputs/highlightedRanges.covmapping -instr-profile %t.profdata | FileCheck %s -check-prefixes=OBJ1,OBJ2 + +// OBJ2: showHighlightedRanges.cpp +// OBJ1: f2.c +// OBJ1: f4.c +// OBJ1: f3.c +// OBJ1: f1.c Index: llvm/trunk/test/tools/llvm-cov/universal-binary.c =================================================================== --- llvm/trunk/test/tools/llvm-cov/universal-binary.c +++ llvm/trunk/test/tools/llvm-cov/universal-binary.c @@ -12,4 +12,4 @@ // WRONG-ARCH: Failed to load coverage // RUN: not llvm-cov report -instr-profile %t.profdata 2>&1 | FileCheck --check-prefix=MISSING-BINARY %s -// MISSING-BINARY: 1 positional argument: See: +// MISSING-BINARY: No filenames specified! Index: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp =================================================================== --- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp +++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp @@ -116,7 +116,7 @@ int export_(int argc, const char **argv, CommandLineParserType commandLineParser); - std::string ObjectFilename; + std::vector ObjectFilenames; CoverageViewOptions ViewOpts; CoverageFiltersMatchAll Filters; @@ -325,13 +325,15 @@ } std::unique_ptr CodeCoverageTool::load() { - if (modifiedTimeGT(ObjectFilename, PGOFilename)) - warning("profile data may be out of date - object is newer", - ObjectFilename); + for (StringRef ObjectFilename : ObjectFilenames) + if (modifiedTimeGT(ObjectFilename, PGOFilename)) + warning("profile data may be out of date - object is newer", + ObjectFilename); auto CoverageOrErr = - CoverageMapping::load(ObjectFilename, PGOFilename, CoverageArch); + CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArch); if (Error E = CoverageOrErr.takeError()) { - error("Failed to load coverage: " + toString(std::move(E)), ObjectFilename); + error("Failed to load coverage: " + toString(std::move(E)), + join(ObjectFilenames.begin(), ObjectFilenames.end(), ", ")); return nullptr; } auto Coverage = std::move(CoverageOrErr.get()); @@ -484,9 +486,12 @@ } int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { - cl::opt ObjectFilename( - cl::Positional, cl::Required, cl::location(this->ObjectFilename), - cl::desc("Covered executable or object file.")); + cl::opt CovFilename( + cl::Positional, cl::desc("Covered executable or object file.")); + + cl::list CovFilenames( + "object", cl::desc("Coverage executable or object file"), cl::ZeroOrMore, + cl::CommaSeparated); cl::list InputSourceFiles( cl::Positional, cl::desc(""), cl::ZeroOrMore); @@ -568,6 +573,15 @@ ViewOpts.Debug = DebugDump; CompareFilenamesOnly = FilenameEquivalence; + if (!CovFilename.empty()) + ObjectFilenames.emplace_back(CovFilename); + for (const std::string &Filename : CovFilenames) + ObjectFilenames.emplace_back(Filename); + if (ObjectFilenames.empty()) { + error("No filenames specified!"); + ::exit(1); + } + ViewOpts.Format = Format; switch (ViewOpts.Format) { case CoverageViewOptions::OutputFormat::Text: