Introduce a new common diagnostic handler ScopedDiagnosticHandler to simplify...
authorRiver Riddle <riverriddle@google.com>
Thu, 23 May 2019 23:16:34 +0000 (16:16 -0700)
committerMehdi Amini <joker.eph@gmail.com>
Sun, 2 Jun 2019 02:59:33 +0000 (19:59 -0700)
--

PiperOrigin-RevId: 249735912

mlir/g3doc/Diagnostics.md
mlir/include/mlir/IR/Diagnostics.h
mlir/lib/IR/Diagnostics.cpp

index b7bf4b8..973555b 100644 (file)
@@ -178,6 +178,29 @@ diagnostic handler with the [`DiagnosticEngine`](#diagnostic-engine).
 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
@@ -270,9 +293,6 @@ with the 'orderID'. The thread that is processing 'a' should set the orderID to
 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++
index 6ffeea5..b2205f0 100644 (file)
@@ -444,6 +444,36 @@ private:
 };
 
 //===----------------------------------------------------------------------===//
+// 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
 //===----------------------------------------------------------------------===//
 
@@ -452,7 +482,7 @@ struct SourceMgrDiagnosticHandlerImpl;
 } // 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();
index c8f4cc1..6d7a24a 100644 (file)
@@ -262,6 +262,21 @@ void DiagnosticEngine::emit(Diagnostic diag) {
 }
 
 //===----------------------------------------------------------------------===//
+// 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 {
@@ -328,7 +343,8 @@ static llvm::SourceMgr::DiagKind getDiagKind(DiagnosticSeverity kind) {
 
 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); });