diff --git a/flang/include/flang/Frontend/FrontendAction.h b/flang/include/flang/Frontend/FrontendAction.h --- a/flang/include/flang/Frontend/FrontendAction.h +++ b/flang/include/flang/Frontend/FrontendAction.h @@ -39,6 +39,12 @@ /// By default it returns true if a compiler error occurred. virtual bool ShouldEraseOutputFiles(); + /// Callback at the start of processing a single input. + /// + /// \return True on success; on failure ExecutionAction() and + /// EndSourceFileAction() will not be called. + virtual bool BeginSourceFileAction(CompilerInstance &ci) { return true; } + /// @} public: @@ -76,7 +82,7 @@ /// @} /// @name Public Action Interface - /// @} + /// @{ /// Prepare the action for processing the input file \p input. /// diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h --- a/flang/include/flang/Frontend/FrontendActions.h +++ b/flang/include/flang/Frontend/FrontendActions.h @@ -21,15 +21,23 @@ void ExecuteAction() override; }; -class PrintPreprocessedAction : public FrontendAction { +class EmitObjAction : public FrontendAction { void ExecuteAction() override; }; -class ParseSyntaxOnlyAction : public FrontendAction { +//===----------------------------------------------------------------------===// +// Prescan Actions +//===----------------------------------------------------------------------===// +class PrescanAction : public FrontendAction { void ExecuteAction() override; + bool BeginSourceFileAction(CompilerInstance &ci) override; }; -class EmitObjAction : public FrontendAction { +class PrintPreprocessedAction : public PrescanAction { + void ExecuteAction() override; +}; + +class ParseSyntaxOnlyAction : public PrescanAction { void ExecuteAction() override; }; diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp --- a/flang/lib/Frontend/CompilerInstance.cpp +++ b/flang/lib/Frontend/CompilerInstance.cpp @@ -148,12 +148,6 @@ // Run the frontend action `act` for every input file. for (const FrontendInputFile &fif : frontendOpts().inputs_) { if (act.BeginSourceFile(*this, fif)) { - // Switch between fixed and free form format based on the input file - // extension. Ideally we should have all Fortran options set before - // entering this loop (i.e. processing any input files). However, we - // can't decide between fixed and free form based on the file extension - // earlier than this. - invoc.fortranOpts().isFixedForm = fif.IsFixedForm(); if (llvm::Error err = act.Execute()) { consumeError(std::move(err)); } diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -35,10 +35,17 @@ assert(!realInput.IsEmpty() && "Unexpected empty filename!"); set_currentInput(realInput); set_instance(&ci); + if (!ci.HasAllSources()) { BeginSourceFileCleanUp(*this, ci); return false; } + + if (!BeginSourceFileAction(ci)) { + BeginSourceFileCleanUp(*this, ci); + return false; + } + return true; } @@ -47,25 +54,6 @@ } llvm::Error FrontendAction::Execute() { - CompilerInstance &ci = this->instance(); - - std::string currentInputPath{GetCurrentFileOrBufferName()}; - - Fortran::parser::Options parserOptions = - this->instance().invocation().fortranOpts(); - - // Prescan. In case of failure, report and return. - ci.parsing().Prescan(currentInputPath, parserOptions); - - if (ci.parsing().messages().AnyFatalError()) { - const unsigned diagID = ci.diagnostics().getCustomDiagID( - clang::DiagnosticsEngine::Error, "Could not scan %0"); - ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); - ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); - - return llvm::Error::success(); - } - ExecuteAction(); return llvm::Error::success(); diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -16,8 +16,37 @@ using namespace Fortran::frontend; -void InputOutputTestAction::ExecuteAction() { +bool PrescanAction::BeginSourceFileAction(CompilerInstance &c1) { + CompilerInstance &ci = this->instance(); + + std::string currentInputPath{GetCurrentFileOrBufferName()}; + + Fortran::parser::Options parserOptions = + this->instance().invocation().fortranOpts(); + + // Switch between fixed and free form format based on the input file + // extension. Ideally we should have all Fortran options set before + // entering this loop (i.e. processing any input files). However, we + // can't decide between fixed and free form based on the file extension + // earlier than this. + parserOptions.isFixedForm = currentInput().IsFixedForm(); + + // Prescan. In case of failure, report and return. + ci.parsing().Prescan(currentInputPath, parserOptions); + + if (ci.parsing().messages().AnyFatalError()) { + const unsigned diagID = ci.diagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Could not scan %0"); + ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); + ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); + + return false; + } + return true; +} + +void InputOutputTestAction::ExecuteAction() { // Get the name of the file from FrontendInputFile current. std::string path{GetCurrentFileOrBufferName()}; std::string buf;