[llvm-branch-commits] [llvm] [Support] Check verify directives in buffers without diagnostics (PR #233307)

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


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

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

---
 .../llvm/Support/SourceMgrDiagnosticVerifier.h |  4 ++--
 .../Support/SourceMgrDiagnosticVerifier.cpp    | 18 ++++++++++++------
 llvm/test/tools/llvm-mc/verify/basic.s         | 12 ++++++++++++
 .../SourceMgrDiagnosticVerifierTest.cpp        | 17 +++++++++++++++++
 4 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
index cc1060ab3ccb1..0268be4c64f97 100644
--- a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
+++ b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
@@ -63,8 +63,8 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
   };
 
   /// 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
+  /// diagnostics. Buffers added later are scanned when they are first needed,
+  /// at the latest by \c verify(). Verifier errors (near misses, unmatched
   /// expected diagnostics, malformed directives) are printed to \p os,
   /// bypassing \p mgr's diagnostic handler.
   ///
diff --git a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
index 246813d987180..b1f78f655cb4c 100644
--- a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
+++ b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
@@ -254,6 +254,10 @@ SourceMgrDiagnosticVerifier::process(SourceMgr::DiagKind kind,
     // with a location in an unknown file can never match anything.
     diags = computeExpectedDiags(loc->buf);
   } else {
+    // '@unknown' directives may be in any buffer, including ones added after
+    // the verifier was created.
+    for (unsigned i = 0, e = mgr.getNumBuffers(); i != e; ++i)
+      (void)computeExpectedDiags(mgr.getMemoryBuffer(i + 1));
     diags = expectedUnknownLocDiags;
   }
 
@@ -327,16 +331,18 @@ bool SourceMgrDiagnosticVerifier::verify() {
       emitError(diag, "expected " + getDiagKindStr(diag.kind) + " \"" +
                           diag.substring + "\" was not produced");
   };
-  // Check buffers in registration order so that the output is deterministic.
+  // Check all buffers in registration order, including ones that were added
+  // after the verifier was created and had no diagnostics (e.g. included
+  // files). Clear the lists rather than the map so that calling verify()
+  // again does not rescan the buffers and report their directives again.
   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)
+    const MemoryBuffer *buf = mgr.getMemoryBuffer(i + 1);
+    for (const ExpectedDiag &diag : computeExpectedDiags(buf))
       checkExpectedDiags(diag);
+    expectedDiagsPerBuffer[buf].clear();
   }
   for (const ExpectedDiag &diag : expectedUnknownLocDiags)
     checkExpectedDiags(diag);
-  expectedDiagsPerBuffer.clear();
+  expectedUnknownLocDiags.clear();
   return ok;
 }
diff --git a/llvm/test/tools/llvm-mc/verify/basic.s b/llvm/test/tools/llvm-mc/verify/basic.s
index 787ae59c255f7..063081ef2dcb9 100644
--- a/llvm/test/tools/llvm-mc/verify/basic.s
+++ b/llvm/test/tools/llvm-mc/verify/basic.s
@@ -43,6 +43,10 @@
 # RUN: not llvm-mc --triple=riscv32 --verify duplicate.s 2>&1 \
 # RUN:   | FileCheck duplicate.s --implicit-check-not=error:
 
+## Directives in included files without diagnostics are checked too.
+# RUN: not llvm-mc --triple=riscv32 --verify include.s 2>&1 \
+# RUN:   | FileCheck included.s
+
 ## A file without diagnostics or directives passes.
 # RUN: llvm-mc --triple=riscv32 --verify no-diagnostics.s
 
@@ -160,6 +164,14 @@ addi a0, a0, 1
 # expected-error at -1 {{unknown directive}}
 # CHECK: duplicate.s:1:17: error: unknown directive
 
+#--- include.s
+.include "included.s"
+
+#--- included.s
+addi a0, a0, 1
+# expected-error at -1 {{this will never happen}}
+# CHECK: error: expected error "this will never happen" was not produced
+
 #--- no-diagnostics.s
 addi a0, a0, 1
 
diff --git a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
index 050e1d494bffa..dd22c4a616072 100644
--- a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
+++ b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
@@ -241,3 +241,20 @@ TEST_F(SourceMgrDiagnosticVerifierTest, BuffersWithSameName) {
             MatchResult::Matched);
   EXPECT_FALSE(Verifier.verify());
 }
+
+TEST_F(SourceMgrDiagnosticVerifierTest, BufferAddedLater) {
+  addBuffer("op\n");
+  SourceMgrDiagnosticVerifier Verifier(SM, OS);
+  // E.g. an included file without any diagnostics.
+  addBuffer("op\n# expected-error at -1 {{missing}}\n", "inc.s");
+
+  EXPECT_FALSE(Verifier.verify());
+  EXPECT_NE(StringRef(Output).find(
+                "error: expected error \"missing\" was not produced"),
+            StringRef::npos);
+
+  // Calling verify() again does not report the same directives again.
+  std::string FirstOutput = Output;
+  EXPECT_FALSE(Verifier.verify());
+  EXPECT_EQ(Output, FirstOutput);
+}



More information about the llvm-branch-commits mailing list