[llvm-branch-commits] [llvm] [Support] Track verify directives per buffer instead of per file name (PR #233306)

Alexander Richardson via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Oct 18 15:10:04 PDT 2026


https://github.com/arichardson created https://github.com/llvm/llvm-project/pull/233306

Expected diagnostics were keyed by buffer identifier, so buffers with
the same name (or no name) shared one list, and a diagnostic in one
buffer could match a directive in another. Key them by buffer instead,
and check them in buffer registration order so that the output is
deterministic.

Assisted-by: AI tooling

>From 4e311b62ba4c896b959d976a9db6c268664c4a36 Mon Sep 17 00:00:00 2001
From: Alex Richardson <alexrichardson at google.com>
Date: Sun, 18 Oct 2026 15:09:10 -0700
Subject: [PATCH] [nspr] initial commit

---
 .../Support/SourceMgrDiagnosticVerifier.h     | 12 +++++-----
 .../Support/SourceMgrDiagnosticVerifier.cpp   | 24 ++++++++++---------
 .../SourceMgrDiagnosticVerifierTest.cpp       | 17 +++++++++++++
 3 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
index 5389ddf09701a..359aba7f3fcae 100644
--- a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
+++ b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
@@ -17,8 +17,8 @@
 #define LLVM_SUPPORT_SOURCEMGRDIAGNOSTICVERIFIER_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/SourceMgr.h"
@@ -134,8 +134,8 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
   /// 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.
+  /// Scans \p Buf for expected diagnostics, if it has not been scanned yet,
+  /// and returns its list.
   MutableArrayRef<ExpectedDiag> computeExpectedDiags(const MemoryBuffer *Buf);
 
   const SourceMgr &Mgr;
@@ -147,9 +147,9 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
   /// The strings that start a comment, see the constructor.
   SmallVector<std::string, 0> CommentPrefixes;
 
-  /// The expected diagnostics for each buffer that has been scanned so far,
-  /// keyed by buffer identifier (i.e. file name).
-  StringMap<SmallVector<ExpectedDiag, 2>> ExpectedDiagsPerFile;
+  /// The expected diagnostics for each buffer that has been scanned so far.
+  DenseMap<const MemoryBuffer *, SmallVector<ExpectedDiag, 2>>
+      ExpectedDiagsPerBuffer;
 
   /// The expected diagnostics with an '@unknown' location.
   SmallVector<ExpectedDiag, 2> ExpectedUnknownLocDiags;
diff --git a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
index 95b053967eca4..ef0b4373b5cc7 100644
--- a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
+++ b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
@@ -122,7 +122,10 @@ SourceMgrDiagnosticVerifier::computeExpectedDiags(const MemoryBuffer *Buf) {
   // If the buffer is invalid, return an empty list.
   if (!Buf)
     return {};
-  auto &ExpectedDiags = ExpectedDiagsPerFile[Buf->getBufferIdentifier()];
+  auto [It, Inserted] = ExpectedDiagsPerBuffer.try_emplace(Buf);
+  if (!Inserted)
+    return It->second;
+  auto &ExpectedDiags = It->second;
 
   // The number of the last line that did not correlate to a designator.
   unsigned LastNonDesignatorLine = 0;
@@ -250,13 +253,7 @@ SourceMgrDiagnosticVerifier::process(SourceMgr::DiagKind Kind,
   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 (Loc->Buf) {
-      auto It = ExpectedDiagsPerFile.find(Loc->Buf->getBufferIdentifier());
-      if (It != ExpectedDiagsPerFile.end())
-        Diags = It->second;
-      else
-        Diags = computeExpectedDiags(Loc->Buf);
-    }
+    Diags = computeExpectedDiags(Loc->Buf);
   } else {
     Diags = ExpectedUnknownLocDiags;
   }
@@ -328,11 +325,16 @@ bool SourceMgrDiagnosticVerifier::verify() {
       emitError(Diag, "expected " + getDiagKindStr(Diag.Kind) + " \"" +
                           Diag.Substring + "\" was not produced");
   };
-  for (auto &ExpectedDiagsPair : ExpectedDiagsPerFile)
-    for (const ExpectedDiag &Diag : ExpectedDiagsPair.second)
+  // Check buffers in registration order so that the output is deterministic.
+  for (unsigned I = 0, E = Mgr.getNumBuffers(); I != E; ++I) {
+    auto It = ExpectedDiagsPerBuffer.find(Mgr.getMemoryBuffer(I + 1));
+    if (It == ExpectedDiagsPerBuffer.end())
+      continue;
+    for (const ExpectedDiag &Diag : It->second)
       CheckExpectedDiags(Diag);
+  }
   for (const ExpectedDiag &Diag : ExpectedUnknownLocDiags)
     CheckExpectedDiags(Diag);
-  ExpectedDiagsPerFile.clear();
+  ExpectedDiagsPerBuffer.clear();
   return OK;
 }
diff --git a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
index 58df0a59bf2c1..713fb17bbc6d9 100644
--- a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
+++ b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
@@ -195,3 +195,20 @@ TEST_F(SourceMgrDiagnosticVerifierTest, OutOfBoundsLineOffsets) {
   EXPECT_NE(StringRef(Output).find("error: invalid line offset '+99999999999'"),
             StringRef::npos);
 }
+
+TEST_F(SourceMgrDiagnosticVerifierTest, BuffersWithSameName) {
+  const MemoryBuffer *Buf1 =
+      addBuffer("op\n# expected-error at -1 {{first}}\n", "same.s");
+  const MemoryBuffer *Buf2 =
+      addBuffer("op\n# expected-error at -1 {{second}}\n", "same.s");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+
+  // Directives only match diagnostics in their own buffer.
+  EXPECT_EQ(Verifier.process(getMessage(Buf2, SourceMgr::DK_Error, "first")),
+            MatchResult::Unexpected);
+  EXPECT_EQ(Verifier.process(getMessage(Buf1, SourceMgr::DK_Error, "first")),
+            MatchResult::Matched);
+  EXPECT_EQ(Verifier.process(getMessage(Buf2, SourceMgr::DK_Error, "second")),
+            MatchResult::Matched);
+  EXPECT_FALSE(Verifier.verify());
+}



More information about the llvm-branch-commits mailing list