[flang][driver] Fix reading from stdin when using `-test-io`
authorAndrzej Warzynski <andrzej.warzynski@arm.com>
Thu, 4 Feb 2021 16:23:42 +0000 (16:23 +0000)
committerAndrzej Warzynski <andrzej.warzynski@arm.com>
Thu, 4 Feb 2021 16:51:59 +0000 (16:51 +0000)
This patch adds logic in the InputOutputTestAction frontend action for
reading input from stdin. Without this patch the following fails:
```
    flang-new -fc1 -test-io -
```

The implementation of `InputOutputTestAction` is cleaned-up and a test
for reading from stdin is added.

Note that there's a difference between `-test-io` and e.g. `-E` in terms
of file I/O. The frontend action for the former handles all file I/O on
it's own. Conversely, the action corresponding to -E relies on the
prescanner API to handle this.

Currently we can't test reading from stdin for `flang-new -`. In this
case `libclangDriver` assumes `-x -c`. This in turn leads to `flang-new
-cc1`, which is not supported.

flang/lib/Frontend/FrontendActions.cpp
flang/test/Flang-Driver/input-from-stdin.f90 [new file with mode: 0644]

index 61e4a7d..24c4ba5 100644 (file)
@@ -50,31 +50,36 @@ bool PrescanAction::BeginSourceFileAction(CompilerInstance &c1) {
 }
 
 void InputOutputTestAction::ExecuteAction() {
-  // Get the name of the file from FrontendInputFile current.
-  std::string path{GetCurrentFileOrBufferName()};
+  CompilerInstance &ci = instance();
+
+  // Create a stream for errors
   std::string buf;
   llvm::raw_string_ostream error_stream{buf};
-  bool binaryMode = true;
 
-  // Set/store input file info into CompilerInstance.
-  CompilerInstance &ci = instance();
+  // Read the input file
   Fortran::parser::AllSources &allSources{ci.allSources()};
+  std::string path{GetCurrentFileOrBufferName()};
   const Fortran::parser::SourceFile *sf;
-  sf = allSources.Open(path, error_stream, std::optional<std::string>{"."s});
+  if (path == "-")
+    sf = allSources.ReadStandardInput(error_stream);
+  else
+    sf = allSources.Open(path, error_stream, std::optional<std::string>{"."s});
   llvm::ArrayRef<char> fileContent = sf->content();
 
-  // Output file descriptor to receive the content of input file.
+  // Output file descriptor to receive the contents of the input file.
   std::unique_ptr<llvm::raw_ostream> os;
 
-  // Do not write on the output file if using outputStream_.
-  if (ci.IsOutputStreamNull()) {
+  // Copy the contents from the input file to the output file
+  if (!ci.IsOutputStreamNull()) {
+    // An output stream (outputStream_) was set earlier
+    ci.WriteOutputStream(fileContent.data());
+  } else {
+    // No pre-set output stream - create an output file
     os = ci.CreateDefaultOutputFile(
-        binaryMode, GetCurrentFileOrBufferName(), "txt");
+        /*binary=*/true, GetCurrentFileOrBufferName(), "txt");
     if (!os)
       return;
     (*os) << fileContent.data();
-  } else {
-    ci.WriteOutputStream(fileContent.data());
   }
 }
 
diff --git a/flang/test/Flang-Driver/input-from-stdin.f90 b/flang/test/Flang-Driver/input-from-stdin.f90
new file mode 100644 (file)
index 0000000..05f99a3
--- /dev/null
@@ -0,0 +1,44 @@
+! Verify that reading from stdin works as expected
+
+! REQUIRES: new-flang-driver
+
+!--------------------------
+! FLANG DRIVER (flang-new)
+!--------------------------
+! TODO: Add support for `flang-new -`
+! Currently `bin/flang-new  -E -` defaults to `-x c` and e.g. F90 is not allowed
+! in `-x <input-type>` (see `clang::driver::types::canTypeBeUserSpecified` in
+! Types.cpp)
+
+!---------------------------------------
+! FLANG FRONTEND DRIVER (flang-new -fc1)
+!---------------------------------------
+! Test `-E` - for the corresponding frontend actions the driver relies on the prescanner API to handle file I/O
+! RUN: cat %s | flang-new -fc1 -E | FileCheck %s --check-prefix=PP-NOT-DEFINED
+! RUN: cat %s | flang-new -fc1 -DNEW -E | FileCheck %s --check-prefix=PP-DEFINED
+
+! Test `-test-io` - for the corresponding frontend action (`InputOutputTestAction`) the driver handles the file I/O on its own
+! the corresponding action (`PrintPreprocessedAction`)
+! RUN: cat %s | flang-new -fc1 -test-io | FileCheck %s --check-prefix=IO --match-full-lines
+! RUN: cat %s | flang-new -fc1 -DNEW -test-io | FileCheck %s --check-prefix=IO --match-full-lines
+
+!-------------------------
+! EXPECTED OUTPUT for `-E`
+!-------------------------
+! PP-NOT-DEFINED: program b
+! PP-DEFINED: program a
+
+!-------------------------------
+! EXPECTED OUTPUT for `-test-io`
+!-------------------------------
+! IO: #ifdef NEW
+! IO-NEXT:   Program A
+! IO-NEXT: #else
+! IO-NEXT:   Program B
+! IO-NEXT: #endif
+
+#ifdef NEW
+  Program A
+#else
+  Program B
+#endif