diff options
author | James Y Knight <jyknight@google.com> | 2016-02-11 16:46:09 +0000 |
---|---|---|
committer | James Y Knight <jyknight@google.com> | 2016-02-11 16:46:09 +0000 |
commit | 5b06a939bd8e551dafb4acdaba4108b9cdaafef3 (patch) | |
tree | b924378ae3fd5efcc3de43c5d2932b61d1e03a85 | |
parent | b03ba0e6af70f264d25252979d0afea837ad0d50 (diff) |
Add -match-full-lines argument to FileCheck.
This is useful for some tests where more-exact matching is useful, such
as clang's Preprocessor tests.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260540 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/CommandGuide/FileCheck.rst | 12 | ||||
-rw-r--r-- | utils/FileCheck/FileCheck.cpp | 49 |
2 files changed, 44 insertions, 17 deletions
diff --git a/docs/CommandGuide/FileCheck.rst b/docs/CommandGuide/FileCheck.rst index 03c88297677..8d88237f393 100644 --- a/docs/CommandGuide/FileCheck.rst +++ b/docs/CommandGuide/FileCheck.rst @@ -42,6 +42,18 @@ OPTIONS File to check (defaults to stdin). +.. option:: --match-full-lines + + By default, FileCheck allows matches of anywhere on a line. This + option will require all positive matches to cover an entire + line. Leading and trailing whitespace is ignored, unless + :option:`--strict-whitespace` is also specified. (Note: negative + matches from ``CHECK-NOT`` are not affected by this option!) + + Passing this option is equivalent to inserting ``{{^ *}}`` or + ``{{^}}`` before, and ``{{ *$}}`` or ``{{$}}`` after every positive + check pattern. + .. option:: --strict-whitespace By default, FileCheck canonicalizes input horizontal whitespace (spaces and diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index f73a0fee76c..593ea9f441b 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -62,6 +62,12 @@ static cl::opt<bool> AllowEmptyInput( cl::desc("Allow the input file to be empty. This is useful when making\n" "checks that some error message does not occur, for example.")); +static cl::opt<bool> MatchFullLines( + "match-full-lines", cl::init(false), + cl::desc("Require all positive matches to cover an entire input line.\n" + "Allows leading and trailing whitespace if --strict-whitespace\n" + "is not also passed.")); + typedef cl::list<std::string>::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -174,6 +180,8 @@ bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, unsigned LineNumber) { + bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot; + this->LineNumber = LineNumber; PatternLoc = SMLoc::getFromPointer(PatternStr.data()); @@ -191,13 +199,19 @@ bool Pattern::ParsePattern(StringRef PatternStr, } // Check to see if this is a fixed string, or if it has regex pieces. - if (PatternStr.size() < 2 || - (PatternStr.find("{{") == StringRef::npos && - PatternStr.find("[[") == StringRef::npos)) { + if (!MatchFullLinesHere && + (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && + PatternStr.find("[[") == StringRef::npos))) { FixedStr = PatternStr; return false; } + if (MatchFullLinesHere) { + RegExStr += '^'; + if (!NoCanonicalizeWhiteSpace) + RegExStr += " *"; + } + // Paren value #0 is for the fully matched string. Any new parenthesized // values add from there. unsigned CurParen = 1; @@ -329,6 +343,12 @@ bool Pattern::ParsePattern(StringRef PatternStr, PatternStr = PatternStr.substr(FixedMatchEnd); } + if (MatchFullLinesHere) { + if (!NoCanonicalizeWhiteSpace) + RegExStr += " *"; + RegExStr += '$'; + } + return false; } @@ -598,19 +618,15 @@ struct CheckString { /// CheckTy - Specify what kind of check this is. e.g. CHECK-NEXT: directive, /// as opposed to a CHECK: directive. - Check::CheckType CheckTy; + // Check::CheckType CheckTy; /// 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, - StringRef S, - SMLoc L, - Check::CheckType Ty) - : Pat(P), Prefix(S), Loc(L), CheckTy(Ty) {} + CheckString(const Pattern &P, StringRef S, SMLoc L) + : Pat(P), Prefix(S), Loc(L) {} /// Check - Match check string and its "not strings" and/or "dag strings". size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, @@ -942,7 +958,7 @@ static bool ReadCheckFile(SourceMgr &SM, } // Okay, add the string we captured to the output vector and move on. - CheckStrings.emplace_back(P, UsedPrefix, PatternLoc, CheckTy); + CheckStrings.emplace_back(P, UsedPrefix, PatternLoc); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); DagNotMatches = ImplicitNegativeChecks; } @@ -951,8 +967,7 @@ static bool ReadCheckFile(SourceMgr &SM, // prefix as a filler for the error message. if (!DagNotMatches.empty()) { CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(), - SMLoc::getFromPointer(Buffer.data()), - Check::CheckEOF); + SMLoc::getFromPointer(Buffer.data())); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); } @@ -965,7 +980,7 @@ static bool ReadCheckFile(SourceMgr &SM, errs() << "\'" << *I << ":'"; ++I; } - for (; I != E; ++I) + for (; I != E; ++I) errs() << ", \'" << *I << ":'"; errs() << '\n'; @@ -1073,7 +1088,7 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, } bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { - if (CheckTy != Check::CheckNext) + if (Pat.getCheckTy() != Check::CheckNext) return false; // Count the number of newlines between the previous match and this one. @@ -1112,7 +1127,7 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { } bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { - if (CheckTy != Check::CheckSame) + if (Pat.getCheckTy() != Check::CheckSame) return false; // Count the number of newlines between the previous match and this one. @@ -1326,7 +1341,7 @@ int main(int argc, char **argv) { CheckRegion = Buffer; } else { const CheckString &CheckLabelStr = CheckStrings[j]; - if (CheckLabelStr.CheckTy != Check::CheckLabel) { + if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { ++j; continue; } |