This patch adds a `--diff` flag to FileCheck to address the readability
of traditional FileCheck output which can be difficult to parse by
human, especially when dealing with multiple substitutions or large
input files with many mismatches and additional context. This feature
provides a more familiar, scannable format for developers by rendering
mismatches as diffs.
There are two diff modes, split and unified both with substitution and
no-substitution version however to make it easier for reviewer, this
only have unified with no substitution.
Functional description of PR-
`getDiffContext` -
It provides the surrounding context for the mismatch. It uses the
`SourceMgr` to find the Line using `LineNo`. Once it found the pointer,
it scans forward until it hits a newline (\n or \r) or the end of the
memory buffer, then it trim to remove the whitespaces.
`renderDiff`
This function handle the printing of diff, print header(expected and
actual line number), one line context before the target line, mismatch
i.e. expected line and actual line and finally one line after context.
`printDiff`
This does the preparation for printing the diff. It has `CheckStr` with
which it find the expected (pattern) line, It resolve the actual line
either with `OverwriteActualLine` (which it gets from handleDiffFailure
which uses fuzzy match `diag` vector) or with directly `SourceMgr`. It
then asked for Line context from `getDiffContext` and finally call
`renderDiff` for actual printing.
`handleDiffFailure`
This function is important. it first print header of input file and
pattern file path. Then do main task of finding the target input line
for the check pattern line. It uses fuzzy match to find most intended
match. If there is none then target line default to next input line in
the buffer. It then move the `CheckRegion` for next Check line.
`checkInput`
This is where we intercept the flow for diff output. checkInput function
traverse on each check line of each check label. It find the MatchPos,
if it is `npos` then break the loop for check label but in our case we
also call `handleDiffFailure` for printing mismatch. We also have a
handling of check-next and check-empty where even if `MatchPos` is > 0
i.e. there is match later, we intercept then call `handleDiffFailure`
for printing the gap as mismatch.
Example -
`$ cat input.ll`
```llvm
define i32 @sum() {
%res = add nsw i32 10, 20
ret i64 %res
}
```
`$ cat test.txt`
```llvm
; CHECK-LABEL: define i32 @calculate()
; CHECK: %res = add nsw i32 20, 10
; CHECK-NEXT: ret i32 %res
```
`$bin/FileCheck ./test.txt --input-file=./input.ll --diff=unidiff`
```llvm
--- ./test.txt
+++ ./input.ll
@@ -2 +2 @@
define i32 @cal() {
-%res = add nsw i32 20, 10
+%res = add nsw i32 10, 20
ret i64 %res
FileCheck: Found 1 unique textual mismatch.
```
Fixes #77257
Assisted by Gemini AI.
36 KiB
36 KiB