diff --git a/flang/include/flang/Frontend/CompilerInstance.h b/flang/include/flang/Frontend/CompilerInstance.h --- a/flang/include/flang/Frontend/CompilerInstance.h +++ b/flang/include/flang/Frontend/CompilerInstance.h @@ -18,6 +18,21 @@ namespace Fortran::frontend { +/// Helper class for managing a single instance of the Flang compiler. +/// +/// This class serves two purposes: +/// (1) It manages the various objects which are necessary to run the compiler +/// (2) It provides utility routines for constructing and manipulating the +/// common Flang objects. +/// +/// The compiler instance generally owns the instance of all the objects that it +/// manages. However, clients can still share objects by manually setting the +/// object and retaking ownership prior to destroying the CompilerInstance. +/// +/// The compiler instance is intended to simplify clients, but not to lock them +/// in to the compiler instance for everything. When possible, utility functions +/// come in two forms; a short form that reuses the CompilerInstance objects, +/// and a long form that takes explicit instances of any required objects. class CompilerInstance { /// The options used in this compiler instance. @@ -30,6 +45,8 @@ std::shared_ptr parsing_; + std::unique_ptr semantics_; + /// The stream for diagnostics from Semantics llvm::raw_ostream *semaOutputStream_ = &llvm::errs(); @@ -110,6 +127,13 @@ /// Get the current stream for verbose output. llvm::raw_ostream &semaOutputStream() { return *semaOutputStream_; } + Fortran::semantics::Semantics &semantics() { return *semantics_; } + const Fortran::semantics::Semantics &semantics() const { return *semantics_; } + + void setSemantics(std::unique_ptr semantics) { + semantics_ = std::move(semantics); + } + /// } /// @name High-Level Operations /// { 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 @@ -90,18 +90,9 @@ // PrescanAndSema Actions //===----------------------------------------------------------------------===// class PrescanAndSemaAction : public FrontendAction { - std::unique_ptr semantics_; void ExecuteAction() override = 0; bool BeginSourceFileAction(CompilerInstance &ci) override; - -public: - Fortran::semantics::Semantics &semantics() { return *semantics_; } - const Fortran::semantics::Semantics &semantics() const { return *semantics_; } - - void setSemantics(std::unique_ptr semantics) { - semantics_ = std::move(semantics); - } }; class DebugUnparseWithSymbolsAction : public PrescanAndSemaAction { 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 @@ -139,10 +139,10 @@ auto &parseTree{*ci.parsing().parseTree()}; // Prepare semantics - setSemantics(std::make_unique( + ci.setSemantics(std::make_unique( ci.invocation().semanticsContext(), parseTree, ci.invocation().debugModuleDir())); - auto &semantics = this->semantics(); + auto &semantics = ci.semantics(); // Run semantic checks semantics.Perform(); @@ -224,8 +224,10 @@ } void ParseSyntaxOnlyAction::ExecuteAction() { - reportFatalSemanticErrors(semantics(), this->instance().diagnostics(), - GetCurrentFileOrBufferName()); + CompilerInstance &ci = this->instance(); + + reportFatalSemanticErrors( + ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName()); } void DebugUnparseNoSemaAction::ExecuteAction() { @@ -256,24 +258,25 @@ invoc.useAnalyzedObjectsForUnparse() ? &invoc.asFortran() : nullptr); // Report fatal semantic errors - reportFatalSemanticErrors(semantics(), this->instance().diagnostics(), + reportFatalSemanticErrors(ci.semantics(), this->instance().diagnostics(), GetCurrentFileOrBufferName()); } 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(semantics(), this->instance().diagnostics(), - GetCurrentFileOrBufferName()); + reportFatalSemanticErrors( + ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName()); } void DebugDumpSymbolsAction::ExecuteAction() { CompilerInstance &ci = this->instance(); - auto &semantics = this->semantics(); + auto &semantics = ci.semantics(); auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables( instance().invocation().semanticsContext())}; @@ -306,7 +309,7 @@ Fortran::parser::DumpTree( llvm::outs(), parseTree, &ci.invocation().asFortran()); - auto &semantics = this->semantics(); + auto &semantics = ci.semantics(); auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables( instance().invocation().semanticsContext())}; // The runtime derived type information table builder may find and report @@ -339,6 +342,7 @@ } void DebugDumpParseTreeAction::ExecuteAction() { + CompilerInstance &ci = this->instance(); auto &parseTree{instance().parsing().parseTree()}; // Dump parse tree @@ -346,8 +350,8 @@ llvm::outs(), parseTree, &this->instance().invocation().asFortran()); // Report fatal semantic errors - reportFatalSemanticErrors(semantics(), this->instance().diagnostics(), - GetCurrentFileOrBufferName()); + reportFatalSemanticErrors( + ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName()); } void DebugMeasureParseTreeAction::ExecuteAction() { @@ -385,7 +389,7 @@ CompilerInstance &ci = this->instance(); // Report and exit if fatal semantic errors are present if (reportFatalSemanticErrors( - semantics(), ci.diagnostics(), GetCurrentFileOrBufferName())) { + ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName())) { return; } @@ -410,12 +414,13 @@ } void GetDefinitionAction::ExecuteAction() { + CompilerInstance &ci = this->instance(); + // Report and exit if fatal semantic errors are present - if (reportFatalSemanticErrors(semantics(), this->instance().diagnostics(), - GetCurrentFileOrBufferName())) + if (reportFatalSemanticErrors( + ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName())) return; - CompilerInstance &ci = this->instance(); parser::AllCookedSources &cs = ci.allCookedSources(); unsigned diagID = ci.diagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Symbol not found"); @@ -457,12 +462,14 @@ } void GetSymbolsSourcesAction::ExecuteAction() { + CompilerInstance &ci = this->instance(); + // Report and exit if fatal semantic errors are present - if (reportFatalSemanticErrors(semantics(), this->instance().diagnostics(), - GetCurrentFileOrBufferName())) + if (reportFatalSemanticErrors( + ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName())) return; - semantics().DumpSymbolsSources(llvm::outs()); + ci.semantics().DumpSymbolsSources(llvm::outs()); } void EmitObjAction::ExecuteAction() {