Reapply "[llvm-cov] Add an -output-dir option for the show sub-command""

Passing -output-dir path/to/dir to llvm-cov show creates path/to/dir if
it doesn't already exist, and prints reports into that directory.

In function view mode, all views are written into
path/to/dir/functions.$EXTENSION. In file view mode, all views are
written into path/to/dir/coverage/$PATH.$EXTENSION.

Changes since the initial commit:

- Avoid accidentally closing stdout twice.

llvm-svn: 273985
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 04901a2..0943ceb 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -406,6 +406,12 @@
                  clEnumValEnd),
       cl::init(CoverageViewOptions::OutputFormat::Text));
 
+  cl::opt<std::string> ShowOutputDirectory(
+      "output-dir", cl::init(""),
+      cl::desc("Directory in which coverage information is written out"));
+  cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"),
+                                 cl::aliasopt(ShowOutputDirectory));
+
   auto Err = commandLineParser(argc, argv);
   if (Err)
     return Err;
@@ -418,6 +424,14 @@
   ViewOpts.ShowExpandedRegions = ShowExpansions;
   ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
   ViewOpts.ShowFormat = ShowFormat;
+  ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
+
+  if (ViewOpts.ShowOutputDirectory != "") {
+    if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
+      error("Could not create output directory!", E.message());
+      return 1;
+    }
+  }
 
   auto Coverage = load();
   if (!Coverage)
@@ -436,8 +450,17 @@
             << "\n";
         continue;
       }
-      mainView->print(outs(), /*WholeFile=*/false, /*ShowSourceName=*/true);
-      outs() << "\n";
+
+      auto OSOrErr =
+          mainView->createOutputFile("functions", /*InToplevel=*/true);
+      if (Error E = OSOrErr.takeError()) {
+        handleAllErrors(OSOrErr.takeError(),
+                        [&](const ErrorInfoBase &EI) { error(EI.message()); });
+        return 1;
+      }
+      auto OS = std::move(OSOrErr.get());
+      mainView->print(*OS.get(), /*WholeFile=*/false, /*ShowSourceName=*/true);
+      mainView->closeOutputFile(std::move(OS));
     }
     return 0;
   }
@@ -459,10 +482,16 @@
       continue;
     }
 
-    mainView->print(outs(), /*Wholefile=*/true,
+    auto OSOrErr = mainView->createOutputFile(SourceFile, /*InToplevel=*/false);
+    if (Error E = OSOrErr.takeError()) {
+      handleAllErrors(OSOrErr.takeError(),
+                      [&](const ErrorInfoBase &EI) { error(EI.message()); });
+      return 1;
+    }
+    auto OS = std::move(OSOrErr.get());
+    mainView->print(*OS.get(), /*Wholefile=*/true,
                     /*ShowSourceName=*/ShowFilenames);
-    if (SourceFiles.size() > 1)
-      outs() << "\n";
+    mainView->closeOutputFile(std::move(OS));
   }
 
   return 0;