forked from OSchip/llvm-project
[FileCheck] Implement -v and -vv for tracing matches
-v prints all directive pattern matches. -vv additionally prints info that might be noise to users but that can be helpful to FileCheck developers. To maximize code reuse and to make diagnostics more consistent, this patch also adjusts and extends some of the existing diagnostics. CHECK-NOT failures now report variables uses. Many more diagnostics now report the check prefix and kind of directive. Reviewed By: probinson Differential Revision: https://reviews.llvm.org/D47114 llvm-svn: 336967
This commit is contained in:
parent
01c762b9fd
commit
dc5ba317b1
|
@ -95,6 +95,16 @@ OPTIONS
|
|||
|
||||
Show the version number of this program.
|
||||
|
||||
.. option:: -v
|
||||
|
||||
Print directive pattern matches.
|
||||
|
||||
.. option:: -vv
|
||||
|
||||
Print information helpful in diagnosing internal FileCheck issues, such as
|
||||
discarded overlapping ``CHECK-DAG:`` matches, implicit EOF pattern matches,
|
||||
and ``CHECK-NOT:`` patterns that do not have matches. Implies ``-v``.
|
||||
|
||||
.. option:: --allow-deprecated-dag-overlap
|
||||
|
||||
Enable overlapping among matches in a group of consecutive ``CHECK-DAG:``
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
; EMPTY-ERR: FileCheck error: '-' is empty.
|
||||
; EMPTY-ERR-NEXT: FileCheck command line: {{.*}}FileCheck{{.*}}-check-prefix={{.*}}FOO {{.*}}check-empty.txt
|
||||
; NO-EMPTY-ERR-NOT: FileCheck error: '-' is empty.
|
||||
; NOT-FOUND: error: expected string not found in input
|
||||
; NOT-FOUND: error: FOO: expected string not found in input
|
||||
|
|
|
@ -7,5 +7,5 @@ CHECK-LABEL: {{^}}bar
|
|||
CHECK-DAG: {{^}}foo
|
||||
CHECK-LABEL: {{^}}zed
|
||||
|
||||
ERROR: error: expected string not found in input
|
||||
ERROR: error: CHECK-DAG: expected string not found in input
|
||||
ERROR-NEXT: CHECK-DAG: {{.....}}foo
|
||||
|
|
|
@ -8,5 +8,5 @@ bar
|
|||
; FOO: fo{{o}}
|
||||
; BAR: ba{{r}}
|
||||
|
||||
; CHECK: {{error: expected string not found in input}}
|
||||
; CHECK: {{error: FOO: expected string not found in input}}
|
||||
; CHECK-NEXT: {{F}}OO: fo{{[{][{]o[}][}]}}
|
||||
|
|
|
@ -8,5 +8,5 @@ foo
|
|||
; BAR: ba{{z}}
|
||||
; FOO: fo{{o}}
|
||||
|
||||
; CHECK: {{error: expected string not found in input}}
|
||||
; CHECK: {{error: BAR: expected string not found in input}}
|
||||
; CHECK-NEXT: {{B}}AR: ba{{[{][{]z[}][}]}}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
CHECK-NOT: test
|
||||
|
||||
DIAG: CHECK-NOT: pattern specified here
|
||||
DIAG: error: CHECK-NOT: excluded string found in input
|
||||
DIAG-NEXT: CHECK-NOT: test
|
||||
DIAG-NEXT: {{^ \^}}
|
||||
DIAG-NEXT: note: found here
|
||||
DIAG-NEXT: CHECK-NOT: test
|
||||
DIAG-NEXT: {{^ \^}}
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
; RUN: FileCheck -DVALUE=10 -input-file %s %s
|
||||
; RUN: not FileCheck -DVALUE=20 -input-file %s %s 2>&1 | FileCheck %s -check-prefix ERRMSG
|
||||
;
|
||||
; RUN: not FileCheck -DVALUE=10 -check-prefix NOT -input-file %s %s 2>&1 | FileCheck %s -check-prefix NOT-ERRMSG
|
||||
; RUN: FileCheck -DVALUE=20 -check-prefix NOT -input-file %s %s
|
||||
|
||||
Value = 10
|
||||
; CHECK: Value = [[VALUE]]
|
||||
; NOT-NOT: Value = [[VALUE]]
|
||||
|
||||
; ERRMSG: defines.txt:5:10: error: expected string not found in input
|
||||
; ERRMSG: defines.txt:8:10: error: CHECK: expected string not found in input
|
||||
; ERRMSG: defines.txt:1:1: note: scanning from here
|
||||
; ERRMSG: defines.txt:1:1: note: with variable "VALUE" equal to "20"
|
||||
; ERRMSG: defines.txt:4:1: note: possible intended match here
|
||||
; ERRMSG: defines.txt:7:1: note: possible intended match here
|
||||
|
||||
; NOT-ERRMSG: defines.txt:9:12: error: {{NOT}}-NOT: excluded string found in input
|
||||
; NOT-ERRMSG: defines.txt:7:1: note: found here
|
||||
; NOT-ERRMSG: defines.txt:7:1: note: with variable "VALUE" equal to "10"
|
|
@ -9,36 +9,36 @@
|
|||
|
||||
warning: aaa
|
||||
; CHECK-PASS: warning: aaa
|
||||
; CHECK-ERROR1: error: CHECK-FAIL1-NOT: string occurred!
|
||||
; CHECK-ERROR1: command line:1:22: note: CHECK-FAIL1-NOT: pattern specified here
|
||||
; CHECK-ERROR1: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
|
||||
; CHECK-ERROR1-NEXT: -implicit-check-not='warning:'
|
||||
; CHECK-ERROR1: note: found here
|
||||
; CHECK-FAIL2: warning: aaa
|
||||
; CHECK-FAIL3: warning: aaa
|
||||
; CHECK-ERROR4: error: CHECK-FAIL1-NOT: string occurred!
|
||||
; CHECK-ERROR4: command line:1:22: note: CHECK-FAIL1-NOT: pattern specified here
|
||||
; CHECK-ERROR4: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
|
||||
; CHECK-ERROR4-NEXT: {{-implicit-check-not='\{\{aaa\|bbb\|ccc\}\}'}}
|
||||
; CHECK-ERROR5: error: CHECK-FAIL1-NOT: string occurred!
|
||||
; CHECK-ERROR5: command line:1:22: note: CHECK-FAIL1-NOT: pattern specified here
|
||||
; CHECK-ERROR4: note: found here
|
||||
; CHECK-ERROR5: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
|
||||
; CHECK-ERROR5-NEXT: -implicit-check-not='aaa'
|
||||
; CHECK-ERROR5: note: found here
|
||||
|
||||
warning: bbb
|
||||
; CHECK-PASS: warning: bbb
|
||||
; CHECK-FAIL1: warning: bbb
|
||||
; CHECK-ERROR2: error: CHECK-FAIL2-NOT: string occurred!
|
||||
; CHECK-ERROR2: command line:1:22: note: CHECK-FAIL2-NOT: pattern specified here
|
||||
; CHECK-ERROR2: command line:1:22: error: CHECK-FAIL2-NOT: excluded string found in input
|
||||
; CHECK-ERROR2-NEXT: -implicit-check-not='warning:'
|
||||
; CHECK-ERROR2: note: found here
|
||||
; CHECK-FAIL3: warning: bbb
|
||||
; CHECK-ERROR6: error: CHECK-FAIL2-NOT: string occurred!
|
||||
; CHECK-ERROR6: command line:1:22: note: CHECK-FAIL2-NOT: pattern specified here
|
||||
; CHECK-ERROR6: command line:1:22: error: CHECK-FAIL2-NOT: excluded string found in input
|
||||
; CHECK-ERROR6-NEXT: -implicit-check-not='bbb'
|
||||
; CHECK-ERROR6: note: found here
|
||||
|
||||
warning: ccc
|
||||
; CHECK-PASS: warning: ccc
|
||||
; CHECK-FAIL1: warning: ccc
|
||||
; CHECK-FAIL2: warning: ccc
|
||||
; CHECK-ERROR3: error: CHECK-FAIL3-NOT: string occurred!
|
||||
; CHECK-ERROR3: command line:1:22: note: CHECK-FAIL3-NOT: pattern specified here
|
||||
; CHECK-ERROR3: command line:1:22: error: CHECK-FAIL3-NOT: excluded string found in input
|
||||
; CHECK-ERROR3-NEXT: -implicit-check-not='warning:'
|
||||
; CHECK-ERROR7: error: CHECK-FAIL3-NOT: string occurred!
|
||||
; CHECK-ERROR7: command line:1:22: note: CHECK-FAIL3-NOT: pattern specified here
|
||||
; CHECK-ERROR3: note: found here
|
||||
; CHECK-ERROR7: command line:1:22: error: CHECK-FAIL3-NOT: excluded string found in input
|
||||
; CHECK-ERROR7-NEXT: -implicit-check-not='ccc'
|
||||
; CHECK-ERROR7: note: found here
|
||||
|
|
|
@ -26,28 +26,28 @@ Label 66
|
|||
// CHECK:a line
|
||||
// CHECK:trailing whitespace
|
||||
// CHECK:trailing more whitespace
|
||||
// ERROR-STRICT:error: expected string not found in input
|
||||
// ERROR-STRICT:error: {{C}}HECK: expected string not found in input
|
||||
// ERROR-STRICT:// {{C}}HECK:trailing whitespace
|
||||
|
||||
// CHECK-LABEL:Label 2
|
||||
// CHECK:a line
|
||||
// CHECK-NEXT:leading whitespace
|
||||
// CHECK-NEXT: leading more whitespace
|
||||
// ERROR-STRICT:error: expected string not found in input
|
||||
// ERROR-STRICT:error: {{C}}HECK-NEXT: expected string not found in input
|
||||
// ERROR-STRICT:// {{C}}HECK-NEXT:leading whitespace
|
||||
|
||||
// CHECK-LABEL:Label 3
|
||||
// CHECK:line
|
||||
// ERROR:error: expected string not found in input
|
||||
// ERROR:error: {{C}}HECK: expected string not found in input
|
||||
// ERROR:// {{C}}HECK:line
|
||||
|
||||
// CHECK-LABEL:Label 4
|
||||
// CHECK:a line
|
||||
// CHECK-NOT:random
|
||||
// ERROR:error: {{C}}HECK-NOT: string occurred!
|
||||
// ERROR:error: {{C}}HECK-NOT: excluded string found in input
|
||||
// ERROR:a random thing
|
||||
|
||||
// CHECK-LABEL:Label 5
|
||||
// CHECK-LABEL:Label 6
|
||||
// ERROR:error: expected string not found in input
|
||||
// ERROR:error: {{C}}HECK-LABEL: expected string not found in input
|
||||
// ERROR:{{C}}HECK-LABEL:Label 6
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
; RUN: FileCheck -input-file %s %s 2>&1 | FileCheck -check-prefix QUIET --allow-empty %s
|
||||
; RUN: FileCheck -v -input-file %s %s 2>&1 | FileCheck -check-prefix V %s
|
||||
; RUN: FileCheck -vv -input-file %s %s 2>&1 | FileCheck -check-prefixes V,VV %s
|
||||
|
||||
foo
|
||||
bar
|
||||
CHECK: foo
|
||||
CHECK-NOT: raboof
|
||||
CHECK-NEXT: bar
|
||||
|
||||
V: verbose.txt:[[@LINE-4]]:8: remark: {{C}}HECK: expected string found in input
|
||||
V-NEXT: {{C}}HECK: foo{{$}}
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-9]]:1: note: found here
|
||||
V-NEXT: {{^}}foo{{$}}
|
||||
V-NEXT: {{^}}^~~{{$}}
|
||||
|
||||
V-NEXT: verbose.txt:[[@LINE-9]]:13: remark: {{C}}HECK-NEXT: expected string found in input
|
||||
V-NEXT: {{C}}HECK-NEXT: bar{{$}}
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-15]]:1: note: found here
|
||||
V-NEXT: {{^}}bar{{$}}
|
||||
V-NEXT: {{^}}^~~{{$}}
|
||||
|
||||
VV-NEXT: verbose.txt:[[@LINE-17]]:12: remark: {{C}}HECK-NOT: excluded string not found in input
|
||||
VV-NEXT: {{C}}HECK-NOT: raboof{{$}}
|
||||
VV-NEXT: {{^ \^$}}
|
||||
VV-NEXT: verbose.txt:[[@LINE-22]]:1: note: scanning from here
|
||||
VV-NEXT: {{^}}bar{{$}}
|
||||
VV-NEXT: {{^}}^{{$}}
|
||||
|
||||
before empty
|
||||
|
||||
after empty
|
||||
CHECK: before empty
|
||||
CHECK-EMPTY:
|
||||
CHECK-NEXT: after empty
|
||||
|
||||
V: verbose.txt:[[@LINE-4]]:8: remark: {{C}}HECK: expected string found in input
|
||||
V-NEXT: {{C}}HECK: before empty{{$}}
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-10]]:1: note: found here
|
||||
V-NEXT: {{^}}before empty{{$}}
|
||||
V-NEXT: {{^}}^~~~~~~~~~~~{{$}}
|
||||
|
||||
V-NEXT: verbose.txt:[[@LINE-10]]:13: remark: {{C}}HECK-EMPTY: expected string found in input
|
||||
V-NEXT: {{C}}HECK-EMPTY:{{$}}
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-16]]:1: note: found here
|
||||
V-EMPTY:
|
||||
V-NEXT: {{^}}^{{$}}
|
||||
|
||||
V-NEXT: verbose.txt:[[@LINE-16]]:13: remark: {{C}}HECK-NEXT: expected string found in input
|
||||
V-NEXT: {{C}}HECK-NEXT: after empty{{$}}
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-22]]:1: note: found here
|
||||
V-NEXT: {{^}}after empty{{$}}
|
||||
V-NEXT: {{^}}^~~~~~~~~~~{{$}}
|
||||
|
||||
abcdef
|
||||
abcdef
|
||||
CHECK-DAG: abcdef
|
||||
CHECK-DAG: def
|
||||
|
||||
V-NEXT: verbose.txt:[[@LINE-3]]:12: remark: {{C}}HECK-DAG: expected string found in input
|
||||
V-NEXT: {{C}}HECK-DAG: abcdef
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-8]]:1: note: found here
|
||||
V-NEXT: {{^}}abcdef{{$}}
|
||||
V-NEXT: {{^}}^~~~~~{{$}}
|
||||
|
||||
VV-NEXT: verbose.txt:[[@LINE-9]]:12: remark: {{C}}HECK-DAG: expected string found in input
|
||||
VV-NEXT: {{C}}HECK-DAG: def
|
||||
VV-NEXT: {{^ \^$}}
|
||||
VV-NEXT: verbose.txt:[[@LINE-15]]:4: note: found here
|
||||
VV-NEXT: {{^abcdef$}}
|
||||
VV-NEXT: {{^ \^~~$}}
|
||||
VV-NEXT: verbose.txt:[[@LINE-18]]:1: note: match discarded, overlaps earlier DAG match here
|
||||
VV-NEXT: {{^}}abcdef{{$}}
|
||||
VV-NEXT: {{^}}^~~~~~{{$}}
|
||||
|
||||
V-NEXT: verbose.txt:[[@LINE-19]]:12: remark: {{C}}HECK-DAG: expected string found in input
|
||||
V-NEXT: {{C}}HECK-DAG: def
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-24]]:4: note: found here
|
||||
V-NEXT: {{^abcdef$}}
|
||||
V-NEXT: {{^ \^~~$}}
|
||||
|
||||
xyz
|
||||
CHECK: xyz
|
||||
CHECK-NOT: {{z}}yx
|
||||
|
||||
V: verbose.txt:[[@LINE-3]]:8: remark: {{C}}HECK: expected string found in input
|
||||
V-NEXT: {{C}}HECK: xyz{{$}}
|
||||
V-NEXT: {{^ \^$}}
|
||||
V-NEXT: verbose.txt:[[@LINE-7]]:1: note: found here
|
||||
V-NEXT: {{^}}xyz{{$}}
|
||||
V-NEXT: {{^}}^~~{{$}}
|
||||
|
||||
VV-NEXT: verbose.txt:[[@LINE-9]]:19: remark: implicit EOF: expected string found in input
|
||||
VV-NEXT: {{C}}HECK-NOT: {{[{][{]z[}][}]yx$}}
|
||||
VV-NEXT: {{^ \^$}}
|
||||
VV-NEXT: verbose.txt:[[@LINE+13]]:1: note: found here
|
||||
VV-NOT: {{.}}
|
||||
VV: {{^\^$}}
|
||||
|
||||
VV-NEXT: verbose.txt:[[@LINE-16]]:12: remark: {{C}}HECK-NOT: excluded string not found in input
|
||||
VV-NEXT: {{C}}HECK-NOT: {{[{][{]z[}][}]yx$}}
|
||||
VV-NEXT: {{^ \^$}}
|
||||
VV-NEXT: verbose.txt:[[@LINE-20]]:1: note: scanning from here
|
||||
VV-NEXT: {{^C}}HECK: xyz{{$}}
|
||||
VV-NEXT: {{^\^$}}
|
||||
|
||||
QUIET-NOT: {{.}}
|
||||
V-NOT: {{.}}
|
|
@ -90,6 +90,14 @@ static cl::opt<bool> AllowDeprecatedDagOverlap(
|
|||
"provided for convenience as old tests are migrated to the new\n"
|
||||
"non-overlapping CHECK-DAG implementation.\n"));
|
||||
|
||||
static cl::opt<bool> Verbose("v", cl::init(false),
|
||||
cl::desc("Print directive pattern matches.\n"));
|
||||
|
||||
static cl::opt<bool> VerboseVerbose(
|
||||
"vv", cl::init(false),
|
||||
cl::desc("Print information helpful in diagnosing internal FileCheck\n"
|
||||
"issues. Implies -v.\n"));
|
||||
|
||||
typedef cl::list<std::string>::const_iterator prefix_iterator;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -154,8 +162,11 @@ public:
|
|||
unsigned LineNumber);
|
||||
size_t Match(StringRef Buffer, size_t &MatchLen,
|
||||
StringMap<StringRef> &VariableTable) const;
|
||||
void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const;
|
||||
void PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable,
|
||||
SMRange MatchRange = None) const;
|
||||
void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const;
|
||||
|
||||
bool hasVariable() const {
|
||||
return !(VariableUses.empty() && VariableDefs.empty());
|
||||
|
@ -484,8 +495,12 @@ size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
|
|||
VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
|
||||
}
|
||||
|
||||
MatchLen = FullMatch.size();
|
||||
return FullMatch.data() - Buffer.data();
|
||||
// Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
|
||||
// the required preceding newline, which is consumed by the pattern in the
|
||||
// case of CHECK-EMPTY but not CHECK-NEXT.
|
||||
size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
|
||||
MatchLen = FullMatch.size() - MatchStartSkip;
|
||||
return FullMatch.data() - Buffer.data() + MatchStartSkip;
|
||||
}
|
||||
|
||||
|
||||
|
@ -511,11 +526,9 @@ Pattern::ComputeMatchDistance(StringRef Buffer,
|
|||
return BufferPrefix.edit_distance(ExampleString);
|
||||
}
|
||||
|
||||
/// Prints additional information about a failure to match involving this
|
||||
/// pattern.
|
||||
void Pattern::PrintFailureInfo(
|
||||
const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const {
|
||||
void Pattern::PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable,
|
||||
SMRange MatchRange) const {
|
||||
// If this was a regular expression using variables, print the current
|
||||
// variable values.
|
||||
if (!VariableUses.empty()) {
|
||||
|
@ -547,11 +560,19 @@ void Pattern::PrintFailureInfo(
|
|||
}
|
||||
}
|
||||
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
|
||||
OS.str());
|
||||
if (MatchRange.isValid())
|
||||
SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
|
||||
{MatchRange});
|
||||
else
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
|
||||
SourceMgr::DK_Note, OS.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Pattern::PrintFuzzyMatch(
|
||||
const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const {
|
||||
// Attempt to find the closest/best fuzzy match. Usually an error happens
|
||||
// because some string in the output didn't exactly match. In these cases, we
|
||||
// would like to show the user a best guess at what "should have" matched, to
|
||||
|
@ -741,6 +762,33 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
|
|||
llvm_unreachable("Bad check type");
|
||||
}
|
||||
|
||||
// Get a description of the type.
|
||||
static std::string CheckTypeName(StringRef Prefix, Check::CheckType Ty) {
|
||||
switch (Ty) {
|
||||
case Check::CheckNone:
|
||||
return "invalid";
|
||||
case Check::CheckPlain:
|
||||
return Prefix;
|
||||
case Check::CheckNext:
|
||||
return Prefix.str() + "-NEXT";
|
||||
case Check::CheckSame:
|
||||
return Prefix.str() + "-SAME";
|
||||
case Check::CheckNot:
|
||||
return Prefix.str() + "-NOT";
|
||||
case Check::CheckDAG:
|
||||
return Prefix.str() + "-DAG";
|
||||
case Check::CheckLabel:
|
||||
return Prefix.str() + "-LABEL";
|
||||
case Check::CheckEmpty:
|
||||
return Prefix.str() + "-EMPTY";
|
||||
case Check::CheckEOF:
|
||||
return "implicit EOF";
|
||||
case Check::CheckBadNot:
|
||||
return "bad NOT";
|
||||
}
|
||||
llvm_unreachable("unknown CheckType");
|
||||
}
|
||||
|
||||
static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
|
||||
if (Buffer.size() <= Prefix.size())
|
||||
return Check::CheckNone;
|
||||
|
@ -990,12 +1038,49 @@ static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
|
||||
StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
StringRef Prefix, SMLoc Loc, const Pattern &Pat,
|
||||
StringRef Buffer, StringMap<StringRef> &VariableTable,
|
||||
size_t MatchPos, size_t MatchLen) {
|
||||
if (ExpectedMatch) {
|
||||
if (!Verbose)
|
||||
return;
|
||||
if (!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);
|
||||
SM.PrintMessage(
|
||||
Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error,
|
||||
CheckTypeName(Prefix, Pat.getCheckTy()) + ": " +
|
||||
(ExpectedMatch ? "expected" : "excluded") +
|
||||
" string found in input");
|
||||
SM.PrintMessage(MatchStart, SourceMgr::DK_Note, "found here", {MatchRange});
|
||||
Pat.PrintVariableUses(SM, Buffer, VariableTable, MatchRange);
|
||||
}
|
||||
|
||||
static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
const CheckString &CheckStr, StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable, size_t MatchPos,
|
||||
size_t MatchLen) {
|
||||
PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
|
||||
Buffer, VariableTable, MatchPos, MatchLen);
|
||||
}
|
||||
|
||||
static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
StringRef Prefix, SMLoc Loc, const Pattern &Pat,
|
||||
StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
if (!ExpectedMatch && !VerboseVerbose)
|
||||
return;
|
||||
|
||||
// Otherwise, we have an error, emit an error message.
|
||||
SM.PrintMessage(Loc, SourceMgr::DK_Error,
|
||||
"expected string not found in input");
|
||||
SM.PrintMessage(Loc,
|
||||
ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark,
|
||||
CheckTypeName(Prefix, Pat.getCheckTy()) + ": " +
|
||||
(ExpectedMatch ? "expected" : "excluded") +
|
||||
" string not found in input");
|
||||
|
||||
// Print the "scanning from here" line. If the current position is at the
|
||||
// end of a line, advance to the start of the next line.
|
||||
|
@ -1005,13 +1090,16 @@ static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
|
|||
"scanning from here");
|
||||
|
||||
// Allow the pattern to print additional information if desired.
|
||||
Pat.PrintFailureInfo(SM, Buffer, VariableTable);
|
||||
Pat.PrintVariableUses(SM, Buffer, VariableTable);
|
||||
if (ExpectedMatch)
|
||||
Pat.PrintFuzzyMatch(SM, Buffer, VariableTable);
|
||||
}
|
||||
|
||||
static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
|
||||
StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
|
||||
static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
const CheckString &CheckStr, StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
|
||||
Buffer, VariableTable);
|
||||
}
|
||||
|
||||
/// Count the number of newlines in the specified range.
|
||||
|
@ -1059,9 +1147,10 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
|
|||
StringRef MatchBuffer = Buffer.substr(LastPos);
|
||||
size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
|
||||
if (MatchPos == StringRef::npos) {
|
||||
PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
|
||||
PrintNoMatch(true, SM, *this, MatchBuffer, VariableTable);
|
||||
return StringRef::npos;
|
||||
}
|
||||
PrintMatch(true, SM, *this, MatchBuffer, VariableTable, MatchPos, MatchLen);
|
||||
|
||||
// Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
|
||||
// or CHECK-NOT
|
||||
|
@ -1107,11 +1196,6 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
|
|||
const char *FirstNewLine = nullptr;
|
||||
unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
|
||||
|
||||
// For CHECK-EMPTY, the preceding new line is consumed by the pattern, so
|
||||
// this needs to be re-added.
|
||||
if (Pat.getCheckTy() == Check::CheckEmpty)
|
||||
++NumNewLines;
|
||||
|
||||
if (NumNewLines == 0) {
|
||||
SM.PrintMessage(Loc, SourceMgr::DK_Error,
|
||||
CheckName + ": is on the same line as previous match");
|
||||
|
@ -1177,13 +1261,15 @@ bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
|
|||
size_t MatchLen = 0;
|
||||
size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
|
||||
|
||||
if (Pos == StringRef::npos)
|
||||
if (Pos == StringRef::npos) {
|
||||
PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, Buffer,
|
||||
VariableTable);
|
||||
continue;
|
||||
}
|
||||
|
||||
PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, Buffer, VariableTable,
|
||||
Pos, MatchLen);
|
||||
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos),
|
||||
SourceMgr::DK_Error, Prefix + "-NOT: string occurred!");
|
||||
SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
|
||||
Prefix + "-NOT: pattern specified here");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1230,11 +1316,15 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
|||
// With a group of CHECK-DAGs, a single mismatching means the match on
|
||||
// that group of CHECK-DAGs fails immediately.
|
||||
if (MatchPosBuf == StringRef::npos) {
|
||||
PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
|
||||
PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, MatchBuffer,
|
||||
VariableTable);
|
||||
return StringRef::npos;
|
||||
}
|
||||
// Re-calc it as the offset relative to the start of the original string.
|
||||
MatchPos += MatchPosBuf;
|
||||
if (VerboseVerbose)
|
||||
PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, Buffer, VariableTable,
|
||||
MatchPos, MatchLen);
|
||||
if (AllowDeprecatedDagOverlap)
|
||||
break;
|
||||
// Iterate previous matches until overlapping match or insertion point.
|
||||
|
@ -1253,8 +1343,19 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
|||
Matches.insert(MI, M);
|
||||
break;
|
||||
}
|
||||
if (VerboseVerbose) {
|
||||
SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
|
||||
SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
|
||||
SMRange OldRange(OldStart, OldEnd);
|
||||
SM.PrintMessage(OldStart, SourceMgr::DK_Note,
|
||||
"match discarded, overlaps earlier DAG match here",
|
||||
{OldRange});
|
||||
}
|
||||
MatchPos = MI->End;
|
||||
}
|
||||
if (!VerboseVerbose)
|
||||
PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, Buffer, VariableTable,
|
||||
MatchPos, MatchLen);
|
||||
|
||||
if (!NotStrings.empty()) {
|
||||
if (MatchPos < LastPos) {
|
||||
|
@ -1455,6 +1556,9 @@ int main(int argc, char **argv) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
if (VerboseVerbose)
|
||||
Verbose = true;
|
||||
|
||||
SourceMgr SM;
|
||||
|
||||
// Read the expected strings from the check file.
|
||||
|
|
Loading…
Reference in New Issue