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 @@ -13,6 +13,7 @@ #include "flang/Frontend/PreprocessorOptions.h" #include "flang/Parser/parsing.h" #include "flang/Parser/provenance.h" +#include "flang/Semantics/runtime-type-info.h" #include "flang/Semantics/semantics.h" #include "llvm/Support/raw_ostream.h" @@ -47,6 +48,8 @@ std::unique_ptr semantics_; + std::unique_ptr rtTyTables_; + /// The stream for diagnostics from Semantics llvm::raw_ostream *semaOutputStream_ = &llvm::errs(); @@ -129,6 +132,16 @@ semantics_ = std::move(semantics); } + void setRtTyTables( + std::unique_ptr tables) { + rtTyTables_ = std::move(tables); + } + + Fortran::semantics::RuntimeDerivedTypeTables &getRtTyTables() { + assert(rtTyTables_ && "Missing runtime derived type tables!"); + return *rtTyTables_; + } + /// } /// @name High-Level Operations /// { diff --git a/flang/include/flang/Frontend/FrontendAction.h b/flang/include/flang/Frontend/FrontendAction.h --- a/flang/include/flang/Frontend/FrontendAction.h +++ b/flang/include/flang/Frontend/FrontendAction.h @@ -112,6 +112,10 @@ // Run semantic checks for the current input file. Return False if fatal // errors are reported, True otherwise. bool RunSemanticChecks(); + // Generate run-time type information for derived types. This may lead to new + // semantic errors. Return False if fatal errors are reported, True + // otherwise. + bool GenerateRtTypeTables(); // Report fatal semantic errors. Return True if present, false otherwise. bool reportFatalSemanticErrors(); 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 @@ -133,7 +133,12 @@ // PrescanAndSemaDebug Actions // // These actions will parse the input, run the semantic checks and execute -// their actions regardless of whether any semantic errors are found. +// their actions _regardless of_ whether any semantic errors have been found. +// This can be useful when adding new languge feature and when you wish to +// investigate compiler output (e.g. the parse tree) despite any semantic +// errors. +// +// NOTE: Use with care and for development only! //===----------------------------------------------------------------------===// class PrescanAndSemaDebugAction : public FrontendAction { diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -180,6 +180,21 @@ return true; } +bool FrontendAction::GenerateRtTypeTables() { + instance().setRtTyTables( + std::make_unique( + BuildRuntimeDerivedTypeTables( + instance().invocation().semanticsContext()))); + + // The runtime derived type information table builder may find additional + // semantic errors. Report them. + if (reportFatalSemanticErrors()) { + return false; + } + + return true; +} + template bool FrontendAction::reportFatalErrors(const char (&message)[N]) { if (!instance_->parsing().messages().empty() && 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 @@ -47,12 +47,18 @@ } bool PrescanAndSemaAction::BeginSourceFileAction() { - return RunPrescan() && RunParse() && RunSemanticChecks(); + return RunPrescan() && RunParse() && RunSemanticChecks() && + GenerateRtTypeTables(); } bool PrescanAndSemaDebugAction::BeginSourceFileAction() { - // Semantic checks are made to succeed unconditionally. - return RunPrescan() && RunParse() && (RunSemanticChecks() || true); + // This is a "debug" action for development purposes. To facilitate this, the + // semantic checks are made to succeed unconditionally to prevent this action + // from exiting early (i.e. in the presence of semantic errors). We should + // never do this in actions intended for end-users or otherwise regular + // compiler workflows! + return RunPrescan() && RunParse() && (RunSemanticChecks() || true) && + (GenerateRtTypeTables() || true); } bool CodeGenAction::BeginSourceFileAction() { @@ -218,25 +224,18 @@ void DebugDumpSymbolsAction::ExecuteAction() { CompilerInstance &ci = this->instance(); - auto &semantics = ci.semantics(); - auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables( - instance().invocation().semanticsContext())}; - // 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(); - - if (!tables.schemata) { + if (!ci.getRtTyTables().schemata) { unsigned DiagID = ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "could not find module file for __fortran_type_info"); ci.diagnostics().Report(DiagID); llvm::errs() << "\n"; + return; } // Dump symbols - semantics.DumpSymbols(llvm::outs()); + ci.semantics().DumpSymbols(llvm::outs()); } void DebugDumpAllAction::ExecuteAction() { @@ -250,27 +249,20 @@ Fortran::parser::DumpTree( llvm::outs(), parseTree, &ci.invocation().asFortran()); - auto &semantics = ci.semantics(); - auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables( - instance().invocation().semanticsContext())}; - // 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(); - - if (!tables.schemata) { + if (!ci.getRtTyTables().schemata) { unsigned DiagID = ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "could not find module file for __fortran_type_info"); ci.diagnostics().Report(DiagID); llvm::errs() << "\n"; + return; } // Dump symbols llvm::outs() << "====================="; llvm::outs() << " Flang: symbols dump "; llvm::outs() << "=====================\n"; - semantics.DumpSymbols(llvm::outs()); + ci.semantics().DumpSymbols(llvm::outs()); } void DebugDumpParseTreeNoSemaAction::ExecuteAction() {