/// 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:
/// @}
/// @name Public Action Interface
- /// @}
+ /// @{
/// Prepare the action for processing the input file \p input.
///
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 = 0;
+ bool BeginSourceFileAction(CompilerInstance &ci) override;
+};
+
+class PrintPreprocessedAction : public PrescanAction {
void ExecuteAction() override;
};
-class EmitObjAction : public FrontendAction {
+class ParseSyntaxOnlyAction : public PrescanAction {
void ExecuteAction() override;
};
// Run the frontend action `act` for every input file.
for (const FrontendInputFile &fif : frontendOpts().inputs_) {
if (act.BeginSourceFile(*this, fif)) {
- if (invoc.frontendOpts().fortranForm_ == FortranForm::Unknown) {
- // 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));
}
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;
}
}
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();
using namespace Fortran::frontend;
-void InputOutputTestAction::ExecuteAction() {
+bool PrescanAction::BeginSourceFileAction(CompilerInstance &c1) {
+ CompilerInstance &ci = this->instance();
+
+ std::string currentInputPath{GetCurrentFileOrBufferName()};
+
+ Fortran::parser::Options parserOptions = ci.invocation().fortranOpts();
+ if (ci.invocation().frontendOpts().fortranForm_ == FortranForm::Unknown) {
+ // Switch between fixed and free form format based on the input file
+ // extension.
+ //
+ // Ideally we should have all Fortran options set before entering this
+ // method (i.e. before processing any specific 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;