[flang] Ensure lowering diagnostic handler does not outlive lowering (#151608)

When the LoweringBridge is created, it registers an MLIR Diagnostics
handler with the MLIRContext. However, it never deregisters it once
lowering is finished.

This fixes this particular scenario. It also makes it so that the
Diagnostics handler is optional.
This commit is contained in:
Razvan Lupusoru 2025-08-01 09:27:36 -07:00 committed by GitHub
parent 25c07763f7
commit 2f33b01651
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 21 deletions

View File

@ -76,6 +76,7 @@ public:
loweringOptions, envDefaults, languageFeatures,
targetMachine, targetOptions, codeGenOptions);
}
~LoweringBridge();
//===--------------------------------------------------------------------===//
// Getters
@ -174,6 +175,7 @@ private:
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults;
const Fortran::common::LanguageFeatureControl &languageFeatures;
std::set<std::string> tempNames;
std::optional<mlir::DiagnosticEngine::HandlerID> diagHandlerID;
};
} // namespace lower

View File

@ -74,5 +74,10 @@ ENUM_LOWERINGOPT(SkipExternalRttiDefinition, unsigned, 1, 0)
/// If false, lower to the complex dialect of MLIR.
/// On by default.
ENUM_LOWERINGOPT(ComplexDivisionToRuntime, unsigned, 1, 1)
/// When true, it registers MLIRDiagnosticsHandler for the duration
/// of the lowering pipeline.
ENUM_LOWERINGOPT(RegisterMLIRDiagnosticsHandler, unsigned, 1, 1)
#undef LOWERINGOPT
#undef ENUM_LOWERINGOPT

View File

@ -6707,27 +6707,30 @@ Fortran::lower::LoweringBridge::LoweringBridge(
loweringOptions{loweringOptions}, envDefaults{envDefaults},
languageFeatures{languageFeatures} {
// Register the diagnostic handler.
context.getDiagEngine().registerHandler([](mlir::Diagnostic &diag) {
llvm::raw_ostream &os = llvm::errs();
switch (diag.getSeverity()) {
case mlir::DiagnosticSeverity::Error:
os << "error: ";
break;
case mlir::DiagnosticSeverity::Remark:
os << "info: ";
break;
case mlir::DiagnosticSeverity::Warning:
os << "warning: ";
break;
default:
break;
}
if (!mlir::isa<mlir::UnknownLoc>(diag.getLocation()))
os << diag.getLocation() << ": ";
os << diag << '\n';
os.flush();
return mlir::success();
});
if (loweringOptions.getRegisterMLIRDiagnosticsHandler()) {
diagHandlerID =
context.getDiagEngine().registerHandler([](mlir::Diagnostic &diag) {
llvm::raw_ostream &os = llvm::errs();
switch (diag.getSeverity()) {
case mlir::DiagnosticSeverity::Error:
os << "error: ";
break;
case mlir::DiagnosticSeverity::Remark:
os << "info: ";
break;
case mlir::DiagnosticSeverity::Warning:
os << "warning: ";
break;
default:
break;
}
if (!mlir::isa<mlir::UnknownLoc>(diag.getLocation()))
os << diag.getLocation() << ": ";
os << diag << '\n';
os.flush();
return mlir::success();
});
}
auto getPathLocation = [&semanticsContext, &context]() -> mlir::Location {
std::optional<std::string> path;
@ -6769,6 +6772,11 @@ Fortran::lower::LoweringBridge::LoweringBridge(
fir::setCommandline(*module, *cgOpts.RecordCommandLine);
}
Fortran::lower::LoweringBridge::~LoweringBridge() {
if (diagHandlerID)
context.getDiagEngine().eraseHandler(*diagHandlerID);
}
void Fortran::lower::genCleanUpInRegionIfAny(
mlir::Location loc, fir::FirOpBuilder &builder, mlir::Region &region,
Fortran::lower::StatementContext &context) {