From 4db6511779e70780f7b36bb7ef54276752f5f640 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sun, 2 Dec 2012 16:02:41 +0000 Subject: Fix a bug in FileCheck that wouldn't let define variables as follows: ; CHECK: [[VAR:[a-z]]] The problem was that to find the end of the regex var definition, it was simplistically looking for the next ]] and finding the incorrect one. A better approach is to count nesting of brackets (taking escaping into account). This way the brackets that are part of the regex can be discovered and skipped properly, and the ]] ending is detected in the right place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169109 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 51 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'utils') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 7b330d5ec7..c1d017fae4 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -119,6 +119,13 @@ private: /// \brief Evaluates expression and stores the result to \p Value. /// \return true on success. false when the expression has invalid syntax. bool EvaluateExpression(StringRef Expr, std::string &Value) const; + + /// \brief Finds the closing sequence of a regex variable usage or + /// definition. Str has to point in the beginning of the definition + /// (right after the opening sequence). + /// \return offset of the closing sequence within Str, or npos if it was not + /// found. + size_t FindRegexVarEnd(StringRef Str); }; @@ -187,8 +194,10 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject // it. This is to catch some common errors. if (PatternStr.startswith("[[")) { - // Verify that it is terminated properly. - size_t End = PatternStr.find("]]"); + // Find the closing bracket pair ending the match. End is going to be an + // offset relative to the beginning of the match string. + size_t End = FindRegexVarEnd(PatternStr.substr(2)); + if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), SourceMgr::DK_Error, @@ -196,8 +205,8 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, return true; } - StringRef MatchStr = PatternStr.substr(2, End-2); - PatternStr = PatternStr.substr(End+2); + StringRef MatchStr = PatternStr.substr(2, End); + PatternStr = PatternStr.substr(End+4); // Get the regex name (e.g. "foo"). size_t NameEnd = MatchStr.find(':'); @@ -519,6 +528,40 @@ void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, } } +size_t Pattern::FindRegexVarEnd(StringRef Str) { + // Offset keeps track of the current offset within the input Str + size_t Offset = 0; + // [...] Nesting depth + size_t BracketDepth = 0; + + while (!Str.empty()) { + if (Str.startswith("]]") && BracketDepth == 0) + return Offset; + if (Str[0] == '\\') { + // Backslash escapes the next char within regexes, so skip them both. + Str = Str.substr(2); + Offset += 2; + } else { + switch (Str[0]) { + default: + break; + case '[': + BracketDepth++; + break; + case ']': + assert(BracketDepth > 0 && "Invalid regex"); + BracketDepth--; + break; + } + Str = Str.substr(1); + Offset++; + } + } + + return StringRef::npos; +} + + //===----------------------------------------------------------------------===// // Check Strings. //===----------------------------------------------------------------------===// -- cgit v1.2.3