Index: test/tools/llvm-cov/cov_dir.cpp =================================================================== --- test/tools/llvm-cov/cov_dir.cpp +++ test/tools/llvm-cov/cov_dir.cpp @@ -0,0 +1,7 @@ +//RUN: rm -rf %t +//RUN: mkdir -p %t/a/b/ +//RUN: echo "" > %t/a/b/c.tmp +//RUN: echo "" > %t/a/d.tmp +//RUN: llvm-cov show /dev/null -instr-profile=/dev/null -dump-input-file-list %t | FileCheck %s +//CHECK-DAG: {{.*}}c.tmp +//CHECK-DAG: {{.*}}d.tmp Index: tools/llvm-cov/CodeCoverage.cpp =================================================================== --- tools/llvm-cov/CodeCoverage.cpp +++ tools/llvm-cov/CodeCoverage.cpp @@ -70,6 +70,9 @@ /// \brief Load the coverage mapping data. Return true if an error occured. std::unique_ptr load(); + /// \brief Collects all source files recursively inside the directory. + void collectSourceFiles(StringRef Path); + int run(Command Cmd, int argc, const char **argv); typedef llvm::function_ref CommandLineParserType; @@ -90,6 +93,7 @@ bool CompareFilenamesOnly; StringMap RemappedFilenames; std::string CoverageArch; + bool DumpFileNames; private: std::vector CollectedPaths; @@ -249,6 +253,34 @@ return Coverage; } +void CodeCoverageTool::collectSourceFiles(StringRef Path) { + if (CompareFilenamesOnly) { + addCollectedPath(Path.str()); + return; + } + llvm::sys::fs::file_status Status; + llvm::sys::fs::status(Path, Status); + if (llvm::sys::fs::exists(Status)) { + // If it's a source file, collect it. + if (llvm::sys::fs::is_regular_file(Status)) { + addCollectedPath(Path.str()); + return; + } + if (llvm::sys::fs::is_directory(Status)) { + std::error_code EC; + // Collect all source files within this directory by iterating + // recursively. + for (llvm::sys::fs::recursive_directory_iterator File(Path, EC), FileEnd; + File != FileEnd && !EC; File.increment(EC)) { + if (llvm::sys::fs::is_regular_file(File->path())) { + addCollectedPath(File->path()); + } + } + } + } else + errs() << "Error: Can't access: " << Path.str().c_str() << "\n"; +} + int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { cl::opt ObjectFilename( cl::Positional, cl::Required, cl::location(this->ObjectFilename), @@ -321,10 +353,15 @@ "use-color", cl::desc("Emit colored output (default=autodetect)"), cl::init(cl::BOU_UNSET)); + cl::opt DumpInputFileList( + "dump-input-file-list", cl::Optional, + cl::desc("Dump just filenames traversing into the directories.")); + auto commandLineParser = [&, this](int argc, const char **argv) -> int { cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n"); ViewOpts.Debug = DebugDump; CompareFilenamesOnly = FilenameEquivalence; + DumpFileNames = DumpInputFileList; ViewOpts.Format = Format; switch (ViewOpts.Format) { @@ -379,8 +416,15 @@ errs() << "error: " << File << ": " << EC.message(); return 1; } - addCollectedPath(Path.str()); + collectSourceFiles(Path.str()); } + + if (DumpFileNames) { + for (StringRef SF : SourceFiles) + outs() << SF << "\n"; + return 0; + } + return 0; }; @@ -432,6 +476,8 @@ if (Err) return Err; + if (DumpFileNames) + return 0; ViewOpts.ShowLineNumbers = true; ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 || !ShowRegions || ShowBestLineRegionsCounts; @@ -527,6 +573,8 @@ if (Err) return Err; + if (DumpFileNames) + return 0; auto Coverage = load(); if (!Coverage) return 1;