[PATCH] D87989: [Flang][Driver] Add InputOutputTest frontend action with new -test-IO flag
Andrzej Warzynski via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 22 10:19:54 PDT 2020
awarzynski added a comment.
@CarolineConcatto , thank you for this patch! It implements some really important functionality and IMO the overall structure is solid.
I've left quite a few comments, but mostly nits and suggestions for more detailed comments. There's a few, but it's a relatively big patch :)
One suggestion - IMO this patch first and foremost creates the scaffolding for writing frontend actions. The `test-IO` flag is only really there to facilitate testing. Perhaps it's worth updating the commit message to reflect that? I would definitely like to see a bit more emphasis on the fact that this patch introduces the necessary APIs for reading and writing files. For me that's the key functionality here.
Also, I tested this patch and currently `-test-IO` is listed together with other `clang` options (check `clang --help-hidden`). Please, could you fix that?
================
Comment at: clang/include/clang/Driver/Options.td:3514
+//===----------------------------------------------------------------------===//
+def TEST_IO : Flag<["-"], "test-IO">, Flags<[HelpHidden, FlangOption, FC1Option]>,Group<Action_Group>,
+HelpText<"Only run the InputOutputTest action">;
----------------
I think that `test-io` would be more consistent with other options in the file.
================
Comment at: clang/include/clang/Driver/Options.td:3515
+def TEST_IO : Flag<["-"], "test-IO">, Flags<[HelpHidden, FlangOption, FC1Option]>,Group<Action_Group>,
+HelpText<"Only run the InputOutputTest action">;
+
----------------
I would help to make this a bit more specific. What about: `Run the InputOuputTest action. Use for development and testing only`?
================
Comment at: clang/lib/Driver/ToolChains/Flang.cpp:39-40
} else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
+ CmdArgs.push_back("-triple");
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
if (JA.getType() == types::TY_Nothing) {
----------------
It would be helpful to have a note that explains this change. Perhaps something like this:
```
// TODO: Note that eventually all actions will require a triple (e.g. `-triple aarch64-unknown-linux-gnu`). However, `-triple` is currently not supported by `flang-new -fc1`, so we only add it to actions that we don't support/execute just yet.
```
Probably above line 33. What do you think?
================
Comment at: clang/lib/Driver/Types.cpp:329
if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) ||
+ DAL.getLastArg(options::OPT_TEST_IO) ||
DAL.getLastArg(options::OPT__SLASH_EP) ||
----------------
This should probably be the last option here (as it's the latest to be added). Also, worth adding a comment about, e.g.:
```
-test-io is used by Flang to run InputOutputTest action
```
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:26
+ /// The Fortran file manager.
+ std::shared_ptr<Fortran::parser::AllSources> allSources_;
----------------
[nit] Forrtran or Flang?
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:33
+ /// Holds the name of the output file.
+ /// Helps to go through the list when working with the outputFiles_
+ struct OutputFile {
----------------
[nit] 'the outputFiles_' -> 'outputFiles_'
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:40-42
+ /// If the output doesn't support seeking (terminal, pipe), we switch
+ /// the stream to a buffer_ostream. These are the buffer and the original
+ /// stream.
----------------
[nit]
```
/// If the output doesn't support seeking (terminal, pipe), we switch
/// the stream to a buffer_ostream. These are the buffer and the original
/// stream.
```
vvv
```
/// Output stream that doesn't support seeking (e.g. terminal, pipe). This stream is normally wrapped
/// in buffer_ostream before being passed to users (e.g. via CreateOutputFile).
```
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:48
+
+ /// Force an output buffer.
+ std::unique_ptr<llvm::raw_pwrite_stream> outputStream_;
----------------
I think that:
```
This field holds the output stream provided by the user. Normally, users of CompilerInstance will call CreateOutputFile to obtain/create an output stream. If they want to provide their own output stream, this field will facilitate this. It is optional and will normally be just a nullptr.
```
would be a bit more informative :)
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:65
+ /// setInvocation - Replace the current invocation.
+ void SetInvocation(std::shared_ptr<CompilerInvocation> value);
----------------
[nit] Delete
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:68
+
+ /// Return the current source manager.
+ Fortran::parser::AllSources &GetAllSources() const { return *allSources_; }
----------------
[nit] There is no source manager here.
It's probably worth decorating everything related to `AllSources` with:
```
/// }
/// @name File manager
/// {
```
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:73
+
+ /// @name High-Level Operations
+ /// {
----------------
Missing `/// }`
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:76
+
+ /// ExecuteAction - Execute the provided action against the compiler's
+ /// CompilerInvocation object.
----------------
[nit] No need to repeat the name of the method/member variable in comments. Same for the rest of the patch.
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:146-147
+
+ /// Has a function to create a new output file and add it to the list of
+ /// tracked output files.
+ ///
----------------
Remove `Has a`? Also, could you expand and clarify the differences between this method and the one below? Ta!
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:158
+ /// \param error [out] - On failure, the error.
+ /// \param extension - The extension to use for derived output names.
+ /// \param binary - The mode to open the file in.
----------------
This argument is after `binary`
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:164
+ CreateOutputFile(llvm::StringRef outputPath, std::error_code &error,
+ bool binary, llvm::StringRef inFile,
+ llvm::StringRef extension, std::string *resultPathName);
----------------
This argument is not documented.
================
Comment at: flang/include/flang/Frontend/CompilerInstance.h:171-177
+ // OutputStream is private and its contenct cannot be checked outside
+ // CompilerInstance.
+ bool NullOutputStream() {
+ if (outputStream_ == nullptr)
+ return true;
+ return false;
+ }
----------------
[nit] I think that the comment is redundant - this is clear from the implementation and it is a fairly standard C++ idiom (e.g. accessors).
It's a good practice to use proper questions to name functions like this one, e.g. `IsOutputStreamNull`. Then, both possible return values answer this question. Sorry, I couldn't find a link that would document this.
Also, this would be simpler, yet semantically equivalent:
```
bool IsOutputStreamNull() {return (outputStream_ == nullptr);}
```
================
Comment at: flang/include/flang/Frontend/FrontendAction.h:85
+
+ /// Set the source manager's main input file, and run the action.
+ llvm::Error Execute();
----------------
AFAIK, there is no source manager - only file manager.
================
Comment at: flang/include/flang/Frontend/FrontendOptions.h:19-21
+ // This is temporary solution
+ // Avoids Action = PrintPreprocessedInput as option 0
+ DummyAction = 0,
----------------
I recommend that this is replaced with:
```
InvalidAction = 0,
```
I think that this requires no comments.
================
Comment at: flang/include/flang/Frontend/FrontendOptions.h:111
+ const llvm::MemoryBuffer *GetBuffer() const {
+ assert(IsBuffer());
+ return buffer_;
----------------
Add message, e.g.
```
assert(IsBuffer() && "Requested buffer_, but it is empty!");
```
================
Comment at: flang/lib/Frontend/CompilerInstance.cpp:26
+CompilerInstance::~CompilerInstance() {
+ assert(OutputFiles.empty() && "Still output files in flight?");
+}
----------------
`outputFiles_`?
================
Comment at: flang/lib/Frontend/CompilerInstance.cpp:94-100
+ // Flushes the stream
+ if (!binary || os->supportsSeeking())
+ return std::move(os);
+ auto b = std::make_unique<llvm::buffer_ostream>(*os);
+ assert(!nonSeekStream_);
+ nonSeekStream_ = std::move(os);
+
----------------
The stream is not flushed until it's destructor is called. This happens elsewhere. Here we just return the stream corresponding to the output file.
Since there's a distinction between seekable and non-seekable streams, I'd be tempted to split this as follows:
```
// Return the stream corresponding to the output file. For non-seekable streams, wrap it in llvm::buffer_ostream first.
if (!binary || os->supportsSeeking())
return std::move(os);
assert(!nonSeekStream_ && "The non-seek stream has already been set!");
auto b = std::make_unique<llvm::buffer_ostream>(*os);
nonSeekStream_ = std::move(os);
return std::move(b);
```
================
Comment at: flang/lib/Frontend/FrontendActions.cpp:19
+
+ // Get the name of the file from FrontendInputFile current
+ std::string path{GetCurrentFileOrBufferName()};
----------------
[nit] Get the name of the current file from FrontendInputFile
================
Comment at: flang/test/Flang-Driver/driver-help-hidden.f90:7
+! RUN: %flang-new --help-hidden 2>&1 | FileCheck %s
+! RUN: not %flang-new -help-hidden 2>&1 | FileCheck %s --check-prefix=ERROR
+
----------------
[nit] Both `--check-prefix=ERROR` and `--check-prefix=ERROR-HIDDEN` check the `help-hidden` flang`. Perhaps `--check-prefix=ERROR-FLANG-NEW` and `--check-prefix=ERROR-FLANG-NEW-FC1` would make the difference between the two cases more obvious?
================
Comment at: flang/test/Flang-Driver/driver-help-hidden.f90:27
+!-------------------------------------------------------------
+! EXPECTED OUTPUT FOR FLANG FRONTEND DRIVER (flang-new -fc1)
+!-------------------------------------------------------------
----------------
This is the expected error for both `flang-new` (compiler driver) and `flang-new -fc1` (the frontend driver).
================
Comment at: flang/test/Flang-Driver/emit-obj.f90:2
! RUN: not %flang-new %s 2>&1 | FileCheck %s --check-prefix=ERROR-IMPLICIT
-! RUN: not %flang-new -emit-obj %s 2>&1 | FileCheck %s --check-prefix=ERROR-EXPLICIT
! RUN: not %flang-new -fc1 -emit-obj %s 2>&1 | FileCheck %s --check-prefix=ERROR-FC1
----------------
Why is this line deleted? `flang-new -emit-obj` should still fail, right?
================
Comment at: flang/test/Flang-Driver/emit-obj.f90:12
! ERROR-IMPLICIT: error: unknown argument: '-emit-obj'
-! ERROR-IMPLICIT: error: unknown argument: '-o'
-
-! ERROR-EXPLICIT: error: unknown argument: '-o'
+! ERROR-IMPLICIT-NOT: error: unknown argument: '-o'
----------------
I'd be tempted just to delete this line - we have tests elsewhere to show that `-o` is indeed supported.
================
Comment at: flang/test/Frontend/multiple-input-files.f90:1
+! RUN: rm -rf %S/multiple-input-files.txt %S/Inputs/empty-file.txt
+
----------------
I think that this test will be much more interesting and useful if `empty-file.f90` is not empty :)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D87989/new/
https://reviews.llvm.org/D87989
More information about the cfe-commits
mailing list