[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