Optional<int> const ExceptionGuard(SourcePosition const&position, Pattern pattern) { try { return pattern.Match(position); } catch (Exception<String> exception) { throw Scanner::Error(exception.Position - position, exception.Error); } };
size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, size_t &MatchLen, StringMap<StringRef> &VariableTable) const { size_t LastPos = 0; std::vector<const Pattern *> NotStrings; // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL // bounds; we have not processed variable definitions within the bounded block // yet so cannot handle any final CHECK-DAG yet; this is handled when going // over the block again (including the last CHECK-LABEL) in normal mode. if (!IsLabelScanMode) { // Match "dag strings" (with mixed "not strings" if any). LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable); if (LastPos == StringRef::npos) return StringRef::npos; } // Match itself from the last position after matching CHECK-DAG. StringRef MatchBuffer = Buffer.substr(LastPos); size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); if (MatchPos == StringRef::npos) { PrintCheckFailed(SM, *this, MatchBuffer, VariableTable); return StringRef::npos; } // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT // or CHECK-NOT if (!IsLabelScanMode) { StringRef SkippedRegion = Buffer.substr(LastPos, 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 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 LastPos + MatchPos; }
bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector<const Pattern *> &NotStrings, StringMap<StringRef> &VariableTable) const { for (unsigned ChunkNo = 0, e = NotStrings.size(); ChunkNo != e; ++ChunkNo) { const Pattern *Pat = NotStrings[ChunkNo]; assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!"); size_t MatchLen = 0; size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable); if (Pos == StringRef::npos) continue; 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; } return false; }
size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector<const Pattern *> &NotStrings, StringMap<StringRef> &VariableTable) const { if (DagNotStrings.empty()) return 0; size_t LastPos = 0; size_t StartPos = LastPos; for (unsigned ChunkNo = 0, e = DagNotStrings.size(); ChunkNo != e; ++ChunkNo) { const Pattern &Pat = DagNotStrings[ChunkNo]; assert((Pat.getCheckTy() == Check::CheckDAG || Pat.getCheckTy() == Check::CheckNot) && "Invalid CHECK-DAG or CHECK-NOT!"); if (Pat.getCheckTy() == Check::CheckNot) { NotStrings.push_back(&Pat); continue; } 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"); 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.substr(LastPos, MatchPos); if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) return StringRef::npos; // Clear "not strings". NotStrings.clear(); } // Update the last position with CHECK-DAG matches. LastPos = std::max(MatchPos + MatchLen, LastPos); } return LastPos; }