summaryrefslogtreecommitdiff
path: root/utils/FileCheck/FileCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/FileCheck/FileCheck.cpp')
-rw-r--r--utils/FileCheck/FileCheck.cpp373
1 files changed, 282 insertions, 91 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 7db97301637d..b9cd99e8ffd5 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -21,14 +21,14 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cctype>
+#include <list>
#include <map>
#include <string>
#include <system_error>
@@ -83,6 +83,28 @@ static cl::opt<bool> EnableVarScope(
"do not start with '$' will be reset at the beginning of\n"
"each CHECK-LABEL block."));
+static cl::opt<bool> AllowDeprecatedDagOverlap(
+ "allow-deprecated-dag-overlap", cl::init(false),
+ cl::desc("Enable overlapping among matches in a group of consecutive\n"
+ "CHECK-DAG directives. This option is deprecated and is only\n"
+ "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"));
+static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";
+
+static cl::opt<bool> DumpInputOnFailure(
+ "dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)),
+ cl::desc("Dump original input to stderr before failing.\n"
+ "The value can be also controlled using\n"
+ "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"));
+
typedef cl::list<std::string>::const_iterator prefix_iterator;
//===----------------------------------------------------------------------===//
@@ -98,6 +120,7 @@ enum CheckType {
CheckNot,
CheckDAG,
CheckLabel,
+ CheckEmpty,
/// Indicates the pattern only matches the end of file. This is used for
/// trailing CHECK-NOTs.
@@ -146,8 +169,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());
@@ -185,12 +211,25 @@ bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
// Check that there is something on the line.
- if (PatternStr.empty()) {
+ if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
"found empty check string with prefix '" + Prefix + ":'");
return true;
}
+ if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
+ SM.PrintMessage(
+ PatternLoc, SourceMgr::DK_Error,
+ "found non-empty check string for empty check with prefix '" + Prefix +
+ ":'");
+ return true;
+ }
+
+ if (CheckTy == Check::CheckEmpty) {
+ RegExStr = "(\n$)";
+ return false;
+ }
+
// Check to see if this is a fixed string, or if it has regex pieces.
if (!MatchFullLinesHere &&
(PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
@@ -463,8 +502,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;
}
@@ -490,11 +533,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()) {
@@ -526,11 +567,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
@@ -710,6 +759,9 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
case Check::CheckLabel:
return sizeof("-LABEL:") - 1;
+ case Check::CheckEmpty:
+ return sizeof("-EMPTY:") - 1;
+
case Check::CheckEOF:
llvm_unreachable("Should not be using EOF size");
}
@@ -717,7 +769,37 @@ 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;
+
char NextChar = Buffer[Prefix.size()];
// Verify that the : is present after the prefix.
@@ -743,10 +825,14 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
if (Rest.startswith("LABEL:"))
return Check::CheckLabel;
+ if (Rest.startswith("EMPTY:"))
+ return Check::CheckEmpty;
+
// You can't combine -NOT with another suffix.
if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
- Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:"))
+ Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
+ Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
return Check::CheckBadNot;
return Check::CheckNone;
@@ -906,10 +992,13 @@ static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
Buffer = Buffer.substr(EOL);
- // Verify that CHECK-NEXT lines have at least one CHECK line before them.
- if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
+ // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
+ if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
+ CheckTy == Check::CheckEmpty) &&
CheckStrings.empty()) {
- StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
+ StringRef Type = CheckTy == Check::CheckNext
+ ? "NEXT"
+ : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
SourceMgr::DK_Error,
"found '" + UsedPrefix + "-" + Type +
@@ -956,12 +1045,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.
@@ -971,13 +1097,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.
@@ -1025,9 +1154,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
@@ -1055,22 +1185,27 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
/// Verify there is a single line in the given buffer.
bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
- if (Pat.getCheckTy() != Check::CheckNext)
+ if (Pat.getCheckTy() != Check::CheckNext &&
+ Pat.getCheckTy() != Check::CheckEmpty)
return false;
+ Twine CheckName =
+ Prefix +
+ Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
+
// Count the number of newlines between the previous match and this one.
assert(Buffer.data() !=
SM.getMemoryBuffer(SM.FindBufferContainingLoc(
SMLoc::getFromPointer(Buffer.data())))
->getBufferStart() &&
- "CHECK-NEXT can't be the first check in a file");
+ "CHECK-NEXT and CHECK-EMPTY can't be the first check in a file");
const char *FirstNewLine = nullptr;
unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
if (NumNewLines == 0) {
SM.PrintMessage(Loc, SourceMgr::DK_Error,
- Prefix + "-NEXT: is on the same line as previous match");
+ CheckName + ": is on the same line as previous match");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
"'next' match was here");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
@@ -1080,8 +1215,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
if (NumNewLines != 1) {
SM.PrintMessage(Loc, SourceMgr::DK_Error,
- Prefix +
- "-NEXT: is not on the line after the previous match");
+ CheckName +
+ ": is not on the line after the previous match");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
"'next' match was here");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
@@ -1133,13 +1268,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;
}
@@ -1153,10 +1290,23 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
if (DagNotStrings.empty())
return 0;
- size_t LastPos = 0;
- size_t StartPos = LastPos;
-
- for (const Pattern &Pat : DagNotStrings) {
+ // The start of the search range.
+ size_t StartPos = 0;
+
+ struct MatchRange {
+ size_t Pos;
+ size_t End;
+ };
+ // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
+ // ranges are erased from this list once they are no longer in the search
+ // range.
+ std::list<MatchRange> MatchRanges;
+
+ // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
+ // group, so we don't use a range-based for loop here.
+ for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
+ PatItr != PatEnd; ++PatItr) {
+ const Pattern &Pat = *PatItr;
assert((Pat.getCheckTy() == Check::CheckDAG ||
Pat.getCheckTy() == Check::CheckNot) &&
"Invalid CHECK-DAG or CHECK-NOT!");
@@ -1168,57 +1318,92 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
- size_t MatchLen = 0, MatchPos;
-
// CHECK-DAG always matches from the start.
- StringRef MatchBuffer = Buffer.substr(StartPos);
- MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
- // With a group of CHECK-DAGs, a single mismatching means the match on
- // that group of CHECK-DAGs fails immediately.
- if (MatchPos == StringRef::npos) {
- PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
- return StringRef::npos;
- }
- // Re-calc it as the offset relative to the start of the original string.
- MatchPos += StartPos;
-
- if (!NotStrings.empty()) {
- if (MatchPos < LastPos) {
- // Reordered?
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
- SourceMgr::DK_Error,
- Prefix + "-DAG: found a match of CHECK-DAG"
- " reordering across a CHECK-NOT");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
- SourceMgr::DK_Note,
- Prefix + "-DAG: the farthest match of CHECK-DAG"
- " is found here");
- SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
- Prefix + "-NOT: the crossed pattern specified"
- " here");
- SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
- Prefix + "-DAG: the reordered pattern specified"
- " here");
+ size_t MatchLen = 0, MatchPos = StartPos;
+
+ // Search for a match that doesn't overlap a previous match in this
+ // CHECK-DAG group.
+ for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
+ StringRef MatchBuffer = Buffer.substr(MatchPos);
+ size_t MatchPosBuf = Pat.Match(MatchBuffer, MatchLen, VariableTable);
+ // With a group of CHECK-DAGs, a single mismatching means the match on
+ // that group of CHECK-DAGs fails immediately.
+ if (MatchPosBuf == StringRef::npos) {
+ PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, MatchBuffer,
+ VariableTable);
return StringRef::npos;
}
- // All subsequent CHECK-DAGs should be matched from the farthest
- // position of all precedent CHECK-DAGs (including this one.)
- StartPos = LastPos;
- // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
- // CHECK-DAG, verify that there's no 'not' strings occurred in that
- // region.
- StringRef SkippedRegion = Buffer.slice(LastPos, MatchPos);
- if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
- return StringRef::npos;
- // Clear "not strings".
- NotStrings.clear();
+ // 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);
+ MatchRange M{MatchPos, MatchPos + MatchLen};
+ if (AllowDeprecatedDagOverlap) {
+ // We don't need to track all matches in this mode, so we just maintain
+ // one match range that encompasses the current CHECK-DAG group's
+ // matches.
+ if (MatchRanges.empty())
+ MatchRanges.insert(MatchRanges.end(), M);
+ else {
+ auto Block = MatchRanges.begin();
+ Block->Pos = std::min(Block->Pos, M.Pos);
+ Block->End = std::max(Block->End, M.End);
+ }
+ break;
+ }
+ // Iterate previous matches until overlapping match or insertion point.
+ bool Overlap = false;
+ for (; MI != ME; ++MI) {
+ if (M.Pos < MI->End) {
+ // !Overlap => New match has no overlap and is before this old match.
+ // Overlap => New match overlaps this old match.
+ Overlap = MI->Pos < M.End;
+ break;
+ }
+ }
+ if (!Overlap) {
+ // Insert non-overlapping match into list.
+ MatchRanges.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);
+
+ // Handle the end of a CHECK-DAG group.
+ if (std::next(PatItr) == PatEnd ||
+ std::next(PatItr)->getCheckTy() == Check::CheckNot) {
+ if (!NotStrings.empty()) {
+ // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
+ // CHECK-DAG, verify that there are no 'not' strings occurred in that
+ // region.
+ StringRef SkippedRegion =
+ Buffer.slice(StartPos, MatchRanges.begin()->Pos);
+ if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
+ return StringRef::npos;
+ // Clear "not strings".
+ NotStrings.clear();
+ }
+ // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
+ // end of this CHECK-DAG group's match range.
+ StartPos = MatchRanges.rbegin()->End;
+ // Don't waste time checking for (impossible) overlaps before that.
+ MatchRanges.clear();
}
-
- // Update the last position with CHECK-DAG matches.
- LastPos = std::max(MatchPos + MatchLen, LastPos);
}
- return LastPos;
+ return StartPos;
}
// A check prefix must contain only alphanumeric, hyphens and underscores.
@@ -1357,8 +1542,7 @@ bool CheckInput(SourceMgr &SM, StringRef Buffer,
}
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
+ InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
if (!ValidateCheckPrefixes()) {
@@ -1379,6 +1563,9 @@ int main(int argc, char **argv) {
return 2;
}
+ if (VerboseVerbose)
+ Verbose = true;
+
SourceMgr SM;
// Read the expected strings from the check file.
@@ -1425,5 +1612,9 @@ int main(int argc, char **argv) {
InputFileText, InputFile.getBufferIdentifier()),
SMLoc());
- return CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
+ int ExitCode = CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
+ if (ExitCode == 1 && DumpInputOnFailure)
+ errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n";
+
+ return ExitCode;
}