Skip to content

Commit

Permalink
[flang][nfc] Tweak the FrontendAction class
Browse files Browse the repository at this point in the history
This patch refactors the `FrontendAction` class. It merely moves code
around so that re-using it is easier. No new functionality is
introduced.

1. Three new member methods are introduced: `RunPrescan`, `RunParse`,
`RunSemanticChecks`.
2. The following free functions are re-implemented as member methods:
  * `reportFatalSemanticErrors`
  * `reportFatalScanningErrors`
  * `reportFatalParsingErrors`
  * `reportFatalErrors`
`reportFatalSemanticErrors` is updated to resemble the other error
reporting functions and to make the API more consistent.
3. The `BeginSourceFileAction` methods are simplified and the unused
input argument is deleted.

Differential Revision: https://reviews.llvm.org/D108130
  • Loading branch information
banach-space committed Aug 17, 2021
1 parent ce8272a commit 4f21e6a
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 148 deletions.
30 changes: 29 additions & 1 deletion flang/include/flang/Frontend/FrontendAction.h
Expand Up @@ -43,7 +43,7 @@ class FrontendAction {
///
/// \return True on success; on failure ExecutionAction() and
/// EndSourceFileAction() will not be called.
virtual bool BeginSourceFileAction(CompilerInstance &ci) { return true; }
virtual bool BeginSourceFileAction() { return true; }

/// @}

Expand Down Expand Up @@ -100,6 +100,34 @@ class FrontendAction {
/// Perform any per-file post processing, deallocate per-file
/// objects, and run statistics and output file cleanup code.
void EndSourceFile();

/// @}
protected:
// Prescan the current input file. Return False if fatal errors are reported,
// True otherwise.
bool RunPrescan();
// Parse the current input file. Return False if fatal errors are reported,
// True otherwise.
bool RunParse();
// Run semantic checks for the current input file. Return False if fatal
// errors are reported, True otherwise.
bool RunSemanticChecks();

// Report fatal semantic errors. Return True if present, false otherwise.
bool reportFatalSemanticErrors();

// Report fatal scanning errors. Return True if present, false otherwise.
inline bool reportFatalScanningErrors() {
return reportFatalErrors("Could not scan %0");
}

// Report fatal parsing errors. Return True if present, false otherwise
inline bool reportFatalParsingErrors() {
return reportFatalErrors("Could not parse %0");
}

private:
template <unsigned N> bool reportFatalErrors(const char (&message)[N]);
};

} // namespace Fortran::frontend
Expand Down
6 changes: 3 additions & 3 deletions flang/include/flang/Frontend/FrontendActions.h
Expand Up @@ -51,7 +51,7 @@ class InitOnlyAction : public FrontendAction {
//===----------------------------------------------------------------------===//
class PrescanAction : public FrontendAction {
void ExecuteAction() override = 0;
bool BeginSourceFileAction(CompilerInstance &ci) override;
bool BeginSourceFileAction() override;
};

class PrintPreprocessedAction : public PrescanAction {
Expand All @@ -75,7 +75,7 @@ class DebugMeasureParseTreeAction : public PrescanAction {
//===----------------------------------------------------------------------===//
class PrescanAndParseAction : public FrontendAction {
void ExecuteAction() override = 0;
bool BeginSourceFileAction(CompilerInstance &ci) override;
bool BeginSourceFileAction() override;
};

class DebugUnparseNoSemaAction : public PrescanAndParseAction {
Expand All @@ -92,7 +92,7 @@ class DebugDumpParseTreeNoSemaAction : public PrescanAndParseAction {
class PrescanAndSemaAction : public FrontendAction {

void ExecuteAction() override = 0;
bool BeginSourceFileAction(CompilerInstance &ci) override;
bool BeginSourceFileAction() override;
};

class DebugUnparseWithSymbolsAction : public PrescanAndSemaAction {
Expand Down
95 changes: 94 additions & 1 deletion flang/lib/Frontend/FrontendAction.cpp
Expand Up @@ -89,7 +89,7 @@ bool FrontendAction::BeginSourceFile(
invoc.fortranOpts().isFixedForm = currentInput().IsFixedForm();
}

if (!BeginSourceFileAction(ci)) {
if (!BeginSourceFileAction()) {
BeginSourceFileCleanUp(*this, ci);
return false;
}
Expand Down Expand Up @@ -117,3 +117,96 @@ void FrontendAction::EndSourceFile() {
set_instance(nullptr);
set_currentInput(FrontendInputFile());
}

bool FrontendAction::RunPrescan() {
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);

return !reportFatalScanningErrors();
}

bool FrontendAction::RunParse() {
CompilerInstance &ci = this->instance();

// Parse. In case of failure, report and return.
ci.parsing().Parse(llvm::outs());

if (reportFatalParsingErrors()) {
return false;
}

// Report the diagnostics from parsing
ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());

return true;
}

bool FrontendAction::RunSemanticChecks() {
CompilerInstance &ci = this->instance();
std::optional<parser::Program> &parseTree{ci.parsing().parseTree()};
assert(parseTree && "Cannot run semantic checks without a parse tree!");

// Prepare semantics
ci.setSemantics(std::make_unique<Fortran::semantics::Semantics>(
ci.invocation().semanticsContext(), *parseTree,
ci.invocation().debugModuleDir()));
auto &semantics = ci.semantics();

// Run semantic checks
semantics.Perform();

if (reportFatalSemanticErrors()) {
return false;
}

// Report the diagnostics from the semantic checks
semantics.EmitMessages(ci.semaOutputStream());

return true;
}

template <unsigned N>
bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
if (!instance_->parsing().messages().empty() &&
(instance_->invocation().warnAsErr() ||
instance_->parsing().messages().AnyFatalError())) {
const unsigned diagID = instance_->diagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, message);
instance_->diagnostics().Report(diagID) << GetCurrentFileOrBufferName();
instance_->parsing().messages().Emit(
llvm::errs(), instance_->allCookedSources());
return true;
}
return false;
}

bool FrontendAction::reportFatalSemanticErrors() {
auto &diags = instance_->diagnostics();
auto &sema = instance_->semantics();

if (instance_->semantics().AnyFatalError()) {
unsigned DiagID = diags.getCustomDiagID(
clang::DiagnosticsEngine::Error, "Semantic errors in %0");
diags.Report(DiagID) << GetCurrentFileOrBufferName();
sema.EmitMessages(instance_->semaOutputStream());

return true;
}

return false;
}

0 comments on commit 4f21e6a

Please sign in to comment.