[llvm] r349422 - [FileCheck] Annotate input dump (5/7)
Joel E. Denny via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 17 16:03:03 PST 2018
Author: jdenny
Date: Mon Dec 17 16:03:03 2018
New Revision: 349422
URL: http://llvm.org/viewvc/llvm-project?rev=349422&view=rev
Log:
[FileCheck] Annotate input dump (5/7)
This patch implements input annotations for diagnostics enabled by -v,
which report good matches for directives. These annotations mark
match ranges using `^~~`.
For example:
```
$ FileCheck -dump-input=help
The following description was requested by -dump-input=help to
explain the input annotations printed by -dump-input=always and
-dump-input=fail:
- L: labels line number L of the input file
- T:L labels the only match result for a pattern of type T from line L of
the check file
- T:L'N labels the Nth match result for a pattern of type T from line L of
the check file
- ^~~ marks good match (reported if -v)
- !~~ marks bad match, such as:
- CHECK-NEXT on same line as previous match (error)
- CHECK-NOT found (error)
- X~~ marks search range when no match is found, such as:
- CHECK-NEXT not found (error)
- ? marks fuzzy match when no match is found
- colors success, error, fuzzy match, unmatched input
If you are not seeing color above or in input dumps, try: -color
$ FileCheck -v -dump-input=always check3 < input3 |& sed -n '/^<<<</,$p'
<<<<<<
1: abc foobar def
check:1 ^~~
not:2 !~~~~~ error: no match expected
check:3 ^~~
>>>>>>
$ cat check3
CHECK: abc
CHECK-NOT: foobar
CHECK: def
$ cat input3
abc foobar def
```
-vv enables these annotations for FileCheck's implicit EOF patterns as
well. For an example where EOF patterns become relevant, see patch 7
in this series.
If colors are enabled, `^~~` is green to suggest success.
-v plus color enables highlighting of input text that has no final
match for any expected pattern. The highlight uses a cyan background
to suggest a cold section. This highlighting can make it easier to
spot text that was intended to be matched but that failed to be
matched in a long series of good matches.
CHECK-COUNT-<num> good matches are another case where there can be
multiple match results for the same directive.
Reviewed By: george.karpenkov, probinson
Differential Revision: https://reviews.llvm.org/D53897
Modified:
llvm/trunk/include/llvm/Support/FileCheck.h
llvm/trunk/lib/Support/FileCheck.cpp
llvm/trunk/test/FileCheck/dump-input-annotations.txt
llvm/trunk/test/FileCheck/dump-input-enable.txt
llvm/trunk/utils/FileCheck/FileCheck.cpp
Modified: llvm/trunk/include/llvm/Support/FileCheck.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/FileCheck.h?rev=349422&r1=349421&r2=349422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/FileCheck.h (original)
+++ llvm/trunk/include/llvm/Support/FileCheck.h Mon Dec 17 16:03:03 2018
@@ -163,6 +163,8 @@ struct FileCheckDiag {
/// example, there might be a fuzzy match after a fail.
enum MatchType {
// TODO: More members will appear with later patches in this series.
+ /// Indicates the final match for an expected pattern.
+ MatchFinalAndExpected,
/// Indicates the final match for an excluded pattern.
MatchFinalButExcluded,
/// Indicates the final match for an expected pattern, but the match is on
Modified: llvm/trunk/lib/Support/FileCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/FileCheck.cpp?rev=349422&r1=349421&r2=349422&view=diff
==============================================================================
--- llvm/trunk/lib/Support/FileCheck.cpp (original)
+++ llvm/trunk/lib/Support/FileCheck.cpp Mon Dec 17 16:03:03 2018
@@ -416,14 +416,19 @@ static SMRange ProcessMatchResult(FileCh
const SourceMgr &SM, SMLoc Loc,
Check::FileCheckType CheckTy,
StringRef Buffer, size_t Pos, size_t Len,
- std::vector<FileCheckDiag> *Diags) {
+ std::vector<FileCheckDiag> *Diags,
+ bool AdjustPrevDiag = false) {
SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
SMRange Range(Start, End);
// TODO: The second condition will disappear when we extend this to handle
// more match types.
- if (Diags && MatchTy != FileCheckDiag::MatchTypeCount)
- Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
+ if (Diags && MatchTy != FileCheckDiag::MatchTypeCount) {
+ if (AdjustPrevDiag)
+ Diags->rbegin()->MatchTy = MatchTy;
+ else
+ Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
+ }
return Range;
}
@@ -905,7 +910,7 @@ static void PrintMatch(bool ExpectedMatc
return;
}
SMRange MatchRange = ProcessMatchResult(
- ExpectedMatch ? FileCheckDiag::MatchTypeCount
+ ExpectedMatch ? FileCheckDiag::MatchFinalAndExpected
: FileCheckDiag::MatchFinalButExcluded,
SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
std::string Message = formatv("{0}: {1} string found in input",
@@ -1060,7 +1065,7 @@ size_t FileCheckString::Check(const Sour
if (CheckNext(SM, SkippedRegion)) {
ProcessMatchResult(FileCheckDiag::MatchFinalButWrongLine, SM, Loc,
Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
- Diags);
+ Diags, Req.Verbose);
return StringRef::npos;
}
@@ -1069,7 +1074,7 @@ size_t FileCheckString::Check(const Sour
if (CheckSame(SM, SkippedRegion)) {
ProcessMatchResult(FileCheckDiag::MatchFinalButWrongLine, SM, Loc,
Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
- Diags);
+ Diags, Req.Verbose);
return StringRef::npos;
}
@@ -1278,6 +1283,8 @@ FileCheckString::CheckDag(const SourceMg
SM.PrintMessage(OldStart, SourceMgr::DK_Note,
"match discarded, overlaps earlier DAG match here",
{OldRange});
+ if (Diags)
+ Diags->pop_back();
}
MatchPos = MI->End;
}
Modified: llvm/trunk/test/FileCheck/dump-input-annotations.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/dump-input-annotations.txt?rev=349422&r1=349421&r2=349422&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/dump-input-annotations.txt (original)
+++ llvm/trunk/test/FileCheck/dump-input-annotations.txt Mon Dec 17 16:03:03 2018
@@ -21,6 +21,7 @@
; ALIGN:Full input was:
; ALIGN-NEXT:<<<<<<
; ALIGN-NEXT: 1: hello world
+; ALIGN-NEXT:check:1 ^~~~~
; ALIGN-NEXT:check:2'0 X~~~~
; ALIGN-NEXT: 2: goodbye
; ALIGN-NEXT:check:2'0 ~~~~~~~
@@ -54,6 +55,7 @@
; CHK: <<<<<<
; CHK-NEXT: 1: hello
+; CHK-V-NEXT: check:1 ^~~~~
; CHK-NEXT: 2: again
; CHK-NEXT: check:2'0 X~~~~
; CHK-NEXT: 3: whirled
@@ -75,19 +77,22 @@
; RUN: echo 'CHECK-COUNT-3: pete' > %t.chk
; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefix=CNT
+; RUN: | FileCheck -match-full-lines %s -check-prefixes=CNT,CNT-Q
; 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: 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
-; CNT: <<<<<<
-; CNT-NEXT: 1: pete
-; CNT-NEXT: 2: repete
-; CNT-NEXT: 3: repeat
-; CNT-NEXT: count:1 X~~~~~ error: no match found
-; CNT-NEXT: >>>>>>
-; CNT-NOT: {{.}}
+; CNT: <<<<<<
+; CNT-NEXT: 1: pete
+; CNT-V-NEXT: count:1'0 ^~~~
+; CNT-NEXT: 2: repete
+; CNT-V-NEXT: count:1'1 ^~~~
+; CNT-NEXT: 3: repeat
+; CNT-Q-NEXT: count:1 X~~~~~ error: no match found
+; CNT-V-NEXT: count:1'2 X~~~~~ error: no match found
+; CNT-NEXT: >>>>>>
+; CNT-NOT: {{.}}
;--------------------------------------------------
; CHECK-NEXT (also: EOF search-range, wrong-line match)
@@ -110,10 +115,12 @@
; RUN: | FileCheck -match-full-lines %s -check-prefixes=NXT,NXT-V,NXT-VV
; NXT: <<<<<<
-; NXT-NEXT: 1: hello
-; NXT-NEXT: 2: again
-; NXT-NEXT: 3:
-; NXT-NEXT: next:3 X error: no match found
+; NXT-NEXT: 1: hello
+; NXT-V-NEXT: check:1 ^~~~~
+; NXT-NEXT: 2: again
+; NXT-V-NEXT: next:2 ^~~~~
+; NXT-NEXT: 3:
+; NXT-NEXT: next:3 X error: no match found
; NXT-NEXT: >>>>>>
; NXT-NOT: {{.}}
@@ -135,7 +142,8 @@
; NXT2-NOT: {{.}}
;--------------------------------------------------
-; CHECK-SAME (also: single-char search range, wrong-line match)
+; CHECK-SAME (also: multiple annotations per line, single-char search range,
+; wrong-line match)
;--------------------------------------------------
; Good match and no match.
@@ -154,8 +162,10 @@
; RUN: | FileCheck -match-full-lines %s -check-prefixes=SAM,SAM-V,SAM-VV
; SAM: <<<<<<
-; SAM-NEXT: 1: hello world!
-; SAM-NEXT: same:3 X error: no match found
+; 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: {{.}}
@@ -168,13 +178,16 @@
; 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: {{.}}
;--------------------------------------------------
-; CHECK-EMPTY (also: search range ends at label, wrong-line match)
+; CHECK-EMPTY (also: search range ends at label, single-char match, wrong-line
+; match)
;--------------------------------------------------
; Good match and no match.
@@ -203,11 +216,14 @@
; EMP: <<<<<<
; EMP-NEXT: 1: hello
+; EMP-V-NEXT: check:1 ^~~~~
; EMP-NEXT: 2:
+; EMP-V-NEXT: empty:2 ^
; EMP-NEXT: 3: world
; EMP-NEXT: empty:3 X~~~~
; EMP-NEXT: 4: label
; EMP-NEXT: empty:3 ~~~~~ error: no match found
+; EMP-V-NEXT: label:4 ^~~~~
; EMP-NEXT: >>>>>>
; EMP-NOT: {{.}}
@@ -228,6 +244,7 @@
; 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
@@ -235,7 +252,7 @@
; EMP2-NOT: {{.}}
;--------------------------------------------------
-; CHECK-NOT
+; CHECK-NOT (also: EOF pattern)
;--------------------------------------------------
; No match (success) and unexpected match (error).
@@ -259,6 +276,8 @@
; NOT-NEXT: 2: world
; NOT-NEXT: not:2 !~~~~ error: no match expected
; NOT-NEXT: 3: again
+; NOT-VV-NEXT: 4:
+; NOT-VV-NEXT: eof:2 ^
; NOT-NEXT: >>>>>>
; NOT-NOT: {{.}}
@@ -278,11 +297,12 @@
; NOT2-NEXT: 2: world
; NOT2-NEXT: not:2 !~~~~ error: no match expected
; NOT2-NEXT: 3: again
+; NOT2-V-NEXT: check:3 ^~~
; NOT2-NEXT: >>>>>>
; NOT2-NOT: {{.}}
;--------------------------------------------------
-; CHECK-DAG
+; CHECK-DAG (also: matches in different order than directives)
;--------------------------------------------------
; Good match, discarded match plus good match, and no match.
@@ -297,22 +317,28 @@
; RUN: echo 'CHECK-DAG: def' >> %t.chk
; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG
+; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG,DAG-Q
; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG
+; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG,DAG-V
; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \
-; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG
+; RUN: | FileCheck -match-full-lines %s -check-prefixes=DAG,DAG-V,DAG-VV
; DAG: <<<<<<
-; DAG-NEXT: 1: abc
-; DAG-NEXT: 2: def
-; DAG-NEXT: 3: abc
-; DAG-NEXT: dag:4 X~~ error: no match found
+; DAG-NEXT: 1: abc
+; DAG-V-NEXT: dag:2 ^~~
+; DAG-NEXT: 2: def
+; DAG-V-NEXT: dag:1 ^~~
+; DAG-NEXT: 3: abc
+; DAG-V-NEXT: dag:3 ^~~
+; DAG-NEXT: dag:4 X~~ error: no match found
; DAG-NEXT: >>>>>>
; DAG-NOT: {{.}}
;--------------------------------------------------
; CHECK-LABEL
+;
+; FIXME: Labels sometimes produce redundant diagnostics for good matches.
+; That bug is independent of but affects -dump-input.
;--------------------------------------------------
; Good match and no match.
@@ -335,6 +361,8 @@
; LAB: <<<<<<
; LAB-NEXT: 1: lab0
+; LAB-V-NEXT: label:1'0 ^~~~
+; LAB-V-NEXT: label:1'1 ^~~~
; LAB-NEXT: 2: foo
; LAB-NEXT: label:3'0 X~~
; LAB-NEXT: 3: lab1
Modified: llvm/trunk/test/FileCheck/dump-input-enable.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/dump-input-enable.txt?rev=349422&r1=349421&r2=349422&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/dump-input-enable.txt (original)
+++ llvm/trunk/test/FileCheck/dump-input-enable.txt Mon Dec 17 16:03:03 2018
@@ -112,7 +112,9 @@ HELP-NOT: {{.}}
; CHECK-GOOD: Full input was:
; CHECK-GOOD-NEXT: <<<<<<
; CHECK-GOOD-NEXT: 1: ciao
+; CHECK-GOOD-NEXT: check:1 ^~~~
; CHECK-GOOD-NEXT: 2: world
+; CHECK-GOOD-NEXT: next:2 ^~~~~
; CHECK-GOOD-NEXT: >>>>>>
; CHECK-ERR: Full input was:
Modified: llvm/trunk/utils/FileCheck/FileCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/FileCheck/FileCheck.cpp?rev=349422&r1=349421&r2=349422&view=diff
==============================================================================
--- llvm/trunk/utils/FileCheck/FileCheck.cpp (original)
+++ llvm/trunk/utils/FileCheck/FileCheck.cpp Mon Dec 17 16:03:03 2018
@@ -137,12 +137,15 @@ struct MarkerStyle {
/// A note to follow the marker, or empty string if none.
std::string Note;
MarkerStyle() {}
- MarkerStyle(char Lead, raw_ostream::Colors Color, const std::string &Note)
+ MarkerStyle(char Lead, raw_ostream::Colors Color,
+ const std::string &Note = "")
: Lead(Lead), Color(Color), Note(Note) {}
};
static MarkerStyle GetMarker(FileCheckDiag::MatchType MatchTy) {
switch (MatchTy) {
+ case FileCheckDiag::MatchFinalAndExpected:
+ return MarkerStyle('^', raw_ostream::GREEN);
case FileCheckDiag::MatchFinalButExcluded:
return MarkerStyle('!', raw_ostream::RED, "error: no match expected");
case FileCheckDiag::MatchFinalButWrongLine:
@@ -181,6 +184,9 @@ static void DumpInputAnnotationHelp(raw_
// Markers on annotation lines.
OS << " - ";
+ WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "^~~";
+ OS << " marks good match (reported if -v)\n"
+ << " - ";
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "!~~";
OS << " marks bad match, such as:\n"
<< " - CHECK-NEXT on same line as previous match (error)\n"
@@ -195,9 +201,13 @@ static void DumpInputAnnotationHelp(raw_
// Colors.
OS << " - colors ";
+ WithColor(OS, raw_ostream::GREEN, true) << "success";
+ OS << ", ";
WithColor(OS, raw_ostream::RED, true) << "error";
OS << ", ";
WithColor(OS, raw_ostream::MAGENTA, true) << "fuzzy match";
+ OS << ", ";
+ WithColor(OS, raw_ostream::CYAN, true, true) << "unmatched input";
OS << "\n\n"
<< "If you are not seeing color above or in input dumps, try: -color\n";
}
@@ -222,6 +232,8 @@ struct InputAnnotation {
unsigned InputStartCol, InputEndCol;
/// The marker to use.
MarkerStyle Marker;
+ /// Whether this annotation represents a final match for an expected pattern.
+ bool FinalAndExpectedMatch;
};
/// Get an abbreviation for the check type.
@@ -289,6 +301,8 @@ static void BuildInputAnnotations(const
MarkerStyle Marker = GetMarker(DiagItr->MatchTy);
A.Marker = Marker;
+ A.FinalAndExpectedMatch =
+ DiagItr->MatchTy == FileCheckDiag::MatchFinalAndExpected;
// Compute the mark location, and break annotation into multiple
// annotations if it spans multiple lines.
@@ -328,15 +342,17 @@ static void BuildInputAnnotations(const
B.Marker.Note = "";
} else
B.InputEndCol = DiagItr->InputEndCol;
+ B.FinalAndExpectedMatch = A.FinalAndExpectedMatch;
Annotations.push_back(B);
}
}
}
}
-static void DumpAnnotatedInput(
- raw_ostream &OS, StringRef InputFileText,
- std::vector<InputAnnotation> &Annotations, unsigned LabelWidth) {
+static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
+ StringRef InputFileText,
+ std::vector<InputAnnotation> &Annotations,
+ unsigned LabelWidth) {
OS << "Full input was:\n<<<<<<\n";
// Sort annotations.
@@ -359,9 +375,15 @@ static void DumpAnnotatedInput(
return A.InputLine < B.InputLine;
if (A.CheckLine != B.CheckLine)
return A.CheckLine < B.CheckLine;
- assert(A.CheckDiagIndex != B.CheckDiagIndex &&
- "expected diagnostic indices to be unique within a "
- " check line");
+ // FIXME: Sometimes CHECK-LABEL reports its match twice with
+ // other diagnostics in between, and then diag index incrementing
+ // fails to work properly, and then this assert fails. We should
+ // suppress one of those diagnostics or do a better job of
+ // computing this index. For now, we just produce a redundant
+ // CHECK-LABEL annotation.
+ // assert(A.CheckDiagIndex != B.CheckDiagIndex &&
+ // "expected diagnostic indices to be unique within a "
+ // " check line");
return A.CheckDiagIndex < B.CheckDiagIndex;
});
@@ -393,14 +415,45 @@ static void DumpAnnotatedInput(
WithColor(OS, raw_ostream::BLACK, true)
<< format_decimal(Line, LabelWidth) << ": ";
- // Print numbered line.
+ // For case where -v and colors are enabled, find the annotations for final
+ // matches for expected patterns in order to highlight everything else in
+ // the line. There are no such annotations if -v is disabled.
+ std::vector<InputAnnotation> FinalAndExpectedMatches;
+ if (Req.Verbose && WithColor(OS).colorsEnabled()) {
+ for (auto I = AnnotationItr; I != AnnotationEnd && I->InputLine == Line;
+ ++I) {
+ if (I->FinalAndExpectedMatch)
+ FinalAndExpectedMatches.push_back(*I);
+ }
+ }
+
+ // Print numbered line with highlighting where there are no matches for
+ // expected patterns.
bool Newline = false;
- while (InputFilePtr != InputFileEnd && !Newline) {
- if (*InputFilePtr == '\n')
- Newline = true;
- else
- OS << *InputFilePtr;
- ++InputFilePtr;
+ {
+ WithColor COS(OS);
+ bool InMatch = false;
+ if (Req.Verbose)
+ COS.changeColor(raw_ostream::CYAN, true, true);
+ for (unsigned Col = 1; InputFilePtr != InputFileEnd && !Newline; ++Col) {
+ bool WasInMatch = InMatch;
+ InMatch = false;
+ for (auto M : FinalAndExpectedMatches) {
+ if (M.InputStartCol <= Col && Col < M.InputEndCol) {
+ InMatch = true;
+ break;
+ }
+ }
+ if (!WasInMatch && InMatch)
+ COS.resetColor();
+ else if (WasInMatch && !InMatch)
+ COS.changeColor(raw_ostream::CYAN, true, true);
+ if (*InputFilePtr == '\n')
+ Newline = true;
+ else
+ COS << *InputFilePtr;
+ ++InputFilePtr;
+ }
}
OS << '\n';
unsigned InputLineWidth = InputFilePtr - InputFileLine - Newline;
@@ -561,7 +614,7 @@ int main(int argc, char **argv) {
std::vector<InputAnnotation> Annotations;
unsigned LabelWidth;
BuildInputAnnotations(Diags, Annotations, LabelWidth);
- DumpAnnotatedInput(errs(), InputFileText, Annotations, LabelWidth);
+ DumpAnnotatedInput(errs(), Req, InputFileText, Annotations, LabelWidth);
}
return ExitCode;
More information about the llvm-commits
mailing list