[llvm] [FileCheck] Improve colors in input dumps (PR #204936)
Joel E. Denny via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 27 15:36:49 PDT 2026
https://github.com/jdenny-ornl updated https://github.com/llvm/llvm-project/pull/204936
>From b2b510ad0bc268135b237e9ef8dcda6b31bea888 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sat, 16 May 2026 19:05:20 -0400
Subject: [PATCH 01/18] [FileCheck] Resurrect overflow tests
D150880 (landed as 0726cb004718) uses `APInt` to eliminate most
integer overflow issues from FileCheck numeric variables. It also
removes the 4 tests in
`llvm/test/FileCheck/match-time-error-propagation`.
While the elimination of overflow issues reduces the importance of
those tests, the tests still seem worthwhile. Without them, I see no
test that exercises the "unable to substitute variable or numeric
expression: overflow error" diagnostic in FileCheck input dumps.
This patch resurrects those tests and updates them to exercise the
remaining unsigned underflow case.
---
.../invalid-excluded-pattern.txt | 68 +++++++++++++++++++
.../invalid-expected-pattern.txt | 55 +++++++++++++++
.../matched-excluded-pattern.txt | 63 +++++++++++++++++
.../matched-expected-pattern.txt | 58 ++++++++++++++++
4 files changed, 244 insertions(+)
create mode 100644 llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt
create mode 100644 llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt
create mode 100644 llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt
create mode 100644 llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
diff --git a/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt
new file mode 100644
index 0000000000000..c8e621eb31796
--- /dev/null
+++ b/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt
@@ -0,0 +1,68 @@
+; Check handling of match-time diagnostics for invalid patterns (e.g.,
+; substitution overflow) in the case of excluded patterns (e.g., CHECK-NOT) that
+; also have other errors.
+;
+; At one time, FileCheck's exit status was zero for this case. Moreover, it
+; printed the error diagnostic only if -vv was specified and input dumps were
+; disabled. Test every combination as the logic is hard to get right.
+
+RUN: echo > %t.chk \
+RUN: 'CHECK-NOT: [[#0x0 - 0x1]] [[UNDEFVAR]]'
+RUN: echo > %t.in '-1'
+
+ ERR-NOT:{{.}}
+ ERR-VV:{{.*}}: remark: implicit EOF: expected string found in input
+ ERR-VV-NEXT:CHECK-NOT: {{.*}}
+ ERR-VV-NEXT:{{ *}}^
+ ERR-VV-NEXT:{{.*}}: note: found here
+ERR-VV-EMPTY:
+ ERR-VV-NEXT:^
+ ERR-NOT:{{.}}
+ ERR:{{.*}}: error: unable to substitute variable or numeric expression: overflow error
+ ERR-NEXT:CHECK-NOT: {{.*}}
+ ERR-NEXT:{{ *}}^
+ ERR-NEXT:{{.*}}: error: undefined variable: UNDEFVAR
+ ERR-NEXT:{{CHECK-NOT: \[\[#0x0 - 0x1\]\] \[\[UNDEFVAR\]\]}}
+ ERR-NEXT:{{ *}}^
+ ERR-NOT:{{error|note|remark|<stdin>}}:
+
+ DUMP:<<<<<<
+ DUMP-NEXT: 1: -1
+ DUMP-NEXT:not:1'0 X~~ error: match failed for invalid pattern
+ DUMP-NEXT:not:1'1 unable to substitute variable or numeric expression: overflow error
+ DUMP-NEXT:not:1'2 undefined variable: UNDEFVAR
+DUMP-VV-NEXT: 2:
+DUMP-VV-NEXT:eof:1 ^
+ DUMP-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check -dump-input=never cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,ERR-VV
+
+;--------------------------------------------------
+; Check -dump-input=fail cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP,DUMP-VV
diff --git a/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt
new file mode 100644
index 0000000000000..6aada8b0c7587
--- /dev/null
+++ b/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt
@@ -0,0 +1,55 @@
+; Check handling of match-time diagnostics for invalid patterns (e.g.,
+; substitution overflow) in the case of expected patterns (e.g., CHECK) that
+; also have other errors.
+
+RUN: echo > %t.chk \
+RUN: 'CHECK: [[#0x0 - 0x1]] [[UNDEFVAR]]'
+RUN: echo > %t.in '-1'
+
+ ERR-NOT:{{.}}
+ ERR:{{.*}}: error: unable to substitute variable or numeric expression: overflow error
+ ERR-NEXT:CHECK: {{.*}}
+ ERR-NEXT:{{ *}}^
+ ERR-NEXT:{{.*}}: error: undefined variable: UNDEFVAR
+ ERR-NEXT:{{CHECK: \[\[#0x0 - 0x1\]\] \[\[UNDEFVAR\]\]}}
+ ERR-NEXT:{{ *}}^
+ ERR-NOT:{{error|note|remark|<stdin>}}:
+
+ DUMP:<<<<<<
+DUMP-NEXT: 1: -1
+DUMP-NEXT:check:1'0 X~~ error: match failed for invalid pattern
+DUMP-NEXT:check:1'1 unable to substitute variable or numeric expression: overflow error
+DUMP-NEXT:check:1'2 undefined variable: UNDEFVAR
+DUMP-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check -dump-input=never cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+;--------------------------------------------------
+; Check -dump-input=fail cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
diff --git a/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt
new file mode 100644
index 0000000000000..b76ff5ed66aa6
--- /dev/null
+++ b/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt
@@ -0,0 +1,63 @@
+; Check handling of match-time diagnostics for invalid patterns (e.g.,
+; substitution overflow) in the case of excluded patterns (e.g., CHECK-NOT) that
+; otherwise have no errors.
+
+RUN: echo > %t.chk 'CHECK-NOT: [[#122+1]] [[STR:abc]] [[#NUM:0x0 - 0x1]]'
+RUN: echo > %t.in '123 abc -1'
+
+ ERR-NOT:{{.}}
+ ERR-VV:{{.*}}: remark: implicit EOF: expected string found in input
+ ERR-VV-NEXT:CHECK-NOT: {{.*}}
+ ERR-VV-NEXT:{{ *}}^
+ ERR-VV-NEXT:{{.*}}: note: found here
+ERR-VV-EMPTY:
+ ERR-VV-NEXT:^
+ ERR-NOT:{{.}}
+ ERR:{{.*}}: error: unable to substitute variable or numeric expression: overflow error
+ ERR-NEXT:CHECK-NOT: {{.*}}
+ ERR-NEXT:{{ *}}^
+ ERR-NEXT:<stdin>:1:1: note: with "122+1" equal to "123"
+ ERR-NEXT:123 abc -1
+ ERR-NEXT:^
+ ERR-NOT:{{error|note|remark|<stdin>}}:
+
+ DUMP:<<<<<<
+ DUMP-NEXT: 1: 123 abc -1
+ DUMP-NEXT:not:1'0 X~~~~~~~~~~ error: match failed for invalid pattern
+ DUMP-NEXT:not:1'1 unable to substitute variable or numeric expression: overflow error
+ DUMP-NEXT:not:1'2 with "122+1" equal to "123"
+DUMP-VV-NEXT: 2:
+DUMP-VV-NEXT:eof:1 ^
+ DUMP-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check -dump-input=never cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,ERR-VV
+
+;--------------------------------------------------
+; Check -dump-input=fail cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP,DUMP-VV
diff --git a/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
new file mode 100644
index 0000000000000..3388a53273918
--- /dev/null
+++ b/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
@@ -0,0 +1,58 @@
+; Check handling of match-time diagnostics for invalid patterns (e.g.,
+; substitution overflow) in the case of expected patterns (e.g., CHECK-NOT) that
+; otherwise have no errors.
+
+RUN: echo > %t.chk 'CHECK: [[#122+1]] [[STR:abc]] [[#NUM:0x0 - 0x1]]'
+RUN: echo > %t.in '123 abc -1'
+
+ ERR-NOT:{{.}}
+ ERR:{{.*}}: error: unable to substitute variable or numeric expression: overflow error
+ ERR-NEXT:CHECK: {{.*}}
+ ERR-NEXT:{{ *}}^
+ ERR-NEXT:<stdin>:1:1: note: with "122+1" equal to "123"
+ ERR-NEXT:123 abc -1
+ ERR-NEXT:^
+ ERR-NEXT:<stdin>:1:3: note: possible intended match here
+ ERR-NEXT:123 abc -1
+ ERR-NEXT: ^
+ ERR-NOT:{{error|note|remark|<stdin>}}:
+
+ DUMP:<<<<<<
+DUMP-NEXT: 1: 123 abc -1
+DUMP-NEXT:check:1'0 X~~~~~~~~~~ error: match failed for invalid pattern
+DUMP-NEXT:check:1'1 unable to substitute variable or numeric expression: overflow error
+DUMP-NEXT:check:1'2 with "122+1" equal to "123"
+DUMP-NEXT:check:1'3 ? possible intended match
+DUMP-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check -dump-input=never cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=never -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR
+
+;--------------------------------------------------
+; Check -dump-input=fail cases.
+;--------------------------------------------------
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -v %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input=fail -vv %t.chk < %t.in 2>&1 \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=ERR,DUMP
>From 2b7c4d04afabd18b0f84bbea9294935bc84e5657 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sat, 16 May 2026 20:14:44 -0400
Subject: [PATCH 02/18] [FileCheck] Refactor -dump-input test
This patch refactors `llvm/test/FileCheck/dump-input/annotations.txt`
to improve maintainability and coverage and to prepare for the
upcoming implementation of search range annotations.
Lit substitutions
=================
The test repeats the same basic set of RUN lines *many* times. This
patch encapsulates those in lit substitutions to improve
maintainability. By doing so, it also helps to ensure more consistent
coverage of all cases and thus slightly expands coverage.
-strict-whitespace
==================
Via those substitutions, this patch adds `-strict-whitespace`
throughout the test, and it drops the initial `-strict-whitespace`
case because it is then redundant. That causes many whitespace
changes throughout the test, so this patch is easier to read with `git
diff -w`.
When I originally wrote the test, I thought maintaining it would be
too painful with `-strict-whitespace`. However, I now think it is
important for usability to thoroughly check that annotations are
correctly aligned with the input, especially given the upcoming search
range annotations.
-dump-input-label-width
=======================
To address that anticipated maintenance pain, and to make the above
change easier to implement, this patch also implements a new hidden
FileCheck option, `-dump-input-label-width`. It enables tests like
this one not to have to fuss with fluctuations in the label column
width that are caused when varying the verbosity options. I do not
anticipate this option will be used outside FileCheck's own test
suite.
Splitting directive blocks
==========================
To improve readability, this patch splits apart directive blocks where
the same annotations appear multiple times with small differences at
different verbosity levels. See new header comments for details.
---
.../test/FileCheck/dump-input/annotations.txt | 1123 +++++++++--------
llvm/utils/FileCheck/FileCheck.cpp | 11 +
2 files changed, 614 insertions(+), 520 deletions(-)
diff --git a/llvm/test/FileCheck/dump-input/annotations.txt b/llvm/test/FileCheck/dump-input/annotations.txt
index 367ea3377e6ae..f928f3c3eaada 100644
--- a/llvm/test/FileCheck/dump-input/annotations.txt
+++ b/llvm/test/FileCheck/dump-input/annotations.txt
@@ -1,43 +1,111 @@
+; Throughout this file, where %{pre}=FOO, FileCheck prefixes are as follows to
+; indicate the level of FileCheck verbosity under test:
+; - FOO = quiet, -v, or -vv
+; - FOO-V = -v or -vv (-vv implies -v)
+; - FOO-VV = -vv
+; - FOO-Q = quiet only
+; - FOO-VQ = -v only
+;
+; Most cases use just FOO, FOO-V, and FOO-VV in a unified block of directives
+; that checks an input dump where some annotations are omitted at lower
+; verbosity levels.
+;
+; For a few cases, multiple annotations persist but *change* across verbosity
+; levels, usually due to modified annotation labels. Seeing multiple versions
+; of the same annotation in the same block of directives can be confusing. To
+; improve readability, it is usually best to split these into separate blocks.
+; For example, use FOO-Q to check only the version without -v or -vv.
+
+; DEFINE: %{pre} =
+; DEFINE: %{opts} =
+;
+; DEFINE: %{run-fc} = \
+; DEFINE: %ProtectFileCheckOutput \
+; DEFINE: FileCheck -dump-input=always -input-file=%t.in %t.chk \
+; DEFINE: -dump-input-label-width=15 %{opts}
+;
+; DEFINE: %{check-fc} = \
+; DEFINE: FileCheck -strict-whitespace -match-full-lines %s \
+; DEFINE: -allow-unused-prefixes \
+; DEFINE: -implicit-check-not='remark:' -implicit-check-not='error:'
+;
+; For each case, it is usually best to run these in order of decreasing
+; verbosity to maximize the information for debugging when the case is broken.
+;
+; DEFINE: %{run-vv} = %{run-fc} -vv 2>&1 | \
+; DEFINE: %{check-fc} -check-prefixes=%{pre},%{pre}-V,%{pre}-VV
+; DEFINE: %{run-v} = %{run-fc} -v 2>&1 | \
+; DEFINE: %{check-fc} -check-prefixes=%{pre},%{pre}-V,%{pre}-VQ
+; DEFINE: %{run} = %{run-fc} 2>&1 | \
+; DEFINE: %{check-fc} -check-prefixes=%{pre},%{pre}-Q
+
;--------------------------------------------------
-; Use -strict-whitespace to check marker and note alignment here.
-; (Also check multiline marker where start/end columns vary across lines.)
+; Label column width
;
-; In the remaining checks, don't use -strict-whitespace and thus check just the
-; presence, order, and lengths of markers. That way, if we ever change padding
-; within line labels, we don't have to adjust so many tests.
+; Check that the label column width is sane when we do not force a minimum. The
+; rest of the test file is easier to maintain if we otherwise always force it
+; because that avoids the possibility of it fluctuating across different
+; verbosity levels.
;--------------------------------------------------
+; Check with both the annotation label and the line number fairly short.
+;
; RUN: echo 'hello world' > %t.in
-; RUN: echo 'goodbye' >> %t.in
-; RUN: echo 'world' >> %t.in
-; RUN: echo 'unicorn' >> %t.in
-
-; RUN: echo 'CHECK: hello' > %t.chk
-; RUN: echo 'CHECK: universe' >> %t.chk
-
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -strict-whitespace -match-full-lines -check-prefix=ALIGN \
-; RUN: -implicit-check-not='remark:' %s
+; RUN: echo 'CHECK: hello world' > %t.chk
+;
+; REDEFINE: %{opts} = -dump-input-label-width=0
+; REDEFINE: %{pre} = WIDTH-SHORT
+; RUN: %{run-v}
+;
+; WIDTH-SHORT:<<<<<<
+; WIDTH-SHORT-NEXT: 1: hello world
+; WIDTH-SHORT-NEXT:check:1 ^~~~~~~~~~~
+; WIDTH-SHORT-NEXT:>>>>>>
+; WIDTH-SHORT-NOT:{{.}}
-; Verbose diagnostics are suppressed but not errors.
-; ALIGN:{{.*}}error:{{.*}}
-; ALIGN:{{.*}}possible intended match here{{.*}}
-
-; ALIGN:Input was:
-; ALIGN-NEXT:<<<<<<
-; ALIGN-NEXT: 1: hello world
-; ALIGN-NEXT:check:1 ^~~~~
-; ALIGN-NEXT:check:2'0 X~~~~~~ error: no match found
-; ALIGN-NEXT: 2: goodbye
-; ALIGN-NEXT:check:2'0 ~~~~~~~~
-; ALIGN-NEXT: 3: world
-; ALIGN-NEXT:check:2'0 ~~~~~~
-; ALIGN-NEXT: 4: unicorn
-; ALIGN-NEXT:check:2'0 ~~~~~~~~
-; ALIGN-NEXT:check:2'1 ? possible intended match
-; ALIGN-NEXT:>>>>>>
-; ALIGN-NOT:{{.}}
+; Check that lengthening the annotation label widens the column.
+;
+; RUN: echo 'hello world' > %t.in
+; RUN: echo 'hello world' >> %t.in
+; RUN: echo 'CHECK-COUNT-2: hello world' > %t.chk
+;
+; REDEFINE: %{opts} = -dump-input-label-width=0
+; REDEFINE: %{pre} = WIDTH-ANNOT
+; RUN: %{run-v}
+;
+; WIDTH-ANNOT:<<<<<<
+; WIDTH-ANNOT-NEXT: 1: hello world
+; WIDTH-ANNOT-NEXT:count:1'0 ^~~~~~~~~~~
+; WIDTH-ANNOT-NEXT: 2: hello world
+; WIDTH-ANNOT-NEXT:count:1'1 ^~~~~~~~~~~
+; WIDTH-ANNOT-NEXT:>>>>>>
+; WIDTH-ANNOT-NOT:{{.}}
+
+; Check that a longer line number (6 characters) than annotation label (5
+; characters) widens the column.
+;
+; RUN: %python -c 'print("x\n" * 10**5, end="")' > %t.in
+; RUN: echo 'the end' >> %t.in
+; RUN: echo 'CHECK-DAG: the end' > %t.chk
+;
+; REDEFINE: %{opts} = -dump-input-label-width=0 -dump-input-filter=annotation \
+; REDEFINE: -dump-input-context=3
+; REDEFINE: %{pre} = WIDTH-LINENO
+; RUN: %{run-v}
+;
+; WIDTH-LINENO:<<<<<<
+; WIDTH-LINENO-NEXT: .
+; WIDTH-LINENO-NEXT: .
+; WIDTH-LINENO-NEXT: .
+; WIDTH-LINENO-NEXT: 99998: x
+; WIDTH-LINENO-NEXT: 99999: x
+; WIDTH-LINENO-NEXT: 100000: x
+; WIDTH-LINENO-NEXT: 100001: the end
+; WIDTH-LINENO-NEXT:dag:1 ^~~~~~~
+; WIDTH-LINENO-NEXT:>>>>>>
+; WIDTH-LINENO-NOT:{{.}}
+
+; REDEFINE: %{opts} =
;--------------------------------------------------
; CHECK (also: multi-line search range, fuzzy match)
@@ -52,34 +120,26 @@
; RUN: echo 'CHECK: hello' > %t.chk
; RUN: echo 'CHECK: world' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=CHK \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=CHK,CHK-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=CHK,CHK-V \
-; RUN: -implicit-check-not='remark:'
+; REDEFINE: %{pre} = CHK
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; CHK: {{.*}}error:{{.*}}
-; CHK: {{.*}}possible intended match here{{.*}}
-
-; CHK: <<<<<<
-; CHK-NEXT: 1: hello
-; CHK-V-NEXT: check:1 ^~~~~
-; CHK-NEXT: check:2'0 X error: no match found
-; CHK-NEXT: 2: again
-; CHK-NEXT: check:2'0 ~~~~~~
-; CHK-NEXT: 3: whirled
-; CHK-NEXT: check:2'0 ~~~~~~~~
-; CHK-NEXT: check:2'1 ? possible intended match
-; CHK-NEXT: >>>>>>
-; CHK-NOT: {{.}}
+; CHK:{{.*}}error:{{.*}}
+; CHK:{{.*}}possible intended match here{{.*}}
+
+; CHK:<<<<<<
+; CHK-NEXT: 1: hello
+; CHK-V-NEXT:check:1 ^~~~~
+; CHK-NEXT:check:2'0 X error: no match found
+; CHK-NEXT: 2: again
+; CHK-NEXT:check:2'0 ~~~~~~
+; CHK-NEXT: 3: whirled
+; CHK-NEXT:check:2'0 ~~~~~~~~
+; CHK-NEXT:check:2'1 ? possible intended match
+; CHK-NEXT:>>>>>>
+; CHK-NOT:{{.}}
;--------------------------------------------------
; CHECK-COUNT-<num>
@@ -93,36 +153,35 @@
; RUN: echo 'CHECK-COUNT-3: pete' > %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=CNT,CNT-Q \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=CNT,CNT-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=CNT,CNT-V \
-; RUN: -implicit-check-not='remark:'
+; REDEFINE: %{pre} = CNT
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; CNT: {{.*}}error:{{.*}}
-
-; CNT: <<<<<<
-; CNT-NEXT: 1: pete
-; CNT-V-NEXT: count:1'0 ^~~~
-; CNT-NEXT: 2: repete
-; CNT-V-NEXT: count:1'1 ^~~~
-; CNT-Q-NEXT: count:1'0 X error: no match found
-; CNT-V-NEXT: count:1'2 X error: no match found
-; CNT-NEXT: 3: repeat
-; CNT-Q-NEXT: count:1'0 ~~~~~~~
-; CNT-Q-NEXT: count:1'1 ? possible intended match
-; CNT-V-NEXT: count:1'2 ~~~~~~~
-; CNT-V-NEXT: count:1'3 ? possible intended match
-; CNT-NEXT: >>>>>>
-; CNT-NOT: {{.}}
+; CNT:{{.*}}error:{{.*}}
+
+; CNT-V:<<<<<<
+; CNT-V-NEXT: 1: pete
+; CNT-V-NEXT:count:1'0 ^~~~
+; CNT-V-NEXT: 2: repete
+; CNT-V-NEXT:count:1'1 ^~~~
+; CNT-V-NEXT:count:1'2 X error: no match found
+; CNT-V-NEXT: 3: repeat
+; CNT-V-NEXT:count:1'2 ~~~~~~~
+; CNT-V-NEXT:count:1'3 ? possible intended match
+; CNT-V-NEXT:>>>>>>
+; CNT-V-NOT:{{.}}
+
+; CNT-Q:<<<<<<
+; CNT-Q-NEXT: 1: pete
+; CNT-Q-NEXT: 2: repete
+; CNT-Q-NEXT:count:1'0 X error: no match found
+; CNT-Q-NEXT: 3: repeat
+; CNT-Q-NEXT:count:1'0 ~~~~~~~
+; CNT-Q-NEXT:count:1'1 ? possible intended match
+; CNT-Q-NEXT:>>>>>>
+; CNT-Q-NOT:{{.}}
;--------------------------------------------------
; CHECK-NEXT (also: EOF search-range, wrong-line match)
@@ -137,48 +196,46 @@
; RUN: echo 'CHECK-NEXT: again' >> %t.chk
; RUN: echo 'CHECK-NEXT: world' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=NXT \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=NXT,NXT-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=NXT,NXT-V,NXT-VV \
-; RUN: -implicit-check-not='remark:' -allow-unused-prefixes
+; REDEFINE: %{pre} = NXT
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; NXT: {{.*}}error:{{.*}}
+; NXT:{{.*}}error:{{.*}}
-; NXT: <<<<<<
-; NXT-NEXT: 1: hello
-; NXT-V-NEXT: check:1 ^~~~~
-; NXT-NEXT: 2: again
-; NXT-V-NEXT: next:2 ^~~~~
-; NXT-NEXT: next:3 X error: no match found
-; NXT-NEXT: >>>>>>
-; NXT-NOT: {{.}}
+; NXT:<<<<<<
+; NXT-NEXT: 1: hello
+; NXT-V-NEXT:check:1 ^~~~~
+; NXT-NEXT: 2: again
+; NXT-V-NEXT:next:2 ^~~~~
+; NXT-NEXT:next:3 X error: no match found
+; NXT-NEXT:>>>>>>
+; NXT-NOT:{{.}}
; Wrong-line match.
; RUN: echo 'yonder' >> %t.in
; RUN: echo 'world' >> %t.in
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=NXT2
+; REDEFINE: %{pre} = NXT2
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
-; NXT2: <<<<<<
-; NXT2-NEXT: 1: hello
-; NXT2-NEXT: 2: again
-; NXT2-NEXT: 3: yonder
-; NXT2-NEXT: 4: world
-; NXT2-NEXT: next:3 !~~~~ error: match on wrong line
-; NXT2-NEXT: >>>>>>
-; NXT2-NOT: {{.}}
+; Verbose diagnostics are suppressed but not errors.
+; NXT2:{{.*}}error:{{.*}}
+
+; NXT2:<<<<<<
+; NXT2-NEXT: 1: hello
+; NXT2-V-NEXT:check:1 ^~~~~
+; NXT2-NEXT: 2: again
+; NXT2-V-NEXT:next:2 ^~~~~
+; NXT2-NEXT: 3: yonder
+; NXT2-NEXT: 4: world
+; NXT2-NEXT:next:3 !~~~~ error: match on wrong line
+; NXT2-NEXT:>>>>>>
+; NXT2-NOT:{{.}}
;--------------------------------------------------
; CHECK-SAME (also: multiple annotations per line, single-char search range,
@@ -193,50 +250,42 @@
; RUN: echo 'CHECK-SAME: world' >> %t.chk
; RUN: echo 'CHECK-SAME: again' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=SAM \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=SAM,SAM-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=SAM,SAM-V,SAM-VV \
-; RUN: -implicit-check-not='remark:' -allow-unused-prefixes
+; REDEFINE: %{pre} = SAM
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; SAM: {{.*}}error:{{.*}}
+; SAM:{{.*}}error:{{.*}}
-; SAM: <<<<<<
-; SAM-NEXT: 1: hello world!
-; SAM-V-NEXT: check:1 ^~~~~
-; SAM-V-NEXT: same:2 ^~~~~
-; SAM-NEXT: same:3 X~ error: no match found
-; SAM-NEXT: >>>>>>
-; SAM-NOT: {{.}}
+; SAM:<<<<<<
+; SAM-NEXT: 1: hello world!
+; SAM-V-NEXT:check:1 ^~~~~
+; SAM-V-NEXT:same:2 ^~~~~
+; SAM-NEXT:same:3 X~ error: no match found
+; SAM-NEXT:>>>>>>
+; SAM-NOT:{{.}}
; Wrong-line match.
; RUN: echo 'again' >> %t.in
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=SAM2 \
-; RUN: -implicit-check-not='remark:'
+; REDEFINE: %{pre} = SAM2
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; SAM2: {{.*}}error:{{.*}}
+; SAM2:{{.*}}error:{{.*}}
-; SAM2: <<<<<<
-; SAM2-NEXT: 1: hello world!
-; SAM2-NEXT: check:1 ^~~~~
-; SAM2-NEXT: same:2 ^~~~~
-; SAM2-NEXT: 2: again
-; SAM2-NEXT: same:3 !~~~~ error: match on wrong line
-; SAM2-NEXT: >>>>>>
-; SAM2-NOT: {{.}}
+; SAM2:<<<<<<
+; SAM2-NEXT: 1: hello world!
+; SAM2-V-NEXT:check:1 ^~~~~
+; SAM2-V-NEXT:same:2 ^~~~~
+; SAM2-NEXT: 2: again
+; SAM2-NEXT:same:3 !~~~~ error: match on wrong line
+; SAM2-NEXT:>>>>>>
+; SAM2-NOT:{{.}}
;--------------------------------------------------
; CHECK-EMPTY (also: search range ends at label, single-char match, wrong-line
@@ -260,35 +309,27 @@
; RUN: echo 'CHECK-EMPTY:' >> %t.chk
; RUN: echo 'CHECK-LABEL: label' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=EMP \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=EMP,EMP-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=EMP,EMP-V,EMP-VV \
-; RUN: -implicit-check-not='remark:' -allow-unused-prefixes
+; REDEFINE: %{pre} = EMP
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; EMP: {{.*}}error:{{.*}}
-
-; EMP: <<<<<<
-; EMP-NEXT: 1: hello
-; EMP-V-NEXT: check:1 ^~~~~
-; EMP-NEXT: 2:
-; EMP-V-NEXT: empty:2 ^
-; EMP-NEXT: empty:3 X error: no match found
-; EMP-NEXT: 3: world
-; EMP-NEXT: empty:3 ~~~~~~
-; EMP-NEXT: 4: label
-; EMP-V-NEXT: label:4 ^~~~~
-; EMP-NEXT: empty:3 ~~~~~
-; EMP-NEXT: >>>>>>
-; EMP-NOT: {{.}}
+; EMP:{{.*}}error:{{.*}}
+
+; EMP:<<<<<<
+; EMP-NEXT: 1: hello
+; EMP-V-NEXT:check:1 ^~~~~
+; EMP-NEXT: 2:
+; EMP-V-NEXT:empty:2 ^
+; EMP-NEXT:empty:3 X error: no match found
+; EMP-NEXT: 3: world
+; EMP-NEXT:empty:3 ~~~~~~
+; EMP-NEXT: 4: label
+; EMP-V-NEXT:label:4 ^~~~~
+; EMP-NEXT:empty:3 ~~~~~
+; EMP-NEXT:>>>>>>
+; EMP-NOT:{{.}}
; Wrong-line match.
@@ -298,30 +339,22 @@
; RUN: echo 'CHECK: hello' > %t.chk
; RUN: echo 'CHECK-EMPTY:' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=EMP2 \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=EMP2,EMP2-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=EMP2,EMP2-V,EMP2-VV \
-; RUN: -implicit-check-not='remark:' -allow-unused-prefixes
+; REDEFINE: %{pre} = EMP2
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; EMP2: {{.*}}error:{{.*}}
+; EMP2:{{.*}}error:{{.*}}
-; EMP2: <<<<<<
-; EMP2-NEXT: 1: hello
-; EMP2-V-NEXT: check:1 ^~~~~
-; EMP2-NEXT: 2: world
-; EMP2-NEXT: 3:
-; EMP2-NEXT: empty:2 ! error: match on wrong line
-; EMP2-NEXT: >>>>>>
-; EMP2-NOT: {{.}}
+; EMP2:<<<<<<
+; EMP2-NEXT: 1: hello
+; EMP2-V-NEXT:check:1 ^~~~~
+; EMP2-NEXT: 2: world
+; EMP2-NEXT: 3:
+; EMP2-NEXT:empty:2 ! error: match on wrong line
+; EMP2-NEXT:>>>>>>
+; EMP2-NOT:{{.}}
;--------------------------------------------------
; CHECK-NOT (also: EOF pattern, and multiline range that ends before EOL)
@@ -336,66 +369,50 @@
; RUN: echo 'CHECK-NOT: goodbye' > %t.chk
; RUN: echo 'CHECK-NOT: world' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=NOT \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=NOT,NOT-V \
-; RUN: -implicit-check-not='remark:' -allow-unused-prefixes
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=NOT,NOT-V,NOT-VV \
-; RUN: -implicit-check-not='remark:' -allow-unused-prefixes
+; REDEFINE: %{pre} = NOT
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; NOT: {{.*}}error:{{.*}}
-
-; NOT: <<<<<<
-; NOT-NEXT: 1: hello
-; NOT-VV-NEXT: not:1 X~~~~~
-; NOT-NEXT: 2: world
-; NOT-VV-NEXT: not:1 ~~~~~~
-; NOT-NEXT: not:2 !~~~~ error: no match expected
-; NOT-NEXT: 3: again
-; NOT-VV-NEXT: not:1 ~~~~~~
-; NOT-VV-NEXT: 4:
-; NOT-VV-NEXT: eof:2 ^
-; NOT-NEXT: >>>>>>
-; NOT-NOT: {{.}}
+; NOT:{{.*}}error:{{.*}}
+
+; NOT:<<<<<<
+; NOT-NEXT: 1: hello
+; NOT-VV-NEXT:not:1 X~~~~~
+; NOT-NEXT: 2: world
+; NOT-VV-NEXT:not:1 ~~~~~~
+; NOT-NEXT:not:2 !~~~~ error: no match expected
+; NOT-NEXT: 3: again
+; NOT-VV-NEXT:not:1 ~~~~~~
+; NOT-VV-NEXT: 4:
+; NOT-VV-NEXT:eof:2 ^
+; NOT-NEXT:>>>>>>
+; NOT-NOT:{{.}}
; Again, but with a CHECK instead of EOF as search range end.
; RUN: echo 'CHECK: ain' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=NOT2 \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=NOT2,NOT2-V \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=NOT2,NOT2-V,NOT2-VV \
-; RUN: -implicit-check-not='remark:'
+; REDEFINE: %{pre} = NOT2
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; NOT2: {{.*}}error:{{.*}}
-
-; NOT2: <<<<<<
-; NOT2-NEXT: 1: hello
-; NOT2-VV-NEXT: not:1 X~~~~~
-; NOT2-NEXT: 2: world
-; NOT2-VV-NEXT: not:1 ~~~~~~
-; NOT2-NEXT: not:2 !~~~~ error: no match expected
-; NOT2-NEXT: 3: again
-; NOT2-V-NEXT: check:3 ^~~
-; NOT2-VV-NEXT: not:1 ~~
-; NOT2-NEXT: >>>>>>
-; NOT2-NOT: {{.}}
+; NOT2:{{.*}}error:{{.*}}
+
+; NOT2:<<<<<<
+; NOT2-NEXT: 1: hello
+; NOT2-VV-NEXT:not:1 X~~~~~
+; NOT2-NEXT: 2: world
+; NOT2-VV-NEXT:not:1 ~~~~~~
+; NOT2-NEXT:not:2 !~~~~ error: no match expected
+; NOT2-NEXT: 3: again
+; NOT2-V-NEXT:check:3 ^~~
+; NOT2-VV-NEXT:not:1 ~~
+; NOT2-NEXT:>>>>>>
+; NOT2-NOT:{{.}}
;--------------------------------------------------
; CHECK-DAG (also: matches in different order than directives, discarded match)
@@ -412,47 +429,48 @@
; RUN: echo 'CHECK-DAG: abc' >> %t.chk
; RUN: echo 'CHECK-DAG: def' >> %t.chk
-; Prefixes used here:
-; DAG = quiet, -v, or -vv
-; DAG-Q = quiet
-; DAG-V = -v or -vv (-vv implies -v)
-; DAG-VQ = -v and not -vv
-; DAG-VV = -vv
-
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG,DAG-Q \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG,DAG-V,DAG-VQ \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG,DAG-V,DAG-VV \
-; RUN: -implicit-check-not='remark:'
+; REDEFINE: %{pre} = DAG
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
-; DAG: {{.*}}error:{{.*}}
-
-; DAG: <<<<<<
-; DAG-NEXT: 1: abc
-; DAG-V-NEXT: dag:2 ^~~
-; DAG-VV-NEXT: dag:3'0 !~~ discard: overlaps earlier match
-; DAG-NEXT: 2: def
-; DAG-V-NEXT: dag:1 ^~~
-; DAG-VV-NEXT: dag:4'0 !~~ discard: overlaps earlier match
-; DAG-Q-NEXT: dag:4 X error: no match found
-; DAG-VQ-NEXT: dag:4 X error: no match found
-; DAG-VV-NEXT: dag:4'1 X error: no match found
-; DAG-NEXT: 3: abc
-; DAG-VQ-NEXT: dag:3 ^~~
-; DAG-VV-NEXT: dag:3'1 ^~~
-; DAG-Q-NEXT: dag:4 ~~~~
-; DAG-VQ-NEXT: dag:4 ~~~~
-; DAG-VV-NEXT: dag:4'1 ~~~~
-; DAG-NEXT: >>>>>>
-; DAG-NOT: {{.}}
+; DAG:{{.*}}error:{{.*}}
+
+; DAG-VV:<<<<<<
+; DAG-VV-NEXT: 1: abc
+; DAG-VV-NEXT:dag:2 ^~~
+; DAG-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
+; DAG-VV-NEXT: 2: def
+; DAG-VV-NEXT:dag:1 ^~~
+; DAG-VV-NEXT:dag:4'0 !~~ discard: overlaps earlier match
+; DAG-VV-NEXT:dag:4'1 X error: no match found
+; DAG-VV-NEXT: 3: abc
+; DAG-VV-NEXT:dag:3'1 ^~~
+; DAG-VV-NEXT:dag:4'1 ~~~~
+; DAG-VV-NEXT:>>>>>>
+; DAG-VV-NOT:{{.}}
+
+; DAG-VQ:<<<<<<
+; DAG-VQ-NEXT: 1: abc
+; DAG-VQ-NEXT:dag:2 ^~~
+; DAG-VQ-NEXT: 2: def
+; DAG-VQ-NEXT:dag:1 ^~~
+; DAG-VQ-NEXT:dag:4 X error: no match found
+; DAG-VQ-NEXT: 3: abc
+; DAG-VQ-NEXT:dag:3 ^~~
+; DAG-VQ-NEXT:dag:4 ~~~~
+; DAG-VQ-NEXT:>>>>>>
+; DAG-VQ-NOT:{{.}}
+
+; DAG-Q:<<<<<<
+; DAG-Q-NEXT: 1: abc
+; DAG-Q-NEXT: 2: def
+; DAG-Q-NEXT:dag:4 X error: no match found
+; DAG-Q-NEXT: 3: abc
+; DAG-Q-NEXT:dag:4 ~~~~
+; DAG-Q-NEXT:>>>>>>
+; DAG-Q-NOT:{{.}}
; Check sorting of annotations when the order of diagnostics across an input
; line is different than the order of the associated directives in the check
@@ -467,39 +485,43 @@
; RUN: echo 'CHECK-DAG: de' >> %t.chk
; RUN: echo 'CHECK-DAG: def' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG1L,DAG1L-Q \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG1L,DAG1L-V,DAG1L-VQ \
-; RUN: -implicit-check-not='remark:'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG1L,DAG1L-V,DAG1L-VV \
-; RUN: -implicit-check-not='remark:'
+; REDEFINE: %{pre} = DAG1L
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
; DAG1L:{{.*}}error:{{.*}}
-; DAG1L:<<<<<<
-; DAG1L-NEXT: 1: abc def abc def
-; DAG1L-V-NEXT:dag:1 ^~~
-; DAG1L-V-NEXT:dag:2 ^~
-; DAG1L-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
-; DAG1L-VQ-NEXT:dag:3 ^~~
-; DAG1L-VV-NEXT:dag:3'1 ^~~
-; DAG1L-VV-NEXT:dag:4'0 !~ discard: overlaps earlier match
-; DAG1L-VQ-NEXT:dag:4 ^~
-; DAG1L-VV-NEXT:dag:4'1 ^~
-; DAG1L-VV-NEXT:dag:5'0 !~~ discard: overlaps earlier match
-; DAG1L-VV-NEXT:dag:5'1 !~~ discard: overlaps earlier match
-; DAG1L-Q-NEXT:dag:5 X~ error: no match found
-; DAG1L-VQ-NEXT:dag:5 X~ error: no match found
-; DAG1L-VV-NEXT:dag:5'2 X~ error: no match found
-; DAG1L-NEXT:>>>>>>
-; DAG1L-NOT:{{.}}
+; DAG1L-VV:<<<<<<
+; DAG1L-VV-NEXT: 1: abc def abc def
+; DAG1L-VV-NEXT:dag:1 ^~~
+; DAG1L-VV-NEXT:dag:2 ^~
+; DAG1L-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:3'1 ^~~
+; DAG1L-VV-NEXT:dag:4'0 !~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:4'1 ^~
+; DAG1L-VV-NEXT:dag:5'0 !~~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:5'1 !~~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:5'2 X~ error: no match found
+; DAG1L-VV-NEXT:>>>>>>
+; DAG1L-VV-NOT:{{.}}
+
+; DAG1L-VQ:<<<<<<
+; DAG1L-VQ-NEXT: 1: abc def abc def
+; DAG1L-VQ-NEXT:dag:1 ^~~
+; DAG1L-VQ-NEXT:dag:2 ^~
+; DAG1L-VQ-NEXT:dag:3 ^~~
+; DAG1L-VQ-NEXT:dag:4 ^~
+; DAG1L-VQ-NEXT:dag:5 X~ error: no match found
+; DAG1L-VQ-NEXT:>>>>>>
+; DAG1L-VQ-NOT:{{.}}
+
+; DAG1L-Q:<<<<<<
+; DAG1L-Q-NEXT: 1: abc def abc def
+; DAG1L-Q-NEXT:dag:5 X~ error: no match found
+; DAG1L-Q-NEXT:>>>>>>
+; DAG1L-Q-NOT:{{.}}
;--------------------------------------------------
; CHECK-LABEL
@@ -547,61 +569,73 @@
; RUN: echo 'CHECK-NOT: labelF' >> %t.chk
; RUN: echo 'CHECK-LABEL: labelF' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=LAB,LAB-Q \
-; RUN: -implicit-check-not='{{remark:|error:}}'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=LAB,LAB-V \
-; RUN: -implicit-check-not='{{remark:|error:}}'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=LAB,LAB-V,LAB-VV \
-; RUN: -implicit-check-not='{{remark:|error:}}'
+; REDEFINE: %{pre} = LAB
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
; Verbose diagnostics are suppressed but not errors.
; LAB:{{.*}}.chk:3:8: error: CHECK: expected string not found in input
; LAB:{{.*}}.chk:6:14: error: CHECK-LABEL: expected string not found in input
; LAB:{{.*}}.chk:9:12: error: CHECK-NOT: excluded string found in input
-; LAB:<<<<<<
-; LAB-NEXT: 1: text
-; LAB-V-NEXT:check:1 ^~~~
-; LAB-NEXT: 2: labelA
-; LAB-V-NEXT:label:2'0 ^~~~~~
-; LAB-V-NEXT:label:2'1 ^~~~~~
-; LAB-NEXT:check:3 X error: no match found
-; LAB-NEXT: 3: textA
-; LAB-NEXT:check:3 ~~~~~~
-; LAB-NEXT: 4: labelB
-; LAB-V-NEXT:label:4 ^~~~~~
-; LAB-NEXT:check:3 ~~~~~~
-; LAB-NEXT: 5: textB
-; LAB-NEXT: 6: labelC
-; LAB-V-NEXT:label:6'0 ^~~~~~
-; LAB-V-NEXT:check:5 ^~~~~~
-; LAB-Q-NEXT:label:6 X error: no match found
-; LAB-V-NEXT:label:6'1 X error: no match found
-; LAB-VV-NEXT:not:7 X
-; LAB-NEXT: 7: textC
-; LAB-VV-NEXT:not:7 ~~~~~~
-; LAB-NEXT: 8: labelD
-; LAB-V-NEXT:label:8'0 ^~~~~~
-; LAB-V-NEXT:label:8'1 ^~~~~~
-; LAB-NEXT: 9: textD
-; LAB-NEXT:not:9 !~~~~ error: no match expected
-; LAB-NEXT: 10: labelE
-; LAB-V-NEXT:label:10'0 ^~~~~~
-; LAB-V-NEXT:label:10'1 ^~~~~~
-; LAB-VV-NEXT:not:11 X
-; LAB-NEXT: 11: textE
-; LAB-VV-NEXT:not:11 ~~~~~~
-; LAB-NEXT: 12: labelF
-; LAB-V-NEXT:label:12'0 ^~~~~~
-; LAB-V-NEXT:label:12'1 ^~~~~~
-; LAB-NEXT:>>>>>>
-; LAB-NOT:{{.}}
+; LAB-V:<<<<<<
+; LAB-V-NEXT: 1: text
+; LAB-V-NEXT:check:1 ^~~~
+; LAB-V-NEXT: 2: labelA
+; LAB-V-NEXT:label:2'0 ^~~~~~
+; LAB-V-NEXT:label:2'1 ^~~~~~
+; LAB-V-NEXT:check:3 X error: no match found
+; LAB-V-NEXT: 3: textA
+; LAB-V-NEXT:check:3 ~~~~~~
+; LAB-V-NEXT: 4: labelB
+; LAB-V-NEXT:label:4 ^~~~~~
+; LAB-V-NEXT:check:3 ~~~~~~
+; LAB-V-NEXT: 5: textB
+; LAB-V-NEXT: 6: labelC
+; LAB-V-NEXT:label:6'0 ^~~~~~
+; LAB-V-NEXT:check:5 ^~~~~~
+; LAB-V-NEXT:label:6'1 X error: no match found
+; LAB-VV-NEXT:not:7 X
+; LAB-V-NEXT: 7: textC
+; LAB-VV-NEXT:not:7 ~~~~~~
+; LAB-V-NEXT: 8: labelD
+; LAB-V-NEXT:label:8'0 ^~~~~~
+; LAB-V-NEXT:label:8'1 ^~~~~~
+; LAB-V-NEXT: 9: textD
+; LAB-V-NEXT:not:9 !~~~~ error: no match expected
+; LAB-V-NEXT: 10: labelE
+; LAB-V-NEXT:label:10'0 ^~~~~~
+; LAB-V-NEXT:label:10'1 ^~~~~~
+; LAB-VV-NEXT:not:11 X
+; LAB-V-NEXT: 11: textE
+; LAB-VV-NEXT:not:11 ~~~~~~
+; LAB-V-NEXT: 12: labelF
+; LAB-V-NEXT:label:12'0 ^~~~~~
+; LAB-V-NEXT:label:12'1 ^~~~~~
+; LAB-V-NEXT:>>>>>>
+; LAB-V-NOT:{{.}}
+
+; LAB-Q:<<<<<<
+; LAB-Q-NEXT: 1: text
+; LAB-Q-NEXT: 2: labelA
+; LAB-Q-NEXT:check:3 X error: no match found
+; LAB-Q-NEXT: 3: textA
+; LAB-Q-NEXT:check:3 ~~~~~~
+; LAB-Q-NEXT: 4: labelB
+; LAB-Q-NEXT:check:3 ~~~~~~
+; LAB-Q-NEXT: 5: textB
+; LAB-Q-NEXT: 6: labelC
+; LAB-Q-NEXT:label:6 X error: no match found
+; LAB-Q-NEXT: 7: textC
+; LAB-Q-NEXT: 8: labelD
+; LAB-Q-NEXT: 9: textD
+; LAB-Q-NEXT:not:9 !~~~~ error: no match expected
+; LAB-Q-NEXT: 10: labelE
+; LAB-Q-NEXT: 11: textE
+; LAB-Q-NEXT: 12: labelF
+; LAB-Q-NEXT:>>>>>>
+; LAB-Q-NOT:{{.}}
;--------------------------------------------------
; --implicit-check-not
@@ -618,58 +652,50 @@
; RUN: echo 'CHECK: wor' >> %t.chk
; RUN: echo 'CHECK: !' >> %t.chk
-; Prefixes used here:
-; IMPNOT = quiet, -v, or -vv
-; IMPNOT-Q = quiet
-; IMPNOT-V = -v or -vv (-vv implies -v)
-; IMPNOT-VQ = -v and not -vv
-; IMPNOT-VV = -vv
-
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file=%t.in %t.chk 2>&1 \
-; RUN: --implicit-check-not='goodbye' \
-; RUN: --implicit-check-not='world' \
-; RUN: --implicit-check-not='again' \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=IMPNOT,IMPNOT-Q \
-; RUN: -implicit-check-not='{{remark:|error:}}'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file=%t.in %t.chk -v 2>&1 \
-; RUN: --implicit-check-not='goodbye' \
-; RUN: --implicit-check-not='world' \
-; RUN: --implicit-check-not='again' \
-; RUN: | FileCheck -match-full-lines %s \
-; RUN: -check-prefixes=IMPNOT,IMPNOT-V,IMPNOT-VQ \
-; RUN: -implicit-check-not='{{remark:|error:}}'
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -input-file=%t.in %t.chk -vv 2>&1 \
-; RUN: --implicit-check-not='goodbye' \
-; RUN: --implicit-check-not='world' \
-; RUN: --implicit-check-not='again' \
-; RUN: | FileCheck -match-full-lines %s \
-; RUN: -check-prefixes=IMPNOT,IMPNOT-V,IMPNOT-VV \
-; RUN: -implicit-check-not='{{remark:|error:}}'
+; REDEFINE: %{pre} = IMPNOT
+; REDEFINE: %{opts} = \
+; REDEFINE: --implicit-check-not='goodbye' \
+; REDEFINE: --implicit-check-not='world' \
+; REDEFINE: --implicit-check-not='again'
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+; REDEFINE: %{opts} =
; Verbose diagnostics are suppressed but not errors.
; IMPNOT:{{.*}}command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
-; IMPNOT:<<<<<<
-; IMPNOT-NEXT: 1: hello world again!
-; IMPNOT-V-NEXT:check:1 ^~~
-; IMPNOT-VV-NEXT:not:imp1'0 X
-; IMPNOT-VV-NEXT:not:imp2'0 X
-; IMPNOT-VV-NEXT:not:imp3'0 X
-; IMPNOT-V-NEXT:check:2 ^~~
-; IMPNOT-VV-NEXT:not:imp1'1 X~~
-; IMPNOT-VV-NEXT:not:imp2'1 X~~
-; IMPNOT-VV-NEXT:not:imp3'1 X~~
-; IMPNOT-V-NEXT:check:3 ^
-; IMPNOT-VV-NEXT:not:imp1'2 X~~~~~~~
-; IMPNOT-VV-NEXT:not:imp2'2 X~~~~~~~
-; IMPNOT-Q-NEXT:not:imp3 !~~~~ error: no match expected
-; IMPNOT-VQ-NEXT:not:imp3 !~~~~ error: no match expected
-; IMPNOT-VV-NEXT:not:imp3'2 !~~~~ error: no match expected
-; IMPNOT-NEXT:>>>>>>
-; IMPNOT-NOT:{{.}}
+; IMPNOT-VV:<<<<<<
+; IMPNOT-VV-NEXT: 1: hello world again!
+; IMPNOT-VV-NEXT:check:1 ^~~
+; IMPNOT-VV-NEXT:not:imp1'0 X
+; IMPNOT-VV-NEXT:not:imp2'0 X
+; IMPNOT-VV-NEXT:not:imp3'0 X
+; IMPNOT-VV-NEXT:check:2 ^~~
+; IMPNOT-VV-NEXT:not:imp1'1 X~~
+; IMPNOT-VV-NEXT:not:imp2'1 X~~
+; IMPNOT-VV-NEXT:not:imp3'1 X~~
+; IMPNOT-VV-NEXT:check:3 ^
+; IMPNOT-VV-NEXT:not:imp1'2 X~~~~~~~
+; IMPNOT-VV-NEXT:not:imp2'2 X~~~~~~~
+; IMPNOT-VV-NEXT:not:imp3'2 !~~~~ error: no match expected
+; IMPNOT-VV-NEXT:>>>>>>
+; IMPNOT-VV-NOT:{{.}}
+
+; IMPNOT-VQ:<<<<<<
+; IMPNOT-VQ-NEXT: 1: hello world again!
+; IMPNOT-VQ-NEXT:check:1 ^~~
+; IMPNOT-VQ-NEXT:check:2 ^~~
+; IMPNOT-VQ-NEXT:check:3 ^
+; IMPNOT-VQ-NEXT:not:imp3 !~~~~ error: no match expected
+; IMPNOT-VQ-NEXT:>>>>>>
+; IMPNOT-VQ-NOT:{{.}}
+
+; IMPNOT-Q:<<<<<<
+; IMPNOT-Q-NEXT: 1: hello world again!
+; IMPNOT-Q-NEXT:not:imp3 !~~~~ error: no match expected
+; IMPNOT-Q-NEXT:>>>>>>
+; IMPNOT-Q-NOT:{{.}}
;--------------------------------------------------
; Substitutions: successful and failed positive directives.
@@ -681,25 +707,32 @@
; RUN: echo 'CHECK: [[DEF_MATCH1]] [[DEF_MATCH2]]' > %t.chk
; RUN: echo 'CHECK: [[DEF_MATCH1]] [[UNDEF]] [[DEF_NOMATCH]]' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -vv -input-file=%t.in %t.chk 2>&1 \
-; RUN: -DDEF_MATCH1=def-match1 -DDEF_MATCH2=def-match2 \
-; RUN: -DDEF_NOMATCH=foobar \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=SUBST-POS
-
-; SUBST-POS:<<<<<<
-; SUBST-POS-NEXT: 1: def-match1 def-match2
-; SUBST-POS-NEXT:check:1'0 ^~~~~~~~~~~~~~~~~~~~~
-; SUBST-POS-NEXT:check:1'1 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-POS-NEXT:check:1'2 with "DEF_MATCH2" equal to "def-match2"
-; SUBST-POS-NEXT:check:2'0 X error: match failed for invalid pattern
-; SUBST-POS-NEXT:check:2'1 undefined variable: UNDEF
-; SUBST-POS-NEXT:check:2'2 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-POS-NEXT:check:2'3 with "DEF_NOMATCH" equal to "foobar"
-; SUBST-POS-NEXT: 2: def-match1 def-nomatch
-; SUBST-POS-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~
-; SUBST-POS-NEXT:check:2'4 ? possible intended match
-; SUBST-POS-NEXT:>>>>>>
+; REDEFINE: %{pre} = SUBST-POS
+; REDEFINE: %{opts} = \
+; REDEFINE: -DDEF_MATCH1=def-match1 -DDEF_MATCH2=def-match2 \
+; REDEFINE: -DDEF_NOMATCH=foobar
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+; REDEFINE: %{opts} =
+
+; Verbose diagnostics are suppressed but not errors.
+; SUBST-POS:{{.*}}error:{{.*}}
+; SUBST-POS:{{.*}}possible intended match here{{.*}}
+
+; SUBST-POS:<<<<<<
+; SUBST-POS-NEXT: 1: def-match1 def-match2
+; SUBST-POS-V-NEXT:check:1'0 ^~~~~~~~~~~~~~~~~~~~~
+; SUBST-POS-V-NEXT:check:1'1 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-POS-V-NEXT:check:1'2 with "DEF_MATCH2" equal to "def-match2"
+; SUBST-POS-NEXT:check:2'0 X error: match failed for invalid pattern
+; SUBST-POS-NEXT:check:2'1 undefined variable: UNDEF
+; SUBST-POS-NEXT:check:2'2 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-POS-NEXT:check:2'3 with "DEF_NOMATCH" equal to "foobar"
+; SUBST-POS-NEXT: 2: def-match1 def-nomatch
+; SUBST-POS-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~
+; SUBST-POS-NEXT:check:2'4 ? possible intended match
+; SUBST-POS-NEXT:>>>>>>
;--------------------------------------------------
; Substitutions: successful and failed negative directives.
@@ -713,26 +746,33 @@
; RUN: echo 'CHECK-NOT: [[DEF_MATCH1]] [[DEF_MATCH2]]' >> %t.chk
; RUN: echo 'CHECK: END' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -vv -input-file=%t.in %t.chk 2>&1 \
-; RUN: -DDEF_MATCH1=def-match1 -DDEF_MATCH2=def-match2 \
-; RUN: -DDEF_NOMATCH=foobar \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=SUBST-NEG
-
-; SUBST-NEG:<<<<<<
-; SUBST-NEG-NEXT: 1: def-match1 def-nomatch
-; SUBST-NEG-NEXT:not:1'0 X~~~~~~~~~~~~~~~~~~~~~~ error: match failed for invalid pattern
-; SUBST-NEG-NEXT:not:1'1 undefined variable: UNDEF
-; SUBST-NEG-NEXT:not:1'2 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-NEG-NEXT:not:1'3 with "DEF_NOMATCH" equal to "foobar"
-; SUBST-NEG-NEXT: 2: def-match1 def-match2
-; SUBST-NEG-NEXT:not:1'0 ~~~~~~~~~~~~~~~~~~~~~~
-; SUBST-NEG-NEXT:not:2'0 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
-; SUBST-NEG-NEXT:not:2'1 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-NEG-NEXT:not:2'2 with "DEF_MATCH2" equal to "def-match2"
-; SUBST-NEG-NEXT: 3: END
-; SUBST-NEG-NEXT:check:3 ^~~
-; SUBST-NEG-NEXT:>>>>>>
+; REDEFINE: %{pre} = SUBST-NEG
+; REDEFINE: %{opts} = \
+; REDEFINE: -DDEF_MATCH1=def-match1 -DDEF_MATCH2=def-match2 \
+; REDEFINE: -DDEF_NOMATCH=foobar
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+; REDEFINE: %{opts} =
+
+; Verbose diagnostics are suppressed but not errors.
+; SUBST-NEG:{{.*}}error:{{.*}}
+; SUBST-NEG:{{.*}}error:{{.*}}
+
+; SUBST-NEG:<<<<<<
+; SUBST-NEG-NEXT: 1: def-match1 def-nomatch
+; SUBST-NEG-NEXT:not:1'0 X~~~~~~~~~~~~~~~~~~~~~~ error: match failed for invalid pattern
+; SUBST-NEG-NEXT:not:1'1 undefined variable: UNDEF
+; SUBST-NEG-NEXT:not:1'2 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-NEG-NEXT:not:1'3 with "DEF_NOMATCH" equal to "foobar"
+; SUBST-NEG-NEXT: 2: def-match1 def-match2
+; SUBST-NEG-NEXT:not:1'0 ~~~~~~~~~~~~~~~~~~~~~~
+; SUBST-NEG-NEXT:not:2'0 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
+; SUBST-NEG-NEXT:not:2'1 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-NEG-NEXT:not:2'2 with "DEF_MATCH2" equal to "def-match2"
+; SUBST-NEG-NEXT: 3: END
+; SUBST-NEG-V-NEXT:check:3 ^~~
+; SUBST-NEG-NEXT:>>>>>>
;--------------------------------------------------
; Captured variables
@@ -757,33 +797,37 @@
; RUN: echo 'CHECK-NOT: var in neg match: [[VAR:foo]]' >> %t.chk
; RUN: echo 'CHECK: END' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -vv -input-file=%t.in %t.chk 2>&1 \
-; RUN: | FileCheck -strict-whitespace -match-full-lines %s -check-prefix=CAPTURE-NEG
-
-; CAPTURE-NEG:<<<<<<
-; CAPTURE-NEG-NEXT: 1: strvar: foo
-; CAPTURE-NEG-NEXT:check:1'0 ^~~~~~~~~~~
-; CAPTURE-NEG-NEXT:check:1'1 ^~~ captured var "STRVAR"
-; CAPTURE-NEG-NEXT: 2: numvar no expr: 51
-; CAPTURE-NEG-NEXT:check:2'0 ^~~~~~~~~~~~~~~~~~
-; CAPTURE-NEG-NEXT:check:2'1 ^~ captured var "NUMVAR_NO_EXPR"
-; CAPTURE-NEG-NEXT: 3: numvar expr: -49
-; CAPTURE-NEG-NEXT:check:3'0 ^~~~~~~~~~~~~~~~
-; CAPTURE-NEG-NEXT:check:3'1 with "%d,NUMVAR_EXPR:2-NUMVAR_NO_EXPR" equal to "-49"
-; CAPTURE-NEG-NEXT:check:3'2 ^~~ captured var "NUMVAR_EXPR"
-; CAPTURE-NEG-NEXT: 4: many: foo 100 8 bar
-; CAPTURE-NEG-NEXT:check:4'0 ^~~~~~~~~~~~~~~~~~~
-; CAPTURE-NEG-NEXT:check:4'1 ^~~ captured var "VAR1"
-; CAPTURE-NEG-NEXT:check:4'2 ^~~ captured var "VAR3"
-; CAPTURE-NEG-NEXT:check:4'3 ^ captured var "VAR2"
-; CAPTURE-NEG-NEXT:check:4'4 ^~~ captured var "VAR4"
-; CAPTURE-NEG-NEXT: 5: var in neg match: foo
-; CAPTURE-NEG-NEXT:not:5'0 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
-; CAPTURE-NEG-NEXT:not:5'1 !~~ captured var "VAR"
-; CAPTURE-NEG-NEXT: 6: END
-; CAPTURE-NEG-NEXT:check:6 ^~~
-; CAPTURE-NEG-NEXT:>>>>>>
+; REDEFINE: %{pre} = CAPTURE-NEG
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+
+; Verbose diagnostics are suppressed but not errors.
+; CAPTURE-NEG:{{.*}}error:{{.*}}
+
+; CAPTURE-NEG:<<<<<<
+; CAPTURE-NEG-NEXT: 1: strvar: foo
+; CAPTURE-NEG-V-NEXT:check:1'0 ^~~~~~~~~~~
+ CAPTURE-NEG-V-NEXT:check:1'1 ^~~ captured var "STRVAR"
+; CAPTURE-NEG-NEXT: 2: numvar no expr: 51
+; CAPTURE-NEG-V-NEXT:check:2'0 ^~~~~~~~~~~~~~~~~~
+; CAPTURE-NEG-V-NEXT:check:2'1 ^~ captured var "NUMVAR_NO_EXPR"
+; CAPTURE-NEG-NEXT: 3: numvar expr: -49
+; CAPTURE-NEG-V-NEXT:check:3'0 ^~~~~~~~~~~~~~~~
+; CAPTURE-NEG-V-NEXT:check:3'1 with "%d,NUMVAR_EXPR:2-NUMVAR_NO_EXPR" equal to "-49"
+; CAPTURE-NEG-V-NEXT:check:3'2 ^~~ captured var "NUMVAR_EXPR"
+; CAPTURE-NEG-NEXT: 4: many: foo 100 8 bar
+; CAPTURE-NEG-V-NEXT:check:4'0 ^~~~~~~~~~~~~~~~~~~
+; CAPTURE-NEG-V-NEXT:check:4'1 ^~~ captured var "VAR1"
+; CAPTURE-NEG-V-NEXT:check:4'2 ^~~ captured var "VAR3"
+; CAPTURE-NEG-V-NEXT:check:4'3 ^ captured var "VAR2"
+; CAPTURE-NEG-V-NEXT:check:4'4 ^~~ captured var "VAR4"
+; CAPTURE-NEG-NEXT: 5: var in neg match: foo
+; CAPTURE-NEG-NEXT:not:5'0 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
+; CAPTURE-NEG-NEXT:not:5'1 !~~ captured var "VAR"
+; CAPTURE-NEG-NEXT: 6: END
+; CAPTURE-NEG-V-NEXT:check:6 ^~~
+; CAPTURE-NEG-NEXT:>>>>>>
;--------------------------------------------------
; CHECK-NEXT, CHECK-SAME, CHECK-DAG note fixups.
@@ -804,17 +848,27 @@
; RUN: echo 'CHECK: pre' > %t.chk
; RUN: echo 'CHECK-NEXT: [[VAR]]' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -vv -input-file=%t.in %t.chk 2>&1 \
-; RUN: -DVAR=var \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=SUBST_NEXT
+; REDEFINE: %{pre} = SUBST_NEXT
+; REDEFINE: %{opts} = -DVAR=var
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+; REDEFINE: %{opts} =
-; SUBST_NEXT:<<<<<<
-; SUBST_NEXT-NEXT: 1: pre var
-; SUBST_NEXT-NEXT:check:1 ^~~
-; SUBST_NEXT-NEXT:next:2'0 !~~ error: match on wrong line
-; SUBST_NEXT-NEXT:next:2'1 with "VAR" equal to "var"
-; SUBST_NEXT-NEXT:>>>>>>
+; Verbose diagnostics are suppressed but not errors.
+; SUBST_NEXT:{{.*}}error:{{.*}}
+
+; SUBST_NEXT-V:<<<<<<
+; SUBST_NEXT-V-NEXT: 1: pre var
+; SUBST_NEXT-V-NEXT:check:1 ^~~
+; SUBST_NEXT-V-NEXT:next:2'0 !~~ error: match on wrong line
+; SUBST_NEXT-V-NEXT:next:2'1 with "VAR" equal to "var"
+; SUBST_NEXT-V-NEXT:>>>>>>
+
+; SUBST_NEXT-Q:<<<<<<
+; SUBST_NEXT-Q-NEXT: 1: pre var
+; SUBST_NEXT-Q-NEXT:next:2 !~~ error: match on wrong line
+; SUBST_NEXT-Q-NEXT:>>>>>>
;- - - - - - - - - - - - - - - - - - - - - - - - -
; CHECK-SAME.
@@ -826,18 +880,29 @@
; RUN: echo 'CHECK: pre' > %t.chk
; RUN: echo 'CHECK-SAME: [[VAR]]' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: not FileCheck -dump-input=always -vv -input-file=%t.in %t.chk 2>&1 \
-; RUN: -DVAR=var \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=SUBST_SAME
+; REDEFINE: %{pre} = SUBST_SAME
+; REDEFINE: %{opts} = -DVAR=var
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+; REDEFINE: %{opts} =
-; SUBST_SAME:<<<<<<
-; SUBST_SAME-NEXT: 1: pre
-; SUBST_SAME-NEXT:check:1 ^~~
-; SUBST_SAME-NEXT: 2: var
-; SUBST_SAME-NEXT:same:2'0 !~~ error: match on wrong line
-; SUBST_SAME-NEXT:same:2'1 with "VAR" equal to "var"
-; SUBST_SAME-NEXT:>>>>>>
+; Verbose diagnostics are suppressed but not errors.
+; SUBST_SAME:{{.*}}error:{{.*}}
+
+; SUBST_SAME-V:<<<<<<
+; SUBST_SAME-V-NEXT: 1: pre
+; SUBST_SAME-V-NEXT:check:1 ^~~
+; SUBST_SAME-V-NEXT: 2: var
+; SUBST_SAME-V-NEXT:same:2'0 !~~ error: match on wrong line
+; SUBST_SAME-V-NEXT:same:2'1 with "VAR" equal to "var"
+; SUBST_SAME-V-NEXT:>>>>>>
+
+; SUBST_SAME-Q:<<<<<<
+; SUBST_SAME-Q-NEXT: 1: pre
+; SUBST_SAME-Q-NEXT: 2: var
+; SUBST_SAME-Q-NEXT:same:2 !~~ error: match on wrong line
+; SUBST_SAME-Q-NEXT:>>>>>>
;- - - - - - - - - - - - - - - - - - - - - - - - -
; CHECK-DAG.
@@ -851,19 +916,37 @@
; RUN: echo 'CHECK-DAG: [[VAR]]' >> %t.chk
; RUN: echo 'CHECK: END' >> %t.chk
-; RUN: %ProtectFileCheckOutput \
-; RUN: FileCheck -dump-input=always -vv -input-file=%t.in %t.chk 2>&1 \
-; RUN: -DVAR=var \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=SUBST_DAG
-
-; SUBST_DAG:<<<<<<
-; SUBST_DAG-NEXT: 1: var
-; SUBST_DAG-NEXT:dag:1 ^~~
-; SUBST_DAG-NEXT:dag:2'0 !~~ discard: overlaps earlier match
-; SUBST_DAG-NEXT:dag:2'1 with "VAR" equal to "var"
-; SUBST_DAG-NEXT: 2: var
-; SUBST_DAG-NEXT:dag:2'2 ^~~
-; SUBST_DAG-NEXT:dag:2'3 with "VAR" equal to "var"
-; SUBST_DAG-NEXT: 3: END
-; SUBST_DAG-NEXT:check:3 ^~~
-; SUBST_DAG-NEXT:>>>>>>
+; REDEFINE: %{pre} = SUBST_DAG
+; REDEFINE: %{opts} = -DVAR=var
+; RUN: %{run-vv}
+; RUN: %{run-v}
+; RUN: %{run}
+; REDEFINE: %{opts} =
+
+; SUBST_DAG-VV:<<<<<<
+; SUBST_DAG-VV-NEXT: 1: var
+; SUBST_DAG-VV-NEXT:dag:1 ^~~
+; SUBST_DAG-VV-NEXT:dag:2'0 !~~ discard: overlaps earlier match
+; SUBST_DAG-VV-NEXT:dag:2'1 with "VAR" equal to "var"
+; SUBST_DAG-VV-NEXT: 2: var
+; SUBST_DAG-VV-NEXT:dag:2'2 ^~~
+; SUBST_DAG-VV-NEXT:dag:2'3 with "VAR" equal to "var"
+; SUBST_DAG-VV-NEXT: 3: END
+; SUBST_DAG-VV-NEXT:check:3 ^~~
+; SUBST_DAG-VV-NEXT:>>>>>>
+
+; SUBST_DAG-VQ:<<<<<<
+; SUBST_DAG-VQ-NEXT: 1: var
+; SUBST_DAG-VQ-NEXT:dag:1 ^~~
+; SUBST_DAG-VQ-NEXT: 2: var
+; SUBST_DAG-VQ-NEXT:dag:2'0 ^~~
+; SUBST_DAG-VQ-NEXT:dag:2'1 with "VAR" equal to "var"
+; SUBST_DAG-VQ-NEXT: 3: END
+; SUBST_DAG-VQ-NEXT:check:3 ^~~
+; SUBST_DAG-VQ-NEXT:>>>>>>
+
+; SUBST_DAG-Q:<<<<<<
+; SUBST_DAG-Q-NEXT: 1: var
+; SUBST_DAG-Q-NEXT: 2: var
+; SUBST_DAG-Q-NEXT: 3: END
+; SUBST_DAG-Q-NEXT:>>>>>>
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index faa568a791757..8c760db50a375 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -168,6 +168,16 @@ static cl::list<unsigned> DumpInputContexts(
"this option, the largest specified <N> has precedence. The\n"
"default is 5.\n"));
+static cl::opt<unsigned> DumpInputLabelWidth(
+ "dump-input-label-width", cl::value_desc("N"), cl::init(0), cl::Hidden,
+ cl::desc("In the dump requested by -dump-input, set <N> as the minimum\n"
+ "width for the initial label column. When there are multiple\n"
+ "occurrences of this option, the last specified has precedence.\n"
+ "The default is 0, meaning that the actual labels fully\n"
+ "determine the width. FileCheck's own test suite uses this\n"
+ "option to avoid a fluctuating column width when checking input\n"
+ "dumps. This option is not expected to be useful elsewhere.\n"));
+
typedef cl::list<std::string>::const_iterator prefix_iterator;
@@ -759,6 +769,7 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
// One space would be enough to achieve that, but more makes it even easier
// to see.
LabelWidthGlobal = std::max(LabelWidthGlobal, LineNoWidth) + 3;
+ LabelWidthGlobal = std::max(LabelWidthGlobal, DumpInputLabelWidth.getValue());
// Print annotated input lines.
unsigned PrevLineInFilter = 0; // 0 means none so far
>From e407a44495ddd10b96745443ea5a7391874ab3b0 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sat, 16 May 2026 20:21:24 -0400
Subject: [PATCH 03/18] [FileCheck] Annotate search ranges with { } in
-dump-input
Example
=======
```
$ cat check
CHECK: start
CHECK-NEXT: end
$ FileCheck -v -dump-input-context=2 check < input |& tail -23
<<<<<<
1: start
check:1 ^~~~~
next:2'0 { search range start (exclusive)
2: foo0
3: foo1
.
.
.
21: foo19
22: foo20
23: end
next:2'1 !~~ error: match on wrong line
24: bar0
25: bar1
.
.
.
42: bar18
43: bar19
44: bar20
next:2'2 } search range end (exclusive)
>>>>>>
```
Without this patch, input lines 1-3 and 42-44 are not shown. However,
lines 1-3 are where the actual problem is because that is where the
`CHECK-NEXT` directive was expected to match but did not.
Search Ranges Are Helpful
=========================
In general, this patch marks any failed pattern's search range by
using the annotation style shown above, and these annotations are
filtered in when using `-dump-input-filter=error`, which is the
default filter. Seeing the search range can be helpful for
understanding the pattern's behavior. Moreover, the cause of the
pattern failure is often the input at the start or end of the search
range. For example:
- A `CHECK-NEXT` or `CHECK-SAME` match on the wrong line, as in the
above example.
- A `CHECK-NOT` unexpected match because a neighboring directive
matched at an unexpected point, affecting the search range.
- An unmatched `CHECK` because a subsequent `CHECK-LABEL` matched at
an unexpected point, affecting the search range end. (In this case,
the search range start and thus the prior directive's match is
already revealed without this patch.)
This patch introduces tests in
`llvm/test/FileCheck/dump-input/search-range-annotations` to
demonstrate those cases.
This patch is a replacement for D96653, which attempted to address the
above cases but in a less straight-forward and somewhat broken manner.
The idea of the current patch was discussed during that review.
Replacing `X~~`
===============
Without this patch, search ranges for unmatched patterns (whether a
success, as for `CHECK-NOT`, or a failure, as for `CHECK`) are already
marked with `X~~`. In those cases, this patch replaces those
annotations with the new annotations shown above. As described above,
this patch adds the new annotations to all other failed matched
patterns as well.
`X~~` is thus no longer used by `-dump-input`. The `X~~` style is
very noisy, especially for consecutive unmatched unexpected patterns
(like a `CHECK-NOT` block), all of which mark every line of their
identical search ranges. Switching to the new style significantly
reduces the noise in such cases. That noise was discussed recently in
issue #77257 and PRs linked from there, and that discussion led to the
resurrection of this patch.
Without this patch, `-dump-input-filter=error` filters in only the
start of a search range that spans multiple lines because an entire
`X~~` is one annotation. With this patch, it filters in both the
start and end of a search range because they are separate annotations
(or a single one-liner, as discussed below). With or without this
patch, a different argument to `-dump-input-filter` (and `-vv`) is
required to filter in the search range for an unmatched unexpected
pattern, like `CHECK-NOT`, because that is not an error.
One-Liners
==========
If a search range does not involve multiple input lines, this patch
keeps the `{` and `}` markers on the same output line like this:
```
<<<<<<
1: start foo end
check:1 ^~~~~
check:3 ^~~
not:2 { } search range (exclusive bounds)
>>>>>>
```
Exclusive Boundaries
====================
`{` and `}` are to be interpreted as exclusive bounds. That is, the
characters at those markers are not included in the search range, but
everything in between is. To try to avoid confusion, this patch adds
the word "exclusive" in every search range annotation.
When the search range starts or ends at a line boundary, the marker
cannot be placed at the first or last character of the line because
that would exclude that character. This patch instead places the
marker in the margin of the input dump, either before the line's first
character or after the line's last character (usually a newline),
rather than on the adjacent line. I have found this makes the
annotations easier to read (more apt have a one-liner, at least), and
I do not think it would make much sense to move a start annotation to
an imaginary line 0. For example, the `{` and `}` below appear in the
input dump margins, before the first character, `s`, and after the
space representing the newline:
```
<<<<<<
1: start
check:1'0 { } search range (exclusive bounds)
check:1'1 error: no match found
>>>>>>
```
Before trying exclusive bounds, I experimented with notations
involving inclusive bounds (e.g., `[` and `]`, or `[` and `)`). Such
notations either cannot distinguish empty ranges (without a cryptic
inversion like `][`) from one-character ranges, or they cannot
represent them with one-liners (because they must occupy the same
column), increasing verbosity. I ultimately decided I prefer
exclusive bounds because they are visually and semantically symmetric
while consistently concise and unambiguous.
For comparison, match ranges (e.g., `^~~`) cannot distinguish
one-character ranges from empty ranges. However, in my experience,
empty match ranges are uncommon, and usually it is easy to distinguish
them based on the pattern or directive (e.g., `CHECK-EMPTY`). In
contrast, empty search ranges can occur repeatedly when directive
matches are adjacent and `-implicit-check-not` is used.
---
llvm/include/llvm/FileCheck/FileCheck.h | 4 +-
.../test/FileCheck/dump-input/annotations.txt | 477 ++++++++++----
llvm/test/FileCheck/dump-input/context.txt | 204 +++---
llvm/test/FileCheck/dump-input/enable.txt | 49 +-
llvm/test/FileCheck/dump-input/filter.txt | 597 +++++++++++-------
.../check-label-follows.txt | 74 +++
.../check-next-same.txt | 61 ++
.../search-range-annotations/check-not.txt | 112 ++++
.../invalid-excluded-pattern.txt | 7 +-
.../invalid-expected-pattern.txt | 7 +-
.../matched-excluded-pattern.txt | 7 +-
.../matched-expected-pattern.txt | 9 +-
llvm/utils/FileCheck/FileCheck.cpp | 230 ++++++-
13 files changed, 1337 insertions(+), 501 deletions(-)
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
diff --git a/llvm/include/llvm/FileCheck/FileCheck.h b/llvm/include/llvm/FileCheck/FileCheck.h
index b000f5b0dac73..61486567c403b 100644
--- a/llvm/include/llvm/FileCheck/FileCheck.h
+++ b/llvm/include/llvm/FileCheck/FileCheck.h
@@ -302,7 +302,7 @@ class MatchNoneDiag : public MatchResultDiag {
/// \c MatchResultDiag.
class MatchNoteDiag : public FileCheckDiag {
private:
- MatchResultDiag *MRD;
+ const MatchResultDiag *MRD;
public:
MatchNoteDiag(FileCheckDiagKind Kind) : FileCheckDiag(Kind), MRD(nullptr) {}
@@ -316,7 +316,7 @@ class MatchNoteDiag : public FileCheckDiag {
/// Get the note's associated \c MatchResultDiag.
const MatchResultDiag &getMatchResultDiag() const override { return *MRD; }
/// Set the note's associated \c MatchResultDiag.
- void setMatchResultDiag(MatchResultDiag *MRDNew) {
+ void setMatchResultDiag(const MatchResultDiag *MRDNew) {
assert(!MRD && "expected setMatchResultDiag to be called only once");
MRD = MRDNew;
}
diff --git a/llvm/test/FileCheck/dump-input/annotations.txt b/llvm/test/FileCheck/dump-input/annotations.txt
index f928f3c3eaada..b8a92d090f77b 100644
--- a/llvm/test/FileCheck/dump-input/annotations.txt
+++ b/llvm/test/FileCheck/dump-input/annotations.txt
@@ -132,12 +132,12 @@
; CHK:<<<<<<
; CHK-NEXT: 1: hello
; CHK-V-NEXT:check:1 ^~~~~
-; CHK-NEXT:check:2'0 X error: no match found
+; CHK-NEXT:check:2'0 { search range start (exclusive)
+; CHK-NEXT:check:2'1 error: no match found
; CHK-NEXT: 2: again
-; CHK-NEXT:check:2'0 ~~~~~~
; CHK-NEXT: 3: whirled
-; CHK-NEXT:check:2'0 ~~~~~~~~
-; CHK-NEXT:check:2'1 ? possible intended match
+; CHK-NEXT:check:2'2 ? possible intended match
+; CHK-NEXT:check:2'3 } search range end (exclusive)
; CHK-NEXT:>>>>>>
; CHK-NOT:{{.}}
@@ -166,25 +166,27 @@
; CNT-V-NEXT:count:1'0 ^~~~
; CNT-V-NEXT: 2: repete
; CNT-V-NEXT:count:1'1 ^~~~
-; CNT-V-NEXT:count:1'2 X error: no match found
+; CNT-V-NEXT:count:1'2 { search range start (exclusive)
+; CNT-V-NEXT:count:1'3 error: no match found
; CNT-V-NEXT: 3: repeat
-; CNT-V-NEXT:count:1'2 ~~~~~~~
-; CNT-V-NEXT:count:1'3 ? possible intended match
+; CNT-V-NEXT:count:1'4 ? possible intended match
+; CNT-V-NEXT:count:1'5 } search range end (exclusive)
; CNT-V-NEXT:>>>>>>
; CNT-V-NOT:{{.}}
; CNT-Q:<<<<<<
; CNT-Q-NEXT: 1: pete
; CNT-Q-NEXT: 2: repete
-; CNT-Q-NEXT:count:1'0 X error: no match found
+; CNT-Q-NEXT:count:1'0 { search range start (exclusive)
+; CNT-Q-NEXT:count:1'1 error: no match found
; CNT-Q-NEXT: 3: repeat
-; CNT-Q-NEXT:count:1'0 ~~~~~~~
-; CNT-Q-NEXT:count:1'1 ? possible intended match
+; CNT-Q-NEXT:count:1'2 ? possible intended match
+; CNT-Q-NEXT:count:1'3 } search range end (exclusive)
; CNT-Q-NEXT:>>>>>>
; CNT-Q-NOT:{{.}}
;--------------------------------------------------
-; CHECK-NEXT (also: EOF search-range, wrong-line match)
+; CHECK-NEXT (also: EOF search-range, single-char search range, wrong-line match)
;--------------------------------------------------
; Good match and no match.
@@ -209,7 +211,8 @@
; NXT-V-NEXT:check:1 ^~~~~
; NXT-NEXT: 2: again
; NXT-V-NEXT:next:2 ^~~~~
-; NXT-NEXT:next:3 X error: no match found
+; NXT-NEXT:next:3'0 { } search range (exclusive bounds)
+; NXT-NEXT:next:3'1 error: no match found
; NXT-NEXT:>>>>>>
; NXT-NOT:{{.}}
@@ -231,15 +234,16 @@
; NXT2-V-NEXT:check:1 ^~~~~
; NXT2-NEXT: 2: again
; NXT2-V-NEXT:next:2 ^~~~~
+; NXT2-NEXT:next:3'0 { search range start (exclusive)
; NXT2-NEXT: 3: yonder
; NXT2-NEXT: 4: world
-; NXT2-NEXT:next:3 !~~~~ error: match on wrong line
+; NXT2-NEXT:next:3'1 !~~~~ error: match on wrong line
+; NXT2-NEXT:next:3'2 } search range end (exclusive)
; NXT2-NEXT:>>>>>>
; NXT2-NOT:{{.}}
;--------------------------------------------------
-; CHECK-SAME (also: multiple annotations per line, single-char search range,
-; wrong-line match)
+; CHECK-SAME (also: multiple annotations per line, wrong-line match)
;--------------------------------------------------
; Good match and no match.
@@ -262,7 +266,8 @@
; SAM-NEXT: 1: hello world!
; SAM-V-NEXT:check:1 ^~~~~
; SAM-V-NEXT:same:2 ^~~~~
-; SAM-NEXT:same:3 X~ error: no match found
+; SAM-NEXT:same:3'0 { } search range (exclusive bounds)
+; SAM-NEXT:same:3'1 error: no match found
; SAM-NEXT:>>>>>>
; SAM-NOT:{{.}}
@@ -282,13 +287,15 @@
; SAM2-NEXT: 1: hello world!
; SAM2-V-NEXT:check:1 ^~~~~
; SAM2-V-NEXT:same:2 ^~~~~
+; SAM2-NEXT:same:3'0 { search range start (exclusive)
; SAM2-NEXT: 2: again
-; SAM2-NEXT:same:3 !~~~~ error: match on wrong line
+; SAM2-NEXT:same:3'1 !~~~~ error: match on wrong line
+; SAM2-NEXT:same:3'2 } search range end (exclusive)
; SAM2-NEXT:>>>>>>
; SAM2-NOT:{{.}}
;--------------------------------------------------
-; CHECK-EMPTY (also: search range ends at label, single-char match, wrong-line
+; CHECK-EMPTY (also: search range ends at label, empty match range, wrong-line
; match)
;--------------------------------------------------
@@ -322,12 +329,12 @@
; EMP-V-NEXT:check:1 ^~~~~
; EMP-NEXT: 2:
; EMP-V-NEXT:empty:2 ^
-; EMP-NEXT:empty:3 X error: no match found
+; EMP-NEXT:empty:3'0 { search range start (exclusive)
+; EMP-NEXT:empty:3'1 error: no match found
; EMP-NEXT: 3: world
-; EMP-NEXT:empty:3 ~~~~~~
; EMP-NEXT: 4: label
; EMP-V-NEXT:label:4 ^~~~~
-; EMP-NEXT:empty:3 ~~~~~
+; EMP-NEXT:empty:3'2 } search range end (exclusive)
; EMP-NEXT:>>>>>>
; EMP-NOT:{{.}}
@@ -347,12 +354,24 @@
; Verbose diagnostics are suppressed but not errors.
; EMP2:{{.*}}error:{{.*}}
+; TODO: The search range of CHECK-EMPTY logically ends at the last character of
+; the file, as show below. However, it can actually match the empty string
+; immediately after its search range, as shown below. That is, -dump-input
+; seems to be doing the right thing: it makes no sense to show the search range
+; including a non-existent character. If it's worth the effort to change
+; anything here, then CHECK-EMPTY should probably report any match past the end
+; of the file as a failure to match at all. That would also include cases that
+; are currently successful matches, but that's a strange enough case that it
+; probably wouldn't be backward-incompatible for real test suites.
+
; EMP2:<<<<<<
; EMP2-NEXT: 1: hello
; EMP2-V-NEXT:check:1 ^~~~~
+; EMP2-NEXT:empty:2'0 { search range start (exclusive)
; EMP2-NEXT: 2: world
+; EMP2-NEXT:empty:2'2 } search range end (exclusive)
; EMP2-NEXT: 3:
-; EMP2-NEXT:empty:2 ! error: match on wrong line
+; EMP2-NEXT:empty:2'1 ! error: match on wrong line
; EMP2-NEXT:>>>>>>
; EMP2-NOT:{{.}}
@@ -379,12 +398,13 @@
; NOT:<<<<<<
; NOT-NEXT: 1: hello
-; NOT-VV-NEXT:not:1 X~~~~~
+; NOT-VV-NEXT:not:1'0 { search range start (exclusive)
+; NOT-NEXT:not:2'0 { search range start (exclusive)
; NOT-NEXT: 2: world
-; NOT-VV-NEXT:not:1 ~~~~~~
-; NOT-NEXT:not:2 !~~~~ error: no match expected
+; NOT-NEXT:not:2'1 !~~~~ error: no match expected
; NOT-NEXT: 3: again
-; NOT-VV-NEXT:not:1 ~~~~~~
+; NOT-VV-NEXT:not:1'1 } search range end (exclusive)
+; NOT-NEXT:not:2'2 } search range end (exclusive)
; NOT-VV-NEXT: 4:
; NOT-VV-NEXT:eof:2 ^
; NOT-NEXT:>>>>>>
@@ -404,13 +424,14 @@
; NOT2:<<<<<<
; NOT2-NEXT: 1: hello
-; NOT2-VV-NEXT:not:1 X~~~~~
+; NOT2-VV-NEXT:not:1'0 { search range start (exclusive)
+; NOT2-NEXT:not:2'0 { search range start (exclusive)
; NOT2-NEXT: 2: world
-; NOT2-VV-NEXT:not:1 ~~~~~~
-; NOT2-NEXT:not:2 !~~~~ error: no match expected
+; NOT2-NEXT:not:2'1 !~~~~ error: no match expected
; NOT2-NEXT: 3: again
; NOT2-V-NEXT:check:3 ^~~
-; NOT2-VV-NEXT:not:1 ~~
+; NOT2-VV-NEXT:not:1'1 } search range end (exclusive)
+; NOT2-NEXT:not:2'2 } search range end (exclusive)
; NOT2-NEXT:>>>>>>
; NOT2-NOT:{{.}}
@@ -440,14 +461,15 @@
; DAG-VV:<<<<<<
; DAG-VV-NEXT: 1: abc
; DAG-VV-NEXT:dag:2 ^~~
-; DAG-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
+; DAG-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
; DAG-VV-NEXT: 2: def
; DAG-VV-NEXT:dag:1 ^~~
-; DAG-VV-NEXT:dag:4'0 !~~ discard: overlaps earlier match
-; DAG-VV-NEXT:dag:4'1 X error: no match found
+; DAG-VV-NEXT:dag:4'0 !~~ discard: overlaps earlier match
+; DAG-VV-NEXT:dag:4'1 { search range start (exclusive)
+; DAG-VV-NEXT:dag:4'2 error: no match found
; DAG-VV-NEXT: 3: abc
; DAG-VV-NEXT:dag:3'1 ^~~
-; DAG-VV-NEXT:dag:4'1 ~~~~
+; DAG-VV-NEXT:dag:4'3 } search range end (exclusive)
; DAG-VV-NEXT:>>>>>>
; DAG-VV-NOT:{{.}}
@@ -456,19 +478,21 @@
; DAG-VQ-NEXT:dag:2 ^~~
; DAG-VQ-NEXT: 2: def
; DAG-VQ-NEXT:dag:1 ^~~
-; DAG-VQ-NEXT:dag:4 X error: no match found
+; DAG-VQ-NEXT:dag:4'0 { search range start (exclusive)
+; DAG-VQ-NEXT:dag:4'1 error: no match found
; DAG-VQ-NEXT: 3: abc
; DAG-VQ-NEXT:dag:3 ^~~
-; DAG-VQ-NEXT:dag:4 ~~~~
+; DAG-VQ-NEXT:dag:4'2 } search range end (exclusive)
; DAG-VQ-NEXT:>>>>>>
; DAG-VQ-NOT:{{.}}
; DAG-Q:<<<<<<
; DAG-Q-NEXT: 1: abc
; DAG-Q-NEXT: 2: def
-; DAG-Q-NEXT:dag:4 X error: no match found
+; DAG-Q-NEXT:dag:4'0 { search range start (exclusive)
+; DAG-Q-NEXT:dag:4'1 error: no match found
; DAG-Q-NEXT: 3: abc
-; DAG-Q-NEXT:dag:4 ~~~~
+; DAG-Q-NEXT:dag:4'2 } search range end (exclusive)
; DAG-Q-NEXT:>>>>>>
; DAG-Q-NOT:{{.}}
@@ -497,13 +521,14 @@
; DAG1L-VV-NEXT: 1: abc def abc def
; DAG1L-VV-NEXT:dag:1 ^~~
; DAG1L-VV-NEXT:dag:2 ^~
-; DAG1L-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:3'0 !~~ discard: overlaps earlier match
; DAG1L-VV-NEXT:dag:3'1 ^~~
-; DAG1L-VV-NEXT:dag:4'0 !~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:4'0 !~ discard: overlaps earlier match
; DAG1L-VV-NEXT:dag:4'1 ^~
-; DAG1L-VV-NEXT:dag:5'0 !~~ discard: overlaps earlier match
-; DAG1L-VV-NEXT:dag:5'1 !~~ discard: overlaps earlier match
-; DAG1L-VV-NEXT:dag:5'2 X~ error: no match found
+; DAG1L-VV-NEXT:dag:5'0 !~~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:5'1 !~~ discard: overlaps earlier match
+; DAG1L-VV-NEXT:dag:5'2 { } search range (exclusive bounds)
+; DAG1L-VV-NEXT:dag:5'3 error: no match found
; DAG1L-VV-NEXT:>>>>>>
; DAG1L-VV-NOT:{{.}}
@@ -513,13 +538,15 @@
; DAG1L-VQ-NEXT:dag:2 ^~
; DAG1L-VQ-NEXT:dag:3 ^~~
; DAG1L-VQ-NEXT:dag:4 ^~
-; DAG1L-VQ-NEXT:dag:5 X~ error: no match found
+; DAG1L-VQ-NEXT:dag:5'0 { } search range (exclusive bounds)
+; DAG1L-VQ-NEXT:dag:5'1 error: no match found
; DAG1L-VQ-NEXT:>>>>>>
; DAG1L-VQ-NOT:{{.}}
; DAG1L-Q:<<<<<<
; DAG1L-Q-NEXT: 1: abc def abc def
-; DAG1L-Q-NEXT:dag:5 X~ error: no match found
+; DAG1L-Q-NEXT:dag:5'0 { } search range (exclusive bounds)
+; DAG1L-Q-NEXT:dag:5'1 error: no match found
; DAG1L-Q-NEXT:>>>>>>
; DAG1L-Q-NOT:{{.}}
@@ -585,31 +612,34 @@
; LAB-V-NEXT: 2: labelA
; LAB-V-NEXT:label:2'0 ^~~~~~
; LAB-V-NEXT:label:2'1 ^~~~~~
-; LAB-V-NEXT:check:3 X error: no match found
+; LAB-V-NEXT:check:3'0 { search range start (exclusive)
+; LAB-V-NEXT:check:3'1 error: no match found
; LAB-V-NEXT: 3: textA
-; LAB-V-NEXT:check:3 ~~~~~~
; LAB-V-NEXT: 4: labelB
; LAB-V-NEXT:label:4 ^~~~~~
-; LAB-V-NEXT:check:3 ~~~~~~
+; LAB-V-NEXT:check:3'2 } search range end (exclusive)
; LAB-V-NEXT: 5: textB
; LAB-V-NEXT: 6: labelC
; LAB-V-NEXT:label:6'0 ^~~~~~
; LAB-V-NEXT:check:5 ^~~~~~
-; LAB-V-NEXT:label:6'1 X error: no match found
-; LAB-VV-NEXT:not:7 X
+; LAB-V-NEXT:label:6'1 {} search range (exclusive bounds)
+; LAB-V-NEXT:label:6'2 error: no match found
+; LAB-VV-NEXT:not:7'0 { search range start (exclusive)
; LAB-V-NEXT: 7: textC
-; LAB-VV-NEXT:not:7 ~~~~~~
+; LAB-VV-NEXT:not:7'1 } search range end (exclusive)
; LAB-V-NEXT: 8: labelD
; LAB-V-NEXT:label:8'0 ^~~~~~
; LAB-V-NEXT:label:8'1 ^~~~~~
+; LAB-V-NEXT:not:9'0 { search range start (exclusive)
; LAB-V-NEXT: 9: textD
-; LAB-V-NEXT:not:9 !~~~~ error: no match expected
+; LAB-V-NEXT:not:9'1 !~~~~ error: no match expected
+; LAB-V-NEXT:not:9'2 } search range end (exclusive)
; LAB-V-NEXT: 10: labelE
; LAB-V-NEXT:label:10'0 ^~~~~~
; LAB-V-NEXT:label:10'1 ^~~~~~
-; LAB-VV-NEXT:not:11 X
+; LAB-VV-NEXT:not:11'0 { search range start (exclusive)
; LAB-V-NEXT: 11: textE
-; LAB-VV-NEXT:not:11 ~~~~~~
+; LAB-VV-NEXT:not:11'1 } search range end (exclusive)
; LAB-V-NEXT: 12: labelF
; LAB-V-NEXT:label:12'0 ^~~~~~
; LAB-V-NEXT:label:12'1 ^~~~~~
@@ -619,18 +649,21 @@
; LAB-Q:<<<<<<
; LAB-Q-NEXT: 1: text
; LAB-Q-NEXT: 2: labelA
-; LAB-Q-NEXT:check:3 X error: no match found
+; LAB-Q-NEXT:check:3'0 { search range start (exclusive)
+; LAB-Q-NEXT:check:3'1 error: no match found
; LAB-Q-NEXT: 3: textA
-; LAB-Q-NEXT:check:3 ~~~~~~
; LAB-Q-NEXT: 4: labelB
-; LAB-Q-NEXT:check:3 ~~~~~~
+; LAB-Q-NEXT:check:3'2 } search range end (exclusive)
; LAB-Q-NEXT: 5: textB
; LAB-Q-NEXT: 6: labelC
-; LAB-Q-NEXT:label:6 X error: no match found
+; LAB-Q-NEXT:label:6'0 {} search range (exclusive bounds)
+; LAB-Q-NEXT:label:6'1 error: no match found
; LAB-Q-NEXT: 7: textC
; LAB-Q-NEXT: 8: labelD
+; LAB-Q-NEXT:not:9'0 { search range start (exclusive)
; LAB-Q-NEXT: 9: textD
-; LAB-Q-NEXT:not:9 !~~~~ error: no match expected
+; LAB-Q-NEXT:not:9'1 !~~~~ error: no match expected
+; LAB-Q-NEXT:not:9'2 } search range end (exclusive)
; LAB-Q-NEXT: 10: labelE
; LAB-Q-NEXT: 11: textE
; LAB-Q-NEXT: 12: labelF
@@ -668,17 +701,18 @@
; IMPNOT-VV:<<<<<<
; IMPNOT-VV-NEXT: 1: hello world again!
; IMPNOT-VV-NEXT:check:1 ^~~
-; IMPNOT-VV-NEXT:not:imp1'0 X
-; IMPNOT-VV-NEXT:not:imp2'0 X
-; IMPNOT-VV-NEXT:not:imp3'0 X
+; IMPNOT-VV-NEXT:not:imp1'0 {} search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp2'0 {} search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp3'0 {} search range (exclusive bounds)
; IMPNOT-VV-NEXT:check:2 ^~~
-; IMPNOT-VV-NEXT:not:imp1'1 X~~
-; IMPNOT-VV-NEXT:not:imp2'1 X~~
-; IMPNOT-VV-NEXT:not:imp3'1 X~~
+; IMPNOT-VV-NEXT:not:imp1'1 { } search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp2'1 { } search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp3'1 { } search range (exclusive bounds)
; IMPNOT-VV-NEXT:check:3 ^
-; IMPNOT-VV-NEXT:not:imp1'2 X~~~~~~~
-; IMPNOT-VV-NEXT:not:imp2'2 X~~~~~~~
-; IMPNOT-VV-NEXT:not:imp3'2 !~~~~ error: no match expected
+; IMPNOT-VV-NEXT:not:imp1'2 { } search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp2'2 { } search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp3'2 { } search range (exclusive bounds)
+; IMPNOT-VV-NEXT:not:imp3'3 !~~~~ error: no match expected
; IMPNOT-VV-NEXT:>>>>>>
; IMPNOT-VV-NOT:{{.}}
@@ -687,13 +721,15 @@
; IMPNOT-VQ-NEXT:check:1 ^~~
; IMPNOT-VQ-NEXT:check:2 ^~~
; IMPNOT-VQ-NEXT:check:3 ^
-; IMPNOT-VQ-NEXT:not:imp3 !~~~~ error: no match expected
+; IMPNOT-VQ-NEXT:not:imp3'0 { } search range (exclusive bounds)
+; IMPNOT-VQ-NEXT:not:imp3'1 !~~~~ error: no match expected
; IMPNOT-VQ-NEXT:>>>>>>
; IMPNOT-VQ-NOT:{{.}}
; IMPNOT-Q:<<<<<<
; IMPNOT-Q-NEXT: 1: hello world again!
-; IMPNOT-Q-NEXT:not:imp3 !~~~~ error: no match expected
+; IMPNOT-Q-NEXT:not:imp3'0 { } search range (exclusive bounds)
+; IMPNOT-Q-NEXT:not:imp3'1 !~~~~ error: no match expected
; IMPNOT-Q-NEXT:>>>>>>
; IMPNOT-Q-NOT:{{.}}
@@ -723,15 +759,16 @@
; SUBST-POS:<<<<<<
; SUBST-POS-NEXT: 1: def-match1 def-match2
; SUBST-POS-V-NEXT:check:1'0 ^~~~~~~~~~~~~~~~~~~~~
-; SUBST-POS-V-NEXT:check:1'1 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-POS-V-NEXT:check:1'2 with "DEF_MATCH2" equal to "def-match2"
-; SUBST-POS-NEXT:check:2'0 X error: match failed for invalid pattern
-; SUBST-POS-NEXT:check:2'1 undefined variable: UNDEF
-; SUBST-POS-NEXT:check:2'2 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-POS-NEXT:check:2'3 with "DEF_NOMATCH" equal to "foobar"
+; SUBST-POS-V-NEXT:check:1'1 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-POS-V-NEXT:check:1'2 with "DEF_MATCH2" equal to "def-match2"
+; SUBST-POS-NEXT:check:2'0 { search range start (exclusive)
+; SUBST-POS-NEXT:check:2'1 error: match failed for invalid pattern
+; SUBST-POS-NEXT:check:2'2 undefined variable: UNDEF
+; SUBST-POS-NEXT:check:2'3 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-POS-NEXT:check:2'4 with "DEF_NOMATCH" equal to "foobar"
; SUBST-POS-NEXT: 2: def-match1 def-nomatch
-; SUBST-POS-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~
-; SUBST-POS-NEXT:check:2'4 ? possible intended match
+; SUBST-POS-NEXT:check:2'5 ? possible intended match
+; SUBST-POS-NEXT:check:2'6 } search range end (exclusive)
; SUBST-POS-NEXT:>>>>>>
;--------------------------------------------------
@@ -761,15 +798,18 @@
; SUBST-NEG:<<<<<<
; SUBST-NEG-NEXT: 1: def-match1 def-nomatch
-; SUBST-NEG-NEXT:not:1'0 X~~~~~~~~~~~~~~~~~~~~~~ error: match failed for invalid pattern
-; SUBST-NEG-NEXT:not:1'1 undefined variable: UNDEF
-; SUBST-NEG-NEXT:not:1'2 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-NEG-NEXT:not:1'3 with "DEF_NOMATCH" equal to "foobar"
+; SUBST-NEG-NEXT:not:1'0 { search range start (exclusive)
+; SUBST-NEG-NEXT:not:1'1 error: match failed for invalid pattern
+; SUBST-NEG-NEXT:not:1'2 undefined variable: UNDEF
+; SUBST-NEG-NEXT:not:1'3 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-NEG-NEXT:not:1'4 with "DEF_NOMATCH" equal to "foobar"
+; SUBST-NEG-NEXT:not:2'0 { search range start (exclusive)
; SUBST-NEG-NEXT: 2: def-match1 def-match2
-; SUBST-NEG-NEXT:not:1'0 ~~~~~~~~~~~~~~~~~~~~~~
-; SUBST-NEG-NEXT:not:2'0 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
-; SUBST-NEG-NEXT:not:2'1 with "DEF_MATCH1" equal to "def-match1"
-; SUBST-NEG-NEXT:not:2'2 with "DEF_MATCH2" equal to "def-match2"
+; SUBST-NEG-NEXT:not:1'5 } search range end (exclusive)
+; SUBST-NEG-NEXT:not:2'1 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
+; SUBST-NEG-NEXT:not:2'2 with "DEF_MATCH1" equal to "def-match1"
+; SUBST-NEG-NEXT:not:2'3 with "DEF_MATCH2" equal to "def-match2"
+; SUBST-NEG-NEXT:not:2'4 } search range end (exclusive)
; SUBST-NEG-NEXT: 3: END
; SUBST-NEG-V-NEXT:check:3 ^~~
; SUBST-NEG-NEXT:>>>>>>
@@ -808,23 +848,25 @@
; CAPTURE-NEG:<<<<<<
; CAPTURE-NEG-NEXT: 1: strvar: foo
; CAPTURE-NEG-V-NEXT:check:1'0 ^~~~~~~~~~~
- CAPTURE-NEG-V-NEXT:check:1'1 ^~~ captured var "STRVAR"
+ CAPTURE-NEG-V-NEXT:check:1'1 ^~~ captured var "STRVAR"
; CAPTURE-NEG-NEXT: 2: numvar no expr: 51
; CAPTURE-NEG-V-NEXT:check:2'0 ^~~~~~~~~~~~~~~~~~
-; CAPTURE-NEG-V-NEXT:check:2'1 ^~ captured var "NUMVAR_NO_EXPR"
+; CAPTURE-NEG-V-NEXT:check:2'1 ^~ captured var "NUMVAR_NO_EXPR"
; CAPTURE-NEG-NEXT: 3: numvar expr: -49
; CAPTURE-NEG-V-NEXT:check:3'0 ^~~~~~~~~~~~~~~~
-; CAPTURE-NEG-V-NEXT:check:3'1 with "%d,NUMVAR_EXPR:2-NUMVAR_NO_EXPR" equal to "-49"
-; CAPTURE-NEG-V-NEXT:check:3'2 ^~~ captured var "NUMVAR_EXPR"
+; CAPTURE-NEG-V-NEXT:check:3'1 with "%d,NUMVAR_EXPR:2-NUMVAR_NO_EXPR" equal to "-49"
+; CAPTURE-NEG-V-NEXT:check:3'2 ^~~ captured var "NUMVAR_EXPR"
; CAPTURE-NEG-NEXT: 4: many: foo 100 8 bar
; CAPTURE-NEG-V-NEXT:check:4'0 ^~~~~~~~~~~~~~~~~~~
-; CAPTURE-NEG-V-NEXT:check:4'1 ^~~ captured var "VAR1"
-; CAPTURE-NEG-V-NEXT:check:4'2 ^~~ captured var "VAR3"
-; CAPTURE-NEG-V-NEXT:check:4'3 ^ captured var "VAR2"
-; CAPTURE-NEG-V-NEXT:check:4'4 ^~~ captured var "VAR4"
+; CAPTURE-NEG-V-NEXT:check:4'1 ^~~ captured var "VAR1"
+; CAPTURE-NEG-V-NEXT:check:4'2 ^~~ captured var "VAR3"
+; CAPTURE-NEG-V-NEXT:check:4'3 ^ captured var "VAR2"
+; CAPTURE-NEG-V-NEXT:check:4'4 ^~~ captured var "VAR4"
+; CAPTURE-NEG-NEXT:not:5'0 { search range start (exclusive)
; CAPTURE-NEG-NEXT: 5: var in neg match: foo
-; CAPTURE-NEG-NEXT:not:5'0 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
-; CAPTURE-NEG-NEXT:not:5'1 !~~ captured var "VAR"
+; CAPTURE-NEG-NEXT:not:5'1 !~~~~~~~~~~~~~~~~~~~~ error: no match expected
+; CAPTURE-NEG-NEXT:not:5'2 !~~ captured var "VAR"
+; CAPTURE-NEG-NEXT:not:5'3 } search range end (exclusive)
; CAPTURE-NEG-NEXT: 6: END
; CAPTURE-NEG-V-NEXT:check:6 ^~~
; CAPTURE-NEG-NEXT:>>>>>>
@@ -858,17 +900,13 @@
; Verbose diagnostics are suppressed but not errors.
; SUBST_NEXT:{{.*}}error:{{.*}}
-; SUBST_NEXT-V:<<<<<<
-; SUBST_NEXT-V-NEXT: 1: pre var
+; SUBST_NEXT:<<<<<<
+; SUBST_NEXT-NEXT: 1: pre var
; SUBST_NEXT-V-NEXT:check:1 ^~~
-; SUBST_NEXT-V-NEXT:next:2'0 !~~ error: match on wrong line
-; SUBST_NEXT-V-NEXT:next:2'1 with "VAR" equal to "var"
-; SUBST_NEXT-V-NEXT:>>>>>>
-
-; SUBST_NEXT-Q:<<<<<<
-; SUBST_NEXT-Q-NEXT: 1: pre var
-; SUBST_NEXT-Q-NEXT:next:2 !~~ error: match on wrong line
-; SUBST_NEXT-Q-NEXT:>>>>>>
+; SUBST_NEXT-NEXT:next:2'0 { } search range (exclusive bounds)
+; SUBST_NEXT-NEXT:next:2'1 !~~ error: match on wrong line
+; SUBST_NEXT-V-NEXT:next:2'2 with "VAR" equal to "var"
+; SUBST_NEXT-NEXT:>>>>>>
;- - - - - - - - - - - - - - - - - - - - - - - - -
; CHECK-SAME.
@@ -893,15 +931,19 @@
; SUBST_SAME-V:<<<<<<
; SUBST_SAME-V-NEXT: 1: pre
; SUBST_SAME-V-NEXT:check:1 ^~~
+; SUBST_SAME-V-NEXT:same:2'0 { search range start (exclusive)
; SUBST_SAME-V-NEXT: 2: var
-; SUBST_SAME-V-NEXT:same:2'0 !~~ error: match on wrong line
-; SUBST_SAME-V-NEXT:same:2'1 with "VAR" equal to "var"
+; SUBST_SAME-V-NEXT:same:2'1 !~~ error: match on wrong line
+; SUBST_SAME-V-NEXT:same:2'2 with "VAR" equal to "var"
+; SUBST_SAME-V-NEXT:same:2'3 } search range end (exclusive)
; SUBST_SAME-V-NEXT:>>>>>>
; SUBST_SAME-Q:<<<<<<
; SUBST_SAME-Q-NEXT: 1: pre
+; SUBST_SAME-Q-NEXT:same:2'0 { search range start (exclusive)
; SUBST_SAME-Q-NEXT: 2: var
-; SUBST_SAME-Q-NEXT:same:2 !~~ error: match on wrong line
+; SUBST_SAME-Q-NEXT:same:2'1 !~~ error: match on wrong line
+; SUBST_SAME-Q-NEXT:same:2'2 } search range end (exclusive)
; SUBST_SAME-Q-NEXT:>>>>>>
;- - - - - - - - - - - - - - - - - - - - - - - - -
@@ -926,11 +968,11 @@
; SUBST_DAG-VV:<<<<<<
; SUBST_DAG-VV-NEXT: 1: var
; SUBST_DAG-VV-NEXT:dag:1 ^~~
-; SUBST_DAG-VV-NEXT:dag:2'0 !~~ discard: overlaps earlier match
-; SUBST_DAG-VV-NEXT:dag:2'1 with "VAR" equal to "var"
+; SUBST_DAG-VV-NEXT:dag:2'0 !~~ discard: overlaps earlier match
+; SUBST_DAG-VV-NEXT:dag:2'1 with "VAR" equal to "var"
; SUBST_DAG-VV-NEXT: 2: var
; SUBST_DAG-VV-NEXT:dag:2'2 ^~~
-; SUBST_DAG-VV-NEXT:dag:2'3 with "VAR" equal to "var"
+; SUBST_DAG-VV-NEXT:dag:2'3 with "VAR" equal to "var"
; SUBST_DAG-VV-NEXT: 3: END
; SUBST_DAG-VV-NEXT:check:3 ^~~
; SUBST_DAG-VV-NEXT:>>>>>>
@@ -940,7 +982,7 @@
; SUBST_DAG-VQ-NEXT:dag:1 ^~~
; SUBST_DAG-VQ-NEXT: 2: var
; SUBST_DAG-VQ-NEXT:dag:2'0 ^~~
-; SUBST_DAG-VQ-NEXT:dag:2'1 with "VAR" equal to "var"
+; SUBST_DAG-VQ-NEXT:dag:2'1 with "VAR" equal to "var"
; SUBST_DAG-VQ-NEXT: 3: END
; SUBST_DAG-VQ-NEXT:check:3 ^~~
; SUBST_DAG-VQ-NEXT:>>>>>>
@@ -950,3 +992,212 @@
; SUBST_DAG-Q-NEXT: 2: var
; SUBST_DAG-Q-NEXT: 3: END
; SUBST_DAG-Q-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check multiline marker where start/end columns vary across lines.
+;--------------------------------------------------
+
+; RUN: echo '<start' > %t.in
+; RUN: echo '' >> %t.in
+; RUN: echo '1' >> %t.in
+; RUN: echo '12' >> %t.in
+; RUN: echo 'end>' >> %t.in
+
+; RUN: echo 'CHECK: start{{(.|[[:space:]])*}}end' > %t.chk
+
+; REDEFINE: %{pre} = MULTILINE-MARKER
+; RUN: %{run-vv}
+; RUN: %{run-v}
+; RUN: %{run}
+
+; MULTILINE-MARKER:<<<<<<
+; MULTILINE-MARKER-NEXT: 1: <start
+; MULTILINE-MARKER-V-NEXT:check:1 ^~~~~~
+; MULTILINE-MARKER-NEXT: 2:
+; MULTILINE-MARKER-V-NEXT:check:1 ~
+; MULTILINE-MARKER-NEXT: 3: 1
+; MULTILINE-MARKER-V-NEXT:check:1 ~~
+; MULTILINE-MARKER-NEXT: 4: 12
+; MULTILINE-MARKER-V-NEXT:check:1 ~~~
+; MULTILINE-MARKER-NEXT: 5: end>
+; MULTILINE-MARKER-V-NEXT:check:1 ~~~
+; MULTILINE-MARKER-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check empty and single-character match ranges.
+;--------------------------------------------------
+
+; RUN: echo '11' > %t.in
+
+; RUN: echo 'empty at bof: CHECK: {{0?}}' > %t.chk
+; RUN: echo 'single at bof: CHECK: {{1?}}' >> %t.chk
+; RUN: echo 'empty in middle: CHECK: {{0?}}' >> %t.chk
+; RUN: echo 'single in middle: CHECK: {{1?}}' >> %t.chk
+; RUN: echo 'single at eof: CHECK: {{[[:space:]]?}}' >> %t.chk
+; RUN: echo 'empty at eof: CHECK: {{0?}}' >> %t.chk
+
+; REDEFINE: %{pre} = EMPTY-SINGLE-MATCH
+; RUN: %{run-vv}
+; RUN: %{run-v}
+; RUN: %{run}
+
+; EMPTY-SINGLE-MATCH:<<<<<<
+; EMPTY-SINGLE-MATCH-NEXT: 1: 11
+; EMPTY-SINGLE-MATCH-V-NEXT:check:1 ^
+; EMPTY-SINGLE-MATCH-V-NEXT:check:2 ^
+; EMPTY-SINGLE-MATCH-V-NEXT:check:3 ^
+; EMPTY-SINGLE-MATCH-V-NEXT:check:4 ^
+; EMPTY-SINGLE-MATCH-V-NEXT:check:5 ^
+; EMPTY-SINGLE-MATCH-V-NEXT: 2:
+; EMPTY-SINGLE-MATCH-V-NEXT:check:6 ^
+; EMPTY-SINGLE-MATCH-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check search range for empty file and thus empty search range at start/end of
+; file.
+;--------------------------------------------------
+
+; RUN: echo 'CHECK-NOT: foo' > %t.chk
+; REDEFINE: %{opts} = -input-file=/dev/null -allow-empty
+
+; REDEFINE: %{pre} = NEG-SEARCH-EMPTY-FILE
+; RUN: %{run-vv}
+; RUN: %{run-v}
+; RUN: %{run}
+
+; NEG-SEARCH-EMPTY-FILE:<<<<<<
+; NEG-SEARCH-EMPTY-FILE-VV-NEXT: 1:
+; NEG-SEARCH-EMPTY-FILE-VV-NEXT:eof:1 ^
+; NEG-SEARCH-EMPTY-FILE-VV-NEXT:not:1 {} search range (exclusive bounds)
+; NEG-SEARCH-EMPTY-FILE-NEXT:>>>>>>
+
+; RUN: echo 'CHECK: foo' > %t.chk
+
+; REDEFINE: %{pre} = POS-SEARCH-EMPTY-FILE
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+
+; Verbose diagnostics are suppressed but not errors.
+; POS-SEARCH-EMPTY-FILE:{{.*}}error:{{.*}}
+
+; POS-SEARCH-EMPTY-FILE:<<<<<<
+; POS-SEARCH-EMPTY-FILE-NEXT: 1:
+; POS-SEARCH-EMPTY-FILE-NEXT:check:1'0 {} search range (exclusive bounds)
+; POS-SEARCH-EMPTY-FILE-NEXT:check:1'1 error: no match found
+; POS-SEARCH-EMPTY-FILE-NEXT:>>>>>>
+
+; REDEFINE: %{opts} =
+
+;--------------------------------------------------
+; Check non-empty search range at start/end of file.
+;--------------------------------------------------
+
+; RUN: echo 'one line' > %t.in
+
+; RUN: echo 'CHECK-NOT: foo' > %t.chk
+
+; REDEFINE: %{pre} = SEARCH-BOF-EOF-ONE-LINE
+; RUN: %{run-vv}
+; RUN: %{run-v}
+; RUN: %{run}
+
+; SEARCH-BOF-EOF-ONE-LINE:<<<<<<
+; SEARCH-BOF-EOF-ONE-LINE-NEXT: 1: one line
+; SEARCH-BOF-EOF-ONE-LINE-VV-NEXT:not:1 { } search range (exclusive bounds)
+; SEARCH-BOF-EOF-ONE-LINE-VV-NEXT: 2:
+; SEARCH-BOF-EOF-ONE-LINE-VV-NEXT:eof:1 ^
+; SEARCH-BOF-EOF-ONE-LINE-NEXT:>>>>>>
+
+; RUN: echo 'line 1' > %t.in
+; RUN: echo 'line 2' >> %t.in
+
+; RUN: echo 'CHECK: foo' > %t.chk
+
+; REDEFINE: %{pre} = SEARCH-BOF-EOF-MULTI-LINE
+; RUN: not %{run-vv}
+; RUN: not %{run-v}
+; RUN: not %{run}
+
+; Verbose diagnostics are suppressed but not errors.
+; SEARCH-BOF-EOF-MULTI-LINE:{{.*}}error:{{.*}}
+
+; SEARCH-BOF-EOF-MULTI-LINE:<<<<<<
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT: 1: line 1
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'0 { search range start (exclusive)
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'1 error: no match found
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT: 2: line 2
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'2 } search range end (exclusive)
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT:>>>>>>
+
+;--------------------------------------------------
+; Check search ranges at line boundaries but not file boundaries. Also check
+; empty search ranges (for non-empty file) and one-character search ranges.
+;--------------------------------------------------
+
+; RUN: echo 'start' > %t.in
+; RUN: echo 'empty' >> %t.in
+; RUN: echo 'next' >> %t.in
+; RUN: echo 'one char' >> %t.in
+; RUN: echo 'next' >> %t.in
+; RUN: echo 'one line' >> %t.in
+; RUN: echo 'next' >> %t.in
+; RUN: echo 'multi' >> %t.in
+; RUN: echo 'line' >> %t.in
+; RUN: echo 'next' >> %t.in
+; RUN: echo 'off by one' >> %t.in
+; RUN: echo ' end' >> %t.in
+
+; RUN: echo ' 1: CHECK: start{{[[:space:]]}}' > %t.chk
+; RUN: echo ' 2: CHECK-NOT: foo' >> %t.chk
+; RUN: echo ' 3: CHECK: empty' >> %t.chk
+; RUN: echo ' 4: CHECK-NOT: foo' >> %t.chk
+; RUN: echo ' 5: CHECK: {{[[:space:]]}}next{{[[:space:]]}}' >> %t.chk
+; RUN: echo ' 6: CHECK-NOT: foo' >> %t.chk
+; RUN: echo ' 7: CHECK: ne char' >> %t.chk
+; RUN: echo ' 8: CHECK-NOT: foo' >> %t.chk
+; RUN: echo ' 9: CHECK: next{{[[:space:]]}}' >> %t.chk
+; RUN: echo '10: CHECK-NOT: foo' >> %t.chk
+; RUN: echo '11: CHECK: next{{[[:space:]]}}' >> %t.chk
+; RUN: echo '12: CHECK-NOT: foo' >> %t.chk
+; RUN: echo '13: CHECK: next' >> %t.chk
+; RUN: echo '14: CHECK-NOT: foo' >> %t.chk
+; RUN: echo '15: CHECK: end' >> %t.chk
+
+; REDEFINE: %{pre} = SEARCH-LINE-BOUNDS
+; RUN: %{run-vv}
+; RUN: %{run-v}
+; RUN: %{run}
+
+; SEARCH-LINE-BOUNDS:<<<<<<
+; SEARCH-LINE-BOUNDS-NEXT: 1: start
+; SEARCH-LINE-BOUNDS-V-NEXT:check:1 ^~~~~~
+; SEARCH-LINE-BOUNDS-NEXT: 2: empty
+; SEARCH-LINE-BOUNDS-V-NEXT:check:3 ^~~~~
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:2 {} search range (exclusive bounds)
+; SEARCH-LINE-BOUNDS-V-NEXT:check:5 ^
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:4 {} search range (exclusive bounds)
+; SEARCH-LINE-BOUNDS-NEXT: 3: next
+; SEARCH-LINE-BOUNDS-V-NEXT:check:5 ~~~~~
+; SEARCH-LINE-BOUNDS-NEXT: 4: one char
+; SEARCH-LINE-BOUNDS-V-NEXT:check:7 ^~~~~~~
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:6 { } search range (exclusive bounds)
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:8 { } search range (exclusive bounds)
+; SEARCH-LINE-BOUNDS-NEXT: 5: next
+; SEARCH-LINE-BOUNDS-V-NEXT:check:9 ^~~~~
+; SEARCH-LINE-BOUNDS-NEXT: 6: one line
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:10 { } search range (exclusive bounds)
+; SEARCH-LINE-BOUNDS-NEXT: 7: next
+; SEARCH-LINE-BOUNDS-V-NEXT:check:11 ^~~~~
+; SEARCH-LINE-BOUNDS-NEXT: 8: multi
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:12'0 { search range start (exclusive)
+; SEARCH-LINE-BOUNDS-NEXT: 9: line
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:12'1 } search range end (exclusive)
+; SEARCH-LINE-BOUNDS-NEXT: 10: next
+; SEARCH-LINE-BOUNDS-V-NEXT:check:13 ^~~~
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:14'0 { search range start (exclusive)
+; SEARCH-LINE-BOUNDS-NEXT: 11: off by one
+; SEARCH-LINE-BOUNDS-NEXT: 12: end
+; SEARCH-LINE-BOUNDS-V-NEXT:check:15 ^~~
+; SEARCH-LINE-BOUNDS-VV-NEXT:not:14'1 } search range end (exclusive)
+; SEARCH-LINE-BOUNDS-NEXT:>>>>>>
diff --git a/llvm/test/FileCheck/dump-input/context.txt b/llvm/test/FileCheck/dump-input/context.txt
index 78092a909dbd8..8a567a5d567b2 100644
--- a/llvm/test/FileCheck/dump-input/context.txt
+++ b/llvm/test/FileCheck/dump-input/context.txt
@@ -52,111 +52,113 @@
; RUN: echo 'CHECK-LABEL: lab1' > %t.chk
; RUN: echo ' CHECK-NEXT: hello' >> %t.chk
; RUN: echo 'CHECK-LABEL: lab2' >> %t.chk
-; RUN: echo ' CHECK-NEXT: world' >> %t.chk
-
-; C0: <<<<<<
-; CS-NEXT: .
-; CS-NEXT: .
-; CS-NEXT: .
-; C5-NEXT: 1: foo8
-; C5-NEXT: 2: foo7
-; C5-NEXT: 3: foo6
-; C5-NEXT: 4: foo5
-; C4-NEXT: 5: foo4
-; C3-NEXT: 6: foo3
-; C2-NEXT: 7: foo2
-; C1-NEXT: 8: foo1
-; C0-NEXT: 9: lab1 hello
-; C0-NEXT: label:1'0 ^~~~
-; C0-NEXT: label:1'1 ^~~~
-; C0-NEXT: next:2 !~~~~ error: match on wrong line
-; C1-NEXT: 10: foo1
-; C2-NEXT: 11: foo2
-; C3-NEXT: 12: foo3
-; C4-NEXT: 13: foo4
-; C5-NEXT: 14: foo5
-; C6-NEXT: 15: foo6
-; C6-NEXT: 16: foo7
-; CM-NEXT: .
-; CM-NEXT: .
-; CM-NEXT: .
-; C6-NEXT: 17: foo7
-; C6-NEXT: 18: foo6
-; C5-NEXT: 19: foo5
-; C4-NEXT: 20: foo4
-; C3-NEXT: 21: foo3
-; C2-NEXT: 22: foo2
-; C1-NEXT: 23: foo1
-; C0-NEXT: 24: lab2 world
-; C0-NEXT: label:3 ^~~~
-; C0-NEXT: next:4 !~~~~ error: match on wrong line
-; C1-NEXT: 25: foo1
-; C2-NEXT: 26: foo2
-; C3-NEXT: 27: foo3
-; C4-NEXT: 28: foo4
-; C5-NEXT: 29: foo5
-; C6-NEXT: 30: foo6
-; C7-NEXT: 31: foo7
-; C7-NEXT: 32: foo8
-; C7-NEXT: 33: foo9
-; C7-NEXT: 34: foo0
-; CE-NEXT: .
-; CE-NEXT: .
-; CE-NEXT: .
-; C0-NEXT: >>>>>>
+
+; C0:<<<<<<
+; CS-NEXT: .
+; CS-NEXT: .
+; CS-NEXT: .
+; C5-NEXT: 1: foo8
+; C5-NEXT: 2: foo7
+; C5-NEXT: 3: foo6
+; C5-NEXT: 4: foo5
+; C4-NEXT: 5: foo4
+; C3-NEXT: 6: foo3
+; C2-NEXT: 7: foo2
+; C1-NEXT: 8: foo1
+; C0-NEXT: 9: lab1 hello
+; C0-NEXT:label:1'0 ^~~~
+; C0-NEXT:label:1'1 ^~~~
+; C0-NEXT:next:2'0 { search range start (exclusive)
+; C0-NEXT:next:2'1 !~~~~ error: match on wrong line
+; C1-NEXT: 10: foo1
+; C2-NEXT: 11: foo2
+; C3-NEXT: 12: foo3
+; C4-NEXT: 13: foo4
+; C5-NEXT: 14: foo5
+; C6-NEXT: 15: foo6
+; C6-NEXT: 16: foo7
+; CM-NEXT: .
+; CM-NEXT: .
+; CM-NEXT: .
+; C6-NEXT: 17: foo7
+; C6-NEXT: 18: foo6
+; C5-NEXT: 19: foo5
+; C4-NEXT: 20: foo4
+; C3-NEXT: 21: foo3
+; C2-NEXT: 22: foo2
+; C1-NEXT: 23: foo1
+; C0-NEXT: 24: lab2 world
+; C0-NEXT:label:3 ^~~~
+; C0-NEXT:next:2'2 } search range end (exclusive)
+; C1-NEXT: 25: foo1
+; C2-NEXT: 26: foo2
+; C3-NEXT: 27: foo3
+; C4-NEXT: 28: foo4
+; C5-NEXT: 29: foo5
+; C6-NEXT: 30: foo6
+; C7-NEXT: 31: foo7
+; C7-NEXT: 32: foo8
+; C7-NEXT: 33: foo9
+; C7-NEXT: 34: foo0
+; CE-NEXT: .
+; CE-NEXT: .
+; CE-NEXT: .
+; C0-NEXT:>>>>>>
; Now build an alternate set of checks where input lines that might be elided by
; ellipses have annotations.
; RUN: cp %t.in %t.wide.in
-; RUN: echo 'CHECK-LABEL: lab1' > %t.wide.chk
-; RUN: echo ' CHECK: hello' >> %t.wide.chk
-; RUN: echo ' CHECK: goodbye' >> %t.wide.chk
-; RUN: echo 'CHECK-LABEL: lab2' >> %t.wide.chk
-; RUN: echo ' CHECK-NEXT: world' >> %t.wide.chk
-
-; W5: <<<<<<
-; W5: 9: lab1 hello
-; W5-NEXT: label:1'0 ^~~~
-; W5-NEXT: label:1'1 ^~~~
-; W5-NEXT: check:2 ^~~~~
-; W5-NEXT: check:3'0 X error: no match found
-; W5-NEXT: 10: foo1
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: check:3'1 ? possible intended match
-; W5-NEXT: 11: foo2
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 12: foo3
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 13: foo4
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 14: foo5
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 15: foo6
-; W5-NEXT: check:3'0 ~~~~~
-; W6-NEXT: 16: foo7
-; W6-NEXT: check:3'0 ~~~~~
-; WM-NEXT: .
-; WM-NEXT: .
-; WM-NEXT: .
-; W6-NEXT: 17: foo7
-; W6-NEXT: check:3'0 ~~~~~
-; W6-NEXT: 18: foo6
-; W6-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 19: foo5
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 20: foo4
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 21: foo3
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 22: foo2
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 23: foo1
-; W5-NEXT: check:3'0 ~~~~~
-; W5-NEXT: 24: lab2 world
-; W5-NEXT: label:4 ^~~~
-; W5-NEXT: check:3'0 ~~~~
-; W5-NEXT: next:5 !~~~~ error: match on wrong line
+; RUN: echo 'CHECK-LABEL: lab1' > %t.wide.chk
+; RUN: echo ' CHECK-DAG: hello{{([foo0-9[:space:]])*}}' >> %t.wide.chk
+; RUN: echo ' CHECK-DAG: goodbye' >> %t.wide.chk
+; RUN: echo 'CHECK-LABEL: lab2' >> %t.wide.chk
+; RUN: echo ' CHECK-NEXT: world' >> %t.wide.chk
+
+; W5:<<<<<<
+; W5: 9: lab1 hello
+; W5-NEXT:label:1'0 ^~~~
+; W5-NEXT:label:1'1 ^~~~
+; W5-NEXT:dag:2 ^~~~~~
+; W5-NEXT:dag:3'0 { search range start (exclusive)
+; W5-NEXT:dag:3'1 error: no match found
+; W5-NEXT: 10: foo1
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT:dag:3'2 ? possible intended match
+; W5-NEXT: 11: foo2
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 12: foo3
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 13: foo4
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 14: foo5
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 15: foo6
+; W5-NEXT:dag:2 ~~~~~
+; W6-NEXT: 16: foo7
+; W6-NEXT:dag:2 ~~~~~
+; WM-NEXT: .
+; WM-NEXT: .
+; WM-NEXT: .
+; W6-NEXT: 17: foo7
+; W6-NEXT:dag:2 ~~~~~
+; W6-NEXT: 18: foo6
+; W6-NEXT:dag:2 ~~~~~
+; W5-NEXT: 19: foo5
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 20: foo4
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 21: foo3
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 22: foo2
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 23: foo1
+; W5-NEXT:dag:2 ~~~~~
+; W5-NEXT: 24: lab2 world
+; W5-NEXT:label:4 ^~~~
+; W5-NEXT:dag:3'3 } search range end (exclusive)
+; W5-NEXT:next:5'0 { search range start (exclusive)
+; W5-NEXT:next:5'1 !~~~~ error: match on wrong line
;--------------------------------------------------
; Check -dump-input-context=<bad value>.
@@ -172,7 +174,7 @@
; RUN: -dump-input-context=foobar \
; RUN: | FileCheck %s -match-full-lines -check-prefix=BADVAL -DVAL=foobar
-BADVAL: {{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-context option: '[[VAL]]' value invalid for uint argument!
+BADVAL:{{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-context option: '[[VAL]]' value invalid for uint argument!
;--------------------------------------------------
; Check -dump-input-context explicit values.
diff --git a/llvm/test/FileCheck/dump-input/enable.txt b/llvm/test/FileCheck/dump-input/enable.txt
index 89b56960885e3..58472eb4751f0 100644
--- a/llvm/test/FileCheck/dump-input/enable.txt
+++ b/llvm/test/FileCheck/dump-input/enable.txt
@@ -27,7 +27,7 @@
; RUN: %ProtectFileCheckOutput not FileCheck -dump-input=foobar 2>&1 \
; RUN: | FileCheck %s -match-full-lines -check-prefix=BADVAL
-BADVAL: {{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input option: Cannot find option named 'foobar'!
+BADVAL:{{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input option: Cannot find option named 'foobar'!
;--------------------------------------------------
; Check -dump-input=help.
@@ -228,28 +228,29 @@ BADVAL: {{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input option: Cannot find op
; HELP-NOT: {{.}}
; Trace is sometimes suppressed.
-; TRACE: {{.*}}remark:{{.*}}
-; NOTRACE-NOT: remark:
+; TRACE:{{.*}}remark:{{.*}}
+; NOTRACE-NOT:remark:
; Error diagnostics are never suppressed.
-; ERR: {{.*}}error:{{.*}}
-
-; NODUMP-NOT: <<<<<<
-
-; DUMP-OK: Input was:
-; DUMP-OK-NEXT: <<<<<<
-; DUMP-OK-NEXT: 1: hello
-; DUMP-OK-NEXT: check:1 ^~~~~
-; DUMP-OK-NEXT: 2: world
-; DUMP-OK-NEXT: next:2 ^~~~~
-; DUMP-OK-NEXT: >>>>>>
-
-; DUMP-ERR: Input was:
-; DUMP-ERR-NEXT: <<<<<<
-; DUMP-ERR-NEXT: 1: hello
-; DUMP-ERR-V-NEXT: check:1 ^~~~~
-; DUMP-ERR-NEXT: next:2'0 X error: no match found
-; DUMP-ERR-NEXT: 2: whirled
-; DUMP-ERR-NEXT: next:2'0 ~~~~~~~~
-; DUMP-ERR-NEXT: next:2'1 ? possible intended match
-; DUMP-ERR-NEXT: >>>>>>
+; ERR:{{.*}}error:{{.*}}
+
+; NODUMP-NOT:<<<<<<
+
+; DUMP-OK:Input was:
+; DUMP-OK-NEXT:<<<<<<
+; DUMP-OK-NEXT: 1: hello
+; DUMP-OK-NEXT:check:1 ^~~~~
+; DUMP-OK-NEXT: 2: world
+; DUMP-OK-NEXT:next:2 ^~~~~
+; DUMP-OK-NEXT:>>>>>>
+
+; DUMP-ERR:Input was:
+; DUMP-ERR-NEXT:<<<<<<
+; DUMP-ERR-NEXT: 1: hello
+; DUMP-ERR-V-NEXT:check:1 ^~~~~
+; DUMP-ERR-NEXT:next:2'0 { search range start (exclusive)
+; DUMP-ERR-NEXT:next:2'1 error: no match found
+; DUMP-ERR-NEXT: 2: whirled
+; DUMP-ERR-NEXT:next:2'2 ? possible intended match
+; DUMP-ERR-NEXT:next:2'3 } search range end (exclusive)
+; DUMP-ERR-NEXT:>>>>>>
diff --git a/llvm/test/FileCheck/dump-input/filter.txt b/llvm/test/FileCheck/dump-input/filter.txt
index 6ea858d2126e6..7f7df8e2d1095 100644
--- a/llvm/test/FileCheck/dump-input/filter.txt
+++ b/llvm/test/FileCheck/dump-input/filter.txt
@@ -30,7 +30,7 @@
; RUN: echo foo8 >> %t.in
; RUN: echo foo9 >> %t.in
; line 23
-; RUN: echo word >> %t.in
+; RUN: echo world >> %t.in
; RUN: echo foo0 >> %t.in
; RUN: echo foo1 >> %t.in
; RUN: echo foo2 >> %t.in
@@ -42,207 +42,290 @@
; RUN: echo foo8 >> %t.in
; RUN: echo foo9 >> %t.in
; line 34
-; RUN: echo end >> %t.in
-
-; RUN: echo 'CHECK: start' > %t.chk
-; RUN: echo 'CHECK: hello' >> %t.chk
-; RUN: echo 'CHECK: world' >> %t.chk
-; RUN: echo 'CHECK: end' >> %t.chk
+; RUN: echo bye >> %t.in
+; RUN: echo foo0 >> %t.in
+; RUN: echo foo1 >> %t.in
+; RUN: echo foo2 >> %t.in
+; RUN: echo foo3 >> %t.in
+; RUN: echo foo4 >> %t.in
+; RUN: echo foo5 >> %t.in
+; RUN: echo foo6 >> %t.in
+; RUN: echo foo7 >> %t.in
+; RUN: echo foo8 >> %t.in
+; RUN: echo foo9 >> %t.in
+; line 45
+; RUN: echo sleep >> %t.in
+; RUN: echo foo0 >> %t.in
+; RUN: echo foo1 >> %t.in
+; RUN: echo foo2 >> %t.in
+; RUN: echo foo3 >> %t.in
+; RUN: echo foo4 >> %t.in
+; RUN: echo foo5 >> %t.in
+; RUN: echo foo6 >> %t.in
+; RUN: echo foo7 >> %t.in
+; RUN: echo foo8 >> %t.in
+; RUN: echo foo9 >> %t.in
+; RUN: echo end >> %t.in
+
+; RUN: echo 'CHECK: start' > %t.chk
+; RUN: echo 'CHECK: hello{{(.|[[:space:]])*}}world' >> %t.chk
+; RUN: echo 'CHECK-NOT: bye{{(.|[[:space:]])*}}sleep' >> %t.chk
+; RUN: echo 'CHECK: end' >> %t.chk
;--------------------------------------------------
; Directives for checking the dump.
;--------------------------------------------------
-; ALL: <<<<<<
-; ALL-NEXT: 1: start
-; ALL-NEXT: check:1 ^~~~~
-; ALL-NEXT: 2: foo0
-; ALL-NEXT: 3: foo1
-; ALL-NEXT: 4: foo2
-; ALL-NEXT: 5: foo3
-; ALL-NEXT: 6: foo4
-; ALL-NEXT: 7: foo5
-; ALL-NEXT: 8: foo6
-; ALL-NEXT: 9: foo7
-; ALL-NEXT: 10: foo8
-; ALL-NEXT: 11: foo9
-; ALL-NEXT: 12: hello
-; ALL-NEXT: check:2 ^~~~~
-; ALL-NEXT: check:3'0 X error: no match found
-; ALL-NEXT: 13: foo0
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 14: foo1
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 15: foo2
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 16: foo3
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 17: foo4
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 18: foo5
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 19: foo6
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 20: foo7
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 21: foo8
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 22: foo9
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 23: word
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: check:3'1 ? possible intended match
-; ALL-NEXT: 24: foo0
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 25: foo1
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 26: foo2
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 27: foo3
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 28: foo4
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 29: foo5
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 30: foo6
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 31: foo7
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 32: foo8
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 33: foo9
-; ALL-NEXT: check:3'0 ~~~~~
-; ALL-NEXT: 34: end
-; ALL-NEXT: check:3'0 ~~~~
-; ALL-NEXT: >>>>>>
-
-; ANNOTATION-FULL: <<<<<<
-; ANNOTATION-FULL-NEXT: 1: start
-; ANNOTATION-FULL-NEXT: check:1 ^~~~~
-; ANNOTATION-FULL-NEXT: 2: foo0
-; ANNOTATION-FULL-NEXT: 3: foo1
-; ANNOTATION-FULL-NEXT: .
-; ANNOTATION-FULL-NEXT: .
-; ANNOTATION-FULL-NEXT: .
-; ANNOTATION-FULL-NEXT: 10: foo8
-; ANNOTATION-FULL-NEXT: 11: foo9
-; ANNOTATION-FULL-NEXT: 12: hello
-; ANNOTATION-FULL-NEXT: check:2 ^~~~~
-; ANNOTATION-FULL-NEXT: check:3'0 X error: no match found
-; ANNOTATION-FULL-NEXT: 13: foo0
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 14: foo1
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 15: foo2
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 16: foo3
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 17: foo4
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 18: foo5
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 19: foo6
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 20: foo7
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 21: foo8
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 22: foo9
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 23: word
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: check:3'1 ? possible intended match
-; ANNOTATION-FULL-NEXT: 24: foo0
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 25: foo1
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 26: foo2
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 27: foo3
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 28: foo4
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 29: foo5
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 30: foo6
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 31: foo7
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 32: foo8
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 33: foo9
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~~
-; ANNOTATION-FULL-NEXT: 34: end
-; ANNOTATION-FULL-NEXT: check:3'0 ~~~~
-; ANNOTATION-FULL-NEXT: >>>>>>
-
-; ANNOTATION: <<<<<<
-; ANNOTATION-NEXT: 1: start
-; ANNOTATION-NEXT: check:1 ^~~~~
-; ANNOTATION-NEXT: 2: foo0
-; ANNOTATION-NEXT: 3: foo1
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: 10: foo8
-; ANNOTATION-NEXT: 11: foo9
-; ANNOTATION-NEXT: 12: hello
-; ANNOTATION-NEXT: check:2 ^~~~~
-; ANNOTATION-NEXT: check:3'0 X error: no match found
-; ANNOTATION-NEXT: 13: foo0
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: 14: foo1
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: 21: foo8
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: 22: foo9
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: 23: word
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: check:3'1 ? possible intended match
-; ANNOTATION-NEXT: 24: foo0
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: 25: foo1
-; ANNOTATION-NEXT: check:3'0 ~~~~~
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: .
-; ANNOTATION-NEXT: >>>>>>
-
-; ERROR: <<<<<<
-; ERROR-NEXT: .
-; ERROR-NEXT: .
-; ERROR-NEXT: .
-; ERROR-NEXT: 10: foo8
-; ERROR-NEXT: 11: foo9
-; ERROR-NEXT: 12: hello
-; ERROR-NEXT: check:2 ^~~~~
-; ERROR-NEXT: check:3'0 X error: no match found
-; ERROR-NEXT: 13: foo0
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: 14: foo1
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: .
-; ERROR-NEXT: .
-; ERROR-NEXT: .
-; ERROR-NEXT: 21: foo8
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: 22: foo9
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: 23: word
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: check:3'1 ? possible intended match
-; ERROR-NEXT: 24: foo0
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: 25: foo1
-; ERROR-NEXT: check:3'0 ~~~~~
-; ERROR-NEXT: .
-; ERROR-NEXT: .
-; ERROR-NEXT: .
-; ERROR-NEXT: >>>>>>
+; ALL:<<<<<<
+; ALL-NEXT: 1: start
+; ALL-NEXT:check:1 ^~~~~
+; ALL-NEXT: 2: foo0
+; ALL-NEXT: 3: foo1
+; ALL-NEXT: 4: foo2
+; ALL-NEXT: 5: foo3
+; ALL-NEXT: 6: foo4
+; ALL-NEXT: 7: foo5
+; ALL-NEXT: 8: foo6
+; ALL-NEXT: 9: foo7
+; ALL-NEXT: 10: foo8
+; ALL-NEXT: 11: foo9
+; ALL-NEXT: 12: hello
+; ALL-NEXT:check:2 ^~~~~~
+; ALL-NEXT: 13: foo0
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 14: foo1
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 15: foo2
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 16: foo3
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 17: foo4
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 18: foo5
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 19: foo6
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 20: foo7
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 21: foo8
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 22: foo9
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT: 23: world
+; ALL-NEXT:check:2 ~~~~~
+; ALL-NEXT:not:3'0 { search range start (exclusive)
+; ALL-NEXT: 24: foo0
+; ALL-NEXT: 25: foo1
+; ALL-NEXT: 26: foo2
+; ALL-NEXT: 27: foo3
+; ALL-NEXT: 28: foo4
+; ALL-NEXT: 29: foo5
+; ALL-NEXT: 30: foo6
+; ALL-NEXT: 31: foo7
+; ALL-NEXT: 32: foo8
+; ALL-NEXT: 33: foo9
+; ALL-NEXT: 34: bye
+; ALL-NEXT:not:3'1 !~~~ error: no match expected
+; ALL-NEXT: 35: foo0
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 36: foo1
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 37: foo2
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 38: foo3
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 39: foo4
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 40: foo5
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 41: foo6
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 42: foo7
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 43: foo8
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 44: foo9
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 45: sleep
+; ALL-NEXT:not:3'1 ~~~~~
+; ALL-NEXT: 46: foo0
+; ALL-NEXT: 47: foo1
+; ALL-NEXT: 48: foo2
+; ALL-NEXT: 49: foo3
+; ALL-NEXT: 50: foo4
+; ALL-NEXT: 51: foo5
+; ALL-NEXT: 52: foo6
+; ALL-NEXT: 53: foo7
+; ALL-NEXT: 54: foo8
+; ALL-NEXT: 55: foo9
+; ALL-NEXT:not:3'2 } search range end (exclusive)
+; ALL-NEXT: 56: end
+; ALL-NEXT:check:4 ^~~
+; ALL-NEXT:>>>>>>
+
+; ANNOTATION-FULL:<<<<<<
+; ANNOTATION-FULL-NEXT: 1: start
+; ANNOTATION-FULL-NEXT:check:1 ^~~~~
+; ANNOTATION-FULL-NEXT: 2: foo0
+; ANNOTATION-FULL-NEXT: 3: foo1
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: 10: foo8
+; ANNOTATION-FULL-NEXT: 11: foo9
+; ANNOTATION-FULL-NEXT: 12: hello
+; ANNOTATION-FULL-NEXT:check:2 ^~~~~~
+; ANNOTATION-FULL-NEXT: 13: foo0
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 14: foo1
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 15: foo2
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 16: foo3
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 17: foo4
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 18: foo5
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 19: foo6
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 20: foo7
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 21: foo8
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 22: foo9
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT: 23: world
+; ANNOTATION-FULL-NEXT:check:2 ~~~~~
+; ANNOTATION-FULL-NEXT:not:3'0 { search range start (exclusive)
+; ANNOTATION-FULL-NEXT: 24: foo0
+; ANNOTATION-FULL-NEXT: 25: foo1
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: 32: foo8
+; ANNOTATION-FULL-NEXT: 33: foo9
+; ANNOTATION-FULL-NEXT: 34: bye
+; ANNOTATION-FULL-NEXT:not:3'1 !~~~ error: no match expected
+; ANNOTATION-FULL-NEXT: 35: foo0
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 36: foo1
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 37: foo2
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 38: foo3
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 39: foo4
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 40: foo5
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 41: foo6
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 42: foo7
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 43: foo8
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 44: foo9
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 45: sleep
+; ANNOTATION-FULL-NEXT:not:3'1 ~~~~~
+; ANNOTATION-FULL-NEXT: 46: foo0
+; ANNOTATION-FULL-NEXT: 47: foo1
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: .
+; ANNOTATION-FULL-NEXT: 53: foo7
+; ANNOTATION-FULL-NEXT: 54: foo8
+; ANNOTATION-FULL-NEXT: 55: foo9
+; ANNOTATION-FULL-NEXT:not:3'2 } search range end (exclusive)
+; ANNOTATION-FULL-NEXT: 56: end
+; ANNOTATION-FULL-NEXT:check:4 ^~~
+; ANNOTATION-FULL-NEXT:>>>>>>
+
+; ANNOTATION:<<<<<<
+; ANNOTATION-NEXT: 1: start
+; ANNOTATION-NEXT:check:1 ^~~~~
+; ANNOTATION-NEXT: 2: foo0
+; ANNOTATION-NEXT: 3: foo1
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: 10: foo8
+; ANNOTATION-NEXT: 11: foo9
+; ANNOTATION-NEXT: 12: hello
+; ANNOTATION-NEXT:check:2 ^~~~~~
+; ANNOTATION-NEXT: 13: foo0
+; ANNOTATION-NEXT:check:2 ~~~~~
+; ANNOTATION-NEXT: 14: foo1
+; ANNOTATION-NEXT:check:2 ~~~~~
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: 21: foo8
+; ANNOTATION-NEXT:check:2 ~~~~~
+; ANNOTATION-NEXT: 22: foo9
+; ANNOTATION-NEXT:check:2 ~~~~~
+; ANNOTATION-NEXT: 23: world
+; ANNOTATION-NEXT:check:2 ~~~~~
+; ANNOTATION-NEXT:not:3'0 { search range start (exclusive)
+; ANNOTATION-NEXT: 24: foo0
+; ANNOTATION-NEXT: 25: foo1
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: 32: foo8
+; ANNOTATION-NEXT: 33: foo9
+; ANNOTATION-NEXT: 34: bye
+; ANNOTATION-NEXT:not:3'1 !~~~ error: no match expected
+; ANNOTATION-NEXT: 35: foo0
+; ANNOTATION-NEXT:not:3'1 ~~~~~
+; ANNOTATION-NEXT: 36: foo1
+; ANNOTATION-NEXT:not:3'1 ~~~~~
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: .
+; ANNOTATION-NEXT: 53: foo7
+; ANNOTATION-NEXT: 54: foo8
+; ANNOTATION-NEXT: 55: foo9
+; ANNOTATION-NEXT:not:3'2 } search range end (exclusive)
+; ANNOTATION-NEXT: 56: end
+; ANNOTATION-NEXT:check:4 ^~~
+; ANNOTATION-NEXT:>>>>>>
+
+; ERROR:<<<<<<
+; ERROR-NEXT: .
+; ERROR-NEXT: .
+; ERROR-NEXT: .
+; ERROR-NEXT: 21: foo8
+; ERROR-NEXT:check:2 ~~~~~
+; ERROR-NEXT: 22: foo9
+; ERROR-NEXT:check:2 ~~~~~
+; ERROR-NEXT: 23: world
+; ERROR-NEXT:check:2 ~~~~~
+; ERROR-NEXT:not:3'0 { search range start (exclusive)
+; ERROR-NEXT: 24: foo0
+; ERROR-NEXT: 25: foo1
+; ERROR-NEXT: .
+; ERROR-NEXT: .
+; ERROR-NEXT: .
+; ERROR-NEXT: 32: foo8
+; ERROR-NEXT: 33: foo9
+; ERROR-NEXT: 34: bye
+; ERROR-NEXT:not:3'1 !~~~ error: no match expected
+; ERROR-NEXT: 35: foo0
+; ERROR-NEXT:not:3'1 ~~~~~
+; ERROR-NEXT: 36: foo1
+; ERROR-NEXT:not:3'1 ~~~~~
+; ERROR-NEXT: .
+; ERROR-NEXT: .
+; ERROR-NEXT: .
+; ERROR-NEXT: 53: foo7
+; ERROR-NEXT: 54: foo8
+; ERROR-NEXT: 55: foo9
+; ERROR-NEXT:not:3'2 } search range end (exclusive)
+; ERROR-NEXT: 56: end
+; ERROR-NEXT:check:4 ^~~
+; ERROR-NEXT:>>>>>>
;--------------------------------------------------
; Check -dump-input-filter=<bad value>.
@@ -253,7 +336,7 @@
; RUN: -dump-input-filter=foobar \
; RUN: | FileCheck %s -match-full-lines -check-prefix=BADVAL
-BADVAL: {{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-filter option: Cannot find option named 'foobar'!
+BADVAL:{{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-filter option: Cannot find option named 'foobar'!
;--------------------------------------------------
; Check -dump-input-filter explicit values.
@@ -380,47 +463,123 @@ BADVAL: {{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-filter option: Cannot
; RUN: < %t.in 2>&1 \
; RUN: | FileCheck %s -match-full-lines -check-prefixes=EMPTY
-; EMPTY: <<<<<<
-; EMPTY-NEXT: .
-; EMPTY-NEXT: .
-; EMPTY-NEXT: .
-; EMPTY-NEXT: >>>>>>
+; EMPTY:<<<<<<
+; EMPTY-NEXT: .
+; EMPTY-NEXT: .
+; EMPTY-NEXT: .
+; EMPTY-NEXT:>>>>>>
;--------------------------------------------------
; Check that other kinds of errors are included by -dump-input-filter=error.
;
-; "error: no match found" and "possible intended match" are checked above.
+; "error: no match expected" is checked above.
;--------------------------------------------------
;- - - - - - - - - - - - - - - - - - - - - - - - -
-; error: no match expected.
+; error: no match found.
+; possible intended match
;- - - - - - - - - - - - - - - - - - - - - - - - -
-; RUN: echo 'foo' > %t.not-err.in
-; RUN: echo 'CHECK-NOT: foo' > %t.not-err.chk
+; RUN: echo 'start' > %t.chk-err.in
+; RUN: echo 'foo0' >> %t.chk-err.in
+; RUN: echo 'foo1' >> %t.chk-err.in
+; RUN: echo 'foo2' >> %t.chk-err.in
+; RUN: echo 'foo3' >> %t.chk-err.in
+; RUN: echo 'hello' >> %t.chk-err.in
+; RUN: echo 'foo0' >> %t.chk-err.in
+; RUN: echo 'foo1' >> %t.chk-err.in
+; RUN: echo 'foo2' >> %t.chk-err.in
+; RUN: echo 'foo3' >> %t.chk-err.in
+; RUN: echo 'end' >> %t.chk-err.in
+
+; RUN: echo 'CHECK: jello' > %t.chk-err.chk
; RUN: %ProtectFileCheckOutput \
; RUN: not FileCheck -dump-input-context=0 -dump-input-filter=error \
-; RUN: %t.not-err.chk < %t.not-err.in 2>&1 \
-; RUN: | FileCheck %s -match-full-lines -check-prefixes=NOT-ERR
-
-; NOT-ERR: 1: foo
-; NOT-ERR-NEXT: not:1 !~~ error: no match expected
+; RUN: %t.chk-err.chk < %t.chk-err.in 2>&1 \
+; RUN: | FileCheck %s -match-full-lines -check-prefixes=CHK-ERR
+
+; CHK-ERR:<<<<<<
+; CHK-ERR-NEXT: 1: start
+; CHK-ERR-NEXT:check:1'0 { search range start (exclusive)
+; CHK-ERR-NEXT:check:1'1 error: no match found
+; CHK-ERR-NEXT: .
+; CHK-ERR-NEXT: .
+; CHK-ERR-NEXT: .
+; CHK-ERR-NEXT: 6: hello
+; CHK-ERR-NEXT:check:1'2 ? possible intended match
+; CHK-ERR-NEXT: .
+; CHK-ERR-NEXT: .
+; CHK-ERR-NEXT: .
+; CHK-ERR-NEXT: 11: end
+; CHK-ERR-NEXT:check:1'3 } search range end (exclusive)
+; CHK-ERR-NEXT:>>>>>>
;- - - - - - - - - - - - - - - - - - - - - - - - -
; error: match on wrong line.
;- - - - - - - - - - - - - - - - - - - - - - - - -
-; RUN: echo 'foo' > %t.next-err.in
-; RUN: echo 'foo' >> %t.next-err.in
-; RUN: echo 'bar' >> %t.next-err.in
-; RUN: echo 'CHECK: foo' > %t.next-err.chk
-; RUN: echo 'CHECK-NEXT: bar' >> %t.next-err.chk
+; RUN: echo 'start' > %t.next-err.in
+; RUN: echo 'foo0' >> %t.next-err.in
+; RUN: echo 'foo1' >> %t.next-err.in
+; RUN: echo 'foo2' >> %t.next-err.in
+; RUN: echo 'foo3' >> %t.next-err.in
+; RUN: echo 'hello' >> %t.next-err.in
+; RUN: echo 'foo0' >> %t.next-err.in
+; RUN: echo 'foo1' >> %t.next-err.in
+; RUN: echo 'foo2' >> %t.next-err.in
+; RUN: echo 'foo3' >> %t.next-err.in
+; RUN: echo 'end' >> %t.next-err.in
+
+; RUN: echo 'CHECK: start' > %t.next-err.chk
+; RUN: echo 'CHECK-NEXT: hello' >> %t.next-err.chk
; RUN: %ProtectFileCheckOutput \
; RUN: not FileCheck -dump-input-context=0 -dump-input-filter=error \
; RUN: %t.next-err.chk < %t.next-err.in 2>&1 \
; RUN: | FileCheck %s -match-full-lines -check-prefixes=NEXT-ERR
-; NEXT-ERR: 3: bar
-; NEXT-ERR-NEXT: next:2 !~~ error: match on wrong line
+; NEXT-ERR:<<<<<<
+; NEXT-ERR-NEXT: 1: start
+; NEXT-ERR-NEXT:next:2'0 { search range start (exclusive)
+; NEXT-ERR-NEXT: .
+; NEXT-ERR-NEXT: .
+; NEXT-ERR-NEXT: .
+; NEXT-ERR-NEXT: 6: hello
+; NEXT-ERR-NEXT:next:2'1 !~~~~ error: match on wrong line
+; NEXT-ERR-NEXT: .
+; NEXT-ERR-NEXT: .
+; NEXT-ERR-NEXT: .
+; NEXT-ERR-NEXT: 11: end
+; NEXT-ERR-NEXT:next:2'2 } search range end (exclusive)
+; NEXT-ERR-NEXT:>>>>>>
+
+;- - - - - - - - - - - - - - - - - - - - - - - - -
+; error: match failed for invalid pattern.
+;- - - - - - - - - - - - - - - - - - - - - - - - -
+
+; RUN: echo 'start' > %t.invalid.in
+; RUN: echo 'foo0' >> %t.invalid.in
+; RUN: echo 'foo1' >> %t.invalid.in
+; RUN: echo 'foo2' >> %t.invalid.in
+; RUN: echo 'foo3' >> %t.invalid.in
+; RUN: echo 'end' >> %t.invalid.in
+
+; RUN: echo 'CHECK: [[#0x0 - 0x1]]' > %t.invalid.chk
+
+; RUN: %ProtectFileCheckOutput \
+; RUN: not FileCheck -dump-input-context=0 -dump-input-filter=error \
+; RUN: %t.invalid.chk < %t.invalid.in 2>&1 \
+; RUN: | FileCheck %s -match-full-lines -check-prefixes=INVALID -strict-whitespace
+
+; INVALID:<<<<<<
+; INVALID-NEXT: 1: start
+; INVALID-NEXT:check:1'0 { search range start (exclusive)
+; INVALID-NEXT:check:1'1 error: match failed for invalid pattern
+; INVALID-NEXT:check:1'2 unable to substitute variable or numeric expression: overflow error
+; INVALID-NEXT: .
+; INVALID-NEXT: .
+; INVALID-NEXT: .
+; INVALID-NEXT: 6: end
+; INVALID-NEXT:check:1'3 } search range end (exclusive)
+; INVALID-NEXT:>>>>>>
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
new file mode 100644
index 0000000000000..b003a9ce4aabd
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
@@ -0,0 +1,74 @@
+; Because -dump-input-filter=error includes a failed directive's search range
+; end, input line 15 below is revealed, and -dump-input-context=2 reveals the
+; surrounding lines. Those lines are where the actual problem is: the "host
+; triples:" header is off by one. Sometimes the key to understanding a
+; directive's failure is where the following CHECK-LABEL matched because it
+; limits the search range.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefix=DMP
+
+ DMP:<<<<<<
+DMP-NEXT: 1: offload triples:
+DMP-NEXT:label:1'0 ^~~~~~~~~~~~~~~~
+DMP-NEXT:label:1'1 ^~~~~~~~~~~~~~~~
+DMP-NEXT:check:2'0 { search range start (exclusive)
+DMP-NEXT:check:2'1 error: no match found
+DMP-NEXT: 2: - x86_64-linux-gnu
+DMP-NEXT:check:2'2 ? possible intended match
+DMP-NEXT: 3: - x86_64-unknown-linux-gnu
+DMP-NEXT: 4: - x86_64-pc-linux-gnu
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: 13: - x86_64-linux-android
+DMP-NEXT: 14: - amdgcn-amd-amdhsa
+DMP-NEXT: 15: host triples:
+DMP-NEXT:label:3 ^~~~~~~~~~~~~
+DMP-NEXT:check:2'3 } search range end (exclusive)
+DMP-NEXT: 16: - nvptx64-nvidia-cuda
+DMP-NEXT: 17: - x86_64-linux-gnu
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT:>>>>>>
+
+;--- check.txt
+CHECK-LABEL: offload triples:
+ CHECK: nvptx64-nvidia-cuda
+CHECK-LABEL: host triples:
+
+;--- input.txt
+offload triples:
+- x86_64-linux-gnu
+- x86_64-unknown-linux-gnu
+- x86_64-pc-linux-gnu
+- x86_64-redhat-linux6E
+- x86_64-redhat-linux
+- x86_64-suse-linux
+- x86_64-manbo-linux-gnu
+- x86_64-linux-gnu
+- x86_64-slackware-linux
+- x86_64-unknown-linux
+- x86_64-amazon-linux
+- x86_64-linux-android
+- amdgcn-amd-amdhsa
+host triples:
+- nvptx64-nvidia-cuda
+- x86_64-linux-gnu
+- x86_64-unknown-linux-gnu
+- x86_64-pc-linux-gnu
+- x86_64-redhat-linux6E
+- x86_64-redhat-linux
+- x86_64-suse-linux
+- x86_64-manbo-linux-gnu
+- x86_64-linux-gnu
+- x86_64-slackware-linux
+- x86_64-unknown-linux
+- x86_64-amazon-linux
+- x86_64-linux-android
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
new file mode 100644
index 0000000000000..0767d4b734590
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
@@ -0,0 +1,61 @@
+; Because -dump-input-filter=error includes a failed directive's search range
+; start, input line 1 below is revealed, and -dump-input-context=2 reveals lines
+; 2-3. Those lines are where the actual problem is because that is where the
+; CHECK-NEXT/CHECK-SAME directive was expected to match but did not. The line
+; where CHECK-NEXT/CHECK-SAME actually matched, line 13, is typically less
+; useful information.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/next.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_NEXT
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/same.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_SAME
+
+ DMP:<<<<<<
+ DMP-NEXT: 1: start
+ DMP-NEXT:check:1 ^~~~~
+DMP_NEXT-NEXT:next:2'0 { search range start (exclusive)
+DMP_SAME-NEXT:same:2'0 { search range start (exclusive)
+ DMP-NEXT: 2: foo0
+ DMP-NEXT: 3: foo1
+ DMP-NEXT: .
+ DMP-NEXT: .
+ DMP-NEXT: .
+ DMP-NEXT: 11: foo9
+ DMP-NEXT: 12: foo10
+ DMP-NEXT: 13: end
+DMP_NEXT-NEXT:next:2'1 !~~ error: match on wrong line
+DMP_SAME-NEXT:same:2'1 !~~ error: match on wrong line
+DMP_NEXT-NEXT:next:2'2 } search range end (exclusive)
+DMP_SAME-NEXT:same:2'2 } search range end (exclusive)
+ DMP-NEXT:>>>>>>
+
+;--- next.txt
+CHECK: start
+CHECK-NEXT: end
+
+;--- same.txt
+CHECK: start
+CHECK-SAME: end
+
+;--- input.txt
+start
+foo0
+foo1
+foo2
+foo3
+foo4
+foo5
+foo6
+foo7
+foo8
+foo9
+foo10
+end
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
new file mode 100644
index 0000000000000..7cae1b85bb47a
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
@@ -0,0 +1,112 @@
+; Because -dump-input-filter=error includes a failed directive's search range,
+; input lines 1 and 62 below are revealed, and -dump-input-context=2 reveals the
+; surrounding lines. Even with only line 1, it looks like the host list
+; includes a GPU triple. Line 62 and its context reveals we have an
+; accidentally nested list. Often the key to understanding a CHECK-NOT failure
+; is where the directives before and after it matched because those establish
+; the search range.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefix=DMP
+
+ DMP:<<<<<<
+DMP-NEXT: 1: <triples kind="host">
+DMP-NEXT:check:1 ^~~~~~~~~~~~~~~~~~~~~
+DMP-NEXT:not:2'0 { search range start (exclusive)
+DMP-NEXT: 2: x86_64-linux-gnu
+DMP-NEXT: 3: x86_64-unknown-linux-gnu
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: 42: x86_64-amazon-linux
+DMP-NEXT: 43: x86_64-linux-android
+DMP-NEXT: 44: nvptx64-nvidia-cuda
+DMP-NEXT:not:2'1 !~~~~~~~~~~~~~~~~~~ error: no match expected
+DMP-NEXT: 45: i686-linux-gnu
+DMP-NEXT: 46: i686-pc-linux-gnu
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: 59: i486-gnu
+DMP-NEXT: 60: i586-gnu
+DMP-NEXT: 61: i686-gnu
+DMP-NEXT:not:2'2 } search range end (exclusive)
+DMP-NEXT: 62: </triples>
+DMP-NEXT:check:3 ^~~~~~~~~~
+DMP-NEXT: 63: </triples>
+DMP-NEXT:>>>>>>
+
+;--- check.txt
+CHECK: <triples kind="host">
+CHECK-NOT: nvptx64-nvidia-cuda
+CHECK: </triples>
+
+;--- input.txt
+<triples kind="host">
+ x86_64-linux-gnu
+ x86_64-unknown-linux-gnu
+ x86_64-pc-linux-gnu
+ x86_64-redhat-linux6E
+ x86_64-redhat-linux
+ x86_64-suse-linux
+ x86_64-manbo-linux-gnu
+ x86_64-linux-gnu
+ x86_64-slackware-linux
+ x86_64-unknown-linux
+ x86_64-amazon-linux
+ x86_64-linux-android
+ i686-linux-gnu
+ i686-pc-linux-gnu
+ i486-linux-gnu
+ i386-linux-gnu
+ i386-redhat-linux6E
+ i686-redhat-linux
+ i586-redhat-linux
+ i386-redhat-linux
+ i586-suse-linux
+ i486-slackware-linux
+ i686-montavista-linux
+ i586-linux-gnu
+ i686-linux-android
+ i386-gnu
+ i486-gnu
+ i586-gnu
+ i686-gnu
+<triples kind="offload">
+ x86_64-linux-gnu
+ x86_64-unknown-linux-gnu
+ x86_64-pc-linux-gnu
+ x86_64-redhat-linux6E
+ x86_64-redhat-linux
+ x86_64-suse-linux
+ x86_64-manbo-linux-gnu
+ x86_64-linux-gnu
+ x86_64-slackware-linux
+ x86_64-unknown-linux
+ x86_64-amazon-linux
+ x86_64-linux-android
+ nvptx64-nvidia-cuda
+ i686-linux-gnu
+ i686-pc-linux-gnu
+ i486-linux-gnu
+ i386-linux-gnu
+ i386-redhat-linux6E
+ i686-redhat-linux
+ i586-redhat-linux
+ i386-redhat-linux
+ i586-suse-linux
+ i486-slackware-linux
+ i686-montavista-linux
+ i586-linux-gnu
+ i686-linux-android
+ i386-gnu
+ i486-gnu
+ i586-gnu
+ i686-gnu
+</triples>
+</triples>
diff --git a/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt
index c8e621eb31796..001f74c0c5a3d 100644
--- a/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt
+++ b/llvm/test/FileCheck/match-time-error-propagation/invalid-excluded-pattern.txt
@@ -28,9 +28,10 @@ ERR-VV-EMPTY:
DUMP:<<<<<<
DUMP-NEXT: 1: -1
- DUMP-NEXT:not:1'0 X~~ error: match failed for invalid pattern
- DUMP-NEXT:not:1'1 unable to substitute variable or numeric expression: overflow error
- DUMP-NEXT:not:1'2 undefined variable: UNDEFVAR
+ DUMP-NEXT:not:1'0 { } search range (exclusive bounds)
+ DUMP-NEXT:not:1'1 error: match failed for invalid pattern
+ DUMP-NEXT:not:1'2 unable to substitute variable or numeric expression: overflow error
+ DUMP-NEXT:not:1'3 undefined variable: UNDEFVAR
DUMP-VV-NEXT: 2:
DUMP-VV-NEXT:eof:1 ^
DUMP-NEXT:>>>>>>
diff --git a/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt
index 6aada8b0c7587..c633a98b76c9a 100644
--- a/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt
+++ b/llvm/test/FileCheck/match-time-error-propagation/invalid-expected-pattern.txt
@@ -17,9 +17,10 @@ RUN: echo > %t.in '-1'
DUMP:<<<<<<
DUMP-NEXT: 1: -1
-DUMP-NEXT:check:1'0 X~~ error: match failed for invalid pattern
-DUMP-NEXT:check:1'1 unable to substitute variable or numeric expression: overflow error
-DUMP-NEXT:check:1'2 undefined variable: UNDEFVAR
+DUMP-NEXT:check:1'0 { } search range (exclusive bounds)
+DUMP-NEXT:check:1'1 error: match failed for invalid pattern
+DUMP-NEXT:check:1'2 unable to substitute variable or numeric expression: overflow error
+DUMP-NEXT:check:1'3 undefined variable: UNDEFVAR
DUMP-NEXT:>>>>>>
;--------------------------------------------------
diff --git a/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt
index b76ff5ed66aa6..7c7a3e44b77d2 100644
--- a/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt
+++ b/llvm/test/FileCheck/match-time-error-propagation/matched-excluded-pattern.txt
@@ -23,9 +23,10 @@ ERR-VV-EMPTY:
DUMP:<<<<<<
DUMP-NEXT: 1: 123 abc -1
- DUMP-NEXT:not:1'0 X~~~~~~~~~~ error: match failed for invalid pattern
- DUMP-NEXT:not:1'1 unable to substitute variable or numeric expression: overflow error
- DUMP-NEXT:not:1'2 with "122+1" equal to "123"
+ DUMP-NEXT:not:1'0 { } search range (exclusive bounds)
+ DUMP-NEXT:not:1'1 error: match failed for invalid pattern
+ DUMP-NEXT:not:1'2 unable to substitute variable or numeric expression: overflow error
+ DUMP-NEXT:not:1'3 with "122+1" equal to "123"
DUMP-VV-NEXT: 2:
DUMP-VV-NEXT:eof:1 ^
DUMP-NEXT:>>>>>>
diff --git a/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
index 3388a53273918..bc7dd506d0ede 100644
--- a/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
+++ b/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
@@ -19,10 +19,11 @@ RUN: echo > %t.in '123 abc -1'
DUMP:<<<<<<
DUMP-NEXT: 1: 123 abc -1
-DUMP-NEXT:check:1'0 X~~~~~~~~~~ error: match failed for invalid pattern
-DUMP-NEXT:check:1'1 unable to substitute variable or numeric expression: overflow error
-DUMP-NEXT:check:1'2 with "122+1" equal to "123"
-DUMP-NEXT:check:1'3 ? possible intended match
+DUMP-NEXT:check:1'0 { } search range (exclusive bounds)
+DUMP-NEXT:check:1'1 error: match failed for invalid pattern
+DUMP-NEXT:check:1'2 unable to substitute variable or numeric expression: overflow error
+DUMP-NEXT:check:1'3 with "122+1" equal to "123"
+DUMP-NEXT:check:1'4 ? possible intended match
DUMP-NEXT:>>>>>>
;--------------------------------------------------
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 8c760db50a375..808df9a41029f 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -217,9 +217,8 @@ static MarkerStyle getMarker(const FileCheckDiag &Diag) {
// don't have markers. For example, a marker for the MatchNoteDiag
// 'with "VAR" equal to "5"' would seem to indicate where "VAR" matches, but
// we don't actually have that location. Instead, we just place the note
- // after the start of the associated MatchResultDiag. This decision is
- // overriden below for the case of MatchNoneDiag because the search range is
- // used instead.
+ // after the start of the associated MatchResultDiag. Search ranges are
+ // indicated separately.
MarkerStyle Res;
bool IsError = Diag.isError() || Diag.getMatchResultDiag().isError();
if (Diag.getMatchRange()) {
@@ -231,7 +230,7 @@ static MarkerStyle getMarker(const FileCheckDiag &Diag) {
Res.Color = IsError ? raw_ostream::RED : raw_ostream::GREEN;
Res.FiltersAsError = IsError;
- // Add Note. Override the default Lead and Color for some diagnostic kinds.
+ // Add Note. Override the default Head and Color for some diagnostic kinds.
switch (Diag.getKind()) {
case FileCheckDiag::MatchFoundDiag:
switch (cast<MatchFoundDiag>(Diag).getStatus()) {
@@ -251,8 +250,6 @@ static MarkerStyle getMarker(const FileCheckDiag &Diag) {
}
break;
case FileCheckDiag::MatchNoneDiag:
- Res.Head = 'X';
- Res.Mid = Res.Tail = '~';
switch (cast<MatchNoneDiag>(Diag).getStatus()) {
case MatchNoneDiag::Success:
break;
@@ -334,8 +331,11 @@ static void DumpInputAnnotationHelp(raw_ostream &OS) {
<< " - CHECK-DAG overlapping match (discarded, reported if "
<< "-vv)\n"
<< " - ";
- WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~";
- OS << " marks search range when no match is found, such as:\n"
+ WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "{ }";
+ OS << " encloses search range (exclusive bounds) when no match is found "
+ << "or\n"
+ << " there is an error, such as:\n"
+ << " - the errors mentioned above\n"
<< " - CHECK-NEXT not found (error)\n"
<< " - CHECK-NOT not found (success, reported if -vv)\n"
<< " - CHECK-DAG not found after discarded matches (error)\n"
@@ -381,7 +381,8 @@ struct InputAnnotation {
unsigned InputLine;
/// The column range (one-origin indexing, inclusive boundaries) in which to
/// mark the input line. If \c InputLastCol is \c UINT_MAX, the rest of the
- /// input line should be marked.
+ /// input line should be marked, and another \c InputAnnotation will continue
+ /// it on the next line.
unsigned InputFirstCol, InputLastCol;
/// The marker to use.
MarkerStyle Marker;
@@ -513,14 +514,55 @@ struct MarkerRange {
/// \p Range specifies the \a logical input range to be depicted by annotation
/// markers \a drawn at the resulting \c MarkerRange.
///
- /// If \p Range is an empty range, then the resulting \c MarkerRange is
- /// expanded to a single character. This avoids a missing marker for an empty
- /// range, but it means the markers for a single-character range are
- /// indistinguishable from markers for an empty range.
- MarkerRange(const SourceMgr &SM, SMRange Range) {
- // Range has an inclusive start as MarkerRange requires.
+ /// \a how that drawing depicts that logical input range is determined by
+ /// \p ShowExclusive. The drawing specifies either:
+ /// - The \a inclusive start and end bounds of the logical input range if
+ /// \p !ShowExclusive. In this case:
+ /// - If the logical input range is empty, then the resulting \c MarkerRange
+ /// is expanded to a single character. This avoids a missing marker, but
+ /// it means the markers for a single-character range are
+ /// indistinguishable from markers for an empty range.
+ /// - The first and last location of the \c MarkerRange are always real
+ /// locations in the input (never, for example, column 0).
+ /// - The \a exclusive start and end bounds of the logical input range if
+ /// \p ShowExclusive. In this case:
+ /// - The \c MarkerRange length is then always at least two because
+ /// exclusive boundaries never occupy the same location.
+ /// - If a \p Range boundary is an input line boundary, the corresponding
+ /// \c MarkerRange column might be in the line's margin (e.g., column 0)
+ /// to avoid placing a marker on an adjacent line. That decision can make
+ /// input annotations more concise (more line-liners) and easier to read.
+ /// It also avoids non-existent adjacent lines (e.g., line 0) that are not
+ /// depicted in the input dump.
+ MarkerRange(const SourceMgr &SM, SMRange Range, bool ShowExclusive = false) {
+ // Given an SMRange representing the range of text "range of text", the
+ // following example compares how it and the resulting MarkerRange encode
+ // the same start (s) and end (e) bounds:
+ //
+ // ....range of text....
+ // s e SMRange
+ // s e MarkerRange with ShowExclusive=false
+ // s e MarkerRange with ShowExclusive=true
+ if (ShowExclusive) {
+ // Range has inclusive start, but ShowExclusive requires exclusive start.
+ First = SM.getLineAndColumn(Range.Start);
+ --First.Col;
+ // Range has an exclusive end as ShowExclusive requires. If it is at a
+ // line boundary, it is at the start of the next line, so normally move it
+ // to the end of the previous line. For an empty range, do not do that as
+ // we do not want an end marker on the line before the start marker.
+ if (Range.Start == Range.End) {
+ Last = SM.getLineAndColumn(Range.End);
+ } else {
+ SMLoc EndLoc = SMLoc::getFromPointer(Range.End.getPointer() - 1);
+ Last = SM.getLineAndColumn(EndLoc);
+ ++Last.Col;
+ }
+ return;
+ }
+ // Range has an inclusive start as !ShowExclusive requires.
First = SM.getLineAndColumn(Range.Start);
- // Range has an exclusive end, but MarkerRange requires an inclusive end.
+ // Range has an exclusive end, but !ShowExclusive requires an inclusive end.
if (Range.Start == Range.End) {
// Convert the empty range to a one-character range.
Last = First;
@@ -541,6 +583,124 @@ struct MarkerRange {
/// Return a range marking only the first character.
MarkerRange truncate() const { return {First, First}; }
};
+
+/// Emits search range annotations for each \c MatchResultDiag as it is
+/// encountered.
+///
+/// In some cases, it emits a single, one-line annotation. Otherwise, it emits
+/// separate annotations for the start and end of the search range. The logic
+/// for making this determination is encapsulated in static member functions.
+class SearchRangeAnnotator {
+private:
+ const SourceMgr &SM;
+ /// Where to append search range annotations.
+ std::vector<InputAnnotation> &Annotations;
+ /// A globally unique index for this annotation.
+ unsigned &LabelIndexGlobal;
+ /// The most recent \c MatchResultDiag, or \c nullptr if all search range
+ /// annotations have been added already for the most recent
+ /// \c MatchResultDiag.
+ const MatchResultDiag *MRD;
+ /// The labeler for \c MRD. Stored by value as the original labeler might be
+ /// destroyed by the time we call \c endDiags here.
+ InputAnnotationLabeler Labeler;
+ /// Would a \c SearchRangeAnnotator make any search range annotations for
+ /// \p MRD?
+ static bool makesAnnotationsFor(const MatchResultDiag &MRD) {
+ return !MRD.getMatchRange() || MRD.isError();
+ }
+ /// Assuming \c makesAnnotationsFor(MRD), would a \c SearchRangeAnnotator make
+ /// a one-line search range annotation for \p MRD? Either way, the search
+ /// range computed for \p MRD is stored in \p SearchRange.
+ static bool makesOneLinerFor(const SourceMgr &SM, const MatchResultDiag &MRD,
+ MarkerRange &SearchRange) {
+ assert(makesAnnotationsFor(MRD) &&
+ "expected makesAnnotationsFor to be checked first");
+ SearchRange = {SM, MRD.getSearchRange(), /*ShowExclusive=*/true};
+ return SearchRange.isSingleLine();
+ }
+ /// Make the next annotation for the current \c MatchResultDiag.
+ void makeAnnotation(bool Start) {
+ InputAnnotation &A = Annotations.emplace_back();
+ A.LabelIndexGlobal = LabelIndexGlobal++;
+ Labeler.generateLabel(A.Label);
+ A.IsFirstLine = true;
+ A.FoundAndExpectedMatch = false;
+ MarkerRange SearchRange;
+ if (makesOneLinerFor(SM, *MRD, SearchRange)) {
+ assert(Start && "expected no search range end annotation for one-liner");
+ A.InputLine = SearchRange.getFirstLoc().Line;
+ A.InputFirstCol = SearchRange.getFirstLoc().Col;
+ A.InputLastCol = SearchRange.getLastLoc().Col;
+ MatchCustomNoteDiag NoteDiag("search range (exclusive bounds)");
+ NoteDiag.setMatchResultDiag(MRD);
+ A.Marker = getMarker(NoteDiag);
+ A.Marker.Head = '{';
+ A.Marker.Mid = ' ';
+ A.Marker.Tail = '}';
+ MRD = nullptr;
+ return;
+ }
+ // We have separate annotations for start and end.
+ MarkerRange::Loc Loc =
+ Start ? SearchRange.getFirstLoc() : SearchRange.getLastLoc();
+ A.InputLine = Loc.Line;
+ A.InputFirstCol = A.InputLastCol = Loc.Col;
+ MatchCustomNoteDiag NoteDiag(std::string("search range ") +
+ (Start ? "start" : "end") + " (exclusive)");
+ NoteDiag.setMatchResultDiag(MRD);
+ A.Marker = getMarker(NoteDiag);
+ A.Marker.Head = Start ? '{' : '}';
+ }
+
+public:
+ /// How many search range annotations would a \c SearchRangeAnnotator generate
+ /// for \c MRD?
+ static unsigned countAnnotationsFor(const SourceMgr &SM,
+ const MatchResultDiag &MRD) {
+ if (!makesAnnotationsFor(MRD))
+ return 0;
+ MarkerRange SearchRange;
+ return makesOneLinerFor(SM, MRD, SearchRange) ? 1 : 2;
+ }
+ /// Are the search range annotations generated by a \c SearchRangeAnnotator
+ /// sufficient for \p MRD? Otherwise, \p MRD needs to be rendered as a
+ /// separate annotation.
+ static bool sufficesFor(const MatchResultDiag &MRD) {
+ return makesAnnotationsFor(MRD) && getMarker(MRD).Note.empty();
+ }
+ /// \p Annotations is where this annotator should append search range
+ /// annotations. \p LabelIndexGlobal is the globally unique index of the next
+ /// annotation label to be generated. This annotator will increment it when
+ /// generating a new label for a search range annotation.
+ SearchRangeAnnotator(const SourceMgr &SM,
+ std::vector<InputAnnotation> &Annotations,
+ unsigned &LabelIndexGlobal)
+ : SM(SM), Annotations(Annotations), LabelIndexGlobal(LabelIndexGlobal),
+ MRD(nullptr) {}
+ /// Emit any search range start annotation or one-line search range annotation
+ /// for \p MRDNew using its labeler \p LabelerNew. This annotator will emit
+ /// any search range end annotation at the next call to \c newMatchResultDiag
+ /// or \c endDiags.
+ void newMatchResultDiag(const MatchResultDiag &MRDNew,
+ InputAnnotationLabeler LabelerNew) {
+ if (MRD) {
+ makeAnnotation(/*Start=*/false);
+ MRD = nullptr;
+ }
+ if (makesAnnotationsFor(MRDNew)) {
+ MRD = &MRDNew;
+ Labeler = LabelerNew;
+ makeAnnotation(/*Start=*/true);
+ }
+ }
+ /// Emit any search range end annotation for the final \c MatchResultDiag
+ /// passed to \c newMatchResultDiag.
+ void endDiags() {
+ if (MRD)
+ makeAnnotation(/*Start=*/false);
+ }
+};
} // namespace
static void
@@ -560,12 +720,22 @@ buildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
// series of zero or more MatchNoteDiag's. Each such MatchResultDiag and its
// MatchNoteDiag series can require multiple labels.
std::map<SMLoc, unsigned, CompareSMLoc> LabelCountPerPattern;
- for (const FileCheckDiag &Diag : Diags)
- ++LabelCountPerPattern[Diag.getMatchResultDiag().getCheckLoc()];
+ for (const FileCheckDiag &Diag : Diags) {
+ unsigned &C = LabelCountPerPattern[Diag.getMatchResultDiag().getCheckLoc()];
+ if (const MatchResultDiag *MRD = dyn_cast<MatchResultDiag>(&Diag)) {
+ C += SearchRangeAnnotator::countAnnotationsFor(SM, *MRD);
+ if (!SearchRangeAnnotator::sufficesFor(*MRD))
+ ++C;
+ } else {
+ ++C;
+ }
+ }
// How many labels have we generated so far per check pattern?
std::map<SMLoc, unsigned, CompareSMLoc> LabelIndexPerPattern;
// How many total labels have we generated so far?
unsigned LabelIndexGlobal = 0;
+ SearchRangeAnnotator TheSearchRangeAnnotator(SM, Annotations,
+ LabelIndexGlobal);
// What's the widest label we've generated so far?
LabelWidthGlobal = 0;
// The labeler for the current MatchResultDiag and its MatchNoteDiag series.
@@ -578,6 +748,9 @@ buildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
LabelCountPerPattern[MRD->getCheckLoc()] > 1
? &LabelIndexPerPattern[MRD->getCheckLoc()]
: nullptr);
+ TheSearchRangeAnnotator.newMatchResultDiag(*MRD, CurLabeler);
+ if (SearchRangeAnnotator::sufficesFor(*MRD))
+ continue;
}
// Build label that is unique for this input annotation before it is
@@ -596,18 +769,13 @@ buildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
A.FoundAndExpectedMatch = true;
}
- // If Diag has a match range, position the marker there. If it is a
- // MatchNoneDiag, position the marker at its search range. Otherwise,
+ // If Diag has a match range, position the marker there. Otherwise,
// position the marker at the start of the most recent MatchResultDiag, with
// which it is associated.
MarkerRange InputRange;
if (Diag.getMatchRange()) {
InputRange = MarkerRange(SM, *Diag.getMatchRange());
- } else if (const MatchNoneDiag *MND = dyn_cast<MatchNoneDiag>(&Diag)) {
- InputRange = MarkerRange(SM, MND->getSearchRange());
} else {
- assert(isa<MatchNoteDiag>(Diag) &&
- "expected only MatchNoteDiag to have no input range");
const MatchResultDiag &MRD = Diag.getMatchResultDiag();
InputRange = MRD.getMatchRange() ? MarkerRange(SM, *MRD.getMatchRange())
: MarkerRange(SM, MRD.getSearchRange());
@@ -647,6 +815,7 @@ buildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
}
}
}
+ TheSearchRangeAnnotator.endDiags();
}
static unsigned FindInputLineInFilter(
@@ -864,17 +1033,20 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
AnnotationItr->InputLine == Line) {
WithColor COS(*LineOS, AnnotationItr->Marker.Color, /*Bold=*/true,
/*BG=*/false, TheColorMode);
- // The two spaces below are where the ": " appears on input lines.
- COS << left_justify(AnnotationItr->Label, LabelWidthGlobal) << " ";
+ // The space below aligns with the ":" on the input line.
+ COS << left_justify(AnnotationItr->Label, LabelWidthGlobal) << " ";
unsigned Col;
- for (Col = 1; Col < AnnotationItr->InputFirstCol; ++Col)
+ // A search range annotation at the beginning of the line starts at column
+ // 0 because it is an exclusive boundary.
+ for (Col = 0; Col < AnnotationItr->InputFirstCol; ++Col)
COS << ' ';
COS << AnnotationItr->Marker.Head;
// If InputLastCol==UINT_MAX, stop at InputLineWidth.
for (++Col; Col < AnnotationItr->InputLastCol && Col <= InputLineWidth;
++Col)
COS << AnnotationItr->Marker.Mid;
- if (Col <= AnnotationItr->InputLastCol && Col <= InputLineWidth) {
+ if (Col <= AnnotationItr->InputLastCol &&
+ AnnotationItr->InputLastCol != UINT_MAX) {
COS << AnnotationItr->Marker.Tail;
++Col;
}
@@ -884,7 +1056,7 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
// put the note right after the marker, subsequent annotations for the
// same input line might appear to mark this note instead of the input
// line.
- for (; Col <= InputLineWidth; ++Col)
+ for (; Col <= InputLineWidth + 1; ++Col)
COS << ' ';
COS << ' ' << Note;
}
>From cb8dacd313cc5e3bc0141ce0d95cd4060fc1d733 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 18 May 2026 10:54:25 -0400
Subject: [PATCH 04/18] Fix incorrect comment
---
.../match-time-error-propagation/matched-expected-pattern.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt b/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
index 3388a53273918..66304b0368fd9 100644
--- a/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
+++ b/llvm/test/FileCheck/match-time-error-propagation/matched-expected-pattern.txt
@@ -1,5 +1,5 @@
; Check handling of match-time diagnostics for invalid patterns (e.g.,
-; substitution overflow) in the case of expected patterns (e.g., CHECK-NOT) that
+; substitution overflow) in the case of expected patterns (e.g., CHECK) that
; otherwise have no errors.
RUN: echo > %t.chk 'CHECK: [[#122+1]] [[STR:abc]] [[#NUM:0x0 - 0x1]]'
>From f9fbf2222585792c7ecb7271b24ad698b7808c8d Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 18 May 2026 11:08:45 -0400
Subject: [PATCH 05/18] Port PR #198138's new tests here
That makes it easier to see the benefit of PR #198138.
---
.../check-label-follows.txt | 67 ++++++++++++
.../check-next-same.txt | 54 ++++++++++
.../search-range-annotations/check-not.txt | 101 ++++++++++++++++++
3 files changed, 222 insertions(+)
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
new file mode 100644
index 0000000000000..08b266a37aa37
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
@@ -0,0 +1,67 @@
+; Because -dump-input-filter=error includes a failed directive's search range
+; end, input line 15 below is revealed, and -dump-input-context=2 reveals the
+; surrounding lines. Those lines are where the actual problem is: the "host
+; triples:" header is off by one. Sometimes the key to understanding a
+; directive's failure is where the following CHECK-LABEL matched because it
+; limits the search range. FIXME: Of course, those lines will not be revealed
+; until braced search ranges are actually implemented.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefix=DMP
+
+ DMP:<<<<<<
+DMP-NEXT: 1: offload triples:
+DMP-NEXT:label:1'0 ^~~~~~~~~~~~~~~~
+DMP-NEXT:label:1'1 ^~~~~~~~~~~~~~~~
+DMP-NEXT:check:2'0 X error: no match found
+DMP-NEXT: 2: - x86_64-linux-gnu
+DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~
+DMP-NEXT:check:2'1 ? possible intended match
+DMP-NEXT: 3: - x86_64-unknown-linux-gnu
+DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+DMP-NEXT: 4: - x86_64-pc-linux-gnu
+DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT:>>>>>>
+
+;--- check.txt
+CHECK-LABEL: offload triples:
+ CHECK: nvptx64-nvidia-cuda
+CHECK-LABEL: host triples:
+
+;--- input.txt
+offload triples:
+- x86_64-linux-gnu
+- x86_64-unknown-linux-gnu
+- x86_64-pc-linux-gnu
+- x86_64-redhat-linux6E
+- x86_64-redhat-linux
+- x86_64-suse-linux
+- x86_64-manbo-linux-gnu
+- x86_64-linux-gnu
+- x86_64-slackware-linux
+- x86_64-unknown-linux
+- x86_64-amazon-linux
+- x86_64-linux-android
+- amdgcn-amd-amdhsa
+host triples:
+- nvptx64-nvidia-cuda
+- x86_64-linux-gnu
+- x86_64-unknown-linux-gnu
+- x86_64-pc-linux-gnu
+- x86_64-redhat-linux6E
+- x86_64-redhat-linux
+- x86_64-suse-linux
+- x86_64-manbo-linux-gnu
+- x86_64-linux-gnu
+- x86_64-slackware-linux
+- x86_64-unknown-linux
+- x86_64-amazon-linux
+- x86_64-linux-android
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
new file mode 100644
index 0000000000000..bfb4a8fa5305b
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
@@ -0,0 +1,54 @@
+; Because -dump-input-filter=error includes a failed directive's search range
+; start, input line 1 below is revealed, and -dump-input-context=2 reveals lines
+; 2-3. Those lines are where the actual problem is because that is where the
+; CHECK-NEXT/CHECK-SAME directive was expected to match but did not. The line
+; where CHECK-NEXT/CHECK-SAME actually matched, line 13, is typically less
+; useful information. FIXME: Of course, the former lines will not be revealed
+; until braced search ranges are actually implemented.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/next.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_NEXT
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/same.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_SAME
+
+ DMP:<<<<<<
+ DMP-NEXT: .
+ DMP-NEXT: .
+ DMP-NEXT: .
+ DMP-NEXT: 11: foo9
+ DMP-NEXT: 12: foo10
+ DMP-NEXT: 13: end
+DMP_NEXT-NEXT:next:2 !~~ error: match on wrong line
+DMP_SAME-NEXT:same:2 !~~ error: match on wrong line
+ DMP-NEXT:>>>>>>
+
+;--- next.txt
+CHECK: start
+CHECK-NEXT: end
+
+;--- same.txt
+CHECK: start
+CHECK-SAME: end
+
+;--- input.txt
+start
+foo0
+foo1
+foo2
+foo3
+foo4
+foo5
+foo6
+foo7
+foo8
+foo9
+foo10
+end
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
new file mode 100644
index 0000000000000..96f8705e71a7b
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
@@ -0,0 +1,101 @@
+; Because -dump-input-filter=error includes a failed directive's search range,
+; input lines 1 and 62 below are revealed, and -dump-input-context=2 reveals the
+; surrounding lines. Even with only line 1, it looks like the host list
+; includes a GPU triple. Line 62 and its context reveals we have an
+; accidentally nested list. Often the key to understanding a CHECK-NOT failure
+; is where the directives before and after it matched because those establish
+; the search range. FIXME: Of course, those lines will not be revealed until
+; braced search ranges are actually implemented.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefix=DMP
+
+ DMP:<<<<<<
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: 42: x86_64-amazon-linux
+DMP-NEXT: 43: x86_64-linux-android
+DMP-NEXT: 44: nvptx64-nvidia-cuda
+DMP-NEXT:not:2 !~~~~~~~~~~~~~~~~~~ error: no match expected
+DMP-NEXT: 45: i686-linux-gnu
+DMP-NEXT: 46: i686-pc-linux-gnu
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT:>>>>>>
+
+;--- check.txt
+CHECK: <triples kind="host">
+CHECK-NOT: nvptx64-nvidia-cuda
+CHECK: </triples>
+
+;--- input.txt
+<triples kind="host">
+ x86_64-linux-gnu
+ x86_64-unknown-linux-gnu
+ x86_64-pc-linux-gnu
+ x86_64-redhat-linux6E
+ x86_64-redhat-linux
+ x86_64-suse-linux
+ x86_64-manbo-linux-gnu
+ x86_64-linux-gnu
+ x86_64-slackware-linux
+ x86_64-unknown-linux
+ x86_64-amazon-linux
+ x86_64-linux-android
+ i686-linux-gnu
+ i686-pc-linux-gnu
+ i486-linux-gnu
+ i386-linux-gnu
+ i386-redhat-linux6E
+ i686-redhat-linux
+ i586-redhat-linux
+ i386-redhat-linux
+ i586-suse-linux
+ i486-slackware-linux
+ i686-montavista-linux
+ i586-linux-gnu
+ i686-linux-android
+ i386-gnu
+ i486-gnu
+ i586-gnu
+ i686-gnu
+<triples kind="offload">
+ x86_64-linux-gnu
+ x86_64-unknown-linux-gnu
+ x86_64-pc-linux-gnu
+ x86_64-redhat-linux6E
+ x86_64-redhat-linux
+ x86_64-suse-linux
+ x86_64-manbo-linux-gnu
+ x86_64-linux-gnu
+ x86_64-slackware-linux
+ x86_64-unknown-linux
+ x86_64-amazon-linux
+ x86_64-linux-android
+ nvptx64-nvidia-cuda
+ i686-linux-gnu
+ i686-pc-linux-gnu
+ i486-linux-gnu
+ i386-linux-gnu
+ i386-redhat-linux6E
+ i686-redhat-linux
+ i586-redhat-linux
+ i386-redhat-linux
+ i586-suse-linux
+ i486-slackware-linux
+ i686-montavista-linux
+ i586-linux-gnu
+ i686-linux-android
+ i386-gnu
+ i486-gnu
+ i586-gnu
+ i686-gnu
+</triples>
+</triples>
>From 21d1e2117b40b7d78d399e5999b2a5d10e80f8eb Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 18 May 2026 11:41:30 -0400
Subject: [PATCH 06/18] Replace MarkerRange::truncate with new constructor
`truncate` was ok before this patch, but now it is unclear what
happens if the original `MarkerRange` had `ShowExclusive==true`. In
that case, it seems like maybe we should end up with a range marking
the characters before and after the one character, but instead we
always end up with a single marker at just the one character.
Currently, `truncate` is never called for that case, but it is better
to keep the API clear for the future. Constructing an entirely new
`MarkerRange` makes it clearer to me that it knows nothing about the
old `MarkerRange`'s `ShowExclusive`. If needed later, we can add a
`ShowExclusive` parameter to the new constructor.
---
llvm/utils/FileCheck/FileCheck.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 808df9a41029f..4d8a036a31903 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -574,14 +574,15 @@ struct MarkerRange {
Last = SM.getLineAndColumn(EndLoc);
}
}
+ /// \p Loc specifies a single input character to be marked by a single
+ /// annotation marker character.
+ MarkerRange(Loc OneChar) : First(OneChar), Last(OneChar) {}
/// Is the marker range contained on a single line?
bool isSingleLine() const { return First.Line == Last.Line; }
/// Get the location of the first marked character.
Loc getFirstLoc() const { return First; }
/// Get the location of the last marked character.
Loc getLastLoc() const { return Last; }
- /// Return a range marking only the first character.
- MarkerRange truncate() const { return {First, First}; }
};
/// Emits search range annotations for each \c MatchResultDiag as it is
@@ -779,7 +780,7 @@ buildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
const MatchResultDiag &MRD = Diag.getMatchResultDiag();
InputRange = MRD.getMatchRange() ? MarkerRange(SM, *MRD.getMatchRange())
: MarkerRange(SM, MRD.getSearchRange());
- InputRange = InputRange.truncate();
+ InputRange = MarkerRange(InputRange.getFirstLoc());
assert(A.Marker.Head == ' ' && "expected no marker for no match range");
}
>From 8765fbeaed66a02f6aebfa23d6c83478dc588f7a Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Thu, 21 May 2026 11:56:25 -0400
Subject: [PATCH 07/18] Revert "Port PR #198138's new tests here"
This reverts commit f9fbf2222585792c7ecb7271b24ad698b7808c8d.
---
.../check-label-follows.txt | 67 ------------
.../check-next-same.txt | 54 ----------
.../search-range-annotations/check-not.txt | 101 ------------------
3 files changed, 222 deletions(-)
delete mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
delete mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
delete mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
deleted file mode 100644
index 08b266a37aa37..0000000000000
--- a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-; Because -dump-input-filter=error includes a failed directive's search range
-; end, input line 15 below is revealed, and -dump-input-context=2 reveals the
-; surrounding lines. Those lines are where the actual problem is: the "host
-; triples:" header is off by one. Sometimes the key to understanding a
-; directive's failure is where the following CHECK-LABEL matched because it
-; limits the search range. FIXME: Of course, those lines will not be revealed
-; until braced search ranges are actually implemented.
-
-RUN: rm -rf %t
-RUN: split-file %s %t
-
-RUN: %ProtectFileCheckOutput \
-RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
-RUN: -dump-input-filter=error 2>&1 | \
-RUN: FileCheck %s -match-full-lines -check-prefix=DMP
-
- DMP:<<<<<<
-DMP-NEXT: 1: offload triples:
-DMP-NEXT:label:1'0 ^~~~~~~~~~~~~~~~
-DMP-NEXT:label:1'1 ^~~~~~~~~~~~~~~~
-DMP-NEXT:check:2'0 X error: no match found
-DMP-NEXT: 2: - x86_64-linux-gnu
-DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~
-DMP-NEXT:check:2'1 ? possible intended match
-DMP-NEXT: 3: - x86_64-unknown-linux-gnu
-DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-DMP-NEXT: 4: - x86_64-pc-linux-gnu
-DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~
-DMP-NEXT: .
-DMP-NEXT: .
-DMP-NEXT: .
-DMP-NEXT:>>>>>>
-
-;--- check.txt
-CHECK-LABEL: offload triples:
- CHECK: nvptx64-nvidia-cuda
-CHECK-LABEL: host triples:
-
-;--- input.txt
-offload triples:
-- x86_64-linux-gnu
-- x86_64-unknown-linux-gnu
-- x86_64-pc-linux-gnu
-- x86_64-redhat-linux6E
-- x86_64-redhat-linux
-- x86_64-suse-linux
-- x86_64-manbo-linux-gnu
-- x86_64-linux-gnu
-- x86_64-slackware-linux
-- x86_64-unknown-linux
-- x86_64-amazon-linux
-- x86_64-linux-android
-- amdgcn-amd-amdhsa
-host triples:
-- nvptx64-nvidia-cuda
-- x86_64-linux-gnu
-- x86_64-unknown-linux-gnu
-- x86_64-pc-linux-gnu
-- x86_64-redhat-linux6E
-- x86_64-redhat-linux
-- x86_64-suse-linux
-- x86_64-manbo-linux-gnu
-- x86_64-linux-gnu
-- x86_64-slackware-linux
-- x86_64-unknown-linux
-- x86_64-amazon-linux
-- x86_64-linux-android
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
deleted file mode 100644
index bfb4a8fa5305b..0000000000000
--- a/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-; Because -dump-input-filter=error includes a failed directive's search range
-; start, input line 1 below is revealed, and -dump-input-context=2 reveals lines
-; 2-3. Those lines are where the actual problem is because that is where the
-; CHECK-NEXT/CHECK-SAME directive was expected to match but did not. The line
-; where CHECK-NEXT/CHECK-SAME actually matched, line 13, is typically less
-; useful information. FIXME: Of course, the former lines will not be revealed
-; until braced search ranges are actually implemented.
-
-RUN: rm -rf %t
-RUN: split-file %s %t
-
-RUN: %ProtectFileCheckOutput \
-RUN: not FileCheck -dump-input-context=2 -v %t/next.txt < %t/input.txt \
-RUN: -dump-input-filter=error 2>&1 | \
-RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_NEXT
-
-RUN: %ProtectFileCheckOutput \
-RUN: not FileCheck -dump-input-context=2 -v %t/same.txt < %t/input.txt \
-RUN: -dump-input-filter=error 2>&1 | \
-RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_SAME
-
- DMP:<<<<<<
- DMP-NEXT: .
- DMP-NEXT: .
- DMP-NEXT: .
- DMP-NEXT: 11: foo9
- DMP-NEXT: 12: foo10
- DMP-NEXT: 13: end
-DMP_NEXT-NEXT:next:2 !~~ error: match on wrong line
-DMP_SAME-NEXT:same:2 !~~ error: match on wrong line
- DMP-NEXT:>>>>>>
-
-;--- next.txt
-CHECK: start
-CHECK-NEXT: end
-
-;--- same.txt
-CHECK: start
-CHECK-SAME: end
-
-;--- input.txt
-start
-foo0
-foo1
-foo2
-foo3
-foo4
-foo5
-foo6
-foo7
-foo8
-foo9
-foo10
-end
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
deleted file mode 100644
index 96f8705e71a7b..0000000000000
--- a/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
+++ /dev/null
@@ -1,101 +0,0 @@
-; Because -dump-input-filter=error includes a failed directive's search range,
-; input lines 1 and 62 below are revealed, and -dump-input-context=2 reveals the
-; surrounding lines. Even with only line 1, it looks like the host list
-; includes a GPU triple. Line 62 and its context reveals we have an
-; accidentally nested list. Often the key to understanding a CHECK-NOT failure
-; is where the directives before and after it matched because those establish
-; the search range. FIXME: Of course, those lines will not be revealed until
-; braced search ranges are actually implemented.
-
-RUN: rm -rf %t
-RUN: split-file %s %t
-
-RUN: %ProtectFileCheckOutput \
-RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
-RUN: -dump-input-filter=error 2>&1 | \
-RUN: FileCheck %s -match-full-lines -check-prefix=DMP
-
- DMP:<<<<<<
-DMP-NEXT: .
-DMP-NEXT: .
-DMP-NEXT: .
-DMP-NEXT: 42: x86_64-amazon-linux
-DMP-NEXT: 43: x86_64-linux-android
-DMP-NEXT: 44: nvptx64-nvidia-cuda
-DMP-NEXT:not:2 !~~~~~~~~~~~~~~~~~~ error: no match expected
-DMP-NEXT: 45: i686-linux-gnu
-DMP-NEXT: 46: i686-pc-linux-gnu
-DMP-NEXT: .
-DMP-NEXT: .
-DMP-NEXT: .
-DMP-NEXT:>>>>>>
-
-;--- check.txt
-CHECK: <triples kind="host">
-CHECK-NOT: nvptx64-nvidia-cuda
-CHECK: </triples>
-
-;--- input.txt
-<triples kind="host">
- x86_64-linux-gnu
- x86_64-unknown-linux-gnu
- x86_64-pc-linux-gnu
- x86_64-redhat-linux6E
- x86_64-redhat-linux
- x86_64-suse-linux
- x86_64-manbo-linux-gnu
- x86_64-linux-gnu
- x86_64-slackware-linux
- x86_64-unknown-linux
- x86_64-amazon-linux
- x86_64-linux-android
- i686-linux-gnu
- i686-pc-linux-gnu
- i486-linux-gnu
- i386-linux-gnu
- i386-redhat-linux6E
- i686-redhat-linux
- i586-redhat-linux
- i386-redhat-linux
- i586-suse-linux
- i486-slackware-linux
- i686-montavista-linux
- i586-linux-gnu
- i686-linux-android
- i386-gnu
- i486-gnu
- i586-gnu
- i686-gnu
-<triples kind="offload">
- x86_64-linux-gnu
- x86_64-unknown-linux-gnu
- x86_64-pc-linux-gnu
- x86_64-redhat-linux6E
- x86_64-redhat-linux
- x86_64-suse-linux
- x86_64-manbo-linux-gnu
- x86_64-linux-gnu
- x86_64-slackware-linux
- x86_64-unknown-linux
- x86_64-amazon-linux
- x86_64-linux-android
- nvptx64-nvidia-cuda
- i686-linux-gnu
- i686-pc-linux-gnu
- i486-linux-gnu
- i386-linux-gnu
- i386-redhat-linux6E
- i686-redhat-linux
- i586-redhat-linux
- i386-redhat-linux
- i586-suse-linux
- i486-slackware-linux
- i686-montavista-linux
- i586-linux-gnu
- i686-linux-android
- i386-gnu
- i486-gnu
- i586-gnu
- i686-gnu
-</triples>
-</triples>
>From 9263c11a053157ce739801df805b33015f3223f4 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Thu, 21 May 2026 12:01:27 -0400
Subject: [PATCH 08/18] [FileCheck] Extract new tests for braced search ranges
here
That makes it easier to see the benefit of PR #198138 there.
---
.../check-label-follows.txt | 67 ++++++++++++
.../check-next-same.txt | 54 ++++++++++
.../search-range-annotations/check-not.txt | 101 ++++++++++++++++++
3 files changed, 222 insertions(+)
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
create mode 100644 llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
new file mode 100644
index 0000000000000..08b266a37aa37
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
@@ -0,0 +1,67 @@
+; Because -dump-input-filter=error includes a failed directive's search range
+; end, input line 15 below is revealed, and -dump-input-context=2 reveals the
+; surrounding lines. Those lines are where the actual problem is: the "host
+; triples:" header is off by one. Sometimes the key to understanding a
+; directive's failure is where the following CHECK-LABEL matched because it
+; limits the search range. FIXME: Of course, those lines will not be revealed
+; until braced search ranges are actually implemented.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefix=DMP
+
+ DMP:<<<<<<
+DMP-NEXT: 1: offload triples:
+DMP-NEXT:label:1'0 ^~~~~~~~~~~~~~~~
+DMP-NEXT:label:1'1 ^~~~~~~~~~~~~~~~
+DMP-NEXT:check:2'0 X error: no match found
+DMP-NEXT: 2: - x86_64-linux-gnu
+DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~
+DMP-NEXT:check:2'1 ? possible intended match
+DMP-NEXT: 3: - x86_64-unknown-linux-gnu
+DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+DMP-NEXT: 4: - x86_64-pc-linux-gnu
+DMP-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT:>>>>>>
+
+;--- check.txt
+CHECK-LABEL: offload triples:
+ CHECK: nvptx64-nvidia-cuda
+CHECK-LABEL: host triples:
+
+;--- input.txt
+offload triples:
+- x86_64-linux-gnu
+- x86_64-unknown-linux-gnu
+- x86_64-pc-linux-gnu
+- x86_64-redhat-linux6E
+- x86_64-redhat-linux
+- x86_64-suse-linux
+- x86_64-manbo-linux-gnu
+- x86_64-linux-gnu
+- x86_64-slackware-linux
+- x86_64-unknown-linux
+- x86_64-amazon-linux
+- x86_64-linux-android
+- amdgcn-amd-amdhsa
+host triples:
+- nvptx64-nvidia-cuda
+- x86_64-linux-gnu
+- x86_64-unknown-linux-gnu
+- x86_64-pc-linux-gnu
+- x86_64-redhat-linux6E
+- x86_64-redhat-linux
+- x86_64-suse-linux
+- x86_64-manbo-linux-gnu
+- x86_64-linux-gnu
+- x86_64-slackware-linux
+- x86_64-unknown-linux
+- x86_64-amazon-linux
+- x86_64-linux-android
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
new file mode 100644
index 0000000000000..bfb4a8fa5305b
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-next-same.txt
@@ -0,0 +1,54 @@
+; Because -dump-input-filter=error includes a failed directive's search range
+; start, input line 1 below is revealed, and -dump-input-context=2 reveals lines
+; 2-3. Those lines are where the actual problem is because that is where the
+; CHECK-NEXT/CHECK-SAME directive was expected to match but did not. The line
+; where CHECK-NEXT/CHECK-SAME actually matched, line 13, is typically less
+; useful information. FIXME: Of course, the former lines will not be revealed
+; until braced search ranges are actually implemented.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/next.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_NEXT
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/same.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefixes=DMP,DMP_SAME
+
+ DMP:<<<<<<
+ DMP-NEXT: .
+ DMP-NEXT: .
+ DMP-NEXT: .
+ DMP-NEXT: 11: foo9
+ DMP-NEXT: 12: foo10
+ DMP-NEXT: 13: end
+DMP_NEXT-NEXT:next:2 !~~ error: match on wrong line
+DMP_SAME-NEXT:same:2 !~~ error: match on wrong line
+ DMP-NEXT:>>>>>>
+
+;--- next.txt
+CHECK: start
+CHECK-NEXT: end
+
+;--- same.txt
+CHECK: start
+CHECK-SAME: end
+
+;--- input.txt
+start
+foo0
+foo1
+foo2
+foo3
+foo4
+foo5
+foo6
+foo7
+foo8
+foo9
+foo10
+end
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
new file mode 100644
index 0000000000000..96f8705e71a7b
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-not.txt
@@ -0,0 +1,101 @@
+; Because -dump-input-filter=error includes a failed directive's search range,
+; input lines 1 and 62 below are revealed, and -dump-input-context=2 reveals the
+; surrounding lines. Even with only line 1, it looks like the host list
+; includes a GPU triple. Line 62 and its context reveals we have an
+; accidentally nested list. Often the key to understanding a CHECK-NOT failure
+; is where the directives before and after it matched because those establish
+; the search range. FIXME: Of course, those lines will not be revealed until
+; braced search ranges are actually implemented.
+
+RUN: rm -rf %t
+RUN: split-file %s %t
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t/check.txt < %t/input.txt \
+RUN: -dump-input-filter=error 2>&1 | \
+RUN: FileCheck %s -match-full-lines -check-prefix=DMP
+
+ DMP:<<<<<<
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: 42: x86_64-amazon-linux
+DMP-NEXT: 43: x86_64-linux-android
+DMP-NEXT: 44: nvptx64-nvidia-cuda
+DMP-NEXT:not:2 !~~~~~~~~~~~~~~~~~~ error: no match expected
+DMP-NEXT: 45: i686-linux-gnu
+DMP-NEXT: 46: i686-pc-linux-gnu
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT: .
+DMP-NEXT:>>>>>>
+
+;--- check.txt
+CHECK: <triples kind="host">
+CHECK-NOT: nvptx64-nvidia-cuda
+CHECK: </triples>
+
+;--- input.txt
+<triples kind="host">
+ x86_64-linux-gnu
+ x86_64-unknown-linux-gnu
+ x86_64-pc-linux-gnu
+ x86_64-redhat-linux6E
+ x86_64-redhat-linux
+ x86_64-suse-linux
+ x86_64-manbo-linux-gnu
+ x86_64-linux-gnu
+ x86_64-slackware-linux
+ x86_64-unknown-linux
+ x86_64-amazon-linux
+ x86_64-linux-android
+ i686-linux-gnu
+ i686-pc-linux-gnu
+ i486-linux-gnu
+ i386-linux-gnu
+ i386-redhat-linux6E
+ i686-redhat-linux
+ i586-redhat-linux
+ i386-redhat-linux
+ i586-suse-linux
+ i486-slackware-linux
+ i686-montavista-linux
+ i586-linux-gnu
+ i686-linux-android
+ i386-gnu
+ i486-gnu
+ i586-gnu
+ i686-gnu
+<triples kind="offload">
+ x86_64-linux-gnu
+ x86_64-unknown-linux-gnu
+ x86_64-pc-linux-gnu
+ x86_64-redhat-linux6E
+ x86_64-redhat-linux
+ x86_64-suse-linux
+ x86_64-manbo-linux-gnu
+ x86_64-linux-gnu
+ x86_64-slackware-linux
+ x86_64-unknown-linux
+ x86_64-amazon-linux
+ x86_64-linux-android
+ nvptx64-nvidia-cuda
+ i686-linux-gnu
+ i686-pc-linux-gnu
+ i486-linux-gnu
+ i386-linux-gnu
+ i386-redhat-linux6E
+ i686-redhat-linux
+ i586-redhat-linux
+ i386-redhat-linux
+ i586-suse-linux
+ i486-slackware-linux
+ i686-montavista-linux
+ i586-linux-gnu
+ i686-linux-android
+ i386-gnu
+ i486-gnu
+ i586-gnu
+ i686-gnu
+</triples>
+</triples>
>From c1148e7591d9e37e7fa56df515b013fcf709793f Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Fri, 22 May 2026 14:41:25 -0400
Subject: [PATCH 09/18] Use -COUNT-2 to make it clearer duplicate is intended
---
llvm/test/FileCheck/dump-input/annotations.txt | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/test/FileCheck/dump-input/annotations.txt b/llvm/test/FileCheck/dump-input/annotations.txt
index f928f3c3eaada..f887e218314e8 100644
--- a/llvm/test/FileCheck/dump-input/annotations.txt
+++ b/llvm/test/FileCheck/dump-input/annotations.txt
@@ -756,8 +756,7 @@
; REDEFINE: %{opts} =
; Verbose diagnostics are suppressed but not errors.
-; SUBST-NEG:{{.*}}error:{{.*}}
-; SUBST-NEG:{{.*}}error:{{.*}}
+; SUBST-NEG-COUNT-2:{{.*}}error:{{.*}}
; SUBST-NEG:<<<<<<
; SUBST-NEG-NEXT: 1: def-match1 def-nomatch
>From dd329096c491dc74469caa0a52cad06ceef1a8b8 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 15 Jun 2026 20:32:02 -0400
Subject: [PATCH 10/18] Address reviewer comments
---
llvm/utils/FileCheck/FileCheck.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 4d8a036a31903..a210f2adc149f 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -379,10 +379,11 @@ struct InputAnnotation {
/// be different from the starting line of the original diagnostic if
/// !IsFirstLine.
unsigned InputLine;
- /// The column range (one-origin indexing, inclusive boundaries) in which to
- /// mark the input line. If \c InputLastCol is \c UINT_MAX, the rest of the
- /// input line should be marked, and another \c InputAnnotation will continue
- /// it on the next line.
+ /// The column range (inclusive boundaries) in which to mark the input line.
+ /// A value of one indicates the first column of the actual input, and a
+ /// value of zero indicates the left margin. If \c InputLastCol is
+ /// \c UINT_MAX, the rest of the input line should be marked, and another
+ /// \c InputAnnotation will continue it on the next line.
unsigned InputFirstCol, InputLastCol;
/// The marker to use.
MarkerStyle Marker;
@@ -506,7 +507,6 @@ struct MarkerRange {
Loc First;
/// Location of the last marked character.
Loc Last;
- MarkerRange(Loc First, Loc Last) : First(First), Last(Last) {}
public:
/// Make an invalid range to be overwritten before being used.
>From ef3cffcb7b190b4ab44e593a019e33eeff793458 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 15 Jun 2026 20:37:43 -0400
Subject: [PATCH 11/18] Remove trailing whitespace
---
llvm/utils/FileCheck/FileCheck.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index a210f2adc149f..412dd69f5dae6 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -381,8 +381,8 @@ struct InputAnnotation {
unsigned InputLine;
/// The column range (inclusive boundaries) in which to mark the input line.
/// A value of one indicates the first column of the actual input, and a
- /// value of zero indicates the left margin. If \c InputLastCol is
- /// \c UINT_MAX, the rest of the input line should be marked, and another
+ /// value of zero indicates the left margin. If \c InputLastCol is
+ /// \c UINT_MAX, the rest of the input line should be marked, and another
/// \c InputAnnotation will continue it on the next line.
unsigned InputFirstCol, InputLastCol;
/// The marker to use.
>From 2df672a9185516005556fadd0156d94083b60a84 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sat, 20 Jun 2026 12:47:44 -0400
Subject: [PATCH 12/18] [FileCheck] Use default colors in input dumps
This patch makes two improvements to colors used in FileCheck input
dumps:
1. Without this patch, input line numbers and ellipses have a
foreground color of black, which is hard to see in a terminal with
a dark color theme. This patch changes that to the terminal's
default color.
2. Without this patch, the input text is accidentally set to bold when
neither `-v` or `-vv` is specified. Perhaps I never noticed
because I tend to always use `-vv`. This patch changes that to use
the terminal's default color.
Case 2 exposes a problem with LLVM's color implementation. Without
this patch, the call to `WithColor`'s constructor actually specifies
bold as `false`, but `WithColor` ignores that when the color is
`SAVEDCOLOR`. While it seems like that should be fixed, I am
concerned about the impact of such a fix on other tools that might
have come to inadvertently depend on the old behavior. For now, this
patch adds fixme comments to the color APIs.
I never found a nice way to write tests checking that FileCheck emits
expected color codes. Do I really want to hardcode the exact codes
into tests? The best I came up with in the past was merely checking
for extra characters, as in `llvm/test/FileCheck/opt-color.txt`, but
that does not really help here as we already expect extra characters
for colors. Maybe we need a script that translates color codes into
some kind of plain text format with symbolic names instead of codes.
That seems like too much work for this fix, so this patch has no test
changes.
---
llvm/include/llvm/Support/WithColor.h | 4 ++++
llvm/include/llvm/Support/raw_ostream.h | 2 ++
llvm/utils/FileCheck/FileCheck.cpp | 18 ++++++++++++++----
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/Support/WithColor.h b/llvm/include/llvm/Support/WithColor.h
index 2835e179e6195..febf211c3a391 100644
--- a/llvm/include/llvm/Support/WithColor.h
+++ b/llvm/include/llvm/Support/WithColor.h
@@ -68,6 +68,8 @@ class WithColor {
/// @param Bold Bold/brighter text, default false
/// @param BG If true, change the background, default: change foreground
/// @param Mode Enable, disable or compute whether to use colors.
+ ///
+ /// FIXME: If Color == SAVEDCOLOR, Bold == false is currently ignored.
LLVM_CTOR_NODISCARD WithColor(
raw_ostream &OS, raw_ostream::Colors Color = raw_ostream::SAVEDCOLOR,
bool Bold = false, bool BG = false, ColorMode Mode = ColorMode::Auto)
@@ -117,6 +119,8 @@ class WithColor {
/// change only the bold attribute, and keep colors untouched
/// @param Bold Bold/brighter text, default false
/// @param BG If true, change the background, default: change foreground
+ ///
+ /// FIXME: If Color == SAVEDCOLOR, Bold == false is currently ignored.
LLVM_ABI WithColor &changeColor(raw_ostream::Colors Color, bool Bold = false,
bool BG = false);
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index 70916d8e4adb0..1e66052c849b7 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -332,6 +332,8 @@ class LLVM_ABI raw_ostream {
/// @param Bold bold/brighter text, default false
/// @param BG if true change the background, default: change foreground
/// @returns itself so it can be used within << invocations
+ ///
+ /// FIXME: If Color == SAVEDCOLOR, Bold == false is currently ignored.
virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false,
bool BG = false);
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 8c760db50a375..5d389102af0c3 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -686,7 +686,7 @@ static void DumpEllipsisOrElidedLines(raw_ostream &OS, std::string &ElidedLines,
unsigned EllipsisLines = 3;
if (EllipsisLines < StringRef(ElidedLines).count('\n')) {
for (unsigned i = 0; i < EllipsisLines; ++i) {
- WithColor(OS, raw_ostream::BLACK, /*Bold=*/true)
+ WithColor(OS, raw_ostream::SAVEDCOLOR, /*Bold=*/true)
<< right_justify(".", LabelWidthGlobal);
OS << '\n';
}
@@ -810,7 +810,7 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
}
// Print right-aligned line number.
- WithColor(*LineOS, raw_ostream::BLACK, /*Bold=*/true, /*BF=*/false,
+ WithColor(*LineOS, raw_ostream::SAVEDCOLOR, /*Bold=*/true, /*BG=*/false,
TheColorMode)
<< format_decimal(Line, LabelWidthGlobal) << ": ";
@@ -833,8 +833,16 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
WithColor COS(*LineOS, raw_ostream::SAVEDCOLOR, /*Bold=*/false,
/*BG=*/false, TheColorMode);
bool InMatch = false;
- if (Req.Verbose)
- COS.changeColor(raw_ostream::CYAN, true, true);
+ if (Req.Verbose) {
+ COS.changeColor(raw_ostream::CYAN, /*Bold=*/true, /*BG=*/true);
+ } else {
+ // Our goal is to use the output streams's default color so that input
+ // text is legibile in both light and dark themes. SAVEDCOLOR above
+ // currently ignores the Bold=false there, so we override it with
+ // resetColor here, which ensures consistent colors with the resetColor
+ // below anyway.
+ COS.resetColor();
+ }
for (unsigned Col = 1; InputFilePtr != InputFileEnd && !Newline; ++Col) {
bool WasInMatch = InMatch;
InMatch = false;
@@ -844,6 +852,8 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
break;
}
}
+ // If !Req.Verbose, FoundAndExpectedMatches is empty, so InMatch and
+ // WasInMatch remain false, so these color transitions never happen.
if (!WasInMatch && InMatch)
COS.resetColor();
else if (WasInMatch && !InMatch)
>From 664c67aec778928d0390dccd782071945046a12d Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sun, 21 Jun 2026 12:32:30 -0400
Subject: [PATCH 13/18] Use BRIGHT_BLACK instead of SAVEDCOLOR for input lines
and ellipses
`BRIGHT_BLACK` is a grayish color that is (1) clearly visible on the
light and dark terminal themes I have tried and (2) typically distinct
from the default color (`SAVED_COLOR`) used for input text.
---
llvm/utils/FileCheck/FileCheck.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 5d389102af0c3..97f3b61a68932 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -686,7 +686,7 @@ static void DumpEllipsisOrElidedLines(raw_ostream &OS, std::string &ElidedLines,
unsigned EllipsisLines = 3;
if (EllipsisLines < StringRef(ElidedLines).count('\n')) {
for (unsigned i = 0; i < EllipsisLines; ++i) {
- WithColor(OS, raw_ostream::SAVEDCOLOR, /*Bold=*/true)
+ WithColor(OS, raw_ostream::BRIGHT_BLACK, /*Bold=*/true)
<< right_justify(".", LabelWidthGlobal);
OS << '\n';
}
@@ -810,7 +810,7 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
}
// Print right-aligned line number.
- WithColor(*LineOS, raw_ostream::SAVEDCOLOR, /*Bold=*/true, /*BG=*/false,
+ WithColor(*LineOS, raw_ostream::BRIGHT_BLACK, /*Bold=*/true, /*BG=*/false,
TheColorMode)
<< format_decimal(Line, LabelWidthGlobal) << ": ";
>From b700d0b2d6c34906762f3ad6987ce490f18e4829 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sun, 21 Jun 2026 17:30:07 -0400
Subject: [PATCH 14/18] Add tests.
---
llvm/test/FileCheck/dump-input/color.txt | 112 +++++++++++++++++++++++
llvm/test/FileCheck/opt-color.txt | 26 ++++--
llvm/test/lit.cfg.py | 94 +++++++++++++++++++
3 files changed, 223 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/FileCheck/dump-input/color.txt
diff --git a/llvm/test/FileCheck/dump-input/color.txt b/llvm/test/FileCheck/dump-input/color.txt
new file mode 100644
index 0000000000000..b4b637421b50b
--- /dev/null
+++ b/llvm/test/FileCheck/dump-input/color.txt
@@ -0,0 +1,112 @@
+; Check that, when color is enabled, input dumps are colored as desired. Other
+; tests check when colors are enabled generally.
+;
+; There are many redundant ANSI escape sequences in FileCheck's color output.
+; In particular, all sequences immediately preceding a <reset> with no text in
+; between are redundant. These sequences should have no impact on what the
+; FileCheck user sees.
+
+; REQUIRES: ansi-escapes
+
+; RUN: split-file %s %t
+
+; DEFINE: %{opts} =
+; DEFINE: %{run} = \
+; DEFINE: %ProtectFileCheckOutput \
+; DEFINE: not FileCheck -color -dump-input=always -dump-input-filter=error \
+; DEFINE: -dump-input-context=2 %{opts} %t/check.txt < %t/input.txt \
+; DEFINE: 2>&1 | \
+; DEFINE: %{reveal-ansi-escapes} | \
+; DEFINE: FileCheck %s -match-full-lines -check-prefixes
+
+; REDEFINE: %{opts} =
+; RUN: %{run} CHECK-Q
+; REDEFINE: %{opts} = -v
+; RUN: %{run} CHECK-V
+; REDEFINE: %{opts} = -vv
+; RUN: %{run} CHECK-VV
+
+; Without -v or -vv:
+; - Line numbers and ellipses are bright black.
+; - Input text is reset to the default.
+; - Errors are red.
+; - Fuzzy matches are magenta.
+;
+; CHECK-Q: Input was:
+; CHECK-Q-NEXT: <<<<<<
+; CHECK-Q-NEXT: <bold><reset><bold-bright-black> 1: <reset><bold><reset>hello <reset>
+; CHECK-Q-NEXT: <bold-red>dag:2'0 { search range start (exclusive)
+; CHECK-Q-NEXT: <reset><bold-red>dag:2'1 error: no match found
+; CHECK-Q-NEXT: <reset><bold-bright-black> 2: <reset><bold><reset>jello <reset>
+; CHECK-Q-NEXT: <bold-magenta>dag:2'2 ? possible intended match
+; CHECK-Q-NEXT: <reset><bold-bright-black> 3: <reset><bold><reset>end <reset>
+; CHECK-Q-NEXT: <bold-red>dag:2'3 } search range end (exclusive)
+; CHECK-Q-NEXT: <reset><bold-bright-black> 4: <reset><bold><reset>foo <reset>
+; CHECK-Q-NEXT: <bold-bright-black> 5: <reset><bold><reset>foo <reset>
+; CHECK-Q-NEXT: <bold-bright-black> .<reset>
+; CHECK-Q-NEXT: <bold-bright-black> .<reset>
+; CHECK-Q-NEXT: <bold-bright-black> .<reset>
+; CHECK-Q-NEXT: >>>>>>
+
+; With -v, all of the above is true but:
+; - Successes are green.
+; - Unmatched input test now has a cyan background.
+;
+; CHECK-V: Input was:
+; CHECK-V-NEXT: <<<<<<
+; CHECK-V-NEXT: <bold><reset><bold-bright-black> 1: <reset><bold><bg-bold-cyan><reset>hello<bg-bold-cyan> <reset>
+; CHECK-V-NEXT: <bold-green>dag:1 ^~~~~
+; CHECK-V-NEXT: <reset><bold-red>dag:2'0 { search range start (exclusive)
+; CHECK-V-NEXT: <reset><bold-red>dag:2'1 error: no match found
+; CHECK-V-NEXT: <reset><bold-bright-black> 2: <reset><bold><bg-bold-cyan>jello <reset>
+; CHECK-V-NEXT: <bold-magenta>dag:2'2 ? possible intended match
+; CHECK-V-NEXT: <reset><bold-bright-black> 3: <reset><bold><bg-bold-cyan><reset>end<bg-bold-cyan> <reset>
+; CHECK-V-NEXT: <bold-green>label:3 ^~~
+; CHECK-V-NEXT: <reset><bold-red>dag:2'3 } search range end (exclusive)
+; CHECK-V-NEXT: <reset><bold-bright-black> 4: <reset><bold><bg-bold-cyan>foo <reset>
+; CHECK-V-NEXT: <bold-bright-black> 5: <reset><bold><bg-bold-cyan>foo <reset>
+; CHECK-V-NEXT: <bold-bright-black> .<reset>
+; CHECK-V-NEXT: <bold-bright-black> .<reset>
+; CHECK-V-NEXT: <bold-bright-black> .<reset>
+; CHECK-V-NEXT: >>>>>>
+
+; With -vv, all of the above is true but:
+; - Discarded matches are cyan.
+;
+; CHECK-VV: Input was:
+; CHECK-VV-NEXT: <<<<<<
+; CHECK-VV-NEXT: <bold><reset><bold-bright-black> 1: <reset><bold><bg-bold-cyan><reset>hello<bg-bold-cyan> <reset>
+; CHECK-VV-NEXT: <bold-green>dag:1 ^~~~~
+; CHECK-VV-NEXT: <reset><bold-cyan>dag:2'0 !~~~~ discard: overlaps earlier match
+; CHECK-VV-NEXT: <reset><bold-red>dag:2'1 { search range start (exclusive)
+; CHECK-VV-NEXT: <reset><bold-red>dag:2'2 error: no match found
+; CHECK-VV-NEXT: <reset><bold-bright-black> 2: <reset><bold><bg-bold-cyan>jello <reset>
+; CHECK-VV-NEXT: <bold-magenta>dag:2'3 ? possible intended match
+; CHECK-VV-NEXT: <reset><bold-bright-black> 3: <reset><bold><bg-bold-cyan><reset>end<bg-bold-cyan> <reset>
+; CHECK-VV-NEXT: <bold-green>label:3 ^~~
+; CHECK-VV-NEXT: <reset><bold-red>dag:2'4 } search range end (exclusive)
+; CHECK-VV-NEXT: <reset><bold-bright-black> 4: <reset><bold><bg-bold-cyan>foo <reset>
+; CHECK-VV-NEXT: <bold-bright-black> 5: <reset><bold><bg-bold-cyan>foo <reset>
+; CHECK-VV-NEXT: <bold-bright-black> .<reset>
+; CHECK-VV-NEXT: <bold-bright-black> .<reset>
+; CHECK-VV-NEXT: <bold-bright-black> .<reset>
+; CHECK-VV-NEXT: >>>>>>
+
+;--- check.txt
+CHECK-DAG: hello
+CHECK-DAG: hello
+CHECK-LABEL: end
+
+;--- input.txt
+hello
+jello
+end
+foo
+foo
+foo
+foo
+foo
+foo
+foo
+foo
+foo
diff --git a/llvm/test/FileCheck/opt-color.txt b/llvm/test/FileCheck/opt-color.txt
index b12fa768881fe..87be3f899f967 100644
--- a/llvm/test/FileCheck/opt-color.txt
+++ b/llvm/test/FileCheck/opt-color.txt
@@ -1,22 +1,30 @@
+; Check when color is enabled.
+
+; REQUIRES: ansi-escapes
+
; Create a case that produces a simple diagnostic.
; RUN: echo foo > %t.in
; CHECK: bar
; Run without and with -color. In the former case, FileCheck should suppress
; color in its diagnostics because stderr is a file.
-; RUN: %ProtectFileCheckOutput not FileCheck %s < %t.in 2> %t.no-color
-; RUN: %ProtectFileCheckOutput not FileCheck -color %s < %t.in 2> %t.color
+; RUN: %ProtectFileCheckOutput not FileCheck %s < %t.in 2>&1 | \
+; RUN: %{reveal-ansi-escapes} > %t.no-color
+; RUN: %ProtectFileCheckOutput not FileCheck -color %s < %t.in 2>&1 | \
+; RUN: %{reveal-ansi-escapes} > %t.color
; Check whether color was produced.
-; RUN: FileCheck -check-prefix NO-COLOR %s < %t.no-color
-; RUN: FileCheck -check-prefix COLOR %s < %t.color
+; DEFINE: %{no-color} = FileCheck -check-prefix=NO-COLOR %s
+; DEFINE: %{color} = FileCheck -check-prefix=COLOR %s
+; RUN: %{no-color} < %t.no-color
+; RUN: %{color} < %t.color
; Make sure our NO-COLOR and COLOR patterns are sane: they don't match the
; opposite cases.
-; RUN: not FileCheck -check-prefix COLOR %s < %t.no-color
-; RUN: not FileCheck -check-prefix NO-COLOR %s < %t.color
+; RUN: not %{no-color} < %t.color
+; RUN: not %{color} < %t.no-color
-; I don't know of a good way to check for ANSI color codes, so just make sure
-; some new characters show up where those codes should appear.
+; The goal here is not to check the exact details of how colors are used. We
+; just check whether colors are enabled at all.
; NO-COLOR: : error: CHECK: expected string not found in input
-; COLOR: : {{.+}}error: {{.+}}CHECK: expected string not found in input
+; COLOR: <bold-red>error:
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index 09df1e3fd6281..cc5c0faa6983d 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -853,6 +853,100 @@ def host_unwind_supports_jit():
if config.has_logf128:
config.available_features.add("has_logf128")
+# ANSI escape sequences.
+#
+# For example:
+#
+# REQUIRES: ansi-escapes
+# RUN: some-cmd -color 2>&1 | %{reveal-ansi-escapes} | FileCheck %s
+# CHECK: Once in a <blue>blue moon<reset>, I'm <green>green with envy<reset>.
+if platform.system() not in ["Windows"]:
+ config.available_features.add("ansi-escapes")
+ # It is not clear that the escape sequence \x1b is portable across sed
+ # implementations, but that is ok because python substitutes the raw
+ # character here.
+ config.substitutions.append(("%{reveal-ansi-escapes}",
+ "sed "
+ "-e 's/\x1b\\[0;30m/<black>/g' "
+ "-e 's/\x1b\\[0;31m/<red>/g' "
+ "-e 's/\x1b\\[0;32m/<green>/g' "
+ "-e 's/\x1b\\[0;33m/<yellow>/g' "
+ "-e 's/\x1b\\[0;34m/<blue>/g' "
+ "-e 's/\x1b\\[0;35m/<magenta>/g' "
+ "-e 's/\x1b\\[0;36m/<cyan>/g' "
+ "-e 's/\x1b\\[0;37m/<white>/g' "
+
+ "-e 's/\x1b\\[0;90m/<bright-black>/g' "
+ "-e 's/\x1b\\[0;91m/<bright-red>/g' "
+ "-e 's/\x1b\\[0;92m/<bright-green>/g' "
+ "-e 's/\x1b\\[0;93m/<bright-yellow>/g' "
+ "-e 's/\x1b\\[0;94m/<bright-blue>/g' "
+ "-e 's/\x1b\\[0;95m/<bright-magenta>/g' "
+ "-e 's/\x1b\\[0;96m/<bright-cyan>/g' "
+ "-e 's/\x1b\\[0;97m/<bright-white>/g' "
+
+ "-e 's/\x1b\\[0;1;30m/<bold-black>/g' "
+ "-e 's/\x1b\\[0;1;31m/<bold-red>/g' "
+ "-e 's/\x1b\\[0;1;32m/<bold-green>/g' "
+ "-e 's/\x1b\\[0;1;33m/<bold-yellow>/g' "
+ "-e 's/\x1b\\[0;1;34m/<bold-blue>/g' "
+ "-e 's/\x1b\\[0;1;35m/<bold-magenta>/g' "
+ "-e 's/\x1b\\[0;1;36m/<bold-cyan>/g' "
+ "-e 's/\x1b\\[0;1;37m/<bold-white>/g' "
+
+ "-e 's/\x1b\\[0;1;90m/<bold-bright-black>/g' "
+ "-e 's/\x1b\\[0;1;91m/<bold-bright-red>/g' "
+ "-e 's/\x1b\\[0;1;92m/<bold-bright-green>/g' "
+ "-e 's/\x1b\\[0;1;93m/<bold-bright-yellow>/g' "
+ "-e 's/\x1b\\[0;1;94m/<bold-bright-blue>/g' "
+ "-e 's/\x1b\\[0;1;95m/<bold-bright-magenta>/g' "
+ "-e 's/\x1b\\[0;1;96m/<bold-bright-cyan>/g' "
+ "-e 's/\x1b\\[0;1;97m/<bold-bright-white>/g' "
+
+ "-e 's/\x1b\\[0;40m/<bg-black>/g' "
+ "-e 's/\x1b\\[0;41m/<bg-red>/g' "
+ "-e 's/\x1b\\[0;42m/<bg-green>/g' "
+ "-e 's/\x1b\\[0;43m/<bg-yellow>/g' "
+ "-e 's/\x1b\\[0;44m/<bg-blue>/g' "
+ "-e 's/\x1b\\[0;45m/<bg-magenta>/g' "
+ "-e 's/\x1b\\[0;46m/<bg-cyan>/g' "
+ "-e 's/\x1b\\[0;47m/<bg-white>/g' "
+
+ "-e 's/\x1b\\[0;100m/<bg-bright-black>/g' "
+ "-e 's/\x1b\\[0;101m/<bg-bright-red>/g' "
+ "-e 's/\x1b\\[0;102m/<bg-bright-green>/g' "
+ "-e 's/\x1b\\[0;103m/<bg-bright-yellow>/g' "
+ "-e 's/\x1b\\[0;104m/<bg-bright-blue>/g' "
+ "-e 's/\x1b\\[0;105m/<bg-bright-magenta>/g' "
+ "-e 's/\x1b\\[0;106m/<bg-bright-cyan>/g' "
+ "-e 's/\x1b\\[0;107m/<bg-bright-white>/g' "
+
+ "-e 's/\x1b\\[0;1;40m/<bg-bold-black>/g' "
+ "-e 's/\x1b\\[0;1;41m/<bg-bold-red>/g' "
+ "-e 's/\x1b\\[0;1;42m/<bg-bold-green>/g' "
+ "-e 's/\x1b\\[0;1;43m/<bg-bold-yellow>/g' "
+ "-e 's/\x1b\\[0;1;44m/<bg-bold-blue>/g' "
+ "-e 's/\x1b\\[0;1;45m/<bg-bold-magenta>/g' "
+ "-e 's/\x1b\\[0;1;46m/<bg-bold-cyan>/g' "
+ "-e 's/\x1b\\[0;1;47m/<bg-bold-white>/g' "
+
+ "-e 's/\x1b\\[0;1;100m/<bg-bold-bright-black>/g' "
+ "-e 's/\x1b\\[0;1;101m/<bg-bold-bright-red>/g' "
+ "-e 's/\x1b\\[0;1;102m/<bg-bold-bright-green>/g' "
+ "-e 's/\x1b\\[0;1;103m/<bg-bold-bright-yellow>/g' "
+ "-e 's/\x1b\\[0;1;104m/<bg-bold-bright-blue>/g' "
+ "-e 's/\x1b\\[0;1;105m/<bg-bold-bright-magenta>/g' "
+ "-e 's/\x1b\\[0;1;106m/<bg-bold-bright-cyan>/g' "
+ "-e 's/\x1b\\[0;1;107m/<bg-bold-bright-white>/g' "
+
+ "-e 's/\x1b\\[1m/<bold>/g' "
+ "-e 's/\x1b\\[7m/<reverse>/g' "
+ "-e 's/\x1b\\[0m/<reset>/g' "
+
+ # Reveal any sequence we missed above.
+ "-e 's/\x1b/<esc>/g' "
+ ))
+
if lit_config.update_tests:
import sys
import os
>From c09712a3411afdb713ef4e6b071c38e04367ffbb Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sun, 21 Jun 2026 17:45:55 -0400
Subject: [PATCH 15/18] Run darker. Add some comments.
---
llvm/test/lit.cfg.py | 161 +++++++++++++++++++++----------------------
1 file changed, 80 insertions(+), 81 deletions(-)
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index cc5c0faa6983d..cd028963dd59e 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -865,87 +865,86 @@ def host_unwind_supports_jit():
# It is not clear that the escape sequence \x1b is portable across sed
# implementations, but that is ok because python substitutes the raw
# character here.
- config.substitutions.append(("%{reveal-ansi-escapes}",
- "sed "
- "-e 's/\x1b\\[0;30m/<black>/g' "
- "-e 's/\x1b\\[0;31m/<red>/g' "
- "-e 's/\x1b\\[0;32m/<green>/g' "
- "-e 's/\x1b\\[0;33m/<yellow>/g' "
- "-e 's/\x1b\\[0;34m/<blue>/g' "
- "-e 's/\x1b\\[0;35m/<magenta>/g' "
- "-e 's/\x1b\\[0;36m/<cyan>/g' "
- "-e 's/\x1b\\[0;37m/<white>/g' "
-
- "-e 's/\x1b\\[0;90m/<bright-black>/g' "
- "-e 's/\x1b\\[0;91m/<bright-red>/g' "
- "-e 's/\x1b\\[0;92m/<bright-green>/g' "
- "-e 's/\x1b\\[0;93m/<bright-yellow>/g' "
- "-e 's/\x1b\\[0;94m/<bright-blue>/g' "
- "-e 's/\x1b\\[0;95m/<bright-magenta>/g' "
- "-e 's/\x1b\\[0;96m/<bright-cyan>/g' "
- "-e 's/\x1b\\[0;97m/<bright-white>/g' "
-
- "-e 's/\x1b\\[0;1;30m/<bold-black>/g' "
- "-e 's/\x1b\\[0;1;31m/<bold-red>/g' "
- "-e 's/\x1b\\[0;1;32m/<bold-green>/g' "
- "-e 's/\x1b\\[0;1;33m/<bold-yellow>/g' "
- "-e 's/\x1b\\[0;1;34m/<bold-blue>/g' "
- "-e 's/\x1b\\[0;1;35m/<bold-magenta>/g' "
- "-e 's/\x1b\\[0;1;36m/<bold-cyan>/g' "
- "-e 's/\x1b\\[0;1;37m/<bold-white>/g' "
-
- "-e 's/\x1b\\[0;1;90m/<bold-bright-black>/g' "
- "-e 's/\x1b\\[0;1;91m/<bold-bright-red>/g' "
- "-e 's/\x1b\\[0;1;92m/<bold-bright-green>/g' "
- "-e 's/\x1b\\[0;1;93m/<bold-bright-yellow>/g' "
- "-e 's/\x1b\\[0;1;94m/<bold-bright-blue>/g' "
- "-e 's/\x1b\\[0;1;95m/<bold-bright-magenta>/g' "
- "-e 's/\x1b\\[0;1;96m/<bold-bright-cyan>/g' "
- "-e 's/\x1b\\[0;1;97m/<bold-bright-white>/g' "
-
- "-e 's/\x1b\\[0;40m/<bg-black>/g' "
- "-e 's/\x1b\\[0;41m/<bg-red>/g' "
- "-e 's/\x1b\\[0;42m/<bg-green>/g' "
- "-e 's/\x1b\\[0;43m/<bg-yellow>/g' "
- "-e 's/\x1b\\[0;44m/<bg-blue>/g' "
- "-e 's/\x1b\\[0;45m/<bg-magenta>/g' "
- "-e 's/\x1b\\[0;46m/<bg-cyan>/g' "
- "-e 's/\x1b\\[0;47m/<bg-white>/g' "
-
- "-e 's/\x1b\\[0;100m/<bg-bright-black>/g' "
- "-e 's/\x1b\\[0;101m/<bg-bright-red>/g' "
- "-e 's/\x1b\\[0;102m/<bg-bright-green>/g' "
- "-e 's/\x1b\\[0;103m/<bg-bright-yellow>/g' "
- "-e 's/\x1b\\[0;104m/<bg-bright-blue>/g' "
- "-e 's/\x1b\\[0;105m/<bg-bright-magenta>/g' "
- "-e 's/\x1b\\[0;106m/<bg-bright-cyan>/g' "
- "-e 's/\x1b\\[0;107m/<bg-bright-white>/g' "
-
- "-e 's/\x1b\\[0;1;40m/<bg-bold-black>/g' "
- "-e 's/\x1b\\[0;1;41m/<bg-bold-red>/g' "
- "-e 's/\x1b\\[0;1;42m/<bg-bold-green>/g' "
- "-e 's/\x1b\\[0;1;43m/<bg-bold-yellow>/g' "
- "-e 's/\x1b\\[0;1;44m/<bg-bold-blue>/g' "
- "-e 's/\x1b\\[0;1;45m/<bg-bold-magenta>/g' "
- "-e 's/\x1b\\[0;1;46m/<bg-bold-cyan>/g' "
- "-e 's/\x1b\\[0;1;47m/<bg-bold-white>/g' "
-
- "-e 's/\x1b\\[0;1;100m/<bg-bold-bright-black>/g' "
- "-e 's/\x1b\\[0;1;101m/<bg-bold-bright-red>/g' "
- "-e 's/\x1b\\[0;1;102m/<bg-bold-bright-green>/g' "
- "-e 's/\x1b\\[0;1;103m/<bg-bold-bright-yellow>/g' "
- "-e 's/\x1b\\[0;1;104m/<bg-bold-bright-blue>/g' "
- "-e 's/\x1b\\[0;1;105m/<bg-bold-bright-magenta>/g' "
- "-e 's/\x1b\\[0;1;106m/<bg-bold-bright-cyan>/g' "
- "-e 's/\x1b\\[0;1;107m/<bg-bold-bright-white>/g' "
-
- "-e 's/\x1b\\[1m/<bold>/g' "
- "-e 's/\x1b\\[7m/<reverse>/g' "
- "-e 's/\x1b\\[0m/<reset>/g' "
-
- # Reveal any sequence we missed above.
- "-e 's/\x1b/<esc>/g' "
- ))
+ config.substitutions.append(
+ (
+ "%{reveal-ansi-escapes}",
+ "sed "
+ # Foreground colors.
+ "-e 's/\x1b\\[0;30m/<black>/g' "
+ "-e 's/\x1b\\[0;31m/<red>/g' "
+ "-e 's/\x1b\\[0;32m/<green>/g' "
+ "-e 's/\x1b\\[0;33m/<yellow>/g' "
+ "-e 's/\x1b\\[0;34m/<blue>/g' "
+ "-e 's/\x1b\\[0;35m/<magenta>/g' "
+ "-e 's/\x1b\\[0;36m/<cyan>/g' "
+ "-e 's/\x1b\\[0;37m/<white>/g' "
+ "-e 's/\x1b\\[0;90m/<bright-black>/g' "
+ "-e 's/\x1b\\[0;91m/<bright-red>/g' "
+ "-e 's/\x1b\\[0;92m/<bright-green>/g' "
+ "-e 's/\x1b\\[0;93m/<bright-yellow>/g' "
+ "-e 's/\x1b\\[0;94m/<bright-blue>/g' "
+ "-e 's/\x1b\\[0;95m/<bright-magenta>/g' "
+ "-e 's/\x1b\\[0;96m/<bright-cyan>/g' "
+ "-e 's/\x1b\\[0;97m/<bright-white>/g' "
+ # Bold foreground colors.
+ "-e 's/\x1b\\[0;1;30m/<bold-black>/g' "
+ "-e 's/\x1b\\[0;1;31m/<bold-red>/g' "
+ "-e 's/\x1b\\[0;1;32m/<bold-green>/g' "
+ "-e 's/\x1b\\[0;1;33m/<bold-yellow>/g' "
+ "-e 's/\x1b\\[0;1;34m/<bold-blue>/g' "
+ "-e 's/\x1b\\[0;1;35m/<bold-magenta>/g' "
+ "-e 's/\x1b\\[0;1;36m/<bold-cyan>/g' "
+ "-e 's/\x1b\\[0;1;37m/<bold-white>/g' "
+ "-e 's/\x1b\\[0;1;90m/<bold-bright-black>/g' "
+ "-e 's/\x1b\\[0;1;91m/<bold-bright-red>/g' "
+ "-e 's/\x1b\\[0;1;92m/<bold-bright-green>/g' "
+ "-e 's/\x1b\\[0;1;93m/<bold-bright-yellow>/g' "
+ "-e 's/\x1b\\[0;1;94m/<bold-bright-blue>/g' "
+ "-e 's/\x1b\\[0;1;95m/<bold-bright-magenta>/g' "
+ "-e 's/\x1b\\[0;1;96m/<bold-bright-cyan>/g' "
+ "-e 's/\x1b\\[0;1;97m/<bold-bright-white>/g' "
+ # Background colors.
+ "-e 's/\x1b\\[0;40m/<bg-black>/g' "
+ "-e 's/\x1b\\[0;41m/<bg-red>/g' "
+ "-e 's/\x1b\\[0;42m/<bg-green>/g' "
+ "-e 's/\x1b\\[0;43m/<bg-yellow>/g' "
+ "-e 's/\x1b\\[0;44m/<bg-blue>/g' "
+ "-e 's/\x1b\\[0;45m/<bg-magenta>/g' "
+ "-e 's/\x1b\\[0;46m/<bg-cyan>/g' "
+ "-e 's/\x1b\\[0;47m/<bg-white>/g' "
+ "-e 's/\x1b\\[0;100m/<bg-bright-black>/g' "
+ "-e 's/\x1b\\[0;101m/<bg-bright-red>/g' "
+ "-e 's/\x1b\\[0;102m/<bg-bright-green>/g' "
+ "-e 's/\x1b\\[0;103m/<bg-bright-yellow>/g' "
+ "-e 's/\x1b\\[0;104m/<bg-bright-blue>/g' "
+ "-e 's/\x1b\\[0;105m/<bg-bright-magenta>/g' "
+ "-e 's/\x1b\\[0;106m/<bg-bright-cyan>/g' "
+ "-e 's/\x1b\\[0;107m/<bg-bright-white>/g' "
+ # Bold background colors.
+ "-e 's/\x1b\\[0;1;40m/<bg-bold-black>/g' "
+ "-e 's/\x1b\\[0;1;41m/<bg-bold-red>/g' "
+ "-e 's/\x1b\\[0;1;42m/<bg-bold-green>/g' "
+ "-e 's/\x1b\\[0;1;43m/<bg-bold-yellow>/g' "
+ "-e 's/\x1b\\[0;1;44m/<bg-bold-blue>/g' "
+ "-e 's/\x1b\\[0;1;45m/<bg-bold-magenta>/g' "
+ "-e 's/\x1b\\[0;1;46m/<bg-bold-cyan>/g' "
+ "-e 's/\x1b\\[0;1;47m/<bg-bold-white>/g' "
+ "-e 's/\x1b\\[0;1;100m/<bg-bold-bright-black>/g' "
+ "-e 's/\x1b\\[0;1;101m/<bg-bold-bright-red>/g' "
+ "-e 's/\x1b\\[0;1;102m/<bg-bold-bright-green>/g' "
+ "-e 's/\x1b\\[0;1;103m/<bg-bold-bright-yellow>/g' "
+ "-e 's/\x1b\\[0;1;104m/<bg-bold-bright-blue>/g' "
+ "-e 's/\x1b\\[0;1;105m/<bg-bold-bright-magenta>/g' "
+ "-e 's/\x1b\\[0;1;106m/<bg-bold-bright-cyan>/g' "
+ "-e 's/\x1b\\[0;1;107m/<bg-bold-bright-white>/g' "
+ # Misc.
+ "-e 's/\x1b\\[1m/<bold>/g' "
+ "-e 's/\x1b\\[7m/<reverse>/g' "
+ "-e 's/\x1b\\[0m/<reset>/g' "
+ # Reveal any sequence we missed above.
+ "-e 's/\x1b/<esc>/g' ",
+ )
+ )
if lit_config.update_tests:
import sys
>From 5ff7656c9f57428b2aa3dc6094415655e2305acb Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 22 Jun 2026 15:34:59 -0400
Subject: [PATCH 16/18] Append "in search range" to "no match found"
Discussed at:
https://discourse.llvm.org/t/rfc-filecheck-improving-input-dump-readability/91112/5
---
.../test/FileCheck/dump-input/annotations.txt | 36 +++++++++----------
llvm/test/FileCheck/dump-input/context.txt | 2 +-
llvm/test/FileCheck/dump-input/enable.txt | 2 +-
llvm/test/FileCheck/dump-input/filter.txt | 4 +--
.../check-label-follows.txt | 2 +-
llvm/utils/FileCheck/FileCheck.cpp | 2 +-
6 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/llvm/test/FileCheck/dump-input/annotations.txt b/llvm/test/FileCheck/dump-input/annotations.txt
index 9f7934f5aa95a..18ece6b508c5f 100644
--- a/llvm/test/FileCheck/dump-input/annotations.txt
+++ b/llvm/test/FileCheck/dump-input/annotations.txt
@@ -133,7 +133,7 @@
; CHK-NEXT: 1: hello
; CHK-V-NEXT:check:1 ^~~~~
; CHK-NEXT:check:2'0 { search range start (exclusive)
-; CHK-NEXT:check:2'1 error: no match found
+; CHK-NEXT:check:2'1 error: no match found in search range
; CHK-NEXT: 2: again
; CHK-NEXT: 3: whirled
; CHK-NEXT:check:2'2 ? possible intended match
@@ -167,7 +167,7 @@
; CNT-V-NEXT: 2: repete
; CNT-V-NEXT:count:1'1 ^~~~
; CNT-V-NEXT:count:1'2 { search range start (exclusive)
-; CNT-V-NEXT:count:1'3 error: no match found
+; CNT-V-NEXT:count:1'3 error: no match found in search range
; CNT-V-NEXT: 3: repeat
; CNT-V-NEXT:count:1'4 ? possible intended match
; CNT-V-NEXT:count:1'5 } search range end (exclusive)
@@ -178,7 +178,7 @@
; CNT-Q-NEXT: 1: pete
; CNT-Q-NEXT: 2: repete
; CNT-Q-NEXT:count:1'0 { search range start (exclusive)
-; CNT-Q-NEXT:count:1'1 error: no match found
+; CNT-Q-NEXT:count:1'1 error: no match found in search range
; CNT-Q-NEXT: 3: repeat
; CNT-Q-NEXT:count:1'2 ? possible intended match
; CNT-Q-NEXT:count:1'3 } search range end (exclusive)
@@ -212,7 +212,7 @@
; NXT-NEXT: 2: again
; NXT-V-NEXT:next:2 ^~~~~
; NXT-NEXT:next:3'0 { } search range (exclusive bounds)
-; NXT-NEXT:next:3'1 error: no match found
+; NXT-NEXT:next:3'1 error: no match found in search range
; NXT-NEXT:>>>>>>
; NXT-NOT:{{.}}
@@ -267,7 +267,7 @@
; SAM-V-NEXT:check:1 ^~~~~
; SAM-V-NEXT:same:2 ^~~~~
; SAM-NEXT:same:3'0 { } search range (exclusive bounds)
-; SAM-NEXT:same:3'1 error: no match found
+; SAM-NEXT:same:3'1 error: no match found in search range
; SAM-NEXT:>>>>>>
; SAM-NOT:{{.}}
@@ -330,7 +330,7 @@
; EMP-NEXT: 2:
; EMP-V-NEXT:empty:2 ^
; EMP-NEXT:empty:3'0 { search range start (exclusive)
-; EMP-NEXT:empty:3'1 error: no match found
+; EMP-NEXT:empty:3'1 error: no match found in search range
; EMP-NEXT: 3: world
; EMP-NEXT: 4: label
; EMP-V-NEXT:label:4 ^~~~~
@@ -466,7 +466,7 @@
; DAG-VV-NEXT:dag:1 ^~~
; DAG-VV-NEXT:dag:4'0 !~~ discard: overlaps earlier match
; DAG-VV-NEXT:dag:4'1 { search range start (exclusive)
-; DAG-VV-NEXT:dag:4'2 error: no match found
+; DAG-VV-NEXT:dag:4'2 error: no match found in search range
; DAG-VV-NEXT: 3: abc
; DAG-VV-NEXT:dag:3'1 ^~~
; DAG-VV-NEXT:dag:4'3 } search range end (exclusive)
@@ -479,7 +479,7 @@
; DAG-VQ-NEXT: 2: def
; DAG-VQ-NEXT:dag:1 ^~~
; DAG-VQ-NEXT:dag:4'0 { search range start (exclusive)
-; DAG-VQ-NEXT:dag:4'1 error: no match found
+; DAG-VQ-NEXT:dag:4'1 error: no match found in search range
; DAG-VQ-NEXT: 3: abc
; DAG-VQ-NEXT:dag:3 ^~~
; DAG-VQ-NEXT:dag:4'2 } search range end (exclusive)
@@ -490,7 +490,7 @@
; DAG-Q-NEXT: 1: abc
; DAG-Q-NEXT: 2: def
; DAG-Q-NEXT:dag:4'0 { search range start (exclusive)
-; DAG-Q-NEXT:dag:4'1 error: no match found
+; DAG-Q-NEXT:dag:4'1 error: no match found in search range
; DAG-Q-NEXT: 3: abc
; DAG-Q-NEXT:dag:4'2 } search range end (exclusive)
; DAG-Q-NEXT:>>>>>>
@@ -528,7 +528,7 @@
; DAG1L-VV-NEXT:dag:5'0 !~~ discard: overlaps earlier match
; DAG1L-VV-NEXT:dag:5'1 !~~ discard: overlaps earlier match
; DAG1L-VV-NEXT:dag:5'2 { } search range (exclusive bounds)
-; DAG1L-VV-NEXT:dag:5'3 error: no match found
+; DAG1L-VV-NEXT:dag:5'3 error: no match found in search range
; DAG1L-VV-NEXT:>>>>>>
; DAG1L-VV-NOT:{{.}}
@@ -539,14 +539,14 @@
; DAG1L-VQ-NEXT:dag:3 ^~~
; DAG1L-VQ-NEXT:dag:4 ^~
; DAG1L-VQ-NEXT:dag:5'0 { } search range (exclusive bounds)
-; DAG1L-VQ-NEXT:dag:5'1 error: no match found
+; DAG1L-VQ-NEXT:dag:5'1 error: no match found in search range
; DAG1L-VQ-NEXT:>>>>>>
; DAG1L-VQ-NOT:{{.}}
; DAG1L-Q:<<<<<<
; DAG1L-Q-NEXT: 1: abc def abc def
; DAG1L-Q-NEXT:dag:5'0 { } search range (exclusive bounds)
-; DAG1L-Q-NEXT:dag:5'1 error: no match found
+; DAG1L-Q-NEXT:dag:5'1 error: no match found in search range
; DAG1L-Q-NEXT:>>>>>>
; DAG1L-Q-NOT:{{.}}
@@ -613,7 +613,7 @@
; LAB-V-NEXT:label:2'0 ^~~~~~
; LAB-V-NEXT:label:2'1 ^~~~~~
; LAB-V-NEXT:check:3'0 { search range start (exclusive)
-; LAB-V-NEXT:check:3'1 error: no match found
+; LAB-V-NEXT:check:3'1 error: no match found in search range
; LAB-V-NEXT: 3: textA
; LAB-V-NEXT: 4: labelB
; LAB-V-NEXT:label:4 ^~~~~~
@@ -623,7 +623,7 @@
; LAB-V-NEXT:label:6'0 ^~~~~~
; LAB-V-NEXT:check:5 ^~~~~~
; LAB-V-NEXT:label:6'1 {} search range (exclusive bounds)
-; LAB-V-NEXT:label:6'2 error: no match found
+; LAB-V-NEXT:label:6'2 error: no match found in search range
; LAB-VV-NEXT:not:7'0 { search range start (exclusive)
; LAB-V-NEXT: 7: textC
; LAB-VV-NEXT:not:7'1 } search range end (exclusive)
@@ -650,14 +650,14 @@
; LAB-Q-NEXT: 1: text
; LAB-Q-NEXT: 2: labelA
; LAB-Q-NEXT:check:3'0 { search range start (exclusive)
-; LAB-Q-NEXT:check:3'1 error: no match found
+; LAB-Q-NEXT:check:3'1 error: no match found in search range
; LAB-Q-NEXT: 3: textA
; LAB-Q-NEXT: 4: labelB
; LAB-Q-NEXT:check:3'2 } search range end (exclusive)
; LAB-Q-NEXT: 5: textB
; LAB-Q-NEXT: 6: labelC
; LAB-Q-NEXT:label:6'0 {} search range (exclusive bounds)
-; LAB-Q-NEXT:label:6'1 error: no match found
+; LAB-Q-NEXT:label:6'1 error: no match found in search range
; LAB-Q-NEXT: 7: textC
; LAB-Q-NEXT: 8: labelD
; LAB-Q-NEXT:not:9'0 { search range start (exclusive)
@@ -1083,7 +1083,7 @@
; POS-SEARCH-EMPTY-FILE:<<<<<<
; POS-SEARCH-EMPTY-FILE-NEXT: 1:
; POS-SEARCH-EMPTY-FILE-NEXT:check:1'0 {} search range (exclusive bounds)
-; POS-SEARCH-EMPTY-FILE-NEXT:check:1'1 error: no match found
+; POS-SEARCH-EMPTY-FILE-NEXT:check:1'1 error: no match found in search range
; POS-SEARCH-EMPTY-FILE-NEXT:>>>>>>
; REDEFINE: %{opts} =
@@ -1124,7 +1124,7 @@
; SEARCH-BOF-EOF-MULTI-LINE:<<<<<<
; SEARCH-BOF-EOF-MULTI-LINE-NEXT: 1: line 1
; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'0 { search range start (exclusive)
-; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'1 error: no match found
+; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'1 error: no match found in search range
; SEARCH-BOF-EOF-MULTI-LINE-NEXT: 2: line 2
; SEARCH-BOF-EOF-MULTI-LINE-NEXT:check:1'2 } search range end (exclusive)
; SEARCH-BOF-EOF-MULTI-LINE-NEXT:>>>>>>
diff --git a/llvm/test/FileCheck/dump-input/context.txt b/llvm/test/FileCheck/dump-input/context.txt
index 8a567a5d567b2..f5bfc78f656af 100644
--- a/llvm/test/FileCheck/dump-input/context.txt
+++ b/llvm/test/FileCheck/dump-input/context.txt
@@ -121,7 +121,7 @@
; W5-NEXT:label:1'1 ^~~~
; W5-NEXT:dag:2 ^~~~~~
; W5-NEXT:dag:3'0 { search range start (exclusive)
-; W5-NEXT:dag:3'1 error: no match found
+; W5-NEXT:dag:3'1 error: no match found in search range
; W5-NEXT: 10: foo1
; W5-NEXT:dag:2 ~~~~~
; W5-NEXT:dag:3'2 ? possible intended match
diff --git a/llvm/test/FileCheck/dump-input/enable.txt b/llvm/test/FileCheck/dump-input/enable.txt
index 58472eb4751f0..3708ef94a4f9d 100644
--- a/llvm/test/FileCheck/dump-input/enable.txt
+++ b/llvm/test/FileCheck/dump-input/enable.txt
@@ -249,7 +249,7 @@ BADVAL:{{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input option: Cannot find opt
; DUMP-ERR-NEXT: 1: hello
; DUMP-ERR-V-NEXT:check:1 ^~~~~
; DUMP-ERR-NEXT:next:2'0 { search range start (exclusive)
-; DUMP-ERR-NEXT:next:2'1 error: no match found
+; DUMP-ERR-NEXT:next:2'1 error: no match found in search range
; DUMP-ERR-NEXT: 2: whirled
; DUMP-ERR-NEXT:next:2'2 ? possible intended match
; DUMP-ERR-NEXT:next:2'3 } search range end (exclusive)
diff --git a/llvm/test/FileCheck/dump-input/filter.txt b/llvm/test/FileCheck/dump-input/filter.txt
index 7f7df8e2d1095..5d8696830a6e5 100644
--- a/llvm/test/FileCheck/dump-input/filter.txt
+++ b/llvm/test/FileCheck/dump-input/filter.txt
@@ -476,7 +476,7 @@ BADVAL:{{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-filter option: Cannot f
;--------------------------------------------------
;- - - - - - - - - - - - - - - - - - - - - - - - -
-; error: no match found.
+; error: no match found in search range.
; possible intended match
;- - - - - - - - - - - - - - - - - - - - - - - - -
@@ -502,7 +502,7 @@ BADVAL:{{F|f}}ile{{C|c}}heck{{.*}}: for the --dump-input-filter option: Cannot f
; CHK-ERR:<<<<<<
; CHK-ERR-NEXT: 1: start
; CHK-ERR-NEXT:check:1'0 { search range start (exclusive)
-; CHK-ERR-NEXT:check:1'1 error: no match found
+; CHK-ERR-NEXT:check:1'1 error: no match found in search range
; CHK-ERR-NEXT: .
; CHK-ERR-NEXT: .
; CHK-ERR-NEXT: .
diff --git a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
index b003a9ce4aabd..098c63765c0ca 100644
--- a/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
+++ b/llvm/test/FileCheck/dump-input/search-range-annotations/check-label-follows.txt
@@ -18,7 +18,7 @@ DMP-NEXT: 1: offload triples:
DMP-NEXT:label:1'0 ^~~~~~~~~~~~~~~~
DMP-NEXT:label:1'1 ^~~~~~~~~~~~~~~~
DMP-NEXT:check:2'0 { search range start (exclusive)
-DMP-NEXT:check:2'1 error: no match found
+DMP-NEXT:check:2'1 error: no match found in search range
DMP-NEXT: 2: - x86_64-linux-gnu
DMP-NEXT:check:2'2 ? possible intended match
DMP-NEXT: 3: - x86_64-unknown-linux-gnu
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 412dd69f5dae6..8668ea86a6ef9 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -257,7 +257,7 @@ static MarkerStyle getMarker(const FileCheckDiag &Diag) {
Res.Note = "match failed for invalid pattern";
break;
case MatchNoneDiag::Expected:
- Res.Note = "no match found";
+ Res.Note = "no match found in search range";
break;
}
break;
>From 556e7f3a4e07deb68a7a96ecb84990adc0c9fc66 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Mon, 22 Jun 2026 15:43:17 -0400
Subject: [PATCH 17/18] Update new test for changes in PR #198138
---
llvm/test/FileCheck/dump-input/color.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/test/FileCheck/dump-input/color.txt b/llvm/test/FileCheck/dump-input/color.txt
index b4b637421b50b..7206c0b3887fe 100644
--- a/llvm/test/FileCheck/dump-input/color.txt
+++ b/llvm/test/FileCheck/dump-input/color.txt
@@ -36,7 +36,7 @@
; CHECK-Q-NEXT: <<<<<<
; CHECK-Q-NEXT: <bold><reset><bold-bright-black> 1: <reset><bold><reset>hello <reset>
; CHECK-Q-NEXT: <bold-red>dag:2'0 { search range start (exclusive)
-; CHECK-Q-NEXT: <reset><bold-red>dag:2'1 error: no match found
+; CHECK-Q-NEXT: <reset><bold-red>dag:2'1 error: no match found in search range
; CHECK-Q-NEXT: <reset><bold-bright-black> 2: <reset><bold><reset>jello <reset>
; CHECK-Q-NEXT: <bold-magenta>dag:2'2 ? possible intended match
; CHECK-Q-NEXT: <reset><bold-bright-black> 3: <reset><bold><reset>end <reset>
@@ -57,7 +57,7 @@
; CHECK-V-NEXT: <bold><reset><bold-bright-black> 1: <reset><bold><bg-bold-cyan><reset>hello<bg-bold-cyan> <reset>
; CHECK-V-NEXT: <bold-green>dag:1 ^~~~~
; CHECK-V-NEXT: <reset><bold-red>dag:2'0 { search range start (exclusive)
-; CHECK-V-NEXT: <reset><bold-red>dag:2'1 error: no match found
+; CHECK-V-NEXT: <reset><bold-red>dag:2'1 error: no match found in search range
; CHECK-V-NEXT: <reset><bold-bright-black> 2: <reset><bold><bg-bold-cyan>jello <reset>
; CHECK-V-NEXT: <bold-magenta>dag:2'2 ? possible intended match
; CHECK-V-NEXT: <reset><bold-bright-black> 3: <reset><bold><bg-bold-cyan><reset>end<bg-bold-cyan> <reset>
@@ -79,7 +79,7 @@
; CHECK-VV-NEXT: <bold-green>dag:1 ^~~~~
; CHECK-VV-NEXT: <reset><bold-cyan>dag:2'0 !~~~~ discard: overlaps earlier match
; CHECK-VV-NEXT: <reset><bold-red>dag:2'1 { search range start (exclusive)
-; CHECK-VV-NEXT: <reset><bold-red>dag:2'2 error: no match found
+; CHECK-VV-NEXT: <reset><bold-red>dag:2'2 error: no match found in search range
; CHECK-VV-NEXT: <reset><bold-bright-black> 2: <reset><bold><bg-bold-cyan>jello <reset>
; CHECK-VV-NEXT: <bold-magenta>dag:2'3 ? possible intended match
; CHECK-VV-NEXT: <reset><bold-bright-black> 3: <reset><bold><bg-bold-cyan><reset>end<bg-bold-cyan> <reset>
>From cb9e8492505bd11b461f97ea8ca505fc05010d97 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Sat, 27 Jun 2026 18:36:28 -0400
Subject: [PATCH 18/18] Fix typo in color.txt comment about unmatched input
---
llvm/test/FileCheck/dump-input/color.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/FileCheck/dump-input/color.txt b/llvm/test/FileCheck/dump-input/color.txt
index 7206c0b3887fe..9d343c0e0fb08 100644
--- a/llvm/test/FileCheck/dump-input/color.txt
+++ b/llvm/test/FileCheck/dump-input/color.txt
@@ -50,7 +50,7 @@
; With -v, all of the above is true but:
; - Successes are green.
-; - Unmatched input test now has a cyan background.
+; - Unmatched input text now has a cyan background.
;
; CHECK-V: Input was:
; CHECK-V-NEXT: <<<<<<
More information about the llvm-commits
mailing list