mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[FileCheck] Annotate input dump (4/7)
This patch implements input annotations for diagnostics that report unexpected matches for CHECK-NOT. Like wrong-line matches for CHECK-NEXT, CHECK-SAME, and CHECK-EMPTY, these annotations mark match ranges using red `!~~` to indicate bad matches that are errors. 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 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 error, fuzzy match 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 not:2 !~~~~~ error: no match expected >>>>>> $ cat check3 CHECK: abc CHECK-NOT: foobar CHECK: def $ cat input3 abc foobar def ``` Reviewed By: george.karpenkov, probinson Differential Revision: https://reviews.llvm.org/D53896 llvm-svn: 349421
This commit is contained in:
parent
dac11cd74f
commit
3ef7d597d8
@ -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 excluded pattern.
|
||||
MatchFinalButExcluded,
|
||||
/// Indicates the final match for an expected pattern, but the match is on
|
||||
/// the wrong line.
|
||||
MatchFinalButWrongLine,
|
||||
@ -210,7 +212,8 @@ struct FileCheckString {
|
||||
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
|
||||
const std::vector<const FileCheckPattern *> &NotStrings,
|
||||
StringMap<StringRef> &VariableTable,
|
||||
const FileCheckRequest &Req) const;
|
||||
const FileCheckRequest &Req,
|
||||
std::vector<FileCheckDiag> *Diags) const;
|
||||
size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
|
||||
std::vector<const FileCheckPattern *> &NotStrings,
|
||||
StringMap<StringRef> &VariableTable,
|
||||
|
@ -896,16 +896,18 @@ static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,
|
||||
int MatchedCount, StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable, size_t MatchPos,
|
||||
size_t MatchLen, const FileCheckRequest &Req) {
|
||||
size_t MatchLen, const FileCheckRequest &Req,
|
||||
std::vector<FileCheckDiag> *Diags) {
|
||||
if (ExpectedMatch) {
|
||||
if (!Req.Verbose)
|
||||
return;
|
||||
if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
|
||||
return;
|
||||
}
|
||||
SMLoc MatchStart = SMLoc::getFromPointer(Buffer.data() + MatchPos);
|
||||
SMLoc MatchEnd = SMLoc::getFromPointer(Buffer.data() + MatchPos + MatchLen);
|
||||
SMRange MatchRange(MatchStart, MatchEnd);
|
||||
SMRange MatchRange = ProcessMatchResult(
|
||||
ExpectedMatch ? FileCheckDiag::MatchTypeCount
|
||||
: FileCheckDiag::MatchFinalButExcluded,
|
||||
SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
|
||||
std::string Message = formatv("{0}: {1} string found in input",
|
||||
Pat.getCheckTy().getDescription(Prefix),
|
||||
(ExpectedMatch ? "expected" : "excluded"))
|
||||
@ -915,17 +917,19 @@ static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
|
||||
SM.PrintMessage(
|
||||
Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
|
||||
SM.PrintMessage(MatchStart, SourceMgr::DK_Note, "found here", {MatchRange});
|
||||
SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
|
||||
{MatchRange});
|
||||
Pat.PrintVariableUses(SM, Buffer, VariableTable, MatchRange);
|
||||
}
|
||||
|
||||
static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
const FileCheckString &CheckStr, int MatchedCount,
|
||||
StringRef Buffer, StringMap<StringRef> &VariableTable,
|
||||
size_t MatchPos, size_t MatchLen,
|
||||
FileCheckRequest &Req) {
|
||||
size_t MatchPos, size_t MatchLen, FileCheckRequest &Req,
|
||||
std::vector<FileCheckDiag> *Diags) {
|
||||
PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
|
||||
MatchedCount, Buffer, VariableTable, MatchPos, MatchLen, Req);
|
||||
MatchedCount, Buffer, VariableTable, MatchPos, MatchLen, Req,
|
||||
Diags);
|
||||
}
|
||||
|
||||
static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
@ -1036,7 +1040,7 @@ size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
|
||||
return StringRef::npos;
|
||||
}
|
||||
PrintMatch(true, SM, *this, i, MatchBuffer, VariableTable, MatchPos,
|
||||
CurrentMatchLen, Req);
|
||||
CurrentMatchLen, Req, Diags);
|
||||
|
||||
// move start point after the match
|
||||
LastMatchEnd += MatchPos + CurrentMatchLen;
|
||||
@ -1071,7 +1075,7 @@ size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
|
||||
|
||||
// If this match had "not strings", verify that they don't exist in the
|
||||
// skipped region.
|
||||
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req))
|
||||
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req, Diags))
|
||||
return StringRef::npos;
|
||||
}
|
||||
|
||||
@ -1154,10 +1158,11 @@ bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
|
||||
}
|
||||
|
||||
/// Verify there's no "not strings" in the given buffer.
|
||||
bool FileCheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
|
||||
const std::vector<const FileCheckPattern *> &NotStrings,
|
||||
StringMap<StringRef> &VariableTable,
|
||||
const FileCheckRequest &Req) const {
|
||||
bool FileCheckString::CheckNot(
|
||||
const SourceMgr &SM, StringRef Buffer,
|
||||
const std::vector<const FileCheckPattern *> &NotStrings,
|
||||
StringMap<StringRef> &VariableTable, const FileCheckRequest &Req,
|
||||
std::vector<FileCheckDiag> *Diags) const {
|
||||
for (const FileCheckPattern *Pat : NotStrings) {
|
||||
assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
|
||||
|
||||
@ -1171,7 +1176,7 @@ bool FileCheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
|
||||
}
|
||||
|
||||
PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, VariableTable,
|
||||
Pos, MatchLen, Req);
|
||||
Pos, MatchLen, Req, Diags);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1236,7 +1241,7 @@ FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
||||
MatchPos += MatchPosBuf;
|
||||
if (Req.VerboseVerbose)
|
||||
PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer,
|
||||
VariableTable, MatchPos, MatchLen, Req);
|
||||
VariableTable, MatchPos, MatchLen, Req, Diags);
|
||||
MatchRange M{MatchPos, MatchPos + MatchLen};
|
||||
if (Req.AllowDeprecatedDagOverlap) {
|
||||
// We don't need to track all matches in this mode, so we just maintain
|
||||
@ -1278,7 +1283,7 @@ FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
||||
}
|
||||
if (!Req.VerboseVerbose)
|
||||
PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, VariableTable,
|
||||
MatchPos, MatchLen, Req);
|
||||
MatchPos, MatchLen, Req, Diags);
|
||||
|
||||
// Handle the end of a CHECK-DAG group.
|
||||
if (std::next(PatItr) == PatEnd ||
|
||||
@ -1289,7 +1294,7 @@ FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
||||
// region.
|
||||
StringRef SkippedRegion =
|
||||
Buffer.slice(StartPos, MatchRanges.begin()->Pos);
|
||||
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req))
|
||||
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req, Diags))
|
||||
return StringRef::npos;
|
||||
// Clear "not strings".
|
||||
NotStrings.clear();
|
||||
|
@ -234,6 +234,53 @@
|
||||
; EMP2-NEXT: >>>>>>
|
||||
; EMP2-NOT: {{.}}
|
||||
|
||||
;--------------------------------------------------
|
||||
; CHECK-NOT
|
||||
;--------------------------------------------------
|
||||
|
||||
; No match (success) and unexpected match (error).
|
||||
|
||||
; RUN: echo 'hello' > %t.in
|
||||
; RUN: echo 'world' >> %t.in
|
||||
; RUN: echo 'again' >> %t.in
|
||||
|
||||
; RUN: echo 'CHECK-NOT: goodbye' > %t.chk
|
||||
; RUN: echo 'CHECK-NOT: world' >> %t.chk
|
||||
|
||||
; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
|
||||
; RUN: | FileCheck -match-full-lines %s -check-prefix=NOT
|
||||
; 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: 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
|
||||
|
||||
; NOT: <<<<<<
|
||||
; NOT-NEXT: 1: hello
|
||||
; NOT-NEXT: 2: world
|
||||
; NOT-NEXT: not:2 !~~~~ error: no match expected
|
||||
; NOT-NEXT: 3: again
|
||||
; NOT-NEXT: >>>>>>
|
||||
; NOT-NOT: {{.}}
|
||||
|
||||
; Again, but with a CHECK instead of EOF as search range end.
|
||||
|
||||
; RUN: echo 'CHECK: ain' >> %t.chk
|
||||
|
||||
; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \
|
||||
; RUN: | FileCheck -match-full-lines %s -check-prefix=NOT2
|
||||
; 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: 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
|
||||
|
||||
; NOT2: <<<<<<
|
||||
; NOT2-NEXT: 1: hello
|
||||
; NOT2-NEXT: 2: world
|
||||
; NOT2-NEXT: not:2 !~~~~ error: no match expected
|
||||
; NOT2-NEXT: 3: again
|
||||
; NOT2-NEXT: >>>>>>
|
||||
; NOT2-NOT: {{.}}
|
||||
|
||||
;--------------------------------------------------
|
||||
; CHECK-DAG
|
||||
;--------------------------------------------------
|
||||
|
@ -143,6 +143,8 @@ struct MarkerStyle {
|
||||
|
||||
static MarkerStyle GetMarker(FileCheckDiag::MatchType MatchTy) {
|
||||
switch (MatchTy) {
|
||||
case FileCheckDiag::MatchFinalButExcluded:
|
||||
return MarkerStyle('!', raw_ostream::RED, "error: no match expected");
|
||||
case FileCheckDiag::MatchFinalButWrongLine:
|
||||
return MarkerStyle('!', raw_ostream::RED, "error: match on wrong line");
|
||||
case FileCheckDiag::MatchNoneButExpected:
|
||||
@ -182,6 +184,7 @@ static void DumpInputAnnotationHelp(raw_ostream &OS) {
|
||||
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "!~~";
|
||||
OS << " marks bad match, such as:\n"
|
||||
<< " - CHECK-NEXT on same line as previous match (error)\n"
|
||||
<< " - CHECK-NOT found (error)\n"
|
||||
<< " - ";
|
||||
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~";
|
||||
OS << " marks search range when no match is found, such as:\n"
|
||||
|
Loading…
Reference in New Issue
Block a user