[flang-commits] [flang] 4f21e6a - [flang][nfc] Tweak the FrontendAction class

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Tue Aug 17 00:53:05 PDT 2021


Author: Andrzej Warzynski
Date: 2021-08-17T07:36:44Z
New Revision: 4f21e6aeddc2dbe4ae22aba5b97cae0c50c961f6

URL: https://github.com/llvm/llvm-project/commit/4f21e6aeddc2dbe4ae22aba5b97cae0c50c961f6
DIFF: https://github.com/llvm/llvm-project/commit/4f21e6aeddc2dbe4ae22aba5b97cae0c50c961f6.diff

LOG: [flang][nfc] Tweak the FrontendAction class

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

Added: 
    

Modified: 
    flang/include/flang/Frontend/FrontendAction.h
    flang/include/flang/Frontend/FrontendActions.h
    flang/lib/Frontend/FrontendAction.cpp
    flang/lib/Frontend/FrontendActions.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Frontend/FrontendAction.h b/flang/include/flang/Frontend/FrontendAction.h
index 87e82fe5274f5..aac1fcf268a08 100644
--- a/flang/include/flang/Frontend/FrontendAction.h
+++ b/flang/include/flang/Frontend/FrontendAction.h
@@ -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; }
 
   /// @}
 
@@ -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

diff  --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 9cfaabcf7677e..43fd1f0f65965 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -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 {
@@ -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 {
@@ -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 {

diff  --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 77700d2abec78..5285681e2904a 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -89,7 +89,7 @@ bool FrontendAction::BeginSourceFile(
     invoc.fortranOpts().isFixedForm = currentInput().IsFixedForm();
   }
 
-  if (!BeginSourceFileAction(ci)) {
+  if (!BeginSourceFileAction()) {
     BeginSourceFileCleanUp(*this, ci);
     return false;
   }
@@ -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;
+}

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index acd6b049dfe8d..f5ff2095281cd 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -27,132 +27,22 @@
 
 using namespace Fortran::frontend;
 
-/// Report fatal semantic errors if present.
-///
-/// \param semantics The semantics instance
-/// \param diags The diagnostics engine instance
-/// \param bufferName The file or buffer name
-///
-/// \return True if fatal semantic errors are present, false if not
-bool reportFatalSemanticErrors(const Fortran::semantics::Semantics &semantics,
-    clang::DiagnosticsEngine &diags, const llvm::StringRef &bufferName) {
-  if (semantics.AnyFatalError()) {
-    unsigned DiagID = diags.getCustomDiagID(
-        clang::DiagnosticsEngine::Error, "Semantic errors in %0");
-    diags.Report(DiagID) << bufferName;
-    return true;
-  }
-  return false;
-}
-
-template <unsigned N>
-static bool reportFatalErrors(
-    const FrontendAction *act, const char (&message)[N]) {
-  CompilerInstance &ci = act->instance();
-  if (!ci.parsing().messages().empty() &&
-      (ci.invocation().warnAsErr() ||
-          ci.parsing().messages().AnyFatalError())) {
-    const unsigned diagID = ci.diagnostics().getCustomDiagID(
-        clang::DiagnosticsEngine::Error, message);
-    ci.diagnostics().Report(diagID) << act->GetCurrentFileOrBufferName();
-    ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
-    return true;
-  }
-  return false;
-}
-
-inline bool reportFatalScanningErrors(const FrontendAction *act) {
-  return reportFatalErrors(act, "Could not scan %0");
-}
-
-inline bool reportFatalParsingErrors(const FrontendAction *act) {
-  return reportFatalErrors(act, "Could not parse %0");
-}
-
-bool PrescanAction::BeginSourceFileAction(CompilerInstance &c1) {
-  CompilerInstance &ci = this->instance();
-  std::string currentInputPath{GetCurrentFileOrBufferName()};
-  Fortran::parser::Options parserOptions = ci.invocation().fortranOpts();
-
-  // Prescan. In case of failure, report and return.
-  ci.parsing().Prescan(currentInputPath, parserOptions);
-
-  return !reportFatalScanningErrors(this);
-}
-
-bool PrescanAndParseAction::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 (reportFatalScanningErrors(this))
-    return false;
-
-  // Parse. In case of failure, report and return.
-  ci.parsing().Parse(llvm::outs());
-
-  if (reportFatalParsingErrors(this))
-    return false;
-
-  // Report the diagnostics from parsing
-  ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
+//===----------------------------------------------------------------------===//
+// Custom BeginSourceFileAction
+//===----------------------------------------------------------------------===//
+bool PrescanAction::BeginSourceFileAction() { return RunPrescan(); }
 
-  return true;
+bool PrescanAndParseAction::BeginSourceFileAction() {
+  return RunPrescan() && RunParse();
 }
 
-bool PrescanAndSemaAction::BeginSourceFileAction(CompilerInstance &c1) {
-  CompilerInstance &ci = this->instance();
-  std::string currentInputPath{GetCurrentFileOrBufferName()};
-  Fortran::parser::Options parserOptions = ci.invocation().fortranOpts();
-
-  // Prescan. In case of failure, report and return.
-  ci.parsing().Prescan(currentInputPath, parserOptions);
-
-  if (reportFatalScanningErrors(this))
-    return false;
-
-  // Parse. In case of failure, report and return.
-  ci.parsing().Parse(llvm::outs());
-
-  if (reportFatalParsingErrors(this))
-    return false;
-
-  // Report the diagnostics from parsing
-  ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
-
-  auto &parseTree{*ci.parsing().parseTree()};
-
-  // 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();
-
-  // Report the diagnostics from the semantic checks
-  semantics.EmitMessages(ci.semaOutputStream());
-
-  return true;
+bool PrescanAndSemaAction::BeginSourceFileAction() {
+  return RunPrescan() & RunParse() && RunSemanticChecks();
 }
 
+//===----------------------------------------------------------------------===//
+// Custom ExecuteAction
+//===----------------------------------------------------------------------===//
 void InputOutputTestAction::ExecuteAction() {
   CompilerInstance &ci = instance();
 
@@ -224,10 +114,6 @@ void DebugDumpProvenanceAction::ExecuteAction() {
 }
 
 void ParseSyntaxOnlyAction::ExecuteAction() {
-  CompilerInstance &ci = this->instance();
-
-  reportFatalSemanticErrors(
-      ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName());
 }
 
 void DebugUnparseNoSemaAction::ExecuteAction() {
@@ -258,20 +144,17 @@ void DebugUnparseAction::ExecuteAction() {
       invoc.useAnalyzedObjectsForUnparse() ? &invoc.asFortran() : nullptr);
 
   // Report fatal semantic errors
-  reportFatalSemanticErrors(ci.semantics(), this->instance().diagnostics(),
-      GetCurrentFileOrBufferName());
+  reportFatalSemanticErrors();
 }
 
 void DebugUnparseWithSymbolsAction::ExecuteAction() {
-  CompilerInstance &ci = this->instance();
   auto &parseTree{*instance().parsing().parseTree()};
 
   Fortran::semantics::UnparseWithSymbols(
       llvm::outs(), parseTree, /*encoding=*/Fortran::parser::Encoding::UTF_8);
 
   // Report fatal semantic errors
-  reportFatalSemanticErrors(
-      ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName());
+  reportFatalSemanticErrors();
 }
 
 void DebugDumpSymbolsAction::ExecuteAction() {
@@ -283,8 +166,7 @@ void DebugDumpSymbolsAction::ExecuteAction() {
   // The runtime derived type information table builder may find and report
   // semantic errors. So it is important that we report them _after_
   // BuildRuntimeDerivedTypeTables is run.
-  reportFatalSemanticErrors(
-      semantics, this->instance().diagnostics(), GetCurrentFileOrBufferName());
+  reportFatalSemanticErrors();
 
   if (!tables.schemata) {
     unsigned DiagID =
@@ -315,8 +197,7 @@ void DebugDumpAllAction::ExecuteAction() {
   // The runtime derived type information table builder may find and report
   // semantic errors. So it is important that we report them _after_
   // BuildRuntimeDerivedTypeTables is run.
-  reportFatalSemanticErrors(
-      semantics, this->instance().diagnostics(), GetCurrentFileOrBufferName());
+  reportFatalSemanticErrors();
 
   if (!tables.schemata) {
     unsigned DiagID =
@@ -342,7 +223,6 @@ void DebugDumpParseTreeNoSemaAction::ExecuteAction() {
 }
 
 void DebugDumpParseTreeAction::ExecuteAction() {
-  CompilerInstance &ci = this->instance();
   auto &parseTree{instance().parsing().parseTree()};
 
   // Dump parse tree
@@ -350,8 +230,7 @@ void DebugDumpParseTreeAction::ExecuteAction() {
       llvm::outs(), parseTree, &this->instance().invocation().asFortran());
 
   // Report fatal semantic errors
-  reportFatalSemanticErrors(
-      ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName());
+  reportFatalSemanticErrors();
 }
 
 void DebugMeasureParseTreeAction::ExecuteAction() {
@@ -388,8 +267,7 @@ void DebugMeasureParseTreeAction::ExecuteAction() {
 void DebugPreFIRTreeAction::ExecuteAction() {
   CompilerInstance &ci = this->instance();
   // Report and exit if fatal semantic errors are present
-  if (reportFatalSemanticErrors(
-          ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName())) {
+  if (reportFatalSemanticErrors()) {
     return;
   }
 
@@ -417,9 +295,9 @@ void GetDefinitionAction::ExecuteAction() {
   CompilerInstance &ci = this->instance();
 
   // Report and exit if fatal semantic errors are present
-  if (reportFatalSemanticErrors(
-          ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName()))
+  if (reportFatalSemanticErrors()) {
     return;
+  }
 
   parser::AllCookedSources &cs = ci.allCookedSources();
   unsigned diagID = ci.diagnostics().getCustomDiagID(
@@ -465,9 +343,9 @@ void GetSymbolsSourcesAction::ExecuteAction() {
   CompilerInstance &ci = this->instance();
 
   // Report and exit if fatal semantic errors are present
-  if (reportFatalSemanticErrors(
-          ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName()))
+  if (reportFatalSemanticErrors()) {
     return;
+  }
 
   ci.semantics().DumpSymbolsSources(llvm::outs());
 }


        


More information about the flang-commits mailing list