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.
std::shared_ptr<Fortran::parser::Parsing> parsing_;
+ std::unique_ptr<Fortran::semantics::Semantics> semantics_;
+
/// The stream for diagnostics from Semantics
llvm::raw_ostream *semaOutputStream_ = &llvm::errs();
/// 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<Fortran::semantics::Semantics> semantics) {
+ semantics_ = std::move(semantics);
+ }
+
/// }
/// @name High-Level Operations
/// {
auto &parseTree{*ci.parsing().parseTree()};
// Prepare semantics
- setSemantics(std::make_unique<Fortran::semantics::Semantics>(
+ ci.setSemantics(std::make_unique<Fortran::semantics::Semantics>(
ci.invocation().semanticsContext(), parseTree,
ci.invocation().debugModuleDir()));
- auto &semantics = this->semantics();
+ auto &semantics = ci.semantics();
// Run semantic checks
semantics.Perform();
}
void ParseSyntaxOnlyAction::ExecuteAction() {
- reportFatalSemanticErrors(semantics(), this->instance().diagnostics(),
- GetCurrentFileOrBufferName());
+ CompilerInstance &ci = this->instance();
+
+ reportFatalSemanticErrors(
+ ci.semantics(), ci.diagnostics(), GetCurrentFileOrBufferName());
}
void DebugUnparseNoSemaAction::ExecuteAction() {
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())};
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
}
void DebugDumpParseTreeAction::ExecuteAction() {
+ CompilerInstance &ci = this->instance();
auto &parseTree{instance().parsing().parseTree()};
// Dump parse tree
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() {
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;
}
}
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");
}
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() {