[Mlir-commits] [mlir] [mlir] Add support for multi-parts diagnostics (PR #217804)

lonely eagle llvmlistbot at llvm.org
Wed Sep 23 17:47:13 PDT 2026


https://github.com/linuxlonelyeagle updated https://github.com/llvm/llvm-project/pull/217804

>From 65e2de569461ed18999389538ba70ed99dc60ffa Mon Sep 17 00:00:00 2001
From: linuxlonelyeagle <2020382038 at qq.com>
Date: Wed, 9 Sep 2026 10:43:07 +0000
Subject: [PATCH 1/4] add next to InFlightDiagnostic.

---
 mlir/include/mlir/IR/Diagnostics.h        | 35 +++++++++++++++-
 mlir/lib/IR/Diagnostics.cpp               | 51 ++++++++++++++++++++---
 mlir/test/IR/diagnostic-handler-next.mlir |  8 ++++
 mlir/test/lib/IR/CMakeLists.txt           |  1 +
 mlir/test/lib/IR/TestDiagnosticsNext.cpp  | 49 ++++++++++++++++++++++
 mlir/tools/mlir-opt/mlir-opt.cpp          |  2 +
 6 files changed, 138 insertions(+), 8 deletions(-)
 create mode 100644 mlir/test/IR/diagnostic-handler-next.mlir
 create mode 100644 mlir/test/lib/IR/TestDiagnosticsNext.cpp

diff --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h
index 3b8fb46b06a48..8f802c131f3ce 100644
--- a/mlir/include/mlir/IR/Diagnostics.h
+++ b/mlir/include/mlir/IR/Diagnostics.h
@@ -249,12 +249,18 @@ class Diagnostic {
     return *this;
   }
 
-  /// Outputs this diagnostic to a stream.
-  void print(raw_ostream &os) const;
+  /// Outputs this diagnostic to a stream. `ChunkIdx` specifies which chunk to
+  /// print to `os`. If empty, all arguments are printed to `os`.
+  void print(raw_ostream &os,
+             std::optional<int64_t> chunkIdx = std::nullopt) const;
 
   /// Converts the diagnostic to a string.
   std::string str() const;
 
+  /// Converts the diagnostic to a vector of strings, where each element
+  /// represents a chunk.
+  SmallVector<std::string> strs() const;
+
   /// Attaches a note to this diagnostic. A new location may be optionally
   /// provided, if not, then the location defaults to the one specified for this
   /// diagnostic. Notes may not be attached to other notes.
@@ -288,6 +294,9 @@ class Diagnostic {
   /// Returns the current list of diagnostic metadata.
   SmallVectorImpl<DiagnosticArgument> &getMetadata() { return metadata; }
 
+  /// Finalizes the current group of arguments and starts a new chunk.
+  void checkpointArguments();
+
 private:
   Diagnostic(const Diagnostic &rhs) = delete;
   Diagnostic &operator=(const Diagnostic &rhs) = delete;
@@ -305,6 +314,9 @@ class Diagnostic {
   /// liveness of non-constant strings used in diagnostics.
   std::vector<std::unique_ptr<char[]>> strings;
 
+  /// Boundary indices in `arguments` that separate different chunks.
+  SmallVector<size_t, 2> chunkSizes;
+
   /// A list of attached notes.
   NoteVector notes;
 
@@ -348,6 +360,17 @@ class InFlightDiagnostic {
     return std::move(append(std::forward<Arg>(arg)));
   }
 
+  /// Enables stream-style manipulators to be chained into the diagnostic.
+  InFlightDiagnostic &
+  operator<<(InFlightDiagnostic &(*manip)(InFlightDiagnostic &)) & {
+    return manip(*this);
+  }
+
+  InFlightDiagnostic &&
+  operator<<(InFlightDiagnostic &(*manip)(InFlightDiagnostic &)) && {
+    return std::move(manip(*this));
+  }
+
   /// Append arguments to the diagnostic.
   template <typename... Args>
   InFlightDiagnostic &append(Args &&...args) & {
@@ -408,6 +431,7 @@ class InFlightDiagnostic {
 
   // Allow access to the constructor.
   friend DiagnosticEngine;
+  friend inline InFlightDiagnostic &next(InFlightDiagnostic &diag);
 
   /// The engine that this diagnostic is to report to.
   DiagnosticEngine *owner = nullptr;
@@ -416,6 +440,13 @@ class InFlightDiagnostic {
   std::optional<Diagnostic> impl;
 };
 
+/// A stream manipulator that checkpoints the current messages, and allowing a
+/// single InFlightDiagnostic to output multiple lines.
+inline InFlightDiagnostic &next(InFlightDiagnostic &diag) {
+  diag.impl->checkpointArguments();
+  return diag;
+}
+
 //===----------------------------------------------------------------------===//
 // DiagnosticEngine
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/IR/Diagnostics.cpp b/mlir/lib/IR/Diagnostics.cpp
index 5caf826c84bdd..a10f581f38522 100644
--- a/mlir/lib/IR/Diagnostics.cpp
+++ b/mlir/lib/IR/Diagnostics.cpp
@@ -161,9 +161,22 @@ Diagnostic &Diagnostic::operator<<(Value val) {
   return *this << str;
 }
 
-/// Outputs this diagnostic to a stream.
-void Diagnostic::print(raw_ostream &os) const {
-  for (auto &arg : getArguments())
+/// Outputs this diagnostic to a stream. `ChunkIdx` specifies which chunk to
+/// print to `os`. If empty, all arguments are printed to `os`.
+void Diagnostic::print(raw_ostream &os, std::optional<int64_t> chunkIdx) const {
+  if (!chunkIdx.has_value()) {
+    for (auto &arg : getArguments())
+      arg.print(os);
+    return;
+  }
+
+  assert(0 <= chunkIdx && chunkIdx <= chunkSizes.size());
+  size_t argumentStart = *chunkIdx - 1 >= 0 ? chunkSizes[*chunkIdx - 1] : 0;
+  size_t argumentEnd = *chunkIdx == static_cast<int64_t>(chunkSizes.size())
+                           ? arguments.size()
+                           : chunkSizes[*chunkIdx];
+  for (auto &arg :
+       getArguments().slice(argumentStart, argumentEnd - argumentStart))
     arg.print(os);
 }
 
@@ -175,6 +188,19 @@ std::string Diagnostic::str() const {
   return str;
 }
 
+/// Converts the diagnostic to a vector of strings, where each element
+/// represents a chunk.
+SmallVector<std::string> Diagnostic::strs() const {
+  SmallVector<std::string, 2> strs;
+  for (size_t i = 0, e = chunkSizes.size(); i <= e; ++i) {
+    std::string str;
+    llvm::raw_string_ostream os(str);
+    print(os, i);
+    strs.push_back(str);
+  }
+  return strs;
+}
+
 /// Attaches a note to this diagnostic. A new location may be optionally
 /// provided, if not, then the location defaults to the one specified for this
 /// diagnostic. Notes may not be attached to other notes.
@@ -196,6 +222,16 @@ Diagnostic &Diagnostic::attachNote(std::optional<Location> noteLoc) {
 /// Allow a diagnostic to be converted to 'failure'.
 Diagnostic::operator LogicalResult() const { return failure(); }
 
+/// Finalizes the current group of arguments and starts a new chunk.
+void Diagnostic::checkpointArguments() {
+  size_t size = arguments.size();
+  if (size == 0)
+    return;
+  if (!chunkSizes.empty() && chunkSizes.back() == arguments.size())
+    return;
+  chunkSizes.push_back(arguments.size());
+}
+
 //===----------------------------------------------------------------------===//
 // InFlightDiagnostic
 //===----------------------------------------------------------------------===//
@@ -505,11 +541,13 @@ void SourceMgrDiagnosticHandler::emitDiagnostic(Diagnostic &diag) {
 
   // If the location stack is empty, use the initial location.
   if (locationStack.empty()) {
-    emitDiagnostic(diag.getLocation(), diag.str(), diag.getSeverity());
+    for (const std::string &str : diag.strs())
+      emitDiagnostic(diag.getLocation(), str, diag.getSeverity());
 
     // Otherwise, use the location stack.
   } else {
-    emitDiagnostic(locationStack.front().first, diag.str(), diag.getSeverity());
+    for (const std::string &str : diag.strs())
+      emitDiagnostic(locationStack.front().first, str, diag.getSeverity());
     for (auto &it : llvm::drop_begin(locationStack))
       emitDiagnostic(it.first, it.second, DiagnosticSeverity::Note);
   }
@@ -879,7 +917,8 @@ void SourceMgrDiagnosticVerifierHandler::registerInContext(MLIRContext *ctx) {
 
 /// Process a single diagnostic.
 void SourceMgrDiagnosticVerifierHandler::process(Diagnostic &diag) {
-  return process(diag.getLocation(), diag.str(), diag.getSeverity());
+  for (const std::string &str : diag.strs())
+    process(diag.getLocation(), str, diag.getSeverity());
 }
 
 /// Process a diagnostic at a certain location.
diff --git a/mlir/test/IR/diagnostic-handler-next.mlir b/mlir/test/IR/diagnostic-handler-next.mlir
new file mode 100644
index 0000000000000..9f7b6853ef9f2
--- /dev/null
+++ b/mlir/test/IR/diagnostic-handler-next.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-opt %s -pass-pipeline="builtin.module(func.func(test-diagnostic-next))" -verify-diagnostics 
+
+// expected-remark @+3 {{test1}}
+// expected-remark @+2 {{test3}}
+// expected-remark @+1 {{test2}}
+func.func @test() {
+  return
+}
diff --git a/mlir/test/lib/IR/CMakeLists.txt b/mlir/test/lib/IR/CMakeLists.txt
index 1abcfc77d2d9b..8310edec228c1 100644
--- a/mlir/test/lib/IR/CMakeLists.txt
+++ b/mlir/test/lib/IR/CMakeLists.txt
@@ -7,6 +7,7 @@ add_mlir_library(MLIRTestIR
   TestClone.cpp
   TestDiagnostics.cpp
   TestDiagnosticsMetadata.cpp
+  TestDiagnosticsNext.cpp
   TestDominance.cpp
   TestFunc.cpp
   TestInterfaces.cpp
diff --git a/mlir/test/lib/IR/TestDiagnosticsNext.cpp b/mlir/test/lib/IR/TestDiagnosticsNext.cpp
new file mode 100644
index 0000000000000..5cab0864c4f76
--- /dev/null
+++ b/mlir/test/lib/IR/TestDiagnosticsNext.cpp
@@ -0,0 +1,49 @@
+//===- TestDiagnosticsNext.cpp - Test Diagnostic Utilities ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains test passes for the next diagnostic manipulator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/SymbolTable.h"
+#include "mlir/Pass/Pass.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace mlir;
+
+namespace {
+struct TestDiagnosticsNextPass
+    : public PassWrapper<TestDiagnosticsNextPass,
+                         InterfacePass<SymbolOpInterface>> {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDiagnosticsNextPass)
+
+  StringRef getArgument() const final { return "test-diagnostic-next"; }
+  StringRef getDescription() const final {
+    return "Test diagnostic next support.";
+  }
+
+  void runOnOperation() override {
+    getOperation()->walk([](SymbolOpInterface op) {
+      StringRef opName = op.getNameAttr();
+      InFlightDiagnostic diag = op->emitRemark(opName) << "1" << next;
+      diag << opName << "2" << next << opName << "3";
+    });
+  }
+};
+
+} // namespace
+
+namespace mlir {
+namespace test {
+void registerTestDiagnosticsNextPass() {
+  PassRegistration<TestDiagnosticsNextPass>{};
+}
+} // namespace test
+} // namespace mlir
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index 47dffb1b2d28b..730e48914281a 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -93,6 +93,7 @@ void registerTestDeadCodeAnalysisPass();
 void registerTestDecomposeCallGraphTypes();
 void registerTestDiagnosticsPass();
 void registerTestDiagnosticsMetadataPass();
+void registerTestDiagnosticsNextPass();
 void registerTestDominancePass();
 void registerTestDynamicPipelinePass();
 void registerTestRemarkPass();
@@ -242,6 +243,7 @@ static void registerTestPasses() {
   mlir::test::registerTestDecomposeCallGraphTypes();
   mlir::test::registerTestDiagnosticsPass();
   mlir::test::registerTestDiagnosticsMetadataPass();
+  mlir::test::registerTestDiagnosticsNextPass();
   mlir::test::registerTestDominancePass();
   mlir::test::registerTestDynamicPipelinePass();
   mlir::test::registerTestRemarkPass();

>From 28eaa1d1d9d5c4dca41d0f8b05714a54c07fd236 Mon Sep 17 00:00:00 2001
From: linuxlonelyeagle <2020382038 at qq.com>
Date: Fri, 11 Sep 2026 03:12:06 +0000
Subject: [PATCH 2/4] fix commemt and make code more easy to understand.

---
 mlir/include/mlir/IR/Diagnostics.h | 29 +++++++++++---------
 mlir/lib/IR/Diagnostics.cpp        | 43 +++++++++++++++++-------------
 2 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h
index 8f802c131f3ce..76ecba5cea481 100644
--- a/mlir/include/mlir/IR/Diagnostics.h
+++ b/mlir/include/mlir/IR/Diagnostics.h
@@ -153,6 +153,9 @@ inline raw_ostream &operator<<(raw_ostream &os, const DiagnosticArgument &arg) {
 /// This class contains all of the information necessary to report a diagnostic
 /// to the DiagnosticEngine. It should generally not be constructed directly,
 /// and instead used transitively via InFlightDiagnostic.
+///
+/// A diagnostic may contain multiple message parts that share its location,
+/// severity, metadata, and attached notes. Empty message parts are ignored.
 class Diagnostic {
   using NoteVector = std::vector<std::unique_ptr<Diagnostic>>;
 
@@ -249,16 +252,17 @@ class Diagnostic {
     return *this;
   }
 
-  /// Outputs this diagnostic to a stream. `ChunkIdx` specifies which chunk to
-  /// print to `os`. If empty, all arguments are printed to `os`.
+  /// Outputs this diagnostic to a stream. If `messagePartIndex` is provided,
+  /// only that message part is printed; otherwise, all arguments are printed
+  /// without separators between message parts.
   void print(raw_ostream &os,
-             std::optional<int64_t> chunkIdx = std::nullopt) const;
+             std::optional<int64_t> messagePartIndex = std::nullopt) const;
 
   /// Converts the diagnostic to a string.
   std::string str() const;
 
-  /// Converts the diagnostic to a vector of strings, where each element
-  /// represents a chunk.
+  /// Converts each message part to a separate string. Returns a single string
+  /// if the diagnostic has not been divided into multiple parts.
   SmallVector<std::string> strs() const;
 
   /// Attaches a note to this diagnostic. A new location may be optionally
@@ -294,8 +298,9 @@ class Diagnostic {
   /// Returns the current list of diagnostic metadata.
   SmallVectorImpl<DiagnosticArgument> &getMetadata() { return metadata; }
 
-  /// Finalizes the current group of arguments and starts a new chunk.
-  void checkpointArguments();
+  /// Starts a new message part. This has no effect if the current message part
+  /// is empty.
+  void startNewMessagePart();
 
 private:
   Diagnostic(const Diagnostic &rhs) = delete;
@@ -314,8 +319,8 @@ class Diagnostic {
   /// liveness of non-constant strings used in diagnostics.
   std::vector<std::unique_ptr<char[]>> strings;
 
-  /// Boundary indices in `arguments` that separate different chunks.
-  SmallVector<size_t, 2> chunkSizes;
+  /// The exclusive end indices in `arguments` of completed message parts.
+  SmallVector<size_t, 2> messagePartEnds;
 
   /// A list of attached notes.
   NoteVector notes;
@@ -440,10 +445,10 @@ class InFlightDiagnostic {
   std::optional<Diagnostic> impl;
 };
 
-/// A stream manipulator that checkpoints the current messages, and allowing a
-/// single InFlightDiagnostic to output multiple lines.
+/// Starts a new message part in an in-flight diagnostic. Leading, trailing, and
+/// consecutive uses of `next` do not create empty message parts.
 inline InFlightDiagnostic &next(InFlightDiagnostic &diag) {
-  diag.impl->checkpointArguments();
+  diag.impl->startNewMessagePart();
   return diag;
 }
 
diff --git a/mlir/lib/IR/Diagnostics.cpp b/mlir/lib/IR/Diagnostics.cpp
index a10f581f38522..81e666db48562 100644
--- a/mlir/lib/IR/Diagnostics.cpp
+++ b/mlir/lib/IR/Diagnostics.cpp
@@ -161,20 +161,23 @@ Diagnostic &Diagnostic::operator<<(Value val) {
   return *this << str;
 }
 
-/// Outputs this diagnostic to a stream. `ChunkIdx` specifies which chunk to
-/// print to `os`. If empty, all arguments are printed to `os`.
-void Diagnostic::print(raw_ostream &os, std::optional<int64_t> chunkIdx) const {
-  if (!chunkIdx.has_value()) {
+/// Outputs this diagnostic to a stream.
+void Diagnostic::print(raw_ostream &os,
+                       std::optional<int64_t> messagePartIndex) const {
+  if (!messagePartIndex.has_value()) {
     for (auto &arg : getArguments())
       arg.print(os);
     return;
   }
 
-  assert(0 <= chunkIdx && chunkIdx <= chunkSizes.size());
-  size_t argumentStart = *chunkIdx - 1 >= 0 ? chunkSizes[*chunkIdx - 1] : 0;
-  size_t argumentEnd = *chunkIdx == static_cast<int64_t>(chunkSizes.size())
-                           ? arguments.size()
-                           : chunkSizes[*chunkIdx];
+  assert(0 <= *messagePartIndex &&
+         *messagePartIndex <= static_cast<int64_t>(messagePartEnds.size()));
+  size_t argumentStart =
+      *messagePartIndex == 0 ? 0 : messagePartEnds[*messagePartIndex - 1];
+  size_t argumentEnd =
+      *messagePartIndex == static_cast<int64_t>(messagePartEnds.size())
+          ? arguments.size()
+          : messagePartEnds[*messagePartIndex];
   for (auto &arg :
        getArguments().slice(argumentStart, argumentEnd - argumentStart))
     arg.print(os);
@@ -188,11 +191,16 @@ std::string Diagnostic::str() const {
   return str;
 }
 
-/// Converts the diagnostic to a vector of strings, where each element
-/// represents a chunk.
+/// Converts each message part to a separate string.
 SmallVector<std::string> Diagnostic::strs() const {
   SmallVector<std::string, 2> strs;
-  for (size_t i = 0, e = chunkSizes.size(); i <= e; ++i) {
+  size_t numMessageParts = messagePartEnds.size();
+
+  // Include the current message part if there are no completed parts or if it
+  // contains arguments after the last completed part.
+  if (messagePartEnds.empty() || messagePartEnds.back() != arguments.size())
+    ++numMessageParts;
+  for (size_t i = 0; i < numMessageParts; ++i) {
     std::string str;
     llvm::raw_string_ostream os(str);
     print(os, i);
@@ -222,14 +230,13 @@ Diagnostic &Diagnostic::attachNote(std::optional<Location> noteLoc) {
 /// Allow a diagnostic to be converted to 'failure'.
 Diagnostic::operator LogicalResult() const { return failure(); }
 
-/// Finalizes the current group of arguments and starts a new chunk.
-void Diagnostic::checkpointArguments() {
-  size_t size = arguments.size();
-  if (size == 0)
+/// Starts a new message part.
+void Diagnostic::startNewMessagePart() {
+  if (arguments.empty())
     return;
-  if (!chunkSizes.empty() && chunkSizes.back() == arguments.size())
+  if (!messagePartEnds.empty() && messagePartEnds.back() == arguments.size())
     return;
-  chunkSizes.push_back(arguments.size());
+  messagePartEnds.push_back(arguments.size());
 }
 
 //===----------------------------------------------------------------------===//

>From 622e4d539c00ecd773637913b4ea75b7933975a4 Mon Sep 17 00:00:00 2001
From: lonely eagle <2020382038 at qq.com>
Date: Wed, 23 Sep 2026 21:56:03 +0800
Subject: [PATCH 3/4] Apply suggestion from @joker-eph

Co-authored-by: Mehdi Amini <joker.eph at gmail.com>
---
 mlir/include/mlir/IR/Diagnostics.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h
index 76ecba5cea481..7fba0fed44981 100644
--- a/mlir/include/mlir/IR/Diagnostics.h
+++ b/mlir/include/mlir/IR/Diagnostics.h
@@ -258,7 +258,7 @@ class Diagnostic {
   void print(raw_ostream &os,
              std::optional<int64_t> messagePartIndex = std::nullopt) const;
 
-  /// Converts the diagnostic to a string.
+  /// Converts the diagnostic to a string, concatenating all the parts if there are multiples.
   std::string str() const;
 
   /// Converts each message part to a separate string. Returns a single string

>From ae5d1600036b40093399a15e380b3fd81f7d6e64 Mon Sep 17 00:00:00 2001
From: linuxlonelyeagle <2020382038 at qq.com>
Date: Wed, 23 Sep 2026 16:00:38 +0000
Subject: [PATCH 4/4] make next in diag namespace.

---
 mlir/include/mlir/IR/Diagnostics.h       | 15 ++++++++-----
 mlir/lib/Target/LLVMIR/ModuleImport.cpp  | 28 ++++++++++++------------
 mlir/test/lib/IR/TestDiagnosticsNext.cpp |  4 ++--
 3 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h
index 7fba0fed44981..aae14b3d6e9ec 100644
--- a/mlir/include/mlir/IR/Diagnostics.h
+++ b/mlir/include/mlir/IR/Diagnostics.h
@@ -258,7 +258,8 @@ class Diagnostic {
   void print(raw_ostream &os,
              std::optional<int64_t> messagePartIndex = std::nullopt) const;
 
-  /// Converts the diagnostic to a string, concatenating all the parts if there are multiples.
+  /// Converts the diagnostic to a string, concatenating all the parts if there
+  /// are multiples.
   std::string str() const;
 
   /// Converts each message part to a separate string. Returns a single string
@@ -338,6 +339,12 @@ inline raw_ostream &operator<<(raw_ostream &os, const Diagnostic &diag) {
 // InFlightDiagnostic
 //===----------------------------------------------------------------------===//
 
+namespace diag {
+/// Starts a new message part in an in-flight diagnostic. Leading, trailing, and
+/// consecutive uses of `next` do not create empty message parts.
+inline InFlightDiagnostic &next(InFlightDiagnostic &diag);
+} // namespace diag
+
 /// This class represents a diagnostic that is inflight and set to be reported.
 /// This allows for last minute modifications of the diagnostic before it is
 /// emitted by a DiagnosticEngine.
@@ -436,7 +443,7 @@ class InFlightDiagnostic {
 
   // Allow access to the constructor.
   friend DiagnosticEngine;
-  friend inline InFlightDiagnostic &next(InFlightDiagnostic &diag);
+  friend inline InFlightDiagnostic &diag::next(InFlightDiagnostic &diag);
 
   /// The engine that this diagnostic is to report to.
   DiagnosticEngine *owner = nullptr;
@@ -445,9 +452,7 @@ class InFlightDiagnostic {
   std::optional<Diagnostic> impl;
 };
 
-/// Starts a new message part in an in-flight diagnostic. Leading, trailing, and
-/// consecutive uses of `next` do not create empty message parts.
-inline InFlightDiagnostic &next(InFlightDiagnostic &diag) {
+inline InFlightDiagnostic &diag::next(InFlightDiagnostic &diag) {
   diag.impl->startNewMessagePart();
   return diag;
 }
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 04f69433b97a0..b95a1d00dd5ab 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1167,13 +1167,13 @@ LogicalResult ModuleImport::convertGlobals() {
         globalVar.getName() == getGlobalDtorsVarName()) {
       if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
         return emitError(UnknownLoc::get(context))
-               << "unhandled global variable: " << diag(globalVar);
+               << "unhandled global variable: " << ::diag(globalVar);
       }
       continue;
     }
     if (failed(convertGlobal(&globalVar))) {
       return emitError(UnknownLoc::get(context))
-             << "unhandled global variable: " << diag(globalVar);
+             << "unhandled global variable: " << ::diag(globalVar);
     }
   }
   return success();
@@ -1183,7 +1183,7 @@ LogicalResult ModuleImport::convertAliases() {
   for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
     if (failed(convertAlias(&alias))) {
       return emitError(UnknownLoc::get(context))
-             << "unhandled global alias: " << diag(alias);
+             << "unhandled global alias: " << ::diag(alias);
     }
   }
   return success();
@@ -1193,7 +1193,7 @@ LogicalResult ModuleImport::convertIFuncs() {
   for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
     if (failed(convertIFunc(&ifunc))) {
       return emitError(UnknownLoc::get(context))
-             << "unhandled global ifunc: " << diag(ifunc);
+             << "unhandled global ifunc: " << ::diag(ifunc);
     }
   }
   return success();
@@ -1255,7 +1255,7 @@ void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
         Location loc = debugImporter->translateLoc(inst->getDebugLoc());
         emitWarning(loc) << "unhandled metadata: "
                          << diagMD(node, llvmModule.get()) << " on "
-                         << diag(*inst);
+                         << ::diag(*inst);
       }
     }
   }
@@ -1726,7 +1726,7 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
     if (!symbolRef) {
       emitWarning(globalOp.getLoc()) << "unhandled associated metadata: "
                                      << diagMD(associatedMD, llvmModule.get())
-                                     << " on " << diag(*globalVar);
+                                     << " on " << ::diag(*globalVar);
     } else {
       globalOp.setAssociatedAttr(symbolRef);
     }
@@ -2047,7 +2047,7 @@ FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
   if (isa<llvm::GlobalValue>(constant))
     error = " since global value is unsupported";
 
-  return emitError(loc) << "unhandled constant: " << diag(*constant) << error;
+  return emitError(loc) << "unhandled constant: " << ::diag(*constant) << error;
 }
 
 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
@@ -2113,7 +2113,7 @@ FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
   Location loc = UnknownLoc::get(context);
   if (auto *inst = dyn_cast<llvm::Instruction>(value))
     loc = translateLoc(inst->getDebugLoc());
-  return emitError(loc) << "unhandled value: " << diag(*value);
+  return emitError(loc) << "unhandled value: " << ::diag(*value);
 }
 
 FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) {
@@ -2419,7 +2419,7 @@ LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
     return success();
 
   Location loc = translateLoc(inst->getDebugLoc());
-  return emitError(loc) << "unhandled intrinsic: " << diag(*inst);
+  return emitError(loc) << "unhandled intrinsic: " << ::diag(*inst);
 }
 
 ArrayAttr
@@ -2772,7 +2772,7 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
   if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
     return success();
 
-  return emitError(loc) << "unhandled instruction: " << diag(*inst);
+  return emitError(loc) << "unhandled instruction: " << ::diag(*inst);
 }
 
 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
@@ -3405,7 +3405,7 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) {
         return;
       emitWarning(funcOp.getLoc())
           << "unhandled function metadata: "
-          << diagMD(metadataNode, llvmModule.get()) << " on " << diag(*func);
+          << diagMD(metadataNode, llvmModule.get()) << " on " << ::diag(*func);
     };
 
     if (iface.isConvertibleMetadata(kind)) {
@@ -3551,7 +3551,7 @@ ModuleImport::processDebugOpArgumentsAndInsertionPt(
     return {};
   FailureOr<Value> argOperand = convertArgOperandToValue();
   if (failed(argOperand)) {
-    emitError(loc) << "failed to convert a debug operand: " << diag(*address);
+    emitError(loc) << "failed to convert a debug operand: " << ::diag(*address);
     return {};
   }
 
@@ -3569,7 +3569,7 @@ ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
   Location loc = translateLoc(dbgIntr->getDebugLoc());
   auto emitUnsupportedWarning = [&]() {
     if (emitExpensiveWarnings)
-      emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
+      emitWarning(loc) << "dropped intrinsic: " << ::diag(*dbgIntr);
     return success();
   };
 
@@ -3719,7 +3719,7 @@ LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
     } else if (inst.getOpcode() != llvm::Instruction::PHI) {
       if (emitExpensiveWarnings) {
         Location loc = debugImporter->translateLoc(inst.getDebugLoc());
-        emitWarning(loc) << "dropped instruction: " << diag(inst);
+        emitWarning(loc) << "dropped instruction: " << ::diag(inst);
       }
     }
   }
diff --git a/mlir/test/lib/IR/TestDiagnosticsNext.cpp b/mlir/test/lib/IR/TestDiagnosticsNext.cpp
index 5cab0864c4f76..2026e80b050d3 100644
--- a/mlir/test/lib/IR/TestDiagnosticsNext.cpp
+++ b/mlir/test/lib/IR/TestDiagnosticsNext.cpp
@@ -32,8 +32,8 @@ struct TestDiagnosticsNextPass
   void runOnOperation() override {
     getOperation()->walk([](SymbolOpInterface op) {
       StringRef opName = op.getNameAttr();
-      InFlightDiagnostic diag = op->emitRemark(opName) << "1" << next;
-      diag << opName << "2" << next << opName << "3";
+      InFlightDiagnostic diag = op->emitRemark(opName) << "1" << diag::next;
+      diag << opName << "2" << diag::next << opName << "3";
     });
   }
 };



More information about the Mlir-commits mailing list