Fix a bug in FileCheck that wouldn't let define variables as follows:
authorEli Bendersky <eliben@google.com>
Sun, 2 Dec 2012 16:02:41 +0000 (16:02 +0000)
committerEli Bendersky <eliben@google.com>
Sun, 2 Dec 2012 16:02:41 +0000 (16:02 +0000)
; 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

test/FileCheck/regex-brackets.txt [new file with mode: 0644]
test/FileCheck/simple-var-capture.txt
utils/FileCheck/FileCheck.cpp

diff --git a/test/FileCheck/regex-brackets.txt b/test/FileCheck/regex-brackets.txt
new file mode 100644 (file)
index 0000000..fd8568d
--- /dev/null
@@ -0,0 +1,7 @@
+// RUN: FileCheck -input-file %s %s
+
+op r1
+op r2, [x r1]
+; CHECK:        op [[REG:r[0-9]]]
+; CHECK:        op [[REG2:r[0-9]]], [x [[REG]]]
+
index c0214d9017c59e32ffa7425c36b03bdfbf5c37cb..a487baaa531cb4eeba03bf0048051d0615b52935 100644 (file)
@@ -2,7 +2,7 @@
 
 op1 r1
 op2 r1, r2
-; CHECK:        op1 [[REG:r[0-9]+]]
+; CHECK:        op1 [[REG:r[0-9]]]
 ; CHECK-NEXT:   op2 [[REG]]
 
 op3 r16, r18, r21
@@ -10,3 +10,4 @@ op4 r30, r18, r21
 ; CHECK:        op3 {{r[0-9]+}}, [[REGa:r[0-9]+]], [[REGb:r[0-9]+]]
 ; CHECK-NEXT:   op4 {{r[0-9]+}}, [[REGa]], [[REGb]]
 
+
index 7b330d5ec751102e736efe1aaab9007ef931ba06..c1d017fae4b93f01b9652bcd516c34fa49039af1 100644 (file)
@@ -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.
 //===----------------------------------------------------------------------===//