summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorJoel E. Denny <jdenny.ornl@gmail.com>2018-07-13 03:08:23 +0000
committerJoel E. Denny <jdenny.ornl@gmail.com>2018-07-13 03:08:23 +0000
commit9074a87ea5f5fc9fa96e955834a79465b59b6703 (patch)
tree0879cf47d85a3ffcfb5855b9cb7631ce1734523e /utils
parent8a35df349b49406e8e3028aee7668be9afe7e44b (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336967 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp170
1 files changed, 137 insertions, 33 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index cd3175f13f0..4efe535cecf 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -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.