https://github.com/arichardson updated 
https://github.com/llvm/llvm-project/pull/227567

>From be7473d07b59c32938d2b04942265de5354fd868 Mon Sep 17 00:00:00 2001
From: Alex Richardson <[email protected]>
Date: Tue, 20 Oct 2026 14:56:03 -0700
Subject: [PATCH] [nspr] initial commit

---
 .../Support/SourceMgrDiagnosticVerifier.h     | 101 +++++++-------
 .../Support/SourceMgrDiagnosticVerifier.cpp   | 126 ++++++++++--------
 llvm/unittests/Support/CMakeLists.txt         |   1 +
 .../SourceMgrDiagnosticVerifierTest.cpp       | 123 +++++++++++++++++
 .../secondary/llvm/unittests/Support/BUILD.gn |   1 +
 mlir/lib/IR/Diagnostics.cpp                   |  29 ++--
 6 files changed, 260 insertions(+), 121 deletions(-)
 create mode 100644 llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp

diff --git a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h 
b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
index 0a81f461d618c..b4a6867ba7f57 100644
--- a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
+++ b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
@@ -43,14 +43,47 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
     /// The diagnostic's text matched an expected diagnostic, but its kind
     /// didn't; a message about this has already been printed.
     NearMiss,
-    /// The diagnostic did not match any expected diagnostic. The caller is
-    /// responsible for reporting it, if desired.
+    /// The diagnostic did not match any expected diagnostic.
     Unexpected,
     /// The diagnostic did not match, but \p reportUnexpected was false, so
     /// nothing was printed and nothing needs to be done.
     Ignored,
   };
 
+  /// The location of an actual diagnostic.
+  struct Location {
+    /// The buffer containing the diagnostic, or null if it is in a file that
+    /// is not known to the SourceMgr (such a diagnostic never matches).
+    const MemoryBuffer *buf;
+    /// The 1-based line number of the diagnostic.
+    unsigned lineNo;
+  };
+
+  /// Scans all buffers currently registered with \p mgr for expected
+  /// diagnostics. Buffers added later are scanned the first time a
+  /// diagnostic is reported in them. Verifier errors (near misses, unmatched
+  /// expected diagnostics, malformed directives) are printed to \p os,
+  /// bypassing \p mgr's diagnostic handler.
+  SourceMgrDiagnosticVerifier(const SourceMgr &mgr, raw_ostream &os);
+
+  /// Matches a diagnostic against the expected diagnostics for \p loc, or
+  /// against the '@unknown' expected diagnostics if \p loc is std::nullopt.
+  /// Prints a message on a near miss. Reporting an unexpected diagnostic is
+  /// left to the caller. If \p reportUnexpected is false, a diagnostic that
+  /// does not match is ignored instead of failing verification.
+  MatchResult process(SourceMgr::DiagKind kind, std::optional<Location> loc,
+                      StringRef message, bool reportUnexpected = true);
+
+  /// Like the overload above, but takes the location from \p diag and also
+  /// prints \p diag if it is unexpected.
+  MatchResult process(const SMDiagnostic &diag, bool reportUnexpected = true);
+
+  /// Reports any expected diagnostic that was never matched by a call to
+  /// \c process. Returns whether verification succeeded overall, i.e. no
+  /// diagnostic mismatches were recorded either here or by \c process.
+  bool verify();
+
+private:
   /// A single diagnostic expected via an 'expected-<kind>' comment.
   struct ExpectedDiag {
     ExpectedDiag(SourceMgr::DiagKind kind, unsigned lineNo, SMLoc fileLoc,
@@ -60,16 +93,6 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
     /// Returns true if this diagnostic matches the given message.
     LLVM_ABI bool match(StringRef str) const;
 
-    /// Computes the regex matcher for a '-re' diagnostic's substring.
-    /// Returns false and prints a message through \p mgr on error.
-    LLVM_ABI bool computeRegex(raw_ostream &os, SourceMgr &mgr);
-
-    /// Prints \p msg at this diagnostic's location and returns false, for
-    /// use as `return emitError(...);` in functions that report failure via
-    /// a bool return.
-    LLVM_ABI bool emitError(raw_ostream &os, SourceMgr &mgr,
-                            const Twine &msg) const;
-
     /// The severity of the diagnostic expected.
     SourceMgr::DiagKind kind;
     /// The line number the expected diagnostic should be on.
@@ -85,45 +108,25 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
     std::optional<Regex> substringRegex;
   };
 
-  SourceMgrDiagnosticVerifier() = default;
-
-  /// Computes and caches the list of expected diagnostics for \p buf, if not
-  /// already cached. Returns the (mutable) cached list.
-  MutableArrayRef<ExpectedDiag> computeExpectedDiags(raw_ostream &os,
-                                                     SourceMgr &mgr,
-                                                     const MemoryBuffer *buf);
-
-  /// Returns the cached expected diagnostics for the buffer named \p bufName,
-  /// or std::nullopt if \p computeExpectedDiags hasn't been called for it.
-  std::optional<MutableArrayRef<ExpectedDiag>>
-  getExpectedDiags(StringRef bufName);
-
-  /// Returns the expected diagnostics with an '@unknown' location.
-  MutableArrayRef<ExpectedDiag> getExpectedUnknownLocDiags() {
-    return expectedUnknownLocDiags;
-  }
-
-  /// Matches a single actual diagnostic against the expected diagnostics
-  /// recorded for \p buf / \p lineNo, computing them first via \p
-  /// computeExpectedDiags if they haven't been already. If \p hasLoc is
-  /// false, the diagnostic has no location and is matched against the
-  /// '@unknown' list instead (\p buf / \p lineNo are ignored). If \p hasLoc
-  /// is true but \p buf is null (e.g. the diagnostic's file isn't a known
-  /// buffer), the diagnostic is matched against an empty list, i.e. it can
-  /// never match and is always unexpected. On a near miss, prints a message
-  /// through \p mgr. \p reportUnexpected controls whether near misses /
-  /// unexpected diagnostics are reported at all.
-  MatchResult process(raw_ostream &os, SourceMgr &mgr, SourceMgr::DiagKind 
kind,
-                      bool hasLoc, const MemoryBuffer *buf, unsigned lineNo,
-                      StringRef message, bool reportUnexpected = true);
+  /// Prints \p diag to \c os, bypassing the SourceMgr's diagnostic handler so
+  /// that a verifier installed as that handler does not re-enter itself.
+  void printDiag(const SMDiagnostic &diag) const;
 
-  /// Reports (through \p mgr) any expected diagnostic that was never matched
-  /// by a call to \p process. Returns whether verification succeeded overall,
-  /// i.e. no diagnostic mismatches were recorded either here or by \p
-  /// process.
-  bool verify(raw_ostream &os, SourceMgr &mgr);
+  /// Records a verification failure, prints \p msg at \p diag's location and
+  /// returns false.
+  bool emitError(const ExpectedDiag &diag, const Twine &msg);
+
+  /// Computes the regex matcher for a '-re' diagnostic's substring. Returns
+  /// false and prints a message on error.
+  bool computeRegex(ExpectedDiag &diag);
+
+  /// Scans \p buf for expected diagnostics and returns the list for its
+  /// buffer identifier.
+  MutableArrayRef<ExpectedDiag> computeExpectedDiags(const MemoryBuffer *buf);
+
+  const SourceMgr &mgr;
+  raw_ostream &os;
 
-private:
   /// Regex used to recognize 'expected-<kind>' comments.
   Regex expected{"expected-(error|note|remark|warning)(-re)? "
                  "*(@([+-][0-9]+|above|below|unknown))? *{{(.*)}}$"};
diff --git a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp 
b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
index 1e33637f05bc4..cae1b3be6b0e1 100644
--- a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
+++ b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
@@ -12,6 +12,13 @@
 
 using namespace llvm;
 
+SourceMgrDiagnosticVerifier::SourceMgrDiagnosticVerifier(const SourceMgr &mgr,
+                                                         raw_ostream &os)
+    : mgr(mgr), os(os) {
+  for (unsigned i = 0, e = mgr.getNumBuffers(); i != e; ++i)
+    (void)computeExpectedDiags(mgr.getMemoryBuffer(i + 1));
+}
+
 /// Given a diagnostic kind, return a human readable string for it.
 static StringRef getDiagKindStr(SourceMgr::DiagKind kind) {
   switch (kind) {
@@ -27,15 +34,23 @@ static StringRef getDiagKindStr(SourceMgr::DiagKind kind) {
   llvm_unreachable("Unknown SourceMgr::DiagKind");
 }
 
-bool SourceMgrDiagnosticVerifier::ExpectedDiag::emitError(
-    raw_ostream &os, SourceMgr &mgr, const Twine &msg) const {
-  if (fileLoc.isValid()) {
-    SMRange range(fileLoc, SMLoc::getFromPointer(fileLoc.getPointer() +
-                                                 substring.size()));
-    mgr.PrintMessage(os, fileLoc, SourceMgr::DK_Error, msg, range);
-  } else {
-    mgr.PrintMessage(os, fileLoc, SourceMgr::DK_Error, msg);
+void SourceMgrDiagnosticVerifier::printDiag(const SMDiagnostic &diag) const {
+  mgr.printIncludeStackForDiagnostic(diag.getLoc(), os);
+  diag.print(nullptr, os);
+}
+
+bool SourceMgrDiagnosticVerifier::emitError(const ExpectedDiag &diag,
+                                            const Twine &msg) {
+  ok = false;
+  SMRange range;
+  ArrayRef<SMRange> ranges;
+  if (diag.fileLoc.isValid()) {
+    range =
+        SMRange(diag.fileLoc, SMLoc::getFromPointer(diag.fileLoc.getPointer() +
+                                                    diag.substring.size()));
+    ranges = range;
   }
+  printDiag(mgr.GetMessage(diag.fileLoc, SourceMgr::DK_Error, msg, ranges));
   return false;
 }
 
@@ -47,43 +62,40 @@ bool 
SourceMgrDiagnosticVerifier::ExpectedDiag::match(StringRef str) const {
   return str.contains(substring);
 }
 
-bool SourceMgrDiagnosticVerifier::ExpectedDiag::computeRegex(raw_ostream &os,
-                                                             SourceMgr &mgr) {
+bool SourceMgrDiagnosticVerifier::computeRegex(ExpectedDiag &diag) {
   std::string regexStr;
-  raw_string_ostream regexOS(regexStr);
-  StringRef strToProcess = substring;
+  raw_string_ostream regexOs(regexStr);
+  StringRef strToProcess = diag.substring;
   while (!strToProcess.empty()) {
     // Find the next regex block.
     size_t regexIt = strToProcess.find("{{");
     if (regexIt == StringRef::npos) {
-      regexOS << Regex::escape(strToProcess);
+      regexOs << Regex::escape(strToProcess);
       break;
     }
-    regexOS << Regex::escape(strToProcess.take_front(regexIt));
+    regexOs << Regex::escape(strToProcess.take_front(regexIt));
     strToProcess = strToProcess.drop_front(regexIt + 2);
 
     // Find the end of the regex block.
     size_t regexEndIt = strToProcess.find("}}");
     if (regexEndIt == StringRef::npos)
-      return emitError(os, mgr, "found start of regex with no end '}}'");
+      return emitError(diag, "found start of regex with no end '}}'");
     StringRef regexBlock = strToProcess.take_front(regexEndIt);
 
     // Validate that the regex is actually valid.
     std::string regexError;
     if (!Regex(regexBlock).isValid(regexError))
-      return emitError(os, mgr, "invalid regex: " + regexError);
+      return emitError(diag, "invalid regex: " + regexError);
 
-    regexOS << '(' << regexBlock << ')';
+    regexOs << '(' << regexBlock << ')';
     strToProcess = strToProcess.drop_front(regexEndIt + 2);
   }
-  substringRegex = Regex(regexStr);
+  diag.substringRegex = Regex(regexStr);
   return true;
 }
 
 MutableArrayRef<SourceMgrDiagnosticVerifier::ExpectedDiag>
-SourceMgrDiagnosticVerifier::computeExpectedDiags(raw_ostream &os,
-                                                  SourceMgr &mgr,
-                                                  const MemoryBuffer *buf) {
+SourceMgrDiagnosticVerifier::computeExpectedDiags(const MemoryBuffer *buf) {
   // If the buffer is invalid, return an empty list.
   if (!buf)
     return {};
@@ -128,10 +140,8 @@ 
SourceMgrDiagnosticVerifier::computeExpectedDiags(raw_ostream &os,
     ExpectedDiag record(kind, lineNo + 1, expectedStart, matches[5]);
 
     // Check to see if this is a regex match, i.e. it includes the `-re`.
-    if (!matches[2].empty() && !record.computeRegex(os, mgr)) {
-      ok = false;
+    if (!matches[2].empty() && !computeRegex(record))
       continue;
-    }
 
     StringRef offsetMatch = matches[3];
     if (!offsetMatch.empty()) {
@@ -171,28 +181,20 @@ 
SourceMgrDiagnosticVerifier::computeExpectedDiags(raw_ostream &os,
   return expectedDiags;
 }
 
-std::optional<MutableArrayRef<SourceMgrDiagnosticVerifier::ExpectedDiag>>
-SourceMgrDiagnosticVerifier::getExpectedDiags(StringRef bufName) {
-  auto expectedDiags = expectedDiagsPerFile.find(bufName);
-  if (expectedDiags != expectedDiagsPerFile.end())
-    return MutableArrayRef<ExpectedDiag>(expectedDiags->second);
-  return std::nullopt;
-}
-
 SourceMgrDiagnosticVerifier::MatchResult
-SourceMgrDiagnosticVerifier::process(raw_ostream &os, SourceMgr &mgr,
-                                     SourceMgr::DiagKind kind, bool hasLoc,
-                                     const MemoryBuffer *buf, unsigned lineNo,
+SourceMgrDiagnosticVerifier::process(SourceMgr::DiagKind kind,
+                                     std::optional<Location> loc,
                                      StringRef message, bool reportUnexpected) 
{
   MutableArrayRef<ExpectedDiag> diags;
-  if (hasLoc) {
+  if (loc) {
     // If the buffer couldn't be resolved, `diags` stays empty: a diagnostic
     // with a location in an unknown file can never match anything.
-    if (buf) {
-      if (auto maybeDiags = getExpectedDiags(buf->getBufferIdentifier()))
-        diags = *maybeDiags;
+    if (loc->buf) {
+      auto it = expectedDiagsPerFile.find(loc->buf->getBufferIdentifier());
+      if (it != expectedDiagsPerFile.end())
+        diags = it->second;
       else
-        diags = computeExpectedDiags(os, mgr, buf);
+        diags = computeExpectedDiags(loc->buf);
     }
   } else {
     diags = expectedUnknownLocDiags;
@@ -205,7 +207,7 @@ SourceMgrDiagnosticVerifier::process(raw_ostream &os, 
SourceMgr &mgr,
   // If this was an expected error, remember that we saw it and return.
   for (auto &e : diags) {
     // File line must match (unless it's an unknown location).
-    if (hasLoc && e.lineNo != lineNo)
+    if (loc && e.lineNo != loc->lineNo)
       continue;
     if (e.match(message)) {
       if (e.kind == kind) {
@@ -226,29 +228,43 @@ SourceMgrDiagnosticVerifier::process(raw_ostream &os, 
SourceMgr &mgr,
 
   // Otherwise, emit an error for the near miss.
   if (nearMiss) {
-    mgr.PrintMessage(os, nearMiss->fileLoc, SourceMgr::DK_Error,
-                     "'" + getDiagKindStr(kind) +
-                         "' diagnostic emitted when expecting a '" +
-                         getDiagKindStr(nearMiss->kind) + "'");
+    printDiag(mgr.GetMessage(nearMiss->fileLoc, SourceMgr::DK_Error,
+                             "'" + getDiagKindStr(kind) +
+                                 "' diagnostic emitted when expecting a '" +
+                                 getDiagKindStr(nearMiss->kind) + "'"));
     return MatchResult::NearMiss;
   }
   return MatchResult::Unexpected;
 }
 
-bool SourceMgrDiagnosticVerifier::verify(raw_ostream &os, SourceMgr &mgr) {
+SourceMgrDiagnosticVerifier::MatchResult
+SourceMgrDiagnosticVerifier::process(const SMDiagnostic &diag,
+                                     bool reportUnexpected) {
+  std::optional<Location> loc;
+  if (diag.getLoc().isValid()) {
+    const MemoryBuffer *buf = nullptr;
+    if (unsigned id = mgr.FindBufferContainingLoc(diag.getLoc()))
+      buf = mgr.getMemoryBuffer(id);
+    loc = Location{buf, static_cast<unsigned>(diag.getLineNo())};
+  }
+  MatchResult result =
+      process(diag.getKind(), loc, diag.getMessage(), reportUnexpected);
+  if (result == MatchResult::Unexpected)
+    printDiag(diag);
+  return result;
+}
+
+bool SourceMgrDiagnosticVerifier::verify() {
   // Verify that all expected errors were seen.
-  auto checkExpectedDiags = [&](ExpectedDiag &diag) {
-    if (!diag.matched) {
-      diag.emitError(os, mgr,
-                     "expected " + getDiagKindStr(diag.kind) + " \"" +
-                         diag.substring + "\" was not produced");
-      ok = false;
-    }
+  auto checkExpectedDiags = [&](const ExpectedDiag &diag) {
+    if (!diag.matched)
+      emitError(diag, "expected " + getDiagKindStr(diag.kind) + " \"" +
+                          diag.substring + "\" was not produced");
   };
   for (auto &expectedDiagsPair : expectedDiagsPerFile)
-    for (auto &diag : expectedDiagsPair.second)
+    for (const ExpectedDiag &diag : expectedDiagsPair.second)
       checkExpectedDiags(diag);
-  for (auto &diag : expectedUnknownLocDiags)
+  for (const ExpectedDiag &diag : expectedUnknownLocDiags)
     checkExpectedDiags(diag);
   expectedDiagsPerFile.clear();
   return ok;
diff --git a/llvm/unittests/Support/CMakeLists.txt 
b/llvm/unittests/Support/CMakeLists.txt
index f9732ff4e0e4b..c5db78950d21b 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -90,6 +90,7 @@ add_llvm_unittest(SupportTests
   SignalsTest.cpp
   SipHashTest.cpp
   SourceMgrTest.cpp
+  SourceMgrDiagnosticVerifierTest.cpp
   SpecialCaseListTest.cpp
   SuffixTreeTest.cpp
   SwapByteOrderTest.cpp
diff --git a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp 
b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
new file mode 100644
index 0000000000000..5f731293a5c50
--- /dev/null
+++ b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
@@ -0,0 +1,123 @@
+//===- unittests/Support/SourceMgrDiagnosticVerifierTest.cpp 
--------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgrDiagnosticVerifier.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using MatchResult = SourceMgrDiagnosticVerifier::MatchResult;
+
+namespace {
+
+class SourceMgrDiagnosticVerifierTest : public testing::Test {
+protected:
+  SourceMgr SM;
+  std::string Output;
+  raw_string_ostream OS{Output};
+
+  const MemoryBuffer *addBuffer(StringRef Text,
+                                StringRef BufferName = "test.s") {
+    unsigned ID = SM.AddNewSourceBuffer(
+        MemoryBuffer::getMemBuffer(Text, BufferName), SMLoc());
+    return SM.getMemoryBuffer(ID);
+  }
+
+  SMDiagnostic getMessage(const MemoryBuffer *Buf, SourceMgr::DiagKind Kind,
+                          StringRef Msg) {
+    return SM.GetMessage(SMLoc::getFromPointer(Buf->getBufferStart()), Kind,
+                         Msg);
+  }
+};
+
+} // namespace
+
+TEST_F(SourceMgrDiagnosticVerifierTest, Match) {
+  const MemoryBuffer *Buf =
+      addBuffer("bad_op\n# expected-error@-1 {{invalid operand}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  EXPECT_EQ(
+      Verifier.process(getMessage(Buf, SourceMgr::DK_Error, "invalid 
operand")),
+      MatchResult::Matched);
+  EXPECT_TRUE(Verifier.verify());
+  EXPECT_EQ(Output, "");
+}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, UnknownLocation) {
+  addBuffer("# expected-warning@unknown {{no location warning}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  SMDiagnostic Diag =
+      SM.GetMessage(SMLoc(), SourceMgr::DK_Warning, "no location warning");
+  EXPECT_EQ(Verifier.process(Diag), MatchResult::Matched);
+  EXPECT_TRUE(Verifier.verify());
+  EXPECT_EQ(Output, "");
+}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, UnmatchedUnknownLocation) {
+  addBuffer("# expected-error@unknown {{missing unknown error}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  EXPECT_FALSE(Verifier.verify());
+  EXPECT_NE(
+      StringRef(Output).find(
+          "error: expected error \"missing unknown error\" was not produced"),
+      StringRef::npos);
+}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, ReportUnexpectedFalse) {
+  const MemoryBuffer *Buf =
+      addBuffer("op\n# expected-error@-1 {{expected msg}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  // An unexpected diagnostic with ReportUnexpected = false is ignored and does
+  // not fail verification.
+  EXPECT_EQ(
+      Verifier.process(getMessage(Buf, SourceMgr::DK_Warning, "unrelated"),
+                       /*reportUnexpected=*/false),
+      MatchResult::Ignored);
+  EXPECT_EQ(
+      Verifier.process(getMessage(Buf, SourceMgr::DK_Error, "expected msg"),
+                       /*reportUnexpected=*/false),
+      MatchResult::Matched);
+  EXPECT_TRUE(Verifier.verify());
+  EXPECT_EQ(Output, "");
+}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, UnknownFileNeverMatches) {
+  addBuffer("# expected-error {{anything}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  SourceMgrDiagnosticVerifier::Location Loc{/*buf=*/nullptr, /*lineNo=*/1};
+  EXPECT_EQ(Verifier.process(SourceMgr::DK_Error, Loc, "anything"),
+            MatchResult::Unexpected);
+  EXPECT_FALSE(Verifier.verify());
+}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, InstalledAsDiagHandler) {
+  addBuffer("op\n# expected-warning@-1 {{bad op}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+  SM.setDiagHandler(
+      [](const SMDiagnostic &Diag, void *Ctx) {
+        static_cast<SourceMgrDiagnosticVerifier *>(Ctx)->process(Diag);
+      },
+      &Verifier);
+
+  // The near-miss message must be printed to OS rather than re-entering the
+  // verifier through the SourceMgr's diagnostic handler.
+  SM.PrintMessage(
+      SMLoc::getFromPointer(SM.getMemoryBuffer(1)->getBufferStart()),
+      SourceMgr::DK_Error, "bad op");
+  EXPECT_NE(StringRef(Output).find(
+                "error: 'error' diagnostic emitted when expecting a 
'warning'"),
+            StringRef::npos);
+  EXPECT_FALSE(Verifier.verify());
+}
diff --git a/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn 
b/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn
index 168b609279cab..7569f7e6fcbb9 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn
@@ -93,6 +93,7 @@ unittest("SupportTests") {
     "SignalsTest.cpp",
     "SipHashTest.cpp",
     "SourceMgrTest.cpp",
+    "SourceMgrDiagnosticVerifierTest.cpp",
     "SpecialCaseListTest.cpp",
     "SuffixTreeTest.cpp",
     "SwapByteOrderTest.cpp",
diff --git a/mlir/lib/IR/Diagnostics.cpp b/mlir/lib/IR/Diagnostics.cpp
index 1e0a6aca7f19d..6b048322cbbc5 100644
--- a/mlir/lib/IR/Diagnostics.cpp
+++ b/mlir/lib/IR/Diagnostics.cpp
@@ -641,8 +641,9 @@ namespace mlir {
 namespace detail {
 struct SourceMgrDiagnosticVerifierHandlerImpl {
   SourceMgrDiagnosticVerifierHandlerImpl(
+      llvm::SourceMgr &srcMgr, raw_ostream &out,
       SourceMgrDiagnosticVerifierHandler::Level level)
-      : level(level) {}
+      : verifier(srcMgr, out), level(level) {}
 
   /// The generic SourceMgr-based verifier core that this handler delegates
   /// scanning and matching of 'expected-*' diagnostics to.
@@ -672,13 +673,7 @@ static StringRef getDiagKindStr(DiagnosticSeverity kind) {
 SourceMgrDiagnosticVerifierHandler::SourceMgrDiagnosticVerifierHandler(
     llvm::SourceMgr &srcMgr, MLIRContext *ctx, raw_ostream &out, Level level)
     : SourceMgrDiagnosticHandler(srcMgr, ctx, out),
-      impl(new SourceMgrDiagnosticVerifierHandlerImpl(level)) {
-  // Compute the expected diagnostics for each of the current files in the
-  // source manager.
-  for (unsigned i = 0, e = mgr.getNumBuffers(); i != e; ++i)
-    (void)impl->verifier.computeExpectedDiags(out, mgr,
-                                              mgr.getMemoryBuffer(i + 1));
-
+      impl(new SourceMgrDiagnosticVerifierHandlerImpl(srcMgr, out, level)) {
   // The base class registered a handler that prints every diagnostic. The
   // verifier takes its place: it consumes diagnostics and reports unexpected
   // ones itself.
@@ -698,7 +693,7 @@ 
SourceMgrDiagnosticVerifierHandler::~SourceMgrDiagnosticVerifierHandler() {
 /// diagnostics were emitted. This return success if all diagnostics were
 /// verified correctly, failure otherwise.
 LogicalResult SourceMgrDiagnosticVerifierHandler::verify() {
-  return success(impl->verifier.verify(os, mgr));
+  return success(impl->verifier.verify());
 }
 
 std::unique_ptr<ScopedDiagnosticHandler>
@@ -719,16 +714,16 @@ void 
SourceMgrDiagnosticVerifierHandler::process(Diagnostic &diag) {
 void SourceMgrDiagnosticVerifierHandler::process(LocationAttr loc,
                                                  StringRef msg,
                                                  DiagnosticSeverity kind) {
-  FileLineColLoc fileLoc = loc.findInstanceOf<FileLineColLoc>();
-  const llvm::MemoryBuffer *buf =
-      fileLoc ? getBufferForFile(fileLoc.getFilename()) : nullptr;
+  using Verifier = llvm::SourceMgrDiagnosticVerifier;
+  std::optional<Verifier::Location> verifierLoc;
+  if (FileLineColLoc fileLoc = loc.findInstanceOf<FileLineColLoc>())
+    verifierLoc = Verifier::Location{getBufferForFile(fileLoc.getFilename()),
+                                     fileLoc.getLine()};
   bool reportUnexpected = impl->level != Level::OnlyExpected;
 
-  using MatchResult = llvm::SourceMgrDiagnosticVerifier::MatchResult;
-  MatchResult result = impl->verifier.process(
-      os, mgr, getDiagKind(kind), /*hasLoc=*/static_cast<bool>(fileLoc), buf,
-      fileLoc ? fileLoc.getLine() : 0, msg, reportUnexpected);
-  if (result == MatchResult::Unexpected)
+  Verifier::MatchResult result = impl->verifier.process(
+      getDiagKind(kind), verifierLoc, msg, reportUnexpected);
+  if (result == Verifier::MatchResult::Unexpected)
     emitDiagnostic(loc, "unexpected " + getDiagKindStr(kind) + ": " + msg,
                    DiagnosticSeverity::Error);
 }

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to