Index: llvm/test/FileCheck/dump-input/filter-error-neighbor/check-dag.txt
===================================================================
--- /dev/null
+++ llvm/test/FileCheck/dump-input/filter-error-neighbor/check-dag.txt
@@ -0,0 +1,62 @@
+; The neighboring behavior of -dump-input-filter=error does not reveal lines
+; that are within an error annotation. CHECK-DAG is the reason. In the example
+; below, it would cause all the CHECK-DAG matches to be revealed.
+;
+; Moreover, the neighboring implementation has special handling for CHECK-LABEL
+; in that its match is revealed if it precedes the last line of an error. That
+; special handling shouldn't be applied to other directives. Otherwise, the
+; successful CHECK-DAG match at the end of the CHECK-DAG error here would be
+; revealed accidentally.
+
+ CHECK:<<<<<<
+CHECK-NEXT: 1: loop iter 3
+CHECK-NEXT:dag:4 ^~~~~~~~~~~
+CHECK-NEXT:dag:10 X~~~~~~~~~~ error: no match found
+CHECK-NEXT: 2: loop iter 0
+CHECK-NEXT:dag:1 ^~~~~~~~~~~
+CHECK-NEXT:dag:10 ~~~~~~~~~~~
+CHECK-NEXT: 3: loop iter 4
+CHECK-NEXT:dag:5 ^~~~~~~~~~~
+CHECK-NEXT:dag:10 ~~~~~~~~~~~
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT:>>>>>>
+
+RUN: echo 'CHECK-DAG: loop iter 0' > %t.chk
+RUN: echo 'CHECK-DAG: loop iter 1' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 2' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 3' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 4' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 5' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 6' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 7' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 8' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 9' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 10' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 11' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 12' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 13' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 14' >> %t.chk
+RUN: echo 'CHECK-DAG: loop iter 15' >> %t.chk
+
+RUN: echo 'loop iter 3' > %t.in
+RUN: echo 'loop iter 0' >> %t.in
+RUN: echo 'loop iter 4' >> %t.in
+RUN: echo 'loop iter 6' >> %t.in
+RUN: echo 'loop iter 12' >> %t.in
+RUN: echo 'loop iter 7' >> %t.in
+RUN: echo 'loop iter 8' >> %t.in
+RUN: echo 'loop iter 14' >> %t.in
+RUN: echo 'loop iter 2' >> %t.in
+RUN: echo 'loop iter 11' >> %t.in
+RUN: echo 'loop iter 1' >> %t.in
+RUN: echo 'loop iter 15' >> %t.in
+RUN: echo 'loop iter 13' >> %t.in
+RUN: echo 'loop iter 10' >> %t.in
+RUN: echo 'loop iter 5' >> %t.in
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t.chk < %t.in 2>&1 \
+RUN: -dump-input-filter=error \
+RUN: | FileCheck %s -match-full-lines
Index: llvm/test/FileCheck/dump-input/filter-error-neighbor/check-label-follows.txt
===================================================================
--- /dev/null
+++ llvm/test/FileCheck/dump-input/filter-error-neighbor/check-label-follows.txt
@@ -0,0 +1,70 @@
+; The neighboring behavior of -dump-input-filter=error reveals input lines 12-16
+; below (neighbor of an error). 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.
+
+ CHECK:<<<<<<
+CHECK-NEXT: 1: offload triples:
+CHECK-NEXT:label:1'0 ^~~~~~~~~~~~~~~~
+CHECK-NEXT:label:1'1 ^~~~~~~~~~~~~~~~
+CHECK-NEXT: 2: - x86_64-linux-gnu
+CHECK-NEXT:check:2'0 X~~~~~~~~~~~~~~~~~ error: no match found
+CHECK-NEXT:check:2'1 ? possible intended match
+CHECK-NEXT: 3: - x86_64-unknown-linux-gnu
+CHECK-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+CHECK-NEXT: 4: - x86_64-pc-linux-gnu
+CHECK-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 12: - x86_64-amazon-linux
+CHECK-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~
+CHECK-NEXT: 13: - x86_64-linux-android
+CHECK-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~
+CHECK-NEXT: 14: host triples:
+CHECK-NEXT:label:3 ^~~~~~~~~~~~~
+CHECK-NEXT:check:2'0 ~~~~~~~~~~~~~
+CHECK-NEXT: 15: - nvptx64-nvidia-cuda
+CHECK-NEXT: 16: - x86_64-linux-gnu
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT:>>>>>>
+
+RUN: echo 'CHECK-LABEL: offload triples:' > %t.chk
+RUN: echo 'CHECK: nvptx64-nvidia-cuda' >> %t.chk
+RUN: echo 'CHECK-LABEL: host triples:' >> %t.chk
+
+RUN: echo 'offload triples:' > %t.in
+RUN: echo '- x86_64-linux-gnu' >> %t.in
+RUN: echo '- x86_64-unknown-linux-gnu' >> %t.in
+RUN: echo '- x86_64-pc-linux-gnu' >> %t.in
+RUN: echo '- x86_64-redhat-linux6E' >> %t.in
+RUN: echo '- x86_64-redhat-linux' >> %t.in
+RUN: echo '- x86_64-suse-linux' >> %t.in
+RUN: echo '- x86_64-manbo-linux-gnu' >> %t.in
+RUN: echo '- x86_64-linux-gnu' >> %t.in
+RUN: echo '- x86_64-slackware-linux' >> %t.in
+RUN: echo '- x86_64-unknown-linux' >> %t.in
+RUN: echo '- x86_64-amazon-linux' >> %t.in
+RUN: echo '- x86_64-linux-android' >> %t.in
+RUN: echo 'host triples:' >> %t.in
+RUN: echo '- nvptx64-nvidia-cuda' >> %t.in
+RUN: echo '- x86_64-linux-gnu' >> %t.in
+RUN: echo '- x86_64-unknown-linux-gnu' >> %t.in
+RUN: echo '- x86_64-pc-linux-gnu' >> %t.in
+RUN: echo '- x86_64-redhat-linux6E' >> %t.in
+RUN: echo '- x86_64-redhat-linux' >> %t.in
+RUN: echo '- x86_64-suse-linux' >> %t.in
+RUN: echo '- x86_64-manbo-linux-gnu' >> %t.in
+RUN: echo '- x86_64-linux-gnu' >> %t.in
+RUN: echo '- x86_64-slackware-linux' >> %t.in
+RUN: echo '- x86_64-unknown-linux' >> %t.in
+RUN: echo '- x86_64-amazon-linux' >> %t.in
+RUN: echo '- x86_64-linux-android' >> %t.in
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t.chk < %t.in 2>&1 \
+RUN: -dump-input-filter=error \
+RUN: | FileCheck %s -match-full-lines
Index: llvm/test/FileCheck/dump-input/filter-error-neighbor/check-next-same.txt
===================================================================
--- /dev/null
+++ llvm/test/FileCheck/dump-input/filter-error-neighbor/check-next-same.txt
@@ -0,0 +1,50 @@
+; The neighboring behavior of -dump-input-filter=error reveals input lines 1-3
+; below (neighbor preceding an error). Those lines are where the actual problem
+; is because that's where the CHECK-NEXT/CHECK-SAME directive was expected to
+; match but didn't. Seeing the line where CHECK-NEXT/CHECK-SAME actually
+; matched, line 13, is typically less useful information.
+
+ CHECK:<<<<<<
+CHECK-NEXT: 1: start
+CHECK-NEXT:check:1 ^~~~~
+CHECK-NEXT: 2: foo0
+CHECK-NEXT: 3: foo1
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 11: foo9
+CHECK-NEXT: 12: foo10
+CHECK-NEXT: 13: end
+ NEXT-NEXT:next:2 !~~ error: match on wrong line
+ SAME-NEXT:same:2 !~~ error: match on wrong line
+CHECK-NEXT:>>>>>>
+
+RUN: echo 'CHECK: start' > %t.next.chk
+RUN: echo 'CHECK-NEXT: end' >> %t.next.chk
+
+RUN: echo 'CHECK: start' > %t.same.chk
+RUN: echo 'CHECK-SAME: end' >> %t.same.chk
+
+RUN: echo start > %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 foo10 >> %t.in
+RUN: echo end >> %t.in
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t.next.chk < %t.in 2>&1 \
+RUN: -dump-input-filter=error \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=CHECK,NEXT
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t.same.chk < %t.in 2>&1 \
+RUN: -dump-input-filter=error \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=CHECK,SAME
Index: llvm/test/FileCheck/dump-input/filter-error-neighbor/check-not.txt
===================================================================
--- /dev/null
+++ llvm/test/FileCheck/dump-input/filter-error-neighbor/check-not.txt
@@ -0,0 +1,103 @@
+; The neighboring behavior of -dump-input-filter=error reveals input lines 1-3
+; and 60-63 below. With only the former (neighbor preceding an error), it looks
+; like the host list includes a GPU triple. The latter (neighbor following an
+; error) 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.
+
+ CHECK:<<<<<<
+CHECK-NEXT: 1:
+CHECK-NEXT:check:1 ^~~~~~~~~~~~~~~~~~~~~
+CHECK-NEXT: 2: x86_64-linux-gnu
+CHECK-NEXT: 3: x86_64-unknown-linux-gnu
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 42: x86_64-amazon-linux
+CHECK-NEXT: 43: x86_64-linux-android
+CHECK-NEXT: 44: nvptx64-nvidia-cuda
+CHECK-NEXT:not:2 !~~~~~~~~~~~~~~~~~~ error: no match expected
+CHECK-NEXT: 45: i686-linux-gnu
+CHECK-NEXT: 46: i686-pc-linux-gnu
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 60: i586-gnu
+CHECK-NEXT: 61: i686-gnu
+CHECK-NEXT: 62:
+CHECK-NEXT:check:3 ^~~~~~~~~~
+CHECK-NEXT: 63:
+CHECK-NEXT:>>>>>>
+
+RUN: echo 'CHECK: ' > %t.chk
+RUN: echo 'CHECK-NOT: nvptx64-nvidia-cuda' >> %t.chk
+RUN: echo 'CHECK: ' >> %t.chk
+
+RUN: echo '' > %t.in
+RUN: echo ' x86_64-linux-gnu' >> %t.in
+RUN: echo ' x86_64-unknown-linux-gnu' >> %t.in
+RUN: echo ' x86_64-pc-linux-gnu' >> %t.in
+RUN: echo ' x86_64-redhat-linux6E' >> %t.in
+RUN: echo ' x86_64-redhat-linux' >> %t.in
+RUN: echo ' x86_64-suse-linux' >> %t.in
+RUN: echo ' x86_64-manbo-linux-gnu' >> %t.in
+RUN: echo ' x86_64-linux-gnu' >> %t.in
+RUN: echo ' x86_64-slackware-linux' >> %t.in
+RUN: echo ' x86_64-unknown-linux' >> %t.in
+RUN: echo ' x86_64-amazon-linux' >> %t.in
+RUN: echo ' x86_64-linux-android' >> %t.in
+RUN: echo ' i686-linux-gnu' >> %t.in
+RUN: echo ' i686-pc-linux-gnu' >> %t.in
+RUN: echo ' i486-linux-gnu' >> %t.in
+RUN: echo ' i386-linux-gnu' >> %t.in
+RUN: echo ' i386-redhat-linux6E' >> %t.in
+RUN: echo ' i686-redhat-linux' >> %t.in
+RUN: echo ' i586-redhat-linux' >> %t.in
+RUN: echo ' i386-redhat-linux' >> %t.in
+RUN: echo ' i586-suse-linux' >> %t.in
+RUN: echo ' i486-slackware-linux' >> %t.in
+RUN: echo ' i686-montavista-linux' >> %t.in
+RUN: echo ' i586-linux-gnu' >> %t.in
+RUN: echo ' i686-linux-android' >> %t.in
+RUN: echo ' i386-gnu' >> %t.in
+RUN: echo ' i486-gnu' >> %t.in
+RUN: echo ' i586-gnu' >> %t.in
+RUN: echo ' i686-gnu' >> %t.in
+RUN: echo '' >> %t.in
+RUN: echo ' x86_64-linux-gnu' >> %t.in
+RUN: echo ' x86_64-unknown-linux-gnu' >> %t.in
+RUN: echo ' x86_64-pc-linux-gnu' >> %t.in
+RUN: echo ' x86_64-redhat-linux6E' >> %t.in
+RUN: echo ' x86_64-redhat-linux' >> %t.in
+RUN: echo ' x86_64-suse-linux' >> %t.in
+RUN: echo ' x86_64-manbo-linux-gnu' >> %t.in
+RUN: echo ' x86_64-linux-gnu' >> %t.in
+RUN: echo ' x86_64-slackware-linux' >> %t.in
+RUN: echo ' x86_64-unknown-linux' >> %t.in
+RUN: echo ' x86_64-amazon-linux' >> %t.in
+RUN: echo ' x86_64-linux-android' >> %t.in
+RUN: echo ' nvptx64-nvidia-cuda' >> %t.in
+RUN: echo ' i686-linux-gnu' >> %t.in
+RUN: echo ' i686-pc-linux-gnu' >> %t.in
+RUN: echo ' i486-linux-gnu' >> %t.in
+RUN: echo ' i386-linux-gnu' >> %t.in
+RUN: echo ' i386-redhat-linux6E' >> %t.in
+RUN: echo ' i686-redhat-linux' >> %t.in
+RUN: echo ' i586-redhat-linux' >> %t.in
+RUN: echo ' i386-redhat-linux' >> %t.in
+RUN: echo ' i586-suse-linux' >> %t.in
+RUN: echo ' i486-slackware-linux' >> %t.in
+RUN: echo ' i686-montavista-linux' >> %t.in
+RUN: echo ' i586-linux-gnu' >> %t.in
+RUN: echo ' i686-linux-android' >> %t.in
+RUN: echo ' i386-gnu' >> %t.in
+RUN: echo ' i486-gnu' >> %t.in
+RUN: echo ' i586-gnu' >> %t.in
+RUN: echo ' i686-gnu' >> %t.in
+RUN: echo '' >> %t.in
+RUN: echo '' >> %t.in
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t.chk < %t.in 2>&1 \
+RUN: -dump-input-filter=error \
+RUN: | FileCheck %s -match-full-lines
Index: llvm/test/FileCheck/dump-input/filter-error-neighbor/multiline.txt
===================================================================
--- /dev/null
+++ llvm/test/FileCheck/dump-input/filter-error-neighbor/multiline.txt
@@ -0,0 +1,112 @@
+; -dump-input-filter=error reveals only the first or last line of an annotation
+; neighboring an error, depending on whether it precedes or follows the error.
+; This test checks that we don't mix up first and last. Otherwise, a preceding
+; or following annotation can accidentally be omitted altogether. Of course,
+; we must have multiline annotations so that first != last.
+;
+; This test also checks that CHECK-LABEL is handled in the same way. That is,
+; CHECK-LABEL has additional special handling in that its match is revealed if
+; it precedes the last line of an error, but that special handling alone
+; wouldn't be sufficient for CHECK-LABEL here: it wouldn't reveal the first
+; CHECK-LABEL's match because the CHECK-NOT match has multiple lines.
+
+ CHECK:<<<<<<
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 3: start
+ CHK-NEXT:check:1 ~~~~~
+ LAB-NEXT:label:1'0 ~~~~~
+ LAB-NEXT:label:1'1 ~~~~~
+CHECK-NEXT: 4: start
+ CHK-NEXT:check:1 ~~~~~
+ LAB-NEXT:label:1'0 ~~~~~
+ LAB-NEXT:label:1'1 ~~~~~
+CHECK-NEXT: 5: start
+ CHK-NEXT:check:1 ~~~~~
+ LAB-NEXT:label:1'0 ~~~~~
+ LAB-NEXT:label:1'1 ~~~~~
+CHECK-NEXT: 6: bar
+CHECK-NEXT: 7: bar
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 14: bar
+CHECK-NEXT: 15: bar
+CHECK-NEXT: 16: foo
+CHECK-NEXT:not:2 !~~ error: no match expected
+CHECK-NEXT: 17: foo
+CHECK-NEXT:not:2 ~~~
+CHECK-NEXT: 18: bar
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: 26: bar
+CHECK-NEXT: 27: bar
+CHECK-NEXT: 28: end
+ CHK-NEXT:check:3 ^~~
+ LAB-NEXT:label:3'0 ^~~
+ LAB-NEXT:label:3'1 ^~~
+CHECK-NEXT: 29: end
+ CHK-NEXT:check:3 ~~~
+ LAB-NEXT:label:3'0 ~~~
+ LAB-NEXT:label:3'1 ~~~
+CHECK-NEXT: 30: end
+ CHK-NEXT:check:3 ~~~
+ LAB-NEXT:label:3'0 ~~~
+ LAB-NEXT:label:3'1 ~~~
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT: .
+CHECK-NEXT:>>>>>>
+
+RUN: echo 'CHECK: start{{([[:space:]]*start)+}}' > %t.chk.chk
+RUN: echo 'CHECK-NOT: foo{{([[:space:]]*foo)*}}' >> %t.chk.chk
+RUN: echo 'CHECK: end{{([[:space:]]*end)+}}' >> %t.chk.chk
+
+RUN: echo 'CHECK-LABEL: start{{([[:space:]]*start)+}}' > %t.lab.chk
+RUN: echo 'CHECK-NOT: foo{{([[:space:]]*foo)*}}' >> %t.lab.chk
+RUN: echo 'CHECK-LABEL: end{{([[:space:]]*end)+}}' >> %t.lab.chk
+
+RUN: echo 'start' > %t.in
+RUN: echo 'start' >> %t.in
+RUN: echo 'start' >> %t.in
+RUN: echo 'start' >> %t.in
+RUN: echo 'start' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'foo' >> %t.in
+RUN: echo 'foo' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'bar' >> %t.in
+RUN: echo 'end' >> %t.in
+RUN: echo 'end' >> %t.in
+RUN: echo 'end' >> %t.in
+RUN: echo 'end' >> %t.in
+RUN: echo 'end' >> %t.in
+
+XUN: %ProtectFileCheckOutput \
+XUN: not FileCheck -dump-input-context=2 -v %t.chk.chk < %t.in 2>&1 \
+XUN: -dump-input-filter=error \
+XUN: | FileCheck %s -match-full-lines -check-prefixes=CHECK,CHK
+
+RUN: %ProtectFileCheckOutput \
+RUN: not FileCheck -dump-input-context=2 -v %t.lab.chk < %t.in 2>&1 \
+RUN: -dump-input-filter=error \
+RUN: | FileCheck %s -match-full-lines -check-prefixes=CHECK,LAB
Index: llvm/test/FileCheck/dump-input/filter.txt
===================================================================
--- llvm/test/FileCheck/dump-input/filter.txt
+++ llvm/test/FileCheck/dump-input/filter.txt
@@ -215,6 +215,7 @@
; ERROR-NEXT: .
; ERROR-NEXT: .
; ERROR-NEXT: .
+; ERROR-NEXT: 10: foo8
; ERROR-NEXT: 11: foo9
; ERROR-NEXT: 12: hello
; ERROR-NEXT: check:2 ^~~~~
Index: llvm/utils/FileCheck/FileCheck.cpp
===================================================================
--- llvm/utils/FileCheck/FileCheck.cpp
+++ llvm/utils/FileCheck/FileCheck.cpp
@@ -156,6 +156,7 @@
"Input lines with starting points of annotations"),
clEnumValN(DumpInputFilterError, "error",
"Input lines with starting points of error "
+ "annotations or with annotations that neighbor error "
"annotations")));
static cl::list DumpInputContexts(
@@ -306,13 +307,18 @@
/// An annotation for a single input line.
struct InputAnnotation {
- /// The index of the match result across all checks
+ /// The index of the match result across all checks.
unsigned DiagIndex;
+ /// The kind of check that produced the match result.
+ Check::FileCheckType CheckTy;
/// The label for this annotation.
std::string Label;
- /// Is this the initial fragment of a diagnostic that has been broken across
- /// multiple lines?
+ /// Is this the initial annotation for a diagnostic, which might be broken
+ /// across multiple lines?
bool IsFirstLine;
+ /// Is this the last annotation for a diagnostic, which might be broken across
+ /// multiple lines?
+ bool IsLastLine;
/// What input line (one-origin indexing) this annotation marks. This might
/// be different from the starting line of the original diagnostic if
/// !IsFirstLine.
@@ -376,6 +382,7 @@
++DiagItr) {
InputAnnotation A;
A.DiagIndex = DiagCount++;
+ A.CheckTy = DiagItr->CheckTy;
// Build label, which uniquely identifies this check result.
unsigned CheckBufferID = SM.FindBufferContainingLoc(DiagItr->CheckLoc);
@@ -424,6 +431,7 @@
// Compute the mark location, and break annotation into multiple
// annotations if it spans multiple lines.
A.IsFirstLine = true;
+ A.IsLastLine = false;
A.InputLine = DiagItr->InputStartLine;
A.InputStartCol = DiagItr->InputStartCol;
if (DiagItr->InputStartLine == DiagItr->InputEndLine) {
@@ -446,8 +454,10 @@
break;
InputAnnotation B;
B.DiagIndex = A.DiagIndex;
+ B.CheckTy = A.CheckTy;
B.Label = A.Label;
B.IsFirstLine = false;
+ B.IsLastLine = false;
B.InputLine = L;
B.Marker = A.Marker;
B.Marker.Lead = '~';
@@ -461,16 +471,19 @@
Annotations.push_back(B);
}
}
+ Annotations.back().IsLastLine = true;
}
}
static unsigned FindInputLineInFilter(
DumpInputFilterValue DumpInputFilter, unsigned CurInputLine,
- const std::vector::iterator &AnnotationBeg,
- const std::vector::iterator &AnnotationEnd) {
+ const std::vector::iterator &AnnotationCur,
+ const std::vector &Annotations) {
if (DumpInputFilter == DumpInputFilterAll)
return CurInputLine;
- for (auto AnnotationItr = AnnotationBeg; AnnotationItr != AnnotationEnd;
+ auto AnnotationBeg = Annotations.begin();
+ auto AnnotationEnd = Annotations.end();
+ for (auto AnnotationItr = AnnotationCur; AnnotationItr != AnnotationEnd;
++AnnotationItr) {
switch (DumpInputFilter) {
case DumpInputFilterAll:
@@ -483,8 +496,50 @@
return AnnotationItr->InputLine;
break;
case DumpInputFilterError:
+ // If it's the first line of an error, include it.
if (AnnotationItr->IsFirstLine && AnnotationItr->Marker.FiltersAsError)
return AnnotationItr->InputLine;
+ // If it's a diagnostic's first line and it's after the last line of an
+ // error, include it. This might reveal an incorrect end to a search
+ // range.
+ if (AnnotationItr->IsFirstLine && AnnotationItr != AnnotationBeg) {
+ auto AnnotationPrev = std::prev(AnnotationItr);
+ if (AnnotationPrev->Marker.FiltersAsError && AnnotationPrev->IsLastLine)
+ return AnnotationItr->InputLine;
+ }
+ // If it's a diagnostic's last line and it's before the first line of an
+ // error, include it. This might reveal an incorrect start to a search
+ // range. It might reveal the incorrect text where a CHECK-NEXT or
+ // CHECK-SAME was expected to match but instead matched on a later line.
+ //
+ // As a special exception, if it's the last line of a CHECK-LABEL match
+ // before the last line of an error, include it. A CHECK-LABEL directive
+ // is processed before all other directives, so its annotation precedes
+ // the last line of an error that precedes it. Don't apply that exception
+ // generally, or a CHECK-DAG error can produce a spurious inclusion due to
+ // a successful CHECK-DAG at the end of the search range.
+ //
+ // Because we include last lines sometimes, input lines from
+ // DumpInputFilterError are not always a subset of input lines from
+ // DumpInputFilterAnnotation.
+ if (AnnotationItr->IsLastLine) {
+ auto AnnotationNext = std::next(AnnotationItr);
+ if (AnnotationNext != AnnotationEnd &&
+ AnnotationNext->Marker.FiltersAsError &&
+ (AnnotationNext->IsFirstLine ||
+ (AnnotationItr->CheckTy == Check::CheckLabel &&
+ AnnotationNext->IsLastLine)))
+ return AnnotationItr->InputLine;
+ }
+ // We have included only first and last lines of diagnostics so that we
+ // don't include a line within an error just because it's next to a
+ // "possible intended match" diagnostic. The "possible intended match"
+ // diagnostic is included on its own merits anyway, but the amount of
+ // context could be unexpectedly augmented.
+ //
+ // We have not included lines just because they're next to non-first and
+ // non-last error lines. Otherwise, a CHECK-DAG error could include many
+ // lines for successful matches from the same CHECK-DAG block.
break;
}
}
@@ -603,7 +658,7 @@
// Compute the previous and next line included by the filter.
if (NextLineInFilter < Line)
NextLineInFilter = FindInputLineInFilter(DumpInputFilter, Line,
- AnnotationItr, AnnotationEnd);
+ AnnotationItr, Annotations);
assert(NextLineInFilter && "expected NextLineInFilter to be computed");
if (NextLineInFilter == Line)
PrevLineInFilter = Line;