[llvm-branch-commits] [llvm] [FileCheck][NFC] Complete FileCheckDiag class hierarchy (PR #195571)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun May 3 18:23:40 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-testing-tools

Author: Joel E. Denny (jdenny-ornl)

<details>
<summary>Changes</summary>

This patch depends on PR #<!-- -->195569 and finishes 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`).

The focus of this patch is finally eliminating `enum MatchType` and completing the `FileCheckDiag` class hierarchy.  That enables the following improvements.

Replace MatchTy and InputRange
==============================

`-dump-input` needs some means to determine (1) whether some notes should be filtered in by `-dump-input-filter=error`, and (2) where to place some notes in the input dump.  Without this patch series, the FileCheck library provides that information by copying the following from a match result to any note that does not have its own versions: (1) the `MatchType`, which determines error status, and (2) the input range so that `-dump-input` can place the note next to the match result.  However, this copied information is redundant as it is already part of the associated match result, and semantically it does not really apply to the note itself.

Furthermore, for a note that does not have a match location (e.g., the FileCheck library does not include match locations when emitting notes about variable substitutions), the FileCheck library is responsible for reducing the copied location to an empty range as a special case that `-dump-input` understands means it should not add a marker (like `^~~`), which would be misleading in the input dump.  However, that means a note can never have a real input range that is empty and that thus refers to just a single position.

This interaction is too subtle, even in the case of just `-dump-input`.  Moreover, it is easy to imagine alternative diagnostic presentation layers where it would be unhelpful and thus more misleading.  For example, imagine (this is just a thought experiment, and I have no plans for this) an HTML-based presentation where notes appear in pop-up windows when clicking on match results.  A copied error status and location is then not relevant for notes.  Association with a match result still is relevant.

This patch removes the `MatchTy` and `InputRange` fields from `FieldCheckDiag`.  It replaces `MatchTy` with `Status` fields in just the `MatchResultDiag` hierarchy.  To replace `InputRange`, it exposes a match range as a `std::optional`, and it adds a search range to `MatchResultDiag` (used now for `MatchNoneDiag` and, in the future, `-dump-input` will present search ranges upon any error).  Thus, this patch relieves the FileCheck library of the above
`-dump-input`-specific responsibilities, and `-dump-input` is now able to cleanly examine the `FileCheckDiag` series for each required property.

Clean up getMarker
==================

Because of the now complete `FileCheckDiag` class hierarchy, this patch is able to clean up the `getMarker` function for `-dump-input`. Without this patch, `getMarker` encodes the lead character, color, message, and error status individually for every possible `MatchType`. With this patch, `getMarker` instead encodes the logic of how the marker properties are generally chosen at the top of the `FileCheckDiag` hierarchy, and then it overrides those choices where needed lower in the hierarchy.  Again, it is now easier for a diagnostic presentation layer to reason about diagnostics.

---

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


5 Files Affected:

- (modified) llvm/include/llvm/FileCheck/FileCheck.h (+229-75) 
- (modified) llvm/lib/FileCheck/FileCheck.cpp (+41-41) 
- (modified) llvm/lib/FileCheck/FileCheckImpl.h (+1-3) 
- (modified) llvm/unittests/FileCheck/FileCheckTest.cpp (+14-13) 
- (modified) llvm/utils/FileCheck/FileCheck.cpp (+91-67) 


``````````diff
diff --git a/llvm/include/llvm/FileCheck/FileCheck.h b/llvm/include/llvm/FileCheck/FileCheck.h
index b171d1048cddb..ea66ca3cb0617 100644
--- a/llvm/include/llvm/FileCheck/FileCheck.h
+++ b/llvm/include/llvm/FileCheck/FileCheck.h
@@ -124,56 +124,31 @@ class MatchResultDiag;
 /// - \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.
+///
+/// Throughout this class hierarchy, a 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 it to succeed.  For example, a \c CHECK directive's pattern is
+/// expected, and a \c CHECK-NOT directive's pattern is excluded.
 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.
-  enum MatchType {
-    /// Indicates a good match for an expected pattern.
-    MatchFoundAndExpected,
-    /// Indicates a match for an excluded pattern.
-    MatchFoundButExcluded,
-    /// Indicates a match for an expected pattern, but the match is on the
-    /// wrong line.
-    MatchFoundButWrongLine,
-    /// Indicates a discarded match for an expected pattern.
-    MatchFoundButDiscarded,
-    /// Indicates an error while processing a match after the match was found
-    /// for an expected or excluded pattern.  The error is specified by \c Note,
-    /// to which it should be appropriate to prepend "error: " later.  The full
-    /// match itself should be recorded in a preceding diagnostic of a different
-    /// \c MatchFound match type.
-    MatchFoundErrorNote,
-    /// Indicates no match for an excluded pattern.
-    MatchNoneAndExcluded,
-    /// Indicates no match for an expected pattern, but this might follow good
-    /// matches when multiple matches are expected for the pattern, or it might
-    /// follow discarded matches for the pattern.
-    MatchNoneButExpected,
-    /// Indicates no match due to an expected or excluded pattern that has
-    /// proven to be invalid at match time.  The exact problems are usually
-    /// reported in subsequent diagnostics of the same match type but with
-    /// \c Note set.
-    MatchNoneForInvalidPattern,
-    /// 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,
+  enum FileCheckDiagKind {
+    // MatchResultDiag
+    FCDK_MatchResultDiag_First,
+    FCDK_MatchFoundDiag = FCDK_MatchResultDiag_First,
+    FCDK_MatchNoneDiag,
+    FCDK_MatchResultDiag_Last = FCDK_MatchNoneDiag,
+    // MatchNoteDiag
+    FCDK_MatchNoteDiag_First,
+    FCDK_MatchFuzzyDiag = FCDK_MatchNoteDiag_First,
+    FCDK_MatchCustomNoteDiag,
+    FCDK_MatchNoteDiag_Last = FCDK_MatchCustomNoteDiag
   };
 
 private:
   const FileCheckDiagKind Kind;
-  MatchType MatchTy;
-  SMRange InputRange;
 
 public:
-  FileCheckDiag(FileCheckDiagKind Kind, MatchType MatchTy, SMRange InputRange)
-      : Kind(Kind), MatchTy(MatchTy), InputRange(InputRange) {}
+  FileCheckDiag(FileCheckDiagKind Kind) : Kind(Kind) {}
   /// Destructor is purely virtual to ensure this remains an abstract class.
   virtual ~FileCheckDiag() = 0;
   /// Of what derived class is this an instance?
@@ -181,30 +156,41 @@ class FileCheckDiag {
   /// 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.
-  SMRange getInputRange() const { return InputRange; }
+  /// Does this diagnostic reveal a new error?
+  ///
+  /// For \c MatchResultDiag, \c !isError() is not always the same as a
+  /// successful pattern match result.  For \c MatchNoteDiag, \c !isError()
+  /// does not indicate the lack of an error but rather the lack of an
+  /// additional error beyond its associated \c MatchResultDiag.  See
+  /// documentation on derived types for details.
+  virtual bool isError() const = 0;
+  /// Return the input range for which this diagnostic indicates text that was
+  /// matched in some way (e.g., successful pattern match, discarded pattern
+  /// match, or variable capture), or return \c std::nullopt if the diagnostic
+  /// has no such input range.
+  virtual std::optional<SMRange> getMatchRange() const = 0;
 };
 
-/// Class for recording a FileCheck diagnostic that reports a match result for a
-/// pattern.
+/// Abstract base class for recording a FileCheck diagnostic that reports a
+/// match result for a pattern.
 class MatchResultDiag : public FileCheckDiag {
 private:
   Check::FileCheckType CheckTy;
   SMLoc CheckLoc;
+  SMRange SearchRange;
 
 public:
-  MatchResultDiag(const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
-                  MatchType MatchTy, SMRange InputRange)
-      : FileCheckDiag(FCDK_MatchResultDiag, MatchTy, InputRange),
-        CheckTy(CheckTy), CheckLoc(CheckLoc) {}
+  MatchResultDiag(FileCheckDiagKind Kind, const Check::FileCheckType &CheckTy,
+                  SMLoc CheckLoc, SMRange SearchRange)
+      : FileCheckDiag(Kind), CheckTy(CheckTy), CheckLoc(CheckLoc),
+        SearchRange(SearchRange) {}
+  /// Destructor is purely virtual to ensure this remains an abstract class.
+  virtual ~MatchResultDiag() = 0;
   /// Is \p FCD an instance of \c MatchResultDiag?
   static bool classof(const FileCheckDiag *FCD) {
-    return FCD->getKind() == FCDK_MatchResultDiag;
+    FileCheckDiagKind FCDK = FCD->getKind();
+    return FCDK_MatchResultDiag_First <= FCDK &&
+           FCDK <= FCDK_MatchResultDiag_Last;
   }
   /// Get itself.
   virtual const MatchResultDiag &getMatchResultDiag() const override {
@@ -214,23 +200,122 @@ class MatchResultDiag : public FileCheckDiag {
   Check::FileCheckType getCheckTy() const { return CheckTy; }
   /// Where is the pattern for this match result?
   SMLoc getCheckLoc() const { return CheckLoc; }
+  /// What is the search range for the match result?
+  SMRange getSearchRange() const { return SearchRange; }
 };
 
-/// Class for recording a FileCheck diagnostic that provides an additional note
-/// (possibly an additional error) about the most recent \c MatchResultDiag.
+/// \c MatchResultDiag for a pattern that matched the input.
+class MatchFoundDiag : public MatchResultDiag {
+public:
+  enum StatusTy {
+    /// Indicates a good match for an expected pattern.
+    Success,
+    /// Indicates a match for an excluded pattern (error).
+    Excluded,
+    /// Indicates a match for an expected pattern, but the match is on the
+    /// wrong line (error).
+    WrongLine,
+    /// Indicates a discarded match for an expected pattern (not an error).
+    Discarded
+  };
+
+private:
+  StatusTy Status;
+  SMRange MatchRange;
+
+public:
+  MatchFoundDiag(const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
+                 StatusTy Status, SMRange MatchRange, SMRange SearchRange)
+      : MatchResultDiag(FCDK_MatchFoundDiag, CheckTy, CheckLoc, SearchRange),
+        Status(Status), MatchRange(MatchRange) {}
+  /// Is \p FCD an instance of \c MatchFoundDiag?
+  static bool classof(const FileCheckDiag *FCD) {
+    return FCD->getKind() == FCDK_MatchFoundDiag;
+  }
+  /// Does this match produce an error?
+  ///
+  /// This is not always the same as \c getStatus()!=Success.  For example,
+  /// \c CHECK-DAG discarded matches are neither successful matches nor errors.
+  virtual bool isError() const override {
+    return Status != Success && Status != Discarded;
+  }
+  /// Was this a successful match?  If not, why not?
+  ///
+  /// See \c isError comments for the relationship between the two.
+  StatusTy getStatus() const { return Status; }
+  /// Adjust a successful status to a non-successful status.
+  ///
+  /// This is designed to be called while emitting diagnostics.  It is not
+  /// designed to be called by a diagnostic presentation layer like
+  /// `-dump-input`.
+  ///
+  /// For example, a match that was originally thought to be successful might
+  /// later be discarded, or it might be determined that it violates a matching
+  /// constraint (e.g., wrong line).
+  void markUnsuccessful(StatusTy S) {
+    assert(Status == Success && S != Success &&
+           "expected to change successful status to unsuccessful");
+    Status = S;
+  }
+  /// Return the match's input range, never \c std::nullopt.
+  virtual std::optional<SMRange> getMatchRange() const override {
+    return MatchRange;
+  }
+};
+
+/// \c MatchResultDiag for a pattern that did not match the input.
+class MatchNoneDiag : public MatchResultDiag {
+public:
+  enum StatusTy {
+    /// Indicates no match for an excluded pattern.
+    Success,
+    /// Indicates no match due to an expected or excluded pattern that has
+    /// proven to be invalid at match time (error).  The exact problems are
+    /// usually reported in subsequent \c MatchNoteDiag objects.
+    InvalidPattern,
+    /// Indicates no match for an expected pattern (error).  In some cases, it
+    /// follows good matches (because multiple matches are expected) or
+    /// discarded matches for the pattern.
+    Expected
+  };
+
+private:
+  StatusTy Status;
+
+public:
+  MatchNoneDiag(const Check::FileCheckType &CheckTy, SMLoc CheckLoc,
+                StatusTy Status, SMRange SearchRange)
+      : MatchResultDiag(FCDK_MatchNoneDiag, CheckTy, CheckLoc, SearchRange),
+        Status(Status) {}
+  /// Is \p FCD an instance of \c MatchNoneDiag?
+  static bool classof(const FileCheckDiag *FCD) {
+    return FCD->getKind() == FCDK_MatchNoneDiag;
+  }
+  /// Does the lack of match represent an error?
+  virtual bool isError() const override { return Status != Success; }
+  /// Does the lack of a match indicate a success?  If not, why not?
+  StatusTy getStatus() const { return Status; }
+  /// Return \c std::nullopt.
+  virtual std::optional<SMRange> getMatchRange() const override {
+    return std::nullopt;
+  }
+};
+
+/// Abstract base class for recording a FileCheck diagnostic that provides an
+/// additional note (possibly a new error) about the most recent
+/// \c MatchResultDiag.
 class MatchNoteDiag : public FileCheckDiag {
 private:
   MatchResultDiag *MRD;
-  std::optional<std::string> CustomNote;
 
 public:
-  MatchNoteDiag(MatchType MatchTy, SMRange InputRange,
-                std::optional<StringRef> CustomNote = std::nullopt)
-      : FileCheckDiag(FCDK_MatchNoteDiag, MatchTy, InputRange), MRD(nullptr),
-        CustomNote(CustomNote) {}
+  MatchNoteDiag(FileCheckDiagKind FCDK) : FileCheckDiag(FCDK), MRD(nullptr) {}
+  /// Destructor is purely virtual to ensure this remains an abstract class.
+  virtual ~MatchNoteDiag() = 0;
   /// Is \p FCD an instance of \c MatchNoteDiag?
   static bool classof(const FileCheckDiag *FCD) {
-    return FCD->getKind() == FCDK_MatchNoteDiag;
+    FileCheckDiagKind FCDK = FCD->getKind();
+    return FCDK_MatchNoteDiag_First <= FCDK && FCDK <= FCDK_MatchNoteDiag_Last;
   }
   /// Get the note's associated \c MatchResultDiag.
   virtual const MatchResultDiag &getMatchResultDiag() const override {
@@ -241,9 +326,82 @@ class MatchNoteDiag : public FileCheckDiag {
     assert(!MRD && "expected setMatchResultDiag to be called only once");
     MRD = MRDNew;
   }
-  /// A note to replace the one normally indicated by the match type, or the
-  /// empty string if none.
-  const std::optional<std::string> &getCustomNote() const { return CustomNote; }
+};
+
+/// \c MatchNoteDiag for a fuzzy match that serves as a suggestion for the next
+/// intended match for an expected pattern with too few or no good matches.
+class MatchFuzzyDiag : public MatchNoteDiag {
+private:
+  SMLoc MatchStart;
+
+public:
+  MatchFuzzyDiag(SMLoc MatchStart)
+      : MatchNoteDiag(FCDK_MatchFuzzyDiag), MatchStart(MatchStart) {}
+  /// Is \p FCD an instance of \c MatchFuzzyDiag?
+  static bool classof(const FileCheckDiag *FCD) {
+    return FCD->getKind() == FCDK_MatchFuzzyDiag;
+  }
+  /// Always false.  A fuzzy match is not an error even though it is performed
+  /// due to an error.
+  virtual bool isError() const override { return false; }
+  /// Return an input range (never \c std::nullopt) starting and ending at the
+  /// match start.  The actual match end is not computed.
+  virtual std::optional<SMRange> getMatchRange() const override {
+    return SMRange(MatchStart, MatchStart);
+  }
+};
+
+/// \c MatchNoteDiag with a custom note not described by any other class derived
+/// from \c MatchNoteDiag.
+class MatchCustomNoteDiag : public MatchNoteDiag {
+private:
+  std::string Note;
+  bool AddsError;
+  std::optional<SMRange> MatchRange;
+
+public:
+  /// If \p MatchRange is specified, it is a range for input text that was
+  /// matched in some way (e.g., variable capture) and that is described by
+  /// this note.  Either way, as usual, the associated \c MatchResultDiag has
+  /// any full match range for the pattern.
+  ///
+  /// If \p AddsError is true, then this note indicates a \a new error that is
+  /// distinct from any error indicated by the associated \c MatchResultDiag.
+  /// The error is described by \c Note, which must be worded appropriately for
+  /// prepending "error: " when presented later.  For example, the associated
+  /// \c MatchResultDiag might indicate a match to either an expected pattern
+  /// (success) or an excluded pattern (error), and \c Note might be "unable to
+  /// represent numeric value" to indicate the match could not be processed
+  /// afterward.
+  ///
+  /// If \p AddsError is false, then this note merely provides additional
+  /// information about the associated \c MatchResultDiag.  That information
+  /// might be something harmless (e.g., variable substitution), or it might be
+  /// one of potentially many problems summarized as an error by the
+  /// \c MatchResultDiag (e.g., one way in which the pattern was invalid).
+  ///@{
+  MatchCustomNoteDiag(SMRange MatchRange, StringRef Note,
+                      bool AddsError = false)
+      : MatchNoteDiag(FCDK_MatchCustomNoteDiag), Note(Note),
+        AddsError(AddsError), MatchRange(MatchRange) {}
+  MatchCustomNoteDiag(StringRef Note)
+      : MatchNoteDiag(FCDK_MatchCustomNoteDiag), Note(Note), AddsError(false) {}
+  ///@}
+  /// Is \p FCD an instance of \c MatchCustomNoteDiag?
+  static bool classof(const FileCheckDiag *FCD) {
+    return FCD->getKind() == FCDK_MatchCustomNoteDiag;
+  }
+  const std::string &getNote() const { return Note; }
+  /// Does this note indicate an \a additional error not indicated by the
+  /// associated \c MatchResultDiag?
+  ///
+  /// For details, see the \c MatchCustomNoteDiag::MatchCustomNoteDiag comments
+  /// for its \c AddsError parameter.
+  virtual bool isError() const override { return AddsError; }
+  /// Return the match range described by the note, or \c std::nullopt if none.
+  virtual std::optional<SMRange> getMatchRange() const override {
+    return MatchRange;
+  }
 };
 
 /// A \c FileCheckDiag series emitted by the FileCheck library.
@@ -272,14 +430,10 @@ class FileCheckDiagList {
       return;
     Note->setMatchResultDiag(CurMatchResultDiag);
   }
-  /// Adjust the most recent \c MatchResultDiag, which must exist, and every
-  /// \c MatchResultNote after it to have the match type \c MatchTy.
-  void adjustPrevDiags(FileCheckDiag::MatchType MatchTy) {
-    assert(CurMatchResultDiag && "expected previous MatchResultDiag");
-    for (auto I = DiagList.rbegin(), E = DiagList.rend();
-         I != E && &**I != CurMatchResultDiag; ++I)
-      (*I)->adjustMatchType(MatchTy);
-    CurMatchResultDiag->adjustMatchType(MatchTy);
+  /// Adjust the previous \c MatchResultDiag, which must be a \c MatchFoundDiag,
+  /// from successful status to unsuccessful status.
+  void adjustPrevMatchFoundDiag(MatchFoundDiag::StatusTy Status) {
+    cast<MatchFoundDiag>(CurMatchResultDiag)->markUnsuccessful(Status);
   }
   /// The \c FileCheckDiag list.
   const std::vector<std::unique_ptr<FileCheckDiag>> &getList() const {
diff --git a/llvm/lib/FileCheck/FileCheck.cpp b/llvm/lib/FileCheck/FileCheck.cpp
index b493eb67fa173..4d3ac87b9c724 100644
--- a/llvm/lib/FileCheck/FileCheck.cpp
+++ b/llvm/lib/FileCheck/FileCheck.cpp
@@ -1260,7 +1260,6 @@ unsigned Pattern::computeMatchDistance(StringRef Buffer) const {
 
 void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
                                  SMRange Range,
-                                 FileCheckDiag::MatchType MatchTy,
                                  FileCheckDiagList *Diags) const {
   // Print what we know about substitutions.
   if (!Substitutions.empty()) {
@@ -1280,13 +1279,13 @@ void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
       OS.write_escaped(Substitution->getFromString()) << "\" equal to ";
       OS << *MatchedValue;
 
-      // We report only the start of the match/search range to suggest we are
-      // reporting the substitutions as set at the start of the match/search.
-      // Indicating a non-zero-length range might instead seem to imply that the
+      // Unlike MatchCustomNoteDiag, PrintMessage needs a location.  We report
+      // only the start of the match/search range to suggest we are reporting
+      // the substitutions as set at the start of the match/search.  Indicating
+      // a non-zero-length range might instead seem to imply that the
       // substitution matches or was captured from exactly that range.
       if (Diags)
-        Diags->emplace<MatchNoteDiag>(
-            MatchTy, SMRange(Range.Start, Range.Start), OS.str());
+        Diags->emplace<MatchCustomNoteDiag>(OS.str());
       else
         SM.PrintMessage(Range.Start, SourceMgr::DK_Note, OS.str());
     }
@@ -1294,7 +1293,6 @@ void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
 }
 
 void Pattern::printVariableDefs(const SourceMgr &SM,
-                                FileCheckDiag::MatchType MatchTy,
                                 FileCheckDiagList *Diags) const {
   if (VariableDefs.empty() && NumericVariableDefs.empty())
     return;
@@ -1340,7 +1338,7 @@ void Pattern::printVariableDefs(const SourceMgr &SM,
     raw_svector_ostream OS(Msg);
     OS << "captured var \"" << VC.Name << "\"";
     if (Diags)
-      Diags->emplace<MatchNoteDiag>(MatchTy, VC.Range, OS.str());
+      Diags->emplace<MatchCustomNoteDiag>(VC.Range, OS.str());
     else
       SM.PrintMessage(VC.Range.Start, SourceMgr::DK_Note, OS.str(), VC.Range);
   }
@@ -1397,10 +1395,10 @@ void Pattern::printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
   // reasonable and not equal to what we showed in the "scanning from here"
   // line.
   if (Best && Best != StringRef::npos && BestQuality < 50) {
-    SMRange MatchRange = buildMatchRange(Buffer, Best, 0);
+    SMLoc MatchStart = SMLoc::getFromPointer(Buffer.data() + Best);
     if (Diags)
-      Diags->emplace<MatchNoteDiag>(FileCheckDiag::MatchFuzzy, MatchRange);
-    SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,
+      Diags->emplace<MatchFuzzyDiag>(MatchStart);
+    SM.PrintMessage(MatchStart, SourceMgr::DK_Note,
                     "possible intended match here");
 
     // FIXME: If we wanted to be really friendly we would show why the match
@@ -1507,6 +1505,8 @@ StringRef FileCheck::CanonicalizeFile(MemoryBuffer &MB,
 }
 
 FileCheckDiag::~FileCheckDiag() {}
+MatchResultDiag::~MatchResultDiag() {}
+MatchNoteDiag::~MatchNoteDiag() {}
 
 static bool IsPartOfWord(char c) {
   return (isAlnum(c) || c == '-' || c == '_');
@@ -2027,15 +2027,16 @@ static Error printMatch(bool ExpectedMatch, const SourceMgr &SM,
   }
 
   // Add "found" diagnostic, substitutions, and variable definitions to Diags.
-  FileCheckDiag::...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/195571


More information about the llvm-branch-commits mailing list