Recognizing the many users will want the same handler functionality, MLIR
provides several common diagnostic handlers for immediate use.
+### Scoped Diagnostic Handler
+
+This diagnostic handler is a simple RAII class that saves and restores the
+current diagnostic handler registered to a given context. This class can be
+either be used directly, or in conjunction with a derived diagnostic handler.
+
+```c++
+// Construct the handler directly.
+MLIRContext context;
+ScopedDiagnosticHandler scopedHandler(&context, [](Diagnostic diag) {
+ ...
+});
+
+// Use this handler in conjunction with another.
+class MyDerivedHandler : public ScopedDiagnosticHandler {
+ MyDerivedHandler(MLIRContext *ctx) : ScopedDiagnosticHandler(ctx) {
+ ctx->getDiagEngine().setHandler([&](Diagnostic diag) {
+ ...
+ });
+ }
+};
+```
+
### SourceMgr Diagnostic Handler
This diagnostic handler is a wrapper around an llvm::SourceMgr instance. It
This provides a way for the handler to deterministically order the diagnostics
that it receives given the thread that it is receiving on.
-Note: This handler automatically saves and restores the current handler
-registered with the context.
-
A simple example is shown below:
```c++
};
//===----------------------------------------------------------------------===//
+// ScopedDiagnosticHandler
+//===----------------------------------------------------------------------===//
+
+/// This diagnostic handler is a simple RAII class that saves and restores the
+/// current diagnostic handler registered to a given context. This class can
+/// be either be used directly, or in conjunction with a derived diagnostic
+/// handler.
+class ScopedDiagnosticHandler {
+public:
+ ScopedDiagnosticHandler(MLIRContext *ctx);
+ ScopedDiagnosticHandler(MLIRContext *ctx,
+ const DiagnosticEngine::HandlerTy &handler);
+ ~ScopedDiagnosticHandler();
+
+ /// Propagate a diagnostic to the existing diagnostic handler.
+ void propagateDiagnostic(Diagnostic diag) {
+ if (existingHandler)
+ existingHandler(std::move(diag));
+ }
+
+private:
+ /// The existing diagnostic handler registered with the context at the time of
+ /// construction.
+ DiagnosticEngine::HandlerTy existingHandler;
+
+ /// The context to register the handler back to.
+ MLIRContext *ctx;
+};
+
+//===----------------------------------------------------------------------===//
// SourceMgrDiagnosticHandler
//===----------------------------------------------------------------------===//
} // end namespace detail
/// This class is a utility diagnostic handler for use with llvm::SourceMgr.
-class SourceMgrDiagnosticHandler {
+class SourceMgrDiagnosticHandler : public ScopedDiagnosticHandler {
public:
SourceMgrDiagnosticHandler(llvm::SourceMgr &mgr, MLIRContext *ctx);
~SourceMgrDiagnosticHandler();
}
//===----------------------------------------------------------------------===//
+// ScopedDiagnosticHandler
+//===----------------------------------------------------------------------===//
+
+ScopedDiagnosticHandler::ScopedDiagnosticHandler(MLIRContext *ctx)
+ : existingHandler(ctx->getDiagEngine().getHandler()), ctx(ctx) {}
+ScopedDiagnosticHandler::ScopedDiagnosticHandler(
+ MLIRContext *ctx, const DiagnosticEngine::HandlerTy &handler)
+ : ScopedDiagnosticHandler(ctx) {
+ ctx->getDiagEngine().setHandler(handler);
+}
+ScopedDiagnosticHandler::~ScopedDiagnosticHandler() {
+ ctx->getDiagEngine().setHandler(existingHandler);
+}
+
+//===----------------------------------------------------------------------===//
// SourceMgrDiagnosticHandler
//===----------------------------------------------------------------------===//
namespace mlir {
SourceMgrDiagnosticHandler::SourceMgrDiagnosticHandler(llvm::SourceMgr &mgr,
MLIRContext *ctx)
- : mgr(mgr), impl(new SourceMgrDiagnosticHandlerImpl()) {
+ : ScopedDiagnosticHandler(ctx), mgr(mgr),
+ impl(new SourceMgrDiagnosticHandlerImpl()) {
// Register a simple diagnostic handler.
ctx->getDiagEngine().setHandler(
[this](Diagnostic diag) { emitDiagnostic(diag); });