Skip to content

Commit 18775ca

Browse files
committed
[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
1 parent bba3ced commit 18775ca

File tree

4 files changed

+147
-148
lines changed

4 files changed

+147
-148
lines changed

flang/include/flang/Frontend/FrontendAction.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class FrontendAction {
4343
///
4444
/// \return True on success; on failure ExecutionAction() and
4545
/// EndSourceFileAction() will not be called.
46-
virtual bool BeginSourceFileAction(CompilerInstance &ci) { return true; }
46+
virtual bool BeginSourceFileAction() { return true; }
4747

4848
/// @}
4949

@@ -100,6 +100,34 @@ class FrontendAction {
100100
/// Perform any per-file post processing, deallocate per-file
101101
/// objects, and run statistics and output file cleanup code.
102102
void EndSourceFile();
103+
104+
/// @}
105+
protected:
106+
// Prescan the current input file. Return False if fatal errors are reported,
107+
// True otherwise.
108+
bool RunPrescan();
109+
// Parse the current input file. Return False if fatal errors are reported,
110+
// True otherwise.
111+
bool RunParse();
112+
// Run semantic checks for the current input file. Return False if fatal
113+
// errors are reported, True otherwise.
114+
bool RunSemanticChecks();
115+
116+
// Report fatal semantic errors. Return True if present, false otherwise.
117+
bool reportFatalSemanticErrors();
118+
119+
// Report fatal scanning errors. Return True if present, false otherwise.
120+
inline bool reportFatalScanningErrors() {
121+
return reportFatalErrors("Could not scan %0");
122+
}
123+
124+
// Report fatal parsing errors. Return True if present, false otherwise
125+
inline bool reportFatalParsingErrors() {
126+
return reportFatalErrors("Could not parse %0");
127+
}
128+
129+
private:
130+
template <unsigned N> bool reportFatalErrors(const char (&message)[N]);
103131
};
104132

105133
} // namespace Fortran::frontend

flang/include/flang/Frontend/FrontendActions.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class InitOnlyAction : public FrontendAction {
4747
//===----------------------------------------------------------------------===//
4848
class PrescanAction : public FrontendAction {
4949
void ExecuteAction() override = 0;
50-
bool BeginSourceFileAction(CompilerInstance &ci) override;
50+
bool BeginSourceFileAction() override;
5151
};
5252

5353
class PrintPreprocessedAction : public PrescanAction {
@@ -71,7 +71,7 @@ class DebugMeasureParseTreeAction : public PrescanAction {
7171
//===----------------------------------------------------------------------===//
7272
class PrescanAndParseAction : public FrontendAction {
7373
void ExecuteAction() override = 0;
74-
bool BeginSourceFileAction(CompilerInstance &ci) override;
74+
bool BeginSourceFileAction() override;
7575
};
7676

7777
class DebugUnparseNoSemaAction : public PrescanAndParseAction {
@@ -88,7 +88,7 @@ class DebugDumpParseTreeNoSemaAction : public PrescanAndParseAction {
8888
class PrescanAndSemaAction : public FrontendAction {
8989

9090
void ExecuteAction() override = 0;
91-
bool BeginSourceFileAction(CompilerInstance &ci) override;
91+
bool BeginSourceFileAction() override;
9292
};
9393

9494
class DebugUnparseWithSymbolsAction : public PrescanAndSemaAction {

flang/lib/Frontend/FrontendAction.cpp

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ bool FrontendAction::BeginSourceFile(
8686
invoc.fortranOpts().isFixedForm = currentInput().IsFixedForm();
8787
}
8888

89-
if (!BeginSourceFileAction(ci)) {
89+
if (!BeginSourceFileAction()) {
9090
BeginSourceFileCleanUp(*this, ci);
9191
return false;
9292
}
@@ -114,3 +114,96 @@ void FrontendAction::EndSourceFile() {
114114
set_instance(nullptr);
115115
set_currentInput(FrontendInputFile());
116116
}
117+
118+
bool FrontendAction::RunPrescan() {
119+
CompilerInstance &ci = this->instance();
120+
std::string currentInputPath{GetCurrentFileOrBufferName()};
121+
Fortran::parser::Options parserOptions = ci.invocation().fortranOpts();
122+
123+
if (ci.invocation().frontendOpts().fortranForm == FortranForm::Unknown) {
124+
// Switch between fixed and free form format based on the input file
125+
// extension.
126+
//
127+
// Ideally we should have all Fortran options set before entering this
128+
// method (i.e. before processing any specific input files). However, we
129+
// can't decide between fixed and free form based on the file extension
130+
// earlier than this.
131+
parserOptions.isFixedForm = currentInput().IsFixedForm();
132+
}
133+
134+
// Prescan. In case of failure, report and return.
135+
ci.parsing().Prescan(currentInputPath, parserOptions);
136+
137+
return !reportFatalScanningErrors();
138+
}
139+
140+
bool FrontendAction::RunParse() {
141+
CompilerInstance &ci = this->instance();
142+
143+
// Parse. In case of failure, report and return.
144+
ci.parsing().Parse(llvm::outs());
145+
146+
if (reportFatalParsingErrors()) {
147+
return false;
148+
}
149+
150+
// Report the diagnostics from parsing
151+
ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
152+
153+
return true;
154+
}
155+
156+
bool FrontendAction::RunSemanticChecks() {
157+
CompilerInstance &ci = this->instance();
158+
std::optional<parser::Program> &parseTree{ci.parsing().parseTree()};
159+
assert(parseTree && "Cannot run semantic checks without a parse tree!");
160+
161+
// Prepare semantics
162+
ci.setSemantics(std::make_unique<Fortran::semantics::Semantics>(
163+
ci.invocation().semanticsContext(), *parseTree,
164+
ci.invocation().debugModuleDir()));
165+
auto &semantics = ci.semantics();
166+
167+
// Run semantic checks
168+
semantics.Perform();
169+
170+
if (reportFatalSemanticErrors()) {
171+
return false;
172+
}
173+
174+
// Report the diagnostics from the semantic checks
175+
semantics.EmitMessages(ci.semaOutputStream());
176+
177+
return true;
178+
}
179+
180+
template <unsigned N>
181+
bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
182+
if (!instance_->parsing().messages().empty() &&
183+
(instance_->invocation().warnAsErr() ||
184+
instance_->parsing().messages().AnyFatalError())) {
185+
const unsigned diagID = instance_->diagnostics().getCustomDiagID(
186+
clang::DiagnosticsEngine::Error, message);
187+
instance_->diagnostics().Report(diagID) << GetCurrentFileOrBufferName();
188+
instance_->parsing().messages().Emit(
189+
llvm::errs(), instance_->allCookedSources());
190+
return true;
191+
}
192+
return false;
193+
}
194+
195+
bool FrontendAction::reportFatalSemanticErrors() {
196+
auto &diags = instance_->diagnostics();
197+
auto &sema = instance_->semantics();
198+
199+
if (instance_->semantics().AnyFatalError()) {
200+
unsigned DiagID = diags.getCustomDiagID(
201+
clang::DiagnosticsEngine::Error, "Semantic errors in %0");
202+
diags.Report(DiagID) << GetCurrentFileOrBufferName();
203+
sema.EmitMessages(instance_->semaOutputStream());
204+
205+
return true;
206+
}
207+
208+
return false;
209+
}

0 commit comments

Comments
 (0)