[llvm-branch-commits] [llvm] [Support] Allow custom prefixes in SourceMgrDiagnosticVerifier (PR #227568)
Alexander Richardson via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 20 14:57:49 PDT 2026
https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/227568
>From a2b05e635901ded6095bdf5a2d5cb4fc938b2c55 Mon Sep 17 00:00:00 2001
From: Alex Richardson <alexrichardson at google.com>
Date: Tue, 20 Oct 2026 14:56:04 -0700
Subject: [PATCH] [nspr] initial commit
---
.../Support/SourceMgrDiagnosticVerifier.h | 11 +++--
.../Support/SourceMgrDiagnosticVerifier.cpp | 46 +++++++++++++------
.../SourceMgrDiagnosticVerifierTest.cpp | 20 ++++++++
3 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
index b4a6867ba7f57..bcd1426e9548f 100644
--- a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
+++ b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
@@ -64,7 +64,11 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
/// 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);
+ ///
+ /// \p prefixes are the directive prefixes to recognize (e.g. "expected"
+ /// for 'expected-error'); they must be non-empty.
+ SourceMgrDiagnosticVerifier(const SourceMgr &mgr, raw_ostream &os,
+ ArrayRef<StringRef> prefixes = {"expected"});
/// Matches a diagnostic against the expected diagnostics for \p loc, or
/// against the '@unknown' expected diagnostics if \p loc is std::nullopt.
@@ -127,9 +131,8 @@ class LLVM_ABI SourceMgrDiagnosticVerifier {
const SourceMgr &mgr;
raw_ostream &os;
- /// Regex used to recognize 'expected-<kind>' comments.
- Regex expected{"expected-(error|note|remark|warning)(-re)? "
- "*(@([+-][0-9]+|above|below|unknown))? *{{(.*)}}$"};
+ /// Regex used to recognize '<prefix>-<kind>' comments.
+ Regex expected;
/// The expected diagnostics for each buffer that has been scanned so far,
/// keyed by buffer identifier (i.e. file name).
diff --git a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
index cae1b3be6b0e1..fac95397e9ecb 100644
--- a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
+++ b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
@@ -7,14 +7,28 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/SourceMgrDiagnosticVerifier.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-SourceMgrDiagnosticVerifier::SourceMgrDiagnosticVerifier(const SourceMgr &mgr,
- raw_ostream &os)
+SourceMgrDiagnosticVerifier::SourceMgrDiagnosticVerifier(
+ const SourceMgr &mgr, raw_ostream &os, ArrayRef<StringRef> prefixes)
: mgr(mgr), os(os) {
+ assert(!prefixes.empty() && "must have at least one prefix");
+ std::string prefixAlt;
+ raw_string_ostream prefixOs(prefixAlt);
+ ListSeparator sep("|");
+ for (StringRef prefix : prefixes) {
+ assert(!prefix.empty() && "prefixes must be non-empty");
+ prefixOs << sep << Regex::escape(prefix);
+ }
+ // Don't match 'expected' inside a longer word such as 'unexpected'.
+ expected = Regex("(^|[^[:alnum:]_-])(" + prefixAlt +
+ ")-(error|note|remark|warning)(-re)?"
+ " *(@([+-][0-9]+|above|below|unknown))? *{{(.*)}}$");
+
for (unsigned i = 0, e = mgr.getNumBuffers(); i != e; ++i)
(void)computeExpectedDiags(mgr.getMemoryBuffer(i + 1));
}
@@ -107,12 +121,16 @@ SourceMgrDiagnosticVerifier::computeExpectedDiags(const MemoryBuffer *buf) {
// The indices of designators that apply to the next non designator line.
SmallVector<unsigned, 1> designatorsForNextLine;
- // Scan the file for expected-* designators.
+ // Scan the file for <prefix>-* designators.
SmallVector<StringRef, 100> lines;
buf->getBuffer().split(lines, '\n');
for (unsigned lineNo = 0, e = lines.size(); lineNo < e; ++lineNo) {
- SmallVector<StringRef, 4> matches;
- if (!expected.match(lines[lineNo].rtrim(), &matches)) {
+ StringRef line = lines[lineNo].rtrim();
+
+ // Every directive contains '{{'; check that first to avoid running the
+ // regex on most lines.
+ SmallVector<StringRef, 8> matches;
+ if (!line.contains("{{") || !expected.match(line, &matches)) {
// Check for designators that apply to this line.
if (!designatorsForNextLine.empty()) {
for (unsigned diagIndex : designatorsForNextLine)
@@ -123,27 +141,27 @@ SourceMgrDiagnosticVerifier::computeExpectedDiags(const MemoryBuffer *buf) {
continue;
}
- // Point to the start of expected-*.
- SMLoc expectedStart = SMLoc::getFromPointer(matches[0].data());
+ // Point to the start of <prefix>-*.
+ SMLoc expectedStart = SMLoc::getFromPointer(matches[2].data());
SourceMgr::DiagKind kind;
- if (matches[1] == "error")
+ if (matches[3] == "error")
kind = SourceMgr::DK_Error;
- else if (matches[1] == "warning")
+ else if (matches[3] == "warning")
kind = SourceMgr::DK_Warning;
- else if (matches[1] == "remark")
+ else if (matches[3] == "remark")
kind = SourceMgr::DK_Remark;
else {
- assert(matches[1] == "note");
+ assert(matches[3] == "note");
kind = SourceMgr::DK_Note;
}
- ExpectedDiag record(kind, lineNo + 1, expectedStart, matches[5]);
+ ExpectedDiag record(kind, lineNo + 1, expectedStart, matches[7]);
// Check to see if this is a regex match, i.e. it includes the `-re`.
- if (!matches[2].empty() && !computeRegex(record))
+ if (!matches[4].empty() && !computeRegex(record))
continue;
- StringRef offsetMatch = matches[3];
+ StringRef offsetMatch = matches[5];
if (!offsetMatch.empty()) {
offsetMatch = offsetMatch.drop_front(1);
diff --git a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
index 5f731293a5c50..19beb0fd98988 100644
--- a/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
+++ b/llvm/unittests/Support/SourceMgrDiagnosticVerifierTest.cpp
@@ -121,3 +121,23 @@ TEST_F(SourceMgrDiagnosticVerifierTest, InstalledAsDiagHandler) {
StringRef::npos);
EXPECT_FALSE(Verifier.verify());
}
+
+TEST_F(SourceMgrDiagnosticVerifierTest, CustomPrefixes) {
+ const MemoryBuffer *Buf =
+ addBuffer("op\n"
+ "// check-error at -1 {{first prefix}}\n"
+ "# alt-warning at -2 {{second prefix}}\n"
+ "// uncheck-error at -3 {{longer prefix ignored}}\n"
+ "// other-check-error at -4 {{hyphenated prefix ignored}}\n"
+ "// expected-error at -5 {{default prefix ignored}}\n");
+ SourceMgrDiagnosticVerifier Verifier(SM, OS, {"check", "alt"});
+
+ EXPECT_EQ(
+ Verifier.process(getMessage(Buf, SourceMgr::DK_Error, "first prefix")),
+ MatchResult::Matched);
+ EXPECT_EQ(
+ Verifier.process(getMessage(Buf, SourceMgr::DK_Warning, "second prefix")),
+ MatchResult::Matched);
+ EXPECT_TRUE(Verifier.verify());
+ EXPECT_EQ(Output, "");
+}
More information about the llvm-branch-commits
mailing list