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

>From aecafbbdf02a88939d1eb582de62335b84edafd0 Mon Sep 17 00:00:00 2001
From: Alex Richardson <[email protected]>
Date: Sun, 18 Oct 2026 16:08:41 -0700
Subject: [PATCH] [nspr] initial commit

---
 .../Support/SourceMgrDiagnosticVerifier.h     | 19 ++++--
 .../Support/SourceMgrDiagnosticVerifier.cpp   | 59 ++++++++++++++-----
 .../SourceMgrDiagnosticVerifierTest.cpp       | 20 +++++++
 3 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h 
b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
index 278c688921e2a..6bc0335bc9812 100644
--- a/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
+++ b/llvm/include/llvm/Support/SourceMgrDiagnosticVerifier.h
@@ -23,6 +23,7 @@
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/SourceMgr.h"
 #include <optional>
+#include <string>
 
 namespace llvm {
 
@@ -64,7 +65,15 @@ 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. If \p CommentPrefixes is
+  /// non-empty, directives are only recognized after the first occurrence of
+  /// one of these strings on a line, so that text outside of comments is
+  /// ignored.
+  SourceMgrDiagnosticVerifier(const SourceMgr &Mgr, raw_ostream &OS,
+                              ArrayRef<StringRef> Prefixes = {"expected"},
+                              ArrayRef<StringRef> CommentPrefixes = {});
 
   /// Matches a diagnostic against the expected diagnostics for \p Loc, or
   /// against the '@unknown' expected diagnostics if \p Loc is std::nullopt.
@@ -127,9 +136,11 @@ 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 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).
diff --git a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp 
b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
index 68358400b3d2a..7a5873fe98e54 100644
--- a/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
+++ b/llvm/lib/Support/SourceMgrDiagnosticVerifier.cpp
@@ -7,14 +7,35 @@
 
//===----------------------------------------------------------------------===//
 
 #include "llvm/Support/SourceMgrDiagnosticVerifier.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
+#include <algorithm>
 
 using namespace llvm;
 
-SourceMgrDiagnosticVerifier::SourceMgrDiagnosticVerifier(const SourceMgr &Mgr,
-                                                         raw_ostream &OS)
+SourceMgrDiagnosticVerifier::SourceMgrDiagnosticVerifier(
+    const SourceMgr &Mgr, raw_ostream &OS, ArrayRef<StringRef> Prefixes,
+    ArrayRef<StringRef> CommentPrefixes)
     : 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 (StringRef Prefix : CommentPrefixes) {
+    assert(!Prefix.empty() && "comment prefixes must be non-empty");
+    this->CommentPrefixes.push_back(Prefix.str());
+  }
+
   for (unsigned I = 0, E = Mgr.getNumBuffers(); I != E; ++I)
     (void)computeExpectedDiags(Mgr.getMemoryBuffer(I + 1));
 }
@@ -107,12 +128,22 @@ 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();
+    if (!CommentPrefixes.empty()) {
+      size_t CommentStart = StringRef::npos;
+      for (StringRef Prefix : CommentPrefixes)
+        CommentStart = std::min(CommentStart, Line.find(Prefix));
+      Line = Line.substr(CommentStart);
+    }
+
+    // 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 +154,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 06e7f19ea2232..6fd5837c35921 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, CustomPrefixesAndCommentScoping) {
+  const MemoryBuffer *Buf =
+      addBuffer("op check-error {{outside comment ignored}}\n"
+                "// check-error@-1 {{first prefix}}\n"
+                "# alt-warning@-2 {{second prefix}}\n"
+                "// uncheck-error@-3 {{longer prefix ignored}}\n"
+                "// other-check-error@-4 {{hyphenated prefix ignored}}\n"
+                "// expected-error@-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, "");
+}

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to