+size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
+ size_t &MatchLen,
+ StringMap<StringRef> &VariableTable) const {
+ size_t MatchPos = Pat.Match(Buffer, MatchLen, VariableTable);
+ if (MatchPos == StringRef::npos) {
+ PrintCheckFailed(SM, *this, Buffer, VariableTable);
+ return StringRef::npos;
+ }
+
+ StringRef SkippedRegion = Buffer.substr(0, MatchPos);
+
+ // If this check is a "CHECK-NEXT", verify that the previous match was on
+ // the previous line (i.e. that there is one newline between them).
+ if (CheckNext(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, VariableTable))
+ return StringRef::npos;
+
+ return MatchPos;
+}
+
+bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
+ if (!IsCheckNext)
+ 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-NEXT can't be the first check in a file");
+
+ unsigned NumNewLines = CountNumNewlinesBetween(Buffer);
+
+ if (NumNewLines == 0) {
+ SM.PrintMessage(Loc, SourceMgr::DK_Error, CheckPrefix+
+ "-NEXT: 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,
+ "previous match ended here");
+ return true;
+ }
+
+ if (NumNewLines != 1) {
+ SM.PrintMessage(Loc, SourceMgr::DK_Error, CheckPrefix+
+ "-NEXT: 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,
+ "previous match ended here");
+ return true;
+ }
+
+ return false;
+}
+
+bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
+ StringMap<StringRef> &VariableTable) const {
+ for (unsigned ChunkNo = 0, e = NotStrings.size();
+ ChunkNo != e; ++ChunkNo) {
+ size_t MatchLen = 0;
+ size_t Pos = NotStrings[ChunkNo].Match(Buffer, MatchLen, VariableTable);
+
+ if (Pos == StringRef::npos) continue;
+
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos),
+ SourceMgr::DK_Error,
+ CheckPrefix+"-NOT: string occurred!");
+ SM.PrintMessage(NotStrings[ChunkNo].getLoc(), SourceMgr::DK_Note,
+ CheckPrefix+"-NOT: pattern specified here");
+ return true;
+ }
+
+ return false;
+}
+