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
This commit is contained in:
Eli Bendersky 2012-12-02 16:02:41 +00:00
parent e469364244
commit 4db6511779
3 changed files with 56 additions and 5 deletions

View File

@ -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]]]

View 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]]

View 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.
//===----------------------------------------------------------------------===//