[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Joel E. Denny via llvm-branch-commits

https://github.com/jdenny-ornl edited 
https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Joel E. Denny via llvm-branch-commits


@@ -111,24 +112,29 @@ class FileCheckType {
 };
 } // namespace Check
 
-/// Summary of a FileCheck diagnostic.
-struct FileCheckDiag {
-  /// What is the FileCheck directive for this diagnostic?
-  Check::FileCheckType CheckTy;
-  /// Where is the FileCheck directive for this diagnostic?
-  SMLoc CheckLoc;
+class MatchResultDiag;
+
+/// Abstract base class for recording a FileCheck diagnostic for a pattern
+/// (e.g., \c CHECK-NEXT directive or \c --implicit-check-not).
+///
+/// \c FileCheckDiag has two direct derived classes:
+/// - \c MatchResultDiag records a match result for a pattern.  There might be
+///   more than one for a single pattern.  For example, for \c CHECK-DAG there
+///   might be several discarded matches before either a good match or a 
failure
+///   to match.
+/// - \c MatchNoteDiag provides an additional note about the most recent
+///   \c MatchResultDiag emitted by a FileCheck invocation.  For example, there
+///   might be a fuzzy match after a failure to match.
+class FileCheckDiag {
+public:
+  enum FileCheckDiagKind { FCDK_MatchResultDiag, FCDK_MatchNoteDiag };

jdenny-ornl wrote:

Without `FCDK_`, these enumerators collide with the derived class names in 
derived class methods, in particular `classof`.  Is it preferred to qualify 
them like `FileCheckDiag::MatchResultDiag` there instead?

Using `FCDK_` is an attempt to followed the examples in [LLVM's RTTI 
docs](https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html#basic-setup).  Do 
those docs need to be updated for LLVM's current preferred style?


https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Joel E. Denny via llvm-branch-commits


@@ -390,76 +390,95 @@ buildInputAnnotations(const SourceMgr &SM, unsigned 
CheckFileBufferID,
   // How many diagnostics does each pattern have?
   std::map DiagCountPerPattern;
   for (const FileCheckDiag &Diag : Diags)
-++DiagCountPerPattern[Diag.CheckLoc];
+++DiagCountPerPattern[Diag.getMatchResultDiag().getCheckLoc()];
   // How many diagnostics have we seen so far per pattern?
   std::map DiagIndexPerPattern;
   // How many total diagnostics have we seen so far?
   unsigned DiagIndex = 0;
   // What's the widest label?
   LabelWidth = 0;
+  // The label prefix that uniquely identifies the current MatchResultDiag and
+  // its MatchNoteDiag series.
+  std::string CurLabelPrefix;
   for (const FileCheckDiag &Diag : Diags) {
 InputAnnotation A;
 A.DiagIndex = DiagIndex++;
+if (const MatchResultDiag *MRD = dyn_cast(&Diag)) {
+  CurLabelPrefix.clear();
+  llvm::raw_string_ostream LabelStrm(CurLabelPrefix);
+  LabelStrm << GetCheckTypeAbbreviation(MRD->getCheckTy()) << ":";
+  unsigned CheckBufferID = SM.FindBufferContainingLoc(MRD->getCheckLoc());
+  if (CheckBufferID == CheckFileBufferID)
+LabelStrm
+<< SM.getLineAndColumn(MRD->getCheckLoc(), CheckBufferID).first;
+  else if (ImpPatBufferIDRange.first <= CheckBufferID &&
+   CheckBufferID < ImpPatBufferIDRange.second)
+LabelStrm << "imp" << (CheckBufferID - ImpPatBufferIDRange.first + 1);
+  else
+llvm_unreachable("expected diagnostic's check location to be either in 
"
+ "the check file or for an implicit pattern");
+}
 
-// Build label, which uniquely identifies this check result.
-unsigned CheckBufferID = SM.FindBufferContainingLoc(Diag.CheckLoc);
-auto CheckLineAndCol = SM.getLineAndColumn(Diag.CheckLoc, CheckBufferID);
-llvm::raw_string_ostream Label(A.Label);
-Label << GetCheckTypeAbbreviation(Diag.CheckTy) << ":";
-if (CheckBufferID == CheckFileBufferID)
-  Label << CheckLineAndCol.first;
-else if (ImpPatBufferIDRange.first <= CheckBufferID &&
- CheckBufferID < ImpPatBufferIDRange.second)
-  Label << "imp" << (CheckBufferID - ImpPatBufferIDRange.first + 1);
-else
-  llvm_unreachable("expected diagnostic's check location to be either in "
-   "the check file or for an implicit pattern");
-if (DiagCountPerPattern[Diag.CheckLoc] > 1)
-  Label << "'" << DiagIndexPerPattern[Diag.CheckLoc]++;
+// Build label that uniquely identifies this FileCheckDiag.
+llvm::raw_string_ostream LabelStrm(A.Label);
+LabelStrm << CurLabelPrefix;
+if (DiagCountPerPattern[Diag.getMatchResultDiag().getCheckLoc()] > 1)
+  LabelStrm
+  << "'"
+  << DiagIndexPerPattern[Diag.getMatchResultDiag().getCheckLoc()]++;
 LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());
 
-A.Marker = GetMarker(Diag.MatchTy);
-if (!Diag.Note.empty()) {
-  A.Marker.Note = Diag.Note;
-  // It's less confusing if notes that don't actually have ranges don't 
have
-  // markers.  For example, a marker for 'with "VAR" equal to "5"' would
-  // seem to indicate where "VAR" matches, but the location we actually 
have
-  // for the marker simply points to the start of the match/search range 
for
-  // the full pattern of which the substitution is potentially just one
-  // component.
-  if (Diag.InputStartLine == Diag.InputEndLine &&
-  Diag.InputStartCol == Diag.InputEndCol)
-A.Marker.Lead = ' ';
+A.Marker = GetMarker(Diag.getMatchType());
+std::optional CustomNote = std::nullopt;

jdenny-ornl wrote:

> `optional` defaults to `nullopt`.

Dropped the init.

> Why not just use `StringRef CustomNote`?

Are you suggesting dropping the `std::optional`?  It is there because we do not 
always have a custom note.

https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Joel E. Denny via llvm-branch-commits


@@ -159,41 +165,124 @@ struct FileCheckDiag {
 /// Indicates a fuzzy match that serves as a suggestion for the next
 /// intended match for an expected pattern with too few or no good matches.
 MatchFuzzy,
-  } MatchTy;
+  };
+
+private:
+  const FileCheckDiagKind Kind;
+  MatchType MatchTy;
+  SMRange InputRange;
+
+public:
+  FileCheckDiag(FileCheckDiagKind Kind, MatchType MatchTy, SMRange InputRange)
+  : Kind(Kind), MatchTy(MatchTy), InputRange(InputRange) {}
+  /// Destructor is purely virtual to ensure this remains an abstract class.
+  virtual ~FileCheckDiag() = 0;
+  /// Of what derived class is this an instance?
+  FileCheckDiagKind getKind() const { return Kind; }
+  /// If this is a \c MatchResultDiag, return itself.  If this is a
+  /// \c MatchNoteDiag, return its associated \c MatchResultDiag.
+  virtual const MatchResultDiag &getMatchResultDiag() const = 0;
+  /// Adjust the match type.
+  void adjustMatchType(MatchType MatchTy) { this->MatchTy = MatchTy; }
+  /// Get the match type.
+  MatchType getMatchType() const { return MatchTy; }
   /// The search range if MatchTy starts with MatchNone, or the match range
   /// otherwise.
-  unsigned InputStartLine;
-  unsigned InputStartCol;
-  unsigned InputEndLine;
-  unsigned InputEndCol;
-  /// A note to replace the one normally indicated by MatchTy, or the empty
-  /// string if none.
-  std::string Note;
-  LLVM_ABI FileCheckDiag(const SourceMgr &SM,
- const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
- MatchType MatchTy, SMRange InputRange,
- StringRef Note = "");
+  SMRange getInputRange() const { return InputRange; }
+};
+
+/// Class for recording a FileCheck diagnostic that reports a match result for 
a
+/// pattern.
+class MatchResultDiag : public FileCheckDiag {
+private:
+  Check::FileCheckType CheckTy;
+  SMLoc CheckLoc;
+
+public:
+  MatchResultDiag(const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
+  MatchType MatchTy, SMRange InputRange)
+  : FileCheckDiag(FCDK_MatchResultDiag, MatchTy, InputRange),
+CheckTy(CheckTy), CheckLoc(CheckLoc) {}
+  /// Is \p FCD an instance of \c MatchResultDiag?
+  static bool classof(const FileCheckDiag *FCD) {
+return FCD->getKind() == FCDK_MatchResultDiag;
+  }
+  /// Get itself.
+  virtual const MatchResultDiag &getMatchResultDiag() const override {

jdenny-ornl wrote:

Done.

https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Joel E. Denny via llvm-branch-commits

https://github.com/jdenny-ornl updated 
https://github.com/llvm/llvm-project/pull/195569

>From 1f468c7903b13911e75c8704a129e8b6e86aa18b Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" 
Date: Sun, 3 May 2026 17:58:37 -0400
Subject: [PATCH 1/3] [FileCheck][NFC] Introduce MatchResultDiag and
 MatchNoteDiag

This patch depends on PR # and continues its effort to decouple
the `-dump-input` presentation layer (in
`llvm/utils/FileCheck/FileCheck.cpp`) and the FileCheck library's
diagnostic emission (in `llvm/lib/FileCheck/FileCheck.cpp`).

Similar to compiler errors/warnings/remarks vs. notes, the
`FileCheckDiag` series emitted by the FileCheck library contains match
results, each of which might be followed by a series of associated
notes before the next match result.  Without this patch series, that
association is not formally modeled by `FileCheckDiag` or clearly
documented, and `-dump-input` is not able to easily reason about it.

This patch improves the situation by introducing two `FileCheckDiag`
derived classes: `MatchResultDiag` and `MatchNoteDiag`.  It extends
`FileCheckDiagList` to directly associate each `MatchNoteDiag` with
its `MatchResultDiag`.  Thus:
- `FileCheckDiagList::adjustPrevDiags` no longer has to determine that
  association based on directive location info.
- Match result instances of `FileCheckDiag` no longer need to store a
  redundant custom note field, which only makes sense for notes.
- Note instances of `FileCheckDiag` no longer need to store the
  directive type and location, which are already stored by their match
  result instances.
- In both the FileCheck library and the `-dump-input` presentation
  layer, it is now clearer when a `FileCheckDiag` is a match result
  vs. a note.
---
 llvm/include/llvm/FileCheck/FileCheck.h| 153 -
 llvm/lib/FileCheck/FileCheck.cpp   |  48 +++
 llvm/unittests/FileCheck/FileCheckTest.cpp |  32 +++--
 llvm/utils/FileCheck/FileCheck.cpp | 101 --
 4 files changed, 221 insertions(+), 113 deletions(-)

diff --git a/llvm/include/llvm/FileCheck/FileCheck.h 
b/llvm/include/llvm/FileCheck/FileCheck.h
index 07684e6fc6cff..b171d1048cddb 100644
--- a/llvm/include/llvm/FileCheck/FileCheck.h
+++ b/llvm/include/llvm/FileCheck/FileCheck.h
@@ -14,6 +14,7 @@
 #define LLVM_FILECHECK_FILECHECK_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/SMLoc.h"
@@ -110,24 +111,29 @@ class FileCheckType {
 };
 } // namespace Check
 
-/// Summary of a FileCheck diagnostic.
-struct FileCheckDiag {
-  /// What is the FileCheck directive for this diagnostic?
-  Check::FileCheckType CheckTy;
-  /// Where is the FileCheck directive for this diagnostic?
-  SMLoc CheckLoc;
+class MatchResultDiag;
+
+/// Abstract base class for recording a FileCheck diagnostic for a pattern
+/// (e.g., \c CHECK-NEXT directive or \c --implicit-check-not).
+///
+/// \c FileCheckDiag has two direct derived classes:
+/// - \c MatchResultDiag records a match result for a pattern.  There might be
+///   more than one for a single pattern.  For example, for \c CHECK-DAG there
+///   might be several discarded matches before either a good match or a 
failure
+///   to match.
+/// - \c MatchNoteDiag provides an additional note about the most recent
+///   \c MatchResultDiag emitted by a FileCheck invocation.  For example, there
+///   might be a fuzzy match after a failure to match.
+class FileCheckDiag {
+public:
+  enum FileCheckDiagKind { FCDK_MatchResultDiag, FCDK_MatchNoteDiag };
+
   /// What type of match result does this diagnostic describe?
   ///
   /// A directive's supplied pattern is said to be either expected or excluded
   /// depending on whether the pattern must have or must not have a match in
   /// order for the directive to succeed.  For example, a CHECK directive's
   /// pattern is expected, and a CHECK-NOT directive's pattern is excluded.
-  ///
-  /// There might be more than one match result for a single pattern.  For
-  /// example, there might be several discarded matches
-  /// (MatchFoundButDiscarded) before either a good match
-  /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),
-  /// and there might be a fuzzy match (MatchFuzzy) after the latter.
   enum MatchType {
 /// Indicates a good match for an expected pattern.
 MatchFoundAndExpected,
@@ -158,39 +164,122 @@ struct FileCheckDiag {
 /// Indicates a fuzzy match that serves as a suggestion for the next
 /// intended match for an expected pattern with too few or no good matches.
 MatchFuzzy,
-  } MatchTy;
+  };
+
+private:
+  const FileCheckDiagKind Kind;
+  MatchType MatchTy;
+  SMRange InputRange;
+
+public:
+  FileCheckDiag(FileCheckDiagKind Kind, MatchType MatchTy, SMRange InputRange)
+  : Kind(Kind), MatchTy(MatchTy), InputRange(InputRange) {}
+  /// Destructor is purely virtual to ensure this remains an 

[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Fangrui Song via llvm-branch-commits


@@ -111,24 +112,29 @@ class FileCheckType {
 };
 } // namespace Check
 
-/// Summary of a FileCheck diagnostic.
-struct FileCheckDiag {
-  /// What is the FileCheck directive for this diagnostic?
-  Check::FileCheckType CheckTy;
-  /// Where is the FileCheck directive for this diagnostic?
-  SMLoc CheckLoc;
+class MatchResultDiag;
+
+/// Abstract base class for recording a FileCheck diagnostic for a pattern
+/// (e.g., \c CHECK-NEXT directive or \c --implicit-check-not).
+///
+/// \c FileCheckDiag has two direct derived classes:
+/// - \c MatchResultDiag records a match result for a pattern.  There might be
+///   more than one for a single pattern.  For example, for \c CHECK-DAG there
+///   might be several discarded matches before either a good match or a 
failure
+///   to match.
+/// - \c MatchNoteDiag provides an additional note about the most recent
+///   \c MatchResultDiag emitted by a FileCheck invocation.  For example, there
+///   might be a fuzzy match after a failure to match.
+class FileCheckDiag {
+public:
+  enum FileCheckDiagKind { FCDK_MatchResultDiag, FCDK_MatchNoteDiag };

MaskRay wrote:

`FCDK_` prefix is reundant since the enum is nested in the class

https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-05 Thread Fangrui Song via llvm-branch-commits


@@ -390,76 +390,95 @@ buildInputAnnotations(const SourceMgr &SM, unsigned 
CheckFileBufferID,
   // How many diagnostics does each pattern have?
   std::map DiagCountPerPattern;
   for (const FileCheckDiag &Diag : Diags)
-++DiagCountPerPattern[Diag.CheckLoc];
+++DiagCountPerPattern[Diag.getMatchResultDiag().getCheckLoc()];
   // How many diagnostics have we seen so far per pattern?
   std::map DiagIndexPerPattern;
   // How many total diagnostics have we seen so far?
   unsigned DiagIndex = 0;
   // What's the widest label?
   LabelWidth = 0;
+  // The label prefix that uniquely identifies the current MatchResultDiag and
+  // its MatchNoteDiag series.
+  std::string CurLabelPrefix;
   for (const FileCheckDiag &Diag : Diags) {
 InputAnnotation A;
 A.DiagIndex = DiagIndex++;
+if (const MatchResultDiag *MRD = dyn_cast(&Diag)) {
+  CurLabelPrefix.clear();
+  llvm::raw_string_ostream LabelStrm(CurLabelPrefix);
+  LabelStrm << GetCheckTypeAbbreviation(MRD->getCheckTy()) << ":";
+  unsigned CheckBufferID = SM.FindBufferContainingLoc(MRD->getCheckLoc());
+  if (CheckBufferID == CheckFileBufferID)
+LabelStrm
+<< SM.getLineAndColumn(MRD->getCheckLoc(), CheckBufferID).first;
+  else if (ImpPatBufferIDRange.first <= CheckBufferID &&
+   CheckBufferID < ImpPatBufferIDRange.second)
+LabelStrm << "imp" << (CheckBufferID - ImpPatBufferIDRange.first + 1);
+  else
+llvm_unreachable("expected diagnostic's check location to be either in 
"
+ "the check file or for an implicit pattern");
+}
 
-// Build label, which uniquely identifies this check result.
-unsigned CheckBufferID = SM.FindBufferContainingLoc(Diag.CheckLoc);
-auto CheckLineAndCol = SM.getLineAndColumn(Diag.CheckLoc, CheckBufferID);
-llvm::raw_string_ostream Label(A.Label);
-Label << GetCheckTypeAbbreviation(Diag.CheckTy) << ":";
-if (CheckBufferID == CheckFileBufferID)
-  Label << CheckLineAndCol.first;
-else if (ImpPatBufferIDRange.first <= CheckBufferID &&
- CheckBufferID < ImpPatBufferIDRange.second)
-  Label << "imp" << (CheckBufferID - ImpPatBufferIDRange.first + 1);
-else
-  llvm_unreachable("expected diagnostic's check location to be either in "
-   "the check file or for an implicit pattern");
-if (DiagCountPerPattern[Diag.CheckLoc] > 1)
-  Label << "'" << DiagIndexPerPattern[Diag.CheckLoc]++;
+// Build label that uniquely identifies this FileCheckDiag.
+llvm::raw_string_ostream LabelStrm(A.Label);
+LabelStrm << CurLabelPrefix;
+if (DiagCountPerPattern[Diag.getMatchResultDiag().getCheckLoc()] > 1)
+  LabelStrm
+  << "'"
+  << DiagIndexPerPattern[Diag.getMatchResultDiag().getCheckLoc()]++;
 LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());
 
-A.Marker = GetMarker(Diag.MatchTy);
-if (!Diag.Note.empty()) {
-  A.Marker.Note = Diag.Note;
-  // It's less confusing if notes that don't actually have ranges don't 
have
-  // markers.  For example, a marker for 'with "VAR" equal to "5"' would
-  // seem to indicate where "VAR" matches, but the location we actually 
have
-  // for the marker simply points to the start of the match/search range 
for
-  // the full pattern of which the substitution is potentially just one
-  // component.
-  if (Diag.InputStartLine == Diag.InputEndLine &&
-  Diag.InputStartCol == Diag.InputEndCol)
-A.Marker.Lead = ' ';
+A.Marker = GetMarker(Diag.getMatchType());
+std::optional CustomNote = std::nullopt;

MaskRay wrote:

`optional` defaults to `nullopt`. Why not just use `StringRef CustomNote`?

https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-04 Thread Fangrui Song via llvm-branch-commits

https://github.com/MaskRay approved this pull request.


https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-04 Thread Fangrui Song via llvm-branch-commits


@@ -159,41 +165,124 @@ struct FileCheckDiag {
 /// Indicates a fuzzy match that serves as a suggestion for the next
 /// intended match for an expected pattern with too few or no good matches.
 MatchFuzzy,
-  } MatchTy;
+  };
+
+private:
+  const FileCheckDiagKind Kind;
+  MatchType MatchTy;
+  SMRange InputRange;
+
+public:
+  FileCheckDiag(FileCheckDiagKind Kind, MatchType MatchTy, SMRange InputRange)
+  : Kind(Kind), MatchTy(MatchTy), InputRange(InputRange) {}
+  /// Destructor is purely virtual to ensure this remains an abstract class.
+  virtual ~FileCheckDiag() = 0;
+  /// Of what derived class is this an instance?
+  FileCheckDiagKind getKind() const { return Kind; }
+  /// If this is a \c MatchResultDiag, return itself.  If this is a
+  /// \c MatchNoteDiag, return its associated \c MatchResultDiag.
+  virtual const MatchResultDiag &getMatchResultDiag() const = 0;
+  /// Adjust the match type.
+  void adjustMatchType(MatchType MatchTy) { this->MatchTy = MatchTy; }
+  /// Get the match type.
+  MatchType getMatchType() const { return MatchTy; }
   /// The search range if MatchTy starts with MatchNone, or the match range
   /// otherwise.
-  unsigned InputStartLine;
-  unsigned InputStartCol;
-  unsigned InputEndLine;
-  unsigned InputEndCol;
-  /// A note to replace the one normally indicated by MatchTy, or the empty
-  /// string if none.
-  std::string Note;
-  LLVM_ABI FileCheckDiag(const SourceMgr &SM,
- const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
- MatchType MatchTy, SMRange InputRange,
- StringRef Note = "");
+  SMRange getInputRange() const { return InputRange; }
+};
+
+/// Class for recording a FileCheck diagnostic that reports a match result for 
a
+/// pattern.
+class MatchResultDiag : public FileCheckDiag {
+private:
+  Check::FileCheckType CheckTy;
+  SMLoc CheckLoc;
+
+public:
+  MatchResultDiag(const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
+  MatchType MatchTy, SMRange InputRange)
+  : FileCheckDiag(FCDK_MatchResultDiag, MatchTy, InputRange),
+CheckTy(CheckTy), CheckLoc(CheckLoc) {}
+  /// Is \p FCD an instance of \c MatchResultDiag?
+  static bool classof(const FileCheckDiag *FCD) {
+return FCD->getKind() == FCDK_MatchResultDiag;
+  }
+  /// Get itself.
+  virtual const MatchResultDiag &getMatchResultDiag() const override {

MaskRay wrote:

drop `virtual` with `override`. 

https://github.com/llvm/llvm-project/pull/195569
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-03 Thread via llvm-branch-commits

llvmorg-github-actions[bot] wrote:




@llvm/pr-subscribers-testing-tools

Author: Joel E. Denny (jdenny-ornl)


Changes

This patch depends on PR #195568 and continues its effort to decouple 
the `-dump-input` presentation layer (in
`llvm/utils/FileCheck/FileCheck.cpp`) and the FileCheck library's diagnostic 
emission (in `llvm/lib/FileCheck/FileCheck.cpp`).

Similar to compiler errors/warnings/remarks vs. notes, the `FileCheckDiag` 
series emitted by the FileCheck library contains match results, each of which 
might be followed by a series of associated notes before the next match result. 
 Without this patch series, that association is not formally modeled by 
`FileCheckDiag` or clearly documented, and `-dump-input` is not able to easily 
reason about it.

This patch improves the situation by introducing two `FileCheckDiag` derived 
classes: `MatchResultDiag` and `MatchNoteDiag`.  It extends `FileCheckDiagList` 
to directly associate each `MatchNoteDiag` with its `MatchResultDiag`.  Thus:
- `FileCheckDiagList::adjustPrevDiags` no longer has to determine that 
association based on directive location info.
- Match result instances of `FileCheckDiag` no longer need to store a redundant 
custom note field, which only makes sense for notes.
- Note instances of `FileCheckDiag` no longer need to store the directive type 
and location, which are already stored by their match result instances.
- In both the FileCheck library and the `-dump-input` presentation layer, it is 
now clearer when a `FileCheckDiag` is a match result vs. a note.

---

Patch is 24.24 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/195569.diff


4 Files Affected:

- (modified) llvm/include/llvm/FileCheck/FileCheck.h (+121-32) 
- (modified) llvm/lib/FileCheck/FileCheck.cpp (+18-30) 
- (modified) llvm/unittests/FileCheck/FileCheckTest.cpp (+22-10) 
- (modified) llvm/utils/FileCheck/FileCheck.cpp (+60-41) 


``diff
diff --git a/llvm/include/llvm/FileCheck/FileCheck.h 
b/llvm/include/llvm/FileCheck/FileCheck.h
index 07684e6fc6cff..b171d1048cddb 100644
--- a/llvm/include/llvm/FileCheck/FileCheck.h
+++ b/llvm/include/llvm/FileCheck/FileCheck.h
@@ -14,6 +14,7 @@
 #define LLVM_FILECHECK_FILECHECK_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/SMLoc.h"
@@ -110,24 +111,29 @@ class FileCheckType {
 };
 } // namespace Check
 
-/// Summary of a FileCheck diagnostic.
-struct FileCheckDiag {
-  /// What is the FileCheck directive for this diagnostic?
-  Check::FileCheckType CheckTy;
-  /// Where is the FileCheck directive for this diagnostic?
-  SMLoc CheckLoc;
+class MatchResultDiag;
+
+/// Abstract base class for recording a FileCheck diagnostic for a pattern
+/// (e.g., \c CHECK-NEXT directive or \c --implicit-check-not).
+///
+/// \c FileCheckDiag has two direct derived classes:
+/// - \c MatchResultDiag records a match result for a pattern.  There might be
+///   more than one for a single pattern.  For example, for \c CHECK-DAG there
+///   might be several discarded matches before either a good match or a 
failure
+///   to match.
+/// - \c MatchNoteDiag provides an additional note about the most recent
+///   \c MatchResultDiag emitted by a FileCheck invocation.  For example, there
+///   might be a fuzzy match after a failure to match.
+class FileCheckDiag {
+public:
+  enum FileCheckDiagKind { FCDK_MatchResultDiag, FCDK_MatchNoteDiag };
+
   /// What type of match result does this diagnostic describe?
   ///
   /// A directive's supplied pattern is said to be either expected or excluded
   /// depending on whether the pattern must have or must not have a match in
   /// order for the directive to succeed.  For example, a CHECK directive's
   /// pattern is expected, and a CHECK-NOT directive's pattern is excluded.
-  ///
-  /// There might be more than one match result for a single pattern.  For
-  /// example, there might be several discarded matches
-  /// (MatchFoundButDiscarded) before either a good match
-  /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),
-  /// and there might be a fuzzy match (MatchFuzzy) after the latter.
   enum MatchType {
 /// Indicates a good match for an expected pattern.
 MatchFoundAndExpected,
@@ -158,39 +164,122 @@ struct FileCheckDiag {
 /// Indicates a fuzzy match that serves as a suggestion for the next
 /// intended match for an expected pattern with too few or no good matches.
 MatchFuzzy,
-  } MatchTy;
+  };
+
+private:
+  const FileCheckDiagKind Kind;
+  MatchType MatchTy;
+  SMRange InputRange;
+
+public:
+  FileCheckDiag(FileCheckDiagKind Kind, MatchType MatchTy, SMRange InputRange)
+  : Kind(Kind), MatchTy(MatchTy), InputRange(InputRange) {}
+  /// Destructor is purely virtual to ensure this remains an abstract class.
+  virtual ~FileCheckDiag() = 0;
+  /// Of what derived class is 

[llvm-branch-commits] [llvm] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag (PR #195569)

2026-05-03 Thread Joel E. Denny via llvm-branch-commits

https://github.com/jdenny-ornl created 
https://github.com/llvm/llvm-project/pull/195569

This patch depends on PR #195568 and continues its effort to decouple the 
`-dump-input` presentation layer (in
`llvm/utils/FileCheck/FileCheck.cpp`) and the FileCheck library's diagnostic 
emission (in `llvm/lib/FileCheck/FileCheck.cpp`).

Similar to compiler errors/warnings/remarks vs. notes, the `FileCheckDiag` 
series emitted by the FileCheck library contains match results, each of which 
might be followed by a series of associated notes before the next match result. 
 Without this patch series, that association is not formally modeled by 
`FileCheckDiag` or clearly documented, and `-dump-input` is not able to easily 
reason about it.

This patch improves the situation by introducing two `FileCheckDiag` derived 
classes: `MatchResultDiag` and `MatchNoteDiag`.  It extends `FileCheckDiagList` 
to directly associate each `MatchNoteDiag` with its `MatchResultDiag`.  Thus:
- `FileCheckDiagList::adjustPrevDiags` no longer has to determine that 
association based on directive location info.
- Match result instances of `FileCheckDiag` no longer need to store a redundant 
custom note field, which only makes sense for notes.
- Note instances of `FileCheckDiag` no longer need to store the directive type 
and location, which are already stored by their match result instances.
- In both the FileCheck library and the `-dump-input` presentation layer, it is 
now clearer when a `FileCheckDiag` is a match result vs. a note.

>From 1f468c7903b13911e75c8704a129e8b6e86aa18b Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" 
Date: Sun, 3 May 2026 17:58:37 -0400
Subject: [PATCH] [FileCheck][NFC] Introduce MatchResultDiag and MatchNoteDiag

This patch depends on PR # and continues its effort to decouple
the `-dump-input` presentation layer (in
`llvm/utils/FileCheck/FileCheck.cpp`) and the FileCheck library's
diagnostic emission (in `llvm/lib/FileCheck/FileCheck.cpp`).

Similar to compiler errors/warnings/remarks vs. notes, the
`FileCheckDiag` series emitted by the FileCheck library contains match
results, each of which might be followed by a series of associated
notes before the next match result.  Without this patch series, that
association is not formally modeled by `FileCheckDiag` or clearly
documented, and `-dump-input` is not able to easily reason about it.

This patch improves the situation by introducing two `FileCheckDiag`
derived classes: `MatchResultDiag` and `MatchNoteDiag`.  It extends
`FileCheckDiagList` to directly associate each `MatchNoteDiag` with
its `MatchResultDiag`.  Thus:
- `FileCheckDiagList::adjustPrevDiags` no longer has to determine that
  association based on directive location info.
- Match result instances of `FileCheckDiag` no longer need to store a
  redundant custom note field, which only makes sense for notes.
- Note instances of `FileCheckDiag` no longer need to store the
  directive type and location, which are already stored by their match
  result instances.
- In both the FileCheck library and the `-dump-input` presentation
  layer, it is now clearer when a `FileCheckDiag` is a match result
  vs. a note.
---
 llvm/include/llvm/FileCheck/FileCheck.h| 153 -
 llvm/lib/FileCheck/FileCheck.cpp   |  48 +++
 llvm/unittests/FileCheck/FileCheckTest.cpp |  32 +++--
 llvm/utils/FileCheck/FileCheck.cpp | 101 --
 4 files changed, 221 insertions(+), 113 deletions(-)

diff --git a/llvm/include/llvm/FileCheck/FileCheck.h 
b/llvm/include/llvm/FileCheck/FileCheck.h
index 07684e6fc6cff..b171d1048cddb 100644
--- a/llvm/include/llvm/FileCheck/FileCheck.h
+++ b/llvm/include/llvm/FileCheck/FileCheck.h
@@ -14,6 +14,7 @@
 #define LLVM_FILECHECK_FILECHECK_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/SMLoc.h"
@@ -110,24 +111,29 @@ class FileCheckType {
 };
 } // namespace Check
 
-/// Summary of a FileCheck diagnostic.
-struct FileCheckDiag {
-  /// What is the FileCheck directive for this diagnostic?
-  Check::FileCheckType CheckTy;
-  /// Where is the FileCheck directive for this diagnostic?
-  SMLoc CheckLoc;
+class MatchResultDiag;
+
+/// Abstract base class for recording a FileCheck diagnostic for a pattern
+/// (e.g., \c CHECK-NEXT directive or \c --implicit-check-not).
+///
+/// \c FileCheckDiag has two direct derived classes:
+/// - \c MatchResultDiag records a match result for a pattern.  There might be
+///   more than one for a single pattern.  For example, for \c CHECK-DAG there
+///   might be several discarded matches before either a good match or a 
failure
+///   to match.
+/// - \c MatchNoteDiag provides an additional note about the most recent
+///   \c MatchResultDiag emitted by a FileCheck invocation.  For example, there
+///   might be a fuzzy match after a failure to match.
+class FileCheckDiag {
+public:
+  enum