aboutsummaryrefslogtreecommitdiff
path: root/utils/FileCheck
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
commit5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch)
treea6140557876943cdd800ee997c9317283394b22c /utils/FileCheck
parentf03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff)
Diffstat (limited to 'utils/FileCheck')
-rw-r--r--utils/FileCheck/FileCheck.cpp66
1 files changed, 56 insertions, 10 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 59affa1ada1b..8fe2f88a3e70 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -73,6 +73,7 @@ namespace Check {
CheckNone = 0,
CheckPlain,
CheckNext,
+ CheckSame,
CheckNot,
CheckDAG,
CheckLabel,
@@ -620,6 +621,9 @@ struct CheckString {
/// CheckNext - Verify there is a single line in the given buffer.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
+ /// CheckSame - Verify there is no newline in the given buffer.
+ bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
+
/// CheckNot - Verify there's no "not strings" in the given buffer.
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
const std::vector<const Pattern *> &NotStrings,
@@ -683,6 +687,9 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
case Check::CheckNext:
return sizeof("-NEXT:") - 1;
+ case Check::CheckSame:
+ return sizeof("-SAME:") - 1;
+
case Check::CheckNot:
return sizeof("-NOT:") - 1;
@@ -713,6 +720,9 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
if (Rest.startswith("NEXT:"))
return Check::CheckNext;
+ if (Rest.startswith("SAME:"))
+ return Check::CheckSame;
+
if (Rest.startswith("NOT:"))
return Check::CheckNot;
@@ -919,10 +929,12 @@ static bool ReadCheckFile(SourceMgr &SM,
Buffer = Buffer.substr(EOL);
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
- if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) {
+ if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
+ CheckStrings.empty()) {
+ StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
SourceMgr::DK_Error,
- "found '" + UsedPrefix + "-NEXT:' without previous '"
+ "found '" + UsedPrefix + "-" + Type + "' without previous '"
+ UsedPrefix + ": line");
return true;
}
@@ -946,7 +958,7 @@ static bool ReadCheckFile(SourceMgr &SM,
// prefix as a filler for the error message.
if (!DagNotMatches.empty()) {
CheckStrings.push_back(CheckString(Pattern(Check::CheckEOF),
- CheckPrefixes[0],
+ *CheckPrefixes.begin(),
SMLoc::getFromPointer(Buffer.data()),
Check::CheckEOF));
std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
@@ -955,12 +967,14 @@ static bool ReadCheckFile(SourceMgr &SM,
if (CheckStrings.empty()) {
errs() << "error: no check strings found with prefix"
<< (CheckPrefixes.size() > 1 ? "es " : " ");
- for (size_t I = 0, N = CheckPrefixes.size(); I != N; ++I) {
- StringRef Prefix(CheckPrefixes[I]);
- errs() << '\'' << Prefix << ":'";
- if (I != N - 1)
- errs() << ", ";
+ prefix_iterator I = CheckPrefixes.begin();
+ prefix_iterator E = CheckPrefixes.end();
+ if (I != E) {
+ errs() << "\'" << *I << ":'";
+ ++I;
}
+ for (; I != E; ++I)
+ errs() << ", \'" << *I << ":'";
errs() << '\n';
return true;
@@ -1041,7 +1055,6 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
return StringRef::npos;
}
- MatchPos += LastPos;
// Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
// or CHECK-NOT
@@ -1053,13 +1066,18 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
if (CheckNext(SM, SkippedRegion))
return StringRef::npos;
+ // If this check is a "CHECK-SAME", verify that the previous match was on
+ // the same line (i.e. that there is no newline between them).
+ if (CheckSame(SM, SkippedRegion))
+ return StringRef::npos;
+
// If this match had "not strings", verify that they don't exist in the
// skipped region.
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
return StringRef::npos;
}
- return MatchPos;
+ return LastPos + MatchPos;
}
bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
@@ -1101,6 +1119,34 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
return false;
}
+bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
+ if (CheckTy != Check::CheckSame)
+ return false;
+
+ // 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-SAME 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 +
+ "-SAME: is not on the same line as 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,
+ "previous match ended here");
+ return true;
+ }
+
+ return false;
+}
+
bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
const std::vector<const Pattern *> &NotStrings,
StringMap<StringRef> &VariableTable) const {