Continue wiring up diagnostic reporting infrastructure, still WIP.
 - Implement a diagnostic hook in one of the paths in mlir-opt which
   captures and reports the diagnostics nicely.
 - Have the parser capture simple location information from the parser
   indicating where each op came from in the source .mlir file.
 - Add a verifyDominance() method to MLFuncVerifier to demo this, resolving b/112086163
 - Add some PrettyStackTrace handlers to make crashes in the testsuite easier
   to track down.

PiperOrigin-RevId: 207488548
diff --git a/lib/IR/MLIRContext.cpp b/lib/IR/MLIRContext.cpp
index 3edb115..b5f8980 100644
--- a/lib/IR/MLIRContext.cpp
+++ b/lib/IR/MLIRContext.cpp
@@ -186,9 +186,9 @@
   /// This is the set of all operations that are registered with the system.
   OperationSet operationSet;
 
-  /// This is the handler to use to report issues, or null if not registered.
-  std::function<void(Attribute *location, StringRef message, bool isError)>
-      issueHandler;
+  /// This is the handler to use to report diagnostics, or null if not
+  /// registered.
+  MLIRContext::DiagnosticHandlerTy diagnosticHandler;
 
   /// These are identifiers uniqued into this MLIRContext.
   llvm::StringMap<char, llvm::BumpPtrAllocator &> identifiers;
@@ -278,9 +278,8 @@
 /// passed location information if present (nullptr if not) along with a
 /// message and a boolean that indicates whether this is an error or warning.
 void MLIRContext::registerDiagnosticHandler(
-    const std::function<void(Attribute *location, StringRef message,
-                             bool isError)> &handler) {
-  getImpl().issueHandler = handler;
+    const DiagnosticHandlerTy &handler) {
+  getImpl().diagnosticHandler = handler;
 }
 
 /// This emits a diagnostic using the registered issue handle if present, or
@@ -288,14 +287,14 @@
 /// interact with this, it should use methods on Operation instead.
 void MLIRContext::emitDiagnostic(Attribute *location,
                                  const llvm::Twine &message,
-                                 bool isError) const {
+                                 DiagnosticKind kind) const {
   // If we had a handler registered, emit the diagnostic using it.
-  auto handler = getImpl().issueHandler;
-  if (handler)
-    return handler(location, message.str(), isError);
+  auto handler = getImpl().diagnosticHandler;
+  if (handler && location)
+    return handler(location, message.str(), kind);
 
-  // The default behavior for warnings is to ignore them.
-  if (!isError)
+  // The default behavior for notes and warnings is to ignore them.
+  if (kind != DiagnosticKind::Error)
     return;
 
   // The default behavior for errors is to emit them to stderr and exit.