diff options
Diffstat (limited to 'utils/FileCheck/FileCheck.cpp')
-rw-r--r-- | utils/FileCheck/FileCheck.cpp | 123 |
1 files changed, 94 insertions, 29 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 5e2d93bf39..e252db9141 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -115,6 +115,9 @@ public: void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, const StringMap<StringRef> &VariableTable) const; + bool hasVariable() const { return !(VariableUses.empty() && + VariableDefs.empty()); } + void setMatchNot(bool Not) { MatchNot = Not; } bool getMatchNot() const { return MatchNot; } @@ -594,17 +597,21 @@ struct CheckString { /// to a CHECK: directive. bool IsCheckNext; + /// IsCheckLabel - This is true if this is a CHECK-LABEL: directive (as + /// opposed to a CHECK: directive. + bool IsCheckLabel; + /// DagNotStrings - These are all of the strings that are disallowed from /// occurring between this match string and the previous one (or start of /// file). std::vector<Pattern> DagNotStrings; - CheckString(const Pattern &P, SMLoc L, bool isCheckNext) - : Pat(P), Loc(L), IsCheckNext(isCheckNext) {} + CheckString(const Pattern &P, SMLoc L, bool isCheckNext, bool isCheckLabel) + : Pat(P), Loc(L), IsCheckNext(isCheckNext), IsCheckLabel(isCheckLabel) {} /// Check - Match check string and its "not strings" and/or "dag strings". - size_t Check(const SourceMgr &SM, StringRef Buffer, size_t &MatchLen, - StringMap<StringRef> &VariableTable) const; + size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabel, + size_t &MatchLen, StringMap<StringRef> &VariableTable) const; /// CheckNext - Verify there is a single line in the given buffer. bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; @@ -703,7 +710,8 @@ static bool ReadCheckFile(SourceMgr &SM, // When we find a check prefix, keep track of whether we find CHECK: or // CHECK-NEXT: - bool IsCheckNext = false, IsCheckNot = false, IsCheckDag = false; + bool IsCheckNext = false, IsCheckNot = false, IsCheckDag = false, + IsCheckLabel = false; // Verify that the : is present after the prefix. if (Buffer[CheckPrefix.size()] == ':') { @@ -720,6 +728,10 @@ static bool ReadCheckFile(SourceMgr &SM, memcmp(Buffer.data()+CheckPrefix.size(), "-DAG:", 5) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+5); IsCheckDag = true; + } else if (Buffer.size() > CheckPrefix.size()+7 && + memcmp(Buffer.data()+CheckPrefix.size(), "-LABEL:", 7) == 0) { + Buffer = Buffer.substr(CheckPrefix.size()+7); + IsCheckLabel = true; } else { Buffer = Buffer.substr(1); continue; @@ -740,6 +752,15 @@ static bool ReadCheckFile(SourceMgr &SM, if (P.ParsePattern(Buffer.substr(0, EOL), SM, LineNumber)) return true; + // Verify that CHECK-LABEL lines do not define or use variables + if (IsCheckLabel && P.hasVariable()) { + SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), + SourceMgr::DK_Error, + "found '"+CheckPrefix+"-LABEL:' with variable definition" + " or use'"); + return true; + } + P.setMatchNot(IsCheckNot); P.setMatchDag(IsCheckDag); @@ -763,7 +784,8 @@ static bool ReadCheckFile(SourceMgr &SM, // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, PatternLoc, - IsCheckNext)); + IsCheckNext, + IsCheckLabel)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); } @@ -771,6 +793,7 @@ static bool ReadCheckFile(SourceMgr &SM, if (!DagNotMatches.empty()) { CheckStrings.push_back(CheckString(Pattern(true), SMLoc::getFromPointer(Buffer.data()), + false, false)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); } @@ -829,15 +852,17 @@ static unsigned CountNumNewlinesBetween(StringRef Range) { } size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, - size_t &MatchLen, + bool IsLabel, size_t &MatchLen, StringMap<StringRef> &VariableTable) const { size_t LastPos = 0; std::vector<const Pattern *> NotStrings; - // Match "dag strings" (with mixed "not strings" if any). - LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable); - if (LastPos == StringRef::npos) - return StringRef::npos; + if (!IsLabel) { + // 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); @@ -848,17 +873,19 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, } MatchPos += LastPos; - StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); + if (!IsLabel) { + 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-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, NotStrings, VariableTable)) - 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; } @@ -1040,18 +1067,56 @@ int main(int argc, char **argv) { // file. StringRef Buffer = F->getBuffer(); - for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) { - const CheckString &CheckStr = CheckStrings[StrNo]; + bool hasError = false; - // Find StrNo in the file. - size_t MatchLen = 0; - size_t MatchPos = CheckStr.Check(SM, Buffer, MatchLen, VariableTable); + unsigned i = 0, j = 0, e = CheckStrings.size(); + + while (true) { + StringRef CheckRegion; + if (j == e) { + CheckRegion = Buffer; + } else { + const CheckString &CheckLabelStr = CheckStrings[j]; + if (!CheckLabelStr.IsCheckLabel) { + ++j; + continue; + } + + // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG + size_t MatchLabelLen = 0; + size_t MatchLabelPos = CheckLabelStr.Check(SM, Buffer, true, + MatchLabelLen, VariableTable); + if (MatchLabelPos == StringRef::npos) { + hasError = true; + break; + } - if (MatchPos == StringRef::npos) - return 1; + CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen); + Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen); + ++j; + } - Buffer = Buffer.substr(MatchPos + MatchLen); + for ( ; i != j; ++i) { + const CheckString &CheckStr = CheckStrings[i]; + + // Check each string within the scanned region, including a second check + // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) + size_t MatchLen = 0; + size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen, + VariableTable); + + if (MatchPos == StringRef::npos) { + hasError = true; + i = j; + break; + } + + CheckRegion = CheckRegion.substr(MatchPos + MatchLen); + } + + if (j == e) + break; } - return 0; + return hasError ? 1 : 0; } |