From 30ce40e3f77d1432903c24caf816c54bb260d833 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Tue, 18 Sep 2012 20:51:39 +0000 Subject: FileCheck: Fix off-by-one bug that made CHECK-NOT: ignore the next character after the colon. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164165 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 33f04ce..afbce35 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -537,11 +537,11 @@ static bool ReadCheckFile(SourceMgr &SM, Buffer = Buffer.substr(CheckPrefix.size()+1); } else if (Buffer.size() > CheckPrefix.size()+6 && memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) { - Buffer = Buffer.substr(CheckPrefix.size()+7); + Buffer = Buffer.substr(CheckPrefix.size()+6); IsCheckNext = true; } else if (Buffer.size() > CheckPrefix.size()+5 && memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) { - Buffer = Buffer.substr(CheckPrefix.size()+6); + Buffer = Buffer.substr(CheckPrefix.size()+5); IsCheckNot = true; } else { Buffer = Buffer.substr(1); -- cgit v1.1 From 9d227af8f73301392d8b629d20f26e98ce96d5aa Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Fri, 21 Sep 2012 15:26:34 +0000 Subject: Clarify comment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164371 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index afbce35..e791628 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -470,7 +470,7 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { continue; } - // If C is not a horizontal whitespace, skip it. + // If current char is not a horizontal whitespace, dump it to output as is. if (*Ptr != ' ' && *Ptr != '\t') { NewFile.push_back(*Ptr); continue; -- cgit v1.1 From 70a870add82dab944b98ee1840fafff33795fc95 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Wed, 14 Nov 2012 21:07:37 +0000 Subject: Support for [[@LINE]], [[@LINE+]], [[@LINE-]] expressions in FileCheck. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167978 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 121 ++++++++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 27 deletions(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index e791628..6fcefd0 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include using namespace llvm; @@ -63,6 +64,9 @@ class Pattern { /// RegEx - If non-empty, this is a regex pattern. std::string RegExStr; + /// \brief Contains the number of line this pattern is in. + unsigned LineNumber; + /// VariableUses - Entries in this vector map to uses of a variable in the /// pattern, e.g. "foo[[bar]]baz". In this case, the RegExStr will contain /// "foobaz" and we'll get an entry in this vector that tells us to insert the @@ -79,7 +83,7 @@ public: Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { } - bool ParsePattern(StringRef PatternStr, SourceMgr &SM); + bool ParsePattern(StringRef PatternStr, SourceMgr &SM, unsigned LineNumber); /// Match - Match the pattern string against the input buffer Buffer. This /// returns the position that is matched or npos if there is no match. If @@ -104,10 +108,16 @@ private: /// should correspond to a perfect match. unsigned ComputeMatchDistance(StringRef Buffer, const StringMap &VariableTable) const; + + /// \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; }; -bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { +bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, + unsigned LineNumber) { + this->LineNumber = LineNumber; PatternLoc = SMLoc::getFromPointer(PatternStr.data()); // Ignore trailing whitespace. @@ -193,13 +203,28 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { return true; } - // Verify that the name is well formed. - for (unsigned i = 0, e = Name.size(); i != e; ++i) - if (Name[i] != '_' && !isalnum(Name[i])) { + // Verify that the name/expression is well formed. FileCheck currently + // supports @LINE, @LINE+number, @LINE-number expressions. The check here + // is relaxed, more strict check is performed in \c EvaluateExpression. + bool IsExpression = false; + for (unsigned i = 0, e = Name.size(); i != e; ++i) { + if (i == 0 && Name[i] == '@') { + if (NameEnd != StringRef::npos) { + SM.PrintMessage(SMLoc::getFromPointer(Name.data()), + SourceMgr::DK_Error, + "invalid name in named regex definition"); + return true; + } + IsExpression = true; + continue; + } + if (Name[i] != '_' && !isalnum(Name[i]) && + (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), SourceMgr::DK_Error, "invalid name in named regex"); return true; } + } // Name can't start with a digit. if (isdigit(Name[0])) { @@ -279,6 +304,24 @@ bool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen, return false; } +bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const { + // The only supported expression is @LINE([\+-]\d+)? + if (!Expr.startswith("@LINE")) + return false; + Expr = Expr.substr(StringRef("@LINE").size()); + int Offset = 0; + if (!Expr.empty()) { + if (Expr[0] == '+') + Expr = Expr.substr(1); + else if (Expr[0] != '-') + return false; + if (Expr.getAsInteger(10, Offset)) + return false; + } + Value = llvm::itostr(LineNumber + Offset); + return true; +} + /// Match - Match the pattern string against the input buffer Buffer. This /// returns the position that is matched or npos if there is no match. If /// there is a match, the size of the matched string is returned in MatchLen. @@ -307,15 +350,21 @@ size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, unsigned InsertOffset = 0; for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { - StringMap::iterator it = - VariableTable.find(VariableUses[i].first); - // If the variable is undefined, return an error. - if (it == VariableTable.end()) - return StringRef::npos; - - // Look up the value and escape it so that we can plop it into the regex. std::string Value; - AddFixedStringToRegEx(it->second, Value); + + if (VariableUses[i].first[0] == '@') { + if (!EvaluateExpression(VariableUses[i].first, Value)) + return StringRef::npos; + } else { + StringMap::iterator it = + VariableTable.find(VariableUses[i].first); + // If the variable is undefined, return an error. + if (it == VariableTable.end()) + return StringRef::npos; + + // Look up the value and escape it so that we can plop it into the regex. + AddFixedStringToRegEx(it->second, Value); + } // Plop it into the regex at the adjusted offset. TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset, @@ -371,19 +420,31 @@ void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, // variable values. if (!VariableUses.empty()) { for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { - StringRef Var = VariableUses[i].first; - StringMap::const_iterator it = VariableTable.find(Var); SmallString<256> Msg; raw_svector_ostream OS(Msg); - - // Check for undefined variable references. - if (it == VariableTable.end()) { - OS << "uses undefined variable \""; - OS.write_escaped(Var) << "\"";; + StringRef Var = VariableUses[i].first; + if (Var[0] == '@') { + std::string Value; + if (EvaluateExpression(Var, Value)) { + OS << "with expression \""; + OS.write_escaped(Var) << "\" equal to \""; + OS.write_escaped(Value) << "\""; + } else { + OS << "uses incorrect expression \""; + OS.write_escaped(Var) << "\""; + } } else { - OS << "with variable \""; - OS.write_escaped(Var) << "\" equal to \""; - OS.write_escaped(it->second) << "\""; + StringMap::const_iterator it = VariableTable.find(Var); + + // Check for undefined variable references. + if (it == VariableTable.end()) { + OS << "uses undefined variable \""; + OS.write_escaped(Var) << "\""; + } else { + OS << "with variable \""; + OS.write_escaped(Var) << "\" equal to \""; + OS.write_escaped(it->second) << "\""; + } } SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, @@ -518,14 +579,20 @@ static bool ReadCheckFile(SourceMgr &SM, std::vector > NotMatches; + unsigned LineNumber = 1; + while (1) { // See if Prefix occurs in the memory buffer. - Buffer = Buffer.substr(Buffer.find(CheckPrefix)); - + size_t PrefixLoc = Buffer.find(CheckPrefix); // If we didn't find a match, we're done. - if (Buffer.empty()) + if (PrefixLoc == StringRef::npos) break; + // Recalculate line number. + LineNumber += Buffer.substr(0, PrefixLoc).count('\n'); + + Buffer = Buffer.substr(PrefixLoc); + const char *CheckPrefixStart = Buffer.data(); // When we find a check prefix, keep track of whether we find CHECK: or @@ -560,7 +627,7 @@ static bool ReadCheckFile(SourceMgr &SM, // Parse the pattern. Pattern P; - if (P.ParsePattern(Buffer.substr(0, EOL), SM)) + if (P.ParsePattern(Buffer.substr(0, EOL), SM, LineNumber)) return true; Buffer = Buffer.substr(EOL); -- cgit v1.1 From 65f3f32100b80366785f86c64a7ff0ee697107eb Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 15 Nov 2012 16:50:59 +0000 Subject: FileCheck: remove useless 'continue' at the end of a 'while(){}' loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168048 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 6fcefd0..c552465 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -256,7 +256,6 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); PatternStr = PatternStr.substr(FixedMatchEnd); - continue; } return false; -- cgit v1.1 From 7f8e76f5140be7cc9ed1cb66cdcdedfa28147641 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 30 Nov 2012 13:51:33 +0000 Subject: Make FileCheck return 2 in case of an error as documented, instead of 1 or true (?!) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169001 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index c552465..0dc8432 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -729,13 +729,13 @@ int main(int argc, char **argv) { MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { errs() << "Could not open input file '" << InputFilename << "': " << ec.message() << '\n'; - return true; + return 2; } MemoryBuffer *F = File.take(); if (F->getBufferSize() == 0) { errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; - return 1; + return 2; } // Remove duplicate spaces in the input file if requested. -- cgit v1.1 From 1e5cbcb10adaca5c80121293b6c414d9285ebcee Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 30 Nov 2012 14:22:14 +0000 Subject: Clean up whitespace and add comments git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169002 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 0dc8432..fb66ac2 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -83,6 +83,10 @@ public: Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { } + /// ParsePattern - Parse the given string into the Pattern. SM provides the + /// SourceMgr used for error reports, and LineNumber is the line number in + /// the input file from which the pattern string was read. + /// Returns true in case of an error, false otherwise. bool ParsePattern(StringRef PatternStr, SourceMgr &SM, unsigned LineNumber); /// Match - Match the pattern string against the input buffer Buffer. This @@ -150,8 +154,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, while (!PatternStr.empty()) { // RegEx matches. if (PatternStr.startswith("{{")) { - - // Otherwise, this is the start of a regex match. Scan for the }}. + // This is the start of a regex match. Scan for the }}. size_t End = PatternStr.find("}}"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), @@ -554,9 +557,9 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { /// ReadCheckFile - Read the check file, which specifies the sequence of /// expected strings. The strings are added to the CheckStrings vector. +/// Returns true in case of an error, false otherwise. static bool ReadCheckFile(SourceMgr &SM, std::vector &CheckStrings) { - // Open the check file, and tell SourceMgr about it. OwningPtr File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) { @@ -575,9 +578,10 @@ static bool ReadCheckFile(SourceMgr &SM, // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); - std::vector > NotMatches; + // LineNumber keeps track of the line on which CheckPrefix instances are + // found. unsigned LineNumber = 1; while (1) { @@ -587,7 +591,6 @@ static bool ReadCheckFile(SourceMgr &SM, if (PrefixLoc == StringRef::npos) break; - // Recalculate line number. LineNumber += Buffer.substr(0, PrefixLoc).count('\n'); Buffer = Buffer.substr(PrefixLoc); @@ -631,7 +634,6 @@ static bool ReadCheckFile(SourceMgr &SM, Buffer = Buffer.substr(EOL); - // Verify that CHECK-NEXT lines have at least one CHECK line before them. if (IsCheckNext && CheckStrings.empty()) { SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), @@ -648,7 +650,6 @@ static bool ReadCheckFile(SourceMgr &SM, continue; } - // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, PatternLoc, -- cgit v1.1 From 9756ca7ba0c7f6c3b1e76ee12ca27ddca04be9d7 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 1 Dec 2012 21:54:48 +0000 Subject: Support referencing variables defined on the same line. See http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20121126/157198.html and related discussions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169101 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 56 ++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index fb66ac2..7b330d5 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -29,6 +29,9 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include +#include +#include +#include using namespace llvm; static cl::opt @@ -73,11 +76,10 @@ class Pattern { /// value of bar at offset 3. std::vector > VariableUses; - /// VariableDefs - Entries in this vector map to definitions of a variable in - /// the pattern, e.g. "foo[[bar:.*]]baz". In this case, the RegExStr will - /// contain "foo(.*)baz" and VariableDefs will contain the pair "bar",1. The - /// index indicates what parenthesized value captures the variable value. - std::vector > VariableDefs; + /// VariableDefs - Maps definitions of variables to their parenthesized + /// capture numbers. + /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 1. + std::map VariableDefs; public: @@ -105,7 +107,8 @@ public: private: static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr); - bool AddRegExToRegEx(StringRef RegExStr, unsigned &CurParen, SourceMgr &SM); + bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); + void AddBackrefToRegEx(unsigned BackrefNum); /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of /// matching this pattern at the start of \arg Buffer; a distance of zero @@ -238,12 +241,25 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, // Handle [[foo]]. if (NameEnd == StringRef::npos) { - VariableUses.push_back(std::make_pair(Name, RegExStr.size())); + // Handle variables that were defined earlier on the same line by + // emitting a backreference. + if (VariableDefs.find(Name) != VariableDefs.end()) { + unsigned VarParenNum = VariableDefs[Name]; + if (VarParenNum < 1 || VarParenNum > 9) { + SM.PrintMessage(SMLoc::getFromPointer(Name.data()), + SourceMgr::DK_Error, + "Can't back-reference more than 9 variables"); + return true; + } + AddBackrefToRegEx(VarParenNum); + } else { + VariableUses.push_back(std::make_pair(Name, RegExStr.size())); + } continue; } // Handle [[foo:.*]]. - VariableDefs.push_back(std::make_pair(Name, CurParen)); + VariableDefs[Name] = CurParen; RegExStr += '('; ++CurParen; @@ -291,21 +307,28 @@ void Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) { } } -bool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen, +bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) { - Regex R(RegexStr); + Regex R(RS); std::string Error; if (!R.isValid(Error)) { - SM.PrintMessage(SMLoc::getFromPointer(RegexStr.data()), SourceMgr::DK_Error, + SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error, "invalid regex: " + Error); return true; } - RegExStr += RegexStr.str(); + RegExStr += RS.str(); CurParen += R.getNumMatches(); return false; } +void Pattern::AddBackrefToRegEx(unsigned BackrefNum) { + assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number"); + std::string Backref = std::string("\\") + + std::string(1, '0' + BackrefNum); + RegExStr += Backref; +} + bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const { // The only supported expression is @LINE([\+-]\d+)? if (!Expr.startswith("@LINE")) @@ -388,10 +411,11 @@ size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, StringRef FullMatch = MatchInfo[0]; // If this defines any variables, remember their values. - for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) { - assert(VariableDefs[i].second < MatchInfo.size() && - "Internal paren error"); - VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second]; + for (std::map::const_iterator I = VariableDefs.begin(), + E = VariableDefs.end(); + I != E; ++I) { + assert(I->second < MatchInfo.size() && "Internal paren error"); + VariableTable[I->first] = MatchInfo[I->second]; } MatchLen = FullMatch.size(); -- cgit v1.1 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/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 7b330d5..c1d017f 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.1 From 4ffd89fa4d2788611187d1a534d2ed46adf1702c Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 4 Dec 2012 10:37:14 +0000 Subject: Sort the #include lines for utils/... I've tried to find main moudle headers where possible, but the TableGen stuff may warrant someone else looking at it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169251 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/FileCheck/FileCheck.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'utils/FileCheck/FileCheck.cpp') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index c1d017f..a0eeb0e 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -17,17 +17,17 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Regex.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" #include #include #include -- cgit v1.1