[llvm-branch-commits] [llvm] [Support] Prefer unmatched directives when matching diagnostics (PR #233308)

Alexander Richardson via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Oct 20 14:57:46 PDT 2026


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

>From daabda75f0c98f9b47de959e3e5d94e8fd8e4a15 Mon Sep 17 00:00:00 2001
From: Alex Richardson <alexrichardson at google.com>
Date: Tue, 20 Oct 2026 14:56:18 -0700
Subject: [PATCH] [nspr] initial commit

---
 .../Support/SourceMgrDiagnosticVerifier.cpp   | 21 ++++++++----
 .../SourceMgrDiagnosticVerifierTest.cpp       | 33 +++++++++++++++++++
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
index b1f78f655cb4c..1946ff4e6c11f 100644
--- a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
+++ b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
@@ -261,11 +261,13 @@ SourceMgrDiagnosticVerifier::process(SourceMgr::DiagKind kind,
     diags = expectedUnknownLocDiags;
   }
 
-  // Search for a matching expected diagnostic.
+  // Search for a matching expected diagnostic, preferring one that has not
+  // been matched yet so that several directives with overlapping text on the
+  // same line can each match a diagnostic.
   // If we find something that is close then emit a more specific error.
+  ExpectedDiag *alreadyMatched = nullptr;
   ExpectedDiag *nearMiss = nullptr;
 
-  // 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 (loc && e.lineNo != loc->lineNo)
@@ -276,17 +278,24 @@ SourceMgrDiagnosticVerifier::process(SourceMgr::DiagKind kind,
     // A directive that already matched a diagnostic is used up.
     if (oneDiagPerDirective && e.matched)
       continue;
-    if (e.match(message)) {
-      if (e.kind == kind) {
+    if (!e.match(message))
+      continue;
+    if (e.kind == kind) {
+      if (!e.matched) {
         e.matched = true;
         return MatchResult::Matched;
       }
-
+      alreadyMatched = &e;
+    } else if (!e.matched) {
       // If this only differs based on the diagnostic kind, then consider it
-      // to be a near miss.
+      // to be a near miss. A directive that already matched another
+      // diagnostic is not a near miss.
       nearMiss = &e;
     }
   }
+  // Unless oneDiagPerDirective is set, a directive can match again.
+  if (alreadyMatched)
+    return MatchResult::Matched;
 
   if (!reportUnexpected)
     return MatchResult::Ignored;
diff --git a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
index dd22c4a616072..c262ff8162084 100644
--- a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
+++ b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
@@ -258,3 +258,36 @@ TEST_F(SourceMgrDiagnosticVerifierTest, BufferAddedLater) {
   EXPECT_FALSE(Verifier.verify());
   EXPECT_EQ(Output, FirstOutput);
 }
+
+TEST_F(SourceMgrDiagnosticVerifierTest, PreferUnmatchedDirective) {
+  const MemoryBuffer *Buf =
+      addBuffer("op\n"
+                "# expected-error at -1 {{operand}}\n"
+                "# expected-error at -2 {{invalid operand}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  // Both diagnostics match the first directive, but the second one must be
+  // matched by the second directive.
+  EXPECT_EQ(Verifier.process(getMessage(Buf, SourceMgr::DK_Error, "operand")),
+            MatchResult::Matched);
+  EXPECT_EQ(
+      Verifier.process(getMessage(Buf, SourceMgr::DK_Error, "invalid operand")),
+      MatchResult::Matched);
+  EXPECT_TRUE(Verifier.verify());
+  EXPECT_EQ(Output, "");
+}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, AlreadyMatchedIsNotNearMiss) {
+  const MemoryBuffer *Buf = addBuffer("op\n# expected-error at -1 {{operand}}\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  EXPECT_EQ(
+      Verifier.process(getMessage(Buf, SourceMgr::DK_Error, "bad operand")),
+      MatchResult::Matched);
+  EXPECT_EQ(
+      Verifier.process(getMessage(Buf, SourceMgr::DK_Note, "note operand")),
+      MatchResult::Unexpected);
+  EXPECT_FALSE(Verifier.verify());
+  EXPECT_EQ(StringRef(Output).find("diagnostic emitted when expecting"),
+            StringRef::npos);
+}



More information about the llvm-branch-commits mailing list