summaryrefslogtreecommitdiff
path: root/utils/FileCheck
diff options
context:
space:
mode:
authorEli Bendersky <eliben@google.com>2012-12-02 16:02:41 +0000
committerEli Bendersky <eliben@google.com>2012-12-02 16:02:41 +0000
commit4db6511779e70780f7b36bb7ef54276752f5f640 (patch)
treebef8603130686d76ac40a05ab83c69929b6aaf11 /utils/FileCheck
parente4693642444e8405a8f5812a3594372f7f108e9e (diff)
downloadllvm-4db6511779e70780f7b36bb7ef54276752f5f640.tar.gz
llvm-4db6511779e70780f7b36bb7ef54276752f5f640.tar.bz2
llvm-4db6511779e70780f7b36bb7ef54276752f5f640.tar.xz
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
Diffstat (limited to 'utils/FileCheck')
-rw-r--r--utils/FileCheck/FileCheck.cpp51
1 files changed, 47 insertions, 4 deletions
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.
//===----------------------------------------------------------------------===//