Fix error output handling on Windows

This broke in 33f7b7755db0ed5cad1b686b7616183927c72ab1, as the new code
path was not handling this case correctly.

Fixes #8402.

PiperOrigin-RevId: 249201968
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
index 3aeff9b..b199335 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -83,7 +83,6 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
@@ -1695,44 +1694,17 @@
         // executed spawn.
         dotDContents = getDotDContents(spawnResults.get(0));
       } catch (ExecException e) {
-        if (featureConfiguration.isEnabled(CppRuleClasses.PARSE_SHOWINCLUDES)) {
-          closeSuppressed(e, spawnExecutionContext.getFileOutErr());
-        }
+        copyTempOutErrToActionOutErr();
         throw e.toActionExecutionException(
             "C++ compilation of rule '" + getOwner().getLabel() + "'",
             actionExecutionContext.getVerboseFailures(),
             CppCompileAction.this);
       } catch (InterruptedException e) {
-        if (featureConfiguration.isEnabled(CppRuleClasses.PARSE_SHOWINCLUDES)) {
-          closeSuppressed(e, spawnExecutionContext.getFileOutErr());
-        }
+        copyTempOutErrToActionOutErr();
         throw e;
       }
 
-      // If parse_showincludes feature is enabled, instead of parsing dotD file we parse the
-      // output of cl.exe caused by /showIncludes option.
-      if (featureConfiguration.isEnabled(CppRuleClasses.PARSE_SHOWINCLUDES)) {
-        try {
-          FileOutErr tempOutErr = spawnExecutionContext.getFileOutErr();
-          FileOutErr outErr = actionExecutionContext.getFileOutErr();
-          tempOutErr.close();
-          if (tempOutErr.hasRecordedStdout()) {
-            try (InputStream in = tempOutErr.getOutputPath().getInputStream()) {
-              ByteStreams.copy(
-                  in,
-                  showIncludesFilterForStdout.getFilteredOutputStream(outErr.getOutputStream()));
-            }
-          }
-          if (tempOutErr.hasRecordedStderr()) {
-            try (InputStream in = tempOutErr.getErrorPath().getInputStream()) {
-              ByteStreams.copy(
-                  in, showIncludesFilterForStderr.getFilteredOutputStream(outErr.getErrorStream()));
-            }
-          }
-        } catch (IOException e) {
-          throw printIOExceptionAndConvertToActionExecutionException(actionExecutionContext, e);
-        }
-      }
+      copyTempOutErrToActionOutErr();
 
       ensureCoverageNotesFilesExist(actionExecutionContext);
 
@@ -1784,11 +1756,30 @@
       return ActionContinuationOrResult.of(ActionResult.create(spawnResults));
     }
 
-    private void closeSuppressed(Exception e, Closeable closeable) {
-      try {
-        closeable.close();
-      } catch (IOException e2) {
-        e.addSuppressed(e2);
+    private void copyTempOutErrToActionOutErr() throws ActionExecutionException {
+      // If parse_showincludes feature is enabled, instead of parsing dotD file we parse the
+      // output of cl.exe caused by /showIncludes option.
+      if (featureConfiguration.isEnabled(CppRuleClasses.PARSE_SHOWINCLUDES)) {
+        try {
+          FileOutErr tempOutErr = spawnExecutionContext.getFileOutErr();
+          FileOutErr outErr = actionExecutionContext.getFileOutErr();
+          tempOutErr.close();
+          if (tempOutErr.hasRecordedStdout()) {
+            try (InputStream in = tempOutErr.getOutputPath().getInputStream()) {
+              ByteStreams.copy(
+                  in,
+                  showIncludesFilterForStdout.getFilteredOutputStream(outErr.getOutputStream()));
+            }
+          }
+          if (tempOutErr.hasRecordedStderr()) {
+            try (InputStream in = tempOutErr.getErrorPath().getInputStream()) {
+              ByteStreams.copy(
+                  in, showIncludesFilterForStderr.getFilteredOutputStream(outErr.getErrorStream()));
+            }
+          }
+        } catch (IOException e) {
+          throw printIOExceptionAndConvertToActionExecutionException(actionExecutionContext, e);
+        }
       }
     }
   }
diff --git a/src/test/py/bazel/bazel_windows_cpp_test.py b/src/test/py/bazel/bazel_windows_cpp_test.py
index ee20860..a7a97de 100644
--- a/src/test/py/bazel/bazel_windows_cpp_test.py
+++ b/src/test/py/bazel/bazel_windows_cpp_test.py
@@ -504,5 +504,23 @@
     ])
     self.AssertExitCode(exit_code, 0, stderr)
 
+  def testCppErrorShouldBeVisible(self):
+    self.ScratchFile('WORKSPACE')
+    self.ScratchFile('BUILD', [
+        'cc_binary(',
+        '  name = "bad",',
+        '  srcs = ["bad.cc"],',
+        ')',
+    ])
+    self.ScratchFile('bad.cc', [
+        'int main(int argc, char** argv) {',
+        '  this_is_an_error();',
+        '}',
+    ])
+    exit_code, stdout, stderr = self.RunBazel(['build', '//:bad'])
+    self.AssertExitCode(exit_code, 1, stderr)
+    self.assertIn('this_is_an_error', ''.join(stdout))
+
+
 if __name__ == '__main__':
   unittest.main()